archery/0000775000175000017500000000000015105742312012041 5ustar bdrungbdrungarchery/release-notes.md0000644000175000017500000000245215105742312015132 0ustar bdrungbdrung# Release notes ## 1.2.1 * No longer depend on `static_assertions`. ## 1.2.0 * Added support for serde. This is gated behind the `serde` feature. ## 1.1.0 * Added support for `triomphe::Arc` as a pointer kind. This gated behind the `triomphe` feature. ## 1.0.0 * No changes. It’s just time to commit to a stable release :). ## 0.5.0 * Fix `Send`/`Sync` unsoundness in `SharedPointer`. See issue [#18](https://github.com/orium/archery/issues/18). * Added `SharedPointer::pin()`. * Added `SharedPointer::as_ptr()`. * Updated dependencies. * Updated to 2021 edition. ## 0.4.0 * Added support for `no_std`. ## 0.3.0 * Renamed `SharedPointerKindRc` and `SharedPointerKindArc` to `RcK` and `ArcK`, respectively. ## 0.2.1 * Minor fix in README. ## 0.2.0 * Added some functionality to `SharedPointer` that you would expect from `Rc`/`Arc`. * Functions: * `SharedPointer::try_unwrap()`. * `SharedPointer::get_mut()`. * `SharedPointer::strong_count()`. * `SharedPointer::ptr_eq()`. * Traits: * `Default`. * `From`. * `From>`. * `std::fmt::Pointer`. ## 0.1.0 * Initial release with `SharedPointer`, `SharedPointerKind`, `SharedPointerKindRc`, and `SharedPointerKindArc`. * Functionality exposed from the underlying pointers: `deref()`, `make_mut()`, `clone()`. archery/Cargo.lock0000644000175000017500000004122015105742312013743 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "archery" version = "1.2.1" dependencies = [ "bincode", "criterion", "pretty_assertions", "serde", "static_assertions", "triomphe", ] [[package]] name = "autocfg" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bincode" version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ "serde", ] [[package]] name = "bumpalo" version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", "serde", ] [[package]] name = "ciborium-io" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", ] [[package]] name = "clap" version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstyle", "clap_lex", ] [[package]] name = "clap_lex" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "criterion" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", "is-terminal", "itertools", "num-traits", "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", "serde_derive", "serde_json", "tinytemplate", "walkdir", ] [[package]] name = "criterion-plot" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", ] [[package]] name = "crossbeam-deque" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "diff" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "half" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", ] [[package]] name = "hermit-abi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "is-terminal" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ "hermit-abi", "libc", "windows-sys", ] [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "plotters" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", "web-sys", ] [[package]] name = "plotters-backend" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-svg" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] [[package]] name = "pretty_assertions" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ "diff", "yansi", ] [[package]] name = "proc-macro2" version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "rayon" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "regex" version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "serde" version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" version = "2.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", "serde_json", ] [[package]] name = "triomphe" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "wasm-bindgen" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "winapi-util" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ "windows-sys", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "yansi" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" archery/Cargo.toml0000644000175000017500000000463415105742312013776 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.66.0" name = "archery" version = "1.2.1" authors = ["Diogo Sousa "] build = false include = [ "/src/**/*.rs", "/Cargo.toml", "/LICENSE.md", "/README.md", "/release-notes.md", ] autobins = false autoexamples = false autotests = false autobenches = false description = "Abstract over the atomicity of reference-counting pointers" homepage = "https://github.com/orium/archery" documentation = "https://docs.rs/archery" readme = "README.md" keywords = [ "rc", "arc", "reference-counting", "no_std", ] categories = [ "concurrency", "memory-management", "rust-patterns", ] license = "MPL-2.0" repository = "https://github.com/orium/archery" [package.metadata.docs.rs] features = [ "triomphe", "serde", ] [lib] name = "archery" path = "src/lib.rs" bench = false [dependencies.serde] version = "1.0.204" optional = true default-features = false [dependencies.triomphe] version = "0.1.13" optional = true default-features = false [dev-dependencies.bincode] version = "1.3.3" [dev-dependencies.criterion] version = "0.5.1" features = ["html_reports"] [dev-dependencies.pretty_assertions] version = "1.4.0" [dev-dependencies.static_assertions] version = "1.1.0" [features] fatal-warnings = [] serde = ["dep:serde"] triomphe = ["dep:triomphe"] [badges.codecov] branch = "main" repository = "orium/archery" service = "github" [lints.clippy] explicit-deref-methods = "allow" if-not-else = "allow" inline-always = "allow" match-bool = "allow" missing-errors-doc = "allow" missing-safety-doc = "allow" module-name-repetitions = "allow" partialeq-ne-impl = "allow" similar-names = "allow" single-match-else = "allow" use-self = "allow" wildcard-imports = "allow" [lints.clippy.all] level = "warn" priority = -2 [lints.clippy.correctness] level = "deny" priority = -1 [lints.clippy.pedantic] level = "warn" priority = -2 [lints.rustdoc] redundant-explicit-links = "allow" archery/.cargo-checksum.json0000664000175000017500000000013115105742312015700 0ustar bdrungbdrung{"files":{},"package":"eae2ed21cd55021f05707a807a5fc85695dafb98832921f6cfa06db67ca5b869"}archery/LICENSE.md0000644000175000017500000003627615105742312013461 0ustar bdrungbdrungMozilla Public License Version 2.0 ================================== ### 1. Definitions **1.1. “Contributor”** means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. **1.2. “Contributor Version”** means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. **1.3. “Contribution”** means Covered Software of a particular Contributor. **1.4. “Covered Software”** means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. **1.5. “Incompatible With Secondary Licenses”** means * **(a)** that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or * **(b)** that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. **1.6. “Executable Form”** means any form of the work other than Source Code Form. **1.7. “Larger Work”** means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. **1.8. “License”** means this document. **1.9. “Licensable”** means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. **1.10. “Modifications”** means any of the following: * **(a)** any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or * **(b)** any new file in Source Code Form that contains any Covered Software. **1.11. “Patent Claims” of a Contributor** means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. **1.12. “Secondary License”** means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. **1.13. “Source Code Form”** means the form of the work preferred for making modifications. **1.14. “You” (or “Your”)** means an individual or a legal entity exercising rights under this License. For legal entities, “You” includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, “control” means **(a)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(b)** ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. ### 2. License Grants and Conditions #### 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: * **(a)** under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and * **(b)** under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. #### 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. #### 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: * **(a)** for any code that a Contributor has removed from Covered Software; or * **(b)** for infringements caused by: **(i)** Your and any other third party's modifications of Covered Software, or **(ii)** the combination of its Contributions with other software (except as part of its Contributor Version); or * **(c)** under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). #### 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). #### 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. #### 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. #### 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. ### 3. Responsibilities #### 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. #### 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: * **(a)** such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and * **(b)** You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. #### 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). #### 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. #### 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. ### 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: **(a)** comply with the terms of this License to the maximum extent possible; and **(b)** describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. ### 5. Termination **5.1.** The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated **(a)** provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and **(b)** on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. **5.2.** If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. **5.3.** In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ### 6. Disclaimer of Warranty > Covered Software is provided under this License on an “as is” > basis, without warranty of any kind, either expressed, implied, or > statutory, including, without limitation, warranties that the > Covered Software is free of defects, merchantable, fit for a > particular purpose or non-infringing. The entire risk as to the > quality and performance of the Covered Software is with You. > Should any Covered Software prove defective in any respect, You > (not any Contributor) assume the cost of any necessary servicing, > repair, or correction. This disclaimer of warranty constitutes an > essential part of this License. No use of any Covered Software is > authorized under this License except under this disclaimer. ### 7. Limitation of Liability > Under no circumstances and under no legal theory, whether tort > (including negligence), contract, or otherwise, shall any > Contributor, or anyone who distributes Covered Software as > permitted above, be liable to You for any direct, indirect, > special, incidental, or consequential damages of any character > including, without limitation, damages for lost profits, loss of > goodwill, work stoppage, computer failure or malfunction, or any > and all other commercial damages or losses, even if such party > shall have been informed of the possibility of such damages. This > limitation of liability shall not apply to liability for death or > personal injury resulting from such party's negligence to the > extent applicable law prohibits such limitation. Some > jurisdictions do not allow the exclusion or limitation of > incidental or consequential damages, so this exclusion and > limitation may not apply to You. ### 8. Litigation Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. ### 9. Miscellaneous This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. ### 10. Versions of the License #### 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. #### 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. #### 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). #### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. ## Exhibit A - Source Code Form License Notice This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. ## Exhibit B - “Incompatible With Secondary Licenses” Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. archery/README.md0000644000175000017500000001222515105742312013320 0ustar bdrungbdrung[![Build Status](https://github.com/orium/archery/workflows/CI/badge.svg)](https://github.com/orium/archery/actions?query=workflow%3ACI) [![Code Coverage](https://codecov.io/gh/orium/archery/branch/main/graph/badge.svg)](https://codecov.io/gh/orium/archery) [![Dependency status](https://deps.rs/repo/github/orium/archery/status.svg)](https://deps.rs/repo/github/orium/archery) [![crates.io](https://img.shields.io/crates/v/archery.svg)](https://crates.io/crates/archery) [![Downloads](https://img.shields.io/crates/d/archery.svg)](https://crates.io/crates/archery) [![Github stars](https://img.shields.io/github/stars/orium/archery.svg?logo=github)](https://github.com/orium/archery/stargazers) [![Documentation](https://docs.rs/archery/badge.svg)](https://docs.rs/archery/) [![License](https://img.shields.io/crates/l/archery.svg)](./LICENSE.md) # `archery` `archery` is a rust library that offers a way to abstraction over [`Rc`](https://doc.rust-lang.org/stable/alloc/rc/struct.Rc.html) and [`Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html) smart pointers. This allows you to create data structures where the pointer type is parameterizable, so you can [avoid the overhead of `Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html#thread-safety) when you don’t need to share data across threads. In languages that supports [higher-kinded polymorphism](https://en.wikipedia.org/wiki/Type_class#Higher-kinded_polymorphism) this would be simple to achieve without any library, but [rust does not support that yet](https://github.com/rust-lang/rfcs/issues/324). To mimic higher-kinded polymorphism `archery` implements the approach suggested by Joshua Liebow-Feeser in “[Rust has higher kinded types already… sort of](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/)”. While [other approaches](#alternative-approaches) exist, they seem to always offer poor ergonomics for the user. ## Setup To use `archery` add the following to your `Cargo.toml`: ```toml [dependencies] archery = "" ``` ## Using `archery` `archery` defines a [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html) that receives the [kind of pointer](https://docs.rs/archery/latest/archery/shared_pointer/kind/trait.SharedPointerKind.html) as a type parameter. This gives you a convenient and ergonomic way to abstract the pointer type away. ### Example Declare a data structure with the pointer kind as a type parameter bounded by [`SharedPointerKind`](https://docs.rs/archery/latest/archery/shared_pointer/kind/trait.SharedPointerKind.html): ```rust use archery::*; struct KeyValuePair { pub key: SharedPointer, pub value: SharedPointer, } impl KeyValuePair { fn new(key: K, value: V) -> KeyValuePair { KeyValuePair { key: SharedPointer::new(key), value: SharedPointer::new(value), } } } ``` To use it just plug-in the kind of pointer you want: ```rust let pair: KeyValuePair<_, _, RcK> = KeyValuePair::new("António Variações", 1944); assert_eq!(*pair.value, 1944); ``` ### `triomphe::Arc` You can also use [`triomphe::Arc`](https://docs.rs/triomphe/latest/triomphe/struct.Arc.html) as the backing implementation of a [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html). This is generally faster than [`std::sync::Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html). Read [`triomphe`’s crate documentation](https://docs.rs/triomphe/latest/triomphe/) to learn more about it. To use it you need to enable the `triomphe` feature in `archery`. Use `ArcTK` as the pointer kind in [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html). ### Serialization We support serialization through [serde](https://crates.io/crates/serde). To use it enable the `serde` feature. To do so change the archery dependency in your `Cargo.toml` to ```toml [dependencies] archery = { version = "", features = ["serde"] } ``` ## Limitations Currently it is not possible to have unsized types inside a [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html). As a workaround you can put the unsized type inside a [`Box`](https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html). ## Alternative approaches An alternative to the approach taken by `archery` is to use traits with associated types to encode type-level functions. This has been suggested [multiple](https://github.com/orium/rpds/issues/7#issuecomment-362635901) [times](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/#comment-4160863400), but offers ugly ergonomics (see [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L153) and [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L249)). archery/src/0000775000175000017500000000000015105742312012630 5ustar bdrungbdrungarchery/src/lib.rs0000644000175000017500000001235015105742312013743 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![no_std] #![cfg_attr(feature = "fatal-warnings", deny(warnings))] // Note: If you change this remember to update `README.md`. To do so run `cargo rdme`. //! `archery` is a rust library that offers a way to abstraction over //! [`Rc`](::alloc::rc::Rc) and //! [`Arc`](::alloc::sync::Arc) smart pointers. //! This allows you to create data structures where the pointer type is parameterizable, so you can //! [avoid the overhead of `Arc`](::alloc::sync::Arc#thread-safety) //! when you don’t need to share data across threads. //! //! In languages that supports //! [higher-kinded polymorphism](https://en.wikipedia.org/wiki/Type_class#Higher-kinded_polymorphism) //! this would be simple to achieve without any library, but //! [rust does not support that yet](https://github.com/rust-lang/rfcs/issues/324). //! To mimic higher-kinded polymorphism `archery` implements the approach suggested by //! Joshua Liebow-Feeser in //! “[Rust has higher kinded types already… sort of](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/)”. //! While [other approaches](#alternative-approaches) exist, they seem to always offer poor //! ergonomics for the user. //! //! # Setup //! //! To use `archery` add the following to your `Cargo.toml`: //! //! ```toml //! [dependencies] //! archery = "" //! ``` //! //! # Using `archery` //! //! `archery` defines a [`SharedPointer`](crate::shared_pointer::SharedPointer) //! that receives the [kind of pointer](crate::shared_pointer::kind::SharedPointerKind) //! as a type parameter. This gives you a convenient and ergonomic way to abstract the pointer //! type away. //! //! ## Example //! //! Declare a data structure with the pointer kind as a type parameter bounded by //! [`SharedPointerKind`](crate::shared_pointer::kind::SharedPointerKind): //! //! ```rust //! use archery::*; //! //! struct KeyValuePair { //! pub key: SharedPointer, //! pub value: SharedPointer, //! } //! //! impl KeyValuePair { //! fn new(key: K, value: V) -> KeyValuePair { //! KeyValuePair { //! key: SharedPointer::new(key), //! value: SharedPointer::new(value), //! } //! } //! } //! ``` //! //! To use it just plug-in the kind of pointer you want: //! //! ```rust //! # use archery::*; //! # //! # struct KeyValuePair { //! # pub key: SharedPointer, //! # pub value: SharedPointer, //! # } //! # //! # impl KeyValuePair { //! # fn new(key: K, value: V) -> KeyValuePair { //! # KeyValuePair { //! # key: SharedPointer::new(key), //! # value: SharedPointer::new(value), //! # } //! # } //! # } //! # //! let pair: KeyValuePair<_, _, RcK> = //! KeyValuePair::new("António Variações", 1944); //! //! assert_eq!(*pair.value, 1944); //! ``` //! //! ## `triomphe::Arc` //! //! You can also use [`triomphe::Arc`](https://docs.rs/triomphe/latest/triomphe/struct.Arc.html) //! as the backing implementation of a [`SharedPointer`](crate::shared_pointer::SharedPointer). //! This is generally faster than [`std::sync::Arc`](::alloc::sync::Arc). //! Read [`triomphe`’s crate documentation](https://docs.rs/triomphe/latest/triomphe/) to learn more //! about it. //! //! To use it you need to enable the `triomphe` feature in `archery`. Use `ArcTK` as the pointer //! kind in [`SharedPointer`](crate::shared_pointer::SharedPointer). //! //! ## Serialization //! //! We support serialization through [serde](https://crates.io/crates/serde). To use it //! enable the `serde` feature. To do so change the archery dependency in your `Cargo.toml` to //! //! ```toml //! [dependencies] //! archery = { version = "", features = ["serde"] } //! ``` //! # Limitations //! //! Currently it is not possible to have unsized types inside a //! [`SharedPointer`](crate::shared_pointer::SharedPointer). As a workaround you can put the //! unsized type inside a [`Box`](::alloc::boxed::Box). //! //! # Alternative approaches //! //! An alternative to the approach taken by `archery` is to use traits with associated types to encode //! type-level functions. This has been suggested //! [multiple](https://github.com/orium/rpds/issues/7#issuecomment-362635901) //! [times](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/#comment-4160863400), //! but offers ugly ergonomics (see //! [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L153) //! and [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L249)). extern crate alloc; #[cfg(test)] #[macro_use] extern crate std; pub mod shared_pointer; pub use shared_pointer::SharedPointer; pub use shared_pointer::kind::SharedPointerKind; #[doc(no_inline)] pub use shared_pointer::kind::ArcK; #[cfg(feature = "triomphe")] #[doc(no_inline)] pub use shared_pointer::kind::ArcTK; #[doc(no_inline)] pub use shared_pointer::kind::RcK; archery/src/shared_pointer/0000775000175000017500000000000015105742312015636 5ustar bdrungbdrungarchery/src/shared_pointer/mod.rs0000644000175000017500000002210615105742312016762 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::shared_pointer::kind::SharedPointerKind; use alloc::boxed::Box; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt; use core::fmt::Debug; use core::fmt::Display; use core::fmt::Formatter; use core::hash::Hash; use core::hash::Hasher; use core::marker::PhantomData; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::pin::Pin; use core::ptr; /// Pointer to shared data with reference-counting. /// /// The type parameter `P` is a [type constructor](https://en.wikipedia.org/wiki/Type_constructor) /// of the underlying pointer type, offering a way to abstraction over [`Rc`](alloc::rc::Rc) and /// [`Arc`](alloc::sync::Arc) smart pointers. /// This allows you to create data structures where the pointer type is parameterizable, so you can /// [avoid the overhead of `Arc`](alloc::sync::Arc#thread-safety) /// when you don’t need to share data across threads. /// /// # Example /// /// Declare a data structure with the pointer kind as a type parameter bounded by /// [`SharedPointerKind`]: /// /// ```rust /// use archery::*; /// /// struct KeyValuePair { /// pub key: SharedPointer, /// pub value: SharedPointer, /// } /// /// impl KeyValuePair { /// fn new(key: K, value: V) -> KeyValuePair { /// KeyValuePair { /// key: SharedPointer::new(key), /// value: SharedPointer::new(value), /// } /// } /// } /// ``` /// /// To use it just plug-in the kind of pointer you want: /// /// ```rust /// # use archery::*; /// # /// # struct KeyValuePair { /// # pub key: SharedPointer, /// # pub value: SharedPointer, /// # } /// # /// # impl KeyValuePair { /// # fn new(key: K, value: V) -> KeyValuePair { /// # KeyValuePair { /// # key: SharedPointer::new(key), /// # value: SharedPointer::new(value), /// # } /// # } /// # } /// # /// let pair: KeyValuePair<_, _, RcK> = /// KeyValuePair::new("António Variações", 1944); /// /// assert_eq!(*pair.value, 1944); /// ``` pub struct SharedPointer where P: SharedPointerKind, { ptr: ManuallyDrop

, _phantom_t: PhantomData, _phantom_no_send_sync: PhantomData<*mut ()>, } unsafe impl Send for SharedPointer where P: SharedPointerKind {} unsafe impl Sync for SharedPointer where P: SharedPointerKind {} impl Unpin for SharedPointer where P: SharedPointerKind {} impl SharedPointer where P: SharedPointerKind, { #[inline(always)] fn new_from_inner(ptr: P) -> SharedPointer { SharedPointer { ptr: ManuallyDrop::new(ptr), _phantom_t: PhantomData, _phantom_no_send_sync: PhantomData, } } #[inline(always)] pub fn new(v: T) -> SharedPointer { SharedPointer::new_from_inner(P::new::(v)) } #[inline(always)] pub fn pin(v: T) -> Pin> { unsafe { Pin::new_unchecked(Self::new(v)) } } #[inline(always)] pub fn as_ptr(this: &Self) -> *const T { unsafe { this.ptr.as_ptr::() } } #[inline(always)] pub fn try_unwrap(mut this: SharedPointer) -> Result> { let ptr: P = unsafe { ManuallyDrop::take(&mut this.ptr) }; mem::forget(this); unsafe { ptr.try_unwrap::() }.map_err(SharedPointer::new_from_inner) } #[inline(always)] pub fn get_mut(this: &mut SharedPointer) -> Option<&mut T> { unsafe { this.ptr.get_mut::() } } #[inline(always)] pub fn strong_count(this: &Self) -> usize { unsafe { this.ptr.strong_count::() } } #[inline(always)] pub fn ptr_eq( this: &SharedPointer, other: &SharedPointer, ) -> bool { ptr::eq(this.deref(), other.deref()) } } impl SharedPointer where T: Clone, P: SharedPointerKind, { #[inline(always)] pub fn make_mut(this: &mut SharedPointer) -> &mut T { unsafe { this.ptr.make_mut::() } } } impl Default for SharedPointer where T: Default, P: SharedPointerKind, { #[inline(always)] fn default() -> SharedPointer { SharedPointer::new(Default::default()) } } impl Deref for SharedPointer where P: SharedPointerKind, { type Target = T; #[inline(always)] fn deref(&self) -> &T { unsafe { self.ptr.deref().deref() } } } impl Borrow for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn borrow(&self) -> &T { self.deref() } } impl AsRef for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn as_ref(&self) -> &T { self.deref() } } impl Clone for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn clone(&self) -> SharedPointer { SharedPointer::new_from_inner(unsafe { self.ptr.deref().clone::() }) } } impl Hash for SharedPointer where T: Hash, P: SharedPointerKind, { #[inline(always)] fn hash(&self, state: &mut H) { self.deref().hash(state); } } impl PartialEq> for SharedPointer where T: PartialEq, P: SharedPointerKind, PO: SharedPointerKind, { #[inline(always)] fn eq(&self, other: &SharedPointer) -> bool { self.deref().eq(other.deref()) } #[inline(always)] fn ne(&self, other: &SharedPointer) -> bool { self.deref().ne(other.deref()) } } impl Eq for SharedPointer where T: Eq, P: SharedPointerKind, { } impl PartialOrd> for SharedPointer where T: PartialOrd, P: SharedPointerKind, PO: SharedPointerKind, { #[inline(always)] fn partial_cmp(&self, other: &SharedPointer) -> Option { self.deref().partial_cmp(other.deref()) } #[inline(always)] fn lt(&self, other: &SharedPointer) -> bool { self.deref().lt(other.deref()) } #[inline(always)] fn le(&self, other: &SharedPointer) -> bool { self.deref().le(other.deref()) } #[inline(always)] fn gt(&self, other: &SharedPointer) -> bool { self.deref().gt(other.deref()) } #[inline(always)] fn ge(&self, other: &SharedPointer) -> bool { self.deref().ge(other.deref()) } } impl Ord for SharedPointer where T: Ord, P: SharedPointerKind, { #[inline(always)] fn cmp(&self, other: &SharedPointer) -> Ordering { self.deref().cmp(other.deref()) } } impl From for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn from(other: T) -> SharedPointer { SharedPointer::new(other) } } impl From> for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn from(v: Box) -> SharedPointer { SharedPointer::new_from_inner(P::from_box(v)) } } impl Debug for SharedPointer where T: Debug, P: SharedPointerKind, { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { Debug::fmt(self.deref(), f) } } impl fmt::Pointer for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&core::ptr::addr_of!(**self), f) } } impl Display for SharedPointer where T: Display, P: SharedPointerKind, { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { Display::fmt(self.deref(), f) } } impl Drop for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn drop(&mut self) { unsafe { self.ptr.drop::(); } } } pub mod kind; #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer}; use ::serde::ser::{Serialize, Serializer}; impl Serialize for SharedPointer where T: Serialize, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { self.as_ref().serialize(serializer) } } impl<'de, T, P> Deserialize<'de> for SharedPointer where T: Deserialize<'de>, P: SharedPointerKind, { fn deserialize>( deserializer: D, ) -> Result, D::Error> { T::deserialize(deserializer).map(SharedPointer::new) } } } #[cfg(test)] mod test; archery/src/shared_pointer/kind/0000775000175000017500000000000015105742312016563 5ustar bdrungbdrungarchery/src/shared_pointer/kind/mod.rs0000644000175000017500000000461715105742312017716 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use core::fmt::Debug; /// Trait for [type constructors](https://en.wikipedia.org/wiki/Type_constructor) of /// reference-counting pointers. /// /// # Safety /// /// `T` may be `!`[`Unpin`], and [`SharedPointer`][1] may be held in a pinned /// form ([`Pin`][2]`>`). /// As such, the implementation of this trait must uphold the pinning invariants /// for `T` while it's held in `Self`. Specifically, this necessitates the /// following: /// /// - `&mut T` is only exposed through the trait methods returning `&mut T`. /// /// - The implementor must not move out the contained `T` unless the semantics /// of trait methods demands that. /// /// - [`Self::drop`] drops `T` in place. /// /// [1]: crate::shared_pointer::SharedPointer /// [2]: core::pin::Pin // // There are two conditions for types implementing this trait to be used in a safe way: // // 1. Always use the correct type `T`. // 2. Make sure that you use it wrapped in something that derives the correct auto-traits taking // into account the type of `T`. // // To elaborate on point 2: a `ArcK` will always implement `Send + Sync`, but that // is only safe if the actually type that `ArcK` holds is in fact `Send + Sync`. // This means that a safe wrapper around this type must make sure it does not implement // `Send + Sync` unless `T: Send + Sync`. This is holds true for `SharedPointer` since it has a // phantom field with `T`, thus the compiler will only make `SharedPointer` implement // `Send + Sync` if `T: Send + Sync`. pub unsafe trait SharedPointerKind: Sized + Debug { fn new(v: T) -> Self; fn from_box(v: Box) -> Self; unsafe fn as_ptr(&self) -> *const T; unsafe fn deref(&self) -> &T; unsafe fn try_unwrap(self) -> Result; unsafe fn get_mut(&mut self) -> Option<&mut T>; unsafe fn make_mut(&mut self) -> &mut T; unsafe fn strong_count(&self) -> usize; #[must_use] unsafe fn clone(&self) -> Self; unsafe fn drop(&mut self); } mod arc; #[cfg(feature = "triomphe")] mod arct; mod rc; use alloc::boxed::Box; #[doc(inline)] pub use arc::ArcK; #[cfg(feature = "triomphe")] #[doc(inline)] pub use arct::ArcTK; #[doc(inline)] pub use rc::RcK; archery/src/shared_pointer/kind/arct/0000775000175000017500000000000015105742312017514 5ustar bdrungbdrungarchery/src/shared_pointer/kind/arct/mod.rs0000644000175000017500000000672415105742312020650 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::shared_pointer::kind::SharedPointerKind; use alloc::boxed::Box; use core::fmt; use core::fmt::Debug; use core::fmt::Formatter; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ops::DerefMut; use core::ptr; use triomphe::Arc; type UntypedArc = Arc<()>; /// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for /// [`triomphe::Arc`](triomphe::Arc) pointers. pub struct ArcTK { /// We use [`ManuallyDrop`] here, so that we can drop it explicitly as /// [`Arc`](triomphe::Arc). Not sure if it can be dropped as [`UntypedArc`], but it /// seems to be playing with fire (even more than we already are). inner: ManuallyDrop, } impl ArcTK { #[inline(always)] fn new_from_inner(arc: Arc) -> ArcTK { ArcTK { inner: ManuallyDrop::new(unsafe { mem::transmute::, UntypedArc>(arc) }) } } #[inline(always)] unsafe fn take_inner(self) -> Arc { let arc: UntypedArc = ManuallyDrop::into_inner(self.inner); mem::transmute(arc) } #[inline(always)] unsafe fn as_inner_ref(&self) -> &Arc { let arc_t: *const Arc = (self.inner.deref() as *const UntypedArc).cast::>(); // Static check to make sure we are not messing up the sizes. // This could happen if we allowed for `T` to be unsized, because it would need to be // represented as a wide pointer inside `Arc`. // TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21 // gets fixed let _ = mem::transmute::>; &*arc_t } #[inline(always)] unsafe fn as_inner_mut(&mut self) -> &mut Arc { let arc_t: *mut Arc = (self.inner.deref_mut() as *mut UntypedArc).cast::>(); &mut *arc_t } } unsafe impl SharedPointerKind for ArcTK { #[inline(always)] fn new(v: T) -> ArcTK { ArcTK::new_from_inner(Arc::new(v)) } #[inline(always)] fn from_box(v: Box) -> ArcTK { ArcTK::new_from_inner::(Arc::from(v)) } #[inline(always)] unsafe fn as_ptr(&self) -> *const T { Arc::as_ptr(self.as_inner_ref()) } #[inline(always)] unsafe fn deref(&self) -> &T { self.as_inner_ref::().as_ref() } #[inline(always)] unsafe fn try_unwrap(self) -> Result { Arc::try_unwrap(self.take_inner()).map_err(ArcTK::new_from_inner) } #[inline(always)] unsafe fn get_mut(&mut self) -> Option<&mut T> { Arc::get_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn make_mut(&mut self) -> &mut T { Arc::make_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn strong_count(&self) -> usize { Arc::count(self.as_inner_ref::()) } #[inline(always)] unsafe fn clone(&self) -> ArcTK { ArcTK { inner: ManuallyDrop::new(Arc::clone(self.as_inner_ref())) } } #[inline(always)] unsafe fn drop(&mut self) { ptr::drop_in_place::>(self.as_inner_mut()); } } impl Debug for ArcTK { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { f.write_str("ArcTK") } } #[cfg(test)] mod test; archery/src/shared_pointer/kind/arct/test.rs0000644000175000017500000001056415105742312021045 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; use std::cell::Cell; use std::string::ToString; type PointerKind = ArcTK; assert_impl_all!(ArcTK: Send, Sync); #[test] fn test_from_box_t() { let mut ptr = PointerKind::from_box(Box::new(42)); unsafe { assert_eq!(ptr.deref::(), &42); ptr.drop::(); } } #[test] fn test_as_ptr() { let mut x = PointerKind::new::<&'static str>("hello"); unsafe { let mut y = PointerKind::clone::<&'static str>(&x); let x_ptr: *const &'static str = PointerKind::as_ptr(&x); assert_eq!(x_ptr, PointerKind::as_ptr(&y)); assert_eq!(*x_ptr, "hello"); x.drop::<&'static str>(); y.drop::<&'static str>(); } } #[test] fn test_deref() { let mut ptr_42 = PointerKind::new::(42); let mut ptr_box_dyn_hello = PointerKind::new::>(Box::new("hello")); unsafe { assert_eq!(ptr_42.deref::(), &42); assert_eq!(ptr_box_dyn_hello.deref::>().to_string(), "hello"); ptr_42.drop::(); ptr_box_dyn_hello.drop::>(); } } #[test] fn test_try_unwrap() { let ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.try_unwrap::().unwrap(), 42); } let ptr = PointerKind::new::(42); unsafe { let ptr_clone = ptr.clone::(); let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err(); let mut ptr = ptr.try_unwrap::().unwrap_err(); assert_eq!(ptr.deref::(), &42); assert_eq!(ptr_clone.deref::(), &42); ptr.drop::(); ptr_clone.drop::(); } } #[test] fn test_get_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.get_mut::().unwrap() += 1; assert_eq!(ptr.deref::(), &43); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.get_mut::(), None); assert_eq!(ptr_clone.get_mut::(), None); ptr.drop::(); *ptr_clone.get_mut::().unwrap() += 1; assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_make_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); // Clone to force make_mut to clone the data. let mut ptr_clone = ptr.clone::(); assert_eq!(ptr_clone.deref::(), &43); *ptr_clone.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); assert_eq!(ptr_clone.deref::(), &44); *ptr.make_mut::() *= 2; assert_eq!(ptr.deref::(), &(2 * 43)); assert_eq!(ptr_clone.deref::(), &44); ptr.drop::(); assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_strong_count() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.strong_count::(), 1); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.strong_count::(), 2); assert_eq!(ptr_clone.strong_count::(), 2); ptr.drop::(); assert_eq!(ptr_clone.strong_count::(), 1); ptr_clone.drop::(); } } #[test] fn test_clone() { let mut ptr = PointerKind::new::>(Cell::new(42)); unsafe { let mut ptr_clone = ptr.clone::>(); assert_eq!(ptr.deref::>().get(), 42); assert_eq!(ptr_clone.deref::>().get(), 42); ptr_clone.deref::>().set(3); assert_eq!(ptr.deref::>().get(), 3); assert_eq!(ptr_clone.deref::>().get(), 3); ptr.drop::>(); assert_eq!(ptr_clone.deref::>().get(), 3); ptr_clone.drop::>(); } } #[test] fn test_debug() { let mut ptr = PointerKind::new::(42); assert_eq!(format!("{:?}", ptr), "ArcTK"); unsafe { ptr.drop::(); } } archery/src/shared_pointer/kind/rc/0000775000175000017500000000000015105742312017167 5ustar bdrungbdrungarchery/src/shared_pointer/kind/rc/mod.rs0000644000175000017500000000665215105742312020323 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::shared_pointer::kind::SharedPointerKind; use alloc::boxed::Box; use alloc::rc::Rc; use core::fmt; use core::fmt::Debug; use core::fmt::Formatter; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ops::DerefMut; use core::ptr; type UntypedRc = Rc<()>; /// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for /// [`Rc`] pointers. pub struct RcK { /// We use [`ManuallyDrop`] here, so that we can drop it explicitly as [`Rc`](alloc::rc::Rc). /// Not sure if it can be dropped as [`UntypedRc`], but it seems to be playing with fire (even /// more than we already are). inner: ManuallyDrop, } impl RcK { #[inline(always)] fn new_from_inner(rc: Rc) -> RcK { RcK { inner: ManuallyDrop::new(unsafe { mem::transmute::, UntypedRc>(rc) }) } } #[inline(always)] unsafe fn take_inner(self) -> Rc { let rc: UntypedRc = ManuallyDrop::into_inner(self.inner); mem::transmute(rc) } #[inline(always)] unsafe fn as_inner_ref(&self) -> &Rc { let rc_t: *const Rc = (self.inner.deref() as *const UntypedRc).cast::>(); // Static check to make sure we are not messing up the sizes. // This could happen if we allowed for `T` to be unsized, because it would need to be // represented as a wide pointer inside `Rc`. // TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21 // gets fixed let _ = mem::transmute::>; &*rc_t } #[inline(always)] unsafe fn as_inner_mut(&mut self) -> &mut Rc { let rc_t: *mut Rc = (self.inner.deref_mut() as *mut UntypedRc).cast::>(); &mut *rc_t } } unsafe impl SharedPointerKind for RcK { #[inline(always)] fn new(v: T) -> RcK { RcK::new_from_inner(Rc::new(v)) } #[inline(always)] fn from_box(v: Box) -> RcK { RcK::new_from_inner::(Rc::from(v)) } #[inline(always)] unsafe fn as_ptr(&self) -> *const T { Rc::as_ptr(self.as_inner_ref()) } #[inline(always)] unsafe fn deref(&self) -> &T { self.as_inner_ref::().as_ref() } #[inline(always)] unsafe fn try_unwrap(self) -> Result { Rc::try_unwrap(self.take_inner()).map_err(RcK::new_from_inner) } #[inline(always)] unsafe fn get_mut(&mut self) -> Option<&mut T> { Rc::get_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn make_mut(&mut self) -> &mut T { Rc::make_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn strong_count(&self) -> usize { Rc::strong_count(self.as_inner_ref::()) } #[inline(always)] unsafe fn clone(&self) -> RcK { RcK { inner: ManuallyDrop::new(Rc::clone(self.as_inner_ref())) } } #[inline(always)] unsafe fn drop(&mut self) { ptr::drop_in_place::>(self.as_inner_mut()); } } impl Debug for RcK { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { f.write_str("RcK") } } #[cfg(test)] mod test; archery/src/shared_pointer/kind/rc/test.rs0000644000175000017500000001055215105742312020515 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use std::cell::Cell; use std::string::ToString; type PointerKind = RcK; #[test] fn test_from_box_t() { let mut ptr = PointerKind::from_box(Box::new(42)); unsafe { assert_eq!(ptr.deref::(), &42); ptr.drop::(); } } #[test] fn test_as_ptr() { let mut x = PointerKind::new::<&'static str>("hello from test_as_ptr"); unsafe { let mut y = PointerKind::clone::<&'static str>(&x); let x_ptr: *const &'static str = PointerKind::as_ptr(&x); assert_eq!(x_ptr, PointerKind::as_ptr(&y)); assert_eq!(*x_ptr, "hello from test_as_ptr"); x.drop::<&'static str>(); y.drop::<&'static str>(); } } #[test] fn test_deref() { let mut ptr_42 = PointerKind::new::(42); let mut ptr_box_dyn_hello = PointerKind::new::>(Box::new("hello from test_deref")); unsafe { assert_eq!(ptr_42.deref::(), &42); assert_eq!( ptr_box_dyn_hello.deref::>().to_string(), "hello from test_deref" ); ptr_42.drop::(); ptr_box_dyn_hello.drop::>(); } } #[test] fn test_try_unwrap() { let ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.try_unwrap::().unwrap(), 42); } let ptr = PointerKind::new::(42); unsafe { let ptr_clone = ptr.clone::(); let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err(); let mut ptr = ptr.try_unwrap::().unwrap_err(); assert_eq!(ptr.deref::(), &42); assert_eq!(ptr_clone.deref::(), &42); ptr.drop::(); ptr_clone.drop::(); } } #[test] fn test_get_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.get_mut::().unwrap() += 1; assert_eq!(ptr.deref::(), &43); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.get_mut::(), None); assert_eq!(ptr_clone.get_mut::(), None); ptr.drop::(); *ptr_clone.get_mut::().unwrap() += 1; assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_make_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); // Clone to force make_mut to clone the data. let mut ptr_clone = ptr.clone::(); assert_eq!(ptr_clone.deref::(), &43); *ptr_clone.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); assert_eq!(ptr_clone.deref::(), &44); *ptr.make_mut::() *= 2; assert_eq!(ptr.deref::(), &(2 * 43)); assert_eq!(ptr_clone.deref::(), &44); ptr.drop::(); assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_strong_count() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.strong_count::(), 1); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.strong_count::(), 2); assert_eq!(ptr_clone.strong_count::(), 2); ptr.drop::(); assert_eq!(ptr_clone.strong_count::(), 1); ptr_clone.drop::(); } } #[test] fn test_clone() { let mut ptr = PointerKind::new::>(Cell::new(42)); unsafe { let mut ptr_clone = ptr.clone::>(); assert_eq!(ptr.deref::>().get(), 42); assert_eq!(ptr_clone.deref::>().get(), 42); ptr_clone.deref::>().set(3); assert_eq!(ptr.deref::>().get(), 3); assert_eq!(ptr_clone.deref::>().get(), 3); ptr.drop::>(); assert_eq!(ptr_clone.deref::>().get(), 3); ptr_clone.drop::>(); } } #[test] fn test_debug() { let mut ptr = PointerKind::new::(42); assert_eq!(format!("{ptr:?}"), "RcK"); unsafe { ptr.drop::(); } } archery/src/shared_pointer/kind/arc/0000775000175000017500000000000015105742312017330 5ustar bdrungbdrungarchery/src/shared_pointer/kind/arc/mod.rs0000644000175000017500000000675315105742312020466 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::shared_pointer::kind::SharedPointerKind; use alloc::boxed::Box; use alloc::sync::Arc; use core::fmt; use core::fmt::Debug; use core::fmt::Formatter; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ops::DerefMut; use core::ptr; type UntypedArc = Arc<()>; /// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for /// [`Arc`] pointers. pub struct ArcK { /// We use [`ManuallyDrop`] here, so that we can drop it explicitly as /// [`Arc`](alloc::sync::Arc). Not sure if it can be dropped as [`UntypedArc`], but it /// seems to be playing with fire (even more than we already are). inner: ManuallyDrop, } impl ArcK { #[inline(always)] fn new_from_inner(arc: Arc) -> ArcK { ArcK { inner: ManuallyDrop::new(unsafe { mem::transmute::, UntypedArc>(arc) }) } } #[inline(always)] unsafe fn take_inner(self) -> Arc { let arc: UntypedArc = ManuallyDrop::into_inner(self.inner); mem::transmute(arc) } #[inline(always)] unsafe fn as_inner_ref(&self) -> &Arc { let arc_t: *const Arc = (self.inner.deref() as *const UntypedArc).cast::>(); // Static check to make sure we are not messing up the sizes. // This could happen if we allowed for `T` to be unsized, because it would need to be // represented as a wide pointer inside `Arc`. // TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21 // gets fixed let _ = mem::transmute::>; &*arc_t } #[inline(always)] unsafe fn as_inner_mut(&mut self) -> &mut Arc { let arc_t: *mut Arc = (self.inner.deref_mut() as *mut UntypedArc).cast::>(); &mut *arc_t } } unsafe impl SharedPointerKind for ArcK { #[inline(always)] fn new(v: T) -> ArcK { ArcK::new_from_inner(Arc::new(v)) } #[inline(always)] fn from_box(v: Box) -> ArcK { ArcK::new_from_inner::(Arc::from(v)) } #[inline(always)] unsafe fn as_ptr(&self) -> *const T { Arc::as_ptr(self.as_inner_ref()) } #[inline(always)] unsafe fn deref(&self) -> &T { self.as_inner_ref::().as_ref() } #[inline(always)] unsafe fn try_unwrap(self) -> Result { Arc::try_unwrap(self.take_inner()).map_err(ArcK::new_from_inner) } #[inline(always)] unsafe fn get_mut(&mut self) -> Option<&mut T> { Arc::get_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn make_mut(&mut self) -> &mut T { Arc::make_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn strong_count(&self) -> usize { Arc::strong_count(self.as_inner_ref::()) } #[inline(always)] unsafe fn clone(&self) -> ArcK { ArcK { inner: ManuallyDrop::new(Arc::clone(self.as_inner_ref())) } } #[inline(always)] unsafe fn drop(&mut self) { ptr::drop_in_place::>(self.as_inner_mut()); } } impl Debug for ArcK { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { f.write_str("ArcK") } } #[cfg(test)] mod test; archery/src/shared_pointer/kind/arc/test.rs0000644000175000017500000001056115105742312020656 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; use std::cell::Cell; use std::string::ToString; type PointerKind = ArcK; assert_impl_all!(ArcK: Send, Sync); #[test] fn test_from_box_t() { let mut ptr = PointerKind::from_box(Box::new(42)); unsafe { assert_eq!(ptr.deref::(), &42); ptr.drop::(); } } #[test] fn test_as_ptr() { let mut x = PointerKind::new::<&'static str>("hello"); unsafe { let mut y = PointerKind::clone::<&'static str>(&x); let x_ptr: *const &'static str = PointerKind::as_ptr(&x); assert_eq!(x_ptr, PointerKind::as_ptr(&y)); assert_eq!(*x_ptr, "hello"); x.drop::<&'static str>(); y.drop::<&'static str>(); } } #[test] fn test_deref() { let mut ptr_42 = PointerKind::new::(42); let mut ptr_box_dyn_hello = PointerKind::new::>(Box::new("hello")); unsafe { assert_eq!(ptr_42.deref::(), &42); assert_eq!(ptr_box_dyn_hello.deref::>().to_string(), "hello"); ptr_42.drop::(); ptr_box_dyn_hello.drop::>(); } } #[test] fn test_try_unwrap() { let ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.try_unwrap::().unwrap(), 42); } let ptr = PointerKind::new::(42); unsafe { let ptr_clone = ptr.clone::(); let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err(); let mut ptr = ptr.try_unwrap::().unwrap_err(); assert_eq!(ptr.deref::(), &42); assert_eq!(ptr_clone.deref::(), &42); ptr.drop::(); ptr_clone.drop::(); } } #[test] fn test_get_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.get_mut::().unwrap() += 1; assert_eq!(ptr.deref::(), &43); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.get_mut::(), None); assert_eq!(ptr_clone.get_mut::(), None); ptr.drop::(); *ptr_clone.get_mut::().unwrap() += 1; assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_make_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); // Clone to force make_mut to clone the data. let mut ptr_clone = ptr.clone::(); assert_eq!(ptr_clone.deref::(), &43); *ptr_clone.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); assert_eq!(ptr_clone.deref::(), &44); *ptr.make_mut::() *= 2; assert_eq!(ptr.deref::(), &(2 * 43)); assert_eq!(ptr_clone.deref::(), &44); ptr.drop::(); assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_strong_count() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.strong_count::(), 1); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.strong_count::(), 2); assert_eq!(ptr_clone.strong_count::(), 2); ptr.drop::(); assert_eq!(ptr_clone.strong_count::(), 1); ptr_clone.drop::(); } } #[test] fn test_clone() { let mut ptr = PointerKind::new::>(Cell::new(42)); unsafe { let mut ptr_clone = ptr.clone::>(); assert_eq!(ptr.deref::>().get(), 42); assert_eq!(ptr_clone.deref::>().get(), 42); ptr_clone.deref::>().set(3); assert_eq!(ptr.deref::>().get(), 3); assert_eq!(ptr_clone.deref::>().get(), 3); ptr.drop::>(); assert_eq!(ptr_clone.deref::>().get(), 3); ptr_clone.drop::>(); } } #[test] fn test_debug() { let mut ptr = PointerKind::new::(42); assert_eq!(format!("{:?}", ptr), "ArcK"); unsafe { ptr.drop::(); } } archery/src/shared_pointer/test.rs0000644000175000017500000002406415105742312017167 0ustar bdrungbdrung/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![allow(clippy::eq_op)] use super::*; use kind::ArcK; use kind::RcK; use static_assertions::assert_impl_all; use std::cell::Cell; use std::mem; use std::string::ToString; assert_impl_all!(SharedPointer: Send, Sync); mod static_check_rc_is_not_send_nor_sync { use crate::{RcK, SharedPointer}; use static_assertions::*; assert_impl_all!(i32: Send, Sync); assert_not_impl_any!(SharedPointer: Send); assert_not_impl_any!(SharedPointer: Sync); } mod static_check_arc_of_non_send_is_not_send_nor_sync { use crate::{ArcK, SharedPointer}; use static_assertions::*; use std::sync::MutexGuard; assert_not_impl_any!(MutexGuard<'static, ()>: Send); assert_impl_all!(MutexGuard<'static, ()>: Sync); assert_not_impl_any!(SharedPointer, ArcK>: Send); assert_not_impl_any!(SharedPointer, ArcK>: Sync); } mod static_check_arc_of_non_sync_is_not_send_nor_sync { use crate::{ArcK, SharedPointer}; use static_assertions::*; use std::cell::Cell; assert_impl_all!(Cell<()>: Send); assert_not_impl_any!(Cell<()>: Sync); assert_not_impl_any!(SharedPointer, ArcK>: Send); assert_not_impl_any!(SharedPointer, ArcK>: Sync); } mod static_check_arc_of_non_send_nor_sync_is_not_send_nor_sync { use crate::{ArcK, SharedPointer}; use alloc::rc::Rc; use static_assertions::*; assert_not_impl_any!(Rc: Send); assert_not_impl_any!(Rc: Sync); assert_not_impl_any!(SharedPointer, ArcK>: Send); assert_not_impl_any!(SharedPointer, ArcK>: Sync); } #[test] fn test_as_ptr() { let x = SharedPointer::<&'static str, RcK>::new("hello"); let y = SharedPointer::clone(&x); let x_ptr: *const &'static str = SharedPointer::as_ptr(&x); assert_eq!(x_ptr, SharedPointer::as_ptr(&y)); assert_eq!(unsafe { *x_ptr }, "hello"); } #[test] fn test_deref() { let ptr_42: SharedPointer = SharedPointer::new(42); let ptr_box_dyn_hello: SharedPointer, RcK> = SharedPointer::new(Box::new("hello")); assert_eq!(*ptr_42, 42); assert_eq!(ptr_box_dyn_hello.to_string(), "hello"); assert_eq!(*Borrow::::borrow(&ptr_42), 42); assert_eq!(Borrow::>::borrow(&ptr_box_dyn_hello).to_string(), "hello"); assert_eq!(*ptr_42.as_ref(), 42); assert_eq!(ptr_box_dyn_hello.as_ref().to_string(), "hello"); } #[test] fn test_try_unwrap() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(SharedPointer::try_unwrap(ptr).unwrap(), 42); let ptr: SharedPointer<_, RcK> = SharedPointer::new(42); let ptr_clone = SharedPointer::clone(&ptr); let ptr_clone = SharedPointer::try_unwrap(ptr_clone).unwrap_err(); let ptr = SharedPointer::try_unwrap(ptr).unwrap_err(); assert_eq!(*ptr, 42); assert_eq!(*ptr_clone, 42); } #[test] fn test_get_mut() { let mut ptr: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(*ptr, 42); *SharedPointer::get_mut(&mut ptr).unwrap() += 1; assert_eq!(*ptr, 43); let mut ptr_clone = SharedPointer::clone(&ptr); assert_eq!(SharedPointer::get_mut(&mut ptr), None); assert_eq!(SharedPointer::get_mut(&mut ptr_clone), None); mem::drop(ptr); *SharedPointer::get_mut(&mut ptr_clone).unwrap() += 1; assert_eq!(*ptr_clone, 44); } #[test] fn test_strong_count() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(SharedPointer::strong_count(&ptr), 1); let ptr_clone = SharedPointer::clone(&ptr); assert_eq!(SharedPointer::strong_count(&ptr), 2); assert_eq!(SharedPointer::strong_count(&ptr_clone), 2); mem::drop(ptr); assert_eq!(SharedPointer::strong_count(&ptr_clone), 1); } #[test] fn test_ptr_eq() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(42); let ptr_same_content: SharedPointer<_, RcK> = SharedPointer::new(42); let ptr_clone: SharedPointer<_, _> = SharedPointer::clone(&ptr); assert!(SharedPointer::ptr_eq(&ptr, &ptr)); assert!(!SharedPointer::ptr_eq(&ptr, &ptr_same_content)); assert!(SharedPointer::ptr_eq(&ptr, &ptr_clone)); } #[test] fn test_make_mut() { let mut ptr: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(*ptr, 42); *SharedPointer::make_mut(&mut ptr) += 1; assert_eq!(*ptr, 43); // Clone to force make_mut to clone the data. let mut ptr_clone = SharedPointer::clone(&ptr); assert_eq!(*ptr_clone, 43); *SharedPointer::make_mut(&mut ptr_clone) += 1; assert_eq!(*ptr, 43); assert_eq!(*ptr_clone, 44); *SharedPointer::make_mut(&mut ptr) *= 2; assert_eq!(*ptr, 2 * 43); assert_eq!(*ptr_clone, 44); mem::drop(ptr); assert_eq!(*ptr_clone, 44); } #[test] fn test_clone() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(Cell::new(42)); let ptr_clone = SharedPointer::clone(&ptr); assert_eq!(ptr.get(), 42); assert_eq!(ptr_clone.get(), 42); ptr_clone.set(3); assert_eq!(ptr.get(), 3); assert_eq!(ptr_clone.get(), 3); mem::drop(ptr); assert_eq!(ptr_clone.get(), 3); } fn hash(pointer: &SharedPointer) -> u64 { let mut hasher = std::collections::hash_map::DefaultHasher::new(); pointer.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { let ptr_42: SharedPointer<_, RcK> = SharedPointer::new(42); let ptr_hello: SharedPointer<_, RcK> = SharedPointer::new("hello"); assert_eq!(hash(&ptr_42), hash(&SharedPointer::<_, RcK>::new(42))); assert_eq!(hash(&ptr_hello), hash(&SharedPointer::<_, RcK>::new("hello"))); } #[test] fn test_hash_pointer_kind_consistent() { let ptr_hello_rc: SharedPointer<_, RcK> = SharedPointer::new("hello"); let ptr_hello_arc: SharedPointer<_, ArcK> = SharedPointer::new("hello"); assert_eq!(hash(&ptr_hello_rc), hash(&ptr_hello_arc)); } #[allow(clippy::nonminimal_bool)] #[test] fn test_eq() { let ptr_22: SharedPointer<_, RcK> = SharedPointer::new(22); let ptr_42: SharedPointer<_, RcK> = SharedPointer::new(42); assert!(ptr_22 == SharedPointer::<_, RcK>::new(22)); assert!(ptr_22 == SharedPointer::<_, ArcK>::new(22)); assert!(ptr_22 == ptr_22); assert!(!(ptr_22 == SharedPointer::<_, RcK>::new(42))); assert!(!(ptr_22 == SharedPointer::<_, ArcK>::new(42))); assert!(!(ptr_22 == ptr_42)); assert!(ptr_22 != SharedPointer::<_, RcK>::new(42)); assert!(ptr_22 != SharedPointer::<_, ArcK>::new(42)); assert!(ptr_22 != ptr_42); assert!(!(ptr_22 != SharedPointer::<_, RcK>::new(22))); assert!(!(ptr_22 != SharedPointer::<_, ArcK>::new(22))); assert!(!(ptr_22 != ptr_22)); } #[allow(clippy::cognitive_complexity)] #[allow(clippy::nonminimal_bool)] #[test] fn test_ord() { let ptr_22: SharedPointer<_, RcK> = SharedPointer::new(22); let ptr_42: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(ptr_22.partial_cmp(&SharedPointer::<_, RcK>::new(22)), Some(Ordering::Equal)); assert_eq!(ptr_22.partial_cmp(&SharedPointer::<_, RcK>::new(42)), Some(Ordering::Less)); assert_eq!(ptr_42.partial_cmp(&SharedPointer::<_, RcK>::new(22)), Some(Ordering::Greater)); assert_eq!(ptr_22.cmp(&SharedPointer::<_, RcK>::new(22)), Ordering::Equal); assert_eq!(ptr_22.cmp(&SharedPointer::<_, RcK>::new(42)), Ordering::Less); assert_eq!(ptr_42.cmp(&SharedPointer::<_, RcK>::new(22)), Ordering::Greater); assert!(ptr_22 < SharedPointer::<_, RcK>::new(42)); assert!(ptr_22 < SharedPointer::<_, ArcK>::new(42)); assert!(ptr_22 < ptr_42); assert!(!(ptr_42 < SharedPointer::<_, RcK>::new(22))); assert!(!(ptr_42 < SharedPointer::<_, ArcK>::new(22))); assert!(!(ptr_42 < ptr_22)); assert!(!(ptr_22 < ptr_22)); assert!(ptr_22 <= SharedPointer::<_, RcK>::new(42)); assert!(ptr_22 <= SharedPointer::<_, ArcK>::new(42)); assert!(ptr_22 <= ptr_42); assert!(ptr_22 <= ptr_22); assert!(!(ptr_42 <= SharedPointer::<_, RcK>::new(22))); assert!(!(ptr_42 <= SharedPointer::<_, ArcK>::new(22))); assert!(!(ptr_42 <= ptr_22)); assert!(ptr_42 > SharedPointer::<_, RcK>::new(22)); assert!(ptr_42 > SharedPointer::<_, ArcK>::new(22)); assert!(ptr_42 > ptr_22); assert!(!(ptr_22 > SharedPointer::<_, RcK>::new(42))); assert!(!(ptr_22 > SharedPointer::<_, ArcK>::new(42))); assert!(!(ptr_22 > ptr_42)); assert!(!(ptr_42 > ptr_42)); assert!(ptr_42 >= SharedPointer::<_, RcK>::new(22)); assert!(ptr_42 >= SharedPointer::<_, ArcK>::new(22)); assert!(ptr_42 >= ptr_22); assert!(ptr_42 >= ptr_42); assert!(!(ptr_22 >= SharedPointer::<_, RcK>::new(42))); assert!(!(ptr_22 >= SharedPointer::<_, ArcK>::new(42))); assert!(!(ptr_22 >= ptr_42)); } #[test] fn test_default() { let ptr: SharedPointer = SharedPointer::default(); assert_eq!(*ptr, 0); } #[test] fn test_from_box_t() { let ptr: SharedPointer = SharedPointer::from(Box::new(42)); assert_eq!(*ptr, 42); } #[test] fn test_from_t() { let ptr: SharedPointer = SharedPointer::from(42); assert_eq!(*ptr, 42); } #[test] fn test_debug() { let ptr: SharedPointer<_, RcK> = SharedPointer::new([1, 2, 3]); assert_eq!(format!("{ptr:?}"), "[1, 2, 3]"); } #[cfg(not(miri))] // Miri doesn't like this one. #[test] fn test_fmt_pointer() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(314); assert_eq!(format!("{ptr:p}"), format!("{:p}", ptr.deref() as *const i32)); } #[test] fn test_display() { let ptr: SharedPointer<_, RcK> = SharedPointer::new("hello"); assert_eq!(format!("{ptr}"), "hello"); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let ptr: SharedPointer<_, RcK> = SharedPointer::new("hello"); let encoded = serialize(&ptr).unwrap(); let decoded: SharedPointer<_, RcK> = deserialize(&encoded).unwrap(); pretty_assertions::assert_eq!(ptr, decoded); } autocfg/0000775000175000017500000000000015105742312012034 5ustar bdrungbdrungautocfg/tests/0000775000175000017500000000000015105742312013176 5ustar bdrungbdrungautocfg/tests/wrappers.rs0000644000175000017500000000374715105742312015420 0ustar bdrungbdrungextern crate autocfg; use std::env; mod support; /// Tests that autocfg uses the RUSTC_WRAPPER and/or RUSTC_WORKSPACE_WRAPPER /// environment variables when running rustc. #[test] #[cfg(unix)] // we're using system binaries as wrappers fn test_wrappers() { fn set(name: &str, value: Option) { match value { Some(true) => env::set_var(name, "/usr/bin/env"), Some(false) => env::set_var(name, "/bin/false"), None => env::remove_var(name), } } let out = support::out_dir(); // This is used as a heuristic to detect rust-lang/cargo#9601. env::set_var("CARGO_ENCODED_RUSTFLAGS", ""); // No wrapper, a good pass-through wrapper, and a bad wrapper. let variants = [None, Some(true), Some(false)]; for &workspace in &variants { for &rustc in &variants { set("RUSTC_WRAPPER", rustc); set("RUSTC_WORKSPACE_WRAPPER", workspace); let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); if rustc == Some(false) || workspace == Some(false) { // Everything should fail with bad wrappers. assert!(!ac.probe_type("usize")); } else { // Try known good and bad types for the wrapped rustc. assert!(ac.probe_type("usize")); assert!(!ac.probe_type("mesize")); } // Either way, we should have found the inner rustc version. assert!(ac.probe_rustc_version(1, 0)); } } // Finally, make sure that `RUSTC_WRAPPER` is applied outermost // by using something that doesn't pass through at all. env::set_var("RUSTC_WRAPPER", "./tests/wrap_ignored"); env::set_var("RUSTC_WORKSPACE_WRAPPER", "/bin/false"); let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); assert!(ac.probe_type("mesize")); // anything goes! // Make sure we also got the version from that wrapper. assert!(ac.probe_rustc_version(12345, 6789)); } autocfg/tests/tests.rs0000644000175000017500000000742615105742312014715 0ustar bdrungbdrungextern crate autocfg; use autocfg::AutoCfg; mod support; fn core_std(ac: &AutoCfg, path: &str) -> String { let krate = if ac.no_std() { "core" } else { "std" }; format!("{}::{}", krate, path) } fn assert_std(ac: &AutoCfg, probe_result: bool) { assert_eq!(!ac.no_std(), probe_result); } fn assert_min(ac: &AutoCfg, major: usize, minor: usize, probe_result: bool) { assert_eq!(ac.probe_rustc_version(major, minor), probe_result); } fn autocfg_for_test() -> AutoCfg { AutoCfg::with_dir(support::out_dir().as_ref()).unwrap() } #[test] fn autocfg_version() { let ac = autocfg_for_test(); assert!(ac.probe_rustc_version(1, 0)); } #[test] fn probe_add() { let ac = autocfg_for_test(); let add = core_std(&ac, "ops::Add"); let add_rhs = add.clone() + ""; let add_rhs_output = add.clone() + ""; let dyn_add_rhs_output = "dyn ".to_string() + &*add_rhs_output; assert!(ac.probe_path(&add)); assert!(ac.probe_trait(&add)); assert!(ac.probe_trait(&add_rhs)); assert!(ac.probe_trait(&add_rhs_output)); assert_min(&ac, 1, 27, ac.probe_type(&dyn_add_rhs_output)); } #[test] fn probe_as_ref() { let ac = autocfg_for_test(); let as_ref = core_std(&ac, "convert::AsRef"); let as_ref_str = as_ref.clone() + ""; let dyn_as_ref_str = "dyn ".to_string() + &*as_ref_str; assert!(ac.probe_path(&as_ref)); assert!(ac.probe_trait(&as_ref_str)); assert!(ac.probe_type(&as_ref_str)); assert_min(&ac, 1, 27, ac.probe_type(&dyn_as_ref_str)); } #[test] fn probe_i128() { let ac = autocfg_for_test(); let i128_path = core_std(&ac, "i128"); assert_min(&ac, 1, 26, ac.probe_path(&i128_path)); assert_min(&ac, 1, 26, ac.probe_type("i128")); } #[test] fn probe_sum() { let ac = autocfg_for_test(); let sum = core_std(&ac, "iter::Sum"); let sum_i32 = sum.clone() + ""; let dyn_sum_i32 = "dyn ".to_string() + &*sum_i32; assert_min(&ac, 1, 12, ac.probe_path(&sum)); assert_min(&ac, 1, 12, ac.probe_trait(&sum)); assert_min(&ac, 1, 12, ac.probe_trait(&sum_i32)); assert_min(&ac, 1, 12, ac.probe_type(&sum_i32)); assert_min(&ac, 1, 27, ac.probe_type(&dyn_sum_i32)); } #[test] fn probe_std() { let ac = autocfg_for_test(); assert_std(&ac, ac.probe_sysroot_crate("std")); } #[test] fn probe_alloc() { let ac = autocfg_for_test(); assert_min(&ac, 1, 36, ac.probe_sysroot_crate("alloc")); } #[test] fn probe_bad_sysroot_crate() { let ac = autocfg_for_test(); assert!(!ac.probe_sysroot_crate("doesnt_exist")); } #[test] fn probe_no_std() { let ac = autocfg_for_test(); assert!(ac.probe_type("i32")); assert!(ac.probe_type("[i32]")); assert_std(&ac, ac.probe_type("Vec")); } #[test] fn probe_expression() { let ac = autocfg_for_test(); assert!(ac.probe_expression(r#""test".trim_left()"#)); assert_min(&ac, 1, 30, ac.probe_expression(r#""test".trim_start()"#)); assert_std(&ac, ac.probe_expression("[1, 2, 3].to_vec()")); } #[test] fn probe_constant() { let ac = autocfg_for_test(); assert!(ac.probe_constant("1 + 2 + 3")); assert_min( &ac, 1, 33, ac.probe_constant("{ let x = 1 + 2 + 3; x * x }"), ); assert_min(&ac, 1, 39, ac.probe_constant(r#""test".len()"#)); } #[test] fn probe_raw() { let ac = autocfg_for_test(); let prefix = if ac.no_std() { "#![no_std]\n" } else { "" }; let f = |s| format!("{}{}", prefix, s); // This attribute **must** be used at the crate level. assert!(ac.probe_raw(&f("#![no_builtins]")).is_ok()); assert!(ac.probe_raw(&f("#![deny(dead_code)] fn x() {}")).is_err()); assert!(ac.probe_raw(&f("#![allow(dead_code)] fn x() {}")).is_ok()); assert!(ac .probe_raw(&f("#![deny(dead_code)] pub fn x() {}")) .is_ok()); } autocfg/tests/rustflags.rs0000644000175000017500000000216015105742312015553 0ustar bdrungbdrungextern crate autocfg; use std::env; mod support; /// Tests that autocfg uses the RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS /// environment variables when running rustc. #[test] fn test_with_sysroot() { let dir = support::exe_dir(); let out = support::out_dir(); // If we have encoded rustflags, they take precedence, even if empty. env::set_var("CARGO_ENCODED_RUSTFLAGS", ""); env::set_var("RUSTFLAGS", &format!("-L {}", dir.display())); let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); assert!(ac.probe_sysroot_crate("std")); assert!(!ac.probe_sysroot_crate("autocfg")); // Now try again with useful encoded args. env::set_var( "CARGO_ENCODED_RUSTFLAGS", &format!("-L\x1f{}", dir.display()), ); let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); assert!(ac.probe_sysroot_crate("autocfg")); // Try the old-style RUSTFLAGS, ensuring HOST != TARGET. env::remove_var("CARGO_ENCODED_RUSTFLAGS"); env::set_var("HOST", "lol"); let ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); assert!(ac.probe_sysroot_crate("autocfg")); } autocfg/tests/wrap_ignored0000755000175000017500000000044415105742312015604 0ustar bdrungbdrung#!/bin/bash for arg in "$@"; do case "$arg" in # Add our own version so we can check that the wrapper is used for that. "--version") echo "release: 12345.6789.0" ;; # Read all input so the writer doesn't get EPIPE when we exit. "-") read -d "" PROBE ;; esac done exit 0 autocfg/tests/no_std.rs0000644000175000017500000000134615105742312015034 0ustar bdrungbdrungextern crate autocfg; use std::env; mod support; /// Tests that we can control the use of `#![no_std]`. #[test] fn no_std() { // Clear the CI `TARGET`, if any, so we're just dealing with the // host target which always has `std` available. env::remove_var("TARGET"); // Use the same path as this test binary. let out = support::out_dir(); let mut ac = autocfg::AutoCfg::with_dir(out.as_ref()).unwrap(); assert!(!ac.no_std()); assert!(ac.probe_path("std::mem")); // `#![no_std]` was stabilized in Rust 1.6 if ac.probe_rustc_version(1, 6) { ac.set_no_std(true); assert!(ac.no_std()); assert!(!ac.probe_path("std::mem")); assert!(ac.probe_path("core::mem")); } } autocfg/tests/support/0000775000175000017500000000000015105742312014712 5ustar bdrungbdrungautocfg/tests/support/mod.rs0000644000175000017500000000115315105742312016035 0ustar bdrungbdrunguse std::borrow::Cow; use std::env; use std::path::{Path, PathBuf}; /// The directory containing this test binary. pub fn exe_dir() -> PathBuf { let exe = env::current_exe().unwrap(); exe.parent().unwrap().to_path_buf() } /// The directory to use for test probes. pub fn out_dir() -> Cow<'static, Path> { if let Some(tmpdir) = option_env!("CARGO_TARGET_TMPDIR") { Cow::Borrowed(tmpdir.as_ref()) } else if let Some(tmpdir) = env::var_os("TESTS_TARGET_DIR") { Cow::Owned(tmpdir.into()) } else { // Use the same path as this test binary. Cow::Owned(exe_dir()) } } autocfg/LICENSE-MIT0000644000175000017500000000203615105742312013467 0ustar bdrungbdrungCopyright (c) 2018 Josh Stone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. autocfg/Cargo.lock0000644000175000017500000000021315105742312013733 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] name = "autocfg" version = "1.4.0" autocfg/Cargo.toml0000644000175000017500000000303515105742312013763 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] rust-version = "1.0" name = "autocfg" version = "1.4.0" authors = ["Josh Stone "] build = false exclude = ["/.github/**"] autobins = false autoexamples = false autotests = false autobenches = false description = "Automatic cfg for Rust compiler features" documentation = "https://docs.rs/autocfg/" readme = "README.md" keywords = [ "rustc", "build", "autoconf", ] categories = ["development-tools::build-utils"] license = "Apache-2.0 OR MIT" repository = "https://github.com/cuviper/autocfg" [lib] name = "autocfg" path = "src/lib.rs" [[example]] name = "integers" path = "examples/integers.rs" [[example]] name = "nightly" path = "examples/nightly.rs" [[example]] name = "paths" path = "examples/paths.rs" [[example]] name = "traits" path = "examples/traits.rs" [[example]] name = "versions" path = "examples/versions.rs" [[test]] name = "no_std" path = "tests/no_std.rs" [[test]] name = "rustflags" path = "tests/rustflags.rs" [[test]] name = "tests" path = "tests/tests.rs" [[test]] name = "wrappers" path = "tests/wrappers.rs" [dependencies] autocfg/.cargo-checksum.json0000664000175000017500000000013115105742312015673 0ustar bdrungbdrung{"files":{},"package":"ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"}autocfg/LICENSE-APACHE0000644000175000017500000002513715105742312013766 0ustar bdrungbdrung Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. autocfg/examples/0000775000175000017500000000000015105742312013652 5ustar bdrungbdrungautocfg/examples/versions.rs0000644000175000017500000000033715105742312016071 0ustar bdrungbdrungextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); for i in 0..100 { ac.emit_rustc_version(1, i); } } autocfg/examples/integers.rs0000644000175000017500000000035315105742312016037 0ustar bdrungbdrungextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); for i in 3..8 { ac.emit_has_type(&format!("i{}", 1 << i)); } } autocfg/examples/paths.rs0000644000175000017500000000124015105742312015332 0ustar bdrungbdrungextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); // since ancient times... ac.emit_has_path("std::vec::Vec"); ac.emit_path_cfg("std::vec::Vec", "has_vec"); // rustc 1.10.0 ac.emit_has_path("std::panic::PanicInfo"); ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info"); // rustc 1.20.0 ac.emit_has_path("std::mem::ManuallyDrop"); ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop"); // rustc 1.25.0 ac.emit_has_path("std::ptr::NonNull"); ac.emit_path_cfg("std::ptr::NonNull", "has_non_null"); } autocfg/examples/traits.rs0000644000175000017500000000147215105742312015530 0ustar bdrungbdrungextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); // since ancient times... ac.emit_has_trait("std::ops::Add"); ac.emit_trait_cfg("std::ops::Add", "has_ops"); // trait parameters have to be provided ac.emit_has_trait("std::borrow::Borrow"); ac.emit_trait_cfg("std::borrow::Borrow", "has_borrow"); // rustc 1.8.0 ac.emit_has_trait("std::ops::AddAssign"); ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops"); // rustc 1.12.0 ac.emit_has_trait("std::iter::Sum"); ac.emit_trait_cfg("std::iter::Sum", "has_sum"); // rustc 1.28.0 ac.emit_has_trait("std::alloc::GlobalAlloc"); ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc"); } autocfg/examples/nightly.rs0000644000175000017500000000107715105742312015701 0ustar bdrungbdrungextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); // When this feature was stabilized, it also renamed the method to // `chunk_by`, so it's important to *use* the feature in your probe. let code = r#" #![feature(slice_group_by)] pub fn probe(slice: &[i32]) -> impl Iterator { slice.group_by(|a, b| a == b) } "#; if ac.probe_raw(code).is_ok() { autocfg::emit("has_slice_group_by"); } } autocfg/README.md0000644000175000017500000000671415105742312013321 0ustar bdrungbdrungautocfg ======= [![autocfg crate](https://img.shields.io/crates/v/autocfg.svg)](https://crates.io/crates/autocfg) [![autocfg documentation](https://docs.rs/autocfg/badge.svg)](https://docs.rs/autocfg) ![minimum rustc 1.0](https://img.shields.io/badge/rustc-1.0+-red.svg) ![build status](https://github.com/cuviper/autocfg/workflows/master/badge.svg) A Rust library for build scripts to automatically configure code based on compiler support. Code snippets are dynamically tested to see if the `rustc` will accept them, rather than hard-coding specific version support. ## Usage Add this to your `Cargo.toml`: ```toml [build-dependencies] autocfg = "1" ``` Then use it in your `build.rs` script to detect compiler features. For example, to test for 128-bit integer support, it might look like: ```rust extern crate autocfg; fn main() { let ac = autocfg::new(); ac.emit_has_type("i128"); // (optional) We don't need to rerun for anything external. autocfg::rerun_path("build.rs"); } ``` If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that should only be used when the compiler supports it. ## Release Notes - 1.4.0 (2024-09-26) - Add `emit_possibility` for Rust 1.80's [checked cfgs], and call that automatically for methods that conditionally `emit`, by @Techcable. [checked cfgs]: https://blog.rust-lang.org/2024/05/06/check-cfg.html - 1.3.0 (2024-05-03) - Add `probe_raw` for direct control of the code that will be test-compiled. - Use wrappers when querying the `rustc` version information too. - 1.2.0 (2024-03-25) - Add `no_std` and `set_no_std` to control the use of `#![no_std]` in probes. - Use `RUSTC_WRAPPER` and `RUSTC_WORKSPACE_WRAPPER` when they are set. - 1.1.0 (2022-02-07) - Use `CARGO_ENCODED_RUSTFLAGS` when it is set. - 1.0.1 (2020-08-20) - Apply `RUSTFLAGS` for more `--target` scenarios, by @adamreichold. - 1.0.0 (2020-01-08) - 🎉 Release 1.0! 🎉 (no breaking changes) - Add `probe_expression` and `emit_expression_cfg` to test arbitrary expressions. - Add `probe_constant` and `emit_constant_cfg` to test arbitrary constant expressions. - 0.1.7 (2019-10-20) - Apply `RUSTFLAGS` when probing `$TARGET != $HOST`, mainly for sysroot, by @roblabla. - 0.1.6 (2019-08-19) - Add `probe`/`emit_sysroot_crate`, by @leo60228. - 0.1.5 (2019-07-16) - Mask some warnings from newer rustc. - 0.1.4 (2019-05-22) - Relax `std`/`no_std` probing to a warning instead of an error. - Improve `rustc` bootstrap compatibility. - 0.1.3 (2019-05-21) - Auto-detects if `#![no_std]` is needed for the `$TARGET`. - 0.1.2 (2019-01-16) - Add `rerun_env(ENV)` to print `cargo:rerun-if-env-changed=ENV`. - Add `rerun_path(PATH)` to print `cargo:rerun-if-changed=PATH`. ## Minimum Rust version policy This crate's minimum supported `rustc` version is `1.0.0`. Compatibility is its entire reason for existence, so this crate will be extremely conservative about raising this requirement. If this is ever deemed necessary, it will be treated as a major breaking change for semver purposes. ## License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT) at your option. autocfg/src/0000775000175000017500000000000015105742312012623 5ustar bdrungbdrungautocfg/src/lib.rs0000644000175000017500000005004315105742312013737 0ustar bdrungbdrung//! A Rust library for build scripts to automatically configure code based on //! compiler support. Code snippets are dynamically tested to see if the `rustc` //! will accept them, rather than hard-coding specific version support. //! //! //! ## Usage //! //! Add this to your `Cargo.toml`: //! //! ```toml //! [build-dependencies] //! autocfg = "1" //! ``` //! //! Then use it in your `build.rs` script to detect compiler features. For //! example, to test for 128-bit integer support, it might look like: //! //! ```rust //! extern crate autocfg; //! //! fn main() { //! # // Normally, cargo will set `OUT_DIR` for build scripts. //! # let exe = std::env::current_exe().unwrap(); //! # std::env::set_var("OUT_DIR", exe.parent().unwrap()); //! let ac = autocfg::new(); //! ac.emit_has_type("i128"); //! //! // (optional) We don't need to rerun for anything external. //! autocfg::rerun_path("build.rs"); //! } //! ``` //! //! If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line //! for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the //! rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that //! should only be used when the compiler supports it. //! //! ## Caution //! //! Many of the probing methods of `AutoCfg` document the particular template they //! use, **subject to change**. The inputs are not validated to make sure they are //! semantically correct for their expected use, so it's _possible_ to escape and //! inject something unintended. However, such abuse is unsupported and will not //! be considered when making changes to the templates. #![deny(missing_debug_implementations)] #![deny(missing_docs)] // allow future warnings that can't be fixed while keeping 1.0 compatibility #![allow(unknown_lints)] #![allow(bare_trait_objects)] #![allow(ellipsis_inclusive_range_patterns)] /// Local macro to avoid `std::try!`, deprecated in Rust 1.39. macro_rules! try { ($result:expr) => { match $result { Ok(value) => value, Err(error) => return Err(error), } }; } use std::env; use std::ffi::OsString; use std::fmt::Arguments; use std::fs; use std::io::{stderr, Write}; use std::path::{Path, PathBuf}; use std::process::Stdio; #[allow(deprecated)] use std::sync::atomic::ATOMIC_USIZE_INIT; use std::sync::atomic::{AtomicUsize, Ordering}; mod error; pub use error::Error; mod rustc; use rustc::Rustc; mod version; use version::Version; #[cfg(test)] mod tests; /// Helper to detect compiler features for `cfg` output in build scripts. #[derive(Clone, Debug)] pub struct AutoCfg { out_dir: PathBuf, rustc: Rustc, rustc_version: Version, target: Option, no_std: bool, rustflags: Vec, uuid: u64, } /// Writes a config flag for rustc on standard out. /// /// This looks like: `cargo:rustc-cfg=CFG` /// /// Cargo will use this in arguments to rustc, like `--cfg CFG`. /// /// This does not automatically call [`emit_possibility`] /// so the compiler my generate an [`unexpected_cfgs` warning][check-cfg-flags]. /// However, all the builtin emit methods on [`AutoCfg`] call [`emit_possibility`] automatically. /// /// [check-cfg-flags]: https://blog.rust-lang.org/2024/05/06/check-cfg.html pub fn emit(cfg: &str) { println!("cargo:rustc-cfg={}", cfg); } /// Writes a line telling Cargo to rerun the build script if `path` changes. /// /// This looks like: `cargo:rerun-if-changed=PATH` /// /// This requires at least cargo 0.7.0, corresponding to rustc 1.6.0. Earlier /// versions of cargo will simply ignore the directive. pub fn rerun_path(path: &str) { println!("cargo:rerun-if-changed={}", path); } /// Writes a line telling Cargo to rerun the build script if the environment /// variable `var` changes. /// /// This looks like: `cargo:rerun-if-env-changed=VAR` /// /// This requires at least cargo 0.21.0, corresponding to rustc 1.20.0. Earlier /// versions of cargo will simply ignore the directive. pub fn rerun_env(var: &str) { println!("cargo:rerun-if-env-changed={}", var); } /// Indicates to rustc that a config flag should not generate an [`unexpected_cfgs` warning][check-cfg-flags] /// /// This looks like `cargo:rustc-check-cfg=cfg(VAR)` /// /// As of rust 1.80, the compiler does [automatic checking of cfgs at compile time][check-cfg-flags]. /// All custom configuration flags must be known to rustc, or they will generate a warning. /// This is done automatically when calling the builtin emit methods on [`AutoCfg`], /// but not when calling [`autocfg::emit`](crate::emit) directly. /// /// Versions before rust 1.80 will simply ignore this directive. /// /// This function indicates to the compiler that the config flag never has a value. /// If this is not desired, see [the blog post][check-cfg]. /// /// [check-cfg-flags]: https://blog.rust-lang.org/2024/05/06/check-cfg.html pub fn emit_possibility(cfg: &str) { println!("cargo:rustc-check-cfg=cfg({})", cfg); } /// Creates a new `AutoCfg` instance. /// /// # Panics /// /// Panics if `AutoCfg::new()` returns an error. pub fn new() -> AutoCfg { AutoCfg::new().unwrap() } impl AutoCfg { /// Creates a new `AutoCfg` instance. /// /// # Common errors /// /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`. /// - The version output from `rustc` can't be parsed. /// - `OUT_DIR` is not set in the environment, or is not a writable directory. /// pub fn new() -> Result { match env::var_os("OUT_DIR") { Some(d) => Self::with_dir(d), None => Err(error::from_str("no OUT_DIR specified!")), } } /// Creates a new `AutoCfg` instance with the specified output directory. /// /// # Common errors /// /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`. /// - The version output from `rustc` can't be parsed. /// - `dir` is not a writable directory. /// pub fn with_dir>(dir: T) -> Result { let rustc = Rustc::new(); let rustc_version = try!(rustc.version()); let target = env::var_os("TARGET"); // Sanity check the output directory let dir = dir.into(); let meta = try!(fs::metadata(&dir).map_err(error::from_io)); if !meta.is_dir() || meta.permissions().readonly() { return Err(error::from_str("output path is not a writable directory")); } let mut ac = AutoCfg { rustflags: rustflags(&target, &dir), out_dir: dir, rustc: rustc, rustc_version: rustc_version, target: target, no_std: false, uuid: new_uuid(), }; // Sanity check with and without `std`. if !ac.probe_raw("").is_ok() { if ac.probe_raw("#![no_std]").is_ok() { ac.no_std = true; } else { // Neither worked, so assume nothing... let warning = b"warning: autocfg could not probe for `std`\n"; stderr().write_all(warning).ok(); } } Ok(ac) } /// Returns whether `AutoCfg` is using `#![no_std]` in its probes. /// /// This is automatically detected during construction -- if an empty probe /// fails while one with `#![no_std]` succeeds, then the attribute will be /// used for all further probes. This is usually only necessary when the /// `TARGET` lacks `std` altogether. If neither succeeds, `no_std` is not /// set, but that `AutoCfg` will probably only work for version checks. /// /// This attribute changes the implicit [prelude] from `std` to `core`, /// which may affect the paths you need to use in other probes. It also /// restricts some types that otherwise get additional methods in `std`, /// like floating-point trigonometry and slice sorting. /// /// See also [`set_no_std`](#method.set_no_std). /// /// [prelude]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute pub fn no_std(&self) -> bool { self.no_std } /// Sets whether `AutoCfg` should use `#![no_std]` in its probes. /// /// See also [`no_std`](#method.no_std). pub fn set_no_std(&mut self, no_std: bool) { self.no_std = no_std; } /// Tests whether the current `rustc` reports a version greater than /// or equal to "`major`.`minor`". pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool { self.rustc_version >= Version::new(major, minor, 0) } /// Sets a `cfg` value of the form `rustc_major_minor`, like `rustc_1_29`, /// if the current `rustc` is at least that version. pub fn emit_rustc_version(&self, major: usize, minor: usize) { let cfg_flag = format!("rustc_{}_{}", major, minor); emit_possibility(&cfg_flag); if self.probe_rustc_version(major, minor) { emit(&cfg_flag); } } /// Returns a new (hopefully unique) crate name for probes. fn new_crate_name(&self) -> String { #[allow(deprecated)] static ID: AtomicUsize = ATOMIC_USIZE_INIT; let id = ID.fetch_add(1, Ordering::Relaxed); format!("autocfg_{:016x}_{}", self.uuid, id) } fn probe_fmt<'a>(&self, source: Arguments<'a>) -> Result<(), Error> { let mut command = self.rustc.command(); command .arg("--crate-name") .arg(self.new_crate_name()) .arg("--crate-type=lib") .arg("--out-dir") .arg(&self.out_dir) .arg("--emit=llvm-ir"); if let Some(target) = self.target.as_ref() { command.arg("--target").arg(target); } command.args(&self.rustflags); command.arg("-").stdin(Stdio::piped()); let mut child = try!(command.spawn().map_err(error::from_io)); let mut stdin = child.stdin.take().expect("rustc stdin"); try!(stdin.write_fmt(source).map_err(error::from_io)); drop(stdin); match child.wait() { Ok(status) if status.success() => Ok(()), Ok(status) => Err(error::from_exit(status)), Err(error) => Err(error::from_io(error)), } } fn probe<'a>(&self, code: Arguments<'a>) -> bool { let result = if self.no_std { self.probe_fmt(format_args!("#![no_std]\n{}", code)) } else { self.probe_fmt(code) }; result.is_ok() } /// Tests whether the given code can be compiled as a Rust library. /// /// This will only return `Ok` if the compiler ran and exited successfully, /// per `ExitStatus::success()`. /// The code is passed to the compiler exactly as-is, notably not even /// adding the [`#![no_std]`][Self::no_std] attribute like other probes. /// /// Raw probes are useful for testing functionality that's not yet covered /// by the rest of the `AutoCfg` API. For example, the following attribute /// **must** be used at the crate level, so it wouldn't work within the code /// templates used by other `probe_*` methods. /// /// ``` /// # extern crate autocfg; /// # // Normally, cargo will set `OUT_DIR` for build scripts. /// # let exe = std::env::current_exe().unwrap(); /// # std::env::set_var("OUT_DIR", exe.parent().unwrap()); /// let ac = autocfg::new(); /// assert!(ac.probe_raw("#![no_builtins]").is_ok()); /// ``` /// /// Rust nightly features could be tested as well -- ideally including a /// code sample to ensure the unstable feature still works as expected. /// For example, `slice::group_by` was renamed to `chunk_by` when it was /// stabilized, even though the feature name was unchanged, so testing the /// `#![feature(..)]` alone wouldn't reveal that. For larger snippets, /// [`include_str!`] may be useful to load them from separate files. /// /// ``` /// # extern crate autocfg; /// # // Normally, cargo will set `OUT_DIR` for build scripts. /// # let exe = std::env::current_exe().unwrap(); /// # std::env::set_var("OUT_DIR", exe.parent().unwrap()); /// let ac = autocfg::new(); /// let code = r#" /// #![feature(slice_group_by)] /// pub fn probe(slice: &[i32]) -> impl Iterator { /// slice.group_by(|a, b| a == b) /// } /// "#; /// if ac.probe_raw(code).is_ok() { /// autocfg::emit("has_slice_group_by"); /// } /// ``` pub fn probe_raw(&self, code: &str) -> Result<(), Error> { self.probe_fmt(format_args!("{}", code)) } /// Tests whether the given sysroot crate can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// extern crate CRATE as probe; /// ``` pub fn probe_sysroot_crate(&self, name: &str) -> bool { // Note: `as _` wasn't stabilized until Rust 1.33 self.probe(format_args!("extern crate {} as probe;", name)) } /// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true. pub fn emit_sysroot_crate(&self, name: &str) { let cfg_flag = format!("has_{}", mangle(name)); emit_possibility(&cfg_flag); if self.probe_sysroot_crate(name) { emit(&cfg_flag); } } /// Tests whether the given path can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub use PATH; /// ``` pub fn probe_path(&self, path: &str) -> bool { self.probe(format_args!("pub use {};", path)) } /// Emits a config value `has_PATH` if `probe_path` returns true. /// /// Any non-identifier characters in the `path` will be replaced with /// `_` in the generated config value. pub fn emit_has_path(&self, path: &str) { self.emit_path_cfg(path, &format!("has_{}", mangle(path))); } /// Emits the given `cfg` value if `probe_path` returns true. pub fn emit_path_cfg(&self, path: &str, cfg: &str) { emit_possibility(cfg); if self.probe_path(path) { emit(cfg); } } /// Tests whether the given trait can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub trait Probe: TRAIT + Sized {} /// ``` pub fn probe_trait(&self, name: &str) -> bool { self.probe(format_args!("pub trait Probe: {} + Sized {{}}", name)) } /// Emits a config value `has_TRAIT` if `probe_trait` returns true. /// /// Any non-identifier characters in the trait `name` will be replaced with /// `_` in the generated config value. pub fn emit_has_trait(&self, name: &str) { self.emit_trait_cfg(name, &format!("has_{}", mangle(name))); } /// Emits the given `cfg` value if `probe_trait` returns true. pub fn emit_trait_cfg(&self, name: &str, cfg: &str) { emit_possibility(cfg); if self.probe_trait(name) { emit(cfg); } } /// Tests whether the given type can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub type Probe = TYPE; /// ``` pub fn probe_type(&self, name: &str) -> bool { self.probe(format_args!("pub type Probe = {};", name)) } /// Emits a config value `has_TYPE` if `probe_type` returns true. /// /// Any non-identifier characters in the type `name` will be replaced with /// `_` in the generated config value. pub fn emit_has_type(&self, name: &str) { self.emit_type_cfg(name, &format!("has_{}", mangle(name))); } /// Emits the given `cfg` value if `probe_type` returns true. pub fn emit_type_cfg(&self, name: &str, cfg: &str) { emit_possibility(cfg); if self.probe_type(name) { emit(cfg); } } /// Tests whether the given expression can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub fn probe() { let _ = EXPR; } /// ``` pub fn probe_expression(&self, expr: &str) -> bool { self.probe(format_args!("pub fn probe() {{ let _ = {}; }}", expr)) } /// Emits the given `cfg` value if `probe_expression` returns true. pub fn emit_expression_cfg(&self, expr: &str, cfg: &str) { emit_possibility(cfg); if self.probe_expression(expr) { emit(cfg); } } /// Tests whether the given constant expression can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub const PROBE: () = ((), EXPR).0; /// ``` pub fn probe_constant(&self, expr: &str) -> bool { self.probe(format_args!("pub const PROBE: () = ((), {}).0;", expr)) } /// Emits the given `cfg` value if `probe_constant` returns true. pub fn emit_constant_cfg(&self, expr: &str, cfg: &str) { emit_possibility(cfg); if self.probe_constant(expr) { emit(cfg); } } } fn mangle(s: &str) -> String { s.chars() .map(|c| match c { 'A'...'Z' | 'a'...'z' | '0'...'9' => c, _ => '_', }) .collect() } fn dir_contains_target( target: &Option, dir: &Path, cargo_target_dir: Option, ) -> bool { target .as_ref() .and_then(|target| { dir.to_str().and_then(|dir| { let mut cargo_target_dir = cargo_target_dir .map(PathBuf::from) .unwrap_or_else(|| PathBuf::from("target")); cargo_target_dir.push(target); cargo_target_dir .to_str() .map(|cargo_target_dir| dir.contains(cargo_target_dir)) }) }) .unwrap_or(false) } fn rustflags(target: &Option, dir: &Path) -> Vec { // Starting with rust-lang/cargo#9601, shipped in Rust 1.55, Cargo always sets // CARGO_ENCODED_RUSTFLAGS for any host/target build script invocation. This // includes any source of flags, whether from the environment, toml config, or // whatever may come in the future. The value is either an empty string, or a // list of arguments separated by the ASCII unit separator (US), 0x1f. if let Ok(a) = env::var("CARGO_ENCODED_RUSTFLAGS") { return if a.is_empty() { Vec::new() } else { a.split('\x1f').map(str::to_string).collect() }; } // Otherwise, we have to take a more heuristic approach, and we don't // support values from toml config at all. // // Cargo only applies RUSTFLAGS for building TARGET artifact in // cross-compilation environment. Sadly, we don't have a way to detect // when we're building HOST artifact in a cross-compilation environment, // so for now we only apply RUSTFLAGS when cross-compiling an artifact. // // See https://github.com/cuviper/autocfg/pull/10#issuecomment-527575030. if *target != env::var_os("HOST") || dir_contains_target(target, dir, env::var_os("CARGO_TARGET_DIR")) { if let Ok(rustflags) = env::var("RUSTFLAGS") { // This is meant to match how cargo handles the RUSTFLAGS environment variable. // See https://github.com/rust-lang/cargo/blob/69aea5b6f69add7c51cca939a79644080c0b0ba0/src/cargo/core/compiler/build_context/target_info.rs#L434-L441 return rustflags .split(' ') .map(str::trim) .filter(|s| !s.is_empty()) .map(str::to_string) .collect(); } } Vec::new() } /// Generates a numeric ID to use in probe crate names. /// /// This attempts to be random, within the constraints of Rust 1.0 and no dependencies. fn new_uuid() -> u64 { const FNV_OFFSET_BASIS: u64 = 0xcbf2_9ce4_8422_2325; const FNV_PRIME: u64 = 0x100_0000_01b3; // This set should have an actual random hasher. let set: std::collections::HashSet = (0..256).collect(); // Feed the `HashSet`-shuffled order into FNV-1a. let mut hash: u64 = FNV_OFFSET_BASIS; for x in set { hash = (hash ^ x).wrapping_mul(FNV_PRIME); } hash } autocfg/src/version.rs0000644000175000017500000000417415105742312014662 0ustar bdrungbdrunguse std::process::Command; use std::str; use super::{error, Error}; /// A version structure for making relative comparisons. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Version { major: usize, minor: usize, patch: usize, } impl Version { /// Creates a `Version` instance for a specific `major.minor.patch` version. pub fn new(major: usize, minor: usize, patch: usize) -> Self { Version { major: major, minor: minor, patch: patch, } } pub fn from_command(command: &mut Command) -> Result { // Get rustc's verbose version let output = try!(command .args(&["--version", "--verbose"]) .output() .map_err(error::from_io)); if !output.status.success() { return Err(error::from_str("could not execute rustc")); } let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8)); // Find the release line in the verbose version output. let release = match output.lines().find(|line| line.starts_with("release: ")) { Some(line) => &line["release: ".len()..], None => return Err(error::from_str("could not find rustc release")), }; // Strip off any extra channel info, e.g. "-beta.N", "-nightly" let version = match release.find('-') { Some(i) => &release[..i], None => release, }; // Split the version into semver components. let mut iter = version.splitn(3, '.'); let major = try!(iter .next() .ok_or_else(|| error::from_str("missing major version"))); let minor = try!(iter .next() .ok_or_else(|| error::from_str("missing minor version"))); let patch = try!(iter .next() .ok_or_else(|| error::from_str("missing patch version"))); Ok(Version::new( try!(major.parse().map_err(error::from_num)), try!(minor.parse().map_err(error::from_num)), try!(patch.parse().map_err(error::from_num)), )) } } autocfg/src/tests.rs0000644000175000017500000000273315105742312014336 0ustar bdrungbdrunguse std::path::Path; #[test] fn version_cmp() { use super::version::Version; let v123 = Version::new(1, 2, 3); assert!(Version::new(1, 0, 0) < v123); assert!(Version::new(1, 2, 2) < v123); assert!(Version::new(1, 2, 3) == v123); assert!(Version::new(1, 2, 4) > v123); assert!(Version::new(1, 10, 0) > v123); assert!(Version::new(2, 0, 0) > v123); } #[test] fn dir_does_not_contain_target() { assert!(!super::dir_contains_target( &Some("x86_64-unknown-linux-gnu".into()), Path::new("/project/target/debug/build/project-ea75983148559682/out"), None, )); } #[test] fn dir_does_contain_target() { assert!(super::dir_contains_target( &Some("x86_64-unknown-linux-gnu".into()), Path::new( "/project/target/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out" ), None, )); } #[test] fn dir_does_not_contain_target_with_custom_target_dir() { assert!(!super::dir_contains_target( &Some("x86_64-unknown-linux-gnu".into()), Path::new("/project/custom/debug/build/project-ea75983148559682/out"), Some("custom".into()), )); } #[test] fn dir_does_contain_target_with_custom_target_dir() { assert!(super::dir_contains_target( &Some("x86_64-unknown-linux-gnu".into()), Path::new( "/project/custom/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out" ), Some("custom".into()), )); } autocfg/src/error.rs0000644000175000017500000000341615105742312014324 0ustar bdrungbdrunguse std::error; use std::fmt; use std::io; use std::num; use std::process; use std::str; /// A common error type for the `autocfg` crate. #[derive(Debug)] pub struct Error { kind: ErrorKind, } impl error::Error for Error { fn description(&self) -> &str { "AutoCfg error" } fn cause(&self) -> Option<&error::Error> { match self.kind { ErrorKind::Io(ref e) => Some(e), ErrorKind::Num(ref e) => Some(e), ErrorKind::Utf8(ref e) => Some(e), ErrorKind::Process(_) | ErrorKind::Other(_) => None, } } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self.kind { ErrorKind::Io(ref e) => e.fmt(f), ErrorKind::Num(ref e) => e.fmt(f), ErrorKind::Utf8(ref e) => e.fmt(f), ErrorKind::Process(ref status) => { // Same message as the newer `ExitStatusError` write!(f, "process exited unsuccessfully: {}", status) } ErrorKind::Other(s) => s.fmt(f), } } } #[derive(Debug)] enum ErrorKind { Io(io::Error), Num(num::ParseIntError), Process(process::ExitStatus), Utf8(str::Utf8Error), Other(&'static str), } pub fn from_exit(status: process::ExitStatus) -> Error { Error { kind: ErrorKind::Process(status), } } pub fn from_io(e: io::Error) -> Error { Error { kind: ErrorKind::Io(e), } } pub fn from_num(e: num::ParseIntError) -> Error { Error { kind: ErrorKind::Num(e), } } pub fn from_utf8(e: str::Utf8Error) -> Error { Error { kind: ErrorKind::Utf8(e), } } pub fn from_str(s: &'static str) -> Error { Error { kind: ErrorKind::Other(s), } } autocfg/src/rustc.rs0000644000175000017500000000525415105742312014335 0ustar bdrungbdrunguse std::env; use std::ffi::OsString; use std::path::PathBuf; use std::process::Command; use super::error::Error; use super::version::Version; #[derive(Clone, Debug)] pub struct Rustc { rustc: PathBuf, rustc_wrapper: Option, rustc_workspace_wrapper: Option, } impl Rustc { pub fn new() -> Self { Rustc { rustc: env::var_os("RUSTC") .unwrap_or_else(|| "rustc".into()) .into(), rustc_wrapper: get_rustc_wrapper(false), rustc_workspace_wrapper: get_rustc_wrapper(true), } } /// Build the command with possible wrappers. pub fn command(&self) -> Command { let mut rustc = self .rustc_wrapper .iter() .chain(self.rustc_workspace_wrapper.iter()) .chain(Some(&self.rustc)); let mut command = Command::new(rustc.next().unwrap()); for arg in rustc { command.arg(arg); } command } /// Try to get the `rustc` version. pub fn version(&self) -> Result { // Some wrappers like clippy-driver don't pass through version commands, // so we try to fall back to combinations without each wrapper. macro_rules! try_version { ($command:expr) => { if let Ok(value) = Version::from_command($command) { return Ok(value); } }; } let rustc = &self.rustc; if let Some(ref rw) = self.rustc_wrapper { if let Some(ref rww) = self.rustc_workspace_wrapper { try_version!(Command::new(rw).args(&[rww, rustc])); } try_version!(Command::new(rw).arg(rustc)); } if let Some(ref rww) = self.rustc_workspace_wrapper { try_version!(Command::new(rww).arg(rustc)); } Version::from_command(&mut Command::new(rustc)) } } fn get_rustc_wrapper(workspace: bool) -> Option { // We didn't really know whether the workspace wrapper is applicable until Cargo started // deliberately setting or unsetting it in rust-lang/cargo#9601. We'll use the encoded // rustflags as a proxy for that change for now, but we could instead check version 1.55. if workspace && env::var_os("CARGO_ENCODED_RUSTFLAGS").is_none() { return None; } let name = if workspace { "RUSTC_WORKSPACE_WRAPPER" } else { "RUSTC_WRAPPER" }; if let Some(wrapper) = env::var_os(name) { // NB: `OsStr` didn't get `len` or `is_empty` until 1.9. if wrapper != OsString::new() { return Some(wrapper.into()); } } None } cc/0000775000175000017500000000000015105742312010771 5ustar bdrungbdrungcc/LICENSE-MIT0000644000175000017500000000204115105742312012420 0ustar bdrungbdrungCopyright (c) 2014 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cc/clippy.toml0000644000175000017500000000033115105742312013161 0ustar bdrungbdrungdisallowed-methods = [ { path = "std::env::var_os", reason = "Please use Build::getenv" }, { path = "std::env::var", reason = "Please use Build::getenv" }, ] doc-valid-idents = ["AppleClang", "OpenBSD", ".."] cc/Cargo.lock0000644000175000017500000001321615105742312012677 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "cc" version = "1.2.25" dependencies = [ "jobserver", "libc", "shlex", "tempfile", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "getrandom" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", "r-efi", "wasi", ] [[package]] name = "jobserver" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ "getrandom", "libc", ] [[package]] name = "libc" version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "linux-raw-sys" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "r-efi" version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "rustix" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "tempfile" version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", "getrandom", "once_cell", "rustix", "windows-sys", ] [[package]] name = "wasi" version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "wit-bindgen-rt" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] cc/Cargo.toml0000644000175000017500000000311015105742312012712 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.63" name = "cc" version = "1.2.25" authors = ["Alex Crichton "] build = false exclude = [ "/.github", "tests", "src/bin", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = """ A build-time dependency for Cargo build scripts to assist in invoking the native C compiler to compile native C code into a static archive to be linked into Rust code. """ homepage = "https://github.com/rust-lang/cc-rs" documentation = "https://docs.rs/cc" readme = "README.md" keywords = ["build-dependencies"] categories = ["development-tools::build-utils"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/cc-rs" [features] jobserver = [] parallel = [ "dep:libc", "dep:jobserver", ] [lib] name = "cc" path = "src/lib.rs" [dependencies.jobserver] version = "0.1.30" optional = true default-features = false [dependencies.shlex] version = "1.3.0" [dev-dependencies.tempfile] version = "3" [target."cfg(unix)".dependencies.libc] version = "0.2.62" optional = true default-features = false cc/.cargo-checksum.json0000664000175000017500000000013115105742312014630 0ustar bdrungbdrung{"files":{},"package":"d0fc897dc1e865cc67c0e05a836d9d3f1df3cbe442aa4a9473b18e12624a4951"}cc/LICENSE-APACHE0000644000175000017500000002513715105742312012723 0ustar bdrungbdrung Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. cc/README.md0000644000175000017500000000204715105742312012251 0ustar bdrungbdrung# cc-rs A library for [Cargo build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html) to compile a set of C/C++/assembly/CUDA files into a static archive for Cargo to link into the crate being built. This crate does not compile code itself; it calls out to the default compiler for the platform. This crate will automatically detect situations such as cross compilation and various environment variables and will build code appropriately. Refer to the [documentation](https://docs.rs/cc) for detailed usage instructions. ## License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in cc-rs by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. cc/CHANGELOG.md0000644000175000017500000005552015105742312012607 0ustar bdrungbdrung# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [1.2.25](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.24...cc-v1.2.25) - 2025-05-30 ### Other - make `powerp64` use `powerpc64-linux-gnu` prefix ([#1474](https://github.com/rust-lang/cc-rs/pull/1474)) ## [1.2.24](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.23...cc-v1.2.24) - 2025-05-23 ### Other - Regenerate windows sys bindings ([#1471](https://github.com/rust-lang/cc-rs/pull/1471)) ## [1.2.23](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.22...cc-v1.2.23) - 2025-05-16 ### Other - support "vxworks" and "nto" OSes on `get_base_archiver_variant` ([#1456](https://github.com/rust-lang/cc-rs/pull/1456)) ## [1.2.22](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.21...cc-v1.2.22) - 2025-05-09 ### Other - Add `flags` method to `cc::Build` for adding multiple flags ([#1466](https://github.com/rust-lang/cc-rs/pull/1466)) ## [1.2.21](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.20...cc-v1.2.21) - 2025-05-02 ### Other - Fix wasm32-unknown-unknown by passing -c ([#1424](https://github.com/rust-lang/cc-rs/pull/1424)) ## [1.2.20](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.19...cc-v1.2.20) - 2025-04-25 ### Other - Regenerate target info ([#1461](https://github.com/rust-lang/cc-rs/pull/1461)) - Fix parser.rs on latest rustc nightly ([#1459](https://github.com/rust-lang/cc-rs/pull/1459)) ## [1.2.19](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.18...cc-v1.2.19) - 2025-04-11 ### Other - Fix musl compilation: Add musl as a prefix fallback ([#1455](https://github.com/rust-lang/cc-rs/pull/1455)) ## [1.2.18](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.17...cc-v1.2.18) - 2025-04-04 ### Other - Regenerate target info ([#1450](https://github.com/rust-lang/cc-rs/pull/1450)) - Use `std::thread::available_parallelism` for determining the default number of jobs ([#1447](https://github.com/rust-lang/cc-rs/pull/1447)) - Fix mips64-openwrt-linux-musl parsing ([#1449](https://github.com/rust-lang/cc-rs/pull/1449)) - Use compiler prefix `x86_64-linux-musl` ([#1443](https://github.com/rust-lang/cc-rs/pull/1443)) ## [1.2.17](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.16...cc-v1.2.17) - 2025-03-21 ### Other - Regenerate target info ([#1439](https://github.com/rust-lang/cc-rs/pull/1439)) - Regenerate windows sys bindings ([#1437](https://github.com/rust-lang/cc-rs/pull/1437)) - Fix wasm32-wali-linux-musl target parsing ([#1434](https://github.com/rust-lang/cc-rs/pull/1434)) - Parse `rustc` target names ([#1413](https://github.com/rust-lang/cc-rs/pull/1413)) - Regenerate target info ([#1429](https://github.com/rust-lang/cc-rs/pull/1429)) - Added base support for `wasm32-wali-linux-musl` target ([#1373](https://github.com/rust-lang/cc-rs/pull/1373)) ## [1.2.16](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.15...cc-v1.2.16) - 2025-02-28 ### Fixed - force windows compiler to run in `out_dir` to prevent artifacts in cwd (#1415) ### Other - use `/arch:SSE2` for `x86` target arch (#1425) - Regenerate windows-sys binding ([#1422](https://github.com/rust-lang/cc-rs/pull/1422)) - Regenerate target info ([#1418](https://github.com/rust-lang/cc-rs/pull/1418)) - Add LIB var when compiling flag_check (#1417) - Change flag ordering ([#1403](https://github.com/rust-lang/cc-rs/pull/1403)) - Fix archiver detection for musl cross compilation ([#1404](https://github.com/rust-lang/cc-rs/pull/1404)) ## [1.2.15](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.14...cc-v1.2.15) - 2025-02-21 ### Other - Regenerate target info ([#1406](https://github.com/rust-lang/cc-rs/pull/1406)) - Always read from all `CFLAGS`-style flags ([#1401](https://github.com/rust-lang/cc-rs/pull/1401)) - Simplify the error output on failed `Command` invocation ([#1397](https://github.com/rust-lang/cc-rs/pull/1397)) ## [1.2.14](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.13...cc-v1.2.14) - 2025-02-14 ### Other - Regenerate target info ([#1398](https://github.com/rust-lang/cc-rs/pull/1398)) - Add support for setting `-gdwarf-{version}` based on RUSTFLAGS ([#1395](https://github.com/rust-lang/cc-rs/pull/1395)) - Add support for alternative network stack io-sock on QNX 7.1 aarch64 and x86_64 ([#1312](https://github.com/rust-lang/cc-rs/pull/1312)) ## [1.2.13](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.12...cc-v1.2.13) - 2025-02-08 ### Other - Fix cross-compiling for Apple platforms ([#1389](https://github.com/rust-lang/cc-rs/pull/1389)) ## [1.2.12](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.11...cc-v1.2.12) - 2025-02-04 ### Other - Split impl Build ([#1382](https://github.com/rust-lang/cc-rs/pull/1382)) - Don't specify both `-target` and `-mtargetos=` on Apple targets ([#1384](https://github.com/rust-lang/cc-rs/pull/1384)) ## [1.2.11](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.10...cc-v1.2.11) - 2025-01-31 ### Other - Fix more flag inheritance ([#1380](https://github.com/rust-lang/cc-rs/pull/1380)) - Include wrapper args. in `stdout` family heuristics to restore classifying `clang --driver-mode=cl` as `Msvc { clang_cl: true }` ([#1378](https://github.com/rust-lang/cc-rs/pull/1378)) - Constrain `-Clto` and `-Cembed-bitcode` flag inheritance to be `clang`-only ([#1379](https://github.com/rust-lang/cc-rs/pull/1379)) - Pass deployment target with `-m*-version-min=` ([#1339](https://github.com/rust-lang/cc-rs/pull/1339)) - Regenerate target info ([#1376](https://github.com/rust-lang/cc-rs/pull/1376)) ## [1.2.10](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.9...cc-v1.2.10) - 2025-01-17 ### Other - Fix CC_FORCE_DISABLE=0 evaluating to true ([#1371](https://github.com/rust-lang/cc-rs/pull/1371)) - Regenerate target info ([#1369](https://github.com/rust-lang/cc-rs/pull/1369)) - Make hidden lifetimes explicit. ([#1366](https://github.com/rust-lang/cc-rs/pull/1366)) ## [1.2.9](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.8...cc-v1.2.9) - 2025-01-12 ### Other - Don't pass inherited PGO flags to GNU compilers (#1363) - Adjusted zig cc judgment and avoided zigbuild errors([#1360](https://github.com/rust-lang/cc-rs/pull/1360)) ([#1361](https://github.com/rust-lang/cc-rs/pull/1361)) - Fix compilation on macOS using clang and fix compilation using zig-cc ([#1364](https://github.com/rust-lang/cc-rs/pull/1364)) ## [1.2.8](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.7...cc-v1.2.8) - 2025-01-11 ### Other - Add `is_like_clang_cl()` getter (#1357) - Fix clippy error in lib.rs ([#1356](https://github.com/rust-lang/cc-rs/pull/1356)) - Regenerate target info ([#1352](https://github.com/rust-lang/cc-rs/pull/1352)) - Fix compiler family detection issue with clang-cl on macOS ([#1328](https://github.com/rust-lang/cc-rs/pull/1328)) - Update `windows-bindgen` dependency ([#1347](https://github.com/rust-lang/cc-rs/pull/1347)) - Fix clippy warnings ([#1346](https://github.com/rust-lang/cc-rs/pull/1346)) ## [1.2.7](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.6...cc-v1.2.7) - 2025-01-03 ### Other - Regenerate target info ([#1342](https://github.com/rust-lang/cc-rs/pull/1342)) - Document new supported architecture names in windows::find - Make is_flag_supported_inner take an &Tool ([#1337](https://github.com/rust-lang/cc-rs/pull/1337)) - Fix is_flag_supported on msvc ([#1336](https://github.com/rust-lang/cc-rs/pull/1336)) - Allow using Visual Studio target names in `find_tool` ([#1335](https://github.com/rust-lang/cc-rs/pull/1335)) ## [1.2.6](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.5...cc-v1.2.6) - 2024-12-27 ### Other - Don't inherit the `/Oy` flag for 64-bit targets ([#1330](https://github.com/rust-lang/cc-rs/pull/1330)) ## [1.2.5](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.4...cc-v1.2.5) - 2024-12-19 ### Other - Check linking when testing if compiler flags are supported ([#1322](https://github.com/rust-lang/cc-rs/pull/1322)) ## [1.2.4](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.3...cc-v1.2.4) - 2024-12-13 ### Other - Add support for C/C++ compiler for Neutrino QNX: `qcc` ([#1319](https://github.com/rust-lang/cc-rs/pull/1319)) - use -maix64 instead of -m64 ([#1307](https://github.com/rust-lang/cc-rs/pull/1307)) ## [1.2.3](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.2...cc-v1.2.3) - 2024-12-06 ### Other - Improve detection of environment when compiling from msbuild or msvc ([#1310](https://github.com/rust-lang/cc-rs/pull/1310)) - Better error message when failing on unknown targets ([#1313](https://github.com/rust-lang/cc-rs/pull/1313)) - Optimize RustcCodegenFlags ([#1305](https://github.com/rust-lang/cc-rs/pull/1305)) ## [1.2.2](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.1...cc-v1.2.2) - 2024-11-29 ### Other - Inherit flags from rustc ([#1279](https://github.com/rust-lang/cc-rs/pull/1279)) - Add support for using sccache wrapper with cuda/nvcc ([#1304](https://github.com/rust-lang/cc-rs/pull/1304)) - Fix msvc stdout not shown on error ([#1303](https://github.com/rust-lang/cc-rs/pull/1303)) - Regenerate target info ([#1301](https://github.com/rust-lang/cc-rs/pull/1301)) - Fix compilation of C++ code for armv7-unknown-linux-gnueabihf ([#1298](https://github.com/rust-lang/cc-rs/pull/1298)) - Fetch target info from Cargo even if `Build::target` is manually set ([#1299](https://github.com/rust-lang/cc-rs/pull/1299)) - Fix two files with different extensions having the same object name ([#1295](https://github.com/rust-lang/cc-rs/pull/1295)) - Allow disabling cc's ability to compile via env var CC_FORCE_DISABLE ([#1292](https://github.com/rust-lang/cc-rs/pull/1292)) - Regenerate target info ([#1293](https://github.com/rust-lang/cc-rs/pull/1293)) ## [1.2.1](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.0...cc-v1.2.1) - 2024-11-14 ### Other - When invoking `cl -?`, set stdin to null ([#1288](https://github.com/rust-lang/cc-rs/pull/1288)) ## [1.2.0](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.37...cc-v1.2.0) - 2024-11-11 ### Added - add i686-pc-windows-gnullvm prefix detection ([#1283](https://github.com/rust-lang/cc-rs/pull/1283)) ### Other - Allow only specifying the architecture ([#1285](https://github.com/rust-lang/cc-rs/pull/1285)) - Fix WASM vs. WASI options ([#1284](https://github.com/rust-lang/cc-rs/pull/1284)) ## [1.1.37](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.36...cc-v1.1.37) - 2024-11-08 ### Other - Use relative directory for obj files hash ([#1270](https://github.com/rust-lang/cc-rs/pull/1270)) - Regenerate target info ([#1280](https://github.com/rust-lang/cc-rs/pull/1280)) ## [1.1.36](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.35...cc-v1.1.36) - 2024-11-05 ### Other - Fix CUDA build with clang++. ([#1273](https://github.com/rust-lang/cc-rs/pull/1273)) ## [1.1.35](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.34...cc-v1.1.35) - 2024-11-04 ### Other - Remove support for FRC ([#1268](https://github.com/rust-lang/cc-rs/pull/1268)) - Do not add -fPIC by default on UEFI targets ([#1263](https://github.com/rust-lang/cc-rs/pull/1263)) - Use -windows-gnu for all UEFI targets ([#1264](https://github.com/rust-lang/cc-rs/pull/1264)) ## [1.1.34](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.33...cc-v1.1.34) - 2024-11-02 ### Other - Remove redundant flags ([#1256](https://github.com/rust-lang/cc-rs/pull/1256)) ## [1.1.33](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.32...cc-v1.1.33) - 2024-11-02 ### Other - Reduce size of `cc::Build` and size of generated targets ([#1257](https://github.com/rust-lang/cc-rs/pull/1257)) ## [1.1.32](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.31...cc-v1.1.32) - 2024-11-02 ### Other - Use `rustc`'s knowledge of LLVM/Clang target triples ([#1252](https://github.com/rust-lang/cc-rs/pull/1252)) - Use Cargo's target information when possible ([#1225](https://github.com/rust-lang/cc-rs/pull/1225)) ## [1.1.31](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.30...cc-v1.1.31) - 2024-10-19 ### Other - Add comment explaining why cc does not rebuild on env PATH change ([#1247](https://github.com/rust-lang/cc-rs/pull/1247)) ## [1.1.30](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.29...cc-v1.1.30) - 2024-10-11 ### Other - Don't pass -fPIC by default on wasm ([#1245](https://github.com/rust-lang/cc-rs/pull/1245)) ## [1.1.29](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.28...cc-v1.1.29) - 2024-10-11 ### Other - Regenerate target info ([#1243](https://github.com/rust-lang/cc-rs/pull/1243)) ## [1.1.28](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.27...cc-v1.1.28) - 2024-10-06 ### Other - Environment variables: For one accepting boolean, treat "0", "false" and empty env as false ([#1238](https://github.com/rust-lang/cc-rs/pull/1238)) ## [1.1.27](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.26...cc-v1.1.27) - 2024-10-06 ### Other - Revert "Use debug version of MSVC runtime library on debug ([#1231](https://github.com/rust-lang/cc-rs/pull/1231))" ([#1237](https://github.com/rust-lang/cc-rs/pull/1237)) - Disable `CC_ENABLE_DEBUG_OUTPUT` if it is set to "0" ([#1234](https://github.com/rust-lang/cc-rs/pull/1234)) ## [1.1.26](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.25...cc-v1.1.26) - 2024-10-06 ### Other - Use debug version of MSVC runtime library on debug ([#1231](https://github.com/rust-lang/cc-rs/pull/1231)) ## [1.1.25](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.24...cc-v1.1.25) - 2024-10-05 ### Other - Remove incorrect "lib" prefixes in CXXSTDLIB doc comments ([#1228](https://github.com/rust-lang/cc-rs/pull/1228)) ## [1.1.24](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.23...cc-v1.1.24) - 2024-10-01 ### Other - Fix wasm32-wasip1-threads: shared-memory disallowed due to not compiled with 'atomics' or 'bulk-memory' features ([#1221](https://github.com/rust-lang/cc-rs/pull/1221)) - Reduce the need for the host target triple ([#1224](https://github.com/rust-lang/cc-rs/pull/1224)) - Add auto cancellation for CI jobs ([#1222](https://github.com/rust-lang/cc-rs/pull/1222)) ## [1.1.23](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.22...cc-v1.1.23) - 2024-09-30 ### Other - Update doc for detecting changes/upgrades of compilers ([#1218](https://github.com/rust-lang/cc-rs/pull/1218)) ## [1.1.22](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.21...cc-v1.1.22) - 2024-09-27 ### Other - Don't rerun if PATH changes ([#1215](https://github.com/rust-lang/cc-rs/pull/1215)) ## [1.1.21](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.20...cc-v1.1.21) - 2024-09-18 ### Other - disable pic for targets that end in `-none` ([#1212](https://github.com/rust-lang/cc-rs/pull/1212)) ## [1.1.20](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.19...cc-v1.1.20) - 2024-09-17 ### Other - Add buildcache as known Rust and C/C++ compiler wrapper ([#1209](https://github.com/rust-lang/cc-rs/pull/1209)) ## [1.1.19](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.18...cc-v1.1.19) - 2024-09-15 ### Other - Add support arm64e-apple-darwin ([#1207](https://github.com/rust-lang/cc-rs/pull/1207)) ## [1.1.18](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.17...cc-v1.1.18) - 2024-09-07 ### Other - Fixed unsoundness in `StderrForwarder::forward_available` ([#1203](https://github.com/rust-lang/cc-rs/pull/1203)) ## [1.1.17](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.16...cc-v1.1.17) - 2024-09-06 ### Fixed - fix finding toolchains when invoked by msbuild ([#1201](https://github.com/rust-lang/cc-rs/pull/1201)) ## [1.1.16](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.15...cc-v1.1.16) - 2024-09-04 ### Other - Treat VxWorks wr-cc as a Gnu compiler ([#1198](https://github.com/rust-lang/cc-rs/pull/1198)) ## [1.1.15](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.14...cc-v1.1.15) - 2024-08-26 ### Other - Add -mfloat-abi=hard as a default argument when using any arm/thumb-none-eabihf target ([#1194](https://github.com/rust-lang/cc-rs/pull/1194)) ## [1.1.14](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.13...cc-v1.1.14) - 2024-08-23 ### Other - allow finding tools from path if VisualStudioDir is set ## [1.1.13](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.12...cc-v1.1.13) - 2024-08-16 ### Other - Fix detect family: should detect emscripten as clang, closes [#1185](https://github.com/rust-lang/cc-rs/pull/1185) ([#1186](https://github.com/rust-lang/cc-rs/pull/1186)) ## [1.1.12](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.11...cc-v1.1.12) - 2024-08-15 ### Other - improve docs ([#1183](https://github.com/rust-lang/cc-rs/pull/1183)) ## [1.1.11](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.10...cc-v1.1.11) - 2024-08-14 ### Other - Add support for parsing shell encoded `*FLAGS` ([#1181](https://github.com/rust-lang/cc-rs/pull/1181)) - Replace vector of tuples with BTreeMap which already is sorted and free of duplicates ([#1177](https://github.com/rust-lang/cc-rs/pull/1177)) ## [1.1.10](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.9...cc-v1.1.10) - 2024-08-11 ### Other - Remap Windows targets triples to their LLVM counterparts ([#1176](https://github.com/rust-lang/cc-rs/pull/1176)) ## [1.1.9](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.8...cc-v1.1.9) - 2024-08-11 ### Other - Add custom CC wrapper to the wrapper whitelist ([#1175](https://github.com/rust-lang/cc-rs/pull/1175)) ## [1.1.8](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.7...cc-v1.1.8) - 2024-08-06 ### Other - Fix broken link in docs.rs ([#1173](https://github.com/rust-lang/cc-rs/pull/1173)) ## [1.1.7](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.6...cc-v1.1.7) - 2024-07-29 ### Other - add `.objects` ([#1166](https://github.com/rust-lang/cc-rs/pull/1166)) ## [1.1.6](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.5...cc-v1.1.6) - 2024-07-19 ### Other - Clippy fixes ([#1163](https://github.com/rust-lang/cc-rs/pull/1163)) ## [1.1.5](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.4...cc-v1.1.5) - 2024-07-15 ### Other - Fix cyclic compilation: Use vendored once_cell ([#1154](https://github.com/rust-lang/cc-rs/pull/1154)) ## [1.1.4](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.3...cc-v1.1.4) - 2024-07-14 ### Other - Support compiling on wasm targets (Supersede [#1068](https://github.com/rust-lang/cc-rs/pull/1068)) ([#1160](https://github.com/rust-lang/cc-rs/pull/1160)) ## [1.1.3](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.2...cc-v1.1.3) - 2024-07-14 ### Other - Reduce msrv to 1.63 ([#1158](https://github.com/rust-lang/cc-rs/pull/1158)) - Revert "Use raw-dylib for windows-sys ([#1137](https://github.com/rust-lang/cc-rs/pull/1137))" ([#1157](https://github.com/rust-lang/cc-rs/pull/1157)) - Fix typos ([#1152](https://github.com/rust-lang/cc-rs/pull/1152)) - Fix `doc_lazy_continuation` lints ([#1153](https://github.com/rust-lang/cc-rs/pull/1153)) ## [1.1.2](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.1...cc-v1.1.2) - 2024-07-12 ### Other - Add empty `jobserver` feature. ([#1150](https://github.com/rust-lang/cc-rs/pull/1150)) ## [1.1.1](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.0...cc-v1.1.1) - 2024-07-12 ### Other - Fix is_flag_supported not respecting emit_rerun_if_env_changed ([#1147](https://github.com/rust-lang/cc-rs/pull/1147)) ([#1148](https://github.com/rust-lang/cc-rs/pull/1148)) ## [1.1.0](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.106...cc-v1.1.0) - 2024-07-08 ### Added - add cargo_output to eliminate last vestiges of stdout pollution ([#1141](https://github.com/rust-lang/cc-rs/pull/1141)) ## [1.0.106](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.105...cc-v1.0.106) - 2024-07-08 ### Other - Drop support for Visual Studio 12 (2013) ([#1046](https://github.com/rust-lang/cc-rs/pull/1046)) - Use raw-dylib for windows-sys ([#1137](https://github.com/rust-lang/cc-rs/pull/1137)) - Bump msrv to 1.67 ([#1143](https://github.com/rust-lang/cc-rs/pull/1143)) - Bump msrv to 1.65 ([#1140](https://github.com/rust-lang/cc-rs/pull/1140)) - Fix clippy warnings ([#1138](https://github.com/rust-lang/cc-rs/pull/1138)) ## [1.0.105](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.104...cc-v1.0.105) - 2024-07-07 ### Other - Regenerate windows sys bindings ([#1132](https://github.com/rust-lang/cc-rs/pull/1132)) - Fix generate-windows-sys-bindings ([#1133](https://github.com/rust-lang/cc-rs/pull/1133)) - Fix gen-windows-sys-binding ([#1130](https://github.com/rust-lang/cc-rs/pull/1130)) - Fix gen-windows-sys-binding ([#1127](https://github.com/rust-lang/cc-rs/pull/1127)) - Update windows-bindgen requirement from 0.57 to 0.58 ([#1123](https://github.com/rust-lang/cc-rs/pull/1123)) ## [1.0.104](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.103...cc-v1.0.104) - 2024-07-01 ### Other - Fixed link break about compile-time-requirements ([#1118](https://github.com/rust-lang/cc-rs/pull/1118)) ## [1.0.103](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.102...cc-v1.0.103) - 2024-06-30 ### Other - Fix compilation for wasm: env WASI_SYSROOT should be optional ([#1114](https://github.com/rust-lang/cc-rs/pull/1114)) ## [1.0.102](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.101...cc-v1.0.102) - 2024-06-29 ### Other - Fix invalid wasi targets compatibility ([#1105](https://github.com/rust-lang/cc-rs/pull/1105)) - Speedup regenerate-target-info and regenerate-windows-sys ([#1110](https://github.com/rust-lang/cc-rs/pull/1110)) ## [1.0.101](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.100...cc-v1.0.101) - 2024-06-25 ### Other - Use `Build::getenv` instead of `env::var*` in anywhere that makes sense ([#1103](https://github.com/rust-lang/cc-rs/pull/1103)) ## [1.0.100](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.99...cc-v1.0.100) - 2024-06-23 ### Other - Update publish.yml to use release-plz ([#1101](https://github.com/rust-lang/cc-rs/pull/1101)) - Accept `OsStr` instead of `str` for flags ([#1100](https://github.com/rust-lang/cc-rs/pull/1100)) - Use `dep:` syntax to avoid implicit features. ([#1099](https://github.com/rust-lang/cc-rs/pull/1099)) - Minor clippy fixes. ([#1098](https://github.com/rust-lang/cc-rs/pull/1098)) - Fix WASI compilation for C++ ([#1083](https://github.com/rust-lang/cc-rs/pull/1083)) - Regenerate windows sys bindings ([#1096](https://github.com/rust-lang/cc-rs/pull/1096)) - Rename regenerate-windows-sys to regenerate-windows-sys.yml ([#1095](https://github.com/rust-lang/cc-rs/pull/1095)) - Create regenerate-windows-sys.yml ([#1094](https://github.com/rust-lang/cc-rs/pull/1094)) - Update windows-bindgen requirement from 0.56 to 0.57 ([#1091](https://github.com/rust-lang/cc-rs/pull/1091)) - Eagerly close tempfile to fix [#1082](https://github.com/rust-lang/cc-rs/pull/1082) ([#1087](https://github.com/rust-lang/cc-rs/pull/1087)) - Output msvc.exe in the output directory ([#1090](https://github.com/rust-lang/cc-rs/pull/1090)) - Fix clippy warnings on Windows ([#1088](https://github.com/rust-lang/cc-rs/pull/1088)) - Don't try to free DLL on drop ([#1089](https://github.com/rust-lang/cc-rs/pull/1089)) - Fix panic safety issue in StderrForwarder ([#1079](https://github.com/rust-lang/cc-rs/pull/1079)) cc/src/0000775000175000017500000000000015105742312011560 5ustar bdrungbdrungcc/src/lib.rs0000644000175000017500000052176215105742312012707 0ustar bdrungbdrung//! A library for [Cargo build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html) //! to compile a set of C/C++/assembly/CUDA files into a static archive for Cargo //! to link into the crate being built. This crate does not compile code itself; //! it calls out to the default compiler for the platform. This crate will //! automatically detect situations such as cross compilation and //! [various environment variables](#external-configuration-via-environment-variables) and will build code appropriately. //! //! # Example //! //! First, you'll want to both add a build script for your crate (`build.rs`) and //! also add this crate to your `Cargo.toml` via: //! //! ```toml //! [build-dependencies] //! cc = "1.0" //! ``` //! //! Next up, you'll want to write a build script like so: //! //! ```rust,no_run //! // build.rs //! cc::Build::new() //! .file("foo.c") //! .file("bar.c") //! .compile("foo"); //! ``` //! //! And that's it! Running `cargo build` should take care of the rest and your Rust //! application will now have the C files `foo.c` and `bar.c` compiled into a file //! named `libfoo.a`. If the C files contain //! //! ```c //! void foo_function(void) { ... } //! ``` //! //! and //! //! ```c //! int32_t bar_function(int32_t x) { ... } //! ``` //! //! you can call them from Rust by declaring them in //! your Rust code like so: //! //! ```rust,no_run //! extern "C" { //! fn foo_function(); //! fn bar_function(x: i32) -> i32; //! } //! //! pub fn call() { //! unsafe { //! foo_function(); //! bar_function(42); //! } //! } //! //! fn main() { //! call(); //! } //! ``` //! //! See [the Rustonomicon](https://doc.rust-lang.org/nomicon/ffi.html) for more details. //! //! # External configuration via environment variables //! //! To control the programs and flags used for building, the builder can set a //! number of different environment variables. //! //! * `CFLAGS` - a series of space separated flags passed to compilers. Note that //! individual flags cannot currently contain spaces, so doing //! something like: `-L=foo\ bar` is not possible. //! * `CC` - the actual C compiler used. Note that this is used as an exact //! executable name, so (for example) no extra flags can be passed inside //! this variable, and the builder must ensure that there aren't any //! trailing spaces. This compiler must understand the `-c` flag. For //! certain `TARGET`s, it also is assumed to know about other flags (most //! common is `-fPIC`). //! * `AR` - the `ar` (archiver) executable to use to build the static library. //! * `CRATE_CC_NO_DEFAULTS` - the default compiler flags may cause conflicts in //! some cross compiling scenarios. Setting this variable //! will disable the generation of default compiler //! flags. //! * `CC_ENABLE_DEBUG_OUTPUT` - if set, compiler command invocations and exit codes will //! be logged to stdout. This is useful for debugging build script issues, but can be //! overly verbose for normal use. //! * `CC_SHELL_ESCAPED_FLAGS` - if set, `*FLAGS` will be parsed as if they were shell //! arguments (similar to `make` and `cmake`) rather than splitting them on each space. //! For example, with `CFLAGS='a "b c"'`, the compiler will be invoked with 2 arguments - //! `a` and `b c` - rather than 3: `a`, `"b` and `c"`. //! * `CXX...` - see [C++ Support](#c-support). //! * `CC_FORCE_DISABLE` - If set, `cc` will never run any [`Command`]s, and methods that //! would return an [`Error`]. This is intended for use by third-party build systems //! which want to be absolutely sure that they are in control of building all //! dependencies. Note that operations that return [`Tool`]s such as //! [`Build::get_compiler`] may produce less accurate results as in some cases `cc` runs //! commands in order to locate compilers. Additionally, this does nothing to prevent //! users from running [`Tool::to_command`] and executing the [`Command`] themselves.//! //! //! Furthermore, projects using this crate may specify custom environment variables //! to be inspected, for example via the `Build::try_flags_from_environment` //! function. Consult the project’s own documentation or its use of the `cc` crate //! for any additional variables it may use. //! //! Each of these variables can also be supplied with certain prefixes and suffixes, //! in the following prioritized order: //! //! 1. `_` - for example, `CC_x86_64-unknown-linux-gnu` //! 2. `_` - for example, `CC_x86_64_unknown_linux_gnu` //! 3. `_` - for example, `HOST_CC` or `TARGET_CFLAGS` //! 4. `` - a plain `CC`, `AR` as above. //! //! If none of these variables exist, cc-rs uses built-in defaults. //! //! In addition to the above optional environment variables, `cc-rs` has some //! functions with hard requirements on some variables supplied by [cargo's //! build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`, //! and `HOST` variables. //! //! [cargo]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#inputs-to-the-build-script //! //! # Optional features //! //! ## Parallel //! //! Currently cc-rs supports parallel compilation (think `make -jN`) but this //! feature is turned off by default. To enable cc-rs to compile C/C++ in parallel, //! you can change your dependency to: //! //! ```toml //! [build-dependencies] //! cc = { version = "1.0", features = ["parallel"] } //! ``` //! //! By default cc-rs will limit parallelism to `$NUM_JOBS`, or if not present it //! will limit it to the number of cpus on the machine. If you are using cargo, //! use `-jN` option of `build`, `test` and `run` commands as `$NUM_JOBS` //! is supplied by cargo. //! //! # Compile-time Requirements //! //! To work properly this crate needs access to a C compiler when the build script //! is being run. This crate does not ship a C compiler with it. The compiler //! required varies per platform, but there are three broad categories: //! //! * Unix platforms require `cc` to be the C compiler. This can be found by //! installing cc/clang on Linux distributions and Xcode on macOS, for example. //! * Windows platforms targeting MSVC (e.g. your target name ends in `-msvc`) //! require Visual Studio to be installed. `cc-rs` attempts to locate it, and //! if it fails, `cl.exe` is expected to be available in `PATH`. This can be //! set up by running the appropriate developer tools shell. //! * Windows platforms targeting MinGW (e.g. your target name ends in `-gnu`) //! require `cc` to be available in `PATH`. We recommend the //! [MinGW-w64](https://www.mingw-w64.org/) distribution. //! You may also acquire it via //! [MSYS2](https://www.msys2.org/), as explained [here][msys2-help]. Make sure //! to install the appropriate architecture corresponding to your installation of //! rustc. GCC from older [MinGW](http://www.mingw.org/) project is compatible //! only with 32-bit rust compiler. //! //! [msys2-help]: https://github.com/rust-lang/rust/blob/master/INSTALL.md#building-on-windows //! //! # C++ support //! //! `cc-rs` supports C++ libraries compilation by using the `cpp` method on //! `Build`: //! //! ```rust,no_run //! cc::Build::new() //! .cpp(true) // Switch to C++ library compilation. //! .file("foo.cpp") //! .compile("foo"); //! ``` //! //! For C++ libraries, the `CXX` and `CXXFLAGS` environment variables are used instead of `CC` and `CFLAGS`. //! //! The C++ standard library may be linked to the crate target. By default it's `libc++` for macOS, FreeBSD, and OpenBSD, `libc++_shared` for Android, nothing for MSVC, and `libstdc++` for anything else. It can be changed in one of two ways: //! //! 1. by using the `cpp_link_stdlib` method on `Build`: //! ```rust,no_run //! cc::Build::new() //! .cpp(true) //! .file("foo.cpp") //! .cpp_link_stdlib("stdc++") // use libstdc++ //! .compile("foo"); //! ``` //! 2. by setting the `CXXSTDLIB` environment variable. //! //! In particular, for Android you may want to [use `c++_static` if you have at most one shared library](https://developer.android.com/ndk/guides/cpp-support). //! //! Remember that C++ does name mangling so `extern "C"` might be required to enable Rust linker to find your functions. //! //! # CUDA C++ support //! //! `cc-rs` also supports compiling CUDA C++ libraries by using the `cuda` method //! on `Build`: //! //! ```rust,no_run //! cc::Build::new() //! // Switch to CUDA C++ library compilation using NVCC. //! .cuda(true) //! .cudart("static") //! // Generate code for Maxwell (GTX 970, 980, 980 Ti, Titan X). //! .flag("-gencode").flag("arch=compute_52,code=sm_52") //! // Generate code for Maxwell (Jetson TX1). //! .flag("-gencode").flag("arch=compute_53,code=sm_53") //! // Generate code for Pascal (GTX 1070, 1080, 1080 Ti, Titan Xp). //! .flag("-gencode").flag("arch=compute_61,code=sm_61") //! // Generate code for Pascal (Tesla P100). //! .flag("-gencode").flag("arch=compute_60,code=sm_60") //! // Generate code for Pascal (Jetson TX2). //! .flag("-gencode").flag("arch=compute_62,code=sm_62") //! // Generate code in parallel //! .flag("-t0") //! .file("bar.cu") //! .compile("bar"); //! ``` #![doc(html_root_url = "https://docs.rs/cc/1.0")] #![deny(warnings)] #![deny(missing_docs)] #![deny(clippy::disallowed_methods)] #![warn(clippy::doc_markdown)] use std::borrow::Cow; use std::collections::HashMap; use std::env; use std::ffi::{OsStr, OsString}; use std::fmt::{self, Display}; use std::fs; use std::io::{self, Write}; use std::path::{Component, Path, PathBuf}; #[cfg(feature = "parallel")] use std::process::Child; use std::process::{Command, Stdio}; use std::sync::{ atomic::{AtomicU8, Ordering::Relaxed}, Arc, RwLock, }; use shlex::Shlex; #[cfg(feature = "parallel")] mod parallel; mod target; mod windows; use self::target::TargetInfo; // Regardless of whether this should be in this crate's public API, // it has been since 2015, so don't break it. pub use windows::find_tools as windows_registry; mod command_helpers; use command_helpers::*; mod tool; pub use tool::Tool; use tool::{CompilerFamilyLookupCache, ToolFamily}; mod tempfile; mod utilities; use utilities::*; mod flags; use flags::*; #[derive(Debug, Eq, PartialEq, Hash)] struct CompilerFlag { compiler: Box, flag: Box, } type Env = Option>; #[derive(Debug, Default)] struct BuildCache { env_cache: RwLock, Env>>, apple_sdk_root_cache: RwLock, Arc>>, apple_versions_cache: RwLock, Arc>>, cached_compiler_family: RwLock, known_flag_support_status_cache: RwLock>, target_info_parser: target::TargetInfoParser, } /// A builder for compilation of a native library. /// /// A `Build` is the main type of the `cc` crate and is used to control all the /// various configuration options and such of a compile. You'll find more /// documentation on each method itself. #[derive(Clone, Debug)] pub struct Build { include_directories: Vec>, definitions: Vec<(Arc, Option>)>, objects: Vec>, flags: Vec>, flags_supported: Vec>, ar_flags: Vec>, asm_flags: Vec>, no_default_flags: bool, files: Vec>, cpp: bool, cpp_link_stdlib: Option>>, cpp_set_stdlib: Option>, cuda: bool, cudart: Option>, ccbin: bool, std: Option>, target: Option>, /// The host compiler. /// /// Try to not access this directly, and instead prefer `cfg!(...)`. host: Option>, out_dir: Option>, opt_level: Option>, debug: Option, force_frame_pointer: Option, env: Vec<(Arc, Arc)>, compiler: Option>, archiver: Option>, ranlib: Option>, cargo_output: CargoOutput, link_lib_modifiers: Vec>, pic: Option, use_plt: Option, static_crt: Option, shared_flag: Option, static_flag: Option, warnings_into_errors: bool, warnings: Option, extra_warnings: Option, emit_rerun_if_env_changed: bool, shell_escaped_flags: Option, build_cache: Arc, inherit_rustflags: bool, } /// Represents the types of errors that may occur while using cc-rs. #[derive(Clone, Debug)] enum ErrorKind { /// Error occurred while performing I/O. IOError, /// Environment variable not found, with the var in question as extra info. EnvVarNotFound, /// Error occurred while using external tools (ie: invocation of compiler). ToolExecError, /// Error occurred due to missing external tools. ToolNotFound, /// One of the function arguments failed validation. InvalidArgument, /// No known macro is defined for the compiler when discovering tool family. ToolFamilyMacroNotFound, /// Invalid target. InvalidTarget, /// Unknown target. UnknownTarget, /// Invalid rustc flag. InvalidFlag, #[cfg(feature = "parallel")] /// jobserver helpthread failure JobserverHelpThreadError, /// `cc` has been disabled by an environment variable. Disabled, } /// Represents an internal error that occurred, with an explanation. #[derive(Clone, Debug)] pub struct Error { /// Describes the kind of error that occurred. kind: ErrorKind, /// More explanation of error that occurred. message: Cow<'static, str>, } impl Error { fn new(kind: ErrorKind, message: impl Into>) -> Error { Error { kind, message: message.into(), } } } impl From for Error { fn from(e: io::Error) -> Error { Error::new(ErrorKind::IOError, format!("{}", e)) } } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", self.kind, self.message) } } impl std::error::Error for Error {} /// Represents an object. /// /// This is a source file -> object file pair. #[derive(Clone, Debug)] struct Object { src: PathBuf, dst: PathBuf, } impl Object { /// Create a new source file -> object file pair. fn new(src: PathBuf, dst: PathBuf) -> Object { Object { src, dst } } } /// Configure the builder. impl Build { /// Construct a new instance of a blank set of configuration. /// /// This builder is finished with the [`compile`] function. /// /// [`compile`]: struct.Build.html#method.compile pub fn new() -> Build { Build { include_directories: Vec::new(), definitions: Vec::new(), objects: Vec::new(), flags: Vec::new(), flags_supported: Vec::new(), ar_flags: Vec::new(), asm_flags: Vec::new(), no_default_flags: false, files: Vec::new(), shared_flag: None, static_flag: None, cpp: false, cpp_link_stdlib: None, cpp_set_stdlib: None, cuda: false, cudart: None, ccbin: true, std: None, target: None, host: None, out_dir: None, opt_level: None, debug: None, force_frame_pointer: None, env: Vec::new(), compiler: None, archiver: None, ranlib: None, cargo_output: CargoOutput::new(), link_lib_modifiers: Vec::new(), pic: None, use_plt: None, static_crt: None, warnings: None, extra_warnings: None, warnings_into_errors: false, emit_rerun_if_env_changed: true, shell_escaped_flags: None, build_cache: Arc::default(), inherit_rustflags: true, } } /// Add a directory to the `-I` or include path for headers /// /// # Example /// /// ```no_run /// use std::path::Path; /// /// let library_path = Path::new("/path/to/library"); /// /// cc::Build::new() /// .file("src/foo.c") /// .include(library_path) /// .include("src") /// .compile("foo"); /// ``` pub fn include>(&mut self, dir: P) -> &mut Build { self.include_directories.push(dir.as_ref().into()); self } /// Add multiple directories to the `-I` include path. /// /// # Example /// /// ```no_run /// # use std::path::Path; /// # let condition = true; /// # /// let mut extra_dir = None; /// if condition { /// extra_dir = Some(Path::new("/path/to")); /// } /// /// cc::Build::new() /// .file("src/foo.c") /// .includes(extra_dir) /// .compile("foo"); /// ``` pub fn includes

(&mut self, dirs: P) -> &mut Build where P: IntoIterator, P::Item: AsRef, { for dir in dirs { self.include(dir); } self } /// Specify a `-D` variable with an optional value. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .define("FOO", "BAR") /// .define("BAZ", None) /// .compile("foo"); /// ``` pub fn define<'a, V: Into>>(&mut self, var: &str, val: V) -> &mut Build { self.definitions .push((var.into(), val.into().map(Into::into))); self } /// Add an arbitrary object file to link in pub fn object>(&mut self, obj: P) -> &mut Build { self.objects.push(obj.as_ref().into()); self } /// Add arbitrary object files to link in pub fn objects

(&mut self, objs: P) -> &mut Build where P: IntoIterator, P::Item: AsRef, { for obj in objs { self.object(obj); } self } /// Add an arbitrary flag to the invocation of the compiler /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .flag("-ffunction-sections") /// .compile("foo"); /// ``` pub fn flag(&mut self, flag: impl AsRef) -> &mut Build { self.flags.push(flag.as_ref().into()); self } /// Add multiple flags to the invocation of the compiler. /// This is equivalent to calling [`flag`](Self::flag) for each item in the iterator. /// /// # Example /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .flags(["-Wall", "-Wextra"]) /// .compile("foo"); /// ``` pub fn flags(&mut self, flags: Iter) -> &mut Build where Iter: IntoIterator, Iter::Item: AsRef, { for flag in flags { self.flag(flag); } self } /// Removes a compiler flag that was added by [`Build::flag`]. /// /// Will not remove flags added by other means (default flags, /// flags from env, and so on). /// /// # Example /// ``` /// cc::Build::new() /// .file("src/foo.c") /// .flag("unwanted_flag") /// .remove_flag("unwanted_flag"); /// ``` pub fn remove_flag(&mut self, flag: &str) -> &mut Build { self.flags.retain(|other_flag| &**other_flag != flag); self } /// Add a flag to the invocation of the ar /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .file("src/bar.c") /// .ar_flag("/NODEFAULTLIB:libc.dll") /// .compile("foo"); /// ``` pub fn ar_flag(&mut self, flag: impl AsRef) -> &mut Build { self.ar_flags.push(flag.as_ref().into()); self } /// Add a flag that will only be used with assembly files. /// /// The flag will be applied to input files with either a `.s` or /// `.asm` extension (case insensitive). /// /// # Example /// /// ```no_run /// cc::Build::new() /// .asm_flag("-Wa,-defsym,abc=1") /// .file("src/foo.S") // The asm flag will be applied here /// .file("src/bar.c") // The asm flag will not be applied here /// .compile("foo"); /// ``` pub fn asm_flag(&mut self, flag: impl AsRef) -> &mut Build { self.asm_flags.push(flag.as_ref().into()); self } /// Add an arbitrary flag to the invocation of the compiler if it supports it /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .flag_if_supported("-Wlogical-op") // only supported by GCC /// .flag_if_supported("-Wunreachable-code") // only supported by clang /// .compile("foo"); /// ``` pub fn flag_if_supported(&mut self, flag: impl AsRef) -> &mut Build { self.flags_supported.push(flag.as_ref().into()); self } /// Add flags from the specified environment variable. /// /// Normally the `cc` crate will consult with the standard set of environment /// variables (such as `CFLAGS` and `CXXFLAGS`) to construct the compiler invocation. Use of /// this method provides additional levers for the end user to use when configuring the build /// process. /// /// Just like the standard variables, this method will search for an environment variable with /// appropriate target prefixes, when appropriate. /// /// # Examples /// /// This method is particularly beneficial in introducing the ability to specify crate-specific /// flags. /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .try_flags_from_environment(concat!(env!("CARGO_PKG_NAME"), "_CFLAGS")) /// .expect("the environment variable must be specified and UTF-8") /// .compile("foo"); /// ``` /// pub fn try_flags_from_environment(&mut self, environ_key: &str) -> Result<&mut Build, Error> { let flags = self.envflags(environ_key)?.ok_or_else(|| { Error::new( ErrorKind::EnvVarNotFound, format!("could not find environment variable {environ_key}"), ) })?; self.flags.extend( flags .into_iter() .map(|flag| Arc::from(OsString::from(flag).as_os_str())), ); Ok(self) } /// Set the `-shared` flag. /// /// When enabled, the compiler will produce a shared object which can /// then be linked with other objects to form an executable. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .compile("libfoo.so"); /// ``` pub fn shared_flag(&mut self, shared_flag: bool) -> &mut Build { self.shared_flag = Some(shared_flag); self } /// Set the `-static` flag. /// /// When enabled on systems that support dynamic linking, this prevents /// linking with the shared libraries. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .static_flag(true) /// .compile("foo"); /// ``` pub fn static_flag(&mut self, static_flag: bool) -> &mut Build { self.static_flag = Some(static_flag); self } /// Disables the generation of default compiler flags. The default compiler /// flags may cause conflicts in some cross compiling scenarios. /// /// Setting the `CRATE_CC_NO_DEFAULTS` environment variable has the same /// effect as setting this to `true`. The presence of the environment /// variable and the value of `no_default_flags` will be OR'd together. pub fn no_default_flags(&mut self, no_default_flags: bool) -> &mut Build { self.no_default_flags = no_default_flags; self } /// Add a file which will be compiled pub fn file>(&mut self, p: P) -> &mut Build { self.files.push(p.as_ref().into()); self } /// Add files which will be compiled pub fn files

(&mut self, p: P) -> &mut Build where P: IntoIterator, P::Item: AsRef, { for file in p.into_iter() { self.file(file); } self } /// Get the files which will be compiled pub fn get_files(&self) -> impl Iterator { self.files.iter().map(AsRef::as_ref) } /// Set C++ support. /// /// The other `cpp_*` options will only become active if this is set to /// `true`. /// /// The name of the C++ standard library to link is decided by: /// 1. If [`cpp_link_stdlib`](Build::cpp_link_stdlib) is set, use its value. /// 2. Else if the `CXXSTDLIB` environment variable is set, use its value. /// 3. Else the default is `c++` for OS X and BSDs, `c++_shared` for Android, /// `None` for MSVC and `stdc++` for anything else. pub fn cpp(&mut self, cpp: bool) -> &mut Build { self.cpp = cpp; self } /// Set CUDA C++ support. /// /// Enabling CUDA will invoke the CUDA compiler, NVCC. While NVCC accepts /// the most common compiler flags, e.g. `-std=c++17`, some project-specific /// flags might have to be prefixed with "-Xcompiler" flag, for example as /// `.flag("-Xcompiler").flag("-fpermissive")`. See the documentation for /// `nvcc`, the CUDA compiler driver, at /// for more information. /// /// If enabled, this also implicitly enables C++ support. pub fn cuda(&mut self, cuda: bool) -> &mut Build { self.cuda = cuda; if cuda { self.cpp = true; self.cudart = Some("static".into()); } self } /// Link CUDA run-time. /// /// This option mimics the `--cudart` NVCC command-line option. Just like /// the original it accepts `{none|shared|static}`, with default being /// `static`. The method has to be invoked after `.cuda(true)`, or not /// at all, if the default is right for the project. pub fn cudart(&mut self, cudart: &str) -> &mut Build { if self.cuda { self.cudart = Some(cudart.into()); } self } /// Set CUDA host compiler. /// /// By default, a `-ccbin` flag will be passed to NVCC to specify the /// underlying host compiler. The value of `-ccbin` is the same as the /// chosen C++ compiler. This is not always desired, because NVCC might /// not support that compiler. In this case, you can remove the `-ccbin` /// flag so that NVCC will choose the host compiler by itself. pub fn ccbin(&mut self, ccbin: bool) -> &mut Build { self.ccbin = ccbin; self } /// Specify the C or C++ language standard version. /// /// These values are common to modern versions of GCC, Clang and MSVC: /// - `c11` for ISO/IEC 9899:2011 /// - `c17` for ISO/IEC 9899:2018 /// - `c++14` for ISO/IEC 14882:2014 /// - `c++17` for ISO/IEC 14882:2017 /// - `c++20` for ISO/IEC 14882:2020 /// /// Other values have less broad support, e.g. MSVC does not support `c++11` /// (`c++14` is the minimum), `c89` (omit the flag instead) or `c99`. /// /// For compiling C++ code, you should also set `.cpp(true)`. /// /// The default is that no standard flag is passed to the compiler, so the /// language version will be the compiler's default. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/modern.cpp") /// .cpp(true) /// .std("c++17") /// .compile("modern"); /// ``` pub fn std(&mut self, std: &str) -> &mut Build { self.std = Some(std.into()); self } /// Set warnings into errors flag. /// /// Disabled by default. /// /// Warning: turning warnings into errors only make sense /// if you are a developer of the crate using cc-rs. /// Some warnings only appear on some architecture or /// specific version of the compiler. Any user of this crate, /// or any other crate depending on it, could fail during /// compile time. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .warnings_into_errors(true) /// .compile("libfoo.a"); /// ``` pub fn warnings_into_errors(&mut self, warnings_into_errors: bool) -> &mut Build { self.warnings_into_errors = warnings_into_errors; self } /// Set warnings flags. /// /// Adds some flags: /// - "-Wall" for MSVC. /// - "-Wall", "-Wextra" for GNU and Clang. /// /// Enabled by default. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .warnings(false) /// .compile("libfoo.a"); /// ``` pub fn warnings(&mut self, warnings: bool) -> &mut Build { self.warnings = Some(warnings); self.extra_warnings = Some(warnings); self } /// Set extra warnings flags. /// /// Adds some flags: /// - nothing for MSVC. /// - "-Wextra" for GNU and Clang. /// /// Enabled by default. /// /// # Example /// /// ```no_run /// // Disables -Wextra, -Wall remains enabled: /// cc::Build::new() /// .file("src/foo.c") /// .extra_warnings(false) /// .compile("libfoo.a"); /// ``` pub fn extra_warnings(&mut self, warnings: bool) -> &mut Build { self.extra_warnings = Some(warnings); self } /// Set the standard library to link against when compiling with C++ /// support. /// /// If the `CXXSTDLIB` environment variable is set, its value will /// override the default value, but not the value explicitly set by calling /// this function. /// /// A value of `None` indicates that no automatic linking should happen, /// otherwise cargo will link against the specified library. /// /// The given library name must not contain the `lib` prefix. /// /// Common values: /// - `stdc++` for GNU /// - `c++` for Clang /// - `c++_shared` or `c++_static` for Android /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .cpp_link_stdlib("stdc++") /// .compile("libfoo.so"); /// ``` pub fn cpp_link_stdlib<'a, V: Into>>( &mut self, cpp_link_stdlib: V, ) -> &mut Build { self.cpp_link_stdlib = Some(cpp_link_stdlib.into().map(Arc::from)); self } /// Force the C++ compiler to use the specified standard library. /// /// Setting this option will automatically set `cpp_link_stdlib` to the same /// value. /// /// The default value of this option is always `None`. /// /// This option has no effect when compiling for a Visual Studio based /// target. /// /// This option sets the `-stdlib` flag, which is only supported by some /// compilers (clang, icc) but not by others (gcc). The library will not /// detect which compiler is used, as such it is the responsibility of the /// caller to ensure that this option is only used in conjunction with a /// compiler which supports the `-stdlib` flag. /// /// A value of `None` indicates that no specific C++ standard library should /// be used, otherwise `-stdlib` is added to the compile invocation. /// /// The given library name must not contain the `lib` prefix. /// /// Common values: /// - `stdc++` for GNU /// - `c++` for Clang /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .cpp_set_stdlib("c++") /// .compile("libfoo.a"); /// ``` pub fn cpp_set_stdlib<'a, V: Into>>( &mut self, cpp_set_stdlib: V, ) -> &mut Build { let cpp_set_stdlib = cpp_set_stdlib.into().map(Arc::from); self.cpp_set_stdlib.clone_from(&cpp_set_stdlib); self.cpp_link_stdlib = Some(cpp_set_stdlib); self } /// Configures the `rustc` target this configuration will be compiling /// for. /// /// This will fail if using a target not in a pre-compiled list taken from /// `rustc +nightly --print target-list`. The list will be updated /// periodically. /// /// You should avoid setting this in build scripts, target information /// will instead be retrieved from the environment variables `TARGET` and /// `CARGO_CFG_TARGET_*` that Cargo sets. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .target("aarch64-linux-android") /// .compile("foo"); /// ``` pub fn target(&mut self, target: &str) -> &mut Build { self.target = Some(target.into()); self } /// Configures the host assumed by this configuration. /// /// This option is automatically scraped from the `HOST` environment /// variable by build scripts, so it's not required to call this function. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .host("arm-linux-gnueabihf") /// .compile("foo"); /// ``` pub fn host(&mut self, host: &str) -> &mut Build { self.host = Some(host.into()); self } /// Configures the optimization level of the generated object files. /// /// This option is automatically scraped from the `OPT_LEVEL` environment /// variable by build scripts, so it's not required to call this function. pub fn opt_level(&mut self, opt_level: u32) -> &mut Build { self.opt_level = Some(opt_level.to_string().into()); self } /// Configures the optimization level of the generated object files. /// /// This option is automatically scraped from the `OPT_LEVEL` environment /// variable by build scripts, so it's not required to call this function. pub fn opt_level_str(&mut self, opt_level: &str) -> &mut Build { self.opt_level = Some(opt_level.into()); self } /// Configures whether the compiler will emit debug information when /// generating object files. /// /// This option is automatically scraped from the `DEBUG` environment /// variable by build scripts, so it's not required to call this function. pub fn debug(&mut self, debug: bool) -> &mut Build { self.debug = Some(debug); self } /// Configures whether the compiler will emit instructions to store /// frame pointers during codegen. /// /// This option is automatically enabled when debug information is emitted. /// Otherwise the target platform compiler's default will be used. /// You can use this option to force a specific setting. pub fn force_frame_pointer(&mut self, force: bool) -> &mut Build { self.force_frame_pointer = Some(force); self } /// Configures the output directory where all object files and static /// libraries will be located. /// /// This option is automatically scraped from the `OUT_DIR` environment /// variable by build scripts, so it's not required to call this function. pub fn out_dir>(&mut self, out_dir: P) -> &mut Build { self.out_dir = Some(out_dir.as_ref().into()); self } /// Configures the compiler to be used to produce output. /// /// This option is automatically determined from the target platform or a /// number of environment variables, so it's not required to call this /// function. pub fn compiler>(&mut self, compiler: P) -> &mut Build { self.compiler = Some(compiler.as_ref().into()); self } /// Configures the tool used to assemble archives. /// /// This option is automatically determined from the target platform or a /// number of environment variables, so it's not required to call this /// function. pub fn archiver>(&mut self, archiver: P) -> &mut Build { self.archiver = Some(archiver.as_ref().into()); self } /// Configures the tool used to index archives. /// /// This option is automatically determined from the target platform or a /// number of environment variables, so it's not required to call this /// function. pub fn ranlib>(&mut self, ranlib: P) -> &mut Build { self.ranlib = Some(ranlib.as_ref().into()); self } /// Define whether metadata should be emitted for cargo allowing it to /// automatically link the binary. Defaults to `true`. /// /// The emitted metadata is: /// /// - `rustc-link-lib=static=`*compiled lib* /// - `rustc-link-search=native=`*target folder* /// - When target is MSVC, the ATL-MFC libs are added via `rustc-link-search=native=` /// - When C++ is enabled, the C++ stdlib is added via `rustc-link-lib` /// - If `emit_rerun_if_env_changed` is not `false`, `rerun-if-env-changed=`*env* /// pub fn cargo_metadata(&mut self, cargo_metadata: bool) -> &mut Build { self.cargo_output.metadata = cargo_metadata; self } /// Define whether compile warnings should be emitted for cargo. Defaults to /// `true`. /// /// If disabled, compiler messages will not be printed. /// Issues unrelated to the compilation will always produce cargo warnings regardless of this setting. pub fn cargo_warnings(&mut self, cargo_warnings: bool) -> &mut Build { self.cargo_output.warnings = cargo_warnings; self } /// Define whether debug information should be emitted for cargo. Defaults to whether /// or not the environment variable `CC_ENABLE_DEBUG_OUTPUT` is set. /// /// If enabled, the compiler will emit debug information when generating object files, /// such as the command invoked and the exit status. pub fn cargo_debug(&mut self, cargo_debug: bool) -> &mut Build { self.cargo_output.debug = cargo_debug; self } /// Define whether compiler output (to stdout) should be emitted. Defaults to `true` /// (forward compiler stdout to this process' stdout) /// /// Some compilers emit errors to stdout, so if you *really* need stdout to be clean /// you should also set this to `false`. pub fn cargo_output(&mut self, cargo_output: bool) -> &mut Build { self.cargo_output.output = if cargo_output { OutputKind::Forward } else { OutputKind::Discard }; self } /// Adds a native library modifier that will be added to the /// `rustc-link-lib=static:MODIFIERS=LIBRARY_NAME` metadata line /// emitted for cargo if `cargo_metadata` is enabled. /// See /// for the list of modifiers accepted by rustc. pub fn link_lib_modifier(&mut self, link_lib_modifier: impl AsRef) -> &mut Build { self.link_lib_modifiers .push(link_lib_modifier.as_ref().into()); self } /// Configures whether the compiler will emit position independent code. /// /// This option defaults to `false` for `windows-gnu` and bare metal targets and /// to `true` for all other targets. pub fn pic(&mut self, pic: bool) -> &mut Build { self.pic = Some(pic); self } /// Configures whether the Procedure Linkage Table is used for indirect /// calls into shared libraries. /// /// The PLT is used to provide features like lazy binding, but introduces /// a small performance loss due to extra pointer indirection. Setting /// `use_plt` to `false` can provide a small performance increase. /// /// Note that skipping the PLT requires a recent version of GCC/Clang. /// /// This only applies to ELF targets. It has no effect on other platforms. pub fn use_plt(&mut self, use_plt: bool) -> &mut Build { self.use_plt = Some(use_plt); self } /// Define whether metadata should be emitted for cargo to detect environment /// changes that should trigger a rebuild. /// /// NOTE that cc does not emit metadata to detect changes for `PATH`, since it could /// be changed every comilation yet does not affect the result of compilation /// (i.e. rust-analyzer adds temporary directory to `PATH`). /// /// cc in general, has no way detecting changes to compiler, as there are so many ways to /// change it and sidestep the detection, for example the compiler might be wrapped in a script /// so detecting change of the file, or using checksum won't work. /// /// We recommend users to decide for themselves, if they want rebuild if the compiler has been upgraded /// or changed, and how to detect that. /// /// This has no effect if the `cargo_metadata` option is `false`. /// /// This option defaults to `true`. pub fn emit_rerun_if_env_changed(&mut self, emit_rerun_if_env_changed: bool) -> &mut Build { self.emit_rerun_if_env_changed = emit_rerun_if_env_changed; self } /// Configures whether the /MT flag or the /MD flag will be passed to msvc build tools. /// /// This option defaults to `false`, and affect only msvc targets. pub fn static_crt(&mut self, static_crt: bool) -> &mut Build { self.static_crt = Some(static_crt); self } /// Configure whether *FLAGS variables are parsed using `shlex`, similarly to `make` and /// `cmake`. /// /// This option defaults to `false`. pub fn shell_escaped_flags(&mut self, shell_escaped_flags: bool) -> &mut Build { self.shell_escaped_flags = Some(shell_escaped_flags); self } /// Configure whether cc should automatically inherit compatible flags passed to rustc /// from `CARGO_ENCODED_RUSTFLAGS`. /// /// This option defaults to `true`. pub fn inherit_rustflags(&mut self, inherit_rustflags: bool) -> &mut Build { self.inherit_rustflags = inherit_rustflags; self } #[doc(hidden)] pub fn __set_env(&mut self, a: A, b: B) -> &mut Build where A: AsRef, B: AsRef, { self.env.push((a.as_ref().into(), b.as_ref().into())); self } } /// Invoke or fetch the compiler or archiver. impl Build { /// Run the compiler to test if it accepts the given flag. /// /// For a convenience method for setting flags conditionally, /// see `flag_if_supported()`. /// /// It may return error if it's unable to run the compiler with a test file /// (e.g. the compiler is missing or a write to the `out_dir` failed). /// /// Note: Once computed, the result of this call is stored in the /// `known_flag_support` field. If `is_flag_supported(flag)` /// is called again, the result will be read from the hash table. pub fn is_flag_supported(&self, flag: impl AsRef) -> Result { self.is_flag_supported_inner( flag.as_ref(), &self.get_base_compiler()?, &self.get_target()?, ) } fn ensure_check_file(&self) -> Result { let out_dir = self.get_out_dir()?; let src = if self.cuda { assert!(self.cpp); out_dir.join("flag_check.cu") } else if self.cpp { out_dir.join("flag_check.cpp") } else { out_dir.join("flag_check.c") }; if !src.exists() { let mut f = fs::File::create(&src)?; write!(f, "int main(void) {{ return 0; }}")?; } Ok(src) } fn is_flag_supported_inner( &self, flag: &OsStr, tool: &Tool, target: &TargetInfo<'_>, ) -> Result { let compiler_flag = CompilerFlag { compiler: tool.path().into(), flag: flag.into(), }; if let Some(is_supported) = self .build_cache .known_flag_support_status_cache .read() .unwrap() .get(&compiler_flag) .cloned() { return Ok(is_supported); } let out_dir = self.get_out_dir()?; let src = self.ensure_check_file()?; let obj = out_dir.join("flag_check"); let mut compiler = { let mut cfg = Build::new(); cfg.flag(flag) .compiler(tool.path()) .cargo_metadata(self.cargo_output.metadata) .opt_level(0) .debug(false) .cpp(self.cpp) .cuda(self.cuda) .inherit_rustflags(false) .emit_rerun_if_env_changed(self.emit_rerun_if_env_changed); if let Some(target) = &self.target { cfg.target(target); } if let Some(host) = &self.host { cfg.host(host); } cfg.try_get_compiler()? }; // Clang uses stderr for verbose output, which yields a false positive // result if the CFLAGS/CXXFLAGS include -v to aid in debugging. if compiler.family.verbose_stderr() { compiler.remove_arg("-v".into()); } if compiler.is_like_clang() { // Avoid reporting that the arg is unsupported just because the // compiler complains that it wasn't used. compiler.push_cc_arg("-Wno-unused-command-line-argument".into()); } let mut cmd = compiler.to_command(); let is_arm = matches!(target.arch, "aarch64" | "arm"); command_add_output_file( &mut cmd, &obj, CmdAddOutputFileArgs { cuda: self.cuda, is_assembler_msvc: false, msvc: compiler.is_like_msvc(), clang: compiler.is_like_clang(), gnu: compiler.is_like_gnu(), is_asm: false, is_arm, }, ); // Checking for compiler flags does not require linking (and we _must_ // avoid making it do so, since it breaks cross-compilation when the C // compiler isn't configured to be able to link). // https://github.com/rust-lang/cc-rs/issues/1423 cmd.arg("-c"); if compiler.supports_path_delimiter() { cmd.arg("--"); } cmd.arg(&src); if compiler.is_like_msvc() { // On MSVC we need to make sure the LIB directory is included // so the CRT can be found. for (key, value) in &tool.env { if key == "LIB" { cmd.env("LIB", value); break; } } } let output = cmd.current_dir(out_dir).output()?; let is_supported = output.status.success() && output.stderr.is_empty(); self.build_cache .known_flag_support_status_cache .write() .unwrap() .insert(compiler_flag, is_supported); Ok(is_supported) } /// Run the compiler, generating the file `output` /// /// This will return a result instead of panicking; see [`Self::compile()`] for /// the complete description. pub fn try_compile(&self, output: &str) -> Result<(), Error> { let mut output_components = Path::new(output).components(); match (output_components.next(), output_components.next()) { (Some(Component::Normal(_)), None) => {} _ => { return Err(Error::new( ErrorKind::InvalidArgument, "argument of `compile` must be a single normal path component", )); } } let (lib_name, gnu_lib_name) = if output.starts_with("lib") && output.ends_with(".a") { (&output[3..output.len() - 2], output.to_owned()) } else { let mut gnu = String::with_capacity(5 + output.len()); gnu.push_str("lib"); gnu.push_str(output); gnu.push_str(".a"); (output, gnu) }; let dst = self.get_out_dir()?; let objects = objects_from_files(&self.files, &dst)?; self.compile_objects(&objects)?; self.assemble(lib_name, &dst.join(gnu_lib_name), &objects)?; let target = self.get_target()?; if target.env == "msvc" { let compiler = self.get_base_compiler()?; let atlmfc_lib = compiler .env() .iter() .find(|&(var, _)| var.as_os_str() == OsStr::new("LIB")) .and_then(|(_, lib_paths)| { env::split_paths(lib_paths).find(|path| { let sub = Path::new("atlmfc/lib"); path.ends_with(sub) || path.parent().map_or(false, |p| p.ends_with(sub)) }) }); if let Some(atlmfc_lib) = atlmfc_lib { self.cargo_output.print_metadata(&format_args!( "cargo:rustc-link-search=native={}", atlmfc_lib.display() )); } } if self.link_lib_modifiers.is_empty() { self.cargo_output .print_metadata(&format_args!("cargo:rustc-link-lib=static={}", lib_name)); } else { self.cargo_output.print_metadata(&format_args!( "cargo:rustc-link-lib=static:{}={}", JoinOsStrs { slice: &self.link_lib_modifiers, delimiter: ',' }, lib_name )); } self.cargo_output.print_metadata(&format_args!( "cargo:rustc-link-search=native={}", dst.display() )); // Add specific C++ libraries, if enabled. if self.cpp { if let Some(stdlib) = self.get_cpp_link_stdlib()? { self.cargo_output .print_metadata(&format_args!("cargo:rustc-link-lib={}", stdlib.display())); } // Link c++ lib from WASI sysroot if target.arch == "wasm32" { if target.os == "wasi" { if let Ok(wasi_sysroot) = self.wasi_sysroot() { self.cargo_output.print_metadata(&format_args!( "cargo:rustc-flags=-L {}/lib/{} -lstatic=c++ -lstatic=c++abi", Path::new(&wasi_sysroot).display(), self.get_raw_target()? )); } } else if target.os == "linux" { let musl_sysroot = self.wasm_musl_sysroot().unwrap(); self.cargo_output.print_metadata(&format_args!( "cargo:rustc-flags=-L {}/lib -lstatic=c++ -lstatic=c++abi", Path::new(&musl_sysroot).display(), )); } } } let cudart = match &self.cudart { Some(opt) => opt, // {none|shared|static} None => "none", }; if cudart != "none" { if let Some(nvcc) = self.which(&self.get_compiler().path, None) { // Try to figure out the -L search path. If it fails, // it's on user to specify one by passing it through // RUSTFLAGS environment variable. let mut libtst = false; let mut libdir = nvcc; libdir.pop(); // remove 'nvcc' libdir.push(".."); if cfg!(target_os = "linux") { libdir.push("targets"); libdir.push(format!("{}-linux", target.arch)); libdir.push("lib"); libtst = true; } else if cfg!(target_env = "msvc") { libdir.push("lib"); match target.arch { "x86_64" => { libdir.push("x64"); libtst = true; } "x86" => { libdir.push("Win32"); libtst = true; } _ => libtst = false, } } if libtst && libdir.is_dir() { self.cargo_output.print_metadata(&format_args!( "cargo:rustc-link-search=native={}", libdir.to_str().unwrap() )); } // And now the -l flag. let lib = match cudart { "shared" => "cudart", "static" => "cudart_static", bad => panic!("unsupported cudart option: {}", bad), }; self.cargo_output .print_metadata(&format_args!("cargo:rustc-link-lib={}", lib)); } } Ok(()) } /// Run the compiler, generating the file `output` /// /// # Library name /// /// The `output` string argument determines the file name for the compiled /// library. The Rust compiler will create an assembly named "lib"+output+".a". /// MSVC will create a file named output+".lib". /// /// The choice of `output` is close to arbitrary, but: /// /// - must be nonempty, /// - must not contain a path separator (`/`), /// - must be unique across all `compile` invocations made by the same build /// script. /// /// If your build script compiles a single source file, the base name of /// that source file would usually be reasonable: /// /// ```no_run /// cc::Build::new().file("blobstore.c").compile("blobstore"); /// ``` /// /// Compiling multiple source files, some people use their crate's name, or /// their crate's name + "-cc". /// /// Otherwise, please use your imagination. /// /// For backwards compatibility, if `output` starts with "lib" *and* ends /// with ".a", a second "lib" prefix and ".a" suffix do not get added on, /// but this usage is deprecated; please omit `lib` and `.a` in the argument /// that you pass. /// /// # Panics /// /// Panics if `output` is not formatted correctly or if one of the underlying /// compiler commands fails. It can also panic if it fails reading file names /// or creating directories. pub fn compile(&self, output: &str) { if let Err(e) = self.try_compile(output) { fail(&e.message); } } /// Run the compiler, generating intermediate files, but without linking /// them into an archive file. /// /// This will return a list of compiled object files, in the same order /// as they were passed in as `file`/`files` methods. pub fn compile_intermediates(&self) -> Vec { match self.try_compile_intermediates() { Ok(v) => v, Err(e) => fail(&e.message), } } /// Run the compiler, generating intermediate files, but without linking /// them into an archive file. /// /// This will return a result instead of panicking; see `compile_intermediates()` for the complete description. pub fn try_compile_intermediates(&self) -> Result, Error> { let dst = self.get_out_dir()?; let objects = objects_from_files(&self.files, &dst)?; self.compile_objects(&objects)?; Ok(objects.into_iter().map(|v| v.dst).collect()) } #[cfg(feature = "parallel")] fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> { use std::cell::Cell; use parallel::async_executor::{block_on, YieldOnce}; check_disabled()?; if objs.len() <= 1 { for obj in objs { let mut cmd = self.create_compile_object_cmd(obj)?; run(&mut cmd, &self.cargo_output)?; } return Ok(()); } // Limit our parallelism globally with a jobserver. let mut tokens = parallel::job_token::ActiveJobTokenServer::new(); // When compiling objects in parallel we do a few dirty tricks to speed // things up: // // * First is that we use the `jobserver` crate to limit the parallelism // of this build script. The `jobserver` crate will use a jobserver // configured by Cargo for build scripts to ensure that parallelism is // coordinated across C compilations and Rust compilations. Before we // compile anything we make sure to wait until we acquire a token. // // Note that this jobserver is cached globally so we only used one per // process and only worry about creating it once. // // * Next we use spawn the process to actually compile objects in // parallel after we've acquired a token to perform some work // // With all that in mind we compile all objects in a loop here, after we // acquire the appropriate tokens, Once all objects have been compiled // we wait on all the processes and propagate the results of compilation. let pendings = Cell::new(Vec::<(Command, KillOnDrop, parallel::job_token::JobToken)>::new()); let is_disconnected = Cell::new(false); let has_made_progress = Cell::new(false); let wait_future = async { let mut error = None; // Buffer the stdout let mut stdout = io::BufWriter::with_capacity(128, io::stdout()); loop { // If the other end of the pipe is already disconnected, then we're not gonna get any new jobs, // so it doesn't make sense to reuse the tokens; in fact, // releasing them as soon as possible (once we know that the other end is disconnected) is beneficial. // Imagine that the last file built takes an hour to finish; in this scenario, // by not releasing the tokens before that last file is done we would effectively block other processes from // starting sooner - even though we only need one token for that last file, not N others that were acquired. let mut pendings_is_empty = false; cell_update(&pendings, |mut pendings| { // Try waiting on them. pendings.retain_mut(|(cmd, child, _token)| { match try_wait_on_child(cmd, &mut child.0, &mut stdout, &mut child.1) { Ok(Some(())) => { // Task done, remove the entry has_made_progress.set(true); false } Ok(None) => true, // Task still not finished, keep the entry Err(err) => { // Task fail, remove the entry. // Since we can only return one error, log the error to make // sure users always see all the compilation failures. has_made_progress.set(true); if self.cargo_output.warnings { let _ = writeln!(stdout, "cargo:warning={}", err); } error = Some(err); false } } }); pendings_is_empty = pendings.is_empty(); pendings }); if pendings_is_empty && is_disconnected.get() { break if let Some(err) = error { Err(err) } else { Ok(()) }; } YieldOnce::default().await; } }; let spawn_future = async { for obj in objs { let mut cmd = self.create_compile_object_cmd(obj)?; let token = tokens.acquire().await?; let mut child = spawn(&mut cmd, &self.cargo_output)?; let mut stderr_forwarder = StderrForwarder::new(&mut child); stderr_forwarder.set_non_blocking()?; cell_update(&pendings, |mut pendings| { pendings.push((cmd, KillOnDrop(child, stderr_forwarder), token)); pendings }); has_made_progress.set(true); } is_disconnected.set(true); Ok::<_, Error>(()) }; return block_on(wait_future, spawn_future, &has_made_progress); struct KillOnDrop(Child, StderrForwarder); impl Drop for KillOnDrop { fn drop(&mut self) { let child = &mut self.0; child.kill().ok(); } } fn cell_update(cell: &Cell, f: F) where T: Default, F: FnOnce(T) -> T, { let old = cell.take(); let new = f(old); cell.set(new); } } #[cfg(not(feature = "parallel"))] fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> { check_disabled()?; for obj in objs { let mut cmd = self.create_compile_object_cmd(obj)?; run(&mut cmd, &self.cargo_output)?; } Ok(()) } fn create_compile_object_cmd(&self, obj: &Object) -> Result { let asm_ext = AsmFileExt::from_path(&obj.src); let is_asm = asm_ext.is_some(); let target = self.get_target()?; let msvc = target.env == "msvc"; let compiler = self.try_get_compiler()?; let is_assembler_msvc = msvc && asm_ext == Some(AsmFileExt::DotAsm); let mut cmd = if is_assembler_msvc { self.msvc_macro_assembler()? } else { let mut cmd = compiler.to_command(); for (a, b) in self.env.iter() { cmd.env(a, b); } cmd }; let is_arm = matches!(target.arch, "aarch64" | "arm"); command_add_output_file( &mut cmd, &obj.dst, CmdAddOutputFileArgs { cuda: self.cuda, is_assembler_msvc, msvc: compiler.is_like_msvc(), clang: compiler.is_like_clang(), gnu: compiler.is_like_gnu(), is_asm, is_arm, }, ); // armasm and armasm64 don't requrie -c option if !is_assembler_msvc || !is_arm { cmd.arg("-c"); } if self.cuda && self.cuda_file_count() > 1 { cmd.arg("--device-c"); } if is_asm { cmd.args(self.asm_flags.iter().map(std::ops::Deref::deref)); } if compiler.supports_path_delimiter() && !is_assembler_msvc { // #513: For `clang-cl`, separate flags/options from the input file. // When cross-compiling macOS -> Windows, this avoids interpreting // common `/Users/...` paths as the `/U` flag and triggering // `-Wslash-u-filename` warning. cmd.arg("--"); } cmd.arg(&obj.src); if cfg!(target_os = "macos") { self.fix_env_for_apple_os(&mut cmd)?; } Ok(cmd) } /// This will return a result instead of panicking; see [`Self::expand()`] for /// the complete description. pub fn try_expand(&self) -> Result, Error> { let compiler = self.try_get_compiler()?; let mut cmd = compiler.to_command(); for (a, b) in self.env.iter() { cmd.env(a, b); } cmd.arg("-E"); assert!( self.files.len() <= 1, "Expand may only be called for a single file" ); let is_asm = self .files .iter() .map(std::ops::Deref::deref) .find_map(AsmFileExt::from_path) .is_some(); if compiler.family == (ToolFamily::Msvc { clang_cl: true }) && !is_asm { // #513: For `clang-cl`, separate flags/options from the input file. // When cross-compiling macOS -> Windows, this avoids interpreting // common `/Users/...` paths as the `/U` flag and triggering // `-Wslash-u-filename` warning. cmd.arg("--"); } cmd.args(self.files.iter().map(std::ops::Deref::deref)); run_output(&mut cmd, &self.cargo_output) } /// Run the compiler, returning the macro-expanded version of the input files. /// /// This is only relevant for C and C++ files. /// /// # Panics /// Panics if more than one file is present in the config, or if compiler /// path has an invalid file name. /// /// # Example /// ```no_run /// let out = cc::Build::new().file("src/foo.c").expand(); /// ``` pub fn expand(&self) -> Vec { match self.try_expand() { Err(e) => fail(&e.message), Ok(v) => v, } } /// Get the compiler that's in use for this configuration. /// /// This function will return a `Tool` which represents the culmination /// of this configuration at a snapshot in time. The returned compiler can /// be inspected (e.g. the path, arguments, environment) to forward along to /// other tools, or the `to_command` method can be used to invoke the /// compiler itself. /// /// This method will take into account all configuration such as debug /// information, optimization level, include directories, defines, etc. /// Additionally, the compiler binary in use follows the standard /// conventions for this path, e.g. looking at the explicitly set compiler, /// environment variables (a number of which are inspected here), and then /// falling back to the default configuration. /// /// # Panics /// /// Panics if an error occurred while determining the architecture. pub fn get_compiler(&self) -> Tool { match self.try_get_compiler() { Ok(tool) => tool, Err(e) => fail(&e.message), } } /// Get the compiler that's in use for this configuration. /// /// This will return a result instead of panicking; see /// [`get_compiler()`](Self::get_compiler) for the complete description. pub fn try_get_compiler(&self) -> Result { let opt_level = self.get_opt_level()?; let target = self.get_target()?; let mut cmd = self.get_base_compiler()?; // The flags below are added in roughly the following order: // 1. Default flags // - Controlled by `cc-rs`. // 2. `rustc`-inherited flags // - Controlled by `rustc`. // 3. Builder flags // - Controlled by the developer using `cc-rs` in e.g. their `build.rs`. // 4. Environment flags // - Controlled by the end user. // // This is important to allow later flags to override previous ones. // Copied from // // Disables non-English messages from localized linkers. // Such messages may cause issues with text encoding on Windows // and prevent inspection of msvc output in case of errors, which we occasionally do. // This should be acceptable because other messages from rustc are in English anyway, // and may also be desirable to improve searchability of the compiler diagnostics. if matches!(cmd.family, ToolFamily::Msvc { clang_cl: false }) { cmd.env.push(("VSLANG".into(), "1033".into())); } else { cmd.env.push(("LC_ALL".into(), "C".into())); } // Disable default flag generation via `no_default_flags` or environment variable let no_defaults = self.no_default_flags || self.getenv_boolean("CRATE_CC_NO_DEFAULTS"); if !no_defaults { self.add_default_flags(&mut cmd, &target, &opt_level)?; } // Specify various flags that are not considered part of the default flags above. // FIXME(madsmtm): Should these be considered part of the defaults? If no, why not? if let Some(ref std) = self.std { let separator = match cmd.family { ToolFamily::Msvc { .. } => ':', ToolFamily::Gnu | ToolFamily::Clang { .. } => '=', }; cmd.push_cc_arg(format!("-std{}{}", separator, std).into()); } for directory in self.include_directories.iter() { cmd.args.push("-I".into()); cmd.args.push(directory.as_os_str().into()); } if self.warnings_into_errors { let warnings_to_errors_flag = cmd.family.warnings_to_errors_flag().into(); cmd.push_cc_arg(warnings_to_errors_flag); } // If warnings and/or extra_warnings haven't been explicitly set, // then we set them only if the environment doesn't already have // CFLAGS/CXXFLAGS, since those variables presumably already contain // the desired set of warnings flags. let envflags = self.envflags(if self.cpp { "CXXFLAGS" } else { "CFLAGS" })?; if self.warnings.unwrap_or(envflags.is_none()) { let wflags = cmd.family.warnings_flags().into(); cmd.push_cc_arg(wflags); } if self.extra_warnings.unwrap_or(envflags.is_none()) { if let Some(wflags) = cmd.family.extra_warnings_flags() { cmd.push_cc_arg(wflags.into()); } } // Add cc flags inherited from matching rustc flags. if self.inherit_rustflags { self.add_inherited_rustflags(&mut cmd, &target)?; } // Set flags configured in the builder (do this second-to-last, to allow these to override // everything above). for flag in self.flags.iter() { cmd.args.push((**flag).into()); } for flag in self.flags_supported.iter() { if self .is_flag_supported_inner(flag, &cmd, &target) .unwrap_or(false) { cmd.push_cc_arg((**flag).into()); } } for (key, value) in self.definitions.iter() { if let Some(ref value) = *value { cmd.args.push(format!("-D{}={}", key, value).into()); } else { cmd.args.push(format!("-D{}", key).into()); } } // Set flags from the environment (do this last, to allow these to override everything else). if let Some(flags) = &envflags { for arg in flags { cmd.push_cc_arg(arg.into()); } } Ok(cmd) } fn add_default_flags( &self, cmd: &mut Tool, target: &TargetInfo<'_>, opt_level: &str, ) -> Result<(), Error> { let raw_target = self.get_raw_target()?; // Non-target flags // If the flag is not conditioned on target variable, it belongs here :) match cmd.family { ToolFamily::Msvc { .. } => { cmd.push_cc_arg("-nologo".into()); let crt_flag = match self.static_crt { Some(true) => "-MT", Some(false) => "-MD", None => { let features = self.getenv("CARGO_CFG_TARGET_FEATURE"); let features = features.as_deref().unwrap_or_default(); if features.to_string_lossy().contains("crt-static") { "-MT" } else { "-MD" } } }; cmd.push_cc_arg(crt_flag.into()); match opt_level { // Msvc uses /O1 to enable all optimizations that minimize code size. "z" | "s" | "1" => cmd.push_opt_unless_duplicate("-O1".into()), // -O3 is a valid value for gcc and clang compilers, but not msvc. Cap to /O2. "2" | "3" => cmd.push_opt_unless_duplicate("-O2".into()), _ => {} } } ToolFamily::Gnu | ToolFamily::Clang { .. } => { // arm-linux-androideabi-gcc 4.8 shipped with Android NDK does // not support '-Oz' if opt_level == "z" && !cmd.is_like_clang() { cmd.push_opt_unless_duplicate("-Os".into()); } else { cmd.push_opt_unless_duplicate(format!("-O{}", opt_level).into()); } if cmd.is_like_clang() && target.os == "android" { // For compatibility with code that doesn't use pre-defined `__ANDROID__` macro. // If compiler used via ndk-build or cmake (officially supported build methods) // this macros is defined. // See https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/build/cmake/android.toolchain.cmake#456 // https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/build/core/build-binary.mk#141 cmd.push_opt_unless_duplicate("-DANDROID".into()); } if target.os != "ios" && target.os != "watchos" && target.os != "tvos" && target.os != "visionos" { cmd.push_cc_arg("-ffunction-sections".into()); cmd.push_cc_arg("-fdata-sections".into()); } // Disable generation of PIC on bare-metal for now: rust-lld doesn't support this yet // // `rustc` also defaults to disable PIC on WASM: // if self.pic.unwrap_or( target.os != "windows" && target.os != "none" && target.os != "uefi" && target.arch != "wasm32" && target.arch != "wasm64", ) { cmd.push_cc_arg("-fPIC".into()); // PLT only applies if code is compiled with PIC support, // and only for ELF targets. if (target.os == "linux" || target.os == "android") && !self.use_plt.unwrap_or(true) { cmd.push_cc_arg("-fno-plt".into()); } } if target.arch == "wasm32" || target.arch == "wasm64" { // WASI does not support exceptions yet. // https://github.com/WebAssembly/exception-handling // // `rustc` also defaults to (currently) disable exceptions // on all WASM targets: // cmd.push_cc_arg("-fno-exceptions".into()); } if target.os == "wasi" { // Link clang sysroot if let Ok(wasi_sysroot) = self.wasi_sysroot() { cmd.push_cc_arg( format!("--sysroot={}", Path::new(&wasi_sysroot).display()).into(), ); } // FIXME(madsmtm): Read from `target_features` instead? if raw_target.contains("threads") { cmd.push_cc_arg("-pthread".into()); } } if target.os == "nto" { // Select the target with `-V`, see qcc documentation: // QNX 7.1: https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.utilities/topic/q/qcc.html // QNX 8.0: https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.utilities/topic/q/qcc.html // This assumes qcc/q++ as compiler, which is currently the only supported compiler for QNX. // See for details: https://github.com/rust-lang/cc-rs/pull/1319 let arg = match target.full_arch { "x86" | "i586" => "-Vgcc_ntox86_cxx", "aarch64" => "-Vgcc_ntoaarch64le_cxx", "x86_64" => "-Vgcc_ntox86_64_cxx", _ => { return Err(Error::new( ErrorKind::InvalidTarget, format!("Unknown architecture for Neutrino QNX: {}", target.arch), )) } }; cmd.push_cc_arg(arg.into()); } } } if self.get_debug() { if self.cuda { // NVCC debug flag cmd.args.push("-G".into()); } let family = cmd.family; family.add_debug_flags(cmd, self.get_dwarf_version()); } if self.get_force_frame_pointer() { let family = cmd.family; family.add_force_frame_pointer(cmd); } if !cmd.is_like_msvc() { if target.arch == "x86" { cmd.args.push("-m32".into()); } else if target.abi == "x32" { cmd.args.push("-mx32".into()); } else if target.os == "aix" { if cmd.family == ToolFamily::Gnu { cmd.args.push("-maix64".into()); } else { cmd.args.push("-m64".into()); } } else if target.arch == "x86_64" || target.arch == "powerpc64" { cmd.args.push("-m64".into()); } } // Target flags match cmd.family { ToolFamily::Clang { .. } => { if !(cmd.has_internal_target_arg || (target.os == "android" && android_clang_compiler_uses_target_arg_internally(&cmd.path))) { if target.os == "freebsd" { // FreeBSD only supports C++11 and above when compiling against libc++ // (available from FreeBSD 10 onwards). Under FreeBSD, clang uses libc++ by // default on FreeBSD 10 and newer unless `--target` is manually passed to // the compiler, in which case its default behavior differs: // * If --target=xxx-unknown-freebsdX(.Y) is specified and X is greater than // or equal to 10, clang++ uses libc++ // * If --target=xxx-unknown-freebsd is specified (without a version), // clang++ cannot assume libc++ is available and reverts to a default of // libstdc++ (this behavior was changed in llvm 14). // // This breaks C++11 (or greater) builds if targeting FreeBSD with the // generic xxx-unknown-freebsd target on clang 13 or below *without* // explicitly specifying that libc++ should be used. // When cross-compiling, we can't infer from the rust/cargo target name // which major version of FreeBSD we are targeting, so we need to make sure // that libc++ is used (unless the user has explicitly specified otherwise). // There's no compelling reason to use a different approach when compiling // natively. if self.cpp && self.cpp_set_stdlib.is_none() { cmd.push_cc_arg("-stdlib=libc++".into()); } } else if target.arch == "wasm32" && target.os == "linux" { for x in &[ "atomics", "bulk-memory", "mutable-globals", "sign-ext", "exception-handling", ] { cmd.push_cc_arg(format!("-m{x}").into()); } for x in &["wasm-exceptions", "declspec"] { cmd.push_cc_arg(format!("-f{x}").into()); } let musl_sysroot = self.wasm_musl_sysroot().unwrap(); cmd.push_cc_arg( format!("--sysroot={}", Path::new(&musl_sysroot).display()).into(), ); cmd.push_cc_arg("-pthread".into()); } // Pass `--target` with the LLVM target to configure Clang for cross-compiling. // // This is **required** for cross-compilation, as it's the only flag that // consistently forces Clang to change the "toolchain" that is responsible for // parsing target-specific flags: // https://github.com/rust-lang/cc-rs/issues/1388 // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.7/clang/lib/Driver/Driver.cpp#L1359-L1360 // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.7/clang/lib/Driver/Driver.cpp#L6347-L6532 // // This can be confusing, because on e.g. host macOS, you can usually get by // with `-arch` and `-mtargetos=`. But that only works because the _default_ // toolchain is `Darwin`, which enables parsing of darwin-specific options. // // NOTE: In the past, we passed the deployment version in here on all Apple // targets, but versioned targets were found to have poor compatibility with // older versions of Clang, especially when it comes to configuration files: // https://github.com/rust-lang/cc-rs/issues/1278 // // So instead, we pass the deployment target with `-m*-version-min=`, and only // pass it here on visionOS and Mac Catalyst where that option does not exist: // https://github.com/rust-lang/cc-rs/issues/1383 let version = if target.os == "visionos" || target.abi == "macabi" { Some(self.apple_deployment_target(target)) } else { None }; let clang_target = target.llvm_target(&self.get_raw_target()?, version.as_deref()); cmd.push_cc_arg(format!("--target={clang_target}").into()); } } ToolFamily::Msvc { clang_cl } => { // This is an undocumented flag from MSVC but helps with making // builds more reproducible by avoiding putting timestamps into // files. cmd.push_cc_arg("-Brepro".into()); if clang_cl { if target.arch == "x86_64" { cmd.push_cc_arg("-m64".into()); } else if target.arch == "x86" { cmd.push_cc_arg("-m32".into()); // See // . // // NOTE: Rust officially supported Windows targets all require SSE2 as part // of baseline target features. // // NOTE: The same applies for STL. See: - // , and - // . cmd.push_cc_arg("-arch:SSE2".into()); } else { cmd.push_cc_arg( format!( "--target={}", target.llvm_target(&self.get_raw_target()?, None) ) .into(), ); } } else if target.full_arch == "i586" { cmd.push_cc_arg("-arch:IA32".into()); } else if target.full_arch == "arm64ec" { cmd.push_cc_arg("-arm64EC".into()); } // There is a check in corecrt.h that will generate a // compilation error if // _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE is // not defined to 1. The check was added in Windows // 8 days because only store apps were allowed on ARM. // This changed with the release of Windows 10 IoT Core. // The check will be going away in future versions of // the SDK, but for all released versions of the // Windows SDK it is required. if target.arch == "arm" { cmd.args .push("-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1".into()); } } ToolFamily::Gnu => { if target.vendor == "kmc" { cmd.args.push("-finput-charset=utf-8".into()); } if self.static_flag.is_none() { let features = self.getenv("CARGO_CFG_TARGET_FEATURE"); let features = features.as_deref().unwrap_or_default(); if features.to_string_lossy().contains("crt-static") { cmd.args.push("-static".into()); } } // armv7 targets get to use armv7 instructions if (target.full_arch.starts_with("armv7") || target.full_arch.starts_with("thumbv7")) && (target.os == "linux" || target.vendor == "kmc") { cmd.args.push("-march=armv7-a".into()); if target.abi == "eabihf" { // lowest common denominator FPU cmd.args.push("-mfpu=vfpv3-d16".into()); cmd.args.push("-mfloat-abi=hard".into()); } } // (x86 Android doesn't say "eabi") if target.os == "android" && target.full_arch.contains("v7") { cmd.args.push("-march=armv7-a".into()); cmd.args.push("-mthumb".into()); if !target.full_arch.contains("neon") { // On android we can guarantee some extra float instructions // (specified in the android spec online) // NEON guarantees even more; see below. cmd.args.push("-mfpu=vfpv3-d16".into()); } cmd.args.push("-mfloat-abi=softfp".into()); } if target.full_arch.contains("neon") { cmd.args.push("-mfpu=neon-vfpv4".into()); } if target.full_arch == "armv4t" && target.os == "linux" { cmd.args.push("-march=armv4t".into()); cmd.args.push("-marm".into()); cmd.args.push("-mfloat-abi=soft".into()); } if target.full_arch == "armv5te" && target.os == "linux" { cmd.args.push("-march=armv5te".into()); cmd.args.push("-marm".into()); cmd.args.push("-mfloat-abi=soft".into()); } // For us arm == armv6 by default if target.full_arch == "arm" && target.os == "linux" { cmd.args.push("-march=armv6".into()); cmd.args.push("-marm".into()); if target.abi == "eabihf" { cmd.args.push("-mfpu=vfp".into()); } else { cmd.args.push("-mfloat-abi=soft".into()); } } // Turn codegen down on i586 to avoid some instructions. if target.full_arch == "i586" && target.os == "linux" { cmd.args.push("-march=pentium".into()); } // Set codegen level for i686 correctly if target.full_arch == "i686" && target.os == "linux" { cmd.args.push("-march=i686".into()); } // Looks like `musl-gcc` makes it hard for `-m32` to make its way // all the way to the linker, so we need to actually instruct the // linker that we're generating 32-bit executables as well. This'll // typically only be used for build scripts which transitively use // these flags that try to compile executables. if target.arch == "x86" && target.env == "musl" { cmd.args.push("-Wl,-melf_i386".into()); } if target.arch == "arm" && target.os == "none" && target.abi == "eabihf" { cmd.args.push("-mfloat-abi=hard".into()) } if target.full_arch.starts_with("thumb") { cmd.args.push("-mthumb".into()); } if target.full_arch.starts_with("thumbv6m") { cmd.args.push("-march=armv6s-m".into()); } if target.full_arch.starts_with("thumbv7em") { cmd.args.push("-march=armv7e-m".into()); if target.abi == "eabihf" { cmd.args.push("-mfpu=fpv4-sp-d16".into()) } } if target.full_arch.starts_with("thumbv7m") { cmd.args.push("-march=armv7-m".into()); } if target.full_arch.starts_with("thumbv8m.base") { cmd.args.push("-march=armv8-m.base".into()); } if target.full_arch.starts_with("thumbv8m.main") { cmd.args.push("-march=armv8-m.main".into()); if target.abi == "eabihf" { cmd.args.push("-mfpu=fpv5-sp-d16".into()) } } if target.full_arch.starts_with("armebv7r") | target.full_arch.starts_with("armv7r") { if target.full_arch.starts_with("armeb") { cmd.args.push("-mbig-endian".into()); } else { cmd.args.push("-mlittle-endian".into()); } // ARM mode cmd.args.push("-marm".into()); // R Profile cmd.args.push("-march=armv7-r".into()); if target.abi == "eabihf" { // lowest common denominator FPU // (see Cortex-R4 technical reference manual) cmd.args.push("-mfpu=vfpv3-d16".into()) } } if target.full_arch.starts_with("armv7a") { cmd.args.push("-march=armv7-a".into()); if target.abi == "eabihf" { // lowest common denominator FPU cmd.args.push("-mfpu=vfpv3-d16".into()); } } if target.arch == "riscv32" || target.arch == "riscv64" { // get the 32i/32imac/32imc/64gc/64imac/... part let arch = &target.full_arch[5..]; if arch.starts_with("64") { if matches!(target.os, "linux" | "freebsd" | "netbsd") { cmd.args.push(("-march=rv64gc").into()); cmd.args.push("-mabi=lp64d".into()); } else { cmd.args.push(("-march=rv".to_owned() + arch).into()); cmd.args.push("-mabi=lp64".into()); } } else if arch.starts_with("32") { if target.os == "linux" { cmd.args.push(("-march=rv32gc").into()); cmd.args.push("-mabi=ilp32d".into()); } else { cmd.args.push(("-march=rv".to_owned() + arch).into()); cmd.args.push("-mabi=ilp32".into()); } } else { cmd.args.push("-mcmodel=medany".into()); } } } } if target.vendor == "apple" { self.apple_flags(cmd)?; } if self.static_flag.unwrap_or(false) { cmd.args.push("-static".into()); } if self.shared_flag.unwrap_or(false) { cmd.args.push("-shared".into()); } if self.cpp { match (self.cpp_set_stdlib.as_ref(), cmd.family) { (None, _) => {} (Some(stdlib), ToolFamily::Gnu) | (Some(stdlib), ToolFamily::Clang { .. }) => { cmd.push_cc_arg(format!("-stdlib=lib{}", stdlib).into()); } _ => { self.cargo_output.print_warning(&format_args!("cpp_set_stdlib is specified, but the {:?} compiler does not support this option, ignored", cmd.family)); } } } Ok(()) } fn add_inherited_rustflags( &self, cmd: &mut Tool, target: &TargetInfo<'_>, ) -> Result<(), Error> { let env_os = match self.getenv("CARGO_ENCODED_RUSTFLAGS") { Some(env) => env, // No encoded RUSTFLAGS -> nothing to do None => return Ok(()), }; let env = env_os.to_string_lossy(); let codegen_flags = RustcCodegenFlags::parse(&env)?; codegen_flags.cc_flags(self, cmd, target); Ok(()) } fn msvc_macro_assembler(&self) -> Result { let target = self.get_target()?; let tool = if target.arch == "x86_64" { "ml64.exe" } else if target.arch == "arm" { "armasm.exe" } else if target.arch == "aarch64" { "armasm64.exe" } else { "ml.exe" }; let mut cmd = self .windows_registry_find(&target, tool) .unwrap_or_else(|| self.cmd(tool)); cmd.arg("-nologo"); // undocumented, yet working with armasm[64] for directory in self.include_directories.iter() { cmd.arg("-I").arg(&**directory); } if target.arch == "aarch64" || target.arch == "arm" { if self.get_debug() { cmd.arg("-g"); } for (key, value) in self.definitions.iter() { cmd.arg("-PreDefine"); if let Some(ref value) = *value { if let Ok(i) = value.parse::() { cmd.arg(format!("{} SETA {}", key, i)); } else if value.starts_with('"') && value.ends_with('"') { cmd.arg(format!("{} SETS {}", key, value)); } else { cmd.arg(format!("{} SETS \"{}\"", key, value)); } } else { cmd.arg(format!("{} SETL {}", key, "{TRUE}")); } } } else { if self.get_debug() { cmd.arg("-Zi"); } for (key, value) in self.definitions.iter() { if let Some(ref value) = *value { cmd.arg(format!("-D{}={}", key, value)); } else { cmd.arg(format!("-D{}", key)); } } } if target.arch == "x86" { cmd.arg("-safeseh"); } Ok(cmd) } fn assemble(&self, lib_name: &str, dst: &Path, objs: &[Object]) -> Result<(), Error> { // Delete the destination if it exists as we want to // create on the first iteration instead of appending. let _ = fs::remove_file(dst); // Add objects to the archive in limited-length batches. This helps keep // the length of the command line within a reasonable length to avoid // blowing system limits on limiting platforms like Windows. let objs: Vec<_> = objs .iter() .map(|o| o.dst.as_path()) .chain(self.objects.iter().map(std::ops::Deref::deref)) .collect(); for chunk in objs.chunks(100) { self.assemble_progressive(dst, chunk)?; } if self.cuda && self.cuda_file_count() > 0 { // Link the device-side code and add it to the target library, // so that non-CUDA linker can link the final binary. let out_dir = self.get_out_dir()?; let dlink = out_dir.join(lib_name.to_owned() + "_dlink.o"); let mut nvcc = self.get_compiler().to_command(); nvcc.arg("--device-link").arg("-o").arg(&dlink).arg(dst); run(&mut nvcc, &self.cargo_output)?; self.assemble_progressive(dst, &[dlink.as_path()])?; } let target = self.get_target()?; if target.env == "msvc" { // The Rust compiler will look for libfoo.a and foo.lib, but the // MSVC linker will also be passed foo.lib, so be sure that both // exist for now. let lib_dst = dst.with_file_name(format!("{}.lib", lib_name)); let _ = fs::remove_file(&lib_dst); match fs::hard_link(dst, &lib_dst).or_else(|_| { // if hard-link fails, just copy (ignoring the number of bytes written) fs::copy(dst, &lib_dst).map(|_| ()) }) { Ok(_) => (), Err(_) => { return Err(Error::new( ErrorKind::IOError, "Could not copy or create a hard-link to the generated lib file.", )); } }; } else { // Non-msvc targets (those using `ar`) need a separate step to add // the symbol table to archives since our construction command of // `cq` doesn't add it for us. let mut ar = self.try_get_archiver()?; // NOTE: We add `s` even if flags were passed using $ARFLAGS/ar_flag, because `s` // here represents a _mode_, not an arbitrary flag. Further discussion of this choice // can be seen in https://github.com/rust-lang/cc-rs/pull/763. run(ar.arg("s").arg(dst), &self.cargo_output)?; } Ok(()) } fn assemble_progressive(&self, dst: &Path, objs: &[&Path]) -> Result<(), Error> { let target = self.get_target()?; let (mut cmd, program, any_flags) = self.try_get_archiver_and_flags()?; if target.env == "msvc" && !program.to_string_lossy().contains("llvm-ar") { // NOTE: -out: here is an I/O flag, and so must be included even if $ARFLAGS/ar_flag is // in use. -nologo on the other hand is just a regular flag, and one that we'll skip if // the caller has explicitly dictated the flags they want. See // https://github.com/rust-lang/cc-rs/pull/763 for further discussion. let mut out = OsString::from("-out:"); out.push(dst); cmd.arg(out); if !any_flags { cmd.arg("-nologo"); } // If the library file already exists, add the library name // as an argument to let lib.exe know we are appending the objs. if dst.exists() { cmd.arg(dst); } cmd.args(objs); run(&mut cmd, &self.cargo_output)?; } else { // Set an environment variable to tell the OSX archiver to ensure // that all dates listed in the archive are zero, improving // determinism of builds. AFAIK there's not really official // documentation of this but there's a lot of references to it if // you search google. // // You can reproduce this locally on a mac with: // // $ touch foo.c // $ cc -c foo.c -o foo.o // // # Notice that these two checksums are different // $ ar crus libfoo1.a foo.o && sleep 2 && ar crus libfoo2.a foo.o // $ md5sum libfoo*.a // // # Notice that these two checksums are the same // $ export ZERO_AR_DATE=1 // $ ar crus libfoo1.a foo.o && sleep 2 && touch foo.o && ar crus libfoo2.a foo.o // $ md5sum libfoo*.a // // In any case if this doesn't end up getting read, it shouldn't // cause that many issues! cmd.env("ZERO_AR_DATE", "1"); // NOTE: We add cq here regardless of whether $ARFLAGS/ar_flag have been used because // it dictates the _mode_ ar runs in, which the setter of $ARFLAGS/ar_flag can't // dictate. See https://github.com/rust-lang/cc-rs/pull/763 for further discussion. run(cmd.arg("cq").arg(dst).args(objs), &self.cargo_output)?; } Ok(()) } fn apple_flags(&self, cmd: &mut Tool) -> Result<(), Error> { let target = self.get_target()?; // This is a Darwin/Apple-specific flag that works both on GCC and Clang, but it is only // necessary on GCC since we specify `-target` on Clang. // https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html#:~:text=arch // https://clang.llvm.org/docs/CommandGuide/clang.html#cmdoption-arch if cmd.is_like_gnu() { let arch = map_darwin_target_from_rust_to_compiler_architecture(&target); cmd.args.push("-arch".into()); cmd.args.push(arch.into()); } // Pass the deployment target via `-mmacosx-version-min=`, `-miphoneos-version-min=` and // similar. Also necessary on GCC, as it forces a compilation error if the compiler is not // configured for Darwin: https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html // // On visionOS and Mac Catalyst, there is no -m*-version-min= flag: // https://github.com/llvm/llvm-project/issues/88271 // And the workaround to use `-mtargetos=` cannot be used with the `--target` flag that we // otherwise specify. So we avoid emitting that, and put the version in `--target` instead. if cmd.is_like_gnu() || !(target.os == "visionos" || target.abi == "macabi") { let min_version = self.apple_deployment_target(&target); cmd.args .push(target.apple_version_flag(&min_version).into()); } // AppleClang sometimes requires sysroot even on macOS if cmd.is_xctoolchain_clang() || target.os != "macos" { self.cargo_output.print_metadata(&format_args!( "Detecting {:?} SDK path for {}", target.os, target.apple_sdk_name(), )); let sdk_path = self.apple_sdk_root(&target)?; cmd.args.push("-isysroot".into()); cmd.args.push(OsStr::new(&sdk_path).to_owned()); if target.abi == "macabi" { // Mac Catalyst uses the macOS SDK, but to compile against and // link to iOS-specific frameworks, we should have the support // library stubs in the include and library search path. let ios_support = Path::new(&sdk_path).join("System/iOSSupport"); cmd.args.extend([ // Header search path OsString::from("-isystem"), ios_support.join("usr/include").into(), // Framework header search path OsString::from("-iframework"), ios_support.join("System/Library/Frameworks").into(), // Library search path { let mut s = OsString::from("-L"); s.push(ios_support.join("usr/lib")); s }, // Framework linker search path { // Technically, we _could_ avoid emitting `-F`, as // `-iframework` implies it, but let's keep it in for // clarity. let mut s = OsString::from("-F"); s.push(ios_support.join("System/Library/Frameworks")); s }, ]); } } Ok(()) } fn cmd>(&self, prog: P) -> Command { let mut cmd = Command::new(prog); for (a, b) in self.env.iter() { cmd.env(a, b); } cmd } fn get_base_compiler(&self) -> Result { let out_dir = self.get_out_dir().ok(); let out_dir = out_dir.as_deref(); if let Some(c) = &self.compiler { return Ok(Tool::new( (**c).to_owned(), &self.build_cache.cached_compiler_family, &self.cargo_output, out_dir, )); } let target = self.get_target()?; let raw_target = self.get_raw_target()?; let (env, msvc, gnu, traditional, clang) = if self.cpp { ("CXX", "cl.exe", "g++", "c++", "clang++") } else { ("CC", "cl.exe", "gcc", "cc", "clang") }; // On historical Solaris systems, "cc" may have been Sun Studio, which // is not flag-compatible with "gcc". This history casts a long shadow, // and many modern illumos distributions today ship GCC as "gcc" without // also making it available as "cc". let default = if cfg!(target_os = "solaris") || cfg!(target_os = "illumos") { gnu } else { traditional }; let cl_exe = self.windows_registry_find_tool(&target, "cl.exe"); let tool_opt: Option = self .env_tool(env) .map(|(tool, wrapper, args)| { // Chop off leading/trailing whitespace to work around // semi-buggy build scripts which are shared in // makefiles/configure scripts (where spaces are far more // lenient) let mut t = Tool::with_args( tool, args.clone(), &self.build_cache.cached_compiler_family, &self.cargo_output, out_dir, ); if let Some(cc_wrapper) = wrapper { t.cc_wrapper_path = Some(Path::new(&cc_wrapper).to_owned()); } for arg in args { t.cc_wrapper_args.push(arg.into()); } t }) .or_else(|| { if target.os == "emscripten" { let tool = if self.cpp { "em++" } else { "emcc" }; // Windows uses bat file so we have to be a bit more specific if cfg!(windows) { let mut t = Tool::with_family( PathBuf::from("cmd"), ToolFamily::Clang { zig_cc: false }, ); t.args.push("/c".into()); t.args.push(format!("{}.bat", tool).into()); Some(t) } else { Some(Tool::new( PathBuf::from(tool), &self.build_cache.cached_compiler_family, &self.cargo_output, out_dir, )) } } else { None } }) .or_else(|| cl_exe.clone()); let tool = match tool_opt { Some(t) => t, None => { let compiler = if cfg!(windows) && target.os == "windows" { if target.env == "msvc" { msvc.to_string() } else { let cc = if target.abi == "llvm" { clang } else { gnu }; format!("{}.exe", cc) } } else if target.os == "ios" || target.os == "watchos" || target.os == "tvos" || target.os == "visionos" { clang.to_string() } else if target.os == "android" { autodetect_android_compiler(&raw_target, gnu, clang) } else if target.os == "cloudabi" { format!( "{}-{}-{}-{}", target.full_arch, target.vendor, target.os, traditional ) } else if target.arch == "wasm32" || target.arch == "wasm64" { // Compiling WASM is not currently supported by GCC, so // let's default to Clang. clang.to_string() } else if target.os == "vxworks" { if self.cpp { "wr-c++".to_string() } else { "wr-cc".to_string() } } else if target.arch == "arm" && target.vendor == "kmc" { format!("arm-kmc-eabi-{}", gnu) } else if target.arch == "aarch64" && target.vendor == "kmc" { format!("aarch64-kmc-elf-{}", gnu) } else if target.os == "nto" { // See for details: https://github.com/rust-lang/cc-rs/pull/1319 if self.cpp { "q++".to_string() } else { "qcc".to_string() } } else if self.get_is_cross_compile()? { let prefix = self.prefix_for_target(&raw_target); match prefix { Some(prefix) => { let cc = if target.abi == "llvm" { clang } else { gnu }; format!("{}-{}", prefix, cc) } None => default.to_string(), } } else { default.to_string() }; let mut t = Tool::new( PathBuf::from(compiler), &self.build_cache.cached_compiler_family, &self.cargo_output, out_dir, ); if let Some(cc_wrapper) = self.rustc_wrapper_fallback() { t.cc_wrapper_path = Some(Path::new(&cc_wrapper).to_owned()); } t } }; let mut tool = if self.cuda { assert!( tool.args.is_empty(), "CUDA compilation currently assumes empty pre-existing args" ); let nvcc = match self.getenv_with_target_prefixes("NVCC") { Err(_) => PathBuf::from("nvcc"), Ok(nvcc) => PathBuf::from(&*nvcc), }; let mut nvcc_tool = Tool::with_features( nvcc, vec![], self.cuda, &self.build_cache.cached_compiler_family, &self.cargo_output, out_dir, ); if self.ccbin { nvcc_tool .args .push(format!("-ccbin={}", tool.path.display()).into()); } if let Some(cc_wrapper) = self.rustc_wrapper_fallback() { nvcc_tool.cc_wrapper_path = Some(Path::new(&cc_wrapper).to_owned()); } nvcc_tool.family = tool.family; nvcc_tool } else { tool }; // New "standalone" C/C++ cross-compiler executables from recent Android NDK // are just shell scripts that call main clang binary (from Android NDK) with // proper `--target` argument. // // For example, armv7a-linux-androideabi16-clang passes // `--target=armv7a-linux-androideabi16` to clang. // // As the shell script calls the main clang binary, the command line limit length // on Windows is restricted to around 8k characters instead of around 32k characters. // To remove this limit, we call the main clang binary directly and construct the // `--target=` ourselves. if cfg!(windows) && android_clang_compiler_uses_target_arg_internally(&tool.path) { if let Some(path) = tool.path.file_name() { let file_name = path.to_str().unwrap().to_owned(); let (target, clang) = file_name.split_at(file_name.rfind('-').unwrap()); tool.has_internal_target_arg = true; tool.path.set_file_name(clang.trim_start_matches('-')); tool.path.set_extension("exe"); tool.args.push(format!("--target={}", target).into()); // Additionally, shell scripts for target i686-linux-android versions 16 to 24 // pass the `mstackrealign` option so we do that here as well. if target.contains("i686-linux-android") { let (_, version) = target.split_at(target.rfind('d').unwrap() + 1); if let Ok(version) = version.parse::() { if version > 15 && version < 25 { tool.args.push("-mstackrealign".into()); } } } }; } // If we found `cl.exe` in our environment, the tool we're returning is // an MSVC-like tool, *and* no env vars were set then set env vars for // the tool that we're returning. // // Env vars are needed for things like `link.exe` being put into PATH as // well as header include paths sometimes. These paths are automatically // included by default but if the `CC` or `CXX` env vars are set these // won't be used. This'll ensure that when the env vars are used to // configure for invocations like `clang-cl` we still get a "works out // of the box" experience. if let Some(cl_exe) = cl_exe { if tool.family == (ToolFamily::Msvc { clang_cl: true }) && tool.env.is_empty() && target.env == "msvc" { for (k, v) in cl_exe.env.iter() { tool.env.push((k.to_owned(), v.to_owned())); } } } if target.env == "msvc" && tool.family == ToolFamily::Gnu { self.cargo_output .print_warning(&"GNU compiler is not supported for this target"); } Ok(tool) } /// Returns a fallback `cc_compiler_wrapper` by introspecting `RUSTC_WRAPPER` fn rustc_wrapper_fallback(&self) -> Option> { // No explicit CC wrapper was detected, but check if RUSTC_WRAPPER // is defined and is a build accelerator that is compatible with // C/C++ compilers (e.g. sccache) const VALID_WRAPPERS: &[&str] = &["sccache", "cachepot", "buildcache"]; let rustc_wrapper = self.getenv("RUSTC_WRAPPER")?; let wrapper_path = Path::new(&rustc_wrapper); let wrapper_stem = wrapper_path.file_stem()?; if VALID_WRAPPERS.contains(&wrapper_stem.to_str()?) { Some(rustc_wrapper) } else { None } } /// Returns compiler path, optional modifier name from whitelist, and arguments vec fn env_tool(&self, name: &str) -> Option<(PathBuf, Option>, Vec)> { let tool = self.getenv_with_target_prefixes(name).ok()?; let tool = tool.to_string_lossy(); let tool = tool.trim(); if tool.is_empty() { return None; } // If this is an exact path on the filesystem we don't want to do any // interpretation at all, just pass it on through. This'll hopefully get // us to support spaces-in-paths. if Path::new(tool).exists() { return Some(( PathBuf::from(tool), self.rustc_wrapper_fallback(), Vec::new(), )); } // Ok now we want to handle a couple of scenarios. We'll assume from // here on out that spaces are splitting separate arguments. Two major // features we want to support are: // // CC='sccache cc' // // aka using `sccache` or any other wrapper/caching-like-thing for // compilations. We want to know what the actual compiler is still, // though, because our `Tool` API support introspection of it to see // what compiler is in use. // // additionally we want to support // // CC='cc -flag' // // where the CC env var is used to also pass default flags to the C // compiler. // // It's true that everything here is a bit of a pain, but apparently if // you're not literally make or bash then you get a lot of bug reports. let mut known_wrappers = vec![ "ccache", "distcc", "sccache", "icecc", "cachepot", "buildcache", ]; let custom_wrapper = self.getenv("CC_KNOWN_WRAPPER_CUSTOM"); if custom_wrapper.is_some() { known_wrappers.push(custom_wrapper.as_deref().unwrap().to_str().unwrap()); } let mut parts = tool.split_whitespace(); let maybe_wrapper = parts.next()?; let file_stem = Path::new(maybe_wrapper).file_stem()?.to_str()?; if known_wrappers.contains(&file_stem) { if let Some(compiler) = parts.next() { return Some(( compiler.into(), Some(Arc::::from(OsStr::new(&maybe_wrapper))), parts.map(|s| s.to_string()).collect(), )); } } Some(( maybe_wrapper.into(), self.rustc_wrapper_fallback(), parts.map(|s| s.to_string()).collect(), )) } /// Returns the C++ standard library: /// 1. If [`cpp_link_stdlib`](cc::Build::cpp_link_stdlib) is set, uses its value. /// 2. Else if the `CXXSTDLIB` environment variable is set, uses its value. /// 3. Else the default is `c++` for OS X and BSDs, `c++_shared` for Android, /// `None` for MSVC and `stdc++` for anything else. fn get_cpp_link_stdlib(&self) -> Result>, Error> { match &self.cpp_link_stdlib { Some(s) => Ok(s.as_deref().map(Path::new).map(Cow::Borrowed)), None => { if let Ok(stdlib) = self.getenv_with_target_prefixes("CXXSTDLIB") { if stdlib.is_empty() { Ok(None) } else { Ok(Some(Cow::Owned(Path::new(&stdlib).to_owned()))) } } else { let target = self.get_target()?; if target.env == "msvc" { Ok(None) } else if target.vendor == "apple" || target.os == "freebsd" || target.os == "openbsd" || target.os == "aix" || (target.os == "linux" && target.env == "ohos") || target.os == "wasi" { Ok(Some(Cow::Borrowed(Path::new("c++")))) } else if target.os == "android" { Ok(Some(Cow::Borrowed(Path::new("c++_shared")))) } else { Ok(Some(Cow::Borrowed(Path::new("stdc++")))) } } } } } /// Get the archiver (ar) that's in use for this configuration. /// /// You can use [`Command::get_program`] to get just the path to the command. /// /// This method will take into account all configuration such as debug /// information, optimization level, include directories, defines, etc. /// Additionally, the compiler binary in use follows the standard /// conventions for this path, e.g. looking at the explicitly set compiler, /// environment variables (a number of which are inspected here), and then /// falling back to the default configuration. /// /// # Panics /// /// Panics if an error occurred while determining the architecture. pub fn get_archiver(&self) -> Command { match self.try_get_archiver() { Ok(tool) => tool, Err(e) => fail(&e.message), } } /// Get the archiver that's in use for this configuration. /// /// This will return a result instead of panicking; /// see [`Self::get_archiver`] for the complete description. pub fn try_get_archiver(&self) -> Result { Ok(self.try_get_archiver_and_flags()?.0) } fn try_get_archiver_and_flags(&self) -> Result<(Command, PathBuf, bool), Error> { let (mut cmd, name) = self.get_base_archiver()?; let mut any_flags = false; if let Some(flags) = self.envflags("ARFLAGS")? { any_flags = true; cmd.args(flags); } for flag in &self.ar_flags { any_flags = true; cmd.arg(&**flag); } Ok((cmd, name, any_flags)) } fn get_base_archiver(&self) -> Result<(Command, PathBuf), Error> { if let Some(ref a) = self.archiver { let archiver = &**a; return Ok((self.cmd(archiver), archiver.into())); } self.get_base_archiver_variant("AR", "ar") } /// Get the ranlib that's in use for this configuration. /// /// You can use [`Command::get_program`] to get just the path to the command. /// /// This method will take into account all configuration such as debug /// information, optimization level, include directories, defines, etc. /// Additionally, the compiler binary in use follows the standard /// conventions for this path, e.g. looking at the explicitly set compiler, /// environment variables (a number of which are inspected here), and then /// falling back to the default configuration. /// /// # Panics /// /// Panics if an error occurred while determining the architecture. pub fn get_ranlib(&self) -> Command { match self.try_get_ranlib() { Ok(tool) => tool, Err(e) => fail(&e.message), } } /// Get the ranlib that's in use for this configuration. /// /// This will return a result instead of panicking; /// see [`Self::get_ranlib`] for the complete description. pub fn try_get_ranlib(&self) -> Result { let mut cmd = self.get_base_ranlib()?; if let Some(flags) = self.envflags("RANLIBFLAGS")? { cmd.args(flags); } Ok(cmd) } fn get_base_ranlib(&self) -> Result { if let Some(ref r) = self.ranlib { return Ok(self.cmd(&**r)); } Ok(self.get_base_archiver_variant("RANLIB", "ranlib")?.0) } fn get_base_archiver_variant( &self, env: &str, tool: &str, ) -> Result<(Command, PathBuf), Error> { let target = self.get_target()?; let mut name = PathBuf::new(); let tool_opt: Option = self .env_tool(env) .map(|(tool, _wrapper, args)| { name.clone_from(&tool); let mut cmd = self.cmd(tool); cmd.args(args); cmd }) .or_else(|| { if target.os == "emscripten" { // Windows use bat files so we have to be a bit more specific if cfg!(windows) { let mut cmd = self.cmd("cmd"); name = format!("em{}.bat", tool).into(); cmd.arg("/c").arg(&name); Some(cmd) } else { name = format!("em{}", tool).into(); Some(self.cmd(&name)) } } else if target.arch == "wasm32" || target.arch == "wasm64" { // Formally speaking one should be able to use this approach, // parsing -print-search-dirs output, to cover all clang targets, // including Android SDKs and other cross-compilation scenarios... // And even extend it to gcc targets by searching for "ar" instead // of "llvm-ar"... let compiler = self.get_base_compiler().ok()?; if compiler.is_like_clang() { name = format!("llvm-{}", tool).into(); self.search_programs( &mut self.cmd(&compiler.path), &name, &self.cargo_output, ) .map(|name| self.cmd(name)) } else { None } } else { None } }); let tool = match tool_opt { Some(t) => t, None => { if target.os == "android" { name = format!("llvm-{}", tool).into(); match Command::new(&name).arg("--version").status() { Ok(status) if status.success() => (), _ => { // FIXME: Use parsed target. let raw_target = self.get_raw_target()?; name = format!("{}-{}", raw_target.replace("armv7", "arm"), tool).into() } } self.cmd(&name) } else if target.env == "msvc" { // NOTE: There isn't really a ranlib on msvc, so arguably we should return // `None` somehow here. But in general, callers will already have to be aware // of not running ranlib on Windows anyway, so it feels okay to return lib.exe // here. let compiler = self.get_base_compiler()?; let mut lib = String::new(); if compiler.family == (ToolFamily::Msvc { clang_cl: true }) { // See if there is 'llvm-lib' next to 'clang-cl' // Another possibility could be to see if there is 'clang' // next to 'clang-cl' and use 'search_programs()' to locate // 'llvm-lib'. This is because 'clang-cl' doesn't support // the -print-search-dirs option. if let Some(mut cmd) = self.which(&compiler.path, None) { cmd.pop(); cmd.push("llvm-lib.exe"); if let Some(llvm_lib) = self.which(&cmd, None) { llvm_lib.to_str().unwrap().clone_into(&mut lib); } } } if lib.is_empty() { name = PathBuf::from("lib.exe"); let mut cmd = match self.windows_registry_find(&target, "lib.exe") { Some(t) => t, None => self.cmd("lib.exe"), }; if target.full_arch == "arm64ec" { cmd.arg("/machine:arm64ec"); } cmd } else { name = lib.into(); self.cmd(&name) } } else if target.os == "illumos" { // The default 'ar' on illumos uses a non-standard flags, // but the OS comes bundled with a GNU-compatible variant. // // Use the GNU-variant to match other Unix systems. name = format!("g{}", tool).into(); self.cmd(&name) } else if target.os == "vxworks" { name = format!("wr-{}", tool).into(); self.cmd(&name) } else if target.os == "nto" { // Ref: https://www.qnx.com/developers/docs/8.0/com.qnx.doc.neutrino.utilities/topic/a/ar.html name = match target.full_arch { "i586" => format!("ntox86-{}", tool).into(), "x86" | "aarch64" | "x86_64" => { format!("nto{}-{}", target.arch, tool).into() } _ => { return Err(Error::new( ErrorKind::InvalidTarget, format!("Unknown architecture for Neutrino QNX: {}", target.arch), )) } }; self.cmd(&name) } else if self.get_is_cross_compile()? { match self.prefix_for_target(&self.get_raw_target()?) { Some(prefix) => { // GCC uses $target-gcc-ar, whereas binutils uses $target-ar -- try both. // Prefer -ar if it exists, as builds of `-gcc-ar` have been observed to be // outright broken (such as when targeting freebsd with `--disable-lto` // toolchain where the archiver attempts to load the LTO plugin anyway but // fails to find one). // // The same applies to ranlib. let chosen = ["", "-gcc"] .iter() .filter_map(|infix| { let target_p = format!("{prefix}{infix}-{tool}"); let status = Command::new(&target_p) .arg("--version") .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::null()) .status() .ok()?; status.success().then_some(target_p) }) .next() .unwrap_or_else(|| tool.to_string()); name = chosen.into(); self.cmd(&name) } None => { name = tool.into(); self.cmd(&name) } } } else { name = tool.into(); self.cmd(&name) } } }; Ok((tool, name)) } // FIXME: Use parsed target instead of raw target. fn prefix_for_target(&self, target: &str) -> Option> { // CROSS_COMPILE is of the form: "arm-linux-gnueabi-" self.getenv("CROSS_COMPILE") .as_deref() .map(|s| s.to_string_lossy().trim_end_matches('-').to_owned()) .map(Cow::Owned) .or_else(|| { // Put aside RUSTC_LINKER's prefix to be used as second choice, after CROSS_COMPILE self.getenv("RUSTC_LINKER").and_then(|var| { var.to_string_lossy() .strip_suffix("-gcc") .map(str::to_string) .map(Cow::Owned) }) }) .or_else(|| { match target { // Note: there is no `aarch64-pc-windows-gnu` target, only `-gnullvm` "aarch64-pc-windows-gnullvm" => Some("aarch64-w64-mingw32"), "aarch64-uwp-windows-gnu" => Some("aarch64-w64-mingw32"), "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu"), "aarch64-unknown-linux-musl" => Some("aarch64-linux-musl"), "aarch64-unknown-netbsd" => Some("aarch64--netbsd"), "arm-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv4t-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv5te-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv5te-unknown-linux-musleabi" => Some("arm-linux-gnueabi"), "arm-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "arm-unknown-linux-musleabi" => Some("arm-linux-musleabi"), "arm-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "arm-unknown-netbsd-eabi" => Some("arm--netbsdelf-eabi"), "armv6-unknown-netbsd-eabihf" => Some("armv6--netbsdelf-eabihf"), "armv7-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "armv7neon-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "armv7neon-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "thumbv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "thumbv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "thumbv7neon-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "thumbv7neon-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "armv7-unknown-netbsd-eabihf" => Some("armv7--netbsdelf-eabihf"), "hexagon-unknown-linux-musl" => Some("hexagon-linux-musl"), "i586-unknown-linux-musl" => Some("musl"), "i686-pc-windows-gnu" => Some("i686-w64-mingw32"), "i686-pc-windows-gnullvm" => Some("i686-w64-mingw32"), "i686-uwp-windows-gnu" => Some("i686-w64-mingw32"), "i686-unknown-linux-gnu" => self.find_working_gnu_prefix(&[ "i686-linux-gnu", "x86_64-linux-gnu", // transparently support gcc-multilib ]), // explicit None if not found, so caller knows to fall back "i686-unknown-linux-musl" => Some("musl"), "i686-unknown-netbsd" => Some("i486--netbsdelf"), "loongarch64-unknown-linux-gnu" => Some("loongarch64-linux-gnu"), "mips-unknown-linux-gnu" => Some("mips-linux-gnu"), "mips-unknown-linux-musl" => Some("mips-linux-musl"), "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"), "mipsel-unknown-linux-musl" => Some("mipsel-linux-musl"), "mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"), "mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"), "mipsisa32r6-unknown-linux-gnu" => Some("mipsisa32r6-linux-gnu"), "mipsisa32r6el-unknown-linux-gnu" => Some("mipsisa32r6el-linux-gnu"), "mipsisa64r6-unknown-linux-gnuabi64" => Some("mipsisa64r6-linux-gnuabi64"), "mipsisa64r6el-unknown-linux-gnuabi64" => Some("mipsisa64r6el-linux-gnuabi64"), "powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"), "powerpc-unknown-linux-gnuspe" => Some("powerpc-linux-gnuspe"), "powerpc-unknown-netbsd" => Some("powerpc--netbsd"), "powerpc64-unknown-linux-gnu" => Some("powerpc64-linux-gnu"), "powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"), "riscv32i-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv32-unknown-elf", "riscv64-unknown-elf", "riscv-none-embed", ]), "riscv32imac-esp-espidf" => Some("riscv32-esp-elf"), "riscv32imac-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv32-unknown-elf", "riscv64-unknown-elf", "riscv-none-embed", ]), "riscv32imac-unknown-xous-elf" => self.find_working_gnu_prefix(&[ "riscv32-unknown-elf", "riscv64-unknown-elf", "riscv-none-embed", ]), "riscv32imc-esp-espidf" => Some("riscv32-esp-elf"), "riscv32imc-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv32-unknown-elf", "riscv64-unknown-elf", "riscv-none-embed", ]), "riscv64gc-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed", ]), "riscv64imac-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed", ]), "riscv64gc-unknown-linux-gnu" => Some("riscv64-linux-gnu"), "riscv32gc-unknown-linux-gnu" => Some("riscv32-linux-gnu"), "riscv64gc-unknown-linux-musl" => Some("riscv64-linux-musl"), "riscv32gc-unknown-linux-musl" => Some("riscv32-linux-musl"), "riscv64gc-unknown-netbsd" => Some("riscv64--netbsd"), "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"), "sparc-unknown-linux-gnu" => Some("sparc-linux-gnu"), "sparc64-unknown-linux-gnu" => Some("sparc64-linux-gnu"), "sparc64-unknown-netbsd" => Some("sparc64--netbsd"), "sparcv9-sun-solaris" => Some("sparcv9-sun-solaris"), "armv7a-none-eabi" => Some("arm-none-eabi"), "armv7a-none-eabihf" => Some("arm-none-eabi"), "armebv7r-none-eabi" => Some("arm-none-eabi"), "armebv7r-none-eabihf" => Some("arm-none-eabi"), "armv7r-none-eabi" => Some("arm-none-eabi"), "armv7r-none-eabihf" => Some("arm-none-eabi"), "armv8r-none-eabihf" => Some("arm-none-eabi"), "thumbv6m-none-eabi" => Some("arm-none-eabi"), "thumbv7em-none-eabi" => Some("arm-none-eabi"), "thumbv7em-none-eabihf" => Some("arm-none-eabi"), "thumbv7m-none-eabi" => Some("arm-none-eabi"), "thumbv8m.base-none-eabi" => Some("arm-none-eabi"), "thumbv8m.main-none-eabi" => Some("arm-none-eabi"), "thumbv8m.main-none-eabihf" => Some("arm-none-eabi"), "x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"), "x86_64-pc-windows-gnullvm" => Some("x86_64-w64-mingw32"), "x86_64-uwp-windows-gnu" => Some("x86_64-w64-mingw32"), "x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"), "x86_64-unknown-linux-gnu" => self.find_working_gnu_prefix(&[ "x86_64-linux-gnu", // rustfmt wrap ]), // explicit None if not found, so caller knows to fall back "x86_64-unknown-linux-musl" => { self.find_working_gnu_prefix(&["x86_64-linux-musl", "musl"]) } "x86_64-unknown-netbsd" => Some("x86_64--netbsd"), _ => None, } .map(Cow::Borrowed) }) } /// Some platforms have multiple, compatible, canonical prefixes. Look through /// each possible prefix for a compiler that exists and return it. The prefixes /// should be ordered from most-likely to least-likely. fn find_working_gnu_prefix(&self, prefixes: &[&'static str]) -> Option<&'static str> { let suffix = if self.cpp { "-g++" } else { "-gcc" }; let extension = std::env::consts::EXE_SUFFIX; // Loop through PATH entries searching for each toolchain. This ensures that we // are more likely to discover the toolchain early on, because chances are good // that the desired toolchain is in one of the higher-priority paths. self.getenv("PATH") .as_ref() .and_then(|path_entries| { env::split_paths(path_entries).find_map(|path_entry| { for prefix in prefixes { let target_compiler = format!("{}{}{}", prefix, suffix, extension); if path_entry.join(&target_compiler).exists() { return Some(prefix); } } None }) }) .copied() // If no toolchain was found, provide the first toolchain that was passed in. // This toolchain has been shown not to exist, however it will appear in the // error that is shown to the user which should make it easier to search for // where it should be obtained. .or_else(|| prefixes.first().copied()) } fn get_target(&self) -> Result, Error> { match &self.target { Some(t) if Some(&**t) != self.getenv_unwrap_str("TARGET").ok().as_deref() => { TargetInfo::from_rustc_target(t) } // Fetch target information from environment if not set, or if the // target was the same as the TARGET environment variable, in // case the user did `build.target(&env::var("TARGET").unwrap())`. _ => self .build_cache .target_info_parser .parse_from_cargo_environment_variables(), } } fn get_raw_target(&self) -> Result, Error> { match &self.target { Some(t) => Ok(Cow::Borrowed(t)), None => self.getenv_unwrap_str("TARGET").map(Cow::Owned), } } fn get_is_cross_compile(&self) -> Result { let target = self.get_raw_target()?; let host: Cow<'_, str> = match &self.host { Some(h) => Cow::Borrowed(h), None => Cow::Owned(self.getenv_unwrap_str("HOST")?), }; Ok(host != target) } fn get_opt_level(&self) -> Result, Error> { match &self.opt_level { Some(ol) => Ok(Cow::Borrowed(ol)), None => self.getenv_unwrap_str("OPT_LEVEL").map(Cow::Owned), } } fn get_debug(&self) -> bool { self.debug.unwrap_or_else(|| self.getenv_boolean("DEBUG")) } fn get_shell_escaped_flags(&self) -> bool { self.shell_escaped_flags .unwrap_or_else(|| self.getenv_boolean("CC_SHELL_ESCAPED_FLAGS")) } fn get_dwarf_version(&self) -> Option { // Tentatively matches the DWARF version defaults as of rustc 1.62. let target = self.get_target().ok()?; if matches!( target.os, "android" | "dragonfly" | "freebsd" | "netbsd" | "openbsd" ) || target.vendor == "apple" || (target.os == "windows" && target.env == "gnu") { Some(2) } else if target.os == "linux" { Some(4) } else { None } } fn get_force_frame_pointer(&self) -> bool { self.force_frame_pointer.unwrap_or_else(|| self.get_debug()) } fn get_out_dir(&self) -> Result, Error> { match &self.out_dir { Some(p) => Ok(Cow::Borrowed(&**p)), None => self .getenv("OUT_DIR") .as_deref() .map(PathBuf::from) .map(Cow::Owned) .ok_or_else(|| { Error::new( ErrorKind::EnvVarNotFound, "Environment variable OUT_DIR not defined.", ) }), } } #[allow(clippy::disallowed_methods)] fn getenv(&self, v: &str) -> Option> { // Returns true for environment variables cargo sets for build scripts: // https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts // // This handles more of the vars than we actually use (it tries to check // complete-ish set), just to avoid needing maintenance if/when new // calls to `getenv`/`getenv_unwrap` are added. fn provided_by_cargo(envvar: &str) -> bool { match envvar { v if v.starts_with("CARGO") || v.starts_with("RUSTC") => true, "HOST" | "TARGET" | "RUSTDOC" | "OUT_DIR" | "OPT_LEVEL" | "DEBUG" | "PROFILE" | "NUM_JOBS" | "RUSTFLAGS" => true, _ => false, } } if let Some(val) = self.build_cache.env_cache.read().unwrap().get(v).cloned() { return val; } // Excluding `PATH` prevents spurious rebuilds on Windows, see // for details. if self.emit_rerun_if_env_changed && !provided_by_cargo(v) && v != "PATH" { self.cargo_output .print_metadata(&format_args!("cargo:rerun-if-env-changed={}", v)); } let r = env::var_os(v).map(Arc::from); self.cargo_output.print_metadata(&format_args!( "{} = {}", v, OptionOsStrDisplay(r.as_deref()) )); self.build_cache .env_cache .write() .unwrap() .insert(v.into(), r.clone()); r } /// get boolean flag that is either true or false fn getenv_boolean(&self, v: &str) -> bool { match self.getenv(v) { Some(s) => &*s != "0" && &*s != "false" && !s.is_empty(), None => false, } } fn getenv_unwrap(&self, v: &str) -> Result, Error> { match self.getenv(v) { Some(s) => Ok(s), None => Err(Error::new( ErrorKind::EnvVarNotFound, format!("Environment variable {} not defined.", v), )), } } fn getenv_unwrap_str(&self, v: &str) -> Result { let env = self.getenv_unwrap(v)?; env.to_str().map(String::from).ok_or_else(|| { Error::new( ErrorKind::EnvVarNotFound, format!("Environment variable {} is not valid utf-8.", v), ) }) } /// The list of environment variables to check for a given env, in order of priority. fn target_envs(&self, env: &str) -> Result<[String; 4], Error> { let target = self.get_raw_target()?; let kind = if self.get_is_cross_compile()? { "TARGET" } else { "HOST" }; let target_u = target.replace('-', "_"); Ok([ format!("{env}_{target}"), format!("{env}_{target_u}"), format!("{kind}_{env}"), env.to_string(), ]) } /// Get a single-valued environment variable with target variants. fn getenv_with_target_prefixes(&self, env: &str) -> Result, Error> { // Take from first environment variable in the environment. let res = self .target_envs(env)? .iter() .filter_map(|env| self.getenv(env)) .next(); match res { Some(res) => Ok(res), None => Err(Error::new( ErrorKind::EnvVarNotFound, format!("could not find environment variable {env}"), )), } } /// Get values from CFLAGS-style environment variable. fn envflags(&self, env: &str) -> Result>, Error> { // Collect from all environment variables, in reverse order as in // `getenv_with_target_prefixes` precedence (so that `CFLAGS_$TARGET` // can override flags in `TARGET_CFLAGS`, which overrides those in // `CFLAGS`). let mut any_set = false; let mut res = vec![]; for env in self.target_envs(env)?.iter().rev() { if let Some(var) = self.getenv(env) { any_set = true; let var = var.to_string_lossy(); if self.get_shell_escaped_flags() { res.extend(Shlex::new(&var)); } else { res.extend(var.split_ascii_whitespace().map(ToString::to_string)); } } } Ok(if any_set { Some(res) } else { None }) } fn fix_env_for_apple_os(&self, cmd: &mut Command) -> Result<(), Error> { let target = self.get_target()?; if cfg!(target_os = "macos") && target.os == "macos" { // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld", // although this is apparently ignored when using the linker at "/usr/bin/ld". cmd.env_remove("IPHONEOS_DEPLOYMENT_TARGET"); } Ok(()) } fn apple_sdk_root_inner(&self, sdk: &str) -> Result, Error> { // Code copied from rustc's compiler/rustc_codegen_ssa/src/back/link.rs. if let Some(sdkroot) = self.getenv("SDKROOT") { let p = Path::new(&sdkroot); let does_sdkroot_contain = |strings: &[&str]| { let sdkroot_str = p.to_string_lossy(); strings.iter().any(|s| sdkroot_str.contains(s)) }; match sdk { // Ignore `SDKROOT` if it's clearly set for the wrong platform. "appletvos" if does_sdkroot_contain(&["TVSimulator.platform", "MacOSX.platform"]) => {} "appletvsimulator" if does_sdkroot_contain(&["TVOS.platform", "MacOSX.platform"]) => {} "iphoneos" if does_sdkroot_contain(&["iPhoneSimulator.platform", "MacOSX.platform"]) => {} "iphonesimulator" if does_sdkroot_contain(&["iPhoneOS.platform", "MacOSX.platform"]) => {} "macosx10.15" if does_sdkroot_contain(&["iPhoneOS.platform", "iPhoneSimulator.platform"]) => { } "watchos" if does_sdkroot_contain(&["WatchSimulator.platform", "MacOSX.platform"]) => {} "watchsimulator" if does_sdkroot_contain(&["WatchOS.platform", "MacOSX.platform"]) => {} "xros" if does_sdkroot_contain(&["XRSimulator.platform", "MacOSX.platform"]) => {} "xrsimulator" if does_sdkroot_contain(&["XROS.platform", "MacOSX.platform"]) => {} // Ignore `SDKROOT` if it's not a valid path. _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} _ => return Ok(sdkroot), } } let sdk_path = run_output( self.cmd("xcrun") .arg("--show-sdk-path") .arg("--sdk") .arg(sdk), &self.cargo_output, )?; let sdk_path = match String::from_utf8(sdk_path) { Ok(p) => p, Err(_) => { return Err(Error::new( ErrorKind::IOError, "Unable to determine Apple SDK path.", )); } }; Ok(Arc::from(OsStr::new(sdk_path.trim()))) } fn apple_sdk_root(&self, target: &TargetInfo<'_>) -> Result, Error> { let sdk = target.apple_sdk_name(); if let Some(ret) = self .build_cache .apple_sdk_root_cache .read() .expect("apple_sdk_root_cache lock failed") .get(sdk) .cloned() { return Ok(ret); } let sdk_path = self.apple_sdk_root_inner(sdk)?; self.build_cache .apple_sdk_root_cache .write() .expect("apple_sdk_root_cache lock failed") .insert(sdk.into(), sdk_path.clone()); Ok(sdk_path) } fn apple_deployment_target(&self, target: &TargetInfo<'_>) -> Arc { let sdk = target.apple_sdk_name(); if let Some(ret) = self .build_cache .apple_versions_cache .read() .expect("apple_versions_cache lock failed") .get(sdk) .cloned() { return ret; } let default_deployment_from_sdk = || -> Option> { let version = run_output( self.cmd("xcrun") .arg("--show-sdk-version") .arg("--sdk") .arg(sdk), &self.cargo_output, ) .ok()?; Some(Arc::from(std::str::from_utf8(&version).ok()?.trim())) }; let deployment_from_env = |name: &str| -> Option> { // note that self.env isn't hit in production codepaths, its mostly just for tests which don't // set the real env self.env .iter() .find(|(k, _)| &**k == OsStr::new(name)) .map(|(_, v)| v) .cloned() .or_else(|| self.getenv(name))? .to_str() .map(Arc::from) }; // Determines if the acquired deployment target is too low to support modern C++ on some Apple platform. // // A long time ago they used libstdc++, but since macOS 10.9 and iOS 7 libc++ has been the library the SDKs provide to link against. // If a `cc`` config wants to use C++, we round up to these versions as the baseline. let maybe_cpp_version_baseline = |deployment_target_ver: Arc| -> Option> { if !self.cpp { return Some(deployment_target_ver); } let mut deployment_target = deployment_target_ver .split('.') .map(|v| v.parse::().expect("integer version")); match target.os { "macos" => { let major = deployment_target.next().unwrap_or(0); let minor = deployment_target.next().unwrap_or(0); // If below 10.9, we ignore it and let the SDK's target definitions handle it. if major == 10 && minor < 9 { self.cargo_output.print_warning(&format_args!( "macOS deployment target ({}) too low, it will be increased", deployment_target_ver )); return None; } } "ios" => { let major = deployment_target.next().unwrap_or(0); // If below 10.7, we ignore it and let the SDK's target definitions handle it. if major < 7 { self.cargo_output.print_warning(&format_args!( "iOS deployment target ({}) too low, it will be increased", deployment_target_ver )); return None; } } // watchOS, tvOS, visionOS, and others are all new enough that libc++ is their baseline. _ => {} } // If the deployment target met or exceeded the C++ baseline Some(deployment_target_ver) }; // The hardcoded minimums here are subject to change in a future compiler release, // and only exist as last resort fallbacks. Don't consider them stable. // `cc` doesn't use rustc's `--print deployment-target`` because the compiler's defaults // don't align well with Apple's SDKs and other third-party libraries that require ~generally~ higher // deployment targets. rustc isn't interested in those by default though so its fine to be different here. // // If no explicit target is passed, `cc` defaults to the current Xcode SDK's `DefaultDeploymentTarget` for better // compatibility. This is also the crate's historical behavior and what has become a relied-on value. // // The ordering of env -> XCode SDK -> old rustc defaults is intentional for performance when using // an explicit target. let version: Arc = match target.os { "macos" => deployment_from_env("MACOSX_DEPLOYMENT_TARGET") .and_then(maybe_cpp_version_baseline) .or_else(default_deployment_from_sdk) .unwrap_or_else(|| { if target.arch == "aarch64" { "11.0".into() } else { let default: Arc = Arc::from("10.7"); maybe_cpp_version_baseline(default.clone()).unwrap_or(default) } }), "ios" => deployment_from_env("IPHONEOS_DEPLOYMENT_TARGET") .and_then(maybe_cpp_version_baseline) .or_else(default_deployment_from_sdk) .unwrap_or_else(|| "7.0".into()), "watchos" => deployment_from_env("WATCHOS_DEPLOYMENT_TARGET") .or_else(default_deployment_from_sdk) .unwrap_or_else(|| "5.0".into()), "tvos" => deployment_from_env("TVOS_DEPLOYMENT_TARGET") .or_else(default_deployment_from_sdk) .unwrap_or_else(|| "9.0".into()), "visionos" => deployment_from_env("XROS_DEPLOYMENT_TARGET") .or_else(default_deployment_from_sdk) .unwrap_or_else(|| "1.0".into()), os => unreachable!("unknown Apple OS: {}", os), }; self.build_cache .apple_versions_cache .write() .expect("apple_versions_cache lock failed") .insert(sdk.into(), version.clone()); version } fn wasm_musl_sysroot(&self) -> Result, Error> { if let Some(musl_sysroot_path) = self.getenv("WASM_MUSL_SYSROOT") { Ok(musl_sysroot_path) } else { Err(Error::new( ErrorKind::EnvVarNotFound, "Environment variable WASM_MUSL_SYSROOT not defined for wasm32. Download sysroot from GitHub & setup environment variable MUSL_SYSROOT targeting the folder.", )) } } fn wasi_sysroot(&self) -> Result, Error> { if let Some(wasi_sysroot_path) = self.getenv("WASI_SYSROOT") { Ok(wasi_sysroot_path) } else { Err(Error::new( ErrorKind::EnvVarNotFound, "Environment variable WASI_SYSROOT not defined. Download sysroot from GitHub & setup environment variable WASI_SYSROOT targeting the folder.", )) } } fn cuda_file_count(&self) -> usize { self.files .iter() .filter(|file| file.extension() == Some(OsStr::new("cu"))) .count() } fn which(&self, tool: &Path, path_entries: Option<&OsStr>) -> Option { fn check_exe(mut exe: PathBuf) -> Option { let exe_ext = std::env::consts::EXE_EXTENSION; let check = exe.exists() || (!exe_ext.is_empty() && exe.set_extension(exe_ext) && exe.exists()); check.then_some(exe) } // Loop through PATH entries searching for the |tool|. let find_exe_in_path = |path_entries: &OsStr| -> Option { env::split_paths(path_entries).find_map(|path_entry| check_exe(path_entry.join(tool))) }; // If |tool| is not just one "word," assume it's an actual path... if tool.components().count() > 1 { check_exe(PathBuf::from(tool)) } else { path_entries .and_then(find_exe_in_path) .or_else(|| find_exe_in_path(&self.getenv("PATH")?)) } } /// search for |prog| on 'programs' path in '|cc| -print-search-dirs' output fn search_programs( &self, cc: &mut Command, prog: &Path, cargo_output: &CargoOutput, ) -> Option { let search_dirs = run_output( cc.arg("-print-search-dirs"), // this doesn't concern the compilation so we always want to show warnings. cargo_output, ) .ok()?; // clang driver appears to be forcing UTF-8 output even on Windows, // hence from_utf8 is assumed to be usable in all cases. let search_dirs = std::str::from_utf8(&search_dirs).ok()?; for dirs in search_dirs.split(['\r', '\n']) { if let Some(path) = dirs.strip_prefix("programs: =") { return self.which(prog, Some(OsStr::new(path))); } } None } fn windows_registry_find(&self, target: &TargetInfo<'_>, tool: &str) -> Option { self.windows_registry_find_tool(target, tool) .map(|c| c.to_command()) } fn windows_registry_find_tool(&self, target: &TargetInfo<'_>, tool: &str) -> Option { struct BuildEnvGetter<'s>(&'s Build); impl windows_registry::EnvGetter for BuildEnvGetter<'_> { fn get_env(&self, name: &str) -> Option { self.0.getenv(name).map(windows_registry::Env::Arced) } } if target.env != "msvc" { return None; } windows_registry::find_tool_inner(target.full_arch, tool, &BuildEnvGetter(self)) } } impl Default for Build { fn default() -> Build { Build::new() } } fn fail(s: &str) -> ! { eprintln!("\n\nerror occurred in cc-rs: {}\n\n", s); std::process::exit(1); } // Use by default minimum available API level // See note about naming here // https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/docs/BuildSystemMaintainers.md#Clang static NEW_STANDALONE_ANDROID_COMPILERS: [&str; 4] = [ "aarch64-linux-android21-clang", "armv7a-linux-androideabi16-clang", "i686-linux-android16-clang", "x86_64-linux-android21-clang", ]; // New "standalone" C/C++ cross-compiler executables from recent Android NDK // are just shell scripts that call main clang binary (from Android NDK) with // proper `--target` argument. // // For example, armv7a-linux-androideabi16-clang passes // `--target=armv7a-linux-androideabi16` to clang. // So to construct proper command line check if // `--target` argument would be passed or not to clang fn android_clang_compiler_uses_target_arg_internally(clang_path: &Path) -> bool { if let Some(filename) = clang_path.file_name() { if let Some(filename_str) = filename.to_str() { if let Some(idx) = filename_str.rfind('-') { return filename_str.split_at(idx).0.contains("android"); } } } false } // FIXME: Use parsed target. fn autodetect_android_compiler(raw_target: &str, gnu: &str, clang: &str) -> String { let new_clang_key = match raw_target { "aarch64-linux-android" => Some("aarch64"), "armv7-linux-androideabi" => Some("armv7a"), "i686-linux-android" => Some("i686"), "x86_64-linux-android" => Some("x86_64"), _ => None, }; let new_clang = new_clang_key .map(|key| { NEW_STANDALONE_ANDROID_COMPILERS .iter() .find(|x| x.starts_with(key)) }) .unwrap_or(None); if let Some(new_clang) = new_clang { if Command::new(new_clang).output().is_ok() { return (*new_clang).into(); } } let target = raw_target .replace("armv7neon", "arm") .replace("armv7", "arm") .replace("thumbv7neon", "arm") .replace("thumbv7", "arm"); let gnu_compiler = format!("{}-{}", target, gnu); let clang_compiler = format!("{}-{}", target, clang); // On Windows, the Android clang compiler is provided as a `.cmd` file instead // of a `.exe` file. `std::process::Command` won't run `.cmd` files unless the // `.cmd` is explicitly appended to the command name, so we do that here. let clang_compiler_cmd = format!("{}-{}.cmd", target, clang); // Check if gnu compiler is present // if not, use clang if Command::new(&gnu_compiler).output().is_ok() { gnu_compiler } else if cfg!(windows) && Command::new(&clang_compiler_cmd).output().is_ok() { clang_compiler_cmd } else { clang_compiler } } // Rust and clang/cc don't agree on how to name the target. fn map_darwin_target_from_rust_to_compiler_architecture<'a>(target: &TargetInfo<'a>) -> &'a str { match target.full_arch { "aarch64" => "arm64", "arm64_32" => "arm64_32", "arm64e" => "arm64e", "armv7k" => "armv7k", "armv7s" => "armv7s", "i386" => "i386", "i686" => "i386", "powerpc" => "ppc", "powerpc64" => "ppc64", "x86_64" => "x86_64", "x86_64h" => "x86_64h", arch => arch, } } #[derive(Clone, Copy, PartialEq)] enum AsmFileExt { /// `.asm` files. On MSVC targets, we assume these should be passed to MASM /// (`ml{,64}.exe`). DotAsm, /// `.s` or `.S` files, which do not have the special handling on MSVC targets. DotS, } impl AsmFileExt { fn from_path(file: &Path) -> Option { if let Some(ext) = file.extension() { if let Some(ext) = ext.to_str() { let ext = ext.to_lowercase(); match &*ext { "asm" => return Some(AsmFileExt::DotAsm), "s" => return Some(AsmFileExt::DotS), _ => return None, } } } None } } /// Returns true if `cc` has been disabled by `CC_FORCE_DISABLE`. fn is_disabled() -> bool { static CACHE: AtomicU8 = AtomicU8::new(0); let val = CACHE.load(Relaxed); // We manually cache the environment var, since we need it in some places // where we don't have access to a `Build` instance. #[allow(clippy::disallowed_methods)] fn compute_is_disabled() -> bool { match std::env::var_os("CC_FORCE_DISABLE") { // Not set? Not disabled. None => false, // Respect `CC_FORCE_DISABLE=0` and some simple synonyms, otherwise // we're disabled. This intentionally includes `CC_FORCE_DISABLE=""` Some(v) => &*v != "0" && &*v != "false" && &*v != "no", } } match val { 2 => true, 1 => false, 0 => { let truth = compute_is_disabled(); let encoded_truth = if truth { 2u8 } else { 1 }; // Might race against another thread, but we'd both be setting the // same value so it should be fine. CACHE.store(encoded_truth, Relaxed); truth } _ => unreachable!(), } } /// Automates the `if is_disabled() { return error }` check and ensures /// we produce a consistent error message for it. fn check_disabled() -> Result<(), Error> { if is_disabled() { return Err(Error::new( ErrorKind::Disabled, "the `cc` crate's functionality has been disabled by the `CC_FORCE_DISABLE` environment variable." )); } Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn test_android_clang_compiler_uses_target_arg_internally() { for version in 16..21 { assert!(android_clang_compiler_uses_target_arg_internally( &PathBuf::from(format!("armv7a-linux-androideabi{}-clang", version)) )); assert!(android_clang_compiler_uses_target_arg_internally( &PathBuf::from(format!("armv7a-linux-androideabi{}-clang++", version)) )); } assert!(!android_clang_compiler_uses_target_arg_internally( &PathBuf::from("clang-i686-linux-android") )); assert!(!android_clang_compiler_uses_target_arg_internally( &PathBuf::from("clang") )); assert!(!android_clang_compiler_uses_target_arg_internally( &PathBuf::from("clang++") )); } } cc/src/command_helpers.rs0000644000175000017500000003624415105742312015275 0ustar bdrungbdrung//! Miscellaneous helpers for running commands use std::{ borrow::Cow, collections::hash_map, ffi::OsString, fmt::Display, fs, hash::Hasher, io::{self, Read, Write}, path::Path, process::{Child, ChildStderr, Command, Stdio}, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, }; use crate::{Error, ErrorKind, Object}; #[derive(Clone, Debug)] pub(crate) struct CargoOutput { pub(crate) metadata: bool, pub(crate) warnings: bool, pub(crate) debug: bool, pub(crate) output: OutputKind, checked_dbg_var: Arc, } /// Different strategies for handling compiler output (to stdout) #[derive(Clone, Debug)] pub(crate) enum OutputKind { /// Forward the output to this process' stdout ([`Stdio::inherit()`]) Forward, /// Discard the output ([`Stdio::null()`]) Discard, /// Capture the result (`[Stdio::piped()`]) Capture, } impl CargoOutput { pub(crate) fn new() -> Self { #[allow(clippy::disallowed_methods)] Self { metadata: true, warnings: true, output: OutputKind::Forward, debug: match std::env::var_os("CC_ENABLE_DEBUG_OUTPUT") { Some(v) => v != "0" && v != "false" && !v.is_empty(), None => false, }, checked_dbg_var: Arc::new(AtomicBool::new(false)), } } pub(crate) fn print_metadata(&self, s: &dyn Display) { if self.metadata { println!("{}", s); } } pub(crate) fn print_warning(&self, arg: &dyn Display) { if self.warnings { println!("cargo:warning={}", arg); } } pub(crate) fn print_debug(&self, arg: &dyn Display) { if self.metadata && !self.checked_dbg_var.load(Ordering::Relaxed) { self.checked_dbg_var.store(true, Ordering::Relaxed); println!("cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT"); } if self.debug { println!("{}", arg); } } fn stdio_for_warnings(&self) -> Stdio { if self.warnings { Stdio::piped() } else { Stdio::null() } } fn stdio_for_output(&self) -> Stdio { match self.output { OutputKind::Capture => Stdio::piped(), OutputKind::Forward => Stdio::inherit(), OutputKind::Discard => Stdio::null(), } } } pub(crate) struct StderrForwarder { inner: Option<(ChildStderr, Vec)>, #[cfg(feature = "parallel")] is_non_blocking: bool, #[cfg(feature = "parallel")] bytes_available_failed: bool, /// number of bytes buffered in inner bytes_buffered: usize, } const MIN_BUFFER_CAPACITY: usize = 100; impl StderrForwarder { pub(crate) fn new(child: &mut Child) -> Self { Self { inner: child .stderr .take() .map(|stderr| (stderr, Vec::with_capacity(MIN_BUFFER_CAPACITY))), bytes_buffered: 0, #[cfg(feature = "parallel")] is_non_blocking: false, #[cfg(feature = "parallel")] bytes_available_failed: false, } } fn forward_available(&mut self) -> bool { if let Some((stderr, buffer)) = self.inner.as_mut() { loop { // For non-blocking we check to see if there is data available, so we should try to // read at least that much. For blocking, always read at least the minimum amount. #[cfg(not(feature = "parallel"))] let to_reserve = MIN_BUFFER_CAPACITY; #[cfg(feature = "parallel")] let to_reserve = if self.is_non_blocking && !self.bytes_available_failed { match crate::parallel::stderr::bytes_available(stderr) { #[cfg(windows)] Ok(0) => break false, #[cfg(unix)] Ok(0) => { // On Unix, depending on the implementation, we may sometimes get 0 in a // loop (either there is data available or the pipe is broken), so // continue with the non-blocking read anyway. MIN_BUFFER_CAPACITY } #[cfg(windows)] Err(_) => { // On Windows, if we get an error then the pipe is broken, so flush // the buffer and bail. if !buffer.is_empty() { write_warning(&buffer[..]); } self.inner = None; break true; } #[cfg(unix)] Err(_) => { // On Unix, depending on the implementation, we may get spurious // errors so make a note not to use bytes_available again and try // the non-blocking read anyway. self.bytes_available_failed = true; MIN_BUFFER_CAPACITY } #[cfg(target_family = "wasm")] Err(_) => panic!("bytes_available should always succeed on wasm"), Ok(bytes_available) => MIN_BUFFER_CAPACITY.max(bytes_available), } } else { MIN_BUFFER_CAPACITY }; if self.bytes_buffered + to_reserve > buffer.len() { buffer.resize(self.bytes_buffered + to_reserve, 0); } match stderr.read(&mut buffer[self.bytes_buffered..]) { Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { // No data currently, yield back. break false; } Err(err) if err.kind() == std::io::ErrorKind::Interrupted => { // Interrupted, try again. continue; } Ok(bytes_read) if bytes_read != 0 => { self.bytes_buffered += bytes_read; let mut consumed = 0; for line in buffer[..self.bytes_buffered].split_inclusive(|&b| b == b'\n') { // Only forward complete lines, leave the rest in the buffer. if let Some((b'\n', line)) = line.split_last() { consumed += line.len() + 1; write_warning(line); } } if consumed > 0 && consumed < self.bytes_buffered { // Remove the consumed bytes from buffer buffer.copy_within(consumed.., 0); } self.bytes_buffered -= consumed; } res => { // End of stream: flush remaining data and bail. if self.bytes_buffered > 0 { write_warning(&buffer[..self.bytes_buffered]); } if let Err(err) = res { write_warning( format!("Failed to read from child stderr: {err}").as_bytes(), ); } self.inner.take(); break true; } } } } else { true } } #[cfg(feature = "parallel")] pub(crate) fn set_non_blocking(&mut self) -> Result<(), Error> { assert!(!self.is_non_blocking); #[cfg(unix)] if let Some((stderr, _)) = self.inner.as_ref() { crate::parallel::stderr::set_non_blocking(stderr)?; } self.is_non_blocking = true; Ok(()) } #[cfg(feature = "parallel")] fn forward_all(&mut self) { while !self.forward_available() {} } #[cfg(not(feature = "parallel"))] fn forward_all(&mut self) { let forward_result = self.forward_available(); assert!(forward_result, "Should have consumed all data"); } } fn write_warning(line: &[u8]) { let stdout = io::stdout(); let mut stdout = stdout.lock(); stdout.write_all(b"cargo:warning=").unwrap(); stdout.write_all(line).unwrap(); stdout.write_all(b"\n").unwrap(); } fn wait_on_child( cmd: &Command, child: &mut Child, cargo_output: &CargoOutput, ) -> Result<(), Error> { StderrForwarder::new(child).forward_all(); let status = match child.wait() { Ok(s) => s, Err(e) => { return Err(Error::new( ErrorKind::ToolExecError, format!("failed to wait on spawned child process `{cmd:?}`: {e}"), )); } }; cargo_output.print_debug(&status); if status.success() { Ok(()) } else { Err(Error::new( ErrorKind::ToolExecError, format!("command did not execute successfully (status code {status}): {cmd:?}"), )) } } /// Find the destination object path for each file in the input source files, /// and store them in the output Object. pub(crate) fn objects_from_files(files: &[Arc], dst: &Path) -> Result, Error> { let mut objects = Vec::with_capacity(files.len()); for file in files { let basename = file .file_name() .ok_or_else(|| { Error::new( ErrorKind::InvalidArgument, "No file_name for object file path!", ) })? .to_string_lossy(); let dirname = file .parent() .ok_or_else(|| { Error::new( ErrorKind::InvalidArgument, "No parent for object file path!", ) })? .to_string_lossy(); // Hash the dirname. This should prevent conflicts if we have multiple // object files with the same filename in different subfolders. let mut hasher = hash_map::DefaultHasher::new(); // Make the dirname relative (if possible) to avoid full system paths influencing the sha // and making the output system-dependent // // NOTE: Here we allow using std::env::var (instead of Build::getenv) because // CARGO_* variables always trigger a rebuild when changed #[allow(clippy::disallowed_methods)] let dirname = if let Some(root) = std::env::var_os("CARGO_MANIFEST_DIR") { let root = root.to_string_lossy(); Cow::Borrowed(dirname.strip_prefix(&*root).unwrap_or(&dirname)) } else { dirname }; hasher.write(dirname.as_bytes()); if let Some(extension) = file.extension() { hasher.write(extension.to_string_lossy().as_bytes()); } let obj = dst .join(format!("{:016x}-{}", hasher.finish(), basename)) .with_extension("o"); match obj.parent() { Some(s) => fs::create_dir_all(s)?, None => { return Err(Error::new( ErrorKind::InvalidArgument, "dst is an invalid path with no parent", )); } }; objects.push(Object::new(file.to_path_buf(), obj)); } Ok(objects) } pub(crate) fn run(cmd: &mut Command, cargo_output: &CargoOutput) -> Result<(), Error> { let mut child = spawn(cmd, cargo_output)?; wait_on_child(cmd, &mut child, cargo_output) } pub(crate) fn run_output(cmd: &mut Command, cargo_output: &CargoOutput) -> Result, Error> { // We specifically need the output to be captured, so override default let mut captured_cargo_output = cargo_output.clone(); captured_cargo_output.output = OutputKind::Capture; let mut child = spawn(cmd, &captured_cargo_output)?; let mut stdout = vec![]; child .stdout .take() .unwrap() .read_to_end(&mut stdout) .unwrap(); // Don't care about this output, use the normal settings wait_on_child(cmd, &mut child, cargo_output)?; Ok(stdout) } pub(crate) fn spawn(cmd: &mut Command, cargo_output: &CargoOutput) -> Result { struct ResetStderr<'cmd>(&'cmd mut Command); impl Drop for ResetStderr<'_> { fn drop(&mut self) { // Reset stderr to default to release pipe_writer so that print thread will // not block forever. self.0.stderr(Stdio::inherit()); } } cargo_output.print_debug(&format_args!("running: {:?}", cmd)); let cmd = ResetStderr(cmd); let child = cmd .0 .stderr(cargo_output.stdio_for_warnings()) .stdout(cargo_output.stdio_for_output()) .spawn(); match child { Ok(child) => Ok(child), Err(ref e) if e.kind() == io::ErrorKind::NotFound => { let extra = if cfg!(windows) { " (see https://docs.rs/cc/latest/cc/#compile-time-requirements for help)" } else { "" }; Err(Error::new( ErrorKind::ToolNotFound, format!("failed to find tool {:?}: {e}{extra}", cmd.0.get_program()), )) } Err(e) => Err(Error::new( ErrorKind::ToolExecError, format!("command `{:?}` failed to start: {e}", cmd.0), )), } } pub(crate) struct CmdAddOutputFileArgs { pub(crate) cuda: bool, pub(crate) is_assembler_msvc: bool, pub(crate) msvc: bool, pub(crate) clang: bool, pub(crate) gnu: bool, pub(crate) is_asm: bool, pub(crate) is_arm: bool, } pub(crate) fn command_add_output_file(cmd: &mut Command, dst: &Path, args: CmdAddOutputFileArgs) { if args.is_assembler_msvc || !(!args.msvc || args.clang || args.gnu || args.cuda || (args.is_asm && args.is_arm)) { let mut s = OsString::from("-Fo"); s.push(dst); cmd.arg(s); } else { cmd.arg("-o").arg(dst); } } #[cfg(feature = "parallel")] pub(crate) fn try_wait_on_child( cmd: &Command, child: &mut Child, stdout: &mut dyn io::Write, stderr_forwarder: &mut StderrForwarder, ) -> Result, Error> { stderr_forwarder.forward_available(); match child.try_wait() { Ok(Some(status)) => { stderr_forwarder.forward_all(); let _ = writeln!(stdout, "{}", status); if status.success() { Ok(Some(())) } else { Err(Error::new( ErrorKind::ToolExecError, format!("command did not execute successfully (status code {status}): {cmd:?}"), )) } } Ok(None) => Ok(None), Err(e) => { stderr_forwarder.forward_all(); Err(Error::new( ErrorKind::ToolExecError, format!("failed to wait on spawned child process `{cmd:?}`: {e}"), )) } } } cc/src/target/0000775000175000017500000000000015105742312013046 5ustar bdrungbdrungcc/src/target/generated.rs0000644000175000017500000004215015105742312015352 0ustar bdrungbdrung//! This file is generated code. Please edit the generator in //! dev-tools/gen-target-info if you need to make changes, or see //! src/target/llvm.rs if you need to configure a specific LLVM triple. #[rustfmt::skip] pub(crate) const LLVM_TARGETS: &[(&str, &str)] = &[ ("aarch64-apple-darwin", "arm64-apple-macosx"), ("aarch64-apple-ios", "arm64-apple-ios"), ("aarch64-apple-ios-macabi", "arm64-apple-ios-macabi"), ("aarch64-apple-ios-sim", "arm64-apple-ios-simulator"), ("aarch64-apple-tvos", "arm64-apple-tvos"), ("aarch64-apple-tvos-sim", "arm64-apple-tvos-simulator"), ("aarch64-apple-visionos", "arm64-apple-xros"), ("aarch64-apple-visionos-sim", "arm64-apple-xros-simulator"), ("aarch64-apple-watchos", "arm64-apple-watchos"), ("aarch64-apple-watchos-sim", "arm64-apple-watchos-simulator"), ("aarch64-fuchsia", "aarch64-fuchsia"), ("aarch64-kmc-solid_asp3", "aarch64-unknown-none"), ("aarch64-linux-android", "aarch64-linux-android"), ("aarch64-nintendo-switch-freestanding", "aarch64-unknown-none"), ("aarch64-pc-windows-gnullvm", "aarch64-pc-windows-gnu"), ("aarch64-pc-windows-msvc", "aarch64-pc-windows-msvc"), ("aarch64-unknown-freebsd", "aarch64-unknown-freebsd"), ("aarch64-unknown-fuchsia", "aarch64-unknown-fuchsia"), ("aarch64-unknown-hermit", "aarch64-unknown-hermit"), ("aarch64-unknown-illumos", "aarch64-unknown-solaris2.11"), ("aarch64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"), ("aarch64-unknown-linux-gnu_ilp32", "aarch64-unknown-linux-gnu_ilp32"), ("aarch64-unknown-linux-musl", "aarch64-unknown-linux-musl"), ("aarch64-unknown-linux-ohos", "aarch64-unknown-linux-ohos"), ("aarch64-unknown-netbsd", "aarch64-unknown-netbsd"), ("aarch64-unknown-none", "aarch64-unknown-none"), ("aarch64-unknown-none-softfloat", "aarch64-unknown-none"), ("aarch64-unknown-nto-qnx700", "aarch64-unknown-unknown"), ("aarch64-unknown-nto-qnx710", "aarch64-unknown-unknown"), ("aarch64-unknown-nto-qnx710_iosock", "aarch64-unknown-unknown"), ("aarch64-unknown-nto-qnx800", "aarch64-unknown-unknown"), ("aarch64-unknown-nuttx", "aarch64-unknown-none"), ("aarch64-unknown-openbsd", "aarch64-unknown-openbsd"), ("aarch64-unknown-redox", "aarch64-unknown-redox"), ("aarch64-unknown-teeos", "aarch64-unknown-none"), ("aarch64-unknown-trusty", "aarch64-unknown-unknown-musl"), ("aarch64-unknown-uefi", "aarch64-unknown-windows"), ("aarch64-uwp-windows-msvc", "aarch64-pc-windows-msvc"), ("aarch64-wrs-vxworks", "aarch64-unknown-linux-gnu"), ("aarch64_be-unknown-linux-gnu", "aarch64_be-unknown-linux-gnu"), ("aarch64_be-unknown-linux-gnu_ilp32", "aarch64_be-unknown-linux-gnu_ilp32"), ("aarch64_be-unknown-netbsd", "aarch64_be-unknown-netbsd"), ("amdgcn-amd-amdhsa", "amdgcn-amd-amdhsa"), ("arm-linux-androideabi", "arm-linux-androideabi"), ("arm-unknown-linux-gnueabi", "arm-unknown-linux-gnueabi"), ("arm-unknown-linux-gnueabihf", "arm-unknown-linux-gnueabihf"), ("arm-unknown-linux-musleabi", "arm-unknown-linux-musleabi"), ("arm-unknown-linux-musleabihf", "arm-unknown-linux-musleabihf"), ("arm64_32-apple-watchos", "arm64_32-apple-watchos"), ("arm64e-apple-darwin", "arm64e-apple-macosx"), ("arm64e-apple-ios", "arm64e-apple-ios"), ("arm64e-apple-tvos", "arm64e-apple-tvos"), ("arm64ec-pc-windows-msvc", "arm64ec-pc-windows-msvc"), ("armeb-unknown-linux-gnueabi", "armeb-unknown-linux-gnueabi"), ("armebv7r-none-eabi", "armebv7r-none-eabi"), ("armebv7r-none-eabihf", "armebv7r-none-eabihf"), ("armv4t-none-eabi", "armv4t-none-eabi"), ("armv4t-unknown-linux-gnueabi", "armv4t-unknown-linux-gnueabi"), ("armv5te-none-eabi", "armv5te-none-eabi"), ("armv5te-unknown-linux-gnueabi", "armv5te-unknown-linux-gnueabi"), ("armv5te-unknown-linux-musleabi", "armv5te-unknown-linux-musleabi"), ("armv5te-unknown-linux-uclibceabi", "armv5te-unknown-linux-gnueabi"), ("armv6-unknown-freebsd", "armv6-unknown-freebsd-gnueabihf"), ("armv6-unknown-netbsd-eabihf", "armv6-unknown-netbsdelf-eabihf"), ("armv6k-nintendo-3ds", "armv6k-none-eabihf"), ("armv7-apple-ios", "armv7-apple-ios7.0.0"), ("armv7-linux-androideabi", "armv7-none-linux-android"), ("armv7-rtems-eabihf", "armv7-unknown-none-eabihf"), ("armv7-sony-vita-newlibeabihf", "thumbv7a-sony-vita-eabihf"), ("armv7-unknown-freebsd", "armv7-unknown-freebsd-gnueabihf"), ("armv7-unknown-linux-gnueabi", "armv7-unknown-linux-gnueabi"), ("armv7-unknown-linux-gnueabihf", "armv7-unknown-linux-gnueabihf"), ("armv7-unknown-linux-musleabi", "armv7-unknown-linux-musleabi"), ("armv7-unknown-linux-musleabihf", "armv7-unknown-linux-musleabihf"), ("armv7-unknown-linux-ohos", "armv7-unknown-linux-ohos"), ("armv7-unknown-linux-uclibceabi", "armv7-unknown-linux-gnueabi"), ("armv7-unknown-linux-uclibceabihf", "armv7-unknown-linux-gnueabihf"), ("armv7-unknown-netbsd-eabihf", "armv7-unknown-netbsdelf-eabihf"), ("armv7-unknown-trusty", "armv7-unknown-unknown-gnueabi"), ("armv7-wrs-vxworks-eabihf", "armv7-unknown-linux-gnueabihf"), ("armv7a-kmc-solid_asp3-eabi", "armv7a-none-eabi"), ("armv7a-kmc-solid_asp3-eabihf", "armv7a-none-eabihf"), ("armv7a-none-eabi", "armv7a-none-eabi"), ("armv7a-none-eabihf", "armv7a-none-eabihf"), ("armv7a-nuttx-eabi", "armv7a-none-eabi"), ("armv7a-nuttx-eabihf", "armv7a-none-eabihf"), ("armv7k-apple-watchos", "armv7k-apple-watchos"), ("armv7r-none-eabi", "armv7r-none-eabi"), ("armv7r-none-eabihf", "armv7r-none-eabihf"), ("armv7s-apple-ios", "armv7s-apple-ios"), ("armv8r-none-eabihf", "armv8r-none-eabihf"), ("asmjs-unknown-emscripten", "wasm32-unknown-emscripten"), ("avr-none", "avr-unknown-unknown"), ("avr-unknown-gnu-atmega328", "avr-unknown-unknown"), ("bpfeb-unknown-none", "bpfeb"), ("bpfel-unknown-none", "bpfel"), ("csky-unknown-linux-gnuabiv2", "csky-unknown-linux-gnuabiv2"), ("csky-unknown-linux-gnuabiv2hf", "csky-unknown-linux-gnuabiv2"), ("hexagon-unknown-linux-musl", "hexagon-unknown-linux-musl"), ("hexagon-unknown-none-elf", "hexagon-unknown-none-elf"), ("i386-apple-ios", "i386-apple-ios-simulator"), ("i586-pc-windows-msvc", "i586-pc-windows-msvc"), ("i586-unknown-linux-gnu", "i586-unknown-linux-gnu"), ("i586-unknown-linux-musl", "i586-unknown-linux-musl"), ("i586-unknown-netbsd", "i586-unknown-netbsdelf"), ("i586-unknown-redox", "i586-unknown-redox"), ("i686-apple-darwin", "i686-apple-macosx"), ("i686-linux-android", "i686-linux-android"), ("i686-pc-nto-qnx700", "i586-pc-unknown"), ("i686-pc-windows-gnu", "i686-pc-windows-gnu"), ("i686-pc-windows-gnullvm", "i686-pc-windows-gnu"), ("i686-pc-windows-msvc", "i686-pc-windows-msvc"), ("i686-unknown-freebsd", "i686-unknown-freebsd"), ("i686-unknown-haiku", "i686-unknown-haiku"), ("i686-unknown-hurd-gnu", "i686-unknown-hurd-gnu"), ("i686-unknown-linux-gnu", "i686-unknown-linux-gnu"), ("i686-unknown-linux-musl", "i686-unknown-linux-musl"), ("i686-unknown-netbsd", "i686-unknown-netbsdelf"), ("i686-unknown-openbsd", "i686-unknown-openbsd"), ("i686-unknown-uefi", "i686-unknown-windows-gnu"), ("i686-uwp-windows-gnu", "i686-pc-windows-gnu"), ("i686-uwp-windows-msvc", "i686-pc-windows-msvc"), ("i686-win7-windows-gnu", "i686-pc-windows-gnu"), ("i686-win7-windows-msvc", "i686-pc-windows-msvc"), ("i686-wrs-vxworks", "i686-unknown-linux-gnu"), ("loongarch64-unknown-linux-gnu", "loongarch64-unknown-linux-gnu"), ("loongarch64-unknown-linux-musl", "loongarch64-unknown-linux-musl"), ("loongarch64-unknown-linux-ohos", "loongarch64-unknown-linux-ohos"), ("loongarch64-unknown-none", "loongarch64-unknown-none"), ("loongarch64-unknown-none-softfloat", "loongarch64-unknown-none"), ("m68k-unknown-linux-gnu", "m68k-unknown-linux-gnu"), ("m68k-unknown-none-elf", "m68k"), ("mips-mti-none-elf", "mips"), ("mips-unknown-linux-gnu", "mips-unknown-linux-gnu"), ("mips-unknown-linux-musl", "mips-unknown-linux-musl"), ("mips-unknown-linux-uclibc", "mips-unknown-linux-gnu"), ("mips64-openwrt-linux-musl", "mips64-unknown-linux-musl"), ("mips64-unknown-linux-gnuabi64", "mips64-unknown-linux-gnuabi64"), ("mips64-unknown-linux-muslabi64", "mips64-unknown-linux-musl"), ("mips64el-unknown-linux-gnuabi64", "mips64el-unknown-linux-gnuabi64"), ("mips64el-unknown-linux-muslabi64", "mips64el-unknown-linux-musl"), ("mipsel-mti-none-elf", "mipsel"), ("mipsel-sony-psp", "mipsel-sony-psp"), ("mipsel-sony-psx", "mipsel-sony-psx"), ("mipsel-unknown-linux-gnu", "mipsel-unknown-linux-gnu"), ("mipsel-unknown-linux-musl", "mipsel-unknown-linux-musl"), ("mipsel-unknown-linux-uclibc", "mipsel-unknown-linux-gnu"), ("mipsel-unknown-netbsd", "mipsel-unknown-netbsd"), ("mipsel-unknown-none", "mipsel-unknown-none"), ("mipsisa32r6-unknown-linux-gnu", "mipsisa32r6-unknown-linux-gnu"), ("mipsisa32r6el-unknown-linux-gnu", "mipsisa32r6el-unknown-linux-gnu"), ("mipsisa64r6-unknown-linux-gnuabi64", "mipsisa64r6-unknown-linux-gnuabi64"), ("mipsisa64r6el-unknown-linux-gnuabi64", "mipsisa64r6el-unknown-linux-gnuabi64"), ("msp430-none-elf", "msp430-none-elf"), ("nvptx64-nvidia-cuda", "nvptx64-nvidia-cuda"), ("powerpc-unknown-freebsd", "powerpc-unknown-freebsd13.0"), ("powerpc-unknown-linux-gnu", "powerpc-unknown-linux-gnu"), ("powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-gnuspe"), ("powerpc-unknown-linux-musl", "powerpc-unknown-linux-musl"), ("powerpc-unknown-linux-muslspe", "powerpc-unknown-linux-muslspe"), ("powerpc-unknown-netbsd", "powerpc-unknown-netbsd"), ("powerpc-unknown-openbsd", "powerpc-unknown-openbsd"), ("powerpc-wrs-vxworks", "powerpc-unknown-linux-gnu"), ("powerpc-wrs-vxworks-spe", "powerpc-unknown-linux-gnuspe"), ("powerpc64-ibm-aix", "powerpc64-ibm-aix"), ("powerpc64-unknown-freebsd", "powerpc64-unknown-freebsd"), ("powerpc64-unknown-linux-gnu", "powerpc64-unknown-linux-gnu"), ("powerpc64-unknown-linux-musl", "powerpc64-unknown-linux-musl"), ("powerpc64-unknown-openbsd", "powerpc64-unknown-openbsd"), ("powerpc64-wrs-vxworks", "powerpc64-unknown-linux-gnu"), ("powerpc64le-unknown-freebsd", "powerpc64le-unknown-freebsd"), ("powerpc64le-unknown-linux-gnu", "powerpc64le-unknown-linux-gnu"), ("powerpc64le-unknown-linux-musl", "powerpc64le-unknown-linux-musl"), ("riscv32-wrs-vxworks", "riscv32-unknown-linux-gnu"), ("riscv32e-unknown-none-elf", "riscv32"), ("riscv32em-unknown-none-elf", "riscv32"), ("riscv32emc-unknown-none-elf", "riscv32"), ("riscv32gc-unknown-linux-gnu", "riscv32-unknown-linux-gnu"), ("riscv32gc-unknown-linux-musl", "riscv32-unknown-linux-musl"), ("riscv32i-unknown-none-elf", "riscv32"), ("riscv32im-risc0-zkvm-elf", "riscv32"), ("riscv32im-unknown-none-elf", "riscv32"), ("riscv32ima-unknown-none-elf", "riscv32"), ("riscv32imac-esp-espidf", "riscv32"), ("riscv32imac-unknown-none-elf", "riscv32"), ("riscv32imac-unknown-nuttx-elf", "riscv32"), ("riscv32imac-unknown-xous-elf", "riscv32"), ("riscv32imafc-esp-espidf", "riscv32"), ("riscv32imafc-unknown-none-elf", "riscv32"), ("riscv32imafc-unknown-nuttx-elf", "riscv32"), ("riscv32imc-esp-espidf", "riscv32"), ("riscv32imc-unknown-none-elf", "riscv32"), ("riscv32imc-unknown-nuttx-elf", "riscv32"), ("riscv64-linux-android", "riscv64-linux-android"), ("riscv64-wrs-vxworks", "riscv64-unknown-linux-gnu"), ("riscv64gc-unknown-freebsd", "riscv64-unknown-freebsd"), ("riscv64gc-unknown-fuchsia", "riscv64-unknown-fuchsia"), ("riscv64gc-unknown-hermit", "riscv64-unknown-hermit"), ("riscv64gc-unknown-linux-gnu", "riscv64-unknown-linux-gnu"), ("riscv64gc-unknown-linux-musl", "riscv64-unknown-linux-musl"), ("riscv64gc-unknown-netbsd", "riscv64-unknown-netbsd"), ("riscv64gc-unknown-none-elf", "riscv64"), ("riscv64gc-unknown-nuttx-elf", "riscv64"), ("riscv64gc-unknown-openbsd", "riscv64-unknown-openbsd"), ("riscv64imac-unknown-none-elf", "riscv64"), ("riscv64imac-unknown-nuttx-elf", "riscv64"), ("s390x-unknown-linux-gnu", "s390x-unknown-linux-gnu"), ("s390x-unknown-linux-musl", "s390x-unknown-linux-musl"), ("sparc-unknown-linux-gnu", "sparc-unknown-linux-gnu"), ("sparc-unknown-none-elf", "sparc-unknown-none-elf"), ("sparc64-unknown-linux-gnu", "sparc64-unknown-linux-gnu"), ("sparc64-unknown-netbsd", "sparc64-unknown-netbsd"), ("sparc64-unknown-openbsd", "sparc64-unknown-openbsd"), ("sparcv9-sun-solaris", "sparcv9-sun-solaris"), ("thumbv4t-none-eabi", "thumbv4t-none-eabi"), ("thumbv5te-none-eabi", "thumbv5te-none-eabi"), ("thumbv6m-none-eabi", "thumbv6m-none-eabi"), ("thumbv6m-nuttx-eabi", "thumbv6m-none-eabi"), ("thumbv7a-nuttx-eabi", "thumbv7a-none-eabi"), ("thumbv7a-nuttx-eabihf", "thumbv7a-none-eabihf"), ("thumbv7a-pc-windows-msvc", "thumbv7a-pc-windows-msvc"), ("thumbv7a-uwp-windows-msvc", "thumbv7a-pc-windows-msvc"), ("thumbv7em-none-eabi", "thumbv7em-none-eabi"), ("thumbv7em-none-eabihf", "thumbv7em-none-eabihf"), ("thumbv7em-nuttx-eabi", "thumbv7em-none-eabi"), ("thumbv7em-nuttx-eabihf", "thumbv7em-none-eabihf"), ("thumbv7m-none-eabi", "thumbv7m-none-eabi"), ("thumbv7m-nuttx-eabi", "thumbv7m-none-eabi"), ("thumbv7neon-linux-androideabi", "armv7-none-linux-android"), ("thumbv7neon-unknown-linux-gnueabihf", "armv7-unknown-linux-gnueabihf"), ("thumbv7neon-unknown-linux-musleabihf", "armv7-unknown-linux-musleabihf"), ("thumbv8m.base-none-eabi", "thumbv8m.base-none-eabi"), ("thumbv8m.base-nuttx-eabi", "thumbv8m.base-none-eabi"), ("thumbv8m.main-none-eabi", "thumbv8m.main-none-eabi"), ("thumbv8m.main-none-eabihf", "thumbv8m.main-none-eabihf"), ("thumbv8m.main-nuttx-eabi", "thumbv8m.main-none-eabi"), ("thumbv8m.main-nuttx-eabihf", "thumbv8m.main-none-eabihf"), ("wasm32-unknown-emscripten", "wasm32-unknown-emscripten"), ("wasm32-unknown-unknown", "wasm32-unknown-unknown"), ("wasm32-wali-linux-musl", "wasm32-wasi"), ("wasm32-wasi", "wasm32-wasi"), ("wasm32-wasip1", "wasm32-wasip1"), ("wasm32-wasip1-threads", "wasm32-wasi"), ("wasm32-wasip2", "wasm32-wasip2"), ("wasm32v1-none", "wasm32-unknown-unknown"), ("wasm64-unknown-unknown", "wasm64-unknown-unknown"), ("x86_64-apple-darwin", "x86_64-apple-macosx"), ("x86_64-apple-ios", "x86_64-apple-ios-simulator"), ("x86_64-apple-ios-macabi", "x86_64-apple-ios-macabi"), ("x86_64-apple-tvos", "x86_64-apple-tvos-simulator"), ("x86_64-apple-watchos-sim", "x86_64-apple-watchos-simulator"), ("x86_64-fortanix-unknown-sgx", "x86_64-elf"), ("x86_64-fuchsia", "x86_64-fuchsia"), ("x86_64-linux-android", "x86_64-linux-android"), ("x86_64-lynx-lynxos178", "x86_64-unknown-unknown-gnu"), ("x86_64-pc-cygwin", "x86_64-pc-cygwin"), ("x86_64-pc-nto-qnx710", "x86_64-pc-unknown"), ("x86_64-pc-nto-qnx710_iosock", "x86_64-pc-unknown"), ("x86_64-pc-nto-qnx800", "x86_64-pc-unknown"), ("x86_64-pc-solaris", "x86_64-pc-solaris"), ("x86_64-pc-windows-gnu", "x86_64-pc-windows-gnu"), ("x86_64-pc-windows-gnullvm", "x86_64-pc-windows-gnu"), ("x86_64-pc-windows-msvc", "x86_64-pc-windows-msvc"), ("x86_64-sun-solaris", "x86_64-pc-solaris"), ("x86_64-unikraft-linux-musl", "x86_64-unknown-linux-musl"), ("x86_64-unknown-dragonfly", "x86_64-unknown-dragonfly"), ("x86_64-unknown-freebsd", "x86_64-unknown-freebsd"), ("x86_64-unknown-fuchsia", "x86_64-unknown-fuchsia"), ("x86_64-unknown-haiku", "x86_64-unknown-haiku"), ("x86_64-unknown-hermit", "x86_64-unknown-hermit"), ("x86_64-unknown-hurd-gnu", "x86_64-unknown-hurd-gnu"), ("x86_64-unknown-illumos", "x86_64-pc-solaris"), ("x86_64-unknown-l4re-uclibc", "x86_64-unknown-l4re-gnu"), ("x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"), ("x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-gnux32"), ("x86_64-unknown-linux-musl", "x86_64-unknown-linux-musl"), ("x86_64-unknown-linux-none", "x86_64-unknown-linux-none"), ("x86_64-unknown-linux-ohos", "x86_64-unknown-linux-ohos"), ("x86_64-unknown-netbsd", "x86_64-unknown-netbsd"), ("x86_64-unknown-none", "x86_64-unknown-none-elf"), ("x86_64-unknown-none-linuxkernel", "x86_64-unknown-none-elf"), ("x86_64-unknown-openbsd", "x86_64-unknown-openbsd"), ("x86_64-unknown-redox", "x86_64-unknown-redox"), ("x86_64-unknown-trusty", "x86_64-unknown-unknown-musl"), ("x86_64-unknown-uefi", "x86_64-unknown-windows"), ("x86_64-uwp-windows-gnu", "x86_64-pc-windows-gnu"), ("x86_64-uwp-windows-msvc", "x86_64-pc-windows-msvc"), ("x86_64-win7-windows-gnu", "x86_64-pc-windows-gnu"), ("x86_64-win7-windows-msvc", "x86_64-pc-windows-msvc"), ("x86_64-wrs-vxworks", "x86_64-unknown-linux-gnu"), ("x86_64h-apple-darwin", "x86_64h-apple-macosx"), ("xtensa-esp32-espidf", "xtensa-none-elf"), ("xtensa-esp32-none-elf", "xtensa-none-elf"), ("xtensa-esp32s2-espidf", "xtensa-none-elf"), ("xtensa-esp32s2-none-elf", "xtensa-none-elf"), ("xtensa-esp32s3-espidf", "xtensa-none-elf"), ("xtensa-esp32s3-none-elf", "xtensa-none-elf"), ]; cc/src/target/parser.rs0000644000175000017500000005024215105742312014711 0ustar bdrungbdrunguse std::env; use crate::{target::TargetInfo, utilities::OnceLock, Error, ErrorKind}; #[derive(Debug)] struct TargetInfoParserInner { full_arch: Box, arch: Box, vendor: Box, os: Box, env: Box, abi: Box, } impl TargetInfoParserInner { fn from_cargo_environment_variables() -> Result { // `TARGET` must be present. // // No need to emit `rerun-if-env-changed` for this, // as it is controlled by Cargo itself. #[allow(clippy::disallowed_methods)] let target_name = env::var("TARGET").map_err(|err| { Error::new( ErrorKind::EnvVarNotFound, format!("failed reading TARGET: {err}"), ) })?; // Parse the full architecture name from the target name. let (full_arch, _rest) = target_name.split_once('-').ok_or(Error::new( ErrorKind::InvalidTarget, format!("target `{target_name}` only had a single component (at least two required)"), ))?; let cargo_env = |name, fallback: Option<&str>| -> Result, Error> { // No need to emit `rerun-if-env-changed` for these, // as they are controlled by Cargo itself. #[allow(clippy::disallowed_methods)] match env::var(name) { Ok(var) => Ok(var.into_boxed_str()), Err(err) => match fallback { Some(fallback) => Ok(fallback.into()), None => Err(Error::new( ErrorKind::EnvVarNotFound, format!("did not find fallback information for target `{target_name}`, and failed reading {name}: {err}"), )), }, } }; // Prefer to use `CARGO_ENV_*` if set, since these contain the most // correct information relative to the current `rustc`, and makes it // possible to support custom target JSON specs unknown to `rustc`. // // NOTE: If the user is using an older `rustc`, that data may be older // than our pre-generated data, but we still prefer Cargo's view of // the world, since at least `cc` won't differ from `rustc` in that // case. // // These may not be set in case the user depended on being able to // just set `TARGET` outside of build scripts; in those cases, fall // back back to data from the known set of target names instead. // // See discussion in #1225 for further details. let fallback_target = TargetInfo::from_rustc_target(&target_name).ok(); let ft = fallback_target.as_ref(); let arch = cargo_env("CARGO_CFG_TARGET_ARCH", ft.map(|t| t.arch))?; let vendor = cargo_env("CARGO_CFG_TARGET_VENDOR", ft.map(|t| t.vendor))?; let os = cargo_env("CARGO_CFG_TARGET_OS", ft.map(|t| t.os))?; let env = cargo_env("CARGO_CFG_TARGET_ENV", ft.map(|t| t.env))?; // `target_abi` was stabilized in Rust 1.78, which is higher than our // MSRV, so it may not always be available; In that case, fall back to // `""`, which is _probably_ correct for unknown target names. let abi = cargo_env("CARGO_CFG_TARGET_ABI", ft.map(|t| t.abi)) .unwrap_or_else(|_| String::default().into_boxed_str()); Ok(Self { full_arch: full_arch.to_string().into_boxed_str(), arch, vendor, os, env, abi, }) } } /// Parser for [`TargetInfo`], contains cached information. #[derive(Default, Debug)] pub(crate) struct TargetInfoParser(OnceLock>); impl TargetInfoParser { pub fn parse_from_cargo_environment_variables(&self) -> Result, Error> { match self .0 .get_or_init(TargetInfoParserInner::from_cargo_environment_variables) { Ok(TargetInfoParserInner { full_arch, arch, vendor, os, env, abi, }) => Ok(TargetInfo { full_arch, arch, vendor, os, env, abi, }), Err(e) => Err(e.clone()), } } } /// Parse the full architecture in the target name into the simpler /// `cfg(target_arch = "...")` that `rustc` exposes. fn parse_arch(full_arch: &str) -> Option<&str> { // NOTE: Some of these don't necessarily match an existing target in // `rustc`. They're parsed anyhow to be as forward-compatible as possible, // while still being correct. // // See also: // https://docs.rs/cfg-expr/0.18.0/cfg_expr/targets/index.html // https://docs.rs/target-lexicon/0.13.2/target_lexicon/enum.Architecture.html // https://gcc.gnu.org/onlinedocs/gcc/Submodel-Options.html // `clang -print-targets` Some(match full_arch { arch if arch.starts_with("mipsisa32r6") => "mips32r6", // mipsisa32r6 | mipsisa32r6el arch if arch.starts_with("mipsisa64r6") => "mips64r6", // mipsisa64r6 | mipsisa64r6el arch if arch.starts_with("mips64") => "mips64", // mips64 | mips64el arch if arch.starts_with("mips") => "mips", // mips | mipsel arch if arch.starts_with("loongarch64") => "loongarch64", arch if arch.starts_with("loongarch32") => "loongarch32", arch if arch.starts_with("powerpc64") => "powerpc64", // powerpc64 | powerpc64le arch if arch.starts_with("powerpc") => "powerpc", arch if arch.starts_with("ppc64") => "powerpc64", arch if arch.starts_with("ppc") => "powerpc", arch if arch.starts_with("x86_64") => "x86_64", // x86_64 | x86_64h arch if arch.starts_with("i") && arch.ends_with("86") => "x86", // i386 | i586 | i686 "arm64ec" => "arm64ec", // https://github.com/rust-lang/rust/issues/131172 arch if arch.starts_with("aarch64") => "aarch64", // arm64e | arm64_32 arch if arch.starts_with("arm64") => "aarch64", // aarch64 | aarch64_be arch if arch.starts_with("arm") => "arm", // arm | armv7s | armeb | ... arch if arch.starts_with("thumb") => "arm", // thumbv4t | thumbv7a | thumbv8m | ... arch if arch.starts_with("riscv64") => "riscv64", arch if arch.starts_with("riscv32") => "riscv32", arch if arch.starts_with("wasm64") => "wasm64", arch if arch.starts_with("wasm32") => "wasm32", // wasm32 | wasm32v1 "asmjs" => "wasm32", arch if arch.starts_with("nvptx64") => "nvptx64", arch if arch.starts_with("nvptx") => "nvptx", arch if arch.starts_with("bpf") => "bpf", // bpfeb | bpfel // https://github.com/bytecodealliance/wasmtime/tree/v30.0.1/pulley arch if arch.starts_with("pulley64") => "pulley64", arch if arch.starts_with("pulley32") => "pulley32", // https://github.com/Clever-ISA/Clever-ISA arch if arch.starts_with("clever") => "clever", "sparc" | "sparcv7" | "sparcv8" => "sparc", "sparc64" | "sparcv9" => "sparc64", "amdgcn" => "amdgpu", "avr" => "avr", "csky" => "csky", "hexagon" => "hexagon", "m68k" => "m68k", "msp430" => "msp430", "r600" => "r600", "s390x" => "s390x", "xtensa" => "xtensa", _ => return None, }) } /// Parse environment and ABI from the last component of the target name. fn parse_envabi(last_component: &str) -> Option<(&str, &str)> { let (env, abi) = match last_component { // Combined environment and ABI // gnullvm | gnueabi | gnueabihf | gnuabiv2 | gnuabi64 | gnuspe | gnux32 | gnu_ilp32 env_and_abi if env_and_abi.starts_with("gnu") => { let abi = env_and_abi.strip_prefix("gnu").unwrap(); let abi = abi.strip_prefix("_").unwrap_or(abi); ("gnu", abi) } // musl | musleabi | musleabihf | muslabi64 | muslspe env_and_abi if env_and_abi.starts_with("musl") => { ("musl", env_and_abi.strip_prefix("musl").unwrap()) } // uclibc | uclibceabi | uclibceabihf env_and_abi if env_and_abi.starts_with("uclibc") => { ("uclibc", env_and_abi.strip_prefix("uclibc").unwrap()) } // newlib | newlibeabihf env_and_abi if env_and_abi.starts_with("newlib") => { ("newlib", env_and_abi.strip_prefix("newlib").unwrap()) } // Environments "msvc" => ("msvc", ""), "ohos" => ("ohos", ""), "qnx700" => ("nto70", ""), "qnx710_iosock" => ("nto71_iosock", ""), "qnx710" => ("nto71", ""), "qnx800" => ("nto80", ""), "sgx" => ("sgx", ""), "threads" => ("threads", ""), // ABIs "abi64" => ("", "abi64"), "abiv2" => ("", "spe"), "eabi" => ("", "eabi"), "eabihf" => ("", "eabihf"), "macabi" => ("", "macabi"), "sim" => ("", "sim"), "softfloat" => ("", "softfloat"), "spe" => ("", "spe"), "x32" => ("", "x32"), // Badly named targets, ELF is already known from target OS. // Probably too late to fix now though. "elf" => ("", ""), // Undesirable to expose to user code (yet): // https://github.com/rust-lang/rust/pull/131166#issuecomment-2389541917 "freestanding" => ("", ""), _ => return None, }; Some((env, abi)) } impl<'a> TargetInfo<'a> { pub(crate) fn from_rustc_target(target: &'a str) -> Result { // FIXME(madsmtm): This target should be renamed, cannot be parsed // with the means we do below (since `none` must not be interpreted // as an env/ABI). if target == "x86_64-unknown-linux-none" { return Ok(Self { full_arch: "x86_64", arch: "x86_64", vendor: "unknown", os: "linux", env: "", abi: "", }); } let mut components = target.split('-'); // Insist that the target name contains at least a valid architecture. let full_arch = components.next().ok_or(Error::new( ErrorKind::InvalidTarget, "target was empty".to_string(), ))?; let arch = parse_arch(full_arch).ok_or_else(|| { Error::new( ErrorKind::UnknownTarget, format!("target `{target}` had an unknown architecture"), ) })?; // Newer target names have begun omitting the vendor, so the only // component we know must be there is the OS name. let components: Vec<_> = components.collect(); let (vendor, os, mut env, mut abi) = match &*components { [] => { return Err(Error::new( ErrorKind::InvalidTarget, format!("target `{target}` must have at least two components"), )) } // Two components; format is `arch-os`. [os] => ("unknown", *os, "", ""), // The three-component case is a bit tricky to handle, it could // either have the format `arch-vendor-os` or `arch-os-env+abi`. [vendor_or_os, os_or_envabi] => { // We differentiate between these by checking if the last // component is an env/ABI; if it isn't, then it's probably // an OS instead. if let Some((env, abi)) = parse_envabi(os_or_envabi) { ("unknown", *vendor_or_os, env, abi) } else { (*vendor_or_os, *os_or_envabi, "", "") } } // Four components; format is `arch-vendor-os-env+abi`. [vendor, os, envabi] => { let (env, abi) = parse_envabi(envabi).ok_or_else(|| { Error::new( ErrorKind::UnknownTarget, format!("unknown environment/ABI `{envabi}` in target `{target}`"), ) })?; (*vendor, *os, env, abi) } _ => { return Err(Error::new( ErrorKind::InvalidTarget, format!("too many components in target `{target}`"), )) } }; // Part of the architecture name is carried over into the ABI. match full_arch { // https://github.com/rust-lang/compiler-team/issues/830 arch if arch.starts_with("riscv32e") => { abi = "ilp32e"; } _ => {} } // Various environment/ABIs are determined based on OS name. match os { "3ds" | "rtems" | "espidf" => env = "newlib", "vxworks" => env = "gnu", "redox" => env = "relibc", "aix" => abi = "vec-extabi", _ => {} } // Extra overrides for badly named targets. match target { // Actually simulator targets. "i386-apple-ios" | "x86_64-apple-ios" | "x86_64-apple-tvos" => { abi = "sim"; } // Name should've contained `muslabi64`. "mips64-openwrt-linux-musl" => { abi = "abi64"; } // Specifies abi even though not in name. "armv6-unknown-freebsd" | "armv6k-nintendo-3ds" | "armv7-unknown-freebsd" => { abi = "eabihf"; } // Specifies abi even though not in name. "armv7-unknown-linux-ohos" | "armv7-unknown-trusty" => { abi = "eabi"; } _ => {} } let os = match os { // Horizon is the common/internal OS name for 3DS and the Switch. "3ds" | "switch" => "horizon", // FIXME(madsmtm): macOS targets are badly named. "darwin" => "macos", // WASI targets contain the preview version in them too. Should've // been `wasi-p1`/`wasi-p2`, but that's probably too late now. os if os.starts_with("wasi") => { env = os.strip_prefix("wasi").unwrap(); "wasi" } // FIXME(madsmtm): Badly named targets `*-linux-androideabi`, // should be `*-android-eabi`. "androideabi" => { abi = "eabi"; "android" } os => os, }; let vendor = match vendor { // esp, esp32, esp32s2 etc. vendor if vendor.starts_with("esp") => "espressif", // FIXME(madsmtm): Badly named targets `*-linux-android*`, // "linux" makes no sense as the vendor name. "linux" if os == "android" || os == "androideabi" => "unknown", // FIXME(madsmtm): Fix in `rustc` after // https://github.com/rust-lang/compiler-team/issues/850. "wali" => "unknown", "lynx" => "unknown", // Some Linux distributions set their name as the target vendor, // so we have to assume that it can be an arbitary string. vendor => vendor, }; // Intentionally also marked as an ABI: // https://github.com/rust-lang/rust/pull/86922 if vendor == "fortanix" { abi = "fortanix"; } if vendor == "uwp" { abi = "uwp"; } Ok(Self { full_arch, arch, vendor, os, env, abi, }) } } #[cfg(test)] #[allow(unexpected_cfgs)] mod tests { use std::process::Command; use super::TargetInfo; use crate::ErrorKind; // Test tier 1 targets. #[test] fn tier1() { let targets = [ "aarch64-unknown-linux-gnu", "aarch64-apple-darwin", "i686-pc-windows-gnu", "i686-pc-windows-msvc", "i686-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", "x86_64-unknown-linux-gnu", ]; for target in targets { // Check that they parse. let _ = TargetInfo::from_rustc_target(target).unwrap(); } } // Various custom target names not (or no longer) known by `rustc`. #[test] fn parse_extra() { let targets = [ "aarch64-unknown-none-gnu", "aarch64-uwp-windows-gnu", "arm-frc-linux-gnueabi", "arm-unknown-netbsd-eabi", "armv7neon-unknown-linux-gnueabihf", "armv7neon-unknown-linux-musleabihf", "thumbv7-unknown-linux-gnueabihf", "thumbv7-unknown-linux-musleabihf", "armv7-apple-ios", "wasm32-wasi", "x86_64-rumprun-netbsd", "x86_64-unknown-linux", "x86_64-alpine-linux-musl", "x86_64-chimera-linux-musl", "x86_64-foxkit-linux-musl", "arm-poky-linux-gnueabi", "x86_64-unknown-moturus", ]; for target in targets { // Check that they parse. let _ = TargetInfo::from_rustc_target(target).unwrap(); } } fn target_from_rustc_cfgs<'a>(target: &'a str, cfgs: &'a str) -> TargetInfo<'a> { // Cannot determine full architecture from cfgs. let (full_arch, _rest) = target.split_once('-').expect("target to have arch"); let mut target = TargetInfo { full_arch, arch: "invalid-none-set", vendor: "invalid-none-set", os: "invalid-none-set", env: "invalid-none-set", // Not set in older Rust versions abi: "", }; for cfg in cfgs.lines() { if let Some((name, value)) = cfg.split_once('=') { // Remove whitespace, if `rustc` decided to insert any. let name = name.trim(); let value = value.trim(); // Remove quotes around value. let value = value.strip_prefix('"').unwrap_or(value); let value = value.strip_suffix('"').unwrap_or(value); match name { "target_arch" => target.arch = value, "target_vendor" => target.vendor = value, "target_os" => target.os = value, "target_env" => target.env = value, "target_abi" => target.abi = value, _ => {} } } else { // Skip cfgs like `debug_assertions` and `unix`. } } target } #[test] fn unknown_env_determined_as_unknown() { let err = TargetInfo::from_rustc_target("aarch64-unknown-linux-bogus").unwrap_err(); assert!(matches!(err.kind, ErrorKind::UnknownTarget)); } // Used in .github/workflows/test-rustc-targets.yml #[test] #[cfg_attr( not(rustc_target_test), ignore = "must enable explicitly with --cfg=rustc_target_test" )] fn parse_rustc_targets() { let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string()); let target_list = Command::new(&rustc) .arg("--print=target-list") .output() .unwrap() .stdout; let target_list = String::from_utf8(target_list).unwrap(); let mut has_failure = false; for target in target_list.lines() { let cfgs = Command::new(&rustc) .arg("--target") .arg(target) .arg("--print=cfg") .output() .unwrap() .stdout; let cfgs = String::from_utf8(cfgs).unwrap(); let expected = target_from_rustc_cfgs(target, &cfgs); let actual = TargetInfo::from_rustc_target(target); if Some(&expected) != actual.as_ref().ok() { eprintln!("failed comparing {target}:"); eprintln!(" expected: Ok({expected:?})"); eprintln!(" actual: {actual:?}"); eprintln!(); has_failure = true; } } if has_failure { panic!("failed comparing targets"); } } } cc/src/target/llvm.rs0000644000175000017500000002411715105742312014371 0ustar bdrungbdrunguse std::borrow::Cow; use super::{generated, TargetInfo}; impl TargetInfo<'_> { /// The LLVM/Clang target triple. /// /// See . /// /// Rust and Clang don't really agree on target naming, so we first try to /// find the matching trible based on `rustc`'s output, but if no such /// triple exists, we attempt to construct the triple from scratch. /// /// NOTE: You should never need to match on this explicitly, use the /// fields on [`TargetInfo`] instead. pub(crate) fn llvm_target( &self, rustc_target: &str, version: Option<&str>, ) -> Cow<'static, str> { if rustc_target == "armv7-apple-ios" { // FIXME(madsmtm): Unnecessary once we bump MSRV to Rust 1.74 return Cow::Borrowed("armv7-apple-ios"); } else if self.os == "uefi" { // Override the UEFI LLVM targets. // // The rustc mappings (as of 1.82) for the UEFI targets are: // * i686-unknown-uefi -> i686-unknown-windows-gnu // * x86_64-unknown-uefi -> x86_64-unknown-windows // * aarch64-unknown-uefi -> aarch64-unknown-windows // // However, in cc-rs all the UEFI targets use // -windows-gnu. This has been the case since 2021 [1]. // * i686-unknown-uefi -> i686-unknown-windows-gnu // * x86_64-unknown-uefi -> x86_64-unknown-windows-gnu // * aarch64-unknown-uefi -> aarch64-unknown-windows-gnu // // For now, override the UEFI mapping to keep the behavior // of cc-rs unchanged. // // TODO: as discussed in [2], it may be possible to switch // to new UEFI targets added to clang, and regardless it // would be good to have consistency between rustc and // cc-rs. // // [1]: https://github.com/rust-lang/cc-rs/pull/623 // [2]: https://github.com/rust-lang/cc-rs/pull/1264 return Cow::Owned(format!("{}-unknown-windows-gnu", self.full_arch)); } // If no version is requested, let's take the triple directly from // `rustc` (the logic below is not yet good enough for most targets). // // FIXME(madsmtm): This should ideally be removed. if version.is_none() { if let Ok(index) = generated::LLVM_TARGETS .binary_search_by_key(&rustc_target, |(rustc_target, _)| rustc_target) { let (_, llvm_target) = &generated::LLVM_TARGETS[index]; return Cow::Borrowed(llvm_target); } } // Otherwise, attempt to construct the triple from the target info. let arch = match self.full_arch { riscv32 if riscv32.starts_with("riscv32") => "riscv32", riscv64 if riscv64.starts_with("riscv64") => "riscv64", "aarch64" if self.vendor == "apple" => "arm64", "armv7" if self.vendor == "sony" => "thumbv7a", // FIXME arch => arch, }; let vendor = match self.vendor { "kmc" | "nintendo" => "unknown", "unknown" if self.os == "android" => "linux", "uwp" => "pc", "espressif" => "", _ if self.arch == "msp430" => "", vendor => vendor, }; let os = match self.os { "macos" => "macosx", "visionos" => "xros", "uefi" => "windows", "solid_asp3" | "horizon" | "teeos" | "nuttx" | "espidf" => "none", "nto" => "unknown", // FIXME "trusty" => "unknown", // FIXME os => os, }; let version = version.unwrap_or(""); let env = match self.env { "newlib" | "nto70" | "nto71" | "nto71_iosock" | "p1" | "p2" | "relibc" | "sgx" | "uclibc" => "", env => env, }; let abi = match self.abi { "sim" => "simulator", "llvm" | "softfloat" | "uwp" | "vec-extabi" => "", "ilp32" => "_ilp32", "abi64" => "", abi => abi, }; Cow::Owned(match (vendor, env, abi) { ("", "", "") => format!("{arch}-{os}{version}"), ("", env, abi) => format!("{arch}-{os}{version}-{env}{abi}"), (vendor, "", "") => format!("{arch}-{vendor}-{os}{version}"), (vendor, env, abi) => format!("{arch}-{vendor}-{os}{version}-{env}{abi}"), }) } } #[cfg(test)] mod tests { use std::process::Command; use crate::TargetInfo; #[test] fn test_old_ios_target() { assert_eq!( TargetInfo { full_arch: "armv7", arch: "armv7", vendor: "apple", os: "ios", env: "", abi: "", } .llvm_target("armv7-apple-ios", None), "armv7-apple-ios" ); } #[test] fn basic_llvm_triple_guessing() { assert_eq!( TargetInfo { full_arch: "aarch64", arch: "aarch64", vendor: "unknown", os: "linux", env: "", abi: "", } .llvm_target("invalid", None), "aarch64-unknown-linux" ); assert_eq!( TargetInfo { full_arch: "x86_64", arch: "x86_64", vendor: "unknown", os: "linux", env: "gnu", abi: "", } .llvm_target("invalid", None), "x86_64-unknown-linux-gnu" ); assert_eq!( TargetInfo { full_arch: "x86_64", arch: "x86_64", vendor: "unknown", os: "linux", env: "gnu", abi: "eabi", } .llvm_target("invalid", None), "x86_64-unknown-linux-gnueabi" ); assert_eq!( TargetInfo { full_arch: "x86_64", arch: "x86_64", vendor: "apple", os: "macos", env: "", abi: "", } .llvm_target("invalid", None), "x86_64-apple-macosx" ); } #[test] fn llvm_version() { assert_eq!( TargetInfo { full_arch: "aarch64", arch: "aarch64", vendor: "apple", os: "ios", env: "", abi: "sim", } .llvm_target("aarch64-apple-ios-sim", Some("14.0")), "arm64-apple-ios14.0-simulator" ); assert_eq!( TargetInfo { full_arch: "aarch64", arch: "aarch64", vendor: "apple", os: "visionos", env: "", abi: "", } .llvm_target("aarch64-apple-visionos", Some("2.0")), "arm64-apple-xros2.0" ); assert_eq!( TargetInfo { full_arch: "aarch64", arch: "aarch64", vendor: "apple", os: "ios", env: "", abi: "macabi", } .llvm_target("aarch64-apple-ios-macabi", Some("13.1")), "arm64-apple-ios13.1-macabi" ); } #[test] fn uefi() { assert_eq!( TargetInfo { full_arch: "i686", arch: "x86", vendor: "unknown", os: "uefi", env: "", abi: "", } .llvm_target("i686-unknown-uefi", None), "i686-unknown-windows-gnu" ); assert_eq!( TargetInfo { full_arch: "x86_64", arch: "x86_64", vendor: "unknown", os: "uefi", env: "", abi: "", } .llvm_target("x86_64-unknown-uefi", None), "x86_64-unknown-windows-gnu" ); assert_eq!( TargetInfo { full_arch: "aarch64", arch: "aarch64", vendor: "unknown", os: "uefi", env: "", abi: "", } .llvm_target("aarch64-unknown-uefi", None), "aarch64-unknown-windows-gnu" ); } #[test] #[ignore = "not yet done"] fn llvm_for_all_rustc_targets() { let rustc = std::env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string()); let target_list = Command::new(&rustc) .arg("--print=target-list") .output() .unwrap() .stdout; let target_list = String::from_utf8(target_list).unwrap(); let mut has_failure = false; for target in target_list.lines() { let spec_json = Command::new(&rustc) .arg("--target") .arg(target) .arg("-Zunstable-options") .arg("--print=target-spec-json") .env("RUSTC_BOOTSTRAP", "1") // Crimes .output() .unwrap() .stdout; let spec_json = String::from_utf8(spec_json).unwrap(); // JSON crimes let expected = spec_json .split_once("llvm-target\": \"") .unwrap() .1 .split_once("\"") .unwrap() .0; let actual = TargetInfo::from_rustc_target(target) .map(|target| target.llvm_target("invalid", None)); if Some(expected) != actual.as_deref().ok() { eprintln!("failed comparing {target}:"); eprintln!(" expected: Ok({expected:?})"); eprintln!(" actual: {actual:?}"); eprintln!(); has_failure = true; } } if has_failure { panic!("failed comparing targets"); } } } cc/src/target/apple.rs0000644000175000017500000000504715105742312014521 0ustar bdrungbdrunguse super::TargetInfo; impl TargetInfo<'_> { pub(crate) fn apple_sdk_name(&self) -> &'static str { match (self.os, self.abi) { ("macos", "") => "macosx", ("ios", "") => "iphoneos", ("ios", "sim") => "iphonesimulator", ("ios", "macabi") => "macosx", ("tvos", "") => "appletvos", ("tvos", "sim") => "appletvsimulator", ("watchos", "") => "watchos", ("watchos", "sim") => "watchsimulator", ("visionos", "") => "xros", ("visionos", "sim") => "xrsimulator", (os, _) => panic!("invalid Apple target OS {}", os), } } pub(crate) fn apple_version_flag(&self, min_version: &str) -> String { // There are many aliases for these, and `-mtargetos=` is preferred on Clang nowadays, but // for compatibility with older Clang, we use the earliest supported name here. // // NOTE: GCC does not support `-miphoneos-version-min=` etc. (because it does not support // iOS in general), but we specify them anyhow in case we actually have a Clang-like // compiler disguised as a GNU-like compiler, or in case GCC adds support for these in the // future. // // See also: // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mmacos-version-min // https://clang.llvm.org/docs/AttributeReference.html#availability // https://gcc.gnu.org/onlinedocs/gcc/Darwin-Options.html#index-mmacosx-version-min match (self.os, self.abi) { ("macos", "") => format!("-mmacosx-version-min={min_version}"), ("ios", "") => format!("-miphoneos-version-min={min_version}"), ("ios", "sim") => format!("-mios-simulator-version-min={min_version}"), ("ios", "macabi") => format!("-mtargetos=ios{min_version}-macabi"), ("tvos", "") => format!("-mappletvos-version-min={min_version}"), ("tvos", "sim") => format!("-mappletvsimulator-version-min={min_version}"), ("watchos", "") => format!("-mwatchos-version-min={min_version}"), ("watchos", "sim") => format!("-mwatchsimulator-version-min={min_version}"), // `-mxros-version-min` does not exist // https://github.com/llvm/llvm-project/issues/88271 ("visionos", "") => format!("-mtargetos=xros{min_version}"), ("visionos", "sim") => format!("-mtargetos=xros{min_version}-simulator"), (os, _) => panic!("invalid Apple target OS {}", os), } } } cc/src/flags.rs0000644000175000017500000005314615105742312013231 0ustar bdrungbdrunguse crate::target::TargetInfo; use crate::{Build, Error, ErrorKind, Tool, ToolFamily}; use std::borrow::Cow; use std::ffi::OsString; #[derive(Debug, PartialEq, Default)] pub(crate) struct RustcCodegenFlags<'a> { branch_protection: Option<&'a str>, code_model: Option<&'a str>, no_vectorize_loops: bool, no_vectorize_slp: bool, profile_generate: Option<&'a str>, profile_use: Option<&'a str>, control_flow_guard: Option<&'a str>, lto: Option<&'a str>, relocation_model: Option<&'a str>, embed_bitcode: Option, force_frame_pointers: Option, no_redzone: Option, soft_float: Option, dwarf_version: Option, } impl<'this> RustcCodegenFlags<'this> { // Parse flags obtained from CARGO_ENCODED_RUSTFLAGS pub(crate) fn parse(rustflags_env: &'this str) -> Result { fn is_flag_prefix(flag: &str) -> bool { [ "-Z", "-C", "--codegen", "-L", "-l", "-o", "-W", "--warn", "-A", "--allow", "-D", "--deny", "-F", "--forbid", ] .contains(&flag) } fn handle_flag_prefix<'a>(prev: &'a str, curr: &'a str) -> (&'a str, &'a str) { match prev { "--codegen" | "-C" => ("-C", curr), // Handle flags passed like --codegen=code-model=small _ if curr.starts_with("--codegen=") => ("-C", &curr[10..]), "-Z" => ("-Z", curr), "-L" | "-l" | "-o" => (prev, curr), // Handle lint flags "-W" | "--warn" => ("-W", curr), "-A" | "--allow" => ("-A", curr), "-D" | "--deny" => ("-D", curr), "-F" | "--forbid" => ("-F", curr), _ => ("", curr), } } let mut codegen_flags = Self::default(); let mut prev_prefix = None; for curr in rustflags_env.split("\u{1f}") { let prev = prev_prefix.take().unwrap_or(""); if prev.is_empty() && is_flag_prefix(curr) { prev_prefix = Some(curr); continue; } let (prefix, rustc_flag) = handle_flag_prefix(prev, curr); codegen_flags.set_rustc_flag(prefix, rustc_flag)?; } Ok(codegen_flags) } fn set_rustc_flag(&mut self, prefix: &str, flag: &'this str) -> Result<(), Error> { // Convert a textual representation of a bool-like rustc flag argument into an actual bool fn arg_to_bool(arg: impl AsRef) -> Option { match arg.as_ref() { "y" | "yes" | "on" | "true" => Some(true), "n" | "no" | "off" | "false" => Some(false), _ => None, } } fn arg_to_u32(arg: impl AsRef) -> Option { arg.as_ref().parse().ok() } let (flag, value) = if let Some((flag, value)) = flag.split_once('=') { (flag, Some(value)) } else { (flag, None) }; let flag = if prefix.is_empty() { Cow::Borrowed(flag) } else { Cow::Owned(format!("{prefix}{flag}")) }; fn flag_ok_or<'flag>( flag: Option<&'flag str>, msg: &'static str, ) -> Result<&'flag str, Error> { flag.ok_or(Error::new(ErrorKind::InvalidFlag, msg)) } match flag.as_ref() { // https://doc.rust-lang.org/rustc/codegen-options/index.html#code-model "-Ccode-model" => { self.code_model = Some(flag_ok_or(value, "-Ccode-model must have a value")?); } // https://doc.rust-lang.org/rustc/codegen-options/index.html#no-vectorize-loops "-Cno-vectorize-loops" => self.no_vectorize_loops = true, // https://doc.rust-lang.org/rustc/codegen-options/index.html#no-vectorize-slp "-Cno-vectorize-slp" => self.no_vectorize_slp = true, // https://doc.rust-lang.org/rustc/codegen-options/index.html#profile-generate "-Cprofile-generate" => { self.profile_generate = Some(flag_ok_or(value, "-Cprofile-generate must have a value")?); } // https://doc.rust-lang.org/rustc/codegen-options/index.html#profile-use "-Cprofile-use" => { self.profile_use = Some(flag_ok_or(value, "-Cprofile-use must have a value")?); } // https://doc.rust-lang.org/rustc/codegen-options/index.html#control-flow-guard "-Ccontrol-flow-guard" => self.control_flow_guard = value.or(Some("true")), // https://doc.rust-lang.org/rustc/codegen-options/index.html#lto "-Clto" => self.lto = value.or(Some("true")), // https://doc.rust-lang.org/rustc/codegen-options/index.html#relocation-model "-Crelocation-model" => { self.relocation_model = Some(flag_ok_or(value, "-Crelocation-model must have a value")?); } // https://doc.rust-lang.org/rustc/codegen-options/index.html#embed-bitcode "-Cembed-bitcode" => self.embed_bitcode = value.map_or(Some(true), arg_to_bool), // https://doc.rust-lang.org/rustc/codegen-options/index.html#force-frame-pointers "-Cforce-frame-pointers" => { self.force_frame_pointers = value.map_or(Some(true), arg_to_bool) } // https://doc.rust-lang.org/rustc/codegen-options/index.html#no-redzone "-Cno-redzone" => self.no_redzone = value.map_or(Some(true), arg_to_bool), // https://doc.rust-lang.org/rustc/codegen-options/index.html#soft-float // Note: This flag is now deprecated in rustc. "-Csoft-float" => self.soft_float = value.map_or(Some(true), arg_to_bool), // https://doc.rust-lang.org/beta/unstable-book/compiler-flags/branch-protection.html // FIXME: Drop the -Z variant and update the doc link once the option is stabilised "-Zbranch-protection" | "-Cbranch-protection" => { self.branch_protection = Some(flag_ok_or(value, "-Zbranch-protection must have a value")?); } // https://doc.rust-lang.org/beta/unstable-book/compiler-flags/dwarf-version.html // FIXME: Drop the -Z variant and update the doc link once the option is stablized "-Zdwarf-version" | "-Cdwarf-version" => { self.dwarf_version = Some(value.and_then(arg_to_u32).ok_or(Error::new( ErrorKind::InvalidFlag, "-Zdwarf-version must have a value", ))?); } _ => {} } Ok(()) } // Rust and clang/cc don't agree on what equivalent flags should look like. pub(crate) fn cc_flags(&self, build: &Build, tool: &mut Tool, target: &TargetInfo<'_>) { let family = tool.family; // Push `flag` to `flags` if it is supported by the currently used CC let mut push_if_supported = |flag: OsString| { if build .is_flag_supported_inner(&flag, tool, target) .unwrap_or(false) { tool.args.push(flag); } else { build.cargo_output.print_warning(&format!( "Inherited flag {:?} is not supported by the currently used CC", flag )); } }; let clang_or_gnu = matches!(family, ToolFamily::Clang { .. }) || matches!(family, ToolFamily::Gnu); // Flags shared between clang and gnu if clang_or_gnu { // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mbranch-protection // https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html#index-mbranch-protection (Aarch64) // https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#index-mbranch-protection-1 (ARM) // https://developer.arm.com/documentation/101754/0619/armclang-Reference/armclang-Command-line-Options/-mbranch-protection if let Some(value) = self.branch_protection { push_if_supported( format!("-mbranch-protection={}", value.replace(",", "+")).into(), ); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mcmodel // https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-mcmodel=`). // FIXME(madsmtm): Parse the model, to make sure we pass the correct value (depending on arch). if let Some(value) = self.code_model { push_if_supported(format!("-mcmodel={value}").into()); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-vectorize // https://gcc.gnu.org/onlinedocs/gnat_ugn/Vectorization-of-loops.html if self.no_vectorize_loops { push_if_supported("-fno-vectorize".into()); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-slp-vectorize // https://gcc.gnu.org/onlinedocs/gnat_ugn/Vectorization-of-loops.html if self.no_vectorize_slp { push_if_supported("-fno-slp-vectorize".into()); } if let Some(value) = self.relocation_model { let cc_flag = match value { // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fPIC // https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fPIC "pic" => Some("-fPIC"), // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fPIE // https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fPIE "pie" => Some("-fPIE"), // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mdynamic-no-pic // https://gcc.gnu.org/onlinedocs/gcc/RS_002f6000-and-PowerPC-Options.html#index-mdynamic-no-pic "dynamic-no-pic" => Some("-mdynamic-no-pic"), _ => None, }; if let Some(cc_flag) = cc_flag { push_if_supported(cc_flag.into()); } } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fno-omit-frame-pointer // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fomit-frame-pointer // https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fomit-frame-pointer if let Some(value) = self.force_frame_pointers { let cc_flag = if value { "-fno-omit-frame-pointer" } else { "-fomit-frame-pointer" }; push_if_supported(cc_flag.into()); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mno-red-zone // https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mno-red-zone // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mred-zone // https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-mred-zone if let Some(value) = self.no_redzone { let cc_flag = if value { "-mno-red-zone" } else { "-mred-zone" }; push_if_supported(cc_flag.into()); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-msoft-float // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mhard-float // https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-msoft-float`). // https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html (several archs, search for `-mhard-float`). if let Some(value) = self.soft_float { let cc_flag = if value { "-msoft-float" } else { // Do not use -mno-soft-float, that's basically just an alias for -mno-implicit-float. "-mhard-float" }; push_if_supported(cc_flag.into()); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-gdwarf-2 // https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#index-gdwarf if let Some(value) = self.dwarf_version { push_if_supported(format!("-gdwarf-{value}").into()); } } // Compiler-exclusive flags match family { ToolFamily::Clang { .. } => { // GNU and Clang compilers both support the same PGO flags, but they use different libraries and // different formats for the profile files which are not compatible. // clang and rustc both internally use llvm, so we want to inherit the PGO flags only for clang. // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fprofile-generate if let Some(value) = self.profile_generate { push_if_supported(format!("-fprofile-generate={value}").into()); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fprofile-use if let Some(value) = self.profile_use { push_if_supported(format!("-fprofile-use={value}").into()); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fembed-bitcode if let Some(value) = self.embed_bitcode { let cc_val = if value { "all" } else { "off" }; push_if_supported(format!("-fembed-bitcode={cc_val}").into()); } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-flto if let Some(value) = self.lto { let cc_val = match value { "y" | "yes" | "on" | "true" | "fat" => Some("full"), "thin" => Some("thin"), _ => None, }; if let Some(cc_val) = cc_val { push_if_supported(format!("-flto={cc_val}").into()); } } // https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mguard if let Some(value) = self.control_flow_guard { let cc_val = match value { "y" | "yes" | "on" | "true" | "checks" => Some("cf"), "nochecks" => Some("cf-nochecks"), "n" | "no" | "off" | "false" => Some("none"), _ => None, }; if let Some(cc_val) = cc_val { push_if_supported(format!("-mguard={cc_val}").into()); } } } ToolFamily::Gnu => {} ToolFamily::Msvc { .. } => { // https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-control-flow-guard if let Some(value) = self.control_flow_guard { let cc_val = match value { "y" | "yes" | "on" | "true" | "checks" => Some("cf"), "n" | "no" | "off" | "false" => Some("cf-"), _ => None, }; if let Some(cc_val) = cc_val { push_if_supported(format!("/guard:{cc_val}").into()); } } // https://learn.microsoft.com/en-us/cpp/build/reference/oy-frame-pointer-omission if let Some(value) = self.force_frame_pointers { // Flag is unsupported on 64-bit arches if !target.arch.contains("64") { let cc_flag = if value { "/Oy-" } else { "/Oy" }; push_if_supported(cc_flag.into()); } } } } } } #[cfg(test)] mod tests { use super::*; #[track_caller] fn check(env: &str, expected: &RustcCodegenFlags) { let actual = RustcCodegenFlags::parse(env).unwrap(); assert_eq!(actual, *expected); } #[test] fn codegen_type() { let expected = RustcCodegenFlags { code_model: Some("tiny"), ..RustcCodegenFlags::default() }; check("-Ccode-model=tiny", &expected); check("-C\u{1f}code-model=tiny", &expected); check("--codegen\u{1f}code-model=tiny", &expected); check("--codegen=code-model=tiny", &expected); } #[test] fn precedence() { check( "-ccode-model=tiny\u{1f}-Ccode-model=small", &RustcCodegenFlags { code_model: Some("small"), ..RustcCodegenFlags::default() }, ); } #[test] fn two_valid_prefixes() { let expected = RustcCodegenFlags::default(); check("-L\u{1f}-Clto", &expected); } #[test] fn three_valid_prefixes() { let expected = RustcCodegenFlags { lto: Some("true"), ..RustcCodegenFlags::default() }; check("-L\u{1f}-L\u{1f}-Clto", &expected); } #[test] fn all_rustc_flags() { // Throw all possible flags at the parser to catch false positives let flags = [ // Set all the flags we recognise first "-Ccode-model=tiny", "-Ccontrol-flow-guard=yes", "-Cembed-bitcode=no", "-Cforce-frame-pointers=yes", "-Clto=false", "-Clink-dead-code=yes", "-Cno-redzone=yes", "-Cno-vectorize-loops", "-Cno-vectorize-slp", "-Cprofile-generate=fooprofile", "-Cprofile-use=fooprofile", "-Crelocation-model=pic", "-Csoft-float=yes", "-Zbranch-protection=bti,pac-ret,leaf", "-Zdwarf-version=5", // Set flags we don't recognise but rustc supports next // rustc flags "--cfg", "a", "--check-cfg 'cfg(verbose)", "-L", "/usr/lib/foo", "-l", "static:+whole-archive=mylib", "--crate-type=dylib", "--crate-name=foo", "--edition=2021", "--emit=asm", "--print=crate-name", "-g", "-O", "-o", "foooutput", "--out-dir", "foooutdir", "--target", "aarch64-unknown-linux-gnu", "-W", "missing-docs", "-D", "unused-variables", "--force-warn", "dead-code", "-A", "unused", "-F", "unused", "--cap-lints", "warn", "--version", "--verbose", "-v", "--extern", "foocrate", "--sysroot", "fooroot", "--error-format", "human", "--color", "auto", "--diagnostic-width", "80", "--remap-path-prefix", "foo=bar", "--json=artifact", // Codegen flags "-Car", "-Ccodegen-units=1", "-Ccollapse-macro-debuginfo=yes", "-Cdebug-assertions=yes", "-Cdebuginfo=1", "-Cdefault-linker-libraries=yes", "-Cdlltool=foo", "-Cextra-filename=foo", "-Cforce-unwind-tables=yes", "-Cincremental=foodir", "-Cinline-threshold=6", "-Cinstrument-coverage", "-Clink-arg=-foo", "-Clink-args=-foo", "-Clink-self-contained=yes", "-Clinker=lld", "-Clinker-flavor=ld.lld", "-Clinker-plugin-lto=yes", "-Cllvm-args=foo", "-Cmetadata=foo", "-Cno-prepopulate-passes", "-Cno-stack-check", "-Copt-level=3", "-Coverflow-checks=yes", "-Cpanic=abort", "-Cpasses=foopass", "-Cprefer-dynamic=yes", "-Crelro-level=partial", "-Cremark=all", "-Crpath=yes", "-Csave-temps=yes", "-Csplit-debuginfo=packed", "-Cstrip=symbols", "-Csymbol-mangling-version=v0", "-Ctarget-cpu=native", "-Ctarget-feature=+sve", // Unstable options "-Ztune-cpu=machine", ]; check( &flags.join("\u{1f}"), &RustcCodegenFlags { code_model: Some("tiny"), control_flow_guard: Some("yes"), embed_bitcode: Some(false), force_frame_pointers: Some(true), lto: Some("false"), no_redzone: Some(true), no_vectorize_loops: true, no_vectorize_slp: true, profile_generate: Some("fooprofile"), profile_use: Some("fooprofile"), relocation_model: Some("pic"), soft_float: Some(true), branch_protection: Some("bti,pac-ret,leaf"), dwarf_version: Some(5), }, ); } } cc/src/detect_compiler_family.c0000644000175000017500000000031615105742312016425 0ustar bdrungbdrung#ifdef __clang__ #pragma message "clang" #endif #ifdef __GNUC__ #pragma message "gcc" #endif #ifdef __EMSCRIPTEN__ #pragma message "emscripten" #endif #ifdef __VXWORKS__ #pragma message "VxWorks" #endif cc/src/windows/0000775000175000017500000000000015105742312013252 5ustar bdrungbdrungcc/src/windows/mod.rs0000644000175000017500000000070315105742312014375 0ustar bdrungbdrung//! These modules are all glue to support reading the MSVC version from //! the registry and from COM interfaces. // This is used in the crate's public API, so don't use #[cfg(windows)] pub mod find_tools; #[cfg(windows)] mod windows_link; #[cfg(windows)] pub(crate) mod windows_sys; #[cfg(windows)] mod registry; #[cfg(windows)] #[macro_use] mod winapi; #[cfg(windows)] mod com; #[cfg(windows)] mod setup_config; #[cfg(windows)] mod vs_instances; cc/src/windows/com.rs0000644000175000017500000000543115105742312014377 0ustar bdrungbdrung// Copyright © 2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. use crate::windows::{ winapi::{IUnknown, Interface}, windows_sys::{ CoInitializeEx, SysFreeString, SysStringLen, BSTR, COINIT_MULTITHREADED, HRESULT, S_FALSE, S_OK, }, }; use std::{ convert::TryInto, ffi::OsString, ops::Deref, os::windows::ffi::OsStringExt, ptr::{null, null_mut}, slice::from_raw_parts, }; pub fn initialize() -> Result<(), HRESULT> { let err = unsafe { CoInitializeEx(null(), COINIT_MULTITHREADED.try_into().unwrap()) }; if err != S_OK && err != S_FALSE { // S_FALSE just means COM is already initialized Err(err) } else { Ok(()) } } pub struct ComPtr(*mut T) where T: Interface; impl ComPtr where T: Interface, { /// Creates a `ComPtr` to wrap a raw pointer. /// It takes ownership over the pointer which means it does __not__ call `AddRef`. /// `T` __must__ be a COM interface that inherits from `IUnknown`. pub unsafe fn from_raw(ptr: *mut T) -> ComPtr { assert!(!ptr.is_null()); ComPtr(ptr) } /// For internal use only. fn as_unknown(&self) -> &IUnknown { unsafe { &*(self.0 as *mut IUnknown) } } /// Performs `QueryInterface` fun. pub fn cast(&self) -> Result, i32> where U: Interface, { let mut obj = null_mut(); let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { ComPtr::from_raw(obj as *mut U) }) } } impl Deref for ComPtr where T: Interface, { type Target = T; fn deref(&self) -> &T { unsafe { &*self.0 } } } impl Clone for ComPtr where T: Interface, { fn clone(&self) -> Self { unsafe { self.as_unknown().AddRef(); ComPtr::from_raw(self.0) } } } impl Drop for ComPtr where T: Interface, { fn drop(&mut self) { unsafe { self.as_unknown().Release(); } } } pub struct BStr(BSTR); impl BStr { pub unsafe fn from_raw(s: BSTR) -> BStr { BStr(s) } pub fn to_osstring(&self) -> OsString { let len = unsafe { SysStringLen(self.0) }; let slice = unsafe { from_raw_parts(self.0, len as usize) }; OsStringExt::from_wide(slice) } } impl Drop for BStr { fn drop(&mut self) { unsafe { SysFreeString(self.0) }; } } cc/src/windows/windows_link.rs0000644000175000017500000000160615105742312016330 0ustar bdrungbdrung//! Provides the `link!` macro used by the generated windows bindings. //! //! This is a simple wrapper around an `extern` block with a `#[link]` attribute. //! It's very roughly equivalent to the windows-targets crate. macro_rules! link_macro { ($library:literal $abi:literal $($link_name:literal)? $(#[$doc:meta])? fn $($function:tt)*) => ( // Note: the windows-targets crate uses a pre-built Windows.lib import library which we don't // have in this repo. So instead we always link kernel32.lib and add the rest of the import // libraries below by using an empty extern block. This works because extern blocks are not // connected to the library given in the #[link] attribute. #[link(name = "kernel32")] extern $abi { $(#[link_name=$link_name])? pub fn $($function)*; } ) } pub(crate) use link_macro as link; cc/src/windows/winapi.rs0000644000175000017500000001077615105742312015120 0ustar bdrungbdrung// Copyright © 2015-2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style, clippy::upper_case_acronyms)] use std::os::raw; pub type wchar_t = u16; pub use crate::windows::windows_sys::{FILETIME, GUID, HRESULT, SAFEARRAY}; pub type REFIID = *const IID; pub type IID = GUID; pub type ULONG = raw::c_ulong; pub type DWORD = u32; pub type LPFILETIME = *mut FILETIME; pub type OLECHAR = WCHAR; pub type WCHAR = wchar_t; pub type LPCOLESTR = *const OLECHAR; pub type LCID = DWORD; pub type LPCWSTR = *const WCHAR; pub type PULONGLONG = *mut ULONGLONG; pub type ULONGLONG = u64; pub trait Interface { fn uuidof() -> GUID; } pub type LPSAFEARRAY = *mut SAFEARRAY; macro_rules! DEFINE_GUID { ( $name:ident, $l:expr, $w1:expr, $w2:expr, $b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, $b6:expr, $b7:expr, $b8:expr ) => { pub const $name: $crate::windows::winapi::GUID = $crate::windows::winapi::GUID { data1: $l, data2: $w1, data3: $w2, data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8], }; }; } macro_rules! RIDL { (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( #[repr(C)] pub struct $vtbl { $(pub $method: unsafe extern "system" fn( This: *mut $interface, $($p: $t),* ) -> $rtr,)+ } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@impl $interface {$(fn $method($($p: $t,)*) -> $rtr,)+}} RIDL!{@uuid $interface $($uuid),+} ); (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) { }) => ( #[repr(C)] pub struct $vtbl { pub parent: $pvtbl, } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@deref $interface $pinterface} RIDL!{@uuid $interface $($uuid),+} ); (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( #[repr(C)] pub struct $vtbl { pub parent: $pvtbl, $(pub $method: unsafe extern "system" fn( This: *mut $interface, $($p: $t,)* ) -> $rtr,)+ } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@impl $interface {$(fn $method($($p: $t,)*) -> $rtr,)+}} RIDL!{@deref $interface $pinterface} RIDL!{@uuid $interface $($uuid),+} ); (@deref $interface:ident $pinterface:ident) => ( impl ::std::ops::Deref for $interface { type Target = $pinterface; #[inline] fn deref(&self) -> &$pinterface { unsafe { &*(self as *const $interface as *const $pinterface) } } } ); (@impl $interface:ident {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( impl $interface { $(#[inline] pub unsafe fn $method(&self, $($p: $t,)*) -> $rtr { ((*self.lpVtbl).$method)(self as *const _ as *mut _, $($p,)*) })+ } ); (@uuid $interface:ident $l:expr, $w1:expr, $w2:expr, $b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, $b6:expr, $b7:expr, $b8:expr ) => ( impl $crate::windows::winapi::Interface for $interface { #[inline] fn uuidof() -> $crate::windows::winapi::GUID { $crate::windows::winapi::GUID { data1: $l, data2: $w1, data3: $w2, data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8], } } } ); } RIDL! {#[uuid(0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)] interface IUnknown(IUnknownVtbl) { fn QueryInterface( riid: REFIID, ppvObject: *mut *mut raw::c_void, ) -> HRESULT, fn AddRef() -> ULONG, fn Release() -> ULONG, }} cc/src/windows/windows_sys.rs0000644000175000017500000001360415105742312016212 0ustar bdrungbdrung// This file is autogenerated. // // To add bindings, edit windows_sys.lst then run: // // ``` // cd generate-windows-sys/ // cargo run // ``` // Bindings generated by `windows-bindgen` 0.61.1 #![allow( non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all )] windows_link::link!("ole32.dll" "system" fn CoCreateInstance(rclsid : *const GUID, punkouter : * mut core::ffi::c_void, dwclscontext : CLSCTX, riid : *const GUID, ppv : *mut *mut core::ffi::c_void) -> HRESULT); windows_link::link!("ole32.dll" "system" fn CoInitializeEx(pvreserved : *const core::ffi::c_void, dwcoinit : u32) -> HRESULT); windows_link::link!("kernel32.dll" "system" fn FreeLibrary(hlibmodule : HMODULE) -> BOOL); windows_link::link!("kernel32.dll" "system" fn GetMachineTypeAttributes(machine : u16, machinetypeattributes : *mut MACHINE_ATTRIBUTES) -> HRESULT); windows_link::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : HMODULE, lpprocname : PCSTR) -> FARPROC); windows_link::link!("kernel32.dll" "system" fn LoadLibraryA(lplibfilename : PCSTR) -> HMODULE); windows_link::link!("kernel32.dll" "system" fn OpenSemaphoreA(dwdesiredaccess : u32, binherithandle : BOOL, lpname : PCSTR) -> HANDLE); windows_link::link!("kernel32.dll" "system" fn PeekNamedPipe(hnamedpipe : HANDLE, lpbuffer : *mut core::ffi::c_void, nbuffersize : u32, lpbytesread : *mut u32, lptotalbytesavail : *mut u32, lpbytesleftthismessage : *mut u32) -> BOOL); windows_link::link!("advapi32.dll" "system" fn RegCloseKey(hkey : HKEY) -> WIN32_ERROR); windows_link::link!("advapi32.dll" "system" fn RegEnumKeyExW(hkey : HKEY, dwindex : u32, lpname : PWSTR, lpcchname : *mut u32, lpreserved : *const u32, lpclass : PWSTR, lpcchclass : *mut u32, lpftlastwritetime : *mut FILETIME) -> WIN32_ERROR); windows_link::link!("advapi32.dll" "system" fn RegOpenKeyExW(hkey : HKEY, lpsubkey : PCWSTR, uloptions : u32, samdesired : REG_SAM_FLAGS, phkresult : *mut HKEY) -> WIN32_ERROR); windows_link::link!("advapi32.dll" "system" fn RegQueryValueExW(hkey : HKEY, lpvaluename : PCWSTR, lpreserved : *const u32, lptype : *mut REG_VALUE_TYPE, lpdata : *mut u8, lpcbdata : *mut u32) -> WIN32_ERROR); windows_link::link!("kernel32.dll" "system" fn ReleaseSemaphore(hsemaphore : HANDLE, lreleasecount : i32, lppreviouscount : *mut i32) -> BOOL); windows_link::link!("oleaut32.dll" "system" fn SysFreeString(bstrstring : BSTR)); windows_link::link!("oleaut32.dll" "system" fn SysStringLen(pbstr : BSTR) -> u32); windows_link::link!("kernel32.dll" "system" fn WaitForSingleObject(hhandle : HANDLE, dwmilliseconds : u32) -> WAIT_EVENT); pub type ADVANCED_FEATURE_FLAGS = u16; pub type BOOL = i32; pub type BSTR = *const u16; pub type CLSCTX = u32; pub const CLSCTX_ALL: CLSCTX = 23u32; pub type COINIT = i32; pub const COINIT_MULTITHREADED: COINIT = 0i32; pub const ERROR_NO_MORE_ITEMS: WIN32_ERROR = 259u32; pub const ERROR_SUCCESS: WIN32_ERROR = 0u32; pub const FALSE: BOOL = 0i32; pub type FARPROC = Option isize>; #[repr(C)] #[derive(Clone, Copy, Default)] pub struct FILETIME { pub dwLowDateTime: u32, pub dwHighDateTime: u32, } pub const FILE_ATTRIBUTE_TEMPORARY: FILE_FLAGS_AND_ATTRIBUTES = 256u32; pub type FILE_FLAGS_AND_ATTRIBUTES = u32; #[repr(C)] #[derive(Clone, Copy)] pub struct GUID { pub data1: u32, pub data2: u16, pub data3: u16, pub data4: [u8; 8], } impl GUID { pub const fn from_u128(uuid: u128) -> Self { Self { data1: (uuid >> 96) as u32, data2: (uuid >> 80 & 0xffff) as u16, data3: (uuid >> 64 & 0xffff) as u16, data4: (uuid as u64).to_be_bytes(), } } } pub type HANDLE = *mut core::ffi::c_void; pub type HINSTANCE = *mut core::ffi::c_void; pub type HKEY = *mut core::ffi::c_void; pub const HKEY_LOCAL_MACHINE: HKEY = -2147483646i32 as _; pub type HMODULE = *mut core::ffi::c_void; pub type HRESULT = i32; pub type IMAGE_FILE_MACHINE = u16; pub const IMAGE_FILE_MACHINE_AMD64: IMAGE_FILE_MACHINE = 34404u16; pub const IID_IUnknown: GUID = GUID::from_u128(0x00000000_0000_0000_c000_000000000046); #[repr(C)] pub struct IUnknown_Vtbl { pub QueryInterface: unsafe extern "system" fn( this: *mut core::ffi::c_void, iid: *const GUID, interface: *mut *mut core::ffi::c_void, ) -> HRESULT, pub AddRef: unsafe extern "system" fn(this: *mut core::ffi::c_void) -> u32, pub Release: unsafe extern "system" fn(this: *mut core::ffi::c_void) -> u32, } pub const KEY_READ: REG_SAM_FLAGS = 131097u32; pub const KEY_WOW64_32KEY: REG_SAM_FLAGS = 512u32; pub type MACHINE_ATTRIBUTES = i32; pub type PCSTR = *const u8; pub type PCWSTR = *const u16; pub type PWSTR = *mut u16; pub type REG_SAM_FLAGS = u32; pub const REG_SZ: REG_VALUE_TYPE = 1u32; pub type REG_VALUE_TYPE = u32; #[repr(C)] #[derive(Clone, Copy)] pub struct SAFEARRAY { pub cDims: u16, pub fFeatures: ADVANCED_FEATURE_FLAGS, pub cbElements: u32, pub cLocks: u32, pub pvData: *mut core::ffi::c_void, pub rgsabound: [SAFEARRAYBOUND; 1], } impl Default for SAFEARRAY { fn default() -> Self { unsafe { core::mem::zeroed() } } } #[repr(C)] #[derive(Clone, Copy, Default)] pub struct SAFEARRAYBOUND { pub cElements: u32, pub lLbound: i32, } pub const SEMAPHORE_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32; pub type SYNCHRONIZATION_ACCESS_RIGHTS = u32; pub const S_FALSE: HRESULT = 0x1_u32 as _; pub const S_OK: HRESULT = 0x0_u32 as _; pub type THREAD_ACCESS_RIGHTS = u32; pub const THREAD_SYNCHRONIZE: THREAD_ACCESS_RIGHTS = 1048576u32; pub const UserEnabled: MACHINE_ATTRIBUTES = 1i32; pub const WAIT_ABANDONED: WAIT_EVENT = 128u32; pub type WAIT_EVENT = u32; pub const WAIT_FAILED: WAIT_EVENT = 4294967295u32; pub const WAIT_OBJECT_0: WAIT_EVENT = 0u32; pub const WAIT_TIMEOUT: WAIT_EVENT = 258u32; pub type WIN32_ERROR = u32; #[link(name = "advapi32")] #[link(name = "ole32")] #[link(name = "oleaut32")] extern "C" {} use super::windows_link; cc/src/windows/find_tools.rs0000644000175000017500000013260415105742312015764 0ustar bdrungbdrung// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A helper module to looking for windows-specific tools: //! 1. On Windows host, probe the Windows Registry if needed; //! 2. On non-Windows host, check specified environment variables. #![allow(clippy::upper_case_acronyms)] use std::{ env, ffi::{OsStr, OsString}, ops::Deref, path::PathBuf, process::Command, sync::Arc, }; use crate::Tool; use crate::ToolFamily; const MSVC_FAMILY: ToolFamily = ToolFamily::Msvc { clang_cl: false }; /// The target provided by the user. #[derive(Copy, Clone, PartialEq, Eq)] enum TargetArch { X86, X64, Arm, Arm64, Arm64ec, } impl TargetArch { /// Parse the `TargetArch` from a str. Returns `None` if the arch is unrecognized. fn new(arch: &str) -> Option { // NOTE: Keep up to date with docs in [`find`]. match arch { "x64" | "x86_64" => Some(Self::X64), "arm64" | "aarch64" => Some(Self::Arm64), "arm64ec" => Some(Self::Arm64ec), "x86" | "i686" | "i586" => Some(Self::X86), "arm" | "thumbv7a" => Some(Self::Arm), _ => None, } } #[cfg(windows)] /// Gets the Visual Studio name for the architecture. fn as_vs_arch(&self) -> &'static str { match self { Self::X64 => "x64", Self::Arm64 | Self::Arm64ec => "arm64", Self::X86 => "x86", Self::Arm => "arm", } } } pub(crate) enum Env { Owned(OsString), Arced(Arc), } impl AsRef for Env { fn as_ref(&self) -> &OsStr { self.deref() } } impl Deref for Env { type Target = OsStr; fn deref(&self) -> &Self::Target { match self { Env::Owned(os_str) => os_str, Env::Arced(os_str) => os_str, } } } impl From for PathBuf { fn from(env: Env) -> Self { match env { Env::Owned(os_str) => PathBuf::from(os_str), Env::Arced(os_str) => PathBuf::from(os_str.deref()), } } } pub(crate) trait EnvGetter { fn get_env(&self, name: &'static str) -> Option; } struct StdEnvGetter; impl EnvGetter for StdEnvGetter { #[allow(clippy::disallowed_methods)] fn get_env(&self, name: &'static str) -> Option { env::var_os(name).map(Env::Owned) } } /// Attempts to find a tool within an MSVC installation using the Windows /// registry as a point to search from. /// /// The `arch_or_target` argument is the architecture or the Rust target name /// that the tool should work for (e.g. compile or link for). The supported /// architecture names are: /// - `"x64"` or `"x86_64"` /// - `"arm64"` or `"aarch64"` /// - `"arm64ec"` /// - `"x86"`, `"i586"` or `"i686"` /// - `"arm"` or `"thumbv7a"` /// /// The `tool` argument is the tool to find (e.g. `cl.exe` or `link.exe`). /// /// This function will return `None` if the tool could not be found, or it will /// return `Some(cmd)` which represents a command that's ready to execute the /// tool with the appropriate environment variables set. /// /// Note that this function always returns `None` for non-MSVC targets (if a /// full target name was specified). pub fn find(arch_or_target: &str, tool: &str) -> Option { find_tool(arch_or_target, tool).map(|c| c.to_command()) } /// Similar to the `find` function above, this function will attempt the same /// operation (finding a MSVC tool in a local install) but instead returns a /// `Tool` which may be introspected. pub fn find_tool(arch_or_target: &str, tool: &str) -> Option { let full_arch = if let Some((full_arch, rest)) = arch_or_target.split_once("-") { // The logic is all tailored for MSVC, if the target is not that then // bail out early. if !rest.contains("msvc") { return None; } full_arch } else { arch_or_target }; find_tool_inner(full_arch, tool, &StdEnvGetter) } pub(crate) fn find_tool_inner( full_arch: &str, tool: &str, env_getter: &dyn EnvGetter, ) -> Option { // We only need the arch. let target = TargetArch::new(full_arch)?; // Looks like msbuild isn't located in the same location as other tools like // cl.exe and lib.exe. if tool.contains("msbuild") { return impl_::find_msbuild(target, env_getter); } // Looks like devenv isn't located in the same location as other tools like // cl.exe and lib.exe. if tool.contains("devenv") { return impl_::find_devenv(target, env_getter); } // Ok, if we're here, now comes the fun part of the probing. Default shells // or shells like MSYS aren't really configured to execute `cl.exe` and the // various compiler tools shipped as part of Visual Studio. Here we try to // first find the relevant tool, then we also have to be sure to fill in // environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that // the tool is actually usable. impl_::find_msvc_environment(tool, target, env_getter) .or_else(|| impl_::find_msvc_15plus(tool, target, env_getter)) .or_else(|| impl_::find_msvc_14(tool, target, env_getter)) } /// A version of Visual Studio #[derive(Debug, PartialEq, Eq, Copy, Clone)] #[non_exhaustive] pub enum VsVers { /// Visual Studio 12 (2013) #[deprecated( note = "Visual Studio 12 is no longer supported. cc will never return this value." )] Vs12, /// Visual Studio 14 (2015) Vs14, /// Visual Studio 15 (2017) Vs15, /// Visual Studio 16 (2019) Vs16, /// Visual Studio 17 (2022) Vs17, } /// Find the most recent installed version of Visual Studio /// /// This is used by the cmake crate to figure out the correct /// generator. #[allow(clippy::disallowed_methods)] pub fn find_vs_version() -> Result { fn has_msbuild_version(version: &str) -> bool { impl_::has_msbuild_version(version, &StdEnvGetter) } match std::env::var("VisualStudioVersion") { Ok(version) => match &version[..] { "17.0" => Ok(VsVers::Vs17), "16.0" => Ok(VsVers::Vs16), "15.0" => Ok(VsVers::Vs15), "14.0" => Ok(VsVers::Vs14), vers => Err(format!( "\n\n\ unsupported or unknown VisualStudio version: {}\n\ if another version is installed consider running \ the appropriate vcvars script before building this \ crate\n\ ", vers )), }, _ => { // Check for the presence of a specific registry key // that indicates visual studio is installed. if has_msbuild_version("17.0") { Ok(VsVers::Vs17) } else if has_msbuild_version("16.0") { Ok(VsVers::Vs16) } else if has_msbuild_version("15.0") { Ok(VsVers::Vs15) } else if has_msbuild_version("14.0") { Ok(VsVers::Vs14) } else { Err("\n\n\ couldn't determine visual studio generator\n\ if VisualStudio is installed, however, consider \ running the appropriate vcvars script before building \ this crate\n\ " .to_string()) } } } } /// Windows Implementation. #[cfg(windows)] mod impl_ { use crate::windows::com; use crate::windows::registry::{RegistryKey, LOCAL_MACHINE}; use crate::windows::setup_config::SetupConfiguration; use crate::windows::vs_instances::{VsInstances, VswhereInstance}; use crate::windows::windows_sys::{ GetMachineTypeAttributes, GetProcAddress, LoadLibraryA, UserEnabled, HMODULE, IMAGE_FILE_MACHINE_AMD64, MACHINE_ATTRIBUTES, S_OK, }; use std::convert::TryFrom; use std::env; use std::ffi::OsString; use std::fs::File; use std::io::Read; use std::iter; use std::mem; use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; use super::{EnvGetter, TargetArch, MSVC_FAMILY}; use crate::Tool; struct MsvcTool { tool: PathBuf, libs: Vec, path: Vec, include: Vec, } struct LibraryHandle(HMODULE); impl LibraryHandle { fn new(name: &[u8]) -> Option { let handle = unsafe { LoadLibraryA(name.as_ptr() as _) }; (!handle.is_null()).then_some(Self(handle)) } /// Get a function pointer to a function in the library. /// # SAFETY /// /// The caller must ensure that the function signature matches the actual function. /// The easiest way to do this is to add an entry to `windows_sys_no_link.list` and use the /// generated function for `func_signature`. /// /// The function returned cannot be used after the handle is dropped. unsafe fn get_proc_address(&self, name: &[u8]) -> Option { let symbol = GetProcAddress(self.0, name.as_ptr() as _); symbol.map(|symbol| mem::transmute_copy(&symbol)) } } type GetMachineTypeAttributesFuncType = unsafe extern "system" fn(u16, *mut MACHINE_ATTRIBUTES) -> i32; const _: () = { // Ensure that our hand-written signature matches the actual function signature. // We can't use `GetMachineTypeAttributes` outside of a const scope otherwise we'll end up statically linking to // it, which will fail to load on older versions of Windows. let _: GetMachineTypeAttributesFuncType = GetMachineTypeAttributes; }; fn is_amd64_emulation_supported_inner() -> Option { // GetMachineTypeAttributes is only available on Win11 22000+, so dynamically load it. let kernel32 = LibraryHandle::new(b"kernel32.dll\0")?; // SAFETY: GetMachineTypeAttributesFuncType is checked to match the real function signature. let get_machine_type_attributes = unsafe { kernel32 .get_proc_address::(b"GetMachineTypeAttributes\0") }?; let mut attributes = Default::default(); if unsafe { get_machine_type_attributes(IMAGE_FILE_MACHINE_AMD64, &mut attributes) } == S_OK { Some((attributes & UserEnabled) != 0) } else { Some(false) } } fn is_amd64_emulation_supported() -> bool { // TODO: Replace with a OnceLock once MSRV is 1.70. static LOAD_VALUE: Once = Once::new(); static IS_SUPPORTED: AtomicBool = AtomicBool::new(false); // Using Relaxed ordering since the Once is providing synchronization. LOAD_VALUE.call_once(|| { IS_SUPPORTED.store( is_amd64_emulation_supported_inner().unwrap_or(false), Ordering::Relaxed, ); }); IS_SUPPORTED.load(Ordering::Relaxed) } impl MsvcTool { fn new(tool: PathBuf) -> MsvcTool { MsvcTool { tool, libs: Vec::new(), path: Vec::new(), include: Vec::new(), } } fn into_tool(self, env_getter: &dyn EnvGetter) -> Tool { let MsvcTool { tool, libs, path, include, } = self; let mut tool = Tool::with_family(tool, MSVC_FAMILY); add_env(&mut tool, "LIB", libs, env_getter); add_env(&mut tool, "PATH", path, env_getter); add_env(&mut tool, "INCLUDE", include, env_getter); tool } } /// Checks to see if the target's arch matches the VS environment. Returns `None` if the /// environment is unknown. fn is_vscmd_target(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { is_vscmd_target_env(target, env_getter).or_else(|| is_vscmd_target_cl(target, env_getter)) } /// Checks to see if the `VSCMD_ARG_TGT_ARCH` environment variable matches the /// given target's arch. Returns `None` if the variable does not exist. fn is_vscmd_target_env(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { let vscmd_arch = env_getter.get_env("VSCMD_ARG_TGT_ARCH")?; Some(target.as_vs_arch() == vscmd_arch.as_ref()) } /// Checks if the cl.exe target matches the given target's arch. Returns `None` if anything /// fails. fn is_vscmd_target_cl(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { let cmd_target = vscmd_target_cl(env_getter)?; Some(target.as_vs_arch() == cmd_target) } /// Detect the target architecture of `cl.exe` in the current path, and return `None` if this /// fails for any reason. fn vscmd_target_cl(env_getter: &dyn EnvGetter) -> Option<&'static str> { let cl_exe = env_getter.get_env("PATH").and_then(|path| { env::split_paths(&path) .map(|p| p.join("cl.exe")) .find(|p| p.exists()) })?; let mut cl = Command::new(cl_exe); cl.stderr(std::process::Stdio::piped()) .stdout(std::process::Stdio::null()); let out = cl.output().ok()?; let cl_arch = out .stderr .split(|&b| b == b'\n' || b == b'\r') .next()? .rsplit(|&b| b == b' ') .next()?; match cl_arch { b"x64" => Some("x64"), b"x86" => Some("x86"), b"ARM64" => Some("arm64"), b"ARM" => Some("arm"), _ => None, } } /// Attempt to find the tool using environment variables set by vcvars. pub(super) fn find_msvc_environment( tool: &str, target: TargetArch, env_getter: &dyn EnvGetter, ) -> Option { // Early return if the environment isn't one that is known to have compiler toolsets in PATH // `VCINSTALLDIR` is set from vcvarsall.bat (developer command prompt) // `VSTEL_MSBuildProjectFullPath` is set by msbuild when invoking custom build steps // NOTE: `VisualStudioDir` used to be used but this isn't set when invoking msbuild from the commandline if env_getter.get_env("VCINSTALLDIR").is_none() && env_getter.get_env("VSTEL_MSBuildProjectFullPath").is_none() { return None; } // If the vscmd target differs from the requested target then // attempt to get the tool using the VS install directory. if is_vscmd_target(target, env_getter) == Some(false) { // We will only get here with versions 15+. let vs_install_dir: PathBuf = env_getter.get_env("VSINSTALLDIR")?.into(); tool_from_vs15plus_instance(tool, target, &vs_install_dir, env_getter) } else { // Fallback to simply using the current environment. env_getter .get_env("PATH") .and_then(|path| { env::split_paths(&path) .map(|p| p.join(tool)) .find(|p| p.exists()) }) .map(|path| Tool::with_family(path, MSVC_FAMILY)) } } fn find_msbuild_vs17(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { find_tool_in_vs16plus_path(r"MSBuild\Current\Bin\MSBuild.exe", target, "17", env_getter) } #[allow(bare_trait_objects)] fn vs16plus_instances( target: TargetArch, version: &'static str, env_getter: &dyn EnvGetter, ) -> Box> { let instances = if let Some(instances) = vs15plus_instances(target, env_getter) { instances } else { return Box::new(iter::empty()); }; Box::new(instances.into_iter().filter_map(move |instance| { let installation_name = instance.installation_name()?; if installation_name.starts_with(&format!("VisualStudio/{}.", version)) || installation_name.starts_with(&format!("VisualStudioPreview/{}.", version)) { Some(instance.installation_path()?) } else { None } })) } fn find_tool_in_vs16plus_path( tool: &str, target: TargetArch, version: &'static str, env_getter: &dyn EnvGetter, ) -> Option { vs16plus_instances(target, version, env_getter) .filter_map(|path| { let path = path.join(tool); if !path.is_file() { return None; } let mut tool = Tool::with_family(path, MSVC_FAMILY); if target == TargetArch::X64 { tool.env.push(("Platform".into(), "X64".into())); } if matches!(target, TargetArch::Arm64 | TargetArch::Arm64ec) { tool.env.push(("Platform".into(), "ARM64".into())); } Some(tool) }) .next() } fn find_msbuild_vs16(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { find_tool_in_vs16plus_path(r"MSBuild\Current\Bin\MSBuild.exe", target, "16", env_getter) } // In MSVC 15 (2017) MS once again changed the scheme for locating // the tooling. Now we must go through some COM interfaces, which // is super fun for Rust. // // Note that much of this logic can be found [online] wrt paths, COM, etc. // // [online]: https://blogs.msdn.microsoft.com/vcblog/2017/03/06/finding-the-visual-c-compiler-tools-in-visual-studio-2017/ // // Returns MSVC 15+ instances (15, 16 right now), the order should be consider undefined. // // However, on ARM64 this method doesn't work because VS Installer fails to register COM component on ARM64. // Hence, as the last resort we try to use vswhere.exe to list available instances. fn vs15plus_instances(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { vs15plus_instances_using_com() .or_else(|| vs15plus_instances_using_vswhere(target, env_getter)) } fn vs15plus_instances_using_com() -> Option { com::initialize().ok()?; let config = SetupConfiguration::new().ok()?; let enum_setup_instances = config.enum_all_instances().ok()?; Some(VsInstances::ComBased(enum_setup_instances)) } fn vs15plus_instances_using_vswhere( target: TargetArch, env_getter: &dyn EnvGetter, ) -> Option { let program_files_path = env_getter .get_env("ProgramFiles(x86)") .or_else(|| env_getter.get_env("ProgramFiles"))?; let program_files_path = Path::new(program_files_path.as_ref()); let vswhere_path = program_files_path.join(r"Microsoft Visual Studio\Installer\vswhere.exe"); if !vswhere_path.exists() { return None; } let tools_arch = match target { TargetArch::X86 | TargetArch::X64 => Some("x86.x64"), TargetArch::Arm => Some("ARM"), TargetArch::Arm64 | TargetArch::Arm64ec => Some("ARM64"), }; let vswhere_output = Command::new(vswhere_path) .args([ "-latest", "-products", "*", "-requires", &format!("Microsoft.VisualStudio.Component.VC.Tools.{}", tools_arch?), "-format", "text", "-nologo", ]) .stderr(std::process::Stdio::inherit()) .output() .ok()?; let vs_instances = VsInstances::VswhereBased(VswhereInstance::try_from(&vswhere_output.stdout).ok()?); Some(vs_instances) } // Inspired from official microsoft/vswhere ParseVersionString // i.e. at most four u16 numbers separated by '.' fn parse_version(version: &str) -> Option> { version .split('.') .map(|chunk| u16::from_str(chunk).ok()) .collect() } pub(super) fn find_msvc_15plus( tool: &str, target: TargetArch, env_getter: &dyn EnvGetter, ) -> Option { let iter = vs15plus_instances(target, env_getter)?; iter.into_iter() .filter_map(|instance| { let version = parse_version(&instance.installation_version()?)?; let instance_path = instance.installation_path()?; let tool = tool_from_vs15plus_instance(tool, target, &instance_path, env_getter)?; Some((version, tool)) }) .max_by(|(a_version, _), (b_version, _)| a_version.cmp(b_version)) .map(|(_version, tool)| tool) } // While the paths to Visual Studio 2017's devenv and MSBuild could // potentially be retrieved from the registry, finding them via // SetupConfiguration has shown to be [more reliable], and is preferred // according to Microsoft. To help head off potential regressions though, // we keep the registry method as a fallback option. // // [more reliable]: https://github.com/rust-lang/cc-rs/pull/331 fn find_tool_in_vs15_path( tool: &str, target: TargetArch, env_getter: &dyn EnvGetter, ) -> Option { let mut path = match vs15plus_instances(target, env_getter) { Some(instances) => instances .into_iter() .filter_map(|instance| instance.installation_path()) .map(|path| path.join(tool)) .find(|path| path.is_file()), None => None, }; if path.is_none() { let key = r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7"; path = LOCAL_MACHINE .open(key.as_ref()) .ok() .and_then(|key| key.query_str("15.0").ok()) .map(|path| PathBuf::from(path).join(tool)) .and_then(|path| if path.is_file() { Some(path) } else { None }); } path.map(|path| { let mut tool = Tool::with_family(path, MSVC_FAMILY); if target == TargetArch::X64 { tool.env.push(("Platform".into(), "X64".into())); } else if matches!(target, TargetArch::Arm64 | TargetArch::Arm64ec) { tool.env.push(("Platform".into(), "ARM64".into())); } tool }) } fn tool_from_vs15plus_instance( tool: &str, target: TargetArch, instance_path: &Path, env_getter: &dyn EnvGetter, ) -> Option { let (root_path, bin_path, host_dylib_path, lib_path, alt_lib_path, include_path) = vs15plus_vc_paths(target, instance_path, env_getter)?; let tool_path = bin_path.join(tool); if !tool_path.exists() { return None; }; let mut tool = MsvcTool::new(tool_path); tool.path.push(bin_path.clone()); tool.path.push(host_dylib_path); if let Some(alt_lib_path) = alt_lib_path { tool.libs.push(alt_lib_path); } tool.libs.push(lib_path); tool.include.push(include_path); if let Some((atl_lib_path, atl_include_path)) = atl_paths(target, &root_path) { tool.libs.push(atl_lib_path); tool.include.push(atl_include_path); } add_sdks(&mut tool, target, env_getter)?; Some(tool.into_tool(env_getter)) } fn vs15plus_vc_paths( target_arch: TargetArch, instance_path: &Path, env_getter: &dyn EnvGetter, ) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf, Option, PathBuf)> { let version = vs15plus_vc_read_version(instance_path)?; let hosts = match host_arch() { X86 => &["X86"], X86_64 => &["X64"], // Starting with VS 17.4, there is a natively hosted compiler on ARM64: // https://devblogs.microsoft.com/visualstudio/arm64-visual-studio-is-officially-here/ // On older versions of VS, we use x64 if running under emulation is supported, // otherwise use x86. AARCH64 => { if is_amd64_emulation_supported() { &["ARM64", "X64", "X86"][..] } else { &["ARM64", "X86"] } } _ => return None, }; let target_dir = target_arch.as_vs_arch(); // The directory layout here is MSVC/bin/Host$host/$target/ let path = instance_path.join(r"VC\Tools\MSVC").join(version); // We use the first available host architecture that can build for the target let (host_path, host) = hosts.iter().find_map(|&x| { let candidate = path.join("bin").join(format!("Host{}", x)); if candidate.join(target_dir).exists() { Some((candidate, x)) } else { None } })?; // This is the path to the toolchain for a particular target, running // on a given host let bin_path = host_path.join(target_dir); // But! we also need PATH to contain the target directory for the host // architecture, because it contains dlls like mspdb140.dll compiled for // the host architecture. let host_dylib_path = host_path.join(host.to_lowercase()); let lib_fragment = if use_spectre_mitigated_libs(env_getter) { r"lib\spectre" } else { "lib" }; let lib_path = path.join(lib_fragment).join(target_dir); let alt_lib_path = (target_arch == TargetArch::Arm64ec).then(|| path.join(lib_fragment).join("arm64ec")); let include_path = path.join("include"); Some(( path, bin_path, host_dylib_path, lib_path, alt_lib_path, include_path, )) } fn vs15plus_vc_read_version(dir: &Path) -> Option { // Try to open the default version file. let mut version_path: PathBuf = dir.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"); let mut version_file = if let Ok(f) = File::open(&version_path) { f } else { // If the default doesn't exist, search for other version files. // These are in the form Microsoft.VCToolsVersion.v143.default.txt // where `143` is any three decimal digit version number. // This sorts versions by lexical order and selects the highest version. let mut version_file = String::new(); version_path.pop(); for file in version_path.read_dir().ok()? { let name = file.ok()?.file_name(); let name = name.to_str()?; if name.starts_with("Microsoft.VCToolsVersion.v") && name.ends_with(".default.txt") && name > &version_file { version_file.replace_range(.., name); } } if version_file.is_empty() { return None; } version_path.push(version_file); File::open(version_path).ok()? }; // Get the version string from the file we found. let mut version = String::new(); version_file.read_to_string(&mut version).ok()?; version.truncate(version.trim_end().len()); Some(version) } fn use_spectre_mitigated_libs(env_getter: &dyn EnvGetter) -> bool { env_getter .get_env("VSCMD_ARG_VCVARS_SPECTRE") .map(|env| env.as_ref() == "spectre") .unwrap_or_default() } fn atl_paths(target: TargetArch, path: &Path) -> Option<(PathBuf, PathBuf)> { let atl_path = path.join("atlmfc"); let sub = target.as_vs_arch(); if atl_path.exists() { Some((atl_path.join("lib").join(sub), atl_path.join("include"))) } else { None } } // For MSVC 14 we need to find the Universal CRT as well as either // the Windows 10 SDK or Windows 8.1 SDK. pub(super) fn find_msvc_14( tool: &str, target: TargetArch, env_getter: &dyn EnvGetter, ) -> Option { let vcdir = get_vc_dir("14.0")?; let mut tool = get_tool(tool, &vcdir, target)?; add_sdks(&mut tool, target, env_getter)?; Some(tool.into_tool(env_getter)) } fn add_sdks(tool: &mut MsvcTool, target: TargetArch, env_getter: &dyn EnvGetter) -> Option<()> { let sub = target.as_vs_arch(); let (ucrt, ucrt_version) = get_ucrt_dir()?; let host = match host_arch() { X86 => "x86", X86_64 => "x64", AARCH64 => "arm64", _ => return None, }; tool.path .push(ucrt.join("bin").join(&ucrt_version).join(host)); let ucrt_include = ucrt.join("include").join(&ucrt_version); tool.include.push(ucrt_include.join("ucrt")); let ucrt_lib = ucrt.join("lib").join(&ucrt_version); tool.libs.push(ucrt_lib.join("ucrt").join(sub)); if let Some((sdk, version)) = get_sdk10_dir(env_getter) { tool.path.push(sdk.join("bin").join(host)); let sdk_lib = sdk.join("lib").join(&version); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk.join("include").join(&version); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("cppwinrt")); tool.include.push(sdk_include.join("winrt")); tool.include.push(sdk_include.join("shared")); } else if let Some(sdk) = get_sdk81_dir() { tool.path.push(sdk.join("bin").join(host)); let sdk_lib = sdk.join("lib").join("winv6.3"); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk.join("include"); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("winrt")); tool.include.push(sdk_include.join("shared")); } Some(()) } fn add_env( tool: &mut Tool, env: &'static str, paths: Vec, env_getter: &dyn EnvGetter, ) { let prev = env_getter.get_env(env); let prev = prev.as_ref().map(AsRef::as_ref).unwrap_or_default(); let prev = env::split_paths(&prev); let new = paths.into_iter().chain(prev); tool.env .push((env.to_string().into(), env::join_paths(new).unwrap())); } // Given a possible MSVC installation directory, we look for the linker and // then add the MSVC library path. fn get_tool(tool: &str, path: &Path, target: TargetArch) -> Option { bin_subdir(target) .into_iter() .map(|(sub, host)| { ( path.join("bin").join(sub).join(tool), path.join("bin").join(host), ) }) .filter(|(path, _)| path.is_file()) .map(|(path, host)| { let mut tool = MsvcTool::new(path); tool.path.push(host); tool }) .filter_map(|mut tool| { let sub = vc_lib_subdir(target); tool.libs.push(path.join("lib").join(sub)); tool.include.push(path.join("include")); let atlmfc_path = path.join("atlmfc"); if atlmfc_path.exists() { tool.libs.push(atlmfc_path.join("lib").join(sub)); tool.include.push(atlmfc_path.join("include")); } Some(tool) }) .next() } // To find MSVC we look in a specific registry key for the version we are // trying to find. fn get_vc_dir(ver: &str) -> Option { let key = r"SOFTWARE\Microsoft\VisualStudio\SxS\VC7"; let key = LOCAL_MACHINE.open(key.as_ref()).ok()?; let path = key.query_str(ver).ok()?; Some(path.into()) } // To find the Universal CRT we look in a specific registry key for where // all the Universal CRTs are located and then sort them asciibetically to // find the newest version. While this sort of sorting isn't ideal, it is // what vcvars does so that's good enough for us. // // Returns a pair of (root, version) for the ucrt dir if found fn get_ucrt_dir() -> Option<(PathBuf, String)> { let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots"; let key = LOCAL_MACHINE.open(key.as_ref()).ok()?; let root = key.query_str("KitsRoot10").ok()?; let readdir = Path::new(&root).join("lib").read_dir().ok()?; let max_libdir = readdir .filter_map(|dir| dir.ok()) .map(|dir| dir.path()) .filter(|dir| { dir.components() .last() .and_then(|c| c.as_os_str().to_str()) .map(|c| c.starts_with("10.") && dir.join("ucrt").is_dir()) .unwrap_or(false) }) .max()?; let version = max_libdir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) } // Vcvars finds the correct version of the Windows 10 SDK by looking // for the include `um\Windows.h` because sometimes a given version will // only have UCRT bits without the rest of the SDK. Since we only care about // libraries and not includes, we instead look for `um\x64\kernel32.lib`. // Since the 32-bit and 64-bit libraries are always installed together we // only need to bother checking x64, making this code a tiny bit simpler. // Like we do for the Universal CRT, we sort the possibilities // asciibetically to find the newest one as that is what vcvars does. // Before doing that, we check the "WindowsSdkDir" and "WindowsSDKVersion" // environment variables set by vcvars to use the environment sdk version // if one is already configured. fn get_sdk10_dir(env_getter: &dyn EnvGetter) -> Option<(PathBuf, String)> { if let (Some(root), Some(version)) = ( env_getter.get_env("WindowsSdkDir"), env_getter .get_env("WindowsSDKVersion") .as_ref() .and_then(|version| version.as_ref().to_str()), ) { return Some(( PathBuf::from(root), version.trim_end_matches('\\').to_string(), )); } let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0"; let key = LOCAL_MACHINE.open(key.as_ref()).ok()?; let root = key.query_str("InstallationFolder").ok()?; let readdir = Path::new(&root).join("lib").read_dir().ok()?; let mut dirs = readdir .filter_map(|dir| dir.ok()) .map(|dir| dir.path()) .collect::>(); dirs.sort(); let dir = dirs .into_iter() .rev() .find(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file())?; let version = dir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) } // Interestingly there are several subdirectories, `win7` `win8` and // `winv6.3`. Vcvars seems to only care about `winv6.3` though, so the same // applies to us. Note that if we were targeting kernel mode drivers // instead of user mode applications, we would care. fn get_sdk81_dir() -> Option { let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1"; let key = LOCAL_MACHINE.open(key.as_ref()).ok()?; let root = key.query_str("InstallationFolder").ok()?; Some(root.into()) } const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0; const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9; const PROCESSOR_ARCHITECTURE_ARM64: u16 = 12; const X86: u16 = PROCESSOR_ARCHITECTURE_INTEL; const X86_64: u16 = PROCESSOR_ARCHITECTURE_AMD64; const AARCH64: u16 = PROCESSOR_ARCHITECTURE_ARM64; // When choosing the tool to use, we have to choose the one which matches // the target architecture. Otherwise we end up in situations where someone // on 32-bit Windows is trying to cross compile to 64-bit and it tries to // invoke the native 64-bit compiler which won't work. // // For the return value of this function, the first member of the tuple is // the folder of the tool we will be invoking, while the second member is // the folder of the host toolchain for that tool which is essential when // using a cross linker. We return a Vec since on x64 there are often two // linkers that can target the architecture we desire. The 64-bit host // linker is preferred, and hence first, due to 64-bit allowing it more // address space to work with and potentially being faster. fn bin_subdir(target: TargetArch) -> Vec<(&'static str, &'static str)> { match (target, host_arch()) { (TargetArch::X86, X86) => vec![("", "")], (TargetArch::X86, X86_64) => vec![("amd64_x86", "amd64"), ("", "")], (TargetArch::X64, X86) => vec![("x86_amd64", "")], (TargetArch::X64, X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")], (TargetArch::Arm, X86) => vec![("x86_arm", "")], (TargetArch::Arm, X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")], _ => vec![], } } // MSVC's x86 libraries are not in a subfolder fn vc_lib_subdir(target: TargetArch) -> &'static str { match target { TargetArch::X86 => "", TargetArch::X64 => "amd64", TargetArch::Arm => "arm", TargetArch::Arm64 | TargetArch::Arm64ec => "arm64", } } #[allow(bad_style)] fn host_arch() -> u16 { type DWORD = u32; type WORD = u16; type LPVOID = *mut u8; type DWORD_PTR = usize; #[repr(C)] struct SYSTEM_INFO { wProcessorArchitecture: WORD, _wReserved: WORD, _dwPageSize: DWORD, _lpMinimumApplicationAddress: LPVOID, _lpMaximumApplicationAddress: LPVOID, _dwActiveProcessorMask: DWORD_PTR, _dwNumberOfProcessors: DWORD, _dwProcessorType: DWORD, _dwAllocationGranularity: DWORD, _wProcessorLevel: WORD, _wProcessorRevision: WORD, } extern "system" { fn GetNativeSystemInfo(lpSystemInfo: *mut SYSTEM_INFO); } unsafe { let mut info = mem::zeroed(); GetNativeSystemInfo(&mut info); info.wProcessorArchitecture } } // Given a registry key, look at all the sub keys and find the one which has // the maximal numeric value. // // Returns the name of the maximal key as well as the opened maximal key. fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> { let mut max_vers = 0; let mut max_key = None; for subkey in key.iter().filter_map(|k| k.ok()) { let val = subkey .to_str() .and_then(|s| s.trim_start_matches('v').replace('.', "").parse().ok()); let val = match val { Some(s) => s, None => continue, }; if val > max_vers { if let Ok(k) = key.open(&subkey) { max_vers = val; max_key = Some((subkey, k)); } } } max_key } #[inline(always)] pub(super) fn has_msbuild_version(version: &str, env_getter: &dyn EnvGetter) -> bool { match version { "17.0" => { find_msbuild_vs17(TargetArch::X64, env_getter).is_some() || find_msbuild_vs17(TargetArch::X86, env_getter).is_some() || find_msbuild_vs17(TargetArch::Arm64, env_getter).is_some() } "16.0" => { find_msbuild_vs16(TargetArch::X64, env_getter).is_some() || find_msbuild_vs16(TargetArch::X86, env_getter).is_some() || find_msbuild_vs16(TargetArch::Arm64, env_getter).is_some() } "15.0" => { find_msbuild_vs15(TargetArch::X64, env_getter).is_some() || find_msbuild_vs15(TargetArch::X86, env_getter).is_some() || find_msbuild_vs15(TargetArch::Arm64, env_getter).is_some() } "14.0" => LOCAL_MACHINE .open(&OsString::from(format!( "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}", version ))) .is_ok(), _ => false, } } pub(super) fn find_devenv(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { find_devenv_vs15(target, env_getter) } fn find_devenv_vs15(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { find_tool_in_vs15_path(r"Common7\IDE\devenv.exe", target, env_getter) } // see http://stackoverflow.com/questions/328017/path-to-msbuild pub(super) fn find_msbuild(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { // VS 15 (2017) changed how to locate msbuild if let Some(r) = find_msbuild_vs17(target, env_getter) { Some(r) } else if let Some(r) = find_msbuild_vs16(target, env_getter) { return Some(r); } else if let Some(r) = find_msbuild_vs15(target, env_getter) { return Some(r); } else { find_old_msbuild(target) } } fn find_msbuild_vs15(target: TargetArch, env_getter: &dyn EnvGetter) -> Option { find_tool_in_vs15_path(r"MSBuild\15.0\Bin\MSBuild.exe", target, env_getter) } fn find_old_msbuild(target: TargetArch) -> Option { let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions"; LOCAL_MACHINE .open(key.as_ref()) .ok() .and_then(|key| { max_version(&key).and_then(|(_vers, key)| key.query_str("MSBuildToolsPath").ok()) }) .map(|path| { let mut path = PathBuf::from(path); path.push("MSBuild.exe"); let mut tool = Tool::with_family(path, MSVC_FAMILY); if target == TargetArch::X64 { tool.env.push(("Platform".into(), "X64".into())); } tool }) } } /// Non-Windows Implementation. #[cfg(not(windows))] mod impl_ { use std::{env, ffi::OsStr}; use super::{EnvGetter, TargetArch, MSVC_FAMILY}; use crate::Tool; /// Finding msbuild.exe tool under unix system is not currently supported. /// Maybe can check it using an environment variable looks like `MSBUILD_BIN`. #[inline(always)] pub(super) fn find_msbuild(_target: TargetArch, _: &dyn EnvGetter) -> Option { None } // Finding devenv.exe tool under unix system is not currently supported. // Maybe can check it using an environment variable looks like `DEVENV_BIN`. #[inline(always)] pub(super) fn find_devenv(_target: TargetArch, _: &dyn EnvGetter) -> Option { None } /// Attempt to find the tool using environment variables set by vcvars. pub(super) fn find_msvc_environment( tool: &str, _target: TargetArch, env_getter: &dyn EnvGetter, ) -> Option { // Early return if the environment doesn't contain a VC install. let vc_install_dir = env_getter.get_env("VCINSTALLDIR")?; let vs_install_dir = env_getter.get_env("VSINSTALLDIR")?; let get_tool = |install_dir: &OsStr| { env::split_paths(install_dir) .map(|p| p.join(tool)) .find(|p| p.exists()) .map(|path| Tool::with_family(path, MSVC_FAMILY)) }; // Take the path of tool for the vc install directory. get_tool(vc_install_dir.as_ref()) // Take the path of tool for the vs install directory. .or_else(|| get_tool(vs_install_dir.as_ref())) // Take the path of tool for the current path environment. .or_else(|| { env_getter .get_env("PATH") .as_ref() .map(|path| path.as_ref()) .and_then(get_tool) }) } #[inline(always)] pub(super) fn find_msvc_15plus( _tool: &str, _target: TargetArch, _: &dyn EnvGetter, ) -> Option { None } // For MSVC 14 we need to find the Universal CRT as well as either // the Windows 10 SDK or Windows 8.1 SDK. #[inline(always)] pub(super) fn find_msvc_14( _tool: &str, _target: TargetArch, _: &dyn EnvGetter, ) -> Option { None } #[inline(always)] pub(super) fn has_msbuild_version(_version: &str, _: &dyn EnvGetter) -> bool { false } } cc/src/windows/vs_instances.rs0000644000175000017500000001453315105742312016323 0ustar bdrungbdrunguse std::borrow::Cow; use std::collections::HashMap; use std::convert::TryFrom; use std::io::BufRead; use std::path::PathBuf; use crate::windows::setup_config::{EnumSetupInstances, SetupInstance}; pub enum VsInstance { Com(SetupInstance), Vswhere(VswhereInstance), } impl VsInstance { pub fn installation_name(&self) -> Option> { match self { VsInstance::Com(s) => s .installation_name() .ok() .and_then(|s| s.into_string().ok()) .map(Cow::from), VsInstance::Vswhere(v) => v.map.get("installationName").map(Cow::from), } } pub fn installation_path(&self) -> Option { match self { VsInstance::Com(s) => s.installation_path().ok().map(PathBuf::from), VsInstance::Vswhere(v) => v.map.get("installationPath").map(PathBuf::from), } } pub fn installation_version(&self) -> Option> { match self { VsInstance::Com(s) => s .installation_version() .ok() .and_then(|s| s.into_string().ok()) .map(Cow::from), VsInstance::Vswhere(v) => v.map.get("installationVersion").map(Cow::from), } } } pub enum VsInstances { ComBased(EnumSetupInstances), VswhereBased(VswhereInstance), } impl IntoIterator for VsInstances { type Item = VsInstance; #[allow(bare_trait_objects)] type IntoIter = Box>; fn into_iter(self) -> Self::IntoIter { match self { VsInstances::ComBased(e) => { Box::new(e.into_iter().filter_map(Result::ok).map(VsInstance::Com)) } VsInstances::VswhereBased(v) => Box::new(std::iter::once(VsInstance::Vswhere(v))), } } } #[derive(Debug)] pub struct VswhereInstance { map: HashMap, } impl TryFrom<&Vec> for VswhereInstance { type Error = &'static str; fn try_from(output: &Vec) -> Result { let map: HashMap<_, _> = output .lines() .map_while(Result::ok) .filter_map(|s| { let mut splitn = s.splitn(2, ": "); Some((splitn.next()?.to_owned(), splitn.next()?.to_owned())) }) .collect(); if !map.contains_key("installationName") || !map.contains_key("installationPath") || !map.contains_key("installationVersion") { return Err("required properties not found"); } Ok(Self { map }) } } #[cfg(test)] mod tests_ { use std::borrow::Cow; use std::convert::TryFrom; use std::path::PathBuf; #[test] fn it_parses_vswhere_output_correctly() { let output = br"instanceId: 58104422 installDate: 21/02/2021 21:50:33 installationName: VisualStudio/16.9.2+31112.23 installationPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools installationVersion: 16.9.31112.23 productId: Microsoft.VisualStudio.Product.BuildTools productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\LaunchDevCmd.bat state: 4294967295 isComplete: 1 isLaunchable: 1 isPrerelease: 0 isRebootRequired: 0 displayName: Visual Studio Build Tools 2019 description: The Visual Studio Build Tools allows you to build native and managed MSBuild-based applications without requiring the Visual Studio IDE. There are options to install the Visual C++ compilers and libraries, MFC, ATL, and C++/CLI support. channelId: VisualStudio.16.Release channelUri: https://aka.ms/vs/16/release/channel enginePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service releaseNotes: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-v16.9#16.9.2 thirdPartyNotices: https://go.microsoft.com/fwlink/?LinkId=660909 updateDate: 2021-03-17T21:16:46.5963702Z catalog_buildBranch: d16.9 catalog_buildVersion: 16.9.31112.23 catalog_id: VisualStudio/16.9.2+31112.23 catalog_localBuild: build-lab catalog_manifestName: VisualStudio catalog_manifestType: installer catalog_productDisplayVersion: 16.9.2 catalog_productLine: Dev16 catalog_productLineVersion: 2019 catalog_productMilestone: RTW catalog_productMilestoneIsPreRelease: False catalog_productName: Visual Studio catalog_productPatchVersion: 2 catalog_productPreReleaseMilestoneSuffix: 1.0 catalog_productSemanticVersion: 16.9.2+31112.23 catalog_requiredEngineVersion: 2.9.3365.38425 properties_campaignId: 156063665.1613940062 properties_channelManifestId: VisualStudio.16.Release/16.9.2+31112.23 properties_nickname: properties_setupEngineFilePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installershell.exe " .to_vec(); let vswhere_instance = super::VswhereInstance::try_from(&output); assert!(vswhere_instance.is_ok()); let vs_instance = super::VsInstance::Vswhere(vswhere_instance.unwrap()); assert_eq!( vs_instance.installation_name(), Some(Cow::from("VisualStudio/16.9.2+31112.23")) ); assert_eq!( vs_instance.installation_path(), Some(PathBuf::from( r"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools" )) ); assert_eq!( vs_instance.installation_version(), Some(Cow::from("16.9.31112.23")) ); } #[test] fn it_returns_an_error_for_empty_output() { let output = b"".to_vec(); let vswhere_instance = super::VswhereInstance::try_from(&output); assert!(vswhere_instance.is_err()); } #[test] fn it_returns_an_error_for_output_consisting_of_empty_lines() { let output = br" " .to_vec(); let vswhere_instance = super::VswhereInstance::try_from(&output); assert!(vswhere_instance.is_err()); } #[test] fn it_returns_an_error_for_output_without_required_properties() { let output = br"instanceId: 58104422 installDate: 21/02/2021 21:50:33 productId: Microsoft.VisualStudio.Product.BuildTools productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\LaunchDevCmd.bat " .to_vec(); let vswhere_instance = super::VswhereInstance::try_from(&output); assert!(vswhere_instance.is_err()); } } cc/src/windows/registry.rs0000644000175000017500000001445115105742312015473 0ustar bdrungbdrung// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use crate::windows::windows_sys::{ RegCloseKey, RegEnumKeyExW, RegOpenKeyExW, RegQueryValueExW, ERROR_NO_MORE_ITEMS, ERROR_SUCCESS, HKEY, HKEY_LOCAL_MACHINE, KEY_READ, KEY_WOW64_32KEY, REG_SZ, }; use std::{ ffi::{OsStr, OsString}, io, ops::RangeFrom, os::windows::prelude::*, ptr::null_mut, }; /// Must never be `HKEY_PERFORMANCE_DATA`. pub(crate) struct RegistryKey(Repr); #[allow(clippy::upper_case_acronyms)] type DWORD = u32; struct OwnedKey(HKEY); /// Note: must not encode `HKEY_PERFORMANCE_DATA` or one of its subkeys. enum Repr { /// `HKEY_LOCAL_MACHINE`. LocalMachine, /// A subkey of `HKEY_LOCAL_MACHINE`. Owned(OwnedKey), } pub struct Iter<'a> { idx: RangeFrom, key: &'a RegistryKey, } unsafe impl Sync for Repr {} unsafe impl Send for Repr {} pub(crate) const LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::LocalMachine); impl RegistryKey { fn raw(&self) -> HKEY { match self.0 { Repr::LocalMachine => HKEY_LOCAL_MACHINE, Repr::Owned(ref val) => val.0, } } /// Open a sub-key of `self`. pub fn open(&self, key: &OsStr) -> io::Result { let key = key.encode_wide().chain(Some(0)).collect::>(); let mut ret = null_mut(); let err = unsafe { RegOpenKeyExW( self.raw(), key.as_ptr(), 0, KEY_READ | KEY_WOW64_32KEY, &mut ret, ) }; if err == ERROR_SUCCESS { Ok(RegistryKey(Repr::Owned(OwnedKey(ret)))) } else { Err(io::Error::from_raw_os_error(err as i32)) } } pub fn iter(&self) -> Iter { Iter { idx: 0.., key: self, } } pub fn query_str(&self, name: &str) -> io::Result { let name: &OsStr = name.as_ref(); let name = name.encode_wide().chain(Some(0)).collect::>(); let mut len = 0; let mut kind = 0; unsafe { let err = RegQueryValueExW( self.raw(), name.as_ptr(), null_mut(), &mut kind, null_mut(), &mut len, ); if err != ERROR_SUCCESS { return Err(io::Error::from_raw_os_error(err as i32)); } if kind != REG_SZ { return Err(io::Error::new( io::ErrorKind::Other, "registry key wasn't a string", )); } // The length here is the length in bytes, but we're using wide // characters so we need to be sure to halve it for the length // passed in. assert!(len % 2 == 0, "impossible wide string size: {} bytes", len); let vlen = len as usize / 2; // Defensively initialized, see comment about // `HKEY_PERFORMANCE_DATA` below. let mut v = vec![0u16; vlen]; let err = RegQueryValueExW( self.raw(), name.as_ptr(), null_mut(), null_mut(), v.as_mut_ptr() as *mut _, &mut len, ); // We don't check for `ERROR_MORE_DATA` (which would if the value // grew between the first and second call to `RegQueryValueExW`), // both because it's extremely unlikely, and this is a bit more // defensive more defensive against weird types of registry keys. if err != ERROR_SUCCESS { return Err(io::Error::from_raw_os_error(err as i32)); } // The length is allowed to change, but should still be even, as // well as smaller. assert!(len % 2 == 0, "impossible wide string size: {} bytes", len); // If the length grew but returned a success code, it *probably* // indicates we're `HKEY_PERFORMANCE_DATA` or a subkey(?). We // consider this UB, since those keys write "undefined" or // "unpredictable" values to len, and need to use a completely // different loop structure. This should be impossible (and enforce // it in the API to the best of our ability), but to mitigate the // damage we do some smoke-checks on the len, and ensure `v` has // been fully initialized (rather than trusting the result of // `RegQueryValueExW`). let actual_len = len as usize / 2; assert!(actual_len <= v.len()); v.truncate(actual_len); // Some registry keys may have a terminating nul character, but // we're not interested in that, so chop it off if it's there. if !v.is_empty() && v[v.len() - 1] == 0 { v.pop(); } Ok(OsString::from_wide(&v)) } } } impl Drop for OwnedKey { fn drop(&mut self) { unsafe { RegCloseKey(self.0); } } } impl<'a> Iterator for Iter<'a> { type Item = io::Result; fn next(&mut self) -> Option> { self.idx.next().and_then(|i| unsafe { let mut v = Vec::with_capacity(256); let mut len = v.capacity() as DWORD; let ret = RegEnumKeyExW( self.key.raw(), i, v.as_mut_ptr(), &mut len, null_mut(), null_mut(), null_mut(), null_mut(), ); if ret == ERROR_NO_MORE_ITEMS { None } else if ret != ERROR_SUCCESS { Some(Err(io::Error::from_raw_os_error(ret as i32))) } else { v.set_len(len as usize); Some(Ok(OsString::from_wide(&v))) } }) } } cc/src/windows/setup_config.rs0000644000175000017500000002127715105742312016314 0ustar bdrungbdrung// Copyright © 2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] #![allow(unused)] use crate::windows::{ com::{BStr, ComPtr}, winapi::{ IUnknown, IUnknownVtbl, Interface, LCID, LPCOLESTR, LPCWSTR, LPFILETIME, LPSAFEARRAY, PULONGLONG, ULONG, }, windows_sys::{CoCreateInstance, BSTR, CLSCTX_ALL, HRESULT, S_FALSE}, }; use std::{ ffi::OsString, ptr::{null, null_mut}, }; // Bindings to the Setup.Configuration stuff pub type InstanceState = u32; pub const eNone: InstanceState = 0; pub const eLocal: InstanceState = 1; pub const eRegistered: InstanceState = 2; pub const eNoRebootRequired: InstanceState = 4; pub const eComplete: InstanceState = -1i32 as u32; RIDL! {#[uuid(0xb41463c3, 0x8866, 0x43b5, 0xbc, 0x33, 0x2b, 0x06, 0x76, 0xf7, 0xf4, 0x2e)] interface ISetupInstance(ISetupInstanceVtbl): IUnknown(IUnknownVtbl) { fn GetInstanceId( pbstrInstanceId: *mut BSTR, ) -> HRESULT, fn GetInstallDate( pInstallDate: LPFILETIME, ) -> HRESULT, fn GetInstallationName( pbstrInstallationName: *mut BSTR, ) -> HRESULT, fn GetInstallationPath( pbstrInstallationPath: *mut BSTR, ) -> HRESULT, fn GetInstallationVersion( pbstrInstallationVersion: *mut BSTR, ) -> HRESULT, fn GetDisplayName( lcid: LCID, pbstrDisplayName: *mut BSTR, ) -> HRESULT, fn GetDescription( lcid: LCID, pbstrDescription: *mut BSTR, ) -> HRESULT, fn ResolvePath( pwszRelativePath: LPCOLESTR, pbstrAbsolutePath: *mut BSTR, ) -> HRESULT, }} RIDL! {#[uuid(0x89143c9a, 0x05af, 0x49b0, 0xb7, 0x17, 0x72, 0xe2, 0x18, 0xa2, 0x18, 0x5c)] interface ISetupInstance2(ISetupInstance2Vtbl): ISetupInstance(ISetupInstanceVtbl) { fn GetState( pState: *mut InstanceState, ) -> HRESULT, fn GetPackages( ppsaPackages: *mut LPSAFEARRAY, ) -> HRESULT, fn GetProduct( ppPackage: *mut *mut ISetupPackageReference, ) -> HRESULT, fn GetProductPath( pbstrProductPath: *mut BSTR, ) -> HRESULT, }} RIDL! {#[uuid(0x6380bcff, 0x41d3, 0x4b2e, 0x8b, 0x2e, 0xbf, 0x8a, 0x68, 0x10, 0xc8, 0x48)] interface IEnumSetupInstances(IEnumSetupInstancesVtbl): IUnknown(IUnknownVtbl) { fn Next( celt: ULONG, rgelt: *mut *mut ISetupInstance, pceltFetched: *mut ULONG, ) -> HRESULT, fn Skip( celt: ULONG, ) -> HRESULT, fn Reset() -> HRESULT, fn Clone( ppenum: *mut *mut IEnumSetupInstances, ) -> HRESULT, }} RIDL! {#[uuid(0x42843719, 0xdb4c, 0x46c2, 0x8e, 0x7c, 0x64, 0xf1, 0x81, 0x6e, 0xfd, 0x5b)] interface ISetupConfiguration(ISetupConfigurationVtbl): IUnknown(IUnknownVtbl) { fn EnumInstances( ppEnumInstances: *mut *mut IEnumSetupInstances, ) -> HRESULT, fn GetInstanceForCurrentProcess( ppInstance: *mut *mut ISetupInstance, ) -> HRESULT, fn GetInstanceForPath( wzPath: LPCWSTR, ppInstance: *mut *mut ISetupInstance, ) -> HRESULT, }} RIDL! {#[uuid(0x26aab78c, 0x4a60, 0x49d6, 0xaf, 0x3b, 0x3c, 0x35, 0xbc, 0x93, 0x36, 0x5d)] interface ISetupConfiguration2(ISetupConfiguration2Vtbl): ISetupConfiguration(ISetupConfigurationVtbl) { fn EnumAllInstances( ppEnumInstances: *mut *mut IEnumSetupInstances, ) -> HRESULT, }} RIDL! {#[uuid(0xda8d8a16, 0xb2b6, 0x4487, 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5)] interface ISetupPackageReference(ISetupPackageReferenceVtbl): IUnknown(IUnknownVtbl) { fn GetId( pbstrId: *mut BSTR, ) -> HRESULT, fn GetVersion( pbstrVersion: *mut BSTR, ) -> HRESULT, fn GetChip( pbstrChip: *mut BSTR, ) -> HRESULT, fn GetLanguage( pbstrLanguage: *mut BSTR, ) -> HRESULT, fn GetBranch( pbstrBranch: *mut BSTR, ) -> HRESULT, fn GetType( pbstrType: *mut BSTR, ) -> HRESULT, fn GetUniqueId( pbstrUniqueId: *mut BSTR, ) -> HRESULT, }} RIDL! {#[uuid(0x42b21b78, 0x6192, 0x463e, 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c)] interface ISetupHelper(ISetupHelperVtbl): IUnknown(IUnknownVtbl) { fn ParseVersion( pwszVersion: LPCOLESTR, pullVersion: PULONGLONG, ) -> HRESULT, fn ParseVersionRange( pwszVersionRange: LPCOLESTR, pullMinVersion: PULONGLONG, pullMaxVersion: PULONGLONG, ) -> HRESULT, }} DEFINE_GUID! {CLSID_SetupConfiguration, 0x177f0c4a, 0x1cd3, 0x4de7, 0xa3, 0x2c, 0x71, 0xdb, 0xbb, 0x9f, 0xa3, 0x6d} // Safe wrapper around the COM interfaces pub struct SetupConfiguration(ComPtr); impl SetupConfiguration { pub fn new() -> Result { let mut obj = null_mut(); let err = unsafe { CoCreateInstance( &CLSID_SetupConfiguration, null_mut(), CLSCTX_ALL, &ISetupConfiguration::uuidof(), &mut obj, ) }; if err < 0 { return Err(err); } let obj = unsafe { ComPtr::from_raw(obj as *mut ISetupConfiguration) }; Ok(SetupConfiguration(obj)) } pub fn get_instance_for_current_process(&self) -> Result { let mut obj = null_mut(); let err = unsafe { self.0.GetInstanceForCurrentProcess(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { SetupInstance::from_raw(obj) }) } pub fn enum_instances(&self) -> Result { let mut obj = null_mut(); let err = unsafe { self.0.EnumInstances(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { EnumSetupInstances::from_raw(obj) }) } pub fn enum_all_instances(&self) -> Result { let mut obj = null_mut(); let this = self.0.cast::()?; let err = unsafe { this.EnumAllInstances(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { EnumSetupInstances::from_raw(obj) }) } } pub struct SetupInstance(ComPtr); impl SetupInstance { pub unsafe fn from_raw(obj: *mut ISetupInstance) -> SetupInstance { SetupInstance(ComPtr::from_raw(obj)) } pub fn instance_id(&self) -> Result { let mut s = null(); let err = unsafe { self.0.GetInstanceId(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_name(&self) -> Result { let mut s = null(); let err = unsafe { self.0.GetInstallationName(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_path(&self) -> Result { let mut s = null(); let err = unsafe { self.0.GetInstallationPath(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_version(&self) -> Result { let mut s = null(); let err = unsafe { self.0.GetInstallationVersion(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn product_path(&self) -> Result { let mut s = null(); let this = self.0.cast::()?; let err = unsafe { this.GetProductPath(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } } pub struct EnumSetupInstances(ComPtr); impl EnumSetupInstances { pub unsafe fn from_raw(obj: *mut IEnumSetupInstances) -> EnumSetupInstances { EnumSetupInstances(ComPtr::from_raw(obj)) } } impl Iterator for EnumSetupInstances { type Item = Result; fn next(&mut self) -> Option> { let mut obj = null_mut(); let err = unsafe { self.0.Next(1, &mut obj, null_mut()) }; if err < 0 { return Some(Err(err)); } if err == S_FALSE { return None; } Some(Ok(unsafe { SetupInstance::from_raw(obj) })) } } cc/src/target.rs0000644000175000017500000000246215105742312013416 0ustar bdrungbdrung//! Parsing of `rustc` target names to match the values exposed to Cargo //! build scripts (`CARGO_CFG_*`). mod apple; mod generated; mod llvm; mod parser; pub(crate) use parser::TargetInfoParser; /// Information specific to a `rustc` target. /// /// See . #[derive(Debug, PartialEq, Clone)] pub(crate) struct TargetInfo<'a> { /// The full architecture, including the subarchitecture. /// /// This differs from `cfg!(target_arch)`, which only specifies the /// overall architecture, which is too coarse for certain cases. pub full_arch: &'a str, /// The overall target architecture. /// /// This is the same as the value of `cfg!(target_arch)`. pub arch: &'a str, /// The target vendor. /// /// This is the same as the value of `cfg!(target_vendor)`. pub vendor: &'a str, /// The operating system, or `none` on bare-metal targets. /// /// This is the same as the value of `cfg!(target_os)`. pub os: &'a str, /// The environment on top of the operating system. /// /// This is the same as the value of `cfg!(target_env)`. pub env: &'a str, /// The ABI on top of the operating system. /// /// This is the same as the value of `cfg!(target_abi)`. pub abi: &'a str, } cc/src/parallel/0000775000175000017500000000000015105742312013354 5ustar bdrungbdrungcc/src/parallel/mod.rs0000644000175000017500000000012015105742312014470 0ustar bdrungbdrungpub(crate) mod async_executor; pub(crate) mod job_token; pub(crate) mod stderr; cc/src/parallel/async_executor.rs0000644000175000017500000000677615105742312016773 0ustar bdrungbdrunguse std::{ cell::Cell, future::Future, pin::Pin, ptr, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, thread, time::Duration, }; use crate::Error; const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new( // Cloning just returns a new no-op raw waker |_| NOOP_RAW_WAKER, // `wake` does nothing |_| {}, // `wake_by_ref` does nothing |_| {}, // Dropping does nothing as we don't allocate anything |_| {}, ); const NOOP_RAW_WAKER: RawWaker = RawWaker::new(ptr::null(), &NOOP_WAKER_VTABLE); #[derive(Default)] pub(crate) struct YieldOnce(bool); impl Future for YieldOnce { type Output = (); fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { let flag = &mut std::pin::Pin::into_inner(self).0; if !*flag { *flag = true; Poll::Pending } else { Poll::Ready(()) } } } /// Execute the futures and return when they are all done. /// /// Here we use our own homebrew async executor since cc is used in the build /// script of many popular projects, pulling in additional dependencies would /// significantly slow down its compilation. pub(crate) fn block_on( mut fut1: Fut1, mut fut2: Fut2, has_made_progress: &Cell, ) -> Result<(), Error> where Fut1: Future>, Fut2: Future>, { // Shadows the future so that it can never be moved and is guaranteed // to be pinned. // // The same trick used in `pin!` macro. // // TODO: Once MSRV is bumped to 1.68, replace this with `std::pin::pin!` let mut fut1 = Some(unsafe { Pin::new_unchecked(&mut fut1) }); let mut fut2 = Some(unsafe { Pin::new_unchecked(&mut fut2) }); // TODO: Once `Waker::noop` stablised and our MSRV is bumped to the version // which it is stablised, replace this with `Waker::noop`. let waker = unsafe { Waker::from_raw(NOOP_RAW_WAKER) }; let mut context = Context::from_waker(&waker); let mut backoff_cnt = 0; loop { has_made_progress.set(false); if let Some(fut) = fut2.as_mut() { if let Poll::Ready(res) = fut.as_mut().poll(&mut context) { fut2 = None; res?; } } if let Some(fut) = fut1.as_mut() { if let Poll::Ready(res) = fut.as_mut().poll(&mut context) { fut1 = None; res?; } } if fut1.is_none() && fut2.is_none() { return Ok(()); } if !has_made_progress.get() { if backoff_cnt > 3 { // We have yielded at least three times without making' // any progress, so we will sleep for a while. let duration = Duration::from_millis(100 * (backoff_cnt - 3).min(10)); thread::sleep(duration); } else { // Given that we spawned a lot of compilation tasks, it is unlikely // that OS cannot find other ready task to execute. // // If all of them are done, then we will yield them and spawn more, // or simply return. // // Thus this will not be turned into a busy-wait loop and it will not // waste CPU resource. thread::yield_now(); } } backoff_cnt = if has_made_progress.get() { 0 } else { backoff_cnt + 1 }; } } cc/src/parallel/job_token.rs0000644000175000017500000002240315105742312015673 0ustar bdrungbdrunguse std::marker::PhantomData; use crate::{utilities::OnceLock, Error}; pub(crate) struct JobToken(PhantomData<()>); impl JobToken { fn new() -> Self { Self(PhantomData) } } impl Drop for JobToken { fn drop(&mut self) { match JobTokenServer::new() { JobTokenServer::Inherited(jobserver) => jobserver.release_token_raw(), JobTokenServer::InProcess(jobserver) => jobserver.release_token_raw(), } } } enum JobTokenServer { Inherited(inherited_jobserver::JobServer), InProcess(inprocess_jobserver::JobServer), } impl JobTokenServer { /// This function returns a static reference to the jobserver because /// - creating a jobserver from env is a bit fd-unsafe (e.g. the fd might /// be closed by other jobserver users in the process) and better do it /// at the start of the program. /// - in case a jobserver cannot be created from env (e.g. it's not /// present), we will create a global in-process only jobserver /// that has to be static so that it will be shared by all cc /// compilation. fn new() -> &'static Self { // TODO: Replace with a OnceLock once MSRV is 1.70 static JOBSERVER: OnceLock = OnceLock::new(); JOBSERVER.get_or_init(|| { unsafe { inherited_jobserver::JobServer::from_env() } .map(Self::Inherited) .unwrap_or_else(|| Self::InProcess(inprocess_jobserver::JobServer::new())) }) } } pub(crate) enum ActiveJobTokenServer { Inherited(inherited_jobserver::ActiveJobServer<'static>), InProcess(&'static inprocess_jobserver::JobServer), } impl ActiveJobTokenServer { pub(crate) fn new() -> Self { match JobTokenServer::new() { JobTokenServer::Inherited(inherited_jobserver) => { Self::Inherited(inherited_jobserver.enter_active()) } JobTokenServer::InProcess(inprocess_jobserver) => Self::InProcess(inprocess_jobserver), } } pub(crate) async fn acquire(&mut self) -> Result { match self { Self::Inherited(jobserver) => jobserver.acquire().await, Self::InProcess(jobserver) => Ok(jobserver.acquire().await), } } } mod inherited_jobserver { use super::JobToken; use crate::{parallel::async_executor::YieldOnce, Error, ErrorKind}; use std::{ io, mem, sync::{mpsc, Mutex, MutexGuard, PoisonError}, }; pub(super) struct JobServer { /// Implicit token for this process which is obtained and will be /// released in parent. Since `JobTokens` only give back what they got, /// there should be at most one global implicit token in the wild. /// /// Since Rust does not execute any `Drop` for global variables, /// we can't just put it back to jobserver and then re-acquire it at /// the end of the process. /// /// Use `Mutex` to avoid race between acquire and release. /// If an `AtomicBool` is used, then it's possible for: /// - `release_token_raw`: Tries to set `global_implicit_token` to true, but it is already /// set to `true`, continue to release it to jobserver /// - `acquire` takes the global implicit token, set `global_implicit_token` to false /// - `release_token_raw` now writes the token back into the jobserver, while /// `global_implicit_token` is `false` /// /// If the program exits here, then cc effectively increases parallelism by one, which is /// incorrect, hence we use a `Mutex` here. global_implicit_token: Mutex, inner: jobserver::Client, } impl JobServer { pub(super) unsafe fn from_env() -> Option { jobserver::Client::from_env().map(|inner| Self { inner, global_implicit_token: Mutex::new(true), }) } fn get_global_implicit_token(&self) -> MutexGuard<'_, bool> { self.global_implicit_token .lock() .unwrap_or_else(PoisonError::into_inner) } /// All tokens except for the global implicit token will be put back into the jobserver /// immediately and they cannot be cached, since Rust does not call `Drop::drop` on /// global variables. pub(super) fn release_token_raw(&self) { let mut global_implicit_token = self.get_global_implicit_token(); if *global_implicit_token { // There's already a global implicit token, so this token must // be released back into jobserver. // // `release_raw` should not block let _ = self.inner.release_raw(); } else { *global_implicit_token = true; } } pub(super) fn enter_active(&self) -> ActiveJobServer<'_> { ActiveJobServer { jobserver: self, helper_thread: None, } } } struct HelperThread { inner: jobserver::HelperThread, /// When rx is dropped, all the token stored within it will be dropped. rx: mpsc::Receiver>, } impl HelperThread { fn new(jobserver: &JobServer) -> Result { let (tx, rx) = mpsc::channel(); Ok(Self { rx, inner: jobserver.inner.clone().into_helper_thread(move |res| { let _ = tx.send(res); })?, }) } } pub(crate) struct ActiveJobServer<'a> { jobserver: &'a JobServer, helper_thread: Option, } impl ActiveJobServer<'_> { pub(super) async fn acquire(&mut self) -> Result { let mut has_requested_token = false; loop { // Fast path if mem::replace(&mut *self.jobserver.get_global_implicit_token(), false) { break Ok(JobToken::new()); } match self.jobserver.inner.try_acquire() { Ok(Some(acquired)) => { acquired.drop_without_releasing(); break Ok(JobToken::new()); } Ok(None) => YieldOnce::default().await, Err(err) if err.kind() == io::ErrorKind::Unsupported => { // Fallback to creating a help thread with blocking acquire let helper_thread = if let Some(thread) = self.helper_thread.as_ref() { thread } else { self.helper_thread .insert(HelperThread::new(self.jobserver)?) }; match helper_thread.rx.try_recv() { Ok(res) => { let acquired = res?; acquired.drop_without_releasing(); break Ok(JobToken::new()); } Err(mpsc::TryRecvError::Disconnected) => break Err(Error::new( ErrorKind::JobserverHelpThreadError, "jobserver help thread has returned before ActiveJobServer is dropped", )), Err(mpsc::TryRecvError::Empty) => { if !has_requested_token { helper_thread.inner.request_token(); has_requested_token = true; } YieldOnce::default().await } } } Err(err) => break Err(err.into()), } } } } } mod inprocess_jobserver { use super::JobToken; use crate::parallel::async_executor::YieldOnce; use std::{ env::var, sync::atomic::{ AtomicU32, Ordering::{AcqRel, Acquire}, }, }; pub(crate) struct JobServer(AtomicU32); impl JobServer { pub(super) fn new() -> Self { // Use `NUM_JOBS` if set (it's configured by Cargo) and otherwise // just fall back to the number of cores on the local machine, or a reasonable // default if that cannot be determined. let parallelism = var("NUM_JOBS") .ok() .and_then(|j| j.parse::().ok()) .or_else(|| Some(std::thread::available_parallelism().ok()?.get() as u32)) .unwrap_or(4); Self(AtomicU32::new(parallelism)) } pub(super) async fn acquire(&self) -> JobToken { loop { let res = self .0 .fetch_update(AcqRel, Acquire, |tokens| tokens.checked_sub(1)); if res.is_ok() { break JobToken::new(); } YieldOnce::default().await } } pub(super) fn release_token_raw(&self) { self.0.fetch_add(1, AcqRel); } } } cc/src/parallel/stderr.rs0000644000175000017500000000525415105742312015231 0ustar bdrungbdrung#![cfg_attr(target_family = "wasm", allow(unused))] /// Helpers functions for [`ChildStderr`]. use std::{convert::TryInto, process::ChildStderr}; use crate::{Error, ErrorKind}; #[cfg(all(not(unix), not(windows), not(target_family = "wasm")))] compile_error!("Only unix and windows support non-blocking pipes! For other OSes, disable the parallel feature."); #[cfg(unix)] fn get_flags(fd: std::os::unix::io::RawFd) -> Result { let flags = unsafe { libc::fcntl(fd, libc::F_GETFL, 0) }; if flags == -1 { Err(Error::new( ErrorKind::IOError, format!( "Failed to get flags for pipe {}: {}", fd, std::io::Error::last_os_error() ), )) } else { Ok(flags) } } #[cfg(unix)] fn set_flags(fd: std::os::unix::io::RawFd, flags: std::os::raw::c_int) -> Result<(), Error> { if unsafe { libc::fcntl(fd, libc::F_SETFL, flags) } == -1 { Err(Error::new( ErrorKind::IOError, format!( "Failed to set flags for pipe {}: {}", fd, std::io::Error::last_os_error() ), )) } else { Ok(()) } } #[cfg(unix)] pub fn set_non_blocking(pipe: &impl std::os::unix::io::AsRawFd) -> Result<(), Error> { // On Unix, switch the pipe to non-blocking mode. // On Windows, we have a different way to be non-blocking. let fd = pipe.as_raw_fd(); let flags = get_flags(fd)?; set_flags(fd, flags | libc::O_NONBLOCK) } pub fn bytes_available(stderr: &mut ChildStderr) -> Result { let mut bytes_available = 0; #[cfg(windows)] { use crate::windows::windows_sys::PeekNamedPipe; use std::os::windows::io::AsRawHandle; use std::ptr::null_mut; if unsafe { PeekNamedPipe( stderr.as_raw_handle(), null_mut(), 0, null_mut(), &mut bytes_available, null_mut(), ) } == 0 { return Err(Error::new( ErrorKind::IOError, format!( "PeekNamedPipe failed with {}", std::io::Error::last_os_error() ), )); } } #[cfg(unix)] { use std::os::unix::io::AsRawFd; if unsafe { libc::ioctl(stderr.as_raw_fd(), libc::FIONREAD, &mut bytes_available) } != 0 { return Err(Error::new( ErrorKind::IOError, format!("ioctl failed with {}", std::io::Error::last_os_error()), )); } } Ok(bytes_available.try_into().unwrap()) } cc/src/utilities.rs0000644000175000017500000000647215105742312014150 0ustar bdrungbdrunguse std::{ cell::UnsafeCell, ffi::OsStr, fmt::{self, Write}, marker::PhantomData, mem::MaybeUninit, panic::{RefUnwindSafe, UnwindSafe}, path::Path, sync::Once, }; pub(super) struct JoinOsStrs<'a, T> { pub(super) slice: &'a [T], pub(super) delimiter: char, } impl fmt::Display for JoinOsStrs<'_, T> where T: AsRef, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let len = self.slice.len(); for (index, os_str) in self.slice.iter().enumerate() { // TODO: Use OsStr::display once it is stablised, // Path and OsStr has the same `Display` impl write!(f, "{}", Path::new(os_str).display())?; if index + 1 < len { f.write_char(self.delimiter)?; } } Ok(()) } } pub(super) struct OptionOsStrDisplay(pub(super) Option); impl fmt::Display for OptionOsStrDisplay where T: AsRef, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // TODO: Use OsStr::display once it is stablised // Path and OsStr has the same `Display` impl if let Some(os_str) = self.0.as_ref() { write!(f, "Some({})", Path::new(os_str).display()) } else { f.write_str("None") } } } pub(crate) struct OnceLock { once: Once, value: UnsafeCell>, _marker: PhantomData, } impl Default for OnceLock { fn default() -> Self { Self::new() } } impl OnceLock { pub(crate) const fn new() -> Self { Self { once: Once::new(), value: UnsafeCell::new(MaybeUninit::uninit()), _marker: PhantomData, } } #[inline] fn is_initialized(&self) -> bool { self.once.is_completed() } unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); #[allow(clippy::needless_borrow)] #[allow(unused_unsafe)] unsafe { (&*self.value.get()).assume_init_ref() } } pub(crate) fn get_or_init(&self, f: impl FnOnce() -> T) -> &T { self.once.call_once(|| { unsafe { &mut *self.value.get() }.write(f()); }); unsafe { self.get_unchecked() } } pub(crate) fn get(&self) -> Option<&T> { if self.is_initialized() { // Safe b/c checked is_initialized Some(unsafe { self.get_unchecked() }) } else { None } } } impl fmt::Debug for OnceLock { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut d = f.debug_tuple("OnceLock"); match self.get() { Some(v) => d.field(v), None => d.field(&format_args!("")), }; d.finish() } } unsafe impl Sync for OnceLock {} unsafe impl Send for OnceLock {} impl RefUnwindSafe for OnceLock {} impl UnwindSafe for OnceLock {} impl Drop for OnceLock { #[inline] fn drop(&mut self) { if self.once.is_completed() { // SAFETY: The cell is initialized and being dropped, so it can't // be accessed again. unsafe { self.value.get_mut().assume_init_drop() }; } } } cc/src/tempfile.rs0000644000175000017500000000434015105742312013732 0ustar bdrungbdrung#![cfg_attr(target_family = "wasm", allow(unused))] use std::{ collections::hash_map::RandomState, fs::{remove_file, File, OpenOptions}, hash::{BuildHasher, Hasher}, io, os, path::{Path, PathBuf}, }; #[cfg(not(any(unix, target_family = "wasm", windows)))] compile_error!("Your system is not supported since cc cannot create named tempfile"); fn rand() -> u64 { RandomState::new().build_hasher().finish() } fn tmpname(suffix: &str) -> String { format!("{}{}", rand(), suffix) } fn create_named(path: &Path) -> io::Result { let mut open_options = OpenOptions::new(); open_options.read(true).write(true).create_new(true); #[cfg(all(unix, not(target_os = "wasi")))] ::mode(&mut open_options, 0o600); #[cfg(windows)] ::custom_flags( &mut open_options, crate::windows::windows_sys::FILE_ATTRIBUTE_TEMPORARY, ); open_options.open(path) } pub(super) struct NamedTempfile { path: PathBuf, file: Option, } impl NamedTempfile { pub(super) fn new(base: &Path, suffix: &str) -> io::Result { for _ in 0..10 { let path = base.join(tmpname(suffix)); match create_named(&path) { Ok(file) => { return Ok(Self { file: Some(file), path, }) } Err(e) if e.kind() == io::ErrorKind::AlreadyExists => continue, Err(e) => return Err(e), }; } Err(io::Error::new( io::ErrorKind::AlreadyExists, format!( "too many temporary files exist in base `{}` with suffix `{}`", base.display(), suffix ), )) } pub(super) fn path(&self) -> &Path { &self.path } pub(super) fn take_file(&mut self) -> Option { self.file.take() } } impl Drop for NamedTempfile { fn drop(&mut self) { // On Windows you have to close all handle to it before // removing the file. self.file.take(); let _ = remove_file(&self.path); } } cc/src/tool.rs0000644000175000017500000004535215105742312013112 0ustar bdrungbdrunguse std::{ borrow::Cow, collections::HashMap, env, ffi::{OsStr, OsString}, io::Write, path::{Path, PathBuf}, process::{Command, Stdio}, sync::RwLock, }; use crate::{ command_helpers::{run_output, CargoOutput}, run, tempfile::NamedTempfile, Error, ErrorKind, OutputKind, }; pub(crate) type CompilerFamilyLookupCache = HashMap]>, ToolFamily>; /// Configuration used to represent an invocation of a C compiler. /// /// This can be used to figure out what compiler is in use, what the arguments /// to it are, and what the environment variables look like for the compiler. /// This can be used to further configure other build systems (e.g. forward /// along CC and/or CFLAGS) or the `to_command` method can be used to run the /// compiler itself. #[derive(Clone, Debug)] #[allow(missing_docs)] pub struct Tool { pub(crate) path: PathBuf, pub(crate) cc_wrapper_path: Option, pub(crate) cc_wrapper_args: Vec, pub(crate) args: Vec, pub(crate) env: Vec<(OsString, OsString)>, pub(crate) family: ToolFamily, pub(crate) cuda: bool, pub(crate) removed_args: Vec, pub(crate) has_internal_target_arg: bool, } impl Tool { pub(crate) fn new( path: PathBuf, cached_compiler_family: &RwLock, cargo_output: &CargoOutput, out_dir: Option<&Path>, ) -> Self { Self::with_features( path, vec![], false, cached_compiler_family, cargo_output, out_dir, ) } pub(crate) fn with_args( path: PathBuf, args: Vec, cached_compiler_family: &RwLock, cargo_output: &CargoOutput, out_dir: Option<&Path>, ) -> Self { Self::with_features( path, args, false, cached_compiler_family, cargo_output, out_dir, ) } /// Explicitly set the `ToolFamily`, skipping name-based detection. pub(crate) fn with_family(path: PathBuf, family: ToolFamily) -> Self { Self { path, cc_wrapper_path: None, cc_wrapper_args: Vec::new(), args: Vec::new(), env: Vec::new(), family, cuda: false, removed_args: Vec::new(), has_internal_target_arg: false, } } pub(crate) fn with_features( path: PathBuf, args: Vec, cuda: bool, cached_compiler_family: &RwLock, cargo_output: &CargoOutput, out_dir: Option<&Path>, ) -> Self { fn is_zig_cc(path: &Path, cargo_output: &CargoOutput) -> bool { run_output( Command::new(path).arg("--version"), // tool detection issues should always be shown as warnings cargo_output, ) .map(|o| String::from_utf8_lossy(&o).contains("ziglang")) .unwrap_or_default() || { match path.file_name().map(OsStr::to_string_lossy) { Some(fname) => fname.contains("zig"), _ => false, } } } fn guess_family_from_stdout( stdout: &str, path: &Path, args: &[String], cargo_output: &CargoOutput, ) -> Result { cargo_output.print_debug(&stdout); // https://gitlab.kitware.com/cmake/cmake/-/blob/69a2eeb9dff5b60f2f1e5b425002a0fd45b7cadb/Modules/CMakeDetermineCompilerId.cmake#L267-271 // stdin is set to null to ensure that the help output is never paginated. let accepts_cl_style_flags = run( Command::new(path).args(args).arg("-?").stdin(Stdio::null()), &{ // the errors are not errors! let mut cargo_output = cargo_output.clone(); cargo_output.warnings = cargo_output.debug; cargo_output.output = OutputKind::Discard; cargo_output }, ) .is_ok(); let clang = stdout.contains(r#""clang""#); let gcc = stdout.contains(r#""gcc""#); let emscripten = stdout.contains(r#""emscripten""#); let vxworks = stdout.contains(r#""VxWorks""#); match (clang, accepts_cl_style_flags, gcc, emscripten, vxworks) { (clang_cl, true, _, false, false) => Ok(ToolFamily::Msvc { clang_cl }), (true, _, _, _, false) | (_, _, _, true, false) => Ok(ToolFamily::Clang { zig_cc: is_zig_cc(path, cargo_output), }), (false, false, true, _, false) | (_, _, _, _, true) => Ok(ToolFamily::Gnu), (false, false, false, false, false) => { cargo_output.print_warning(&"Compiler family detection failed since it does not define `__clang__`, `__GNUC__`, `__EMSCRIPTEN__` or `__VXWORKS__`, also does not accept cl style flag `-?`, fallback to treating it as GNU"); Err(Error::new( ErrorKind::ToolFamilyMacroNotFound, "Expects macro `__clang__`, `__GNUC__` or `__EMSCRIPTEN__`, `__VXWORKS__` or accepts cl style flag `-?`, but found none", )) } } } fn detect_family_inner( path: &Path, args: &[String], cargo_output: &CargoOutput, out_dir: Option<&Path>, ) -> Result { let out_dir = out_dir .map(Cow::Borrowed) .unwrap_or_else(|| Cow::Owned(env::temp_dir())); // Ensure all the parent directories exist otherwise temp file creation // will fail std::fs::create_dir_all(&out_dir).map_err(|err| Error { kind: ErrorKind::IOError, message: format!("failed to create OUT_DIR '{}': {}", out_dir.display(), err) .into(), })?; let mut tmp = NamedTempfile::new(&out_dir, "detect_compiler_family.c").map_err(|err| Error { kind: ErrorKind::IOError, message: format!( "failed to create detect_compiler_family.c temp file in '{}': {}", out_dir.display(), err ) .into(), })?; let mut tmp_file = tmp.take_file().unwrap(); tmp_file.write_all(include_bytes!("detect_compiler_family.c"))?; // Close the file handle *now*, otherwise the compiler may fail to open it on Windows // (#1082). The file stays on disk and its path remains valid until `tmp` is dropped. tmp_file.flush()?; tmp_file.sync_data()?; drop(tmp_file); // When expanding the file, the compiler prints a lot of information to stderr // that it is not an error, but related to expanding itself. // // cc would have to disable warning here to prevent generation of too many warnings. let mut compiler_detect_output = cargo_output.clone(); compiler_detect_output.warnings = compiler_detect_output.debug; let stdout = run_output( Command::new(path).arg("-E").arg(tmp.path()), &compiler_detect_output, )?; let stdout = String::from_utf8_lossy(&stdout); if stdout.contains("-Wslash-u-filename") { let stdout = run_output( Command::new(path).arg("-E").arg("--").arg(tmp.path()), &compiler_detect_output, )?; let stdout = String::from_utf8_lossy(&stdout); guess_family_from_stdout(&stdout, path, args, cargo_output) } else { guess_family_from_stdout(&stdout, path, args, cargo_output) } } let detect_family = |path: &Path, args: &[String]| -> Result { let cache_key = [path.as_os_str()] .iter() .cloned() .chain(args.iter().map(OsStr::new)) .map(Into::into) .collect(); if let Some(family) = cached_compiler_family.read().unwrap().get(&cache_key) { return Ok(*family); } let family = detect_family_inner(path, args, cargo_output, out_dir)?; cached_compiler_family .write() .unwrap() .insert(cache_key, family); Ok(family) }; let family = detect_family(&path, &args).unwrap_or_else(|e| { cargo_output.print_warning(&format_args!( "Compiler family detection failed due to error: {}", e )); match path.file_name().map(OsStr::to_string_lossy) { Some(fname) if fname.contains("clang-cl") => ToolFamily::Msvc { clang_cl: true }, Some(fname) if fname.ends_with("cl") || fname == "cl.exe" => { ToolFamily::Msvc { clang_cl: false } } Some(fname) if fname.contains("clang") => { let is_clang_cl = args .iter() .any(|a| a.strip_prefix("--driver-mode=") == Some("cl")); if is_clang_cl { ToolFamily::Msvc { clang_cl: true } } else { ToolFamily::Clang { zig_cc: is_zig_cc(&path, cargo_output), } } } Some(fname) if fname.contains("zig") => ToolFamily::Clang { zig_cc: true }, _ => ToolFamily::Gnu, } }); Tool { path, cc_wrapper_path: None, cc_wrapper_args: Vec::new(), args: Vec::new(), env: Vec::new(), family, cuda, removed_args: Vec::new(), has_internal_target_arg: false, } } /// Add an argument to be stripped from the final command arguments. pub(crate) fn remove_arg(&mut self, flag: OsString) { self.removed_args.push(flag); } /// Push an "exotic" flag to the end of the compiler's arguments list. /// /// Nvidia compiler accepts only the most common compiler flags like `-D`, /// `-I`, `-c`, etc. Options meant specifically for the underlying /// host C++ compiler have to be prefixed with `-Xcompiler`. /// [Another possible future application for this function is passing /// clang-specific flags to clang-cl, which otherwise accepts only /// MSVC-specific options.] pub(crate) fn push_cc_arg(&mut self, flag: OsString) { if self.cuda { self.args.push("-Xcompiler".into()); } self.args.push(flag); } /// Checks if an argument or flag has already been specified or conflicts. /// /// Currently only checks optimization flags. pub(crate) fn is_duplicate_opt_arg(&self, flag: &OsString) -> bool { let flag = flag.to_str().unwrap(); let mut chars = flag.chars(); // Only duplicate check compiler flags if self.is_like_msvc() { if chars.next() != Some('/') { return false; } } else if (self.is_like_gnu() || self.is_like_clang()) && chars.next() != Some('-') { return false; } // Check for existing optimization flags (-O, /O) if chars.next() == Some('O') { return self .args() .iter() .any(|a| a.to_str().unwrap_or("").chars().nth(1) == Some('O')); } // TODO Check for existing -m..., -m...=..., /arch:... flags false } /// Don't push optimization arg if it conflicts with existing args. pub(crate) fn push_opt_unless_duplicate(&mut self, flag: OsString) { if self.is_duplicate_opt_arg(&flag) { eprintln!("Info: Ignoring duplicate arg {:?}", &flag); } else { self.push_cc_arg(flag); } } /// Converts this compiler into a `Command` that's ready to be run. /// /// This is useful for when the compiler needs to be executed and the /// command returned will already have the initial arguments and environment /// variables configured. pub fn to_command(&self) -> Command { let mut cmd = match self.cc_wrapper_path { Some(ref cc_wrapper_path) => { let mut cmd = Command::new(cc_wrapper_path); cmd.arg(&self.path); cmd } None => Command::new(&self.path), }; cmd.args(&self.cc_wrapper_args); let value = self .args .iter() .filter(|a| !self.removed_args.contains(a)) .collect::>(); cmd.args(&value); for (k, v) in self.env.iter() { cmd.env(k, v); } cmd } /// Returns the path for this compiler. /// /// Note that this may not be a path to a file on the filesystem, e.g. "cc", /// but rather something which will be resolved when a process is spawned. pub fn path(&self) -> &Path { &self.path } /// Returns the default set of arguments to the compiler needed to produce /// executables for the target this compiler generates. pub fn args(&self) -> &[OsString] { &self.args } /// Returns the set of environment variables needed for this compiler to /// operate. /// /// This is typically only used for MSVC compilers currently. pub fn env(&self) -> &[(OsString, OsString)] { &self.env } /// Returns the compiler command in format of CC environment variable. /// Or empty string if CC env was not present /// /// This is typically used by configure script pub fn cc_env(&self) -> OsString { match self.cc_wrapper_path { Some(ref cc_wrapper_path) => { let mut cc_env = cc_wrapper_path.as_os_str().to_owned(); cc_env.push(" "); cc_env.push(self.path.to_path_buf().into_os_string()); for arg in self.cc_wrapper_args.iter() { cc_env.push(" "); cc_env.push(arg); } cc_env } None => OsString::from(""), } } /// Returns the compiler flags in format of CFLAGS environment variable. /// Important here - this will not be CFLAGS from env, its internal gcc's flags to use as CFLAGS /// This is typically used by configure script pub fn cflags_env(&self) -> OsString { let mut flags = OsString::new(); for (i, arg) in self.args.iter().enumerate() { if i > 0 { flags.push(" "); } flags.push(arg); } flags } /// Whether the tool is GNU Compiler Collection-like. pub fn is_like_gnu(&self) -> bool { self.family == ToolFamily::Gnu } /// Whether the tool is Clang-like. pub fn is_like_clang(&self) -> bool { matches!(self.family, ToolFamily::Clang { .. }) } /// Whether the tool is AppleClang under .xctoolchain #[cfg(target_vendor = "apple")] pub(crate) fn is_xctoolchain_clang(&self) -> bool { let path = self.path.to_string_lossy(); path.contains(".xctoolchain/") } #[cfg(not(target_vendor = "apple"))] pub(crate) fn is_xctoolchain_clang(&self) -> bool { false } /// Whether the tool is MSVC-like. pub fn is_like_msvc(&self) -> bool { matches!(self.family, ToolFamily::Msvc { .. }) } /// Whether the tool is `clang-cl`-based MSVC-like. pub fn is_like_clang_cl(&self) -> bool { matches!(self.family, ToolFamily::Msvc { clang_cl: true }) } /// Supports using `--` delimiter to separate arguments and path to source files. pub(crate) fn supports_path_delimiter(&self) -> bool { // homebrew clang and zig-cc does not support this while stock version does matches!(self.family, ToolFamily::Msvc { clang_cl: true }) && !self.cuda } } /// Represents the family of tools this tool belongs to. /// /// Each family of tools differs in how and what arguments they accept. /// /// Detection of a family is done on best-effort basis and may not accurately reflect the tool. #[derive(Copy, Clone, Debug, PartialEq)] pub enum ToolFamily { /// Tool is GNU Compiler Collection-like. Gnu, /// Tool is Clang-like. It differs from the GCC in a sense that it accepts superset of flags /// and its cross-compilation approach is different. Clang { zig_cc: bool }, /// Tool is the MSVC cl.exe. Msvc { clang_cl: bool }, } impl ToolFamily { /// What the flag to request debug info for this family of tools look like pub(crate) fn add_debug_flags(&self, cmd: &mut Tool, dwarf_version: Option) { match *self { ToolFamily::Msvc { .. } => { cmd.push_cc_arg("-Z7".into()); } ToolFamily::Gnu | ToolFamily::Clang { .. } => { cmd.push_cc_arg( dwarf_version .map_or_else(|| "-g".into(), |v| format!("-gdwarf-{}", v)) .into(), ); } } } /// What the flag to force frame pointers. pub(crate) fn add_force_frame_pointer(&self, cmd: &mut Tool) { match *self { ToolFamily::Gnu | ToolFamily::Clang { .. } => { cmd.push_cc_arg("-fno-omit-frame-pointer".into()); } _ => (), } } /// What the flags to enable all warnings pub(crate) fn warnings_flags(&self) -> &'static str { match *self { ToolFamily::Msvc { .. } => "-W4", ToolFamily::Gnu | ToolFamily::Clang { .. } => "-Wall", } } /// What the flags to enable extra warnings pub(crate) fn extra_warnings_flags(&self) -> Option<&'static str> { match *self { ToolFamily::Msvc { .. } => None, ToolFamily::Gnu | ToolFamily::Clang { .. } => Some("-Wextra"), } } /// What the flag to turn warning into errors pub(crate) fn warnings_to_errors_flag(&self) -> &'static str { match *self { ToolFamily::Msvc { .. } => "-WX", ToolFamily::Gnu | ToolFamily::Clang { .. } => "-Werror", } } pub(crate) fn verbose_stderr(&self) -> bool { matches!(*self, ToolFamily::Clang { .. }) } } heck/0000775000175000017500000000000015105742312011316 5ustar bdrungbdrungheck/LICENSE-MIT0000644000175000017500000000205715105742312012754 0ustar bdrungbdrungCopyright (c) 2015 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. heck/Cargo.toml0000644000175000017500000000157415105742312013253 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "heck" version = "0.5.0" include = [ "src/**/*", "LICENSE-*", "README.md", "CHANGELOG.md", ] description = "heck is a case conversion library." readme = "README.md" keywords = [ "string", "case", "camel", "snake", "unicode", ] categories = ["no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/withoutboats/heck" heck/.cargo-checksum.json0000664000175000017500000000013115105742312015155 0ustar bdrungbdrung{"files":{},"package":"2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"}heck/LICENSE-APACHE0000644000175000017500000002513715105742312013250 0ustar bdrungbdrung Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. heck/README.md0000644000175000017500000000363715105742312012604 0ustar bdrungbdrung# **heck** is a case conversion library !["I specifically requested the opposite of this."](./no_step_on_snek.png) This library exists to provide case conversion between common cases like CamelCase and snake_case. It is intended to be unicode aware, internally consistent, and reasonably well performing. ## Definition of a word boundary Word boundaries are defined by non-alphanumeric characters, as well as within those words in this manner: 1. If an uppercase character is followed by lowercase letters, a word boundary is considered to be just prior to that uppercase character. 2. If multiple uppercase characters are consecutive, they are considered to be within a single word, except that the last will be part of the next word if it is followed by lowercase characters (see rule 1). That is, "HelloWorld" is segmented `Hello|World` whereas "XMLHttpRequest" is segmented `XML|Http|Request`. Characters not within words (such as spaces, punctuations, and underscores) are not included in the output string except as they are a part of the case being converted to. Multiple adjacent word boundaries (such as a series of underscores) are folded into one. ("hello__world" in snake case is therefore "hello_world", not the exact same string). Leading or trailing word boundary indicators are dropped, except insofar as CamelCase capitalizes the first word. ## Cases contained in this library: 1. UpperCamelCase 2. lowerCamelCase 3. snake_case 4. kebab-case 5. SHOUTY_SNAKE_CASE 6. Title Case 7. SHOUTY-KEBAB-CASE 8. Train-Case ## MSRV The minimum supported Rust version for this crate is 1.56.0. This may change in minor or patch releases, but we probably won't ever require a very recent version. If you would like to have a stronger guarantee than that, please open an issue. ## License heck is distributed under the terms of both the MIT license and the Apache License (Version 2.0). See LICENSE-APACHE and LICENSE-MIT for details. heck/CHANGELOG.md0000644000175000017500000000130515105742312013124 0ustar bdrungbdrung# unreleased # 0.5.0 - Add `no_std` support. - Remove non-additive `unicode` feature. The library now uses `char::is_alphanumeric` instead of the `unicode-segmentation` library to determine word boundaries in all cases. # 0.4.1 Improvements: - Add Train-Case support # 0.4.0 Breaking changes: * Make unicode support optional (off by default). Enable the `unicode` crate feature if you need unicode support. * Rename all traits from `SomeCase` to `ToSomeCase`, matching `std`s convention of beginning trait names with a verb (`ToOwned`, `AsRef`, …) * Rename `ToMixedCase` to `ToLowerCamelCase` * Rename `ToCamelCase` to `ToUpperCamelCase` * Add `ToPascalCase` as an alias to `ToUpperCamelCase` heck/src/0000775000175000017500000000000015105742312012105 5ustar bdrungbdrungheck/src/shouty_snake.rs0000644000175000017500000000522415105742312015170 0ustar bdrungbdrunguse core::fmt; use alloc::{borrow::ToOwned, string::ToString}; use crate::{transform, uppercase}; /// This trait defines a shouty snake case conversion. /// /// In SHOUTY_SNAKE_CASE, word boundaries are indicated by underscores and all /// words are in uppercase. /// /// ## Example: /// /// ```rust /// use heck::ToShoutySnakeCase; /// /// let sentence = "That world is growing in this minute."; /// assert_eq!(sentence.to_shouty_snake_case(), "THAT_WORLD_IS_GROWING_IN_THIS_MINUTE"); /// ``` pub trait ToShoutySnakeCase: ToOwned { /// Convert this type to shouty snake case. fn to_shouty_snake_case(&self) -> Self::Owned; } /// Oh heck, `ToShoutySnekCase` is an alias for [`ToShoutySnakeCase`]. See /// ToShoutySnakeCase for more documentation. pub trait ToShoutySnekCase: ToOwned { /// CONVERT THIS TYPE TO SNEK CASE. #[allow(non_snake_case)] fn TO_SHOUTY_SNEK_CASE(&self) -> Self::Owned; } impl ToShoutySnekCase for T { fn TO_SHOUTY_SNEK_CASE(&self) -> Self::Owned { self.to_shouty_snake_case() } } impl ToShoutySnakeCase for str { fn to_shouty_snake_case(&self) -> Self::Owned { AsShoutySnakeCase(self).to_string() } } /// This wrapper performs a shouty snake case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsShoutySnakeCase; /// /// let sentence = "That world is growing in this minute."; /// assert_eq!(format!("{}", AsShoutySnakeCase(sentence)), "THAT_WORLD_IS_GROWING_IN_THIS_MINUTE"); /// ``` pub struct AsShoutySnakeCase>(pub T); impl> fmt::Display for AsShoutySnakeCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), uppercase, |f| write!(f, "_"), f) } } #[cfg(test)] mod tests { use super::ToShoutySnakeCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_shouty_snake_case(), $s2) } }; } t!(test1: "CamelCase" => "CAMEL_CASE"); t!(test2: "This is Human case." => "THIS_IS_HUMAN_CASE"); t!(test3: "MixedUP CamelCase, with some Spaces" => "MIXED_UP_CAMEL_CASE_WITH_SOME_SPACES"); t!(test4: "mixed_up_snake_case with some _spaces" => "MIXED_UP_SNAKE_CASE_WITH_SOME_SPACES"); t!(test5: "kebab-case" => "KEBAB_CASE"); t!(test6: "SHOUTY_SNAKE_CASE" => "SHOUTY_SNAKE_CASE"); t!(test7: "snake_case" => "SNAKE_CASE"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "THIS_CONTAINS_ALL_KINDS_OF_WORD_BOUNDARIES"); t!(test9: "XΣXΣ baffle" => "XΣXΣ_BAFFLE"); t!(test10: "XMLHttpRequest" => "XML_HTTP_REQUEST"); } heck/src/kebab.rs0000644000175000017500000000463215105742312013522 0ustar bdrungbdrunguse core::fmt; use alloc::{borrow::ToOwned, string::ToString}; use crate::{lowercase, transform}; /// This trait defines a kebab case conversion. /// /// In kebab-case, word boundaries are indicated by hyphens. /// /// ## Example: /// /// ```rust /// use heck::ToKebabCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(sentence.to_kebab_case(), "we-are-going-to-inherit-the-earth"); /// ``` pub trait ToKebabCase: ToOwned { /// Convert this type to kebab case. fn to_kebab_case(&self) -> Self::Owned; } impl ToKebabCase for str { fn to_kebab_case(&self) -> Self::Owned { AsKebabCase(self).to_string() } } /// This wrapper performs a kebab case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsKebabCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(format!("{}", AsKebabCase(sentence)), "we-are-going-to-inherit-the-earth"); /// ``` pub struct AsKebabCase>(pub T); impl> fmt::Display for AsKebabCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), lowercase, |f| write!(f, "-"), f) } } #[cfg(test)] mod tests { use super::ToKebabCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_kebab_case(), $s2) } }; } t!(test1: "CamelCase" => "camel-case"); t!(test2: "This is Human case." => "this-is-human-case"); t!(test3: "MixedUP CamelCase, with some Spaces" => "mixed-up-camel-case-with-some-spaces"); t!(test4: "mixed_up_ snake_case with some _spaces" => "mixed-up-snake-case-with-some-spaces"); t!(test5: "kebab-case" => "kebab-case"); t!(test6: "SHOUTY_SNAKE_CASE" => "shouty-snake-case"); t!(test7: "snake_case" => "snake-case"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "this-contains-all-kinds-of-word-boundaries"); t!(test9: "XΣXΣ baffle" => "xσxς-baffle"); t!(test10: "XMLHttpRequest" => "xml-http-request"); t!(test11: "لِنَذْهَبْ إِلَى السِّيْنَمَا" => "لِنَذْهَبْ-إِلَى-السِّيْنَمَا"); // Japanese and Chinese do not have word separation. t!(test12: "ファイルを読み込み" => "ファイルを読み込み"); t!(test13: "祝你一天过得愉快" => "祝你一天过得愉快"); } heck/src/lib.rs0000644000175000017500000001454115105742312013224 0ustar bdrungbdrung//! **heck** is a case conversion library. //! //! This library exists to provide case conversion between common cases like //! CamelCase and snake_case. It is intended to be unicode aware, internally //! consistent, and reasonably well performing. //! //! ## Definition of a word boundary //! //! Word boundaries are defined by non-alphanumeric characters, as well as //! within those words in this manner: //! //! 1. If an uppercase character is followed by lowercase letters, a word //! boundary is considered to be just prior to that uppercase character. //! 2. If multiple uppercase characters are consecutive, they are considered to //! be within a single word, except that the last will be part of the next word //! if it is followed by lowercase characters (see rule 1). //! //! That is, "HelloWorld" is segmented `Hello|World` whereas "XMLHttpRequest" is //! segmented `XML|Http|Request`. //! //! Characters not within words (such as spaces, punctuations, and underscores) //! are not included in the output string except as they are a part of the case //! being converted to. Multiple adjacent word boundaries (such as a series of //! underscores) are folded into one. ("hello__world" in snake case is therefore //! "hello_world", not the exact same string). Leading or trailing word boundary //! indicators are dropped, except insofar as CamelCase capitalizes the first //! word. //! //! ### Cases contained in this library: //! //! 1. UpperCamelCase //! 2. lowerCamelCase //! 3. snake_case //! 4. kebab-case //! 5. SHOUTY_SNAKE_CASE //! 6. Title Case //! 7. SHOUTY-KEBAB-CASE //! 8. Train-Case #![deny(missing_docs)] #![forbid(unsafe_code)] #![no_std] extern crate alloc; mod kebab; mod lower_camel; mod shouty_kebab; mod shouty_snake; mod snake; mod title; mod train; mod upper_camel; pub use kebab::{AsKebabCase, ToKebabCase}; pub use lower_camel::{AsLowerCamelCase, ToLowerCamelCase}; pub use shouty_kebab::{AsShoutyKebabCase, ToShoutyKebabCase}; pub use shouty_snake::{ AsShoutySnakeCase, AsShoutySnakeCase as AsShoutySnekCase, ToShoutySnakeCase, ToShoutySnekCase, }; pub use snake::{AsSnakeCase, AsSnakeCase as AsSnekCase, ToSnakeCase, ToSnekCase}; pub use title::{AsTitleCase, ToTitleCase}; pub use train::{AsTrainCase, ToTrainCase}; pub use upper_camel::{ AsUpperCamelCase, AsUpperCamelCase as AsPascalCase, ToPascalCase, ToUpperCamelCase, }; use core::fmt; fn transform( s: &str, mut with_word: F, mut boundary: G, f: &mut fmt::Formatter, ) -> fmt::Result where F: FnMut(&str, &mut fmt::Formatter) -> fmt::Result, G: FnMut(&mut fmt::Formatter) -> fmt::Result, { /// Tracks the current 'mode' of the transformation algorithm as it scans /// the input string. /// /// The mode is a tri-state which tracks the case of the last cased /// character of the current word. If there is no cased character /// (either lowercase or uppercase) since the previous word boundary, /// than the mode is `Boundary`. If the last cased character is lowercase, /// then the mode is `Lowercase`. Othertherwise, the mode is /// `Uppercase`. #[derive(Clone, Copy, PartialEq)] enum WordMode { /// There have been no lowercase or uppercase characters in the current /// word. Boundary, /// The previous cased character in the current word is lowercase. Lowercase, /// The previous cased character in the current word is uppercase. Uppercase, } let mut first_word = true; for word in s.split(|c: char| !c.is_alphanumeric()) { let mut char_indices = word.char_indices().peekable(); let mut init = 0; let mut mode = WordMode::Boundary; while let Some((i, c)) = char_indices.next() { if let Some(&(next_i, next)) = char_indices.peek() { // The mode including the current character, assuming the // current character does not result in a word boundary. let next_mode = if c.is_lowercase() { WordMode::Lowercase } else if c.is_uppercase() { WordMode::Uppercase } else { mode }; // Word boundary after if current is not uppercase and next // is uppercase if next_mode == WordMode::Lowercase && next.is_uppercase() { if !first_word { boundary(f)?; } with_word(&word[init..next_i], f)?; first_word = false; init = next_i; mode = WordMode::Boundary; // Otherwise if current and previous are uppercase and next // is lowercase, word boundary before } else if mode == WordMode::Uppercase && c.is_uppercase() && next.is_lowercase() { if !first_word { boundary(f)?; } else { first_word = false; } with_word(&word[init..i], f)?; init = i; mode = WordMode::Boundary; // Otherwise no word boundary, just update the mode } else { mode = next_mode; } } else { // Collect trailing characters as a word if !first_word { boundary(f)?; } else { first_word = false; } with_word(&word[init..], f)?; break; } } } Ok(()) } fn lowercase(s: &str, f: &mut fmt::Formatter) -> fmt::Result { let mut chars = s.chars().peekable(); while let Some(c) = chars.next() { if c == 'Σ' && chars.peek().is_none() { write!(f, "ς")?; } else { write!(f, "{}", c.to_lowercase())?; } } Ok(()) } fn uppercase(s: &str, f: &mut fmt::Formatter) -> fmt::Result { for c in s.chars() { write!(f, "{}", c.to_uppercase())?; } Ok(()) } fn capitalize(s: &str, f: &mut fmt::Formatter) -> fmt::Result { let mut char_indices = s.char_indices(); if let Some((_, c)) = char_indices.next() { write!(f, "{}", c.to_uppercase())?; if let Some((i, _)) = char_indices.next() { lowercase(&s[i..], f)?; } } Ok(()) } heck/src/snake.rs0000644000175000017500000000616215105742312013557 0ustar bdrungbdrunguse alloc::{ borrow::ToOwned, fmt, string::{String, ToString}, }; use crate::{lowercase, transform}; /// This trait defines a snake case conversion. /// /// In snake_case, word boundaries are indicated by underscores. /// /// ## Example: /// /// ```rust /// use heck::ToSnakeCase; /// /// let sentence = "We carry a new world here, in our hearts."; /// assert_eq!(sentence.to_snake_case(), "we_carry_a_new_world_here_in_our_hearts"); /// ``` pub trait ToSnakeCase: ToOwned { /// Convert this type to snake case. fn to_snake_case(&self) -> Self::Owned; } /// Oh heck, `SnekCase` is an alias for [`ToSnakeCase`]. See ToSnakeCase for /// more documentation. pub trait ToSnekCase: ToOwned { /// Convert this type to snek case. fn to_snek_case(&self) -> Self::Owned; } impl ToSnekCase for T { fn to_snek_case(&self) -> Self::Owned { self.to_snake_case() } } impl ToSnakeCase for str { fn to_snake_case(&self) -> String { AsSnakeCase(self).to_string() } } /// This wrapper performs a snake case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsSnakeCase; /// /// let sentence = "We carry a new world here, in our hearts."; /// assert_eq!(format!("{}", AsSnakeCase(sentence)), "we_carry_a_new_world_here_in_our_hearts"); /// ``` pub struct AsSnakeCase>(pub T); impl> fmt::Display for AsSnakeCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), lowercase, |f| write!(f, "_"), f) } } #[cfg(test)] mod tests { use super::ToSnakeCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_snake_case(), $s2) } }; } t!(test1: "CamelCase" => "camel_case"); t!(test2: "This is Human case." => "this_is_human_case"); t!(test3: "MixedUP CamelCase, with some Spaces" => "mixed_up_camel_case_with_some_spaces"); t!(test4: "mixed_up_ snake_case with some _spaces" => "mixed_up_snake_case_with_some_spaces"); t!(test5: "kebab-case" => "kebab_case"); t!(test6: "SHOUTY_SNAKE_CASE" => "shouty_snake_case"); t!(test7: "snake_case" => "snake_case"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "this_contains_all_kinds_of_word_boundaries"); t!(test9: "XΣXΣ baffle" => "xσxς_baffle"); t!(test10: "XMLHttpRequest" => "xml_http_request"); t!(test11: "FIELD_NAME11" => "field_name11"); t!(test12: "99BOTTLES" => "99bottles"); t!(test13: "FieldNamE11" => "field_nam_e11"); t!(test14: "abc123def456" => "abc123def456"); t!(test16: "abc123DEF456" => "abc123_def456"); t!(test17: "abc123Def456" => "abc123_def456"); t!(test18: "abc123DEf456" => "abc123_d_ef456"); t!(test19: "ABC123def456" => "abc123def456"); t!(test20: "ABC123DEF456" => "abc123def456"); t!(test21: "ABC123Def456" => "abc123_def456"); t!(test22: "ABC123DEf456" => "abc123d_ef456"); t!(test23: "ABC123dEEf456FOO" => "abc123d_e_ef456_foo"); t!(test24: "abcDEF" => "abc_def"); t!(test25: "ABcDE" => "a_bc_de"); } heck/src/title.rs0000644000175000017500000000427215105742312013577 0ustar bdrungbdrunguse core::fmt; use alloc::{ borrow::ToOwned, string::{String, ToString}, }; use crate::{capitalize, transform}; /// This trait defines a title case conversion. /// /// In Title Case, word boundaries are indicated by spaces, and every word is /// capitalized. /// /// ## Example: /// /// ```rust /// use heck::ToTitleCase; /// /// let sentence = "We have always lived in slums and holes in the wall."; /// assert_eq!(sentence.to_title_case(), "We Have Always Lived In Slums And Holes In The Wall"); /// ``` pub trait ToTitleCase: ToOwned { /// Convert this type to title case. fn to_title_case(&self) -> Self::Owned; } impl ToTitleCase for str { fn to_title_case(&self) -> String { AsTitleCase(self).to_string() } } /// This wrapper performs a title case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsTitleCase; /// /// let sentence = "We have always lived in slums and holes in the wall."; /// assert_eq!(format!("{}", AsTitleCase(sentence)), "We Have Always Lived In Slums And Holes In The Wall"); /// ``` pub struct AsTitleCase>(pub T); impl> fmt::Display for AsTitleCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), capitalize, |f| write!(f, " "), f) } } #[cfg(test)] mod tests { use super::ToTitleCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_title_case(), $s2) } }; } t!(test1: "CamelCase" => "Camel Case"); t!(test2: "This is Human case." => "This Is Human Case"); t!(test3: "MixedUP CamelCase, with some Spaces" => "Mixed Up Camel Case With Some Spaces"); t!(test4: "mixed_up_ snake_case, with some _spaces" => "Mixed Up Snake Case With Some Spaces"); t!(test5: "kebab-case" => "Kebab Case"); t!(test6: "SHOUTY_SNAKE_CASE" => "Shouty Snake Case"); t!(test7: "snake_case" => "Snake Case"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "This Contains All Kinds Of Word Boundaries"); t!(test9: "XΣXΣ baffle" => "Xσxς Baffle"); t!(test10: "XMLHttpRequest" => "Xml Http Request"); } heck/src/shouty_kebab.rs0000644000175000017500000000440315105742312015131 0ustar bdrungbdrunguse core::fmt; use alloc::{borrow::ToOwned, string::ToString}; use crate::{transform, uppercase}; /// This trait defines a shouty kebab case conversion. /// /// In SHOUTY-KEBAB-CASE, word boundaries are indicated by hyphens and all /// words are in uppercase. /// /// ## Example: /// /// ```rust /// use heck::ToShoutyKebabCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(sentence.to_shouty_kebab_case(), "WE-ARE-GOING-TO-INHERIT-THE-EARTH"); /// ``` pub trait ToShoutyKebabCase: ToOwned { /// Convert this type to shouty kebab case. fn to_shouty_kebab_case(&self) -> Self::Owned; } impl ToShoutyKebabCase for str { fn to_shouty_kebab_case(&self) -> Self::Owned { AsShoutyKebabCase(self).to_string() } } /// This wrapper performs a kebab case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsShoutyKebabCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(format!("{}", AsShoutyKebabCase(sentence)), "WE-ARE-GOING-TO-INHERIT-THE-EARTH"); /// ``` pub struct AsShoutyKebabCase>(pub T); impl> fmt::Display for AsShoutyKebabCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), uppercase, |f| write!(f, "-"), f) } } #[cfg(test)] mod tests { use super::ToShoutyKebabCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_shouty_kebab_case(), $s2) } }; } t!(test1: "CamelCase" => "CAMEL-CASE"); t!(test2: "This is Human case." => "THIS-IS-HUMAN-CASE"); t!(test3: "MixedUP CamelCase, with some Spaces" => "MIXED-UP-CAMEL-CASE-WITH-SOME-SPACES"); t!(test4: "mixed_up_ snake_case with some _spaces" => "MIXED-UP-SNAKE-CASE-WITH-SOME-SPACES"); t!(test5: "kebab-case" => "KEBAB-CASE"); t!(test6: "SHOUTY_SNAKE_CASE" => "SHOUTY-SNAKE-CASE"); t!(test7: "snake_case" => "SNAKE-CASE"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "THIS-CONTAINS-ALL-KINDS-OF-WORD-BOUNDARIES"); t!(test9: "XΣXΣ baffle" => "XΣXΣ-BAFFLE"); t!(test10: "XMLHttpRequest" => "XML-HTTP-REQUEST"); t!(test11: "SHOUTY-KEBAB-CASE" => "SHOUTY-KEBAB-CASE"); } heck/src/lower_camel.rs0000644000175000017500000000474615105742312014755 0ustar bdrungbdrunguse core::fmt; use alloc::{ borrow::ToOwned, string::{String, ToString}, }; use crate::{capitalize, lowercase, transform}; /// This trait defines a lower camel case conversion. /// /// In lowerCamelCase, word boundaries are indicated by capital letters, /// excepting the first word. /// /// ## Example: /// /// ```rust /// use heck::ToLowerCamelCase; /// /// let sentence = "It is we who built these palaces and cities."; /// assert_eq!(sentence.to_lower_camel_case(), "itIsWeWhoBuiltThesePalacesAndCities"); /// ``` pub trait ToLowerCamelCase: ToOwned { /// Convert this type to lower camel case. fn to_lower_camel_case(&self) -> Self::Owned; } impl ToLowerCamelCase for str { fn to_lower_camel_case(&self) -> String { AsLowerCamelCase(self).to_string() } } /// This wrapper performs a lower camel case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsLowerCamelCase; /// /// let sentence = "It is we who built these palaces and cities."; /// assert_eq!(format!("{}", AsLowerCamelCase(sentence)), "itIsWeWhoBuiltThesePalacesAndCities"); /// ``` pub struct AsLowerCamelCase>(pub T); impl> fmt::Display for AsLowerCamelCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut first = true; transform( self.0.as_ref(), |s, f| { if first { first = false; lowercase(s, f) } else { capitalize(s, f) } }, |_| Ok(()), f, ) } } #[cfg(test)] mod tests { use super::ToLowerCamelCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_lower_camel_case(), $s2) } }; } t!(test1: "CamelCase" => "camelCase"); t!(test2: "This is Human case." => "thisIsHumanCase"); t!(test3: "MixedUP CamelCase, with some Spaces" => "mixedUpCamelCaseWithSomeSpaces"); t!(test4: "mixed_up_ snake_case, with some _spaces" => "mixedUpSnakeCaseWithSomeSpaces"); t!(test5: "kebab-case" => "kebabCase"); t!(test6: "SHOUTY_SNAKE_CASE" => "shoutySnakeCase"); t!(test7: "snake_case" => "snakeCase"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "thisContainsAllKindsOfWordBoundaries"); t!(test9: "XΣXΣ baffle" => "xσxςBaffle"); t!(test10: "XMLHttpRequest" => "xmlHttpRequest"); } heck/src/train.rs0000644000175000017500000000547015105742312013574 0ustar bdrungbdrunguse core::fmt; use alloc::{borrow::ToOwned, string::ToString}; use crate::{capitalize, transform}; /// This trait defines a train case conversion. /// /// In Train-Case, word boundaries are indicated by hyphens and words start /// with Capital Letters. /// /// ## Example: /// /// ```rust /// use heck::ToTrainCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(sentence.to_train_case(), "We-Are-Going-To-Inherit-The-Earth"); /// ``` pub trait ToTrainCase: ToOwned { /// Convert this type to Train-Case. fn to_train_case(&self) -> Self::Owned; } impl ToTrainCase for str { fn to_train_case(&self) -> Self::Owned { AsTrainCase(self).to_string() } } /// This wrapper performs a train case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsTrainCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(format!("{}", AsTrainCase(sentence)), "We-Are-Going-To-Inherit-The-Earth"); /// ``` pub struct AsTrainCase>(pub T); impl> fmt::Display for AsTrainCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), capitalize, |f| write!(f, "-"), f) } } #[cfg(test)] mod tests { use super::ToTrainCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_train_case(), $s2) } }; } t!(test1: "CamelCase" => "Camel-Case"); t!(test2: "This is Human case." => "This-Is-Human-Case"); t!(test3: "MixedUP CamelCase, with some Spaces" => "Mixed-Up-Camel-Case-With-Some-Spaces"); t!(test4: "mixed_up_ snake_case with some _spaces" => "Mixed-Up-Snake-Case-With-Some-Spaces"); t!(test5: "kebab-case" => "Kebab-Case"); t!(test6: "SHOUTY_SNAKE_CASE" => "Shouty-Snake-Case"); t!(test7: "snake_case" => "Snake-Case"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "This-Contains-All-Kinds-Of-Word-Boundaries"); #[cfg(feature = "unicode")] t!(test9: "XΣXΣ baffle" => "Xσxς-Baffle"); t!(test10: "XMLHttpRequest" => "Xml-Http-Request"); t!(test11: "FIELD_NAME11" => "Field-Name11"); t!(test12: "99BOTTLES" => "99bottles"); t!(test13: "FieldNamE11" => "Field-Nam-E11"); t!(test14: "abc123def456" => "Abc123def456"); t!(test16: "abc123DEF456" => "Abc123-Def456"); t!(test17: "abc123Def456" => "Abc123-Def456"); t!(test18: "abc123DEf456" => "Abc123-D-Ef456"); t!(test19: "ABC123def456" => "Abc123def456"); t!(test20: "ABC123DEF456" => "Abc123def456"); t!(test21: "ABC123Def456" => "Abc123-Def456"); t!(test22: "ABC123DEf456" => "Abc123d-Ef456"); t!(test23: "ABC123dEEf456FOO" => "Abc123d-E-Ef456-Foo"); t!(test24: "abcDEF" => "Abc-Def"); t!(test25: "ABcDE" => "A-Bc-De"); } heck/src/upper_camel.rs0000644000175000017500000000506215105742312014750 0ustar bdrungbdrunguse core::fmt; use alloc::{ borrow::ToOwned, string::{String, ToString}, }; use crate::{capitalize, transform}; /// This trait defines an upper camel case conversion. /// /// In UpperCamelCase, word boundaries are indicated by capital letters, /// including the first word. /// /// ## Example: /// /// ```rust /// use heck::ToUpperCamelCase; /// /// let sentence = "We are not in the least afraid of ruins."; /// assert_eq!(sentence.to_upper_camel_case(), "WeAreNotInTheLeastAfraidOfRuins"); /// ``` pub trait ToUpperCamelCase: ToOwned { /// Convert this type to upper camel case. fn to_upper_camel_case(&self) -> Self::Owned; } impl ToUpperCamelCase for str { fn to_upper_camel_case(&self) -> String { AsUpperCamelCase(self).to_string() } } /// `ToPascalCase` is an alias for [`ToUpperCamelCase`]. See ToUpperCamelCase for more /// documentation. pub trait ToPascalCase: ToOwned { /// Convert this type to upper camel case. fn to_pascal_case(&self) -> Self::Owned; } impl ToPascalCase for T { fn to_pascal_case(&self) -> Self::Owned { self.to_upper_camel_case() } } /// This wrapper performs a upper camel case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsUpperCamelCase; /// /// let sentence = "We are not in the least afraid of ruins."; /// assert_eq!(format!("{}", AsUpperCamelCase(sentence)), "WeAreNotInTheLeastAfraidOfRuins"); /// ``` pub struct AsUpperCamelCase>(pub T); impl> fmt::Display for AsUpperCamelCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), capitalize, |_| Ok(()), f) } } #[cfg(test)] mod tests { use super::ToUpperCamelCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_upper_camel_case(), $s2) } }; } t!(test1: "CamelCase" => "CamelCase"); t!(test2: "This is Human case." => "ThisIsHumanCase"); t!(test3: "MixedUP_CamelCase, with some Spaces" => "MixedUpCamelCaseWithSomeSpaces"); t!(test4: "mixed_up_ snake_case, with some _spaces" => "MixedUpSnakeCaseWithSomeSpaces"); t!(test5: "kebab-case" => "KebabCase"); t!(test6: "SHOUTY_SNAKE_CASE" => "ShoutySnakeCase"); t!(test7: "snake_case" => "SnakeCase"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "ThisContainsAllKindsOfWordBoundaries"); t!(test9: "XΣXΣ baffle" => "XσxςBaffle"); t!(test10: "XMLHttpRequest" => "XmlHttpRequest"); } indoc/0000775000175000017500000000000015105742312011500 5ustar bdrungbdrungindoc/tests/0000775000175000017500000000000015105742312012642 5ustar bdrungbdrungindoc/tests/test_indoc.rs0000644000175000017500000000543515105742312015350 0ustar bdrungbdrunguse indoc::indoc; const HELP: &str = indoc! {" Usage: ./foo "}; #[test] fn test_global() { let expected = "Usage: ./foo\n"; assert_eq!(HELP, expected); } #[test] fn byte_string() { let indoc = indoc! {b" a \\b c" }; let expected = b"a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn carriage_return() { // Every line in the string ends with \r\n let indoc = indoc! {" a \\b c" }; let expected = "a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn trailing_comma() { let indoc = indoc! { " test ", }; let expected = "test\n"; assert_eq!(indoc, expected); } #[test] fn empty_string() { let indoc = indoc! {""}; let expected = ""; assert_eq!(indoc, expected); } #[test] fn joined_first_line() { let indoc = indoc! {"\ a" }; let expected = "a"; assert_eq!(indoc, expected); } #[test] fn joined_lines() { let indoc = indoc! {" a\ b c\ d e" }; let expected = "ab\ncd\ne"; assert_eq!(indoc, expected); } #[test] fn no_leading_newline() { let indoc = indoc! {"a b c"}; let expected = "a\nb\nc"; assert_eq!(indoc, expected); } #[test] fn one_line() { let indoc = indoc! {"a"}; let expected = "a"; assert_eq!(indoc, expected); } #[test] fn raw_byte_string() { let indoc = indoc! {br#" "a" \\b c"# }; let expected = b"\"a\"\n\n \\\\b\nc"; assert_eq!(indoc, expected); } #[test] fn raw_string() { let indoc = indoc! {r#" "a" \\b c"# }; let expected = "\"a\"\n\n \\\\b\nc"; assert_eq!(indoc, expected); } #[test] fn string() { let indoc = indoc! {" a \\b c" }; let expected = "a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn string_trailing_newline() { let indoc = indoc! {" a \\b c "}; let expected = "a\n\n \\b\nc\n"; assert_eq!(indoc, expected); } #[test] fn trailing_whitespace() { let indoc = indoc! {" 2 below 0 below -2 below end" }; let expected = "2 below\n \n0 below\n\n-2 below\n\nend"; assert_eq!(indoc, expected); } #[test] fn indoc_as_format_string() { let s = format!(indoc! {"{}"}, true); assert_eq!(s, "true"); } #[test] fn test_metavariable() { macro_rules! indoc_wrapper { ($e:expr) => { indoc!($e) }; } let indoc = indoc_wrapper! {" macros, how do they work "}; let expected = "macros, how do they work\n"; assert_eq!(indoc, expected); } indoc/tests/compiletest.rs0000644000175000017500000000032615105742312015537 0ustar bdrungbdrung#[rustversion::attr(not(nightly), ignore = "requires nightly")] #[cfg_attr(miri, ignore = "incompatible with miri")] #[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/*.rs"); } indoc/tests/test_unindent.rs0000644000175000017500000000225315105742312016073 0ustar bdrungbdrung#![allow(clippy::shadow_unrelated)] use unindent::{unindent, unindent_bytes, Unindent}; #[test] fn fn_unindent_str() { let s = " line one line two"; assert_eq!(unindent(s), "line one\nline two"); let s = "\n\t\t\tline one\n\t\t\tline two"; assert_eq!(unindent(s), "line one\nline two"); } #[test] fn fn_unindent_bytes() { let b = b" line one line two"; assert_eq!(unindent_bytes(b), b"line one\nline two"); let b = b"\n\t\t\tline one\n\t\t\tline two"; assert_eq!(unindent_bytes(b), b"line one\nline two"); } #[test] fn trait_unindent_str() { let s = " line one line two"; assert_eq!(s.unindent(), "line one\nline two"); let s = "\n\t\t\tline one\n\t\t\tline two"; assert_eq!(s.unindent(), "line one\nline two"); } #[test] fn trait_unindent_bytes() { let b = b" line one line two"; assert_eq!(b.unindent(), b"line one\nline two"); let b = b"\n\t\t\tline one\n\t\t\tline two"; assert_eq!(b.unindent(), b"line one\nline two"); } #[test] fn carriage_returns() { let s = "\r\n\tline one\r\n\tline two"; assert_eq!(unindent(s), "line one\r\nline two"); } indoc/tests/ui/0000775000175000017500000000000015105742312013257 5ustar bdrungbdrungindoc/tests/ui/printdoc-binary.rs0000644000175000017500000000007015105742312016724 0ustar bdrungbdrunguse indoc::printdoc; fn main() { printdoc!(b""); } indoc/tests/ui/three-arguments.stderr0000644000175000017500000000026315105742312017615 0ustar bdrungbdrungerror: unexpected tokens in macro invocation; indoc argument must be a single string literal --> tests/ui/three-arguments.rs:8:11 | 8 | " 64 128); | ^^^^^^ indoc/tests/ui/capture-var-nested.stderr0000644000175000017500000000056715105742312020223 0ustar bdrungbdrungerror: there is no argument named `world` --> tests/ui/capture-var-nested.rs:5:21 | 5 | println!(indoc!("Hello {world}")); | ^^^^^^^^^^^^^^^ | = note: did you intend to capture a variable `world` from the surrounding scope? = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro indoc/tests/ui/two-arguments.rs0000644000175000017500000000013315105742312016434 0ustar bdrungbdrunguse indoc::indoc; fn main() { indoc!(" a b c " 64); } indoc/tests/ui/non-lit.stderr0000644000175000017500000000017415105742312016064 0ustar bdrungbdrungerror: argument must be a single string literal --> tests/ui/non-lit.rs:4:12 | 4 | indoc!(fail); | ^^^^ indoc/tests/ui/no-arguments.rs0000644000175000017500000000005715105742312016244 0ustar bdrungbdrunguse indoc::indoc; fn main() { indoc!(); } indoc/tests/ui/no-arguments.stderr0000644000175000017500000000040315105742312017116 0ustar bdrungbdrungerror: unexpected end of macro invocation, expected format string --> tests/ui/no-arguments.rs:4:5 | 4 | indoc!(); | ^^^^^^^^ | = note: this error originates in the macro `indoc` (in Nightly builds, run with -Z macro-backtrace for more info) indoc/tests/ui/printdoc-binary.stderr0000644000175000017500000000022315105742312017603 0ustar bdrungbdrungerror: byte strings are not supported in formatting macros --> tests/ui/printdoc-binary.rs:4:15 | 4 | printdoc!(b""); | ^^^ indoc/tests/ui/printdoc-no-display.stderr0000644000175000017500000000112515105742312020400 0ustar bdrungbdrungerror[E0277]: `NoDisplay` doesn't implement `std::fmt::Display` --> tests/ui/printdoc-no-display.rs:6:21 | 6 | printdoc!("{}", NoDisplay); | ^^^^^^^^^ `NoDisplay` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `NoDisplay` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args` which comes from the expansion of the macro `printdoc` (in Nightly builds, run with -Z macro-backtrace for more info) indoc/tests/ui/two-arguments.stderr0000644000175000017500000000025015105742312017313 0ustar bdrungbdrungerror: unexpected token in macro invocation; indoc argument must be a single string literal --> tests/ui/two-arguments.rs:8:11 | 8 | " 64); | ^^ indoc/tests/ui/non-string.stderr0000644000175000017500000000017315105742312016601 0ustar bdrungbdrungerror: argument must be a single string literal --> tests/ui/non-string.rs:4:12 | 4 | indoc!(64); | ^^ indoc/tests/ui/printdoc-no-named-arg.stderr0000644000175000017500000000026615105742312020573 0ustar bdrungbdrungerror[E0425]: cannot find value `named` in this scope --> tests/ui/printdoc-no-named-arg.rs:4:17 | 4 | printdoc!("{named}"); | ^^^^^ not found in this scope indoc/tests/ui/non-lit.rs0000644000175000017500000000006315105742312015202 0ustar bdrungbdrunguse indoc::indoc; fn main() { indoc!(fail); } indoc/tests/ui/printdoc-extra-arg.stderr0000644000175000017500000000032115105742312020210 0ustar bdrungbdrungerror: argument never used --> tests/ui/printdoc-extra-arg.rs:4:19 | 4 | printdoc!("", 0); | -- ^ argument never used | | | formatting specifier missing indoc/tests/ui/non-string.rs0000644000175000017500000000006115105742312015716 0ustar bdrungbdrunguse indoc::indoc; fn main() { indoc!(64); } indoc/tests/ui/printdoc-no-named-arg.rs0000644000175000017500000000007615105742312017713 0ustar bdrungbdrunguse indoc::printdoc; fn main() { printdoc!("{named}"); } indoc/tests/ui/printdoc-no-display.rs0000644000175000017500000000012715105742312017522 0ustar bdrungbdrunguse indoc::printdoc; struct NoDisplay; fn main() { printdoc!("{}", NoDisplay); } indoc/tests/ui/printdoc-no-arg.rs0000644000175000017500000000007115105742312016624 0ustar bdrungbdrunguse indoc::printdoc; fn main() { printdoc!("{}"); } indoc/tests/ui/printdoc-no-arg.stderr0000644000175000017500000000024415105742312017505 0ustar bdrungbdrungerror: 1 positional argument in format string, but no arguments were given --> tests/ui/printdoc-no-arg.rs:4:16 | 4 | printdoc!("{}"); | ^^ indoc/tests/ui/printdoc-extra-arg.rs0000644000175000017500000000007215105742312017334 0ustar bdrungbdrunguse indoc::printdoc; fn main() { printdoc!("", 0); } indoc/tests/ui/capture-var-nested.rs0000644000175000017500000000014115105742312017330 0ustar bdrungbdrunguse indoc::indoc; fn main() { let world = "world"; println!(indoc!("Hello {world}")); } indoc/tests/ui/three-arguments.rs0000644000175000017500000000013715105742312016736 0ustar bdrungbdrunguse indoc::indoc; fn main() { indoc!(" a b c " 64 128); } indoc/tests/test_concat.rs0000644000175000017500000000053215105742312015514 0ustar bdrungbdrunguse indoc::concatdoc; macro_rules! env { ($var:literal) => { "test" }; } static HELP: &str = concatdoc! {" Usage: ", env!("CARGO_BIN_NAME"), " [options] Options: -h, --help "}; #[test] fn test_help() { let expected = "Usage: test [options]\n\nOptions:\n -h, --help\n"; assert_eq!(HELP, expected); } indoc/tests/test_formatdoc.rs0000644000175000017500000000377015105742312016232 0ustar bdrungbdrunguse indoc::formatdoc; #[test] fn carriage_return() { // Every line in the string ends with \r\n let indoc = formatdoc! {" {} \\{} {}", 'a', 'b', 'c' }; let expected = "a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn empty_string() { let indoc = formatdoc! {""}; let expected = ""; assert_eq!(indoc, expected); } #[test] fn joined_first_line() { let indoc = formatdoc! {"\ {}", 'a' }; let expected = "a"; assert_eq!(indoc, expected); } #[test] fn joined_lines() { let indoc = formatdoc! {" {}\ {} {}\ {} {}", 'a', 'b', 'c', 'd', 'e' }; let expected = "ab\ncd\ne"; assert_eq!(indoc, expected); } #[test] fn no_leading_newline() { let indoc = formatdoc! {"{} {} {}", 'a', 'b', 'c'}; let expected = "a\nb\nc"; assert_eq!(indoc, expected); } #[test] fn one_line() { let indoc = formatdoc! {"a"}; let expected = "a"; assert_eq!(indoc, expected); } #[test] fn raw_string() { let indoc = formatdoc! {r#" {:?}" \\{} {}"#, "a", 'b', 'c' }; let expected = "\"a\"\"\n\n \\\\b\nc"; assert_eq!(indoc, expected); } #[test] fn string() { let indoc = formatdoc! {" {} \\{} {}", 'a', 'b', 'c' }; let expected = "a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn string_trailing_newline() { let indoc = formatdoc! {" {} \\{} {} ", 'a', 'b', 'c' }; let expected = "a\n\n \\b\nc\n"; assert_eq!(indoc, expected); } #[test] fn trailing_whitespace() { let indoc = formatdoc! {" {} {below} {} {below} {} {below} end", 2, 0, -2, below = "below" }; let expected = "2 below\n \n0 below\n\n-2 below\n\nend"; assert_eq!(indoc, expected); } indoc/tests/test_writedoc.rs0000644000175000017500000000170315105742312016066 0ustar bdrungbdrung#![allow(clippy::if_same_then_else, clippy::let_underscore_untyped)] use indoc::writedoc; use std::fmt::Write as _; #[test] fn test_write_to_string() { let mut s = String::new(); writedoc!( s, " one two ", ) .unwrap(); let expected = "one\ntwo\n"; assert_eq!(s, expected); } #[test] fn test_format_args() { let mut s = String::new(); writedoc!( s, " {} {} ", 0, 0, ) .unwrap(); let expected = "0\n0\n"; assert_eq!(s, expected); } #[test] fn test_angle_bracket_parsing() { const ZERO: usize = 0; struct Pair(A, B); impl Pair { const ONE: usize = 1; } let mut s = String::new(); let _ = writedoc! { if ZERO < Pair:: (), ()>::ONE { &mut s } else { &mut s }, "writedoc", }; let expected = "writedoc"; assert_eq!(s, expected); } indoc/LICENSE-MIT0000644000175000017500000000177715105742312013146 0ustar bdrungbdrungPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. indoc/Cargo.lock0000644000175000017500000002015115105742312013402 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "dissimilar" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "glob" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "indexmap" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "indoc" version = "2.0.6" dependencies = [ "rustversion", "trybuild", "unindent", ] [[package]] name = "itoa" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "proc-macro2" version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" dependencies = [ "proc-macro2", ] [[package]] name = "rustversion" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "serde" version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] [[package]] name = "syn" version = "2.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-triple" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "toml" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", "toml_datetime", "toml_edit", ] [[package]] name = "toml_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "winnow", ] [[package]] name = "trybuild" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b812699e0c4f813b872b373a4471717d9eb550da14b311058a4d9cf4173cbca6" dependencies = [ "dissimilar", "glob", "serde", "serde_derive", "serde_json", "target-triple", "termcolor", "toml", ] [[package]] name = "unicode-ident" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "unindent" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ "memchr", ] indoc/Cargo.toml0000644000175000017500000000377715105742312013444 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "indoc" version = "2.0.6" authors = ["David Tolnay "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Indented document literals" documentation = "https://docs.rs/indoc" readme = "README.md" keywords = [ "heredoc", "nowdoc", "multiline", "string", "literal", ] categories = [ "rust-patterns", "text-processing", "no-std", "no-std::no-alloc", ] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/indoc" [package.metadata.docs.rs] rustdoc-args = [ "--generate-link-to-definition", "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", ] targets = ["x86_64-unknown-linux-gnu"] [lib] name = "indoc" path = "src/lib.rs" proc-macro = true [[test]] name = "compiletest" path = "tests/compiletest.rs" [[test]] name = "test_concat" path = "tests/test_concat.rs" [[test]] name = "test_formatdoc" path = "tests/test_formatdoc.rs" [[test]] name = "test_indoc" path = "tests/test_indoc.rs" [[test]] name = "test_unindent" path = "tests/test_unindent.rs" [[test]] name = "test_writedoc" path = "tests/test_writedoc.rs" [dev-dependencies.rustversion] version = "1.0" [dev-dependencies.trybuild] version = "1.0.49" features = ["diff"] [dev-dependencies.unindent] version = "0.2.3" indoc/.cargo-checksum.json0000664000175000017500000000013115105742312015337 0ustar bdrungbdrung{"files":{},"package":"f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"}indoc/LICENSE-APACHE0000644000175000017500000002277315105742312013435 0ustar bdrungbdrung Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS indoc/README.md0000644000175000017500000001017315105742312012757 0ustar bdrungbdrungIndented Documents (indoc) ========================== [github](https://github.com/dtolnay/indoc) [crates.io](https://crates.io/crates/indoc) [docs.rs](https://docs.rs/indoc) [build status](https://github.com/dtolnay/indoc/actions?query=branch%3Amaster) This crate provides a procedural macro for indented string literals. The `indoc!()` macro takes a multiline string literal and un-indents it at compile time so the leftmost non-space character is in the first column. ```toml [dependencies] indoc = "2" ``` *Compiler requirement: rustc 1.56 or greater.*
## Using indoc ```rust use indoc::indoc; fn main() { let testing = indoc! {" def hello(): print('Hello, world!') hello() "}; let expected = "def hello():\n print('Hello, world!')\n\nhello()\n"; assert_eq!(testing, expected); } ``` Indoc also works with raw string literals: ```rust use indoc::indoc; fn main() { let testing = indoc! {r#" def hello(): print("Hello, world!") hello() "#}; let expected = "def hello():\n print(\"Hello, world!\")\n\nhello()\n"; assert_eq!(testing, expected); } ``` And byte string literals: ```rust use indoc::indoc; fn main() { let testing = indoc! {b" def hello(): print('Hello, world!') hello() "}; let expected = b"def hello():\n print('Hello, world!')\n\nhello()\n"; assert_eq!(testing[..], expected[..]); } ```
## Formatting macros The indoc crate exports five additional macros to substitute conveniently for the standard library's formatting macros: - `formatdoc!($fmt, ...)` — equivalent to `format!(indoc!($fmt), ...)` - `printdoc!($fmt, ...)` — equivalent to `print!(indoc!($fmt), ...)` - `eprintdoc!($fmt, ...)` — equivalent to `eprint!(indoc!($fmt), ...)` - `writedoc!($dest, $fmt, ...)` — equivalent to `write!($dest, indoc!($fmt), ...)` - `concatdoc!(...)` — equivalent to `concat!(...)` with each string literal wrapped in `indoc!` ```rust use indoc::{concatdoc, printdoc}; const HELP: &str = concatdoc! {" Usage: ", env!("CARGO_BIN_NAME"), " [options] Options: -h, --help "}; fn main() { printdoc! {" GET {url} Accept: {mime} ", url = "http://localhost:8080", mime = "application/json", } } ```
## Explanation The following rules characterize the behavior of the `indoc!()` macro: 1. Count the leading spaces of each line, ignoring the first line and any lines that are empty or contain spaces only. 2. Take the minimum. 3. If the first line is empty i.e. the string begins with a newline, remove the first line. 4. Remove the computed number of spaces from the beginning of each line.
## Unindent Indoc's indentation logic is available in the `unindent` crate. This may be useful for processing strings that are not statically known at compile time. The crate exposes two functions: - `unindent(&str) -> String` - `unindent_bytes(&[u8]) -> Vec` ```rust use unindent::unindent; fn main() { let indented = " line one line two"; assert_eq!("line one\nline two", unindent(indented)); } ```
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. indoc/src/0000775000175000017500000000000015105742312012267 5ustar bdrungbdrungindoc/src/expr.rs0000644000175000017500000000417015105742312013613 0ustar bdrungbdrunguse crate::error::{Error, Result}; use proc_macro::token_stream::IntoIter as TokenIter; use proc_macro::{Spacing, Span, TokenStream, TokenTree}; use std::iter::{self, Peekable}; pub fn parse(input: &mut Peekable, require_comma: bool) -> Result { #[derive(PartialEq)] enum Lookbehind { JointColon, DoubleColon, JointHyphen, Other, } let mut expr = TokenStream::new(); let mut lookbehind = Lookbehind::Other; let mut angle_bracket_depth = 0; loop { if angle_bracket_depth == 0 { match input.peek() { Some(TokenTree::Punct(punct)) if punct.as_char() == ',' => { return Ok(expr); } _ => {} } } match input.next() { Some(TokenTree::Punct(punct)) => { let ch = punct.as_char(); let spacing = punct.spacing(); expr.extend(iter::once(TokenTree::Punct(punct))); lookbehind = match ch { ':' if lookbehind == Lookbehind::JointColon => Lookbehind::DoubleColon, ':' if spacing == Spacing::Joint => Lookbehind::JointColon, '<' if lookbehind == Lookbehind::DoubleColon => { angle_bracket_depth += 1; Lookbehind::Other } '>' if angle_bracket_depth > 0 && lookbehind != Lookbehind::JointHyphen => { angle_bracket_depth -= 1; Lookbehind::Other } '-' if spacing == Spacing::Joint => Lookbehind::JointHyphen, _ => Lookbehind::Other, }; } Some(token) => expr.extend(iter::once(token)), None => { return if require_comma { Err(Error::new( Span::call_site(), "unexpected end of macro input", )) } else { Ok(expr) }; } } } } indoc/src/lib.rs0000644000175000017500000003177415105742312013415 0ustar bdrungbdrung//! [![github]](https://github.com/dtolnay/indoc) [![crates-io]](https://crates.io/crates/indoc) [![docs-rs]](https://docs.rs/indoc) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //!
//! //! This crate provides a procedural macro for indented string literals. The //! `indoc!()` macro takes a multiline string literal and un-indents it at //! compile time so the leftmost non-space character is in the first column. //! //! ```toml //! [dependencies] //! indoc = "2" //! ``` //! //!
//! //! # Using indoc //! //! ``` //! use indoc::indoc; //! //! fn main() { //! let testing = indoc! {" //! def hello(): //! print('Hello, world!') //! //! hello() //! "}; //! let expected = "def hello():\n print('Hello, world!')\n\nhello()\n"; //! assert_eq!(testing, expected); //! } //! ``` //! //! Indoc also works with raw string literals: //! //! ``` //! use indoc::indoc; //! //! fn main() { //! let testing = indoc! {r#" //! def hello(): //! print("Hello, world!") //! //! hello() //! "#}; //! let expected = "def hello():\n print(\"Hello, world!\")\n\nhello()\n"; //! assert_eq!(testing, expected); //! } //! ``` //! //! And byte string literals: //! //! ``` //! use indoc::indoc; //! //! fn main() { //! let testing = indoc! {b" //! def hello(): //! print('Hello, world!') //! //! hello() //! "}; //! let expected = b"def hello():\n print('Hello, world!')\n\nhello()\n"; //! assert_eq!(testing[..], expected[..]); //! } //! ``` //! //!

//! //! # Formatting macros //! //! The indoc crate exports five additional macros to substitute conveniently //! for the standard library's formatting macros: //! //! - `formatdoc!($fmt, ...)` — equivalent to `format!(indoc!($fmt), ...)` //! - `printdoc!($fmt, ...)` — equivalent to `print!(indoc!($fmt), ...)` //! - `eprintdoc!($fmt, ...)` — equivalent to `eprint!(indoc!($fmt), ...)` //! - `writedoc!($dest, $fmt, ...)` — equivalent to `write!($dest, indoc!($fmt), ...)` //! - `concatdoc!(...)` — equivalent to `concat!(...)` with each string literal wrapped in `indoc!` //! //! ``` //! # macro_rules! env { //! # ($var:literal) => { //! # "example" //! # }; //! # } //! # //! use indoc::{concatdoc, printdoc}; //! //! const HELP: &str = concatdoc! {" //! Usage: ", env!("CARGO_BIN_NAME"), " [options] //! //! Options: //! -h, --help //! "}; //! //! fn main() { //! printdoc! {" //! GET {url} //! Accept: {mime} //! ", //! url = "http://localhost:8080", //! mime = "application/json", //! } //! } //! ``` //! //!

//! //! # Explanation //! //! The following rules characterize the behavior of the `indoc!()` macro: //! //! 1. Count the leading spaces of each line, ignoring the first line and any //! lines that are empty or contain spaces only. //! 2. Take the minimum. //! 3. If the first line is empty i.e. the string begins with a newline, remove //! the first line. //! 4. Remove the computed number of spaces from the beginning of each line. #![doc(html_root_url = "https://docs.rs/indoc/2.0.6")] #![allow( clippy::derive_partial_eq_without_eq, clippy::from_iter_instead_of_collect, clippy::module_name_repetitions, clippy::needless_doctest_main, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref, clippy::type_complexity )] mod error; mod expr; mod unindent; use crate::error::{Error, Result}; use crate::unindent::do_unindent; use proc_macro::token_stream::IntoIter as TokenIter; use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use std::iter::{self, Peekable}; use std::str::FromStr; #[derive(Copy, Clone, PartialEq)] enum Macro { Indoc, Format, Print, Eprint, Write, Concat, } /// Unindent and produce `&'static str` or `&'static [u8]`. /// /// Supports normal strings, raw strings, bytestrings, and raw bytestrings. /// /// # Example /// /// ``` /// # use indoc::indoc; /// # /// // The type of `program` is &'static str /// let program = indoc! {" /// def hello(): /// print('Hello, world!') /// /// hello() /// "}; /// print!("{}", program); /// ``` /// /// ```text /// def hello(): /// print('Hello, world!') /// /// hello() /// ``` #[proc_macro] pub fn indoc(input: TokenStream) -> TokenStream { expand(input, Macro::Indoc) } /// Unindent and call `format!`. /// /// Argument syntax is the same as for [`std::format!`]. /// /// # Example /// /// ``` /// # use indoc::formatdoc; /// # /// let request = formatdoc! {" /// GET {url} /// Accept: {mime} /// ", /// url = "http://localhost:8080", /// mime = "application/json", /// }; /// println!("{}", request); /// ``` /// /// ```text /// GET http://localhost:8080 /// Accept: application/json /// ``` #[proc_macro] pub fn formatdoc(input: TokenStream) -> TokenStream { expand(input, Macro::Format) } /// Unindent and call `print!`. /// /// Argument syntax is the same as for [`std::print!`]. /// /// # Example /// /// ``` /// # use indoc::printdoc; /// # /// printdoc! {" /// GET {url} /// Accept: {mime} /// ", /// url = "http://localhost:8080", /// mime = "application/json", /// } /// ``` /// /// ```text /// GET http://localhost:8080 /// Accept: application/json /// ``` #[proc_macro] pub fn printdoc(input: TokenStream) -> TokenStream { expand(input, Macro::Print) } /// Unindent and call `eprint!`. /// /// Argument syntax is the same as for [`std::eprint!`]. /// /// # Example /// /// ``` /// # use indoc::eprintdoc; /// # /// eprintdoc! {" /// GET {url} /// Accept: {mime} /// ", /// url = "http://localhost:8080", /// mime = "application/json", /// } /// ``` /// /// ```text /// GET http://localhost:8080 /// Accept: application/json /// ``` #[proc_macro] pub fn eprintdoc(input: TokenStream) -> TokenStream { expand(input, Macro::Eprint) } /// Unindent and call `write!`. /// /// Argument syntax is the same as for [`std::write!`]. /// /// # Example /// /// ``` /// # use indoc::writedoc; /// # use std::io::Write; /// # /// let _ = writedoc!( /// std::io::stdout(), /// " /// GET {url} /// Accept: {mime} /// ", /// url = "http://localhost:8080", /// mime = "application/json", /// ); /// ``` /// /// ```text /// GET http://localhost:8080 /// Accept: application/json /// ``` #[proc_macro] pub fn writedoc(input: TokenStream) -> TokenStream { expand(input, Macro::Write) } /// Unindent and call `concat!`. /// /// Argument syntax is the same as for [`std::concat!`]. /// /// # Example /// /// ``` /// # use indoc::concatdoc; /// # /// # macro_rules! env { /// # ($var:literal) => { /// # "example" /// # }; /// # } /// # /// const HELP: &str = concatdoc! {" /// Usage: ", env!("CARGO_BIN_NAME"), " [options] /// /// Options: /// -h, --help /// "}; /// /// print!("{}", HELP); /// ``` /// /// ```text /// Usage: example [options] /// /// Options: /// -h, --help /// ``` #[proc_macro] pub fn concatdoc(input: TokenStream) -> TokenStream { expand(input, Macro::Concat) } fn expand(input: TokenStream, mode: Macro) -> TokenStream { match try_expand(input, mode) { Ok(tokens) => tokens, Err(err) => err.to_compile_error(), } } fn try_expand(input: TokenStream, mode: Macro) -> Result { let mut input = input.into_iter().peekable(); let prefix = match mode { Macro::Indoc | Macro::Format | Macro::Print | Macro::Eprint => None, Macro::Write => { let require_comma = true; let mut expr = expr::parse(&mut input, require_comma)?; expr.extend(iter::once(input.next().unwrap())); // add comma Some(expr) } Macro::Concat => return do_concat(input), }; let first = input.next().ok_or_else(|| { Error::new( Span::call_site(), "unexpected end of macro invocation, expected format string", ) })?; let preserve_empty_first_line = false; let unindented_lit = lit_indoc(first, mode, preserve_empty_first_line)?; let macro_name = match mode { Macro::Indoc => { require_empty_or_trailing_comma(&mut input)?; return Ok(TokenStream::from(TokenTree::Literal(unindented_lit))); } Macro::Format => "format", Macro::Print => "print", Macro::Eprint => "eprint", Macro::Write => "write", Macro::Concat => unreachable!(), }; // #macro_name! { #unindented_lit #args } Ok(TokenStream::from_iter(vec![ TokenTree::Ident(Ident::new(macro_name, Span::call_site())), TokenTree::Punct(Punct::new('!', Spacing::Alone)), TokenTree::Group(Group::new( Delimiter::Brace, prefix .unwrap_or_else(TokenStream::new) .into_iter() .chain(iter::once(TokenTree::Literal(unindented_lit))) .chain(input) .collect(), )), ])) } fn do_concat(mut input: Peekable) -> Result { let mut result = TokenStream::new(); let mut first = true; while input.peek().is_some() { let require_comma = false; let mut expr = expr::parse(&mut input, require_comma)?; let mut expr_tokens = expr.clone().into_iter(); if let Some(token) = expr_tokens.next() { if expr_tokens.next().is_none() { let preserve_empty_first_line = !first; if let Ok(literal) = lit_indoc(token, Macro::Concat, preserve_empty_first_line) { result.extend(iter::once(TokenTree::Literal(literal))); expr = TokenStream::new(); } } } result.extend(expr); if let Some(comma) = input.next() { result.extend(iter::once(comma)); } else { break; } first = false; } // concat! { #result } Ok(TokenStream::from_iter(vec![ TokenTree::Ident(Ident::new("concat", Span::call_site())), TokenTree::Punct(Punct::new('!', Spacing::Alone)), TokenTree::Group(Group::new(Delimiter::Brace, result)), ])) } fn lit_indoc(token: TokenTree, mode: Macro, preserve_empty_first_line: bool) -> Result { let span = token.span(); let mut single_token = Some(token); while let Some(TokenTree::Group(group)) = single_token { single_token = if group.delimiter() == Delimiter::None { let mut token_iter = group.stream().into_iter(); token_iter.next().xor(token_iter.next()) } else { None }; } let single_token = single_token.ok_or_else(|| Error::new(span, "argument must be a single string literal"))?; let repr = single_token.to_string(); let is_string = repr.starts_with('"') || repr.starts_with('r'); let is_byte_string = repr.starts_with("b\"") || repr.starts_with("br"); if !is_string && !is_byte_string { return Err(Error::new(span, "argument must be a single string literal")); } if is_byte_string { match mode { Macro::Indoc => {} Macro::Format | Macro::Print | Macro::Eprint | Macro::Write => { return Err(Error::new( span, "byte strings are not supported in formatting macros", )); } Macro::Concat => { return Err(Error::new( span, "byte strings are not supported in concat macro", )); } } } let begin = repr.find('"').unwrap() + 1; let end = repr.rfind('"').unwrap(); let repr = format!( "{open}{content}{close}", open = &repr[..begin], content = do_unindent(&repr[begin..end], preserve_empty_first_line), close = &repr[end..], ); let mut lit = Literal::from_str(&repr).unwrap(); lit.set_span(span); Ok(lit) } fn require_empty_or_trailing_comma(input: &mut Peekable) -> Result<()> { let first = match input.next() { Some(TokenTree::Punct(punct)) if punct.as_char() == ',' => match input.next() { Some(second) => second, None => return Ok(()), }, Some(first) => first, None => return Ok(()), }; let last = input.last(); let begin_span = first.span(); let end_span = last.as_ref().map_or(begin_span, TokenTree::span); let msg = format!( "unexpected {token} in macro invocation; indoc argument must be a single string literal", token = if last.is_some() { "tokens" } else { "token" } ); Err(Error::new2(begin_span, end_span, &msg)) } indoc/src/unindent.rs0000644000175000017500000000573315105742312014467 0ustar bdrungbdrunguse std::slice::Split; pub fn unindent(s: &str) -> String { let preserve_empty_first_line = false; do_unindent(s, preserve_empty_first_line) } // Compute the maximal number of spaces that can be removed from every line, and // remove them. pub fn unindent_bytes(s: &[u8]) -> Vec { let preserve_empty_first_line = false; do_unindent_bytes(s, preserve_empty_first_line) } pub(crate) fn do_unindent(s: &str, preserve_empty_first_line: bool) -> String { let bytes = s.as_bytes(); let unindented = do_unindent_bytes(bytes, preserve_empty_first_line); String::from_utf8(unindented).unwrap() } fn do_unindent_bytes(s: &[u8], preserve_empty_first_line: bool) -> Vec { // Document may start either on the same line as opening quote or // on the next line let ignore_first_line = !preserve_empty_first_line && (s.starts_with(b"\n") || s.starts_with(b"\r\n")); // Largest number of spaces that can be removed from every // non-whitespace-only line after the first let spaces = s .lines() .skip(1) .filter_map(count_spaces) .min() .unwrap_or(0); let mut result = Vec::with_capacity(s.len()); for (i, line) in s.lines().enumerate() { if i > 1 || (i == 1 && !ignore_first_line) { result.push(b'\n'); } if i == 0 { // Do not un-indent anything on same line as opening quote result.extend_from_slice(line); } else if line.len() > spaces { // Whitespace-only lines may have fewer than the number of spaces // being removed result.extend_from_slice(&line[spaces..]); } } result } pub trait Unindent { type Output; fn unindent(&self) -> Self::Output; } impl Unindent for str { type Output = String; fn unindent(&self) -> Self::Output { unindent(self) } } impl Unindent for String { type Output = String; fn unindent(&self) -> Self::Output { unindent(self) } } impl Unindent for [u8] { type Output = Vec; fn unindent(&self) -> Self::Output { unindent_bytes(self) } } impl Unindent for &T { type Output = T::Output; fn unindent(&self) -> Self::Output { (**self).unindent() } } // Number of leading spaces in the line, or None if the line is entirely spaces. fn count_spaces(line: &[u8]) -> Option { for (i, ch) in line.iter().enumerate() { if *ch != b' ' && *ch != b'\t' { return Some(i); } } None } // Based on core::str::StrExt. trait BytesExt { fn lines(&self) -> Split bool>; } impl BytesExt for [u8] { fn lines(&self) -> Split bool> { fn is_newline(b: &u8) -> bool { *b == b'\n' } let bytestring = if self.starts_with(b"\r\n") { &self[1..] } else { self }; bytestring.split(is_newline as fn(&u8) -> bool) } } indoc/src/error.rs0000644000175000017500000000245115105742312013766 0ustar bdrungbdrunguse proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; pub type Result = std::result::Result; pub struct Error { begin: Span, end: Span, msg: String, } impl Error { pub fn new(span: Span, msg: &str) -> Self { Self::new2(span, span, msg) } pub fn new2(begin: Span, end: Span, msg: &str) -> Self { Error { begin, end, msg: msg.to_owned(), } } pub fn to_compile_error(&self) -> TokenStream { // compile_error! { $msg } TokenStream::from_iter(vec![ TokenTree::Ident(Ident::new("compile_error", self.begin)), TokenTree::Punct({ let mut punct = Punct::new('!', Spacing::Alone); punct.set_span(self.begin); punct }), TokenTree::Group({ let mut group = Group::new(Delimiter::Brace, { TokenStream::from_iter(vec![TokenTree::Literal({ let mut string = Literal::string(&self.msg); string.set_span(self.end); string })]) }); group.set_span(self.end); group }), ]) } } libc/0000775000175000017500000000000015105742312011315 5ustar bdrungbdrunglibc/build.rs0000644000175000017500000002112315105742312012757 0ustar bdrungbdrunguse std::process::{Command, Output}; use std::{env, str}; // List of cfgs this build script is allowed to set. The list is needed to support check-cfg, as we // need to know all the possible cfgs that this script will set. If you need to set another cfg // make sure to add it to this list as well. const ALLOWED_CFGS: &'static [&'static str] = &[ "emscripten_old_stat_abi", "espidf_time32", "freebsd10", "freebsd11", "freebsd12", "freebsd13", "freebsd14", "freebsd15", // Corresponds to `_FILE_OFFSET_BITS=64` in glibc "gnu_file_offset_bits64", // FIXME(ctest): this config shouldn't be needed but ctest can't parse `const extern fn` "libc_const_extern_fn", "libc_deny_warnings", "libc_thread_local", "libc_ctest", // Corresponds to `__USE_TIME_BITS64` in UAPI "linux_time_bits64", ]; // Extra values to allow for check-cfg. const CHECK_CFG_EXTRA: &'static [(&'static str, &'static [&'static str])] = &[ ( "target_os", &[ "switch", "aix", "ohos", "hurd", "rtems", "visionos", "nuttx", "cygwin", ], ), ( "target_env", &["illumos", "wasi", "aix", "ohos", "nto71_iosock", "nto80"], ), ( "target_arch", &["loongarch64", "mips32r6", "mips64r6", "csky"], ), ]; fn main() { // Avoid unnecessary re-building. println!("cargo:rerun-if-changed=build.rs"); let (rustc_minor_ver, _is_nightly) = rustc_minor_nightly(); let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok(); let libc_ci = env::var("LIBC_CI").is_ok(); let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default(); let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); let target_ptr_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap_or_default(); let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); // The ABI of libc used by std is backward compatible with FreeBSD 12. // The ABI of libc from crates.io is backward compatible with FreeBSD 11. // // On CI, we detect the actual FreeBSD version and match its ABI exactly, // running tests to ensure that the ABI is correct. println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_FREEBSD_VERSION"); // Allow overriding the default version for testing let which_freebsd = if let Ok(version) = env::var("RUST_LIBC_UNSTABLE_FREEBSD_VERSION") { let vers = version.parse().unwrap(); println!("cargo:warning=setting FreeBSD version to {vers}"); vers } else if libc_ci { which_freebsd().unwrap_or(11) } else if rustc_dep_of_std { 12 } else { 11 }; match which_freebsd { x if x < 10 => panic!("FreeBSD older than 10 is not supported"), 10 => set_cfg("freebsd10"), 11 => set_cfg("freebsd11"), 12 => set_cfg("freebsd12"), 13 => set_cfg("freebsd13"), 14 => set_cfg("freebsd14"), _ => set_cfg("freebsd15"), } match emcc_version_code() { Some(v) if (v < 30142) => set_cfg("emscripten_old_stat_abi"), // Non-Emscripten or version >= 3.1.42. _ => (), } let linux_time_bits64 = env::var("RUST_LIBC_UNSTABLE_LINUX_TIME_BITS64").is_ok(); println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_LINUX_TIME_BITS64"); if linux_time_bits64 { set_cfg("linux_time_bits64"); } println!("cargo:rerun-if-env-changed=RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS"); match env::var("RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS") { Ok(val) if val == "64" => { if target_env == "gnu" && target_os == "linux" && target_ptr_width == "32" && target_arch != "riscv32" && target_arch != "x86_64" { set_cfg("gnu_file_offset_bits64"); } } Ok(val) if val != "32" => { panic!("RUST_LIBC_UNSTABLE_GNU_FILE_OFFSET_BITS may only be set to '32' or '64'") } _ => {} } // On CI: deny all warnings if libc_ci { set_cfg("libc_deny_warnings"); } // #[thread_local] is currently unstable if rustc_dep_of_std { set_cfg("libc_thread_local"); } // Set unconditionally when ctest is not being invoked. set_cfg("libc_const_extern_fn"); // Since Rust 1.80, configuration that isn't recognized by default needs to be provided to // avoid warnings. if rustc_minor_ver >= 80 { for cfg in ALLOWED_CFGS { if rustc_minor_ver >= 75 { println!("cargo:rustc-check-cfg=cfg({})", cfg); } else { println!("cargo:rustc-check-cfg=values({})", cfg); } } for &(name, values) in CHECK_CFG_EXTRA { let values = values.join("\",\""); if rustc_minor_ver >= 75 { println!("cargo:rustc-check-cfg=cfg({},values(\"{}\"))", name, values); } else { println!("cargo:rustc-check-cfg=values({},\"{}\")", name, values); } } } } /// Run `rustc --version` and capture the output, adjusting arguments as needed if `clippy-driver` /// is used instead. fn rustc_version_cmd(is_clippy_driver: bool) -> Output { let rustc = env::var_os("RUSTC").expect("Failed to get rustc version: missing RUSTC env"); let mut cmd = match env::var_os("RUSTC_WRAPPER") { Some(ref wrapper) if wrapper.is_empty() => Command::new(rustc), Some(wrapper) => { let mut cmd = Command::new(wrapper); cmd.arg(rustc); if is_clippy_driver { cmd.arg("--rustc"); } cmd } None => Command::new(rustc), }; cmd.arg("--version"); let output = cmd.output().expect("Failed to get rustc version"); if !output.status.success() { panic!( "failed to run rustc: {}", String::from_utf8_lossy(output.stderr.as_slice()) ); } output } /// Return the minor version of `rustc`, as well as a bool indicating whether or not the version /// is a nightly. fn rustc_minor_nightly() -> (u32, bool) { macro_rules! otry { ($e:expr) => { match $e { Some(e) => e, None => panic!("Failed to get rustc version"), } }; } let mut output = rustc_version_cmd(false); if otry!(str::from_utf8(&output.stdout).ok()).starts_with("clippy") { output = rustc_version_cmd(true); } let version = otry!(str::from_utf8(&output.stdout).ok()); let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { panic!("Failed to get rustc version"); } let minor = pieces.next(); // If `rustc` was built from a tarball, its version string // will have neither a git hash nor a commit date // (e.g. "rustc 1.39.0"). Treat this case as non-nightly, // since a nightly build should either come from CI // or a git checkout let nightly_raw = otry!(pieces.next()).split('-').nth(1); let nightly = nightly_raw .map(|raw| raw.starts_with("dev") || raw.starts_with("nightly")) .unwrap_or(false); let minor = otry!(otry!(minor).parse().ok()); (minor, nightly) } fn which_freebsd() -> Option { let output = Command::new("freebsd-version").output().ok()?; if !output.status.success() { return None; } let stdout = String::from_utf8(output.stdout).ok()?; match &stdout { s if s.starts_with("10") => Some(10), s if s.starts_with("11") => Some(11), s if s.starts_with("12") => Some(12), s if s.starts_with("13") => Some(13), s if s.starts_with("14") => Some(14), s if s.starts_with("15") => Some(15), _ => None, } } fn emcc_version_code() -> Option { let output = Command::new("emcc").arg("-dumpversion").output().ok()?; if !output.status.success() { return None; } let version = String::from_utf8(output.stdout).ok()?; // Some Emscripten versions come with `-git` attached, so split the // version string also on the `-` char. let mut pieces = version.trim().split(['.', '-']); let major = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0); let minor = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0); let patch = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0); Some(major * 10000 + minor * 100 + patch) } fn set_cfg(cfg: &str) { if !ALLOWED_CFGS.contains(&cfg) { panic!("trying to set cfg {}, but it is not in ALLOWED_CFGS", cfg); } println!("cargo:rustc-cfg={}", cfg); } libc/CONTRIBUTING.md0000644000175000017500000001274315105742312013553 0ustar bdrungbdrung# Contributing to `libc` Welcome! If you are reading this document, it means you are interested in contributing to the `libc` crate. ## v1.0 Roadmap `libc` has two active branches: `main` and `libc-0.2`. `main` is for active development of the upcoming v1.0 release, and should be the target of all pull requests. `libc-0.2` is for updates to the currently released version. If a pull request to `main` is a good candidate for inclusion in an `0.2.x` release, include `@rustbot label stable-nominated` in a comment to propose this. Good candidates will usually meet the following: 1. The included changes are non-breaking. 2. The change applies cleanly to both branches. 3. There is a usecase that justifies inclusion in a stable release (all additions should always have a usecase, hopefully). Once a `stable-nominated` PR targeting `main` has merged, it can be cherry picked to the `libc-0.2` branch. A maintainer will likely do these cherry picks in a batch. Alternatively, you can start this process yourself by creating a new branch based on `libc-0.2` and running `git cherry-pick -xe commit-sha-on-main` (`git cherry-pick -xe start-sha^..end-sha` if a range of commits is needed). `git` will automatically add the "cherry picked from commit" note, but try to add a backport note so the original PR gets crosslinked: ``` # ... original commit message ... (backport ) # add manually (cherry picked from commit 104b6a4ae31c726814c36318dc718470cc96e167) # added by git ``` Once the cherry-pick is complete, open a PR targeting `libc-0.2`. See the [tracking issue](https://github.com/rust-lang/libc/issues/3248) for details. ## Adding an API Want to use an API which currently isn't bound in `libc`? It's quite easy to add one! The internal structure of this crate is designed to minimize the number of `#[cfg]` attributes in order to easily be able to add new items which apply to all platforms in the future. As a result, the crate is organized hierarchically based on platform. Each module has a number of `#[cfg]`'d children, but only one is ever actually compiled. Each module then reexports all the contents of its children. This means that for each platform that libc supports, the path from a leaf module to the root will contain all bindings for the platform in question. Consequently, this indicates where an API should be added! Adding an API at a particular level in the hierarchy means that it is supported on all the child platforms of that level. For example, when adding a Unix API it should be added to `src/unix/mod.rs`, but when adding a Linux-only API it should be added to `src/unix/linux_like/linux/mod.rs`. If you're not 100% sure at what level of the hierarchy an API should be added at, fear not! This crate has CI support which tests any binding against all platforms supported, so you'll see failures if an API is added at the wrong level or has different signatures across platforms. New symbol(s) (i.e. functions, constants etc.) should also be added to the symbols list(s) found in the `libc-test/semver` directory. These lists keep track of what symbols are public in the libc crate and ensures they remain available between changes to the crate. If the new symbol(s) are available on all supported Unixes it should be added to `unix.txt` list1, otherwise they should be added to the OS specific list(s). With that in mind, the steps for adding a new API are: 1. Determine where in the module hierarchy your API should be added. 2. Add the API, including adding new symbol(s) to the semver lists. 3. Send a PR to this repo. 4. Wait for CI to pass, fixing errors. 5. Wait for a merge! 1: Note that this list has nothing to do with any Unix or Posix standard, it's just a list shared among all OSs that declare `#[cfg(unix)]`. ## Test before you commit We have two automated tests running on [GitHub Actions](https://github.com/rust-lang/libc/actions): 1. [`libc-test`](https://github.com/gnzlbg/ctest) - `cd libc-test && cargo test` - Use the `skip_*()` functions in `build.rs` if you really need a workaround. 2. Style checker - [`./ci/style.sh`](https://github.com/rust-lang/libc/blob/main/ci/style.sh) ## Breaking change policy Sometimes an upstream adds a breaking change to their API e.g. removing outdated items, changing the type signature, etc. And we probably should follow that change to build the `libc` crate successfully. It's annoying to do the equivalent of semver-major versioning for each such change. Instead, we mark the item as deprecated and do the actual change after a certain period. The steps are: 1. Add `#[deprecated(since = "", note="")]` attribute to the item. - The `since` field should have a next version of `libc` (e.g., if the current version is `0.2.1`, it should be `0.2.2`). - The `note` field should have a reason to deprecate and a tracking issue to call for comments (e.g., "We consider removing this as the upstream removed it. If you're using it, please comment on #XXX"). 2. If we don't see any concerns for a while, do the change actually. ## Supported target policy When Rust removes a support for a target, the libc crate also may remove the support at any time. ## Releasing your change to crates.io This repository uses [release-plz] to handle releases. Once your pull request has been merged, a maintainer just needs to verify the generated changelog, then merge the bot's release PR. This will automatically publish to crates.io! [release-plz]: https://github.com/MarcoIeni/release-plz libc/tests/0000775000175000017500000000000015105742312012457 5ustar bdrungbdrunglibc/tests/const_fn.rs0000644000175000017500000000022115105742312014627 0ustar bdrungbdrung#[cfg(target_os = "linux")] const _FOO: libc::c_uint = unsafe { libc::CMSG_SPACE(1) }; //^ if CMSG_SPACE is not const, this will fail to compile libc/LICENSE-MIT0000644000175000017500000000206415105742312012751 0ustar bdrungbdrungCopyright (c) 2014-2020 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libc/Cargo.lock0000644000175000017500000000062615105742312013224 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "libc" version = "0.2.172" dependencies = [ "rustc-std-workspace-core", ] [[package]] name = "rustc-std-workspace-core" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9c45b374136f52f2d6311062c7146bff20fec063c3f5d46a410bd937746955" libc/Cargo.toml0000644000175000017500000001157215105742312013251 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.63" name = "libc" version = "0.2.172" authors = ["The Rust Project Developers"] build = "build.rs" exclude = [ "/ci/*", "/.github/*", "/.cirrus.yml", "/triagebot.toml", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = """ Raw FFI bindings to platform libraries like libc. """ homepage = "https://github.com/rust-lang/libc" documentation = "https://docs.rs/libc/" readme = "README.md" keywords = [ "libc", "ffi", "bindings", "operating", "system", ] categories = [ "external-ffi-bindings", "no-std", "os", ] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/libc" [package.metadata.docs.rs] cargo-args = ["-Zbuild-std=core"] default-target = "x86_64-unknown-linux-gnu" features = ["extra_traits"] targets = [ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-linux-android", "aarch64-pc-windows-msvc", "aarch64-unknown-freebsd", "aarch64-unknown-fuchsia", "aarch64-unknown-hermit", "aarch64-unknown-linux-gnu", "aarch64-unknown-linux-musl", "aarch64-unknown-netbsd", "aarch64-unknown-openbsd", "aarch64-wrs-vxworks", "arm-linux-androideabi", "arm-unknown-linux-gnueabi", "arm-unknown-linux-gnueabihf", "arm-unknown-linux-musleabi", "arm-unknown-linux-musleabihf", "armebv7r-none-eabi", "armebv7r-none-eabihf", "armv5te-unknown-linux-gnueabi", "armv5te-unknown-linux-musleabi", "armv7-linux-androideabi", "armv7-unknown-linux-gnueabihf", "armv7-unknown-linux-musleabihf", "armv7-wrs-vxworks-eabihf", "armv7r-none-eabi", "armv7r-none-eabihf", "i586-unknown-linux-gnu", "i586-unknown-linux-musl", "i686-linux-android", "i686-pc-windows-gnu", "i686-pc-windows-msvc", "i686-pc-windows-msvc", "i686-unknown-freebsd", "i686-unknown-haiku", "i686-unknown-linux-gnu", "i686-unknown-linux-musl", "i686-unknown-netbsd", "i686-unknown-openbsd", "i686-wrs-vxworks", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", "mips64-unknown-linux-gnuabi64", "mips64-unknown-linux-muslabi64", "mips64el-unknown-linux-gnuabi64", "mips64el-unknown-linux-muslabi64", "mipsel-sony-psp", "mipsel-unknown-linux-gnu", "mipsel-unknown-linux-musl", "nvptx64-nvidia-cuda", "powerpc-unknown-linux-gnu", "powerpc-unknown-linux-gnuspe", "powerpc-unknown-netbsd", "powerpc-wrs-vxworks", "powerpc-wrs-vxworks-spe", "powerpc64-unknown-freebsd", "powerpc64-unknown-linux-gnu", "powerpc64-wrs-vxworks", "powerpc64le-unknown-linux-gnu", "riscv32gc-unknown-linux-gnu", "riscv32i-unknown-none-elf", "riscv32imac-unknown-none-elf", "riscv32imc-unknown-none-elf", "riscv32-wrs-vxworks", "riscv64gc-unknown-freebsd", "riscv64gc-unknown-hermit", "riscv64gc-unknown-linux-gnu", "riscv64gc-unknown-linux-musl", "riscv64gc-unknown-none-elf", "riscv64imac-unknown-none-elf", "riscv64-wrs-vxworks", "s390x-unknown-linux-gnu", "s390x-unknown-linux-musl", "sparc-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparc64-unknown-netbsd", "sparcv9-sun-solaris", "thumbv6m-none-eabi", "thumbv7em-none-eabi", "thumbv7em-none-eabihf", "thumbv7m-none-eabi", "thumbv7neon-linux-androideabi", "thumbv7neon-unknown-linux-gnueabihf", "wasm32-unknown-emscripten", "wasm32-unknown-unknown", "x86_64-apple-darwin", "x86_64-apple-ios", "x86_64-fortanix-unknown-sgx", "x86_64-linux-android", "x86_64-pc-solaris", "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", "x86_64-unknown-dragonfly", "x86_64-unknown-freebsd", "x86_64-unknown-fuchsia", "x86_64-unknown-haiku", "x86_64-unknown-hermit", "x86_64-unknown-illumos", "x86_64-unknown-l4re-uclibc", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", "x86_64-unknown-openbsd", "x86_64-unknown-redox", "x86_64-wrs-vxworks", ] [features] align = [] const-extern-fn = [] default = ["std"] extra_traits = [] rustc-dep-of-std = [ "align", "rustc-std-workspace-core", ] std = [] use_std = ["std"] [lib] name = "libc" path = "src/lib.rs" [[test]] name = "const_fn" path = "tests/const_fn.rs" [dependencies.rustc-std-workspace-core] version = "1.0.0" optional = true libc/.cargo-checksum.json0000664000175000017500000000013115105742312015154 0ustar bdrungbdrung{"files":{},"package":"d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"}libc/LICENSE-APACHE0000644000175000017500000002277315105742312013252 0ustar bdrungbdrung Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS libc/rustfmt.toml0000644000175000017500000000016115105742312013712 0ustar bdrungbdrungedition = "2021" error_on_line_overflow = true group_imports = "StdExternalCrate" imports_granularity = "Module" libc/README.md0000644000175000017500000001044015105742312012571 0ustar bdrungbdrung# libc - Raw FFI bindings to platforms' system libraries [![GHA Status]][GitHub Actions] [![Cirrus CI Status]][Cirrus CI] [![Latest Version]][crates.io] [![Documentation]][docs.rs] ![License] `libc` provides all of the definitions necessary to easily interoperate with C code (or "C-like" code) on each of the platforms that Rust supports. This includes type definitions (e.g. `c_int`), constants (e.g. `EINVAL`) as well as function headers (e.g. `malloc`). This crate exports all underlying platform types, functions, and constants under the crate root, so all items are accessible as `libc::foo`. The types and values of all the exported APIs match the platform that libc is compiled for. Windows API bindings are not included in this crate. If you are looking for WinAPI bindings, consider using crates like [windows-sys]. More detailed information about the design of this library can be found in its [associated RFC][rfc]. [rfc]: https://github.com/rust-lang/rfcs/blob/HEAD/text/1291-promote-libc.md [windows-sys]: https://docs.rs/windows-sys ## v1.0 Roadmap Currently, `libc` has two active branches: `main` for the upcoming v1.0 release, and `libc-0.2` for the currently published version. By default all pull requests should target `main`; once reviewed, they can be cherry picked to the `libc-0.2` branch if needed. We will stop making new v0.2 releases once v1.0 is released. See the section in [CONTRIBUTING.md](CONTRIBUTING.md#v10-roadmap) for more details. ## Usage Add the following to your `Cargo.toml`: ```toml [dependencies] libc = "0.2" ``` ## Features * `std`: by default `libc` links to the standard library. Disable this feature to remove this dependency and be able to use `libc` in `#![no_std]` crates. * `extra_traits`: all `struct`s implemented in `libc` are `Copy` and `Clone`. This feature derives `Debug`, `Eq`, `Hash`, and `PartialEq`. The following features are deprecated: * `use_std`: this is equivalent to `std` * `const-extern-fn`: this is now enabled by default * `align`: this is now enabled by default ## Rust version support The minimum supported Rust toolchain version is currently **Rust 1.63**. Increases to the MSRV are allowed to change without a major (i.e. semver- breaking) release in order to avoid a ripple effect in the ecosystem. A policy for when this may change is a work in progress. `libc` may continue to compile with Rust versions older than the current MSRV but this is not guaranteed. ## Platform support You can see the platform(target)-specific docs on [docs.rs], select a platform you want to see. See [`ci/verify-build.sh`](https://github.com/rust-lang/libc/blob/HEAD/ci/verify-build.sh) for the platforms on which `libc` is guaranteed to build for each Rust toolchain. The test-matrix at [GitHub Actions] and [Cirrus CI] show the platforms in which `libc` tests are run.

## License This project is licensed under either of * [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) ([LICENSE-APACHE](https://github.com/rust-lang/libc/blob/HEAD/LICENSE-APACHE)) * [MIT License](https://opensource.org/licenses/MIT) ([LICENSE-MIT](https://github.com/rust-lang/libc/blob/HEAD/LICENSE-MIT)) at your option. ## Contributing We welcome all people who want to contribute. Please see the [contributing instructions] for more information. [contributing instructions]: https://github.com/rust-lang/libc/blob/HEAD/CONTRIBUTING.md Contributions in any form (issues, pull requests, etc.) to this project must adhere to Rust's [Code of Conduct]. [Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in `libc` by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. [GitHub Actions]: https://github.com/rust-lang/libc/actions [GHA Status]: https://github.com/rust-lang/libc/workflows/CI/badge.svg [Cirrus CI]: https://cirrus-ci.com/github/rust-lang/libc [Cirrus CI Status]: https://api.cirrus-ci.com/github/rust-lang/libc.svg [crates.io]: https://crates.io/crates/libc [Latest Version]: https://img.shields.io/crates/v/libc.svg [Documentation]: https://docs.rs/libc/badge.svg [docs.rs]: https://docs.rs/libc [License]: https://img.shields.io/crates/l/libc.svg libc/CHANGELOG.md0000644000175000017500000010635415105742312013135 0ustar bdrungbdrung# Changelog ## [0.2.172](https://github.com/rust-lang/libc/compare/0.2.171...0.2.172) - 2025-04-14 ### Added - Android: Add `getauxval` for 32-bit targets ([#4338](https://github.com/rust-lang/libc/pull/4338)) - Android: Add `if_tun.h` ioctls ([#4379](https://github.com/rust-lang/libc/pull/4379)) - Android: Define `SO_BINDTOIFINDEX` ([#4391](https://github.com/rust-lang/libc/pull/4391)) - Cygwin: Add `posix_spawn_file_actions_add[f]chdir[_np]` ([#4387](https://github.com/rust-lang/libc/pull/4387)) - Cygwin: Add new socket options ([#4350](https://github.com/rust-lang/libc/pull/4350)) - Cygwin: Add statfs & fcntl ([#4321](https://github.com/rust-lang/libc/pull/4321)) - FreeBSD: Add `filedesc` and `fdescenttbl` ([#4327](https://github.com/rust-lang/libc/pull/4327)) - Glibc: Add unstable support for _FILE_OFFSET_BITS=64 ([#4345](https://github.com/rust-lang/libc/pull/4345)) - Hermit: Add `AF_UNSPEC` ([#4344](https://github.com/rust-lang/libc/pull/4344)) - Hermit: Add `AF_VSOCK` ([#4344](https://github.com/rust-lang/libc/pull/4344)) - Illumos, NetBSD: Add `timerfd` APIs ([#4333](https://github.com/rust-lang/libc/pull/4333)) - Linux: Add `_IO`, `_IOW`, `_IOR`, `_IOWR` to the exported API ([#4325](https://github.com/rust-lang/libc/pull/4325)) - Linux: Add `tcp_info` to uClibc bindings ([#4347](https://github.com/rust-lang/libc/pull/4347)) - Linux: Add further BPF program flags ([#4356](https://github.com/rust-lang/libc/pull/4356)) - Linux: Add missing INPUT_PROP_XXX flags from `input-event-codes.h` ([#4326](https://github.com/rust-lang/libc/pull/4326)) - Linux: Add missing TLS bindings ([#4296](https://github.com/rust-lang/libc/pull/4296)) - Linux: Add more constants from `seccomp.h` ([#4330](https://github.com/rust-lang/libc/pull/4330)) - Linux: Add more glibc `ptrace_sud_config` and related `PTRACE_*ET_SYSCALL_USER_DISPATCH_CONFIG`. ([#4386](https://github.com/rust-lang/libc/pull/4386)) - Linux: Add new netlink flags ([#4288](https://github.com/rust-lang/libc/pull/4288)) - Linux: Define ioctl codes on more architectures ([#4382](https://github.com/rust-lang/libc/pull/4382)) - Linux: Add missing `pthread_attr_setstack` ([#4349](https://github.com/rust-lang/libc/pull/4349)) - Musl: Add missing `utmpx` API ([#4332](https://github.com/rust-lang/libc/pull/4332)) - Musl: Enable `getrandom` on all platforms ([#4346](https://github.com/rust-lang/libc/pull/4346)) - NuttX: Add more signal constants ([#4353](https://github.com/rust-lang/libc/pull/4353)) - QNX: Add QNX 7.1-iosock and 8.0 to list of additional cfgs ([#4169](https://github.com/rust-lang/libc/pull/4169)) - QNX: Add support for alternative Neutrino network stack `io-sock` ([#4169](https://github.com/rust-lang/libc/pull/4169)) - Redox: Add more `sys/socket.h` and `sys/uio.h` definitions ([#4388](https://github.com/rust-lang/libc/pull/4388)) - Solaris: Temporarily define `O_DIRECT` and `SIGINFO` ([#4348](https://github.com/rust-lang/libc/pull/4348)) - Solarish: Add `secure_getenv` ([#4342](https://github.com/rust-lang/libc/pull/4342)) - VxWorks: Add missing `d_type` member to `dirent` ([#4352](https://github.com/rust-lang/libc/pull/4352)) - VxWorks: Add missing signal-related constsants ([#4352](https://github.com/rust-lang/libc/pull/4352)) - VxWorks: Add more error codes ([#4337](https://github.com/rust-lang/libc/pull/4337)) ### Deprecated - FreeBSD: Deprecate `TCP_PCAP_OUT` and `TCP_PCAP_IN` ([#4381](https://github.com/rust-lang/libc/pull/4381)) ### Fixed - Cygwin: Fix member types of `statfs` ([#4324](https://github.com/rust-lang/libc/pull/4324)) - Cygwin: Fix tests ([#4357](https://github.com/rust-lang/libc/pull/4357)) - Hermit: Make `AF_INET = 3` ([#4344](https://github.com/rust-lang/libc/pull/4344)) - Musl: Fix the syscall table on RISC-V-32 ([#4335](https://github.com/rust-lang/libc/pull/4335)) - Musl: Fix the value of `SA_ONSTACK` on RISC-V-32 ([#4335](https://github.com/rust-lang/libc/pull/4335)) - VxWorks: Fix a typo in the `waitpid` parameter name ([#4334](https://github.com/rust-lang/libc/pull/4334)) ### Removed - Musl: Remove `O_FSYNC` on RISC-V-32 (use `O_SYNC` instead) ([#4335](https://github.com/rust-lang/libc/pull/4335)) - Musl: Remove `RTLD_DEEPBIND` on RISC-V-32 ([#4335](https://github.com/rust-lang/libc/pull/4335)) ### Other - CI: Add matrix env variables to the environment ([#4345](https://github.com/rust-lang/libc/pull/4345)) - CI: Always deny warnings ([#4363](https://github.com/rust-lang/libc/pull/4363)) - CI: Always upload successfully created artifacts ([#4345](https://github.com/rust-lang/libc/pull/4345)) - CI: Install musl from source for loongarch64 ([#4320](https://github.com/rust-lang/libc/pull/4320)) - CI: Revert "Also skip `MFD_EXEC` and `MFD_NOEXEC_SEAL` on sparc64" ([#]()) - CI: Use `$PWD` instead of `$(pwd)` in run-docker ([#4345](https://github.com/rust-lang/libc/pull/4345)) - Solarish: Restrict `openpty` and `forkpty` polyfills to Illumos, replace Solaris implementation with bindings ([#4329](https://github.com/rust-lang/libc/pull/4329)) - Testing: Ensure the makedev test does not emit unused errors ([#4363](https://github.com/rust-lang/libc/pull/4363)) ## [0.2.171](https://github.com/rust-lang/libc/compare/0.2.170...0.2.171) - 2025-03-11 ### Added - Android: Add `if_nameindex`/`if_freenameindex` support ([#4247](https://github.com/rust-lang/libc/pull/4247)) - Apple: Add missing proc types and constants ([#4310](https://github.com/rust-lang/libc/pull/4310)) - BSD: Add `devname` ([#4285](https://github.com/rust-lang/libc/pull/4285)) - Cygwin: Add PTY and group API ([#4309](https://github.com/rust-lang/libc/pull/4309)) - Cygwin: Add support ([#4279](https://github.com/rust-lang/libc/pull/4279)) - FreeBSD: Make `spawn.h` interfaces available on all FreeBSD-like systems ([#4294](https://github.com/rust-lang/libc/pull/4294)) - Linux: Add `AF_XDP` structs for all Linux environments ([#4163](https://github.com/rust-lang/libc/pull/4163)) - Linux: Add SysV semaphore constants ([#4286](https://github.com/rust-lang/libc/pull/4286)) - Linux: Add `F_SEAL_EXEC` ([#4316](https://github.com/rust-lang/libc/pull/4316)) - Linux: Add `SO_PREFER_BUSY_POLL` and `SO_BUSY_POLL_BUDGET` ([#3917](https://github.com/rust-lang/libc/pull/3917)) - Linux: Add `devmem` structs ([#4299](https://github.com/rust-lang/libc/pull/4299)) - Linux: Add socket constants up to `SO_DEVMEM_DONTNEED` ([#4299](https://github.com/rust-lang/libc/pull/4299)) - NetBSD, OpenBSD, DragonflyBSD: Add `closefrom` ([#4290](https://github.com/rust-lang/libc/pull/4290)) - NuttX: Add `pw_passwd` field to `passwd` ([#4222](https://github.com/rust-lang/libc/pull/4222)) - Solarish: define `IP_BOUND_IF` and `IPV6_BOUND_IF` ([#4287](https://github.com/rust-lang/libc/pull/4287)) - Wali: Add bindings for `wasm32-wali-linux-musl` target ([#4244](https://github.com/rust-lang/libc/pull/4244)) ### Changed - AIX: Use `sa_sigaction` instead of a union ([#4250](https://github.com/rust-lang/libc/pull/4250)) - Make `msqid_ds.__msg_cbytes` public ([#4301](https://github.com/rust-lang/libc/pull/4301)) - Unix: Make all `major`, `minor`, `makedev` into `const fn` ([#4208](https://github.com/rust-lang/libc/pull/4208)) ### Deprecated - Linux: Deprecate obsolete packet filter interfaces ([#4267](https://github.com/rust-lang/libc/pull/4267)) ### Fixed - Cygwin: Fix strerror_r ([#4308](https://github.com/rust-lang/libc/pull/4308)) - Cygwin: Fix usage of f! ([#4308](https://github.com/rust-lang/libc/pull/4308)) - Hermit: Make `stat::st_size` signed ([#4298](https://github.com/rust-lang/libc/pull/4298)) - Linux: Correct values for `SI_TIMER`, `SI_MESGQ`, `SI_ASYNCIO` ([#4292](https://github.com/rust-lang/libc/pull/4292)) - NuttX: Update `tm_zone` and `d_name` fields to use `c_char` type ([#4222](https://github.com/rust-lang/libc/pull/4222)) - Xous: Include the prelude to define `c_int` ([#4304](https://github.com/rust-lang/libc/pull/4304)) ### Other - Add labels to FIXMEs ([#4231](https://github.com/rust-lang/libc/pull/4231), [#4232](https://github.com/rust-lang/libc/pull/4232), [#4234](https://github.com/rust-lang/libc/pull/4234), [#4235](https://github.com/rust-lang/libc/pull/4235), [#4236](https://github.com/rust-lang/libc/pull/4236)) - CI: Fix "cannot find libc" error on Sparc64 ([#4317](https://github.com/rust-lang/libc/pull/4317)) - CI: Fix "cannot find libc" error on s390x ([#4317](https://github.com/rust-lang/libc/pull/4317)) - CI: Pass `--no-self-update` to `rustup update` ([#4306](https://github.com/rust-lang/libc/pull/4306)) - CI: Remove tests for the `i586-pc-windows-msvc` target ([#4311](https://github.com/rust-lang/libc/pull/4311)) - CI: Remove the `check_cfg` job ([#4322](https://github.com/rust-lang/libc/pull/4312)) - Change the range syntax that is giving `ctest` problems ([#4311](https://github.com/rust-lang/libc/pull/4311)) - Linux: Split out the stat struct for gnu/b32/mips ([#4276](https://github.com/rust-lang/libc/pull/4276)) ### Removed - NuttX: Remove `pthread_set_name_np` ([#4251](https://github.com/rust-lang/libc/pull/4251)) ## [0.2.170](https://github.com/rust-lang/libc/compare/0.2.169...0.2.170) - 2025-02-23 ### Added - Android: Declare `setdomainname` and `getdomainname` - FreeBSD: Add `evdev` structures - FreeBSD: Add the new `st_filerev` field to `stat32` ([#4254](https://github.com/rust-lang/libc/pull/4254)) - Linux: Add `SI_*`` and `TRAP_*`` signal codes - Linux: Add experimental configuration to enable 64-bit time in kernel APIs, set by `RUST_LIBC_UNSTABLE_LINUX_TIME_BITS64`. - Linux: Add recent socket timestamping flags - Linux: Added new CANFD_FDF flag for the flags field of canfd_frame - Musl: add CLONE_NEWTIME - Solarish: add the posix_spawn family of functions ### Deprecated - Linux: deprecate kernel modules syscalls ### Changed - Emscripten: Assume version is at least 3.1.42 ### Fixed - BSD: Correct the definition of `WEXITSTATUS` - Hurd: Fix CMSG_DATA on 64bit systems ([#4240](https://github.com/rust-lang/libc/pull/424)) - NetBSD: fix `getmntinfo` ([#4265](https://github.com/rust-lang/libc/pull/4265) - VxWorks: Fix the size of `time_t` ### Other - Add labels to FIXMEs , , - CI: Bump FreeBSD CI to 13.4 and 14.2 - Copy definitions from core::ffi and centralize them - Define c_char at top-level and remove per-target c_char definitions - Port style.rs to syn and add tests for the style checker ## [0.2.169](https://github.com/rust-lang/libc/compare/0.2.168...0.2.169) - 2024-12-18 ### Added - FreeBSD: add more socket TCP stack constants - Fuchsia: add a `sockaddr_vm` definition ### Fixed **Breaking**: [rust-lang/rust#132975](https://github.com/rust-lang/rust/pull/132975) corrected the signedness of `core::ffi::c_char` on various Tier 2 and Tier 3 platforms (mostly Arm and RISC-V) to match Clang. This release contains the corresponding changes to `libc`, including the following specific pull requests: - ESP-IDF: Replace arch-conditional `c_char` with a reexport - Fix `c_char` on various targets - Mirror `c_char` configuration from `rust-lang/rust` ### Cleanup - Do not re-export `c_void` in target-specific code ## [0.2.168](https://github.com/rust-lang/libc/compare/0.2.167...0.2.168) - 2024-12-09 ### Added - Linux: Add new process flags ([#4174](https://github.com/rust-lang/libc/pull/4174)) - Linux: Make `IFA_*` constants available on all Linux targets - Linux: add `MAP_DROPPABLE` - Solaris, Illumos: add `SIGRTMIN` and `SIGRTMAX` - Unix, Linux: adding POSIX `memccpy` and `mempcpy` GNU extension - CI: Upload artifacts created by libc-test - CI: Use workflow commands to group output by target - CI: add caching ## [0.2.167](https://github.com/rust-lang/libc/compare/0.2.166...0.2.167) - 2024-11-28 ### Added - Solarish: add `st_fstype` to `stat` - Trusty: Add `intptr_t` and `uintptr_t` ([#4161](https://github.com/rust-lang/libc/pull/4161)) ### Fixed - Fix the build with `rustc-dep-of-std` - Wasi: Add back unsafe block for `clockid_t` static variables ([#4157](https://github.com/rust-lang/libc/pull/4157)) ### Cleanup - Create an internal prelude - Fix `unused_qualifications` ### Other - CI: Check various FreeBSD versions ([#4159](https://github.com/rust-lang/libc/pull/4159)) - CI: add a timeout for all jobs - CI: verify MSRV for `wasm32-wasi` - Migrate to the 2021 edition ### Removed - Remove one unused import after the edition 2021 bump ## [0.2.166](https://github.com/rust-lang/libc/compare/0.2.165...0.2.166) - 2024-11-26 ### Fixed This release resolves two cases of unintentional breakage from the previous release: - Revert removal of array size hacks [#4150](https://github.com/rust-lang/libc/pull/4150) - Ensure `const extern` functions are always enabled [#4151](https://github.com/rust-lang/libc/pull/4151) ## [0.2.165](https://github.com/rust-lang/libc/compare/0.2.164...0.2.165) - 2024-11-25 ### Added - Android: add `mkostemp`, `mkostemps` - Android: add a few API 30 calls - Android: add missing syscall constants - Apple: add `in6_ifreq` - Apple: add missing `sysctl` net types (before release: remove `if_family_id` ([#4137](https://github.com/rust-lang/libc/pulls/4137))) - Freebsd: add `kcmp` call support - Hurd: add `MAP_32BIT` and `MAP_EXCL` - Hurd: add `domainname` field to `utsname` ([#4089](https://github.com/rust-lang/libc/pulls/4089)) - Linux GNU: add `f_flags` to struct `statfs` for arm, mips, powerpc and x86 - Linux GNU: add `malloc_stats` - Linux: add ELF relocation-related structs - Linux: add `ptp_*` structs - Linux: add `ptp_clock_caps` - Linux: add `ptp_pin_function` and most `PTP_` constants - Linux: add missing AF_XDP structs & constants - Linux: add missing netfilter consts ([#3734](https://github.com/rust-lang/libc/pulls/3734)) - Linux: add struct and constants for the `mount_setattr` syscall - Linux: add wireless API - Linux: expose the `len8_dlc` field of `can_frame` - Musl: add `utmpx` API - Musl: add missing syscall constants - NetBSD: add `mcontext`-related data for RISCV64 - Redox: add new `netinet` constants ) - Solarish: add `_POSIX_VDISABLE` ([#4103](https://github.com/rust-lang/libc/pulls/4103)) - Tests: Add a test that the `const extern fn` macro works - Tests: Add test of primitive types against `std` - Unix: Add `htonl`, `htons`, `ntohl`, `ntohs` - Unix: add `aligned_alloc` - Windows: add `aligned_realloc` ### Fixed - **breaking** Hurd: fix `MAP_HASSEMAPHORE` name ([#4127](https://github.com/rust-lang/libc/pulls/4127)) - **breaking** ulibc Mips: fix `SA_*` mismatched types ([#3211](https://github.com/rust-lang/libc/pulls/3211)) - Aix: fix an enum FFI safety warning - Haiku: fix some typos ([#3664](https://github.com/rust-lang/libc/pulls/3664)) - Tests: fix `Elf{32,64}_Relr`-related tests - Tests: fix libc-tests for `loongarch64-linux-musl` - Tests: fix some clippy warnings - Tests: fix tests on `riscv64gc-unknown-freebsd` ### Deprecated - Apple: deprecate `iconv_open` - Apple: deprecate `mach_task_self` - Apple: update `mach` deprecation notices for things that were removed in `main` ### Cleanup - Adjust the `f!` macro to be more flexible - Aix: remove duplicate constants - CI: make scripts more uniform - Drop the `libc_align` conditional - Drop the `libc_cfg_target_vendor` conditional - Drop the `libc_const_size_of` conditional - Drop the `libc_core_cvoid` conditional - Drop the `libc_int128` conditional - Drop the `libc_non_exhaustive` conditional - Drop the `libc_packedN` conditional - Drop the `libc_priv_mod_use` conditional - Drop the `libc_union` conditional - Drop the `long_array` conditional - Drop the `ptr_addr_of` conditional - Drop warnings about deprecated cargo features - Eliminate uses of `struct_formatter` - Fix a few other array size hacks - Glibc: remove redundant definitions ([#3261](https://github.com/rust-lang/libc/pulls/3261)) - Musl: remove redundant definitions ([#3261](https://github.com/rust-lang/libc/pulls/3261)) - Musl: unify definitions of `siginfo_t` ([#3261](https://github.com/rust-lang/libc/pulls/3261)) - Musl: unify definitions of statfs and statfs64 ([#3261](https://github.com/rust-lang/libc/pulls/3261)) - Musl: unify definitions of statvfs and statvfs64 ([#3261](https://github.com/rust-lang/libc/pulls/3261)) - Musl: unify statx definitions ([#3978](https://github.com/rust-lang/libc/pulls/3978)) - Remove array size hacks for Rust < 1.47 - Remove repetitive words - Use #[derive] for Copy/Clone in s! and friends - Use some tricks to format macro bodies ### Other - Apply formatting to macro bodies - Bump libc-test to Rust 2021 Edition - CI: Add a check that semver files don't contain duplicate entries - CI: Add `fanotify_event_info_fid` to FAM-exempt types - CI: Allow rustfmt to organize imports ([#4136](https://github.com/rust-lang/libc/pulls/4136)) - CI: Always run rustfmt - CI: Change 32-bit Docker images to use EOL repos - CI: Change 64-bit Docker images to ubuntu:24.10 - CI: Disable the check for >1 s! invocation - CI: Ensure build channels get run even if FILTER is unset - CI: Ensure there is a fallback for no_std - CI: Fix cases where unset variables cause errors - CI: Naming adjustments and cleanup - CI: Only invoke rustup if running in CI - CI: Remove the logic to handle old rust versions - CI: Set -u (error on unset) in all script files - CI: add support for `loongarch64-unknown-linux-musl` - CI: make `aarch64-apple-darwin` not a nightly-only target - CI: run shellcheck on all scripts - CI: update musl headers to Linux 6.6 - CI: use qemu-sparc64 to run sparc64 tests - Drop the `libc_const_extern_fn` conditional - Drop the `libc_underscore_const_names` conditional - Explicitly set the edition to 2015 - Introduce a `git-blame-ignore-revs` file - Tests: Ignore fields as required on Ubuntu 24.10 - Tests: skip `ATF_*` constants for OpenBSD - Triagebot: Add an autolabel for CI ## [0.2.164](https://github.com/rust-lang/libc/compare/0.2.163...0.2.164) - 2024-11-16 ### MSRV This release increases the MSRV of `libc` to 1.63. ### Other - CI: remove tests with rust < 1.63 - MSRV: document the MSRV of the stable channel to be 1.63 - MacOS: move ifconf to s_no_extra_traits ## [0.2.163](https://github.com/rust-lang/libc/compare/0.2.162...0.2.163) - 2024-11-16 ### Added - Aix: add more `dlopen` flags - Android: add group calls - FreeBSD: add `TCP_FUNCTION_BLK` and `TCP_FUNCTION_ALIAS` - Linux: add `confstr` - Solarish: add `aio` - Solarish: add `arc4random*` ### Changed - Emscripten: upgrade emsdk to 3.1.68 - Hurd: use more standard types - Hurd: use the standard `ssize_t = isize` - Solaris: fix `confstr` and `ucontext_t` ### Other - CI: add Solaris - CI: add `i686-unknown-freebsd` - CI: ensure that calls to `sort` do not depend on locale - Specify `rust-version` in `Cargo.toml` ## [0.2.162](https://github.com/rust-lang/libc/compare/0.2.161...0.2.162) - 2024-11-07 ### Added - Android: fix the alignment of `uc_mcontext` on arm64 - Apple: add `host_cpu_load_info` - ESP-IDF: add a time flag - FreeBSD: add the `CLOSE_RANGE_CLOEXEC` flag - FreeBSD: fix test errors regarding `__gregset_t` - FreeBSD: fix tests on x86 FreeBSD 15 - FreeBSD: make `ucontext_t` and `mcontext_t` available on all architectures - Haiku: add `getentropy` - Illumos: add `syncfs` - Illumos: add some recently-added constants - Linux: add `ioctl` flags - Linux: add epoll busy polling parameters - NuttX: add `pthread_[get/set]name_np` - RTEMS: add `arc4random_buf` - Trusty OS: add initial support - WASIp2: expand socket support ### Fixed - Emscripten: don't pass `-lc` - Hurd: change `st_fsid` field to `st_dev` - Hurd: fix the definition of `utsname` - Illumos/Solaris: fix `FNM_CASEFOLD` definition - Solaris: fix all tests ### Other - CI: Add loongarch64 - CI: Check that semver files are sorted - CI: Re-enable the FreeBSD 15 job - Clean up imports and `extern crate` usage - Convert `mode_t` constants to octal - Remove the `wasm32-wasi` target that has been deleted upstream ## [0.2.161](https://github.com/rust-lang/libc/compare/0.2.160...0.2.161) - 2024-10-17 ### Fixed - OpenBSD: fix `FNM_PATHNAME` and `FNM_NOESCAPE` values ## [0.2.160](https://github.com/rust-lang/libc/compare/0.2.159...0.2.160) - 2024-10-17 ### Added - Android: add `PR_GET_NAME` and `PR_SET_NAME` - Apple: add `F_TRANSFEREXTENTS` - Apple: add `mach_error_string` - Apple: add additional `pthread` APIs - Apple: add the `LOCAL_PEERTOKEN` socket option - BSD: add `RTF_*`, `RTA_*`, `RTAX_*`, and `RTM_*` definitions - Emscripten: add `AT_EACCESS` - Emscripten: add `getgrgid`, `getgrnam`, `getgrnam_r` and `getgrgid_r` - Emscripten: add `getpwnam_r` and `getpwuid_r` - FreeBSD: add `POLLRDHUP` - Haiku: add `arc4random` - Illumos: add `ptsname_r` - Linux: add `fanotify` interfaces - Linux: add `tcp_info` - Linux: add additional AF_PACKET options - Linux: make Elf constants always available - Musl x86: add `iopl` and `ioperm` - Musl: add `posix_spawn` chdir functions - Musl: add `utmpx.h` constants - NetBSD: add `sysctlnametomib`, `CLOCK_THREAD_CPUTIME_ID` and `CLOCK_PROCESS_CPUTIME_ID` - Nuttx: initial support - RTEMS: add `getentropy` - RTEMS: initial support - Solarish: add `POLLRDHUP`, `POSIX_FADV_*`, `O_RSYNC`, and `posix_fallocate` - Unix: add `fnmatch.h` - VxWorks: add riscv64 support - VxWorks: update constants related to the scheduler ### Changed - Redox: change `ino_t` to be `c_ulonglong` ### Fixed - ESP-IDF: fix mismatched constants and structs - FreeBSD: fix `struct stat` on FreeBSD 12+ ### Other - CI: Fix CI for FreeBSD 15 - Docs: link to `windows-sys` ## [0.2.159](https://github.com/rust-lang/libc/compare/0.2.158...0.2.159) - 2024-09-24 ### Added - Android: add more `AT_*` constants in - Apple: add missing `NOTE_*` constants in - Hermit: add missing error numbers in - Hurd: add `__timeval` for 64-bit support in - Linux: add `epoll_pwait2` in - Linux: add `mq_notify` in - Linux: add missing `NFT_CT_*` constants in - Linux: add the `fchmodat2` syscall in - Linux: add the `mseal` syscall in - OpenBSD: add `sendmmsg` and `recvmmsg` in - Unix: add `IN6ADDR_ANY_INIT` and `IN6ADDR_LOOPBACK_INIT` in - VxWorks: add `S_ISVTX` in - VxWorks: add `vxCpuLib` and `taskLib` functions - WASIp2: add definitions for `std::net` support in ### Fixed - Correctly handle version checks when `clippy-driver` is used ### Changed - EspIdf: change signal constants to c_int in - HorizonOS: update network definitions in - Linux: combine `ioctl` APIs in - WASI: enable CI testing in - WASIp2: enable CI testing in ## [0.2.158](https://github.com/rust-lang/libc/compare/0.2.157...0.2.158) - 2024-08-19 ### Other - WASI: fix missing `Iterator` with `rustc-dep-of-std` in ## [0.2.157](https://github.com/rust-lang/libc/compare/0.2.156...0.2.157) - 2024-08-17 ### Added - Apple: add `_NSGetArgv`, `_NSGetArgc` and `_NSGetProgname` in - Build: add `RUSTC_WRAPPER` support in - FreeBSD: add `execvpe` support from 14.1 release in - Fuchsia: add `SO_BINDTOIFINDEX` - Linux: add `klogctl` in - MacOS: add `fcntl` OFD commands in - NetBSD: add `_lwp_park` in - Solaris: add missing networking support in - Unix: add `pthread_equal` in - WASI: add `select`, `FD_SET`, `FD_ZERO`, `FD_ISSET ` in ### Fixed - TEEOS: fix octal notation for `O_*` constants in ### Changed - FreeBSD: always use freebsd12 when `rustc_dep_of_std` is set in ## [0.2.156](https://github.com/rust-lang/libc/compare/v0.2.155...v0.2.156) - 2024-08-15 ### Added - Apple: add `F_ALLOCATEPERSIST` in - Apple: add `os_sync_wait_on_address` and related definitions in - BSD: generalise `IPV6_DONTFRAG` to all BSD targets in - FreeBSD/DragonFly: add `IP_RECVTTL`/`IPV6_RECVHOPLIMIT` in - Hurd: add `XATTR_CREATE`, `XATTR_REPLACE` in - Linux GNU: `confstr` API and `_CS_*` in - Linux musl: add `preadv2` and `pwritev2` (1.2.5 min.) in - VxWorks: add the constant `SOMAXCONN` in - VxWorks: add a few errnoLib related constants in ### Fixed - Solaris/illumos: Change `ifa_flags` type to u64 in - QNX 7.0: Disable `libregex` in ### Changed - QNX NTO: update platform support in - `addr_of!(EXTERN_STATIC)` is now considered safe in ### Removed - Apple: remove `rmx_state` in ### Other - Update or remove CI tests that have been failing libc/src/0000775000175000017500000000000015105742312012104 5ustar bdrungbdrunglibc/src/lib.rs0000644000175000017500000000755515105742312013232 0ustar bdrungbdrung//! libc - Raw FFI bindings to platforms' system libraries #![crate_name = "libc"] #![crate_type = "rlib"] #![allow( renamed_and_removed_lints, // Keep this order. unknown_lints, // Keep this order. bad_style, overflowing_literals, improper_ctypes, // This lint is renamed but we run CI for old stable rustc so should be here. redundant_semicolon, redundant_semicolons, unused_macros, unused_macro_rules, // FIXME(1.0): temporarily allow dead_code to fix CI: // - https://github.com/rust-lang/libc/issues/3740 // - https://github.com/rust-lang/rust/pull/126456 dead_code, )] #![cfg_attr(libc_deny_warnings, deny(warnings))] // Attributes needed when building as part of the standard library #![cfg_attr(feature = "rustc-dep-of-std", feature(link_cfg, no_core))] #![cfg_attr(libc_thread_local, feature(thread_local))] #![cfg_attr(feature = "rustc-dep-of-std", allow(internal_features))] // DIFF(1.0): The thread local references that raise this lint were removed in 1.0 #![cfg_attr(feature = "rustc-dep-of-std", allow(static_mut_refs))] // Enable extra lints: #![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))] #![deny(missing_copy_implementations, safe_packed_borrows)] #![cfg_attr(not(feature = "rustc-dep-of-std"), no_std)] #![cfg_attr(feature = "rustc-dep-of-std", no_core)] #[macro_use] mod macros; cfg_if! { if #[cfg(feature = "rustc-dep-of-std")] { extern crate rustc_std_workspace_core as core; } } pub use core::ffi::c_void; cfg_if! { if #[cfg(windows)] { mod primitives; pub use crate::primitives::*; mod windows; pub use crate::windows::*; prelude!(); } else if #[cfg(target_os = "fuchsia")] { mod primitives; pub use crate::primitives::*; mod fuchsia; pub use crate::fuchsia::*; prelude!(); } else if #[cfg(target_os = "switch")] { mod primitives; pub use primitives::*; mod switch; pub use switch::*; prelude!(); } else if #[cfg(target_os = "psp")] { mod primitives; pub use primitives::*; mod psp; pub use crate::psp::*; prelude!(); } else if #[cfg(target_os = "vxworks")] { mod primitives; pub use crate::primitives::*; mod vxworks; pub use crate::vxworks::*; prelude!(); } else if #[cfg(target_os = "solid_asp3")] { mod primitives; pub use crate::primitives::*; mod solid; pub use crate::solid::*; prelude!(); } else if #[cfg(unix)] { mod primitives; pub use crate::primitives::*; mod unix; pub use crate::unix::*; prelude!(); } else if #[cfg(target_os = "hermit")] { mod primitives; pub use crate::primitives::*; mod hermit; pub use crate::hermit::*; prelude!(); } else if #[cfg(target_os = "teeos")] { mod primitives; pub use primitives::*; mod teeos; pub use teeos::*; prelude!(); } else if #[cfg(target_os = "trusty")] { mod primitives; pub use crate::primitives::*; mod trusty; pub use crate::trusty::*; prelude!(); } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] { mod primitives; pub use crate::primitives::*; mod sgx; pub use crate::sgx::*; prelude!(); } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] { mod primitives; pub use crate::primitives::*; mod wasi; pub use crate::wasi::*; prelude!(); } else if #[cfg(target_os = "xous")] { mod primitives; pub use crate::primitives::*; mod xous; pub use crate::xous::*; prelude!(); } else { // non-supported targets: empty... } } libc/src/fuchsia/0000775000175000017500000000000015105742312013526 5ustar bdrungbdrunglibc/src/fuchsia/mod.rs0000644000175000017500000045217415105742312014666 0ustar bdrungbdrung//! Definitions found commonly among almost all Unix derivatives //! //! More functions and definitions can be found in the more specific modules //! according to the platform in question. use crate::prelude::*; // PUB_TYPE pub type intmax_t = i64; pub type uintmax_t = u64; pub type locale_t = *mut c_void; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type pid_t = i32; pub type uid_t = u32; pub type gid_t = u32; pub type in_addr_t = u32; pub type in_port_t = u16; pub type sighandler_t = size_t; pub type cc_t = c_uchar; pub type sa_family_t = u16; pub type pthread_key_t = c_uint; pub type speed_t = c_uint; pub type tcflag_t = c_uint; pub type clockid_t = c_int; pub type key_t = c_int; pub type id_t = c_uint; pub type useconds_t = u32; pub type dev_t = u64; pub type socklen_t = u32; pub type pthread_t = c_ulong; pub type mode_t = u32; pub type ino64_t = u64; pub type off64_t = i64; pub type blkcnt64_t = i64; pub type rlim64_t = u64; pub type mqd_t = c_int; pub type nfds_t = c_ulong; pub type nl_item = c_int; pub type idtype_t = c_uint; pub type loff_t = c_longlong; pub type __u8 = c_uchar; pub type __u16 = c_ushort; pub type __s16 = c_short; pub type __u32 = c_uint; pub type __s32 = c_int; pub type Elf32_Half = u16; pub type Elf32_Word = u32; pub type Elf32_Off = u32; pub type Elf32_Addr = u32; pub type Elf64_Half = u16; pub type Elf64_Word = u32; pub type Elf64_Off = u64; pub type Elf64_Addr = u64; pub type Elf64_Xword = u64; pub type clock_t = c_long; pub type time_t = c_long; pub type suseconds_t = c_long; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i64; pub type shmatt_t = c_ulong; pub type msgqnum_t = c_ulong; pub type msglen_t = c_ulong; pub type fsblkcnt_t = c_ulonglong; pub type fsfilcnt_t = c_ulonglong; pub type rlim_t = c_ulonglong; // FIXME(fuchsia): why are these uninhabited types? that seems... wrong? // Presumably these should be `()` or an `extern type` (when that stabilizes). #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} impl Copy for DIR {} impl Clone for DIR { fn clone(&self) -> DIR { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos64_t {} // FIXME(fuchsia): fill this out with a struct impl Copy for fpos64_t {} impl Clone for fpos64_t { fn clone(&self) -> fpos64_t { *self } } // PUB_STRUCT s! { pub struct group { pub gr_name: *mut c_char, pub gr_passwd: *mut c_char, pub gr_gid: crate::gid_t, pub gr_mem: *mut *mut c_char, } pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } // FIXME(fuchsia): the rlimit and rusage related functions and types don't exist // within zircon. Are there reasons for keeping them around? pub struct rlimit { pub rlim_cur: rlim_t, pub rlim_max: rlim_t, } pub struct rusage { pub ru_utime: timeval, pub ru_stime: timeval, pub ru_maxrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad1: u32, pub ru_ixrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad2: u32, pub ru_idrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad3: u32, pub ru_isrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad4: u32, pub ru_minflt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad5: u32, pub ru_majflt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad6: u32, pub ru_nswap: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad7: u32, pub ru_inblock: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad8: u32, pub ru_oublock: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad9: u32, pub ru_msgsnd: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad10: u32, pub ru_msgrcv: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad11: u32, pub ru_nsignals: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad12: u32, pub ru_nvcsw: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad13: u32, pub ru_nivcsw: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad14: u32, } pub struct in_addr { pub s_addr: in_addr_t, } pub struct in6_addr { pub s6_addr: [u8; 16], } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: c_int, } pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } pub struct hostent { pub h_name: *mut c_char, pub h_aliases: *mut *mut c_char, pub h_addrtype: c_int, pub h_length: c_int, pub h_addr_list: *mut *mut c_char, } pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct pollfd { pub fd: c_int, pub events: c_short, pub revents: c_short, } pub struct winsize { pub ws_row: c_ushort, pub ws_col: c_ushort, pub ws_xpixel: c_ushort, pub ws_ypixel: c_ushort, } pub struct linger { pub l_onoff: c_int, pub l_linger: c_int, } pub struct sigval { // Actually a union of an int and a void* pub sival_ptr: *mut c_void, } // pub struct itimerval { pub it_interval: crate::timeval, pub it_value: crate::timeval, } // pub struct tms { pub tms_utime: crate::clock_t, pub tms_stime: crate::clock_t, pub tms_cutime: crate::clock_t, pub tms_cstime: crate::clock_t, } pub struct servent { pub s_name: *mut c_char, pub s_aliases: *mut *mut c_char, pub s_port: c_int, pub s_proto: *mut c_char, } pub struct protoent { pub p_name: *mut c_char, pub p_aliases: *mut *mut c_char, pub p_proto: c_int, } pub struct aiocb { pub aio_fildes: c_int, pub aio_lio_opcode: c_int, pub aio_reqprio: c_int, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_sigevent: crate::sigevent, __td: *mut c_void, __lock: [c_int; 2], __err: c_int, __ret: ssize_t, pub aio_offset: off_t, __next: *mut c_void, __prev: *mut c_void, #[cfg(target_pointer_width = "32")] __dummy4: [c_char; 24], #[cfg(target_pointer_width = "64")] __dummy4: [c_char; 16], } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], pub __c_ispeed: crate::speed_t, pub __c_ospeed: crate::speed_t, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct ucred { pub pid: crate::pid_t, pub uid: crate::uid_t, pub gid: crate::gid_t, } pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_vm { pub svm_family: sa_family_t, pub svm_reserved1: c_ushort, pub svm_port: crate::in_port_t, pub svm_cid: c_uint, pub svm_zero: [u8; 4], } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, pub ai_addr: *mut crate::sockaddr, pub ai_canonname: *mut c_char, pub ai_next: *mut addrinfo, } pub struct sockaddr_ll { pub sll_family: c_ushort, pub sll_protocol: c_ushort, pub sll_ifindex: c_int, pub sll_hatype: c_ushort, pub sll_pkttype: c_uchar, pub sll_halen: c_uchar, pub sll_addr: [c_uchar; 8], } pub struct fd_set { fds_bits: [c_ulong; FD_SETSIZE as usize / ULONG_SIZE], } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *const c_char, } pub struct sched_param { pub sched_priority: c_int, pub sched_ss_low_priority: c_int, pub sched_ss_repl_period: crate::timespec, pub sched_ss_init_budget: crate::timespec, pub sched_ss_max_repl: c_int, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct epoll_event { pub events: u32, pub u64: u64, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, pub ifa_addr: *mut crate::sockaddr, pub ifa_netmask: *mut crate::sockaddr, pub ifa_ifu: *mut crate::sockaddr, // FIXME(union) This should be a union pub ifa_data: *mut c_void, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct spwd { pub sp_namp: *mut c_char, pub sp_pwdp: *mut c_char, pub sp_lstchg: c_long, pub sp_min: c_long, pub sp_max: c_long, pub sp_warn: c_long, pub sp_inact: c_long, pub sp_expire: c_long, pub sp_flag: c_ulong, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, #[cfg(target_endian = "little")] pub f_fsid: c_ulong, #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] __f_unused: c_int, #[cfg(target_endian = "big")] pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct dqblk { pub dqb_bhardlimit: u64, pub dqb_bsoftlimit: u64, pub dqb_curspace: u64, pub dqb_ihardlimit: u64, pub dqb_isoftlimit: u64, pub dqb_curinodes: u64, pub dqb_btime: u64, pub dqb_itime: u64, pub dqb_valid: u32, } pub struct signalfd_siginfo { pub ssi_signo: u32, pub ssi_errno: i32, pub ssi_code: i32, pub ssi_pid: u32, pub ssi_uid: u32, pub ssi_fd: i32, pub ssi_tid: u32, pub ssi_band: u32, pub ssi_overrun: u32, pub ssi_trapno: u32, pub ssi_status: i32, pub ssi_int: i32, pub ssi_ptr: u64, pub ssi_utime: u64, pub ssi_stime: u64, pub ssi_addr: u64, pub ssi_addr_lsb: u16, _pad2: u16, pub ssi_syscall: i32, pub ssi_call_addr: u64, pub ssi_arch: u32, _pad: [u8; 28], } pub struct itimerspec { pub it_interval: crate::timespec, pub it_value: crate::timespec, } pub struct fsid_t { __val: [c_int; 2], } pub struct cpu_set_t { #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] bits: [u32; 32], #[cfg(not(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] bits: [u64; 16], } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } // System V IPC pub struct msginfo { pub msgpool: c_int, pub msgmap: c_int, pub msgmax: c_int, pub msgmnb: c_int, pub msgmni: c_int, pub msgssz: c_int, pub msgtql: c_int, pub msgseg: c_ushort, } pub struct mmsghdr { pub msg_hdr: crate::msghdr, pub msg_len: c_uint, } pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } pub struct input_event { pub time: crate::timeval, pub type_: crate::__u16, pub code: crate::__u16, pub value: crate::__s32, } pub struct input_id { pub bustype: crate::__u16, pub vendor: crate::__u16, pub product: crate::__u16, pub version: crate::__u16, } pub struct input_absinfo { pub value: crate::__s32, pub minimum: crate::__s32, pub maximum: crate::__s32, pub fuzz: crate::__s32, pub flat: crate::__s32, pub resolution: crate::__s32, } pub struct input_keymap_entry { pub flags: crate::__u8, pub len: crate::__u8, pub index: crate::__u16, pub keycode: crate::__u32, pub scancode: [crate::__u8; 32], } pub struct input_mask { pub type_: crate::__u32, pub codes_size: crate::__u32, pub codes_ptr: crate::__u64, } pub struct ff_replay { pub length: crate::__u16, pub delay: crate::__u16, } pub struct ff_trigger { pub button: crate::__u16, pub interval: crate::__u16, } pub struct ff_envelope { pub attack_length: crate::__u16, pub attack_level: crate::__u16, pub fade_length: crate::__u16, pub fade_level: crate::__u16, } pub struct ff_constant_effect { pub level: crate::__s16, pub envelope: ff_envelope, } pub struct ff_ramp_effect { pub start_level: crate::__s16, pub end_level: crate::__s16, pub envelope: ff_envelope, } pub struct ff_condition_effect { pub right_saturation: crate::__u16, pub left_saturation: crate::__u16, pub right_coeff: crate::__s16, pub left_coeff: crate::__s16, pub deadband: crate::__u16, pub center: crate::__s16, } pub struct ff_periodic_effect { pub waveform: crate::__u16, pub period: crate::__u16, pub magnitude: crate::__s16, pub offset: crate::__s16, pub phase: crate::__u16, pub envelope: ff_envelope, pub custom_len: crate::__u32, pub custom_data: *mut crate::__s16, } pub struct ff_rumble_effect { pub strong_magnitude: crate::__u16, pub weak_magnitude: crate::__u16, } pub struct ff_effect { pub type_: crate::__u16, pub id: crate::__s16, pub direction: crate::__u16, pub trigger: ff_trigger, pub replay: ff_replay, // FIXME(1.0): this is actually a union #[cfg(target_pointer_width = "64")] pub u: [u64; 4], #[cfg(target_pointer_width = "32")] pub u: [u32; 7], } pub struct dl_phdr_info { #[cfg(target_pointer_width = "64")] pub dlpi_addr: Elf64_Addr, #[cfg(target_pointer_width = "32")] pub dlpi_addr: Elf32_Addr, pub dlpi_name: *const c_char, #[cfg(target_pointer_width = "64")] pub dlpi_phdr: *const Elf64_Phdr, #[cfg(target_pointer_width = "32")] pub dlpi_phdr: *const Elf32_Phdr, #[cfg(target_pointer_width = "64")] pub dlpi_phnum: Elf64_Half, #[cfg(target_pointer_width = "32")] pub dlpi_phnum: Elf32_Half, pub dlpi_adds: c_ulonglong, pub dlpi_subs: c_ulonglong, pub dlpi_tls_modid: size_t, pub dlpi_tls_data: *mut c_void, } pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } pub struct statfs64 { pub f_type: c_ulong, pub f_bsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_ulong, pub f_frsize: c_ulong, pub f_flags: c_ulong, pub f_spare: [c_ulong; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct pthread_attr_t { __size: [u64; 7], } pub struct sigset_t { __val: [c_ulong; 16], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: c_ulong, __pad1: c_ulong, __pad2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } pub struct statfs { pub f_type: c_ulong, pub f_bsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_ulong, pub f_frsize: c_ulong, pub f_flags: c_ulong, pub f_spare: [c_ulong; 4], } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, __pad1: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, __pad2: crate::socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub __pad1: c_int, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct sem_t { __val: [c_int; 8], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, pub _pad: [c_int; 29], _align: [usize; 0], } pub struct termios2 { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; 19], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } pub struct in6_pktinfo { pub ipi6_addr: crate::in6_addr, pub ipi6_ifindex: c_uint, } #[cfg_attr( any(target_pointer_width = "32", target_arch = "x86_64"), repr(align(4)) )] #[cfg_attr( not(any(target_pointer_width = "32", target_arch = "x86_64")), repr(align(8)) )] pub struct pthread_mutexattr_t { size: [u8; crate::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct pthread_rwlockattr_t { size: [u8; crate::__SIZEOF_PTHREAD_RWLOCKATTR_T], } #[repr(align(4))] pub struct pthread_condattr_t { size: [u8; crate::__SIZEOF_PTHREAD_CONDATTR_T], } } s_no_extra_traits! { pub struct sysinfo { pub uptime: c_ulong, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub __reserved: [c_char; 256], } pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char; 108], } pub struct sockaddr_storage { pub ss_family: sa_family_t, __ss_pad2: [u8; 128 - 2 - 8], __ss_align: size_t, } pub struct utsname { pub sysname: [c_char; 65], pub nodename: [c_char; 65], pub release: [c_char; 65], pub version: [c_char; 65], pub machine: [c_char; 65], pub domainname: [c_char; 65], } pub struct dirent { pub d_ino: crate::ino_t, pub d_off: off_t, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } pub struct dirent64 { pub d_ino: crate::ino64_t, pub d_off: off64_t, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } // x32 compatibility // See https://sourceware.org/bugzilla/show_bug.cgi?id=21279 pub struct mq_attr { #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_flags: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_maxmsg: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_msgsize: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_curmsgs: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pad: [i64; 4], #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_flags: c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_maxmsg: c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_msgsize: c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_curmsgs: c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pad: [c_long; 4], } pub struct sockaddr_nl { pub nl_family: crate::sa_family_t, nl_pad: c_ushort, pub nl_pid: u32, pub nl_groups: u32, } pub struct sigevent { pub sigev_value: crate::sigval, pub sigev_signo: c_int, pub sigev_notify: c_int, pub sigev_notify_function: fn(crate::sigval), pub sigev_notify_attributes: *mut pthread_attr_t, pub __pad: [c_char; 56 - 3 * 8], } #[cfg_attr( all( target_pointer_width = "32", any(target_arch = "arm", target_arch = "x86_64") ), repr(align(4)) )] #[cfg_attr( any( target_pointer_width = "64", not(any(target_arch = "arm", target_arch = "x86_64")) ), repr(align(8)) )] pub struct pthread_mutex_t { size: [u8; crate::__SIZEOF_PTHREAD_MUTEX_T], } #[cfg_attr( all( target_pointer_width = "32", any(target_arch = "arm", target_arch = "x86_64") ), repr(align(4)) )] #[cfg_attr( any( target_pointer_width = "64", not(any(target_arch = "arm", target_arch = "x86_64")) ), repr(align(8)) )] pub struct pthread_rwlock_t { size: [u8; crate::__SIZEOF_PTHREAD_RWLOCK_T], } #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] #[cfg_attr(target_arch = "x86", repr(align(4)))] #[cfg_attr(not(target_arch = "x86"), repr(align(8)))] pub struct pthread_cond_t { size: [u8; crate::__SIZEOF_PTHREAD_COND_T], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sysinfo { fn eq(&self, other: &sysinfo) -> bool { self.uptime == other.uptime && self.loads == other.loads && self.totalram == other.totalram && self.freeram == other.freeram && self.sharedram == other.sharedram && self.bufferram == other.bufferram && self.totalswap == other.totalswap && self.freeswap == other.freeswap && self.procs == other.procs && self.pad == other.pad && self.totalhigh == other.totalhigh && self.freehigh == other.freehigh && self.mem_unit == other.mem_unit && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a, b)| a == b) } } impl Eq for sysinfo {} impl fmt::Debug for sysinfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sysinfo") .field("uptime", &self.uptime) .field("loads", &self.loads) .field("totalram", &self.totalram) .field("freeram", &self.freeram) .field("sharedram", &self.sharedram) .field("bufferram", &self.bufferram) .field("totalswap", &self.totalswap) .field("freeswap", &self.freeswap) .field("procs", &self.procs) .field("pad", &self.pad) .field("totalhigh", &self.totalhigh) .field("freehigh", &self.freehigh) .field("mem_unit", &self.mem_unit) // FIXME(debug): .field("__reserved", &self.__reserved) .finish() } } impl hash::Hash for sysinfo { fn hash(&self, state: &mut H) { self.uptime.hash(state); self.loads.hash(state); self.totalram.hash(state); self.freeram.hash(state); self.sharedram.hash(state); self.bufferram.hash(state); self.totalswap.hash(state); self.freeswap.hash(state); self.procs.hash(state); self.pad.hash(state); self.totalhigh.hash(state); self.freehigh.hash(state); self.mem_unit.hash(state); self.__reserved.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME(debug): .field("sun_path", &self.sun_path) .finish() } } impl hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_family == other.ss_family && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_family", &self.ss_family) .field("__ss_align", &self.__ss_align) // FIXME(debug): .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_family.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl fmt::Debug for utsname { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utsname") // FIXME(debug): .field("sysname", &self.sysname) // FIXME(debug): .field("nodename", &self.nodename) // FIXME(debug): .field("release", &self.release) // FIXME(debug): .field("version", &self.version) // FIXME(debug): .field("machine", &self.machine) .finish() } } impl hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for dirent64 { fn eq(&self, other: &dirent64) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent64 {} impl fmt::Debug for dirent64 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent64") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent64 { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_flags == other.mq_flags && self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_curmsgs == other.mq_curmsgs } } impl Eq for mq_attr {} impl fmt::Debug for mq_attr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mq_attr") .field("mq_flags", &self.mq_flags) .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_curmsgs", &self.mq_curmsgs) .finish() } } impl hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_flags.hash(state); self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_curmsgs.hash(state); } } impl PartialEq for sockaddr_nl { fn eq(&self, other: &sockaddr_nl) -> bool { self.nl_family == other.nl_family && self.nl_pid == other.nl_pid && self.nl_groups == other.nl_groups } } impl Eq for sockaddr_nl {} impl fmt::Debug for sockaddr_nl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_nl") .field("nl_family", &self.nl_family) .field("nl_pid", &self.nl_pid) .field("nl_groups", &self.nl_groups) .finish() } } impl hash::Hash for sockaddr_nl { fn hash(&self, state: &mut H) { self.nl_family.hash(state); self.nl_pid.hash(state); self.nl_groups.hash(state); } } // FIXME(msrv): suggested method was added in 1.85 #[allow(unpredictable_function_pointer_comparisons)] impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_value == other.sigev_value && self.sigev_signo == other.sigev_signo && self.sigev_notify == other.sigev_notify && self.sigev_notify_function == other.sigev_notify_function && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_value", &self.sigev_value) .field("sigev_signo", &self.sigev_signo) .field("sigev_notify", &self.sigev_notify) .field("sigev_notify_function", &self.sigev_notify_function) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_value.hash(state); self.sigev_signo.hash(state); self.sigev_notify.hash(state); self.sigev_notify_function.hash(state); self.sigev_notify_attributes.hash(state); } } impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a, b)| a == b) } } impl Eq for pthread_cond_t {} impl fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_cond_t") // FIXME(debug): .field("size", &self.size) .finish() } } impl hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a, b)| a == b) } } impl Eq for pthread_mutex_t {} impl fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_mutex_t") // FIXME(debug): .field("size", &self.size) .finish() } } impl hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a, b)| a == b) } } impl Eq for pthread_rwlock_t {} impl fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_rwlock_t") // FIXME(debug): .field("size", &self.size) .finish() } } impl hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } } } // PUB_CONST pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const SIG_DFL: sighandler_t = 0 as sighandler_t; pub const SIG_IGN: sighandler_t = 1 as sighandler_t; pub const SIG_ERR: sighandler_t = !0 as sighandler_t; pub const DT_UNKNOWN: u8 = 0; pub const DT_FIFO: u8 = 1; pub const DT_CHR: u8 = 2; pub const DT_DIR: u8 = 4; pub const DT_BLK: u8 = 6; pub const DT_REG: u8 = 8; pub const DT_LNK: u8 = 10; pub const DT_SOCK: u8 = 12; pub const FD_CLOEXEC: c_int = 0x1; pub const USRQUOTA: c_int = 0; pub const GRPQUOTA: c_int = 1; pub const SIGIOT: c_int = 6; pub const S_ISUID: crate::mode_t = 0o4000; pub const S_ISGID: crate::mode_t = 0o2000; pub const S_ISVTX: crate::mode_t = 0o1000; pub const IF_NAMESIZE: size_t = 16; pub const IFNAMSIZ: size_t = IF_NAMESIZE; pub const LOG_EMERG: c_int = 0; pub const LOG_ALERT: c_int = 1; pub const LOG_CRIT: c_int = 2; pub const LOG_ERR: c_int = 3; pub const LOG_WARNING: c_int = 4; pub const LOG_NOTICE: c_int = 5; pub const LOG_INFO: c_int = 6; pub const LOG_DEBUG: c_int = 7; pub const LOG_KERN: c_int = 0; pub const LOG_USER: c_int = 1 << 3; pub const LOG_MAIL: c_int = 2 << 3; pub const LOG_DAEMON: c_int = 3 << 3; pub const LOG_AUTH: c_int = 4 << 3; pub const LOG_SYSLOG: c_int = 5 << 3; pub const LOG_LPR: c_int = 6 << 3; pub const LOG_NEWS: c_int = 7 << 3; pub const LOG_UUCP: c_int = 8 << 3; pub const LOG_LOCAL0: c_int = 16 << 3; pub const LOG_LOCAL1: c_int = 17 << 3; pub const LOG_LOCAL2: c_int = 18 << 3; pub const LOG_LOCAL3: c_int = 19 << 3; pub const LOG_LOCAL4: c_int = 20 << 3; pub const LOG_LOCAL5: c_int = 21 << 3; pub const LOG_LOCAL6: c_int = 22 << 3; pub const LOG_LOCAL7: c_int = 23 << 3; pub const LOG_PID: c_int = 0x01; pub const LOG_CONS: c_int = 0x02; pub const LOG_ODELAY: c_int = 0x04; pub const LOG_NDELAY: c_int = 0x08; pub const LOG_NOWAIT: c_int = 0x10; pub const LOG_PRIMASK: c_int = 7; pub const LOG_FACMASK: c_int = 0x3f8; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; pub const PRIO_MIN: c_int = -20; pub const PRIO_MAX: c_int = 20; pub const IPPROTO_ICMP: c_int = 1; pub const IPPROTO_ICMPV6: c_int = 58; pub const IPPROTO_TCP: c_int = 6; pub const IPPROTO_UDP: c_int = 17; pub const IPPROTO_IP: c_int = 0; pub const IPPROTO_IPV6: c_int = 41; pub const INADDR_LOOPBACK: in_addr_t = 2130706433; pub const INADDR_ANY: in_addr_t = 0; pub const INADDR_BROADCAST: in_addr_t = 4294967295; pub const INADDR_NONE: in_addr_t = 4294967295; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 2147483647; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; // Linux-specific fcntls pub const F_SETLEASE: c_int = 1024; pub const F_GETLEASE: c_int = 1025; pub const F_NOTIFY: c_int = 1026; pub const F_CANCELLK: c_int = 1029; pub const F_DUPFD_CLOEXEC: c_int = 1030; pub const F_SETPIPE_SZ: c_int = 1031; pub const F_GETPIPE_SZ: c_int = 1032; pub const F_ADD_SEALS: c_int = 1033; pub const F_GET_SEALS: c_int = 1034; pub const F_SEAL_SEAL: c_int = 0x0001; pub const F_SEAL_SHRINK: c_int = 0x0002; pub const F_SEAL_GROW: c_int = 0x0004; pub const F_SEAL_WRITE: c_int = 0x0008; // FIXME(#235): Include file sealing fcntls once we have a way to verify them. pub const SIGTRAP: c_int = 5; pub const PTHREAD_CREATE_JOINABLE: c_int = 0; pub const PTHREAD_CREATE_DETACHED: c_int = 1; pub const CLOCK_REALTIME: crate::clockid_t = 0; pub const CLOCK_MONOTONIC: crate::clockid_t = 1; pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 3; pub const CLOCK_MONOTONIC_RAW: crate::clockid_t = 4; pub const CLOCK_REALTIME_COARSE: crate::clockid_t = 5; pub const CLOCK_MONOTONIC_COARSE: crate::clockid_t = 6; pub const CLOCK_BOOTTIME: crate::clockid_t = 7; pub const CLOCK_REALTIME_ALARM: crate::clockid_t = 8; pub const CLOCK_BOOTTIME_ALARM: crate::clockid_t = 9; pub const CLOCK_SGI_CYCLE: crate::clockid_t = 10; pub const CLOCK_TAI: crate::clockid_t = 11; pub const TIMER_ABSTIME: c_int = 1; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_LOCKS: c_int = 10; pub const RLIMIT_SIGPENDING: c_int = 11; pub const RLIMIT_MSGQUEUE: c_int = 12; pub const RLIMIT_NICE: c_int = 13; pub const RLIMIT_RTPRIO: c_int = 14; pub const RUSAGE_SELF: c_int = 0; pub const O_RDONLY: c_int = 0; pub const O_WRONLY: c_int = 1; pub const O_RDWR: c_int = 2; pub const S_IFIFO: crate::mode_t = 0o1_0000; pub const S_IFCHR: crate::mode_t = 0o2_0000; pub const S_IFBLK: crate::mode_t = 0o6_0000; pub const S_IFDIR: crate::mode_t = 0o4_0000; pub const S_IFREG: crate::mode_t = 0o10_0000; pub const S_IFLNK: crate::mode_t = 0o12_0000; pub const S_IFSOCK: crate::mode_t = 0o14_0000; pub const S_IFMT: crate::mode_t = 0o17_0000; pub const S_IRWXU: crate::mode_t = 0o0700; pub const S_IXUSR: crate::mode_t = 0o0100; pub const S_IWUSR: crate::mode_t = 0o0200; pub const S_IRUSR: crate::mode_t = 0o0400; pub const S_IRWXG: crate::mode_t = 0o0070; pub const S_IXGRP: crate::mode_t = 0o0010; pub const S_IWGRP: crate::mode_t = 0o0020; pub const S_IRGRP: crate::mode_t = 0o0040; pub const S_IRWXO: crate::mode_t = 0o0007; pub const S_IXOTH: crate::mode_t = 0o0001; pub const S_IWOTH: crate::mode_t = 0o0002; pub const S_IROTH: crate::mode_t = 0o0004; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSEGV: c_int = 11; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const LC_CTYPE: c_int = 0; pub const LC_NUMERIC: c_int = 1; pub const LC_TIME: c_int = 2; pub const LC_COLLATE: c_int = 3; pub const LC_MONETARY: c_int = 4; pub const LC_MESSAGES: c_int = 5; pub const LC_ALL: c_int = 6; pub const LC_CTYPE_MASK: c_int = 1 << LC_CTYPE; pub const LC_NUMERIC_MASK: c_int = 1 << LC_NUMERIC; pub const LC_TIME_MASK: c_int = 1 << LC_TIME; pub const LC_COLLATE_MASK: c_int = 1 << LC_COLLATE; pub const LC_MONETARY_MASK: c_int = 1 << LC_MONETARY; pub const LC_MESSAGES_MASK: c_int = 1 << LC_MESSAGES; // LC_ALL_MASK defined per platform pub const MAP_FILE: c_int = 0x0000; pub const MAP_SHARED: c_int = 0x0001; pub const MAP_PRIVATE: c_int = 0x0002; pub const MAP_FIXED: c_int = 0x0010; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; // MS_ flags for msync(2) pub const MS_ASYNC: c_int = 0x0001; pub const MS_INVALIDATE: c_int = 0x0002; pub const MS_SYNC: c_int = 0x0004; // MS_ flags for mount(2) pub const MS_RDONLY: c_ulong = 0x01; pub const MS_NOSUID: c_ulong = 0x02; pub const MS_NODEV: c_ulong = 0x04; pub const MS_NOEXEC: c_ulong = 0x08; pub const MS_SYNCHRONOUS: c_ulong = 0x10; pub const MS_REMOUNT: c_ulong = 0x20; pub const MS_MANDLOCK: c_ulong = 0x40; pub const MS_DIRSYNC: c_ulong = 0x80; pub const MS_NOATIME: c_ulong = 0x0400; pub const MS_NODIRATIME: c_ulong = 0x0800; pub const MS_BIND: c_ulong = 0x1000; pub const MS_MOVE: c_ulong = 0x2000; pub const MS_REC: c_ulong = 0x4000; pub const MS_SILENT: c_ulong = 0x8000; pub const MS_POSIXACL: c_ulong = 0x010000; pub const MS_UNBINDABLE: c_ulong = 0x020000; pub const MS_PRIVATE: c_ulong = 0x040000; pub const MS_SLAVE: c_ulong = 0x080000; pub const MS_SHARED: c_ulong = 0x100000; pub const MS_RELATIME: c_ulong = 0x200000; pub const MS_KERNMOUNT: c_ulong = 0x400000; pub const MS_I_VERSION: c_ulong = 0x800000; pub const MS_STRICTATIME: c_ulong = 0x1000000; pub const MS_ACTIVE: c_ulong = 0x40000000; pub const MS_NOUSER: c_ulong = 0x80000000; pub const MS_MGC_VAL: c_ulong = 0xc0ed0000; pub const MS_MGC_MSK: c_ulong = 0xffff0000; pub const MS_RMT_MASK: c_ulong = 0x800051; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EWOULDBLOCK: c_int = EAGAIN; pub const SCM_RIGHTS: c_int = 0x01; pub const SCM_CREDENTIALS: c_int = 0x02; pub const PROT_GROWSDOWN: c_int = 0x1000000; pub const PROT_GROWSUP: c_int = 0x2000000; pub const MAP_TYPE: c_int = 0x000f; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const MADV_FREE: c_int = 8; pub const MADV_REMOVE: c_int = 9; pub const MADV_DONTFORK: c_int = 10; pub const MADV_DOFORK: c_int = 11; pub const MADV_MERGEABLE: c_int = 12; pub const MADV_UNMERGEABLE: c_int = 13; pub const MADV_HUGEPAGE: c_int = 14; pub const MADV_NOHUGEPAGE: c_int = 15; pub const MADV_DONTDUMP: c_int = 16; pub const MADV_DODUMP: c_int = 17; pub const MADV_HWPOISON: c_int = 100; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const IFF_UP: c_int = 0x1; pub const IFF_BROADCAST: c_int = 0x2; pub const IFF_DEBUG: c_int = 0x4; pub const IFF_LOOPBACK: c_int = 0x8; pub const IFF_POINTOPOINT: c_int = 0x10; pub const IFF_NOTRAILERS: c_int = 0x20; pub const IFF_RUNNING: c_int = 0x40; pub const IFF_NOARP: c_int = 0x80; pub const IFF_PROMISC: c_int = 0x100; pub const IFF_ALLMULTI: c_int = 0x200; pub const IFF_MASTER: c_int = 0x400; pub const IFF_SLAVE: c_int = 0x800; pub const IFF_MULTICAST: c_int = 0x1000; pub const IFF_PORTSEL: c_int = 0x2000; pub const IFF_AUTOMEDIA: c_int = 0x4000; pub const IFF_DYNAMIC: c_int = 0x8000; pub const IFF_TUN: c_int = 0x0001; pub const IFF_TAP: c_int = 0x0002; pub const IFF_NO_PI: c_int = 0x1000; pub const SOL_IP: c_int = 0; pub const SOL_TCP: c_int = 6; pub const SOL_UDP: c_int = 17; pub const SOL_IPV6: c_int = 41; pub const SOL_ICMPV6: c_int = 58; pub const SOL_RAW: c_int = 255; pub const SOL_DECNET: c_int = 261; pub const SOL_X25: c_int = 262; pub const SOL_PACKET: c_int = 263; pub const SOL_ATM: c_int = 264; pub const SOL_AAL: c_int = 265; pub const SOL_IRDA: c_int = 266; pub const SOL_NETBEUI: c_int = 267; pub const SOL_LLC: c_int = 268; pub const SOL_DCCP: c_int = 269; pub const SOL_NETLINK: c_int = 270; pub const SOL_TIPC: c_int = 271; pub const AF_UNSPEC: c_int = 0; pub const AF_UNIX: c_int = 1; pub const AF_LOCAL: c_int = 1; pub const AF_INET: c_int = 2; pub const AF_AX25: c_int = 3; pub const AF_IPX: c_int = 4; pub const AF_APPLETALK: c_int = 5; pub const AF_NETROM: c_int = 6; pub const AF_BRIDGE: c_int = 7; pub const AF_ATMPVC: c_int = 8; pub const AF_X25: c_int = 9; pub const AF_INET6: c_int = 10; pub const AF_ROSE: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_NETBEUI: c_int = 13; pub const AF_SECURITY: c_int = 14; pub const AF_KEY: c_int = 15; pub const AF_NETLINK: c_int = 16; pub const AF_ROUTE: c_int = AF_NETLINK; pub const AF_PACKET: c_int = 17; pub const AF_ASH: c_int = 18; pub const AF_ECONET: c_int = 19; pub const AF_ATMSVC: c_int = 20; pub const AF_RDS: c_int = 21; pub const AF_SNA: c_int = 22; pub const AF_IRDA: c_int = 23; pub const AF_PPPOX: c_int = 24; pub const AF_WANPIPE: c_int = 25; pub const AF_LLC: c_int = 26; pub const AF_CAN: c_int = 29; pub const AF_TIPC: c_int = 30; pub const AF_BLUETOOTH: c_int = 31; pub const AF_IUCV: c_int = 32; pub const AF_RXRPC: c_int = 33; pub const AF_ISDN: c_int = 34; pub const AF_PHONET: c_int = 35; pub const AF_IEEE802154: c_int = 36; pub const AF_CAIF: c_int = 37; pub const AF_ALG: c_int = 38; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_UNIX: c_int = AF_UNIX; pub const PF_LOCAL: c_int = AF_LOCAL; pub const PF_INET: c_int = AF_INET; pub const PF_AX25: c_int = AF_AX25; pub const PF_IPX: c_int = AF_IPX; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_NETROM: c_int = AF_NETROM; pub const PF_BRIDGE: c_int = AF_BRIDGE; pub const PF_ATMPVC: c_int = AF_ATMPVC; pub const PF_X25: c_int = AF_X25; pub const PF_INET6: c_int = AF_INET6; pub const PF_ROSE: c_int = AF_ROSE; pub const PF_DECnet: c_int = AF_DECnet; pub const PF_NETBEUI: c_int = AF_NETBEUI; pub const PF_SECURITY: c_int = AF_SECURITY; pub const PF_KEY: c_int = AF_KEY; pub const PF_NETLINK: c_int = AF_NETLINK; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_PACKET: c_int = AF_PACKET; pub const PF_ASH: c_int = AF_ASH; pub const PF_ECONET: c_int = AF_ECONET; pub const PF_ATMSVC: c_int = AF_ATMSVC; pub const PF_RDS: c_int = AF_RDS; pub const PF_SNA: c_int = AF_SNA; pub const PF_IRDA: c_int = AF_IRDA; pub const PF_PPPOX: c_int = AF_PPPOX; pub const PF_WANPIPE: c_int = AF_WANPIPE; pub const PF_LLC: c_int = AF_LLC; pub const PF_CAN: c_int = AF_CAN; pub const PF_TIPC: c_int = AF_TIPC; pub const PF_BLUETOOTH: c_int = AF_BLUETOOTH; pub const PF_IUCV: c_int = AF_IUCV; pub const PF_RXRPC: c_int = AF_RXRPC; pub const PF_ISDN: c_int = AF_ISDN; pub const PF_PHONET: c_int = AF_PHONET; pub const PF_IEEE802154: c_int = AF_IEEE802154; pub const PF_CAIF: c_int = AF_CAIF; pub const PF_ALG: c_int = AF_ALG; pub const SOMAXCONN: c_int = 128; pub const MSG_OOB: c_int = 1; pub const MSG_PEEK: c_int = 2; pub const MSG_DONTROUTE: c_int = 4; pub const MSG_CTRUNC: c_int = 8; pub const MSG_TRUNC: c_int = 0x20; pub const MSG_DONTWAIT: c_int = 0x40; pub const MSG_EOR: c_int = 0x80; pub const MSG_WAITALL: c_int = 0x100; pub const MSG_FIN: c_int = 0x200; pub const MSG_SYN: c_int = 0x400; pub const MSG_CONFIRM: c_int = 0x800; pub const MSG_RST: c_int = 0x1000; pub const MSG_ERRQUEUE: c_int = 0x2000; pub const MSG_NOSIGNAL: c_int = 0x4000; pub const MSG_MORE: c_int = 0x8000; pub const MSG_WAITFORONE: c_int = 0x10000; pub const MSG_FASTOPEN: c_int = 0x20000000; pub const MSG_CMSG_CLOEXEC: c_int = 0x40000000; pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const IP_TOS: c_int = 1; pub const IP_TTL: c_int = 2; pub const IP_HDRINCL: c_int = 3; pub const IP_RECVTOS: c_int = 13; pub const IP_FREEBIND: c_int = 15; pub const IP_TRANSPARENT: c_int = 19; pub const IP_MULTICAST_IF: c_int = 32; pub const IP_MULTICAST_TTL: c_int = 33; pub const IP_MULTICAST_LOOP: c_int = 34; pub const IP_ADD_MEMBERSHIP: c_int = 35; pub const IP_DROP_MEMBERSHIP: c_int = 36; pub const IPV6_UNICAST_HOPS: c_int = 16; pub const IPV6_MULTICAST_IF: c_int = 17; pub const IPV6_MULTICAST_HOPS: c_int = 18; pub const IPV6_MULTICAST_LOOP: c_int = 19; pub const IPV6_ADD_MEMBERSHIP: c_int = 20; pub const IPV6_DROP_MEMBERSHIP: c_int = 21; pub const IPV6_V6ONLY: c_int = 26; pub const IPV6_RECVPKTINFO: c_int = 49; pub const IPV6_RECVTCLASS: c_int = 66; pub const IPV6_TCLASS: c_int = 67; pub const TCP_NODELAY: c_int = 1; pub const TCP_MAXSEG: c_int = 2; pub const TCP_CORK: c_int = 3; pub const TCP_KEEPIDLE: c_int = 4; pub const TCP_KEEPINTVL: c_int = 5; pub const TCP_KEEPCNT: c_int = 6; pub const TCP_SYNCNT: c_int = 7; pub const TCP_LINGER2: c_int = 8; pub const TCP_DEFER_ACCEPT: c_int = 9; pub const TCP_WINDOW_CLAMP: c_int = 10; pub const TCP_INFO: c_int = 11; pub const TCP_QUICKACK: c_int = 12; pub const TCP_CONGESTION: c_int = 13; pub const SO_DEBUG: c_int = 1; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; pub const SS_ONSTACK: c_int = 1; pub const SS_DISABLE: c_int = 2; pub const PATH_MAX: c_int = 4096; pub const FD_SETSIZE: usize = 1024; pub const EPOLLIN: c_int = 0x1; pub const EPOLLPRI: c_int = 0x2; pub const EPOLLOUT: c_int = 0x4; pub const EPOLLRDNORM: c_int = 0x40; pub const EPOLLRDBAND: c_int = 0x80; pub const EPOLLWRNORM: c_int = 0x100; pub const EPOLLWRBAND: c_int = 0x200; pub const EPOLLMSG: c_int = 0x400; pub const EPOLLERR: c_int = 0x8; pub const EPOLLHUP: c_int = 0x10; pub const EPOLLET: c_int = 0x80000000; pub const EPOLL_CTL_ADD: c_int = 1; pub const EPOLL_CTL_MOD: c_int = 3; pub const EPOLL_CTL_DEL: c_int = 2; pub const MNT_DETACH: c_int = 0x2; pub const MNT_EXPIRE: c_int = 0x4; pub const Q_GETFMT: c_int = 0x800004; pub const Q_GETINFO: c_int = 0x800005; pub const Q_SETINFO: c_int = 0x800006; pub const QIF_BLIMITS: u32 = 1; pub const QIF_SPACE: u32 = 2; pub const QIF_ILIMITS: u32 = 4; pub const QIF_INODES: u32 = 8; pub const QIF_BTIME: u32 = 16; pub const QIF_ITIME: u32 = 32; pub const QIF_LIMITS: u32 = 5; pub const QIF_USAGE: u32 = 10; pub const QIF_TIMES: u32 = 48; pub const QIF_ALL: u32 = 63; pub const MNT_FORCE: c_int = 0x1; pub const Q_SYNC: c_int = 0x800001; pub const Q_QUOTAON: c_int = 0x800002; pub const Q_QUOTAOFF: c_int = 0x800003; pub const Q_GETQUOTA: c_int = 0x800007; pub const Q_SETQUOTA: c_int = 0x800008; pub const TCIOFF: c_int = 2; pub const TCION: c_int = 3; pub const TCOOFF: c_int = 0; pub const TCOON: c_int = 1; pub const TCIFLUSH: c_int = 0; pub const TCOFLUSH: c_int = 1; pub const TCIOFLUSH: c_int = 2; pub const NL0: c_int = 0x00000000; pub const NL1: c_int = 0x00000100; pub const TAB0: c_int = 0x00000000; pub const CR0: c_int = 0x00000000; pub const FF0: c_int = 0x00000000; pub const BS0: c_int = 0x00000000; pub const VT0: c_int = 0x00000000; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VLNEXT: usize = 15; pub const IGNBRK: crate::tcflag_t = 0x00000001; pub const BRKINT: crate::tcflag_t = 0x00000002; pub const IGNPAR: crate::tcflag_t = 0x00000004; pub const PARMRK: crate::tcflag_t = 0x00000008; pub const INPCK: crate::tcflag_t = 0x00000010; pub const ISTRIP: crate::tcflag_t = 0x00000020; pub const INLCR: crate::tcflag_t = 0x00000040; pub const IGNCR: crate::tcflag_t = 0x00000080; pub const ICRNL: crate::tcflag_t = 0x00000100; pub const IXANY: crate::tcflag_t = 0x00000800; pub const IMAXBEL: crate::tcflag_t = 0x00002000; pub const OPOST: crate::tcflag_t = 0x1; pub const CS5: crate::tcflag_t = 0x00000000; pub const CRTSCTS: crate::tcflag_t = 0x80000000; pub const ECHO: crate::tcflag_t = 0x00000008; pub const OCRNL: crate::tcflag_t = 0o000010; pub const ONOCR: crate::tcflag_t = 0o000020; pub const ONLRET: crate::tcflag_t = 0o000040; pub const OFILL: crate::tcflag_t = 0o000100; pub const OFDEL: crate::tcflag_t = 0o000200; pub const CLONE_VM: c_int = 0x100; pub const CLONE_FS: c_int = 0x200; pub const CLONE_FILES: c_int = 0x400; pub const CLONE_SIGHAND: c_int = 0x800; pub const CLONE_PTRACE: c_int = 0x2000; pub const CLONE_VFORK: c_int = 0x4000; pub const CLONE_PARENT: c_int = 0x8000; pub const CLONE_THREAD: c_int = 0x10000; pub const CLONE_NEWNS: c_int = 0x20000; pub const CLONE_SYSVSEM: c_int = 0x40000; pub const CLONE_SETTLS: c_int = 0x80000; pub const CLONE_PARENT_SETTID: c_int = 0x100000; pub const CLONE_CHILD_CLEARTID: c_int = 0x200000; pub const CLONE_DETACHED: c_int = 0x400000; pub const CLONE_UNTRACED: c_int = 0x800000; pub const CLONE_CHILD_SETTID: c_int = 0x01000000; pub const CLONE_NEWUTS: c_int = 0x04000000; pub const CLONE_NEWIPC: c_int = 0x08000000; pub const CLONE_NEWUSER: c_int = 0x10000000; pub const CLONE_NEWPID: c_int = 0x20000000; pub const CLONE_NEWNET: c_int = 0x40000000; pub const CLONE_IO: c_int = 0x80000000; pub const CLONE_NEWCGROUP: c_int = 0x02000000; pub const WNOHANG: c_int = 0x00000001; pub const WUNTRACED: c_int = 0x00000002; pub const WSTOPPED: c_int = WUNTRACED; pub const WEXITED: c_int = 0x00000004; pub const WCONTINUED: c_int = 0x00000008; pub const WNOWAIT: c_int = 0x01000000; // Options set using PTRACE_SETOPTIONS. pub const PTRACE_O_TRACESYSGOOD: c_int = 0x00000001; pub const PTRACE_O_TRACEFORK: c_int = 0x00000002; pub const PTRACE_O_TRACEVFORK: c_int = 0x00000004; pub const PTRACE_O_TRACECLONE: c_int = 0x00000008; pub const PTRACE_O_TRACEEXEC: c_int = 0x00000010; pub const PTRACE_O_TRACEVFORKDONE: c_int = 0x00000020; pub const PTRACE_O_TRACEEXIT: c_int = 0x00000040; pub const PTRACE_O_TRACESECCOMP: c_int = 0x00000080; pub const PTRACE_O_EXITKILL: c_int = 0x00100000; pub const PTRACE_O_SUSPEND_SECCOMP: c_int = 0x00200000; pub const PTRACE_O_MASK: c_int = 0x003000ff; // Wait extended result codes for the above trace options. pub const PTRACE_EVENT_FORK: c_int = 1; pub const PTRACE_EVENT_VFORK: c_int = 2; pub const PTRACE_EVENT_CLONE: c_int = 3; pub const PTRACE_EVENT_EXEC: c_int = 4; pub const PTRACE_EVENT_VFORK_DONE: c_int = 5; pub const PTRACE_EVENT_EXIT: c_int = 6; pub const PTRACE_EVENT_SECCOMP: c_int = 7; // PTRACE_EVENT_STOP was added to glibc in 2.26 // pub const PTRACE_EVENT_STOP: c_int = 128; pub const __WNOTHREAD: c_int = 0x20000000; pub const __WALL: c_int = 0x40000000; pub const __WCLONE: c_int = 0x80000000; pub const SPLICE_F_MOVE: c_uint = 0x01; pub const SPLICE_F_NONBLOCK: c_uint = 0x02; pub const SPLICE_F_MORE: c_uint = 0x04; pub const SPLICE_F_GIFT: c_uint = 0x08; pub const RTLD_LOCAL: c_int = 0; pub const RTLD_LAZY: c_int = 1; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_RANDOM: c_int = 1; pub const POSIX_FADV_SEQUENTIAL: c_int = 2; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const AT_FDCWD: c_int = -100; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x100; pub const AT_REMOVEDIR: c_int = 0x200; pub const AT_EACCESS: c_int = 0x200; pub const AT_SYMLINK_FOLLOW: c_int = 0x400; pub const AT_NO_AUTOMOUNT: c_int = 0x800; pub const AT_EMPTY_PATH: c_int = 0x1000; pub const LOG_CRON: c_int = 9 << 3; pub const LOG_AUTHPRIV: c_int = 10 << 3; pub const LOG_FTP: c_int = 11 << 3; pub const LOG_PERROR: c_int = 0x20; pub const PIPE_BUF: usize = 4096; pub const SI_LOAD_SHIFT: c_uint = 16; pub const CLD_EXITED: c_int = 1; pub const CLD_KILLED: c_int = 2; pub const CLD_DUMPED: c_int = 3; pub const CLD_TRAPPED: c_int = 4; pub const CLD_STOPPED: c_int = 5; pub const CLD_CONTINUED: c_int = 6; pub const SIGEV_SIGNAL: c_int = 0; pub const SIGEV_NONE: c_int = 1; pub const SIGEV_THREAD: c_int = 2; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const UTIME_OMIT: c_long = 1073741822; pub const UTIME_NOW: c_long = 1073741823; pub const POLLIN: c_short = 0x1; pub const POLLPRI: c_short = 0x2; pub const POLLOUT: c_short = 0x4; pub const POLLERR: c_short = 0x8; pub const POLLHUP: c_short = 0x10; pub const POLLNVAL: c_short = 0x20; pub const POLLRDNORM: c_short = 0x040; pub const POLLRDBAND: c_short = 0x080; pub const ABDAY_1: crate::nl_item = 0x20000; pub const ABDAY_2: crate::nl_item = 0x20001; pub const ABDAY_3: crate::nl_item = 0x20002; pub const ABDAY_4: crate::nl_item = 0x20003; pub const ABDAY_5: crate::nl_item = 0x20004; pub const ABDAY_6: crate::nl_item = 0x20005; pub const ABDAY_7: crate::nl_item = 0x20006; pub const DAY_1: crate::nl_item = 0x20007; pub const DAY_2: crate::nl_item = 0x20008; pub const DAY_3: crate::nl_item = 0x20009; pub const DAY_4: crate::nl_item = 0x2000A; pub const DAY_5: crate::nl_item = 0x2000B; pub const DAY_6: crate::nl_item = 0x2000C; pub const DAY_7: crate::nl_item = 0x2000D; pub const ABMON_1: crate::nl_item = 0x2000E; pub const ABMON_2: crate::nl_item = 0x2000F; pub const ABMON_3: crate::nl_item = 0x20010; pub const ABMON_4: crate::nl_item = 0x20011; pub const ABMON_5: crate::nl_item = 0x20012; pub const ABMON_6: crate::nl_item = 0x20013; pub const ABMON_7: crate::nl_item = 0x20014; pub const ABMON_8: crate::nl_item = 0x20015; pub const ABMON_9: crate::nl_item = 0x20016; pub const ABMON_10: crate::nl_item = 0x20017; pub const ABMON_11: crate::nl_item = 0x20018; pub const ABMON_12: crate::nl_item = 0x20019; pub const MON_1: crate::nl_item = 0x2001A; pub const MON_2: crate::nl_item = 0x2001B; pub const MON_3: crate::nl_item = 0x2001C; pub const MON_4: crate::nl_item = 0x2001D; pub const MON_5: crate::nl_item = 0x2001E; pub const MON_6: crate::nl_item = 0x2001F; pub const MON_7: crate::nl_item = 0x20020; pub const MON_8: crate::nl_item = 0x20021; pub const MON_9: crate::nl_item = 0x20022; pub const MON_10: crate::nl_item = 0x20023; pub const MON_11: crate::nl_item = 0x20024; pub const MON_12: crate::nl_item = 0x20025; pub const AM_STR: crate::nl_item = 0x20026; pub const PM_STR: crate::nl_item = 0x20027; pub const D_T_FMT: crate::nl_item = 0x20028; pub const D_FMT: crate::nl_item = 0x20029; pub const T_FMT: crate::nl_item = 0x2002A; pub const T_FMT_AMPM: crate::nl_item = 0x2002B; pub const ERA: crate::nl_item = 0x2002C; pub const ERA_D_FMT: crate::nl_item = 0x2002E; pub const ALT_DIGITS: crate::nl_item = 0x2002F; pub const ERA_D_T_FMT: crate::nl_item = 0x20030; pub const ERA_T_FMT: crate::nl_item = 0x20031; pub const CODESET: crate::nl_item = 14; pub const CRNCYSTR: crate::nl_item = 0x4000F; pub const RUSAGE_THREAD: c_int = 1; pub const RUSAGE_CHILDREN: c_int = -1; pub const RADIXCHAR: crate::nl_item = 0x10000; pub const THOUSEP: crate::nl_item = 0x10001; pub const YESEXPR: crate::nl_item = 0x50000; pub const NOEXPR: crate::nl_item = 0x50001; pub const YESSTR: crate::nl_item = 0x50002; pub const NOSTR: crate::nl_item = 0x50003; pub const FILENAME_MAX: c_uint = 4096; pub const L_tmpnam: c_uint = 20; pub const _PC_LINK_MAX: c_int = 0; pub const _PC_MAX_CANON: c_int = 1; pub const _PC_MAX_INPUT: c_int = 2; pub const _PC_NAME_MAX: c_int = 3; pub const _PC_PATH_MAX: c_int = 4; pub const _PC_PIPE_BUF: c_int = 5; pub const _PC_CHOWN_RESTRICTED: c_int = 6; pub const _PC_NO_TRUNC: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_SYNC_IO: c_int = 9; pub const _PC_ASYNC_IO: c_int = 10; pub const _PC_PRIO_IO: c_int = 11; pub const _PC_SOCK_MAXBUF: c_int = 12; pub const _PC_FILESIZEBITS: c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: c_int = 16; pub const _PC_REC_XFER_ALIGN: c_int = 17; pub const _PC_ALLOC_SIZE_MIN: c_int = 18; pub const _PC_SYMLINK_MAX: c_int = 19; pub const _PC_2_SYMLINKS: c_int = 20; pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_STREAM_MAX: c_int = 5; pub const _SC_TZNAME_MAX: c_int = 6; pub const _SC_JOB_CONTROL: c_int = 7; pub const _SC_SAVED_IDS: c_int = 8; pub const _SC_REALTIME_SIGNALS: c_int = 9; pub const _SC_PRIORITY_SCHEDULING: c_int = 10; pub const _SC_TIMERS: c_int = 11; pub const _SC_ASYNCHRONOUS_IO: c_int = 12; pub const _SC_PRIORITIZED_IO: c_int = 13; pub const _SC_SYNCHRONIZED_IO: c_int = 14; pub const _SC_FSYNC: c_int = 15; pub const _SC_MAPPED_FILES: c_int = 16; pub const _SC_MEMLOCK: c_int = 17; pub const _SC_MEMLOCK_RANGE: c_int = 18; pub const _SC_MEMORY_PROTECTION: c_int = 19; pub const _SC_MESSAGE_PASSING: c_int = 20; pub const _SC_SEMAPHORES: c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 22; pub const _SC_AIO_LISTIO_MAX: c_int = 23; pub const _SC_AIO_MAX: c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 25; pub const _SC_DELAYTIMER_MAX: c_int = 26; pub const _SC_MQ_OPEN_MAX: c_int = 27; pub const _SC_MQ_PRIO_MAX: c_int = 28; pub const _SC_VERSION: c_int = 29; pub const _SC_PAGESIZE: c_int = 30; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_RTSIG_MAX: c_int = 31; pub const _SC_SEM_NSEMS_MAX: c_int = 32; pub const _SC_SEM_VALUE_MAX: c_int = 33; pub const _SC_SIGQUEUE_MAX: c_int = 34; pub const _SC_TIMER_MAX: c_int = 35; pub const _SC_BC_BASE_MAX: c_int = 36; pub const _SC_BC_DIM_MAX: c_int = 37; pub const _SC_BC_SCALE_MAX: c_int = 38; pub const _SC_BC_STRING_MAX: c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: c_int = 40; pub const _SC_EXPR_NEST_MAX: c_int = 42; pub const _SC_LINE_MAX: c_int = 43; pub const _SC_RE_DUP_MAX: c_int = 44; pub const _SC_2_VERSION: c_int = 46; pub const _SC_2_C_BIND: c_int = 47; pub const _SC_2_C_DEV: c_int = 48; pub const _SC_2_FORT_DEV: c_int = 49; pub const _SC_2_FORT_RUN: c_int = 50; pub const _SC_2_SW_DEV: c_int = 51; pub const _SC_2_LOCALEDEF: c_int = 52; pub const _SC_UIO_MAXIOV: c_int = 60; pub const _SC_IOV_MAX: c_int = 60; pub const _SC_THREADS: c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: c_int = 70; pub const _SC_LOGIN_NAME_MAX: c_int = 71; pub const _SC_TTY_NAME_MAX: c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73; pub const _SC_THREAD_KEYS_MAX: c_int = 74; pub const _SC_THREAD_STACK_MIN: c_int = 75; pub const _SC_THREAD_THREADS_MAX: c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: c_int = 82; pub const _SC_NPROCESSORS_CONF: c_int = 83; pub const _SC_NPROCESSORS_ONLN: c_int = 84; pub const _SC_PHYS_PAGES: c_int = 85; pub const _SC_AVPHYS_PAGES: c_int = 86; pub const _SC_ATEXIT_MAX: c_int = 87; pub const _SC_PASS_MAX: c_int = 88; pub const _SC_XOPEN_VERSION: c_int = 89; pub const _SC_XOPEN_XCU_VERSION: c_int = 90; pub const _SC_XOPEN_UNIX: c_int = 91; pub const _SC_XOPEN_CRYPT: c_int = 92; pub const _SC_XOPEN_ENH_I18N: c_int = 93; pub const _SC_XOPEN_SHM: c_int = 94; pub const _SC_2_CHAR_TERM: c_int = 95; pub const _SC_2_UPE: c_int = 97; pub const _SC_XOPEN_XPG2: c_int = 98; pub const _SC_XOPEN_XPG3: c_int = 99; pub const _SC_XOPEN_XPG4: c_int = 100; pub const _SC_NZERO: c_int = 109; pub const _SC_XBS5_ILP32_OFF32: c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 126; pub const _SC_XBS5_LP64_OFF64: c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 128; pub const _SC_XOPEN_LEGACY: c_int = 129; pub const _SC_XOPEN_REALTIME: c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131; pub const _SC_ADVISORY_INFO: c_int = 132; pub const _SC_BARRIERS: c_int = 133; pub const _SC_CLOCK_SELECTION: c_int = 137; pub const _SC_CPUTIME: c_int = 138; pub const _SC_THREAD_CPUTIME: c_int = 139; pub const _SC_MONOTONIC_CLOCK: c_int = 149; pub const _SC_READER_WRITER_LOCKS: c_int = 153; pub const _SC_SPIN_LOCKS: c_int = 154; pub const _SC_REGEXP: c_int = 155; pub const _SC_SHELL: c_int = 157; pub const _SC_SPAWN: c_int = 159; pub const _SC_SPORADIC_SERVER: c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 161; pub const _SC_TIMEOUTS: c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 165; pub const _SC_2_PBS: c_int = 168; pub const _SC_2_PBS_ACCOUNTING: c_int = 169; pub const _SC_2_PBS_LOCATE: c_int = 170; pub const _SC_2_PBS_MESSAGE: c_int = 171; pub const _SC_2_PBS_TRACK: c_int = 172; pub const _SC_SYMLOOP_MAX: c_int = 173; pub const _SC_STREAMS: c_int = 174; pub const _SC_2_PBS_CHECKPOINT: c_int = 175; pub const _SC_V6_ILP32_OFF32: c_int = 176; pub const _SC_V6_ILP32_OFFBIG: c_int = 177; pub const _SC_V6_LP64_OFF64: c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: c_int = 179; pub const _SC_HOST_NAME_MAX: c_int = 180; pub const _SC_TRACE: c_int = 181; pub const _SC_TRACE_EVENT_FILTER: c_int = 182; pub const _SC_TRACE_INHERIT: c_int = 183; pub const _SC_TRACE_LOG: c_int = 184; pub const _SC_IPV6: c_int = 235; pub const _SC_RAW_SOCKETS: c_int = 236; pub const _SC_V7_ILP32_OFF32: c_int = 237; pub const _SC_V7_ILP32_OFFBIG: c_int = 238; pub const _SC_V7_LP64_OFF64: c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: c_int = 240; pub const _SC_SS_REPL_MAX: c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 242; pub const _SC_TRACE_NAME_MAX: c_int = 243; pub const _SC_TRACE_SYS_MAX: c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 245; pub const _SC_XOPEN_STREAMS: c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 248; pub const RLIM_SAVED_MAX: crate::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: crate::rlim_t = RLIM_INFINITY; pub const GLOB_ERR: c_int = 1 << 0; pub const GLOB_MARK: c_int = 1 << 1; pub const GLOB_NOSORT: c_int = 1 << 2; pub const GLOB_DOOFFS: c_int = 1 << 3; pub const GLOB_NOCHECK: c_int = 1 << 4; pub const GLOB_APPEND: c_int = 1 << 5; pub const GLOB_NOESCAPE: c_int = 1 << 6; pub const GLOB_NOSPACE: c_int = 1; pub const GLOB_ABORTED: c_int = 2; pub const GLOB_NOMATCH: c_int = 3; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 1; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const S_IEXEC: mode_t = 0o0100; pub const S_IWRITE: mode_t = 0o0200; pub const S_IREAD: mode_t = 0o0400; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const IFF_LOWER_UP: c_int = 0x10000; pub const IFF_DORMANT: c_int = 0x20000; pub const IFF_ECHO: c_int = 0x40000; pub const ST_RDONLY: c_ulong = 1; pub const ST_NOSUID: c_ulong = 2; pub const ST_NODEV: c_ulong = 4; pub const ST_NOEXEC: c_ulong = 8; pub const ST_SYNCHRONOUS: c_ulong = 16; pub const ST_MANDLOCK: c_ulong = 64; pub const ST_WRITE: c_ulong = 128; pub const ST_APPEND: c_ulong = 256; pub const ST_IMMUTABLE: c_ulong = 512; pub const ST_NOATIME: c_ulong = 1024; pub const ST_NODIRATIME: c_ulong = 2048; pub const RTLD_NEXT: *mut c_void = -1i64 as *mut c_void; pub const RTLD_DEFAULT: *mut c_void = 0i64 as *mut c_void; pub const RTLD_NODELETE: c_int = 0x1000; pub const RTLD_NOW: c_int = 0x2; pub const TCP_MD5SIG: c_int = 14; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { size: [0; __SIZEOF_PTHREAD_RWLOCK_T], }; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_PROCESS_PRIVATE: c_int = 0; pub const PTHREAD_PROCESS_SHARED: c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const RENAME_NOREPLACE: c_int = 1; pub const RENAME_EXCHANGE: c_int = 2; pub const RENAME_WHITEOUT: c_int = 4; pub const SCHED_OTHER: c_int = 0; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const SCHED_BATCH: c_int = 3; pub const SCHED_IDLE: c_int = 5; // netinet/in.h // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// Hop-by-hop option header pub const IPPROTO_HOPOPTS: c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: c_int = 2; /// for compatibility pub const IPPROTO_IPIP: c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// exterior gateway protocol pub const IPPROTO_EGP: c_int = 8; /// pup pub const IPPROTO_PUP: c_int = 12; // IPPROTO_UDP defined in src/unix/mod.rs /// xns idp pub const IPPROTO_IDP: c_int = 22; /// tp-4 w/ class negotiation pub const IPPROTO_TP: c_int = 29; /// DCCP pub const IPPROTO_DCCP: c_int = 33; // IPPROTO_IPV6 defined in src/unix/mod.rs /// IP6 routing header pub const IPPROTO_ROUTING: c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: c_int = 44; /// resource reservation pub const IPPROTO_RSVP: c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: c_int = 47; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: c_int = 51; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: c_int = 60; pub const IPPROTO_MTP: c_int = 92; pub const IPPROTO_BEETPH: c_int = 94; /// encapsulation header pub const IPPROTO_ENCAP: c_int = 98; /// Protocol indep. multicast pub const IPPROTO_PIM: c_int = 103; /// IP Payload Comp. Protocol pub const IPPROTO_COMP: c_int = 108; /// SCTP pub const IPPROTO_SCTP: c_int = 132; pub const IPPROTO_MH: c_int = 135; pub const IPPROTO_UDPLITE: c_int = 136; pub const IPPROTO_MPLS: c_int = 137; /// raw IP packet pub const IPPROTO_RAW: c_int = 255; pub const IPPROTO_MAX: c_int = 256; pub const AF_IB: c_int = 27; pub const AF_MPLS: c_int = 28; pub const AF_NFC: c_int = 39; pub const AF_VSOCK: c_int = 40; pub const PF_IB: c_int = AF_IB; pub const PF_MPLS: c_int = AF_MPLS; pub const PF_NFC: c_int = AF_NFC; pub const PF_VSOCK: c_int = AF_VSOCK; // System V IPC pub const IPC_PRIVATE: crate::key_t = 0; pub const IPC_CREAT: c_int = 0o1000; pub const IPC_EXCL: c_int = 0o2000; pub const IPC_NOWAIT: c_int = 0o4000; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 1; pub const IPC_STAT: c_int = 2; pub const IPC_INFO: c_int = 3; pub const MSG_STAT: c_int = 11; pub const MSG_INFO: c_int = 12; pub const MSG_NOERROR: c_int = 0o10000; pub const MSG_EXCEPT: c_int = 0o20000; pub const MSG_COPY: c_int = 0o40000; pub const SHM_R: c_int = 0o400; pub const SHM_W: c_int = 0o200; pub const SHM_RDONLY: c_int = 0o10000; pub const SHM_RND: c_int = 0o20000; pub const SHM_REMAP: c_int = 0o40000; pub const SHM_EXEC: c_int = 0o100000; pub const SHM_LOCK: c_int = 11; pub const SHM_UNLOCK: c_int = 12; pub const SHM_HUGETLB: c_int = 0o4000; pub const SHM_NORESERVE: c_int = 0o10000; pub const EPOLLRDHUP: c_int = 0x2000; pub const EPOLLEXCLUSIVE: c_int = 0x10000000; pub const EPOLLONESHOT: c_int = 0x40000000; pub const QFMT_VFS_OLD: c_int = 1; pub const QFMT_VFS_V0: c_int = 2; pub const QFMT_VFS_V1: c_int = 4; pub const EFD_SEMAPHORE: c_int = 0x1; pub const LOG_NFACILITIES: c_int = 24; pub const SEM_FAILED: *mut crate::sem_t = 0 as *mut sem_t; pub const RB_AUTOBOOT: c_int = 0x01234567u32 as i32; pub const RB_HALT_SYSTEM: c_int = 0xcdef0123u32 as i32; pub const RB_ENABLE_CAD: c_int = 0x89abcdefu32 as i32; pub const RB_DISABLE_CAD: c_int = 0x00000000u32 as i32; pub const RB_POWER_OFF: c_int = 0x4321fedcu32 as i32; pub const RB_SW_SUSPEND: c_int = 0xd000fce2u32 as i32; pub const RB_KEXEC: c_int = 0x45584543u32 as i32; pub const AI_PASSIVE: c_int = 0x0001; pub const AI_CANONNAME: c_int = 0x0002; pub const AI_NUMERICHOST: c_int = 0x0004; pub const AI_V4MAPPED: c_int = 0x0008; pub const AI_ALL: c_int = 0x0010; pub const AI_ADDRCONFIG: c_int = 0x0020; pub const AI_NUMERICSERV: c_int = 0x0400; pub const EAI_BADFLAGS: c_int = -1; pub const EAI_NONAME: c_int = -2; pub const EAI_AGAIN: c_int = -3; pub const EAI_FAIL: c_int = -4; pub const EAI_FAMILY: c_int = -6; pub const EAI_SOCKTYPE: c_int = -7; pub const EAI_SERVICE: c_int = -8; pub const EAI_MEMORY: c_int = -10; pub const EAI_OVERFLOW: c_int = -12; pub const NI_NUMERICHOST: c_int = 1; pub const NI_NUMERICSERV: c_int = 2; pub const NI_NOFQDN: c_int = 4; pub const NI_NAMEREQD: c_int = 8; pub const NI_DGRAM: c_int = 16; pub const SYNC_FILE_RANGE_WAIT_BEFORE: c_uint = 1; pub const SYNC_FILE_RANGE_WRITE: c_uint = 2; pub const SYNC_FILE_RANGE_WAIT_AFTER: c_uint = 4; pub const EAI_SYSTEM: c_int = -11; pub const AIO_CANCELED: c_int = 0; pub const AIO_NOTCANCELED: c_int = 1; pub const AIO_ALLDONE: c_int = 2; pub const LIO_READ: c_int = 0; pub const LIO_WRITE: c_int = 1; pub const LIO_NOP: c_int = 2; pub const LIO_WAIT: c_int = 0; pub const LIO_NOWAIT: c_int = 1; pub const MREMAP_MAYMOVE: c_int = 1; pub const MREMAP_FIXED: c_int = 2; pub const PR_SET_PDEATHSIG: c_int = 1; pub const PR_GET_PDEATHSIG: c_int = 2; pub const PR_GET_DUMPABLE: c_int = 3; pub const PR_SET_DUMPABLE: c_int = 4; pub const PR_GET_UNALIGN: c_int = 5; pub const PR_SET_UNALIGN: c_int = 6; pub const PR_UNALIGN_NOPRINT: c_int = 1; pub const PR_UNALIGN_SIGBUS: c_int = 2; pub const PR_GET_KEEPCAPS: c_int = 7; pub const PR_SET_KEEPCAPS: c_int = 8; pub const PR_GET_FPEMU: c_int = 9; pub const PR_SET_FPEMU: c_int = 10; pub const PR_FPEMU_NOPRINT: c_int = 1; pub const PR_FPEMU_SIGFPE: c_int = 2; pub const PR_GET_FPEXC: c_int = 11; pub const PR_SET_FPEXC: c_int = 12; pub const PR_FP_EXC_SW_ENABLE: c_int = 0x80; pub const PR_FP_EXC_DIV: c_int = 0x010000; pub const PR_FP_EXC_OVF: c_int = 0x020000; pub const PR_FP_EXC_UND: c_int = 0x040000; pub const PR_FP_EXC_RES: c_int = 0x080000; pub const PR_FP_EXC_INV: c_int = 0x100000; pub const PR_FP_EXC_DISABLED: c_int = 0; pub const PR_FP_EXC_NONRECOV: c_int = 1; pub const PR_FP_EXC_ASYNC: c_int = 2; pub const PR_FP_EXC_PRECISE: c_int = 3; pub const PR_GET_TIMING: c_int = 13; pub const PR_SET_TIMING: c_int = 14; pub const PR_TIMING_STATISTICAL: c_int = 0; pub const PR_TIMING_TIMESTAMP: c_int = 1; pub const PR_SET_NAME: c_int = 15; pub const PR_GET_NAME: c_int = 16; pub const PR_GET_ENDIAN: c_int = 19; pub const PR_SET_ENDIAN: c_int = 20; pub const PR_ENDIAN_BIG: c_int = 0; pub const PR_ENDIAN_LITTLE: c_int = 1; pub const PR_ENDIAN_PPC_LITTLE: c_int = 2; pub const PR_GET_SECCOMP: c_int = 21; pub const PR_SET_SECCOMP: c_int = 22; pub const PR_CAPBSET_READ: c_int = 23; pub const PR_CAPBSET_DROP: c_int = 24; pub const PR_GET_TSC: c_int = 25; pub const PR_SET_TSC: c_int = 26; pub const PR_TSC_ENABLE: c_int = 1; pub const PR_TSC_SIGSEGV: c_int = 2; pub const PR_GET_SECUREBITS: c_int = 27; pub const PR_SET_SECUREBITS: c_int = 28; pub const PR_SET_TIMERSLACK: c_int = 29; pub const PR_GET_TIMERSLACK: c_int = 30; pub const PR_TASK_PERF_EVENTS_DISABLE: c_int = 31; pub const PR_TASK_PERF_EVENTS_ENABLE: c_int = 32; pub const PR_MCE_KILL: c_int = 33; pub const PR_MCE_KILL_CLEAR: c_int = 0; pub const PR_MCE_KILL_SET: c_int = 1; pub const PR_MCE_KILL_LATE: c_int = 0; pub const PR_MCE_KILL_EARLY: c_int = 1; pub const PR_MCE_KILL_DEFAULT: c_int = 2; pub const PR_MCE_KILL_GET: c_int = 34; pub const PR_SET_MM: c_int = 35; pub const PR_SET_MM_START_CODE: c_int = 1; pub const PR_SET_MM_END_CODE: c_int = 2; pub const PR_SET_MM_START_DATA: c_int = 3; pub const PR_SET_MM_END_DATA: c_int = 4; pub const PR_SET_MM_START_STACK: c_int = 5; pub const PR_SET_MM_START_BRK: c_int = 6; pub const PR_SET_MM_BRK: c_int = 7; pub const PR_SET_MM_ARG_START: c_int = 8; pub const PR_SET_MM_ARG_END: c_int = 9; pub const PR_SET_MM_ENV_START: c_int = 10; pub const PR_SET_MM_ENV_END: c_int = 11; pub const PR_SET_MM_AUXV: c_int = 12; pub const PR_SET_MM_EXE_FILE: c_int = 13; pub const PR_SET_MM_MAP: c_int = 14; pub const PR_SET_MM_MAP_SIZE: c_int = 15; pub const PR_SET_PTRACER: c_int = 0x59616d61; pub const PR_SET_PTRACER_ANY: c_ulong = 0xffffffffffffffff; pub const PR_SET_CHILD_SUBREAPER: c_int = 36; pub const PR_GET_CHILD_SUBREAPER: c_int = 37; pub const PR_SET_NO_NEW_PRIVS: c_int = 38; pub const PR_GET_NO_NEW_PRIVS: c_int = 39; pub const PR_GET_TID_ADDRESS: c_int = 40; pub const PR_SET_THP_DISABLE: c_int = 41; pub const PR_GET_THP_DISABLE: c_int = 42; pub const PR_MPX_ENABLE_MANAGEMENT: c_int = 43; pub const PR_MPX_DISABLE_MANAGEMENT: c_int = 44; pub const PR_SET_FP_MODE: c_int = 45; pub const PR_GET_FP_MODE: c_int = 46; pub const PR_FP_MODE_FR: c_int = 1 << 0; pub const PR_FP_MODE_FRE: c_int = 1 << 1; pub const PR_CAP_AMBIENT: c_int = 47; pub const PR_CAP_AMBIENT_IS_SET: c_int = 1; pub const PR_CAP_AMBIENT_RAISE: c_int = 2; pub const PR_CAP_AMBIENT_LOWER: c_int = 3; pub const PR_CAP_AMBIENT_CLEAR_ALL: c_int = 4; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; pub const ITIMER_PROF: c_int = 2; pub const TFD_CLOEXEC: c_int = O_CLOEXEC; pub const TFD_NONBLOCK: c_int = O_NONBLOCK; pub const TFD_TIMER_ABSTIME: c_int = 1; pub const XATTR_CREATE: c_int = 0x1; pub const XATTR_REPLACE: c_int = 0x2; pub const _POSIX_VDISABLE: crate::cc_t = 0; pub const FALLOC_FL_KEEP_SIZE: c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: c_int = 0x02; pub const FALLOC_FL_COLLAPSE_RANGE: c_int = 0x08; pub const FALLOC_FL_ZERO_RANGE: c_int = 0x10; pub const FALLOC_FL_INSERT_RANGE: c_int = 0x20; pub const FALLOC_FL_UNSHARE_RANGE: c_int = 0x40; // On Linux, libc doesn't define this constant, libattr does instead. // We still define it for Linux as it's defined by libc on other platforms, // and it's mentioned in the man pages for getxattr and setxattr. pub const ENOATTR: c_int = crate::ENODATA; pub const SO_ORIGINAL_DST: c_int = 80; pub const IUTF8: crate::tcflag_t = 0x00004000; pub const CMSPAR: crate::tcflag_t = 0o10000000000; pub const MFD_CLOEXEC: c_uint = 0x0001; pub const MFD_ALLOW_SEALING: c_uint = 0x0002; // these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has // the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32 // so we can use that type here to avoid having to cast. pub const PT_NULL: u32 = 0; pub const PT_LOAD: u32 = 1; pub const PT_DYNAMIC: u32 = 2; pub const PT_INTERP: u32 = 3; pub const PT_NOTE: u32 = 4; pub const PT_SHLIB: u32 = 5; pub const PT_PHDR: u32 = 6; pub const PT_TLS: u32 = 7; pub const PT_NUM: u32 = 8; pub const PT_LOOS: u32 = 0x60000000; pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; pub const PT_GNU_STACK: u32 = 0x6474e551; pub const PT_GNU_RELRO: u32 = 0x6474e552; // Ethernet protocol IDs. pub const ETH_P_LOOP: c_int = 0x0060; pub const ETH_P_PUP: c_int = 0x0200; pub const ETH_P_PUPAT: c_int = 0x0201; pub const ETH_P_IP: c_int = 0x0800; pub const ETH_P_X25: c_int = 0x0805; pub const ETH_P_ARP: c_int = 0x0806; pub const ETH_P_BPQ: c_int = 0x08FF; pub const ETH_P_IEEEPUP: c_int = 0x0a00; pub const ETH_P_IEEEPUPAT: c_int = 0x0a01; pub const ETH_P_BATMAN: c_int = 0x4305; pub const ETH_P_DEC: c_int = 0x6000; pub const ETH_P_DNA_DL: c_int = 0x6001; pub const ETH_P_DNA_RC: c_int = 0x6002; pub const ETH_P_DNA_RT: c_int = 0x6003; pub const ETH_P_LAT: c_int = 0x6004; pub const ETH_P_DIAG: c_int = 0x6005; pub const ETH_P_CUST: c_int = 0x6006; pub const ETH_P_SCA: c_int = 0x6007; pub const ETH_P_TEB: c_int = 0x6558; pub const ETH_P_RARP: c_int = 0x8035; pub const ETH_P_ATALK: c_int = 0x809B; pub const ETH_P_AARP: c_int = 0x80F3; pub const ETH_P_8021Q: c_int = 0x8100; pub const ETH_P_IPX: c_int = 0x8137; pub const ETH_P_IPV6: c_int = 0x86DD; pub const ETH_P_PAUSE: c_int = 0x8808; pub const ETH_P_SLOW: c_int = 0x8809; pub const ETH_P_WCCP: c_int = 0x883E; pub const ETH_P_MPLS_UC: c_int = 0x8847; pub const ETH_P_MPLS_MC: c_int = 0x8848; pub const ETH_P_ATMMPOA: c_int = 0x884c; pub const ETH_P_PPP_DISC: c_int = 0x8863; pub const ETH_P_PPP_SES: c_int = 0x8864; pub const ETH_P_LINK_CTL: c_int = 0x886c; pub const ETH_P_ATMFATE: c_int = 0x8884; pub const ETH_P_PAE: c_int = 0x888E; pub const ETH_P_AOE: c_int = 0x88A2; pub const ETH_P_8021AD: c_int = 0x88A8; pub const ETH_P_802_EX1: c_int = 0x88B5; pub const ETH_P_TIPC: c_int = 0x88CA; pub const ETH_P_8021AH: c_int = 0x88E7; pub const ETH_P_MVRP: c_int = 0x88F5; pub const ETH_P_1588: c_int = 0x88F7; pub const ETH_P_PRP: c_int = 0x88FB; pub const ETH_P_FCOE: c_int = 0x8906; pub const ETH_P_TDLS: c_int = 0x890D; pub const ETH_P_FIP: c_int = 0x8914; pub const ETH_P_80221: c_int = 0x8917; pub const ETH_P_LOOPBACK: c_int = 0x9000; pub const ETH_P_QINQ1: c_int = 0x9100; pub const ETH_P_QINQ2: c_int = 0x9200; pub const ETH_P_QINQ3: c_int = 0x9300; pub const ETH_P_EDSA: c_int = 0xDADA; pub const ETH_P_AF_IUCV: c_int = 0xFBFB; pub const ETH_P_802_3_MIN: c_int = 0x0600; pub const ETH_P_802_3: c_int = 0x0001; pub const ETH_P_AX25: c_int = 0x0002; pub const ETH_P_ALL: c_int = 0x0003; pub const ETH_P_802_2: c_int = 0x0004; pub const ETH_P_SNAP: c_int = 0x0005; pub const ETH_P_DDCMP: c_int = 0x0006; pub const ETH_P_WAN_PPP: c_int = 0x0007; pub const ETH_P_PPP_MP: c_int = 0x0008; pub const ETH_P_LOCALTALK: c_int = 0x0009; pub const ETH_P_CAN: c_int = 0x000C; pub const ETH_P_CANFD: c_int = 0x000D; pub const ETH_P_PPPTALK: c_int = 0x0010; pub const ETH_P_TR_802_2: c_int = 0x0011; pub const ETH_P_MOBITEX: c_int = 0x0015; pub const ETH_P_CONTROL: c_int = 0x0016; pub const ETH_P_IRDA: c_int = 0x0017; pub const ETH_P_ECONET: c_int = 0x0018; pub const ETH_P_HDLC: c_int = 0x0019; pub const ETH_P_ARCNET: c_int = 0x001A; pub const ETH_P_DSA: c_int = 0x001B; pub const ETH_P_TRAILER: c_int = 0x001C; pub const ETH_P_PHONET: c_int = 0x00F5; pub const ETH_P_IEEE802154: c_int = 0x00F6; pub const ETH_P_CAIF: c_int = 0x00F7; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 0x00040000; pub const O_NOATIME: c_int = 0x00002000; pub const O_CLOEXEC: c_int = 0x00000100; pub const O_TMPFILE: c_int = 0x00004000; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const BUFSIZ: c_uint = 1024; pub const TMP_MAX: c_uint = 10000; pub const FOPEN_MAX: c_uint = 1000; pub const O_PATH: c_int = 0x00400000; pub const O_EXEC: c_int = O_PATH; pub const O_SEARCH: c_int = O_PATH; pub const O_ACCMODE: c_int = 03 | O_SEARCH; pub const O_NDELAY: c_int = O_NONBLOCK; pub const NI_MAXHOST: crate::socklen_t = 255; pub const PTHREAD_STACK_MIN: size_t = 2048; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const RLIM_INFINITY: crate::rlim_t = !0; pub const RLIMIT_RTTIME: c_int = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: c_int = 16; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = RLIMIT_NLIMITS; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const SOCK_DCCP: c_int = 6; pub const SOCK_PACKET: c_int = 10; pub const TCP_COOKIE_TRANSACTIONS: c_int = 15; pub const TCP_THIN_LINEAR_TIMEOUTS: c_int = 16; pub const TCP_THIN_DUPACK: c_int = 17; pub const TCP_USER_TIMEOUT: c_int = 18; pub const TCP_REPAIR: c_int = 19; pub const TCP_REPAIR_QUEUE: c_int = 20; pub const TCP_QUEUE_SEQ: c_int = 21; pub const TCP_REPAIR_OPTIONS: c_int = 22; pub const TCP_FASTOPEN: c_int = 23; pub const TCP_TIMESTAMP: c_int = 24; pub const SIGUNUSED: c_int = crate::SIGSYS; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const CPU_SETSIZE: c_int = 128; pub const PTRACE_TRACEME: c_int = 0; pub const PTRACE_PEEKTEXT: c_int = 1; pub const PTRACE_PEEKDATA: c_int = 2; pub const PTRACE_PEEKUSER: c_int = 3; pub const PTRACE_POKETEXT: c_int = 4; pub const PTRACE_POKEDATA: c_int = 5; pub const PTRACE_POKEUSER: c_int = 6; pub const PTRACE_CONT: c_int = 7; pub const PTRACE_KILL: c_int = 8; pub const PTRACE_SINGLESTEP: c_int = 9; pub const PTRACE_GETREGS: c_int = 12; pub const PTRACE_SETREGS: c_int = 13; pub const PTRACE_GETFPREGS: c_int = 14; pub const PTRACE_SETFPREGS: c_int = 15; pub const PTRACE_ATTACH: c_int = 16; pub const PTRACE_DETACH: c_int = 17; pub const PTRACE_GETFPXREGS: c_int = 18; pub const PTRACE_SETFPXREGS: c_int = 19; pub const PTRACE_SYSCALL: c_int = 24; pub const PTRACE_SETOPTIONS: c_int = 0x4200; pub const PTRACE_GETEVENTMSG: c_int = 0x4201; pub const PTRACE_GETSIGINFO: c_int = 0x4202; pub const PTRACE_SETSIGINFO: c_int = 0x4203; pub const PTRACE_GETREGSET: c_int = 0x4204; pub const PTRACE_SETREGSET: c_int = 0x4205; pub const PTRACE_SEIZE: c_int = 0x4206; pub const PTRACE_INTERRUPT: c_int = 0x4207; pub const PTRACE_LISTEN: c_int = 0x4208; pub const PTRACE_PEEKSIGINFO: c_int = 0x4209; pub const EPOLLWAKEUP: c_int = 0x20000000; pub const EFD_NONBLOCK: c_int = crate::O_NONBLOCK; pub const SFD_NONBLOCK: c_int = crate::O_NONBLOCK; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const TIOCINQ: c_int = crate::FIONREAD; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const SO_BINDTODEVICE: c_int = 25; pub const SO_TIMESTAMP: c_int = 29; pub const SO_MARK: c_int = 36; pub const SO_RXQ_OVFL: c_int = 40; pub const SO_PEEK_OFF: c_int = 42; pub const SO_BUSY_POLL: c_int = 46; pub const SO_BINDTOIFINDEX: c_int = 62; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const O_ASYNC: c_int = 0x00000400; pub const FIOCLEX: c_int = 0x5451; pub const FIONBIO: c_int = 0x5421; pub const RLIMIT_RSS: c_int = 5; pub const RLIMIT_NOFILE: c_int = 7; pub const RLIMIT_AS: c_int = 9; pub const RLIMIT_NPROC: c_int = 6; pub const RLIMIT_MEMLOCK: c_int = 8; pub const O_APPEND: c_int = 0x00100000; pub const O_CREAT: c_int = 0x00010000; pub const O_EXCL: c_int = 0x00020000; pub const O_NOCTTY: c_int = 0x00000200; pub const O_NONBLOCK: c_int = 0x00000010; pub const O_SYNC: c_int = 0x00000040 | O_DSYNC; pub const O_RSYNC: c_int = O_SYNC; pub const O_DSYNC: c_int = 0x00000020; pub const SOCK_CLOEXEC: c_int = 0o2000000; pub const SOCK_NONBLOCK: c_int = 0o4000; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_SEQPACKET: c_int = 5; pub const SOL_SOCKET: c_int = 1; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EDEADLOCK: c_int = EDEADLK; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; pub const SO_REUSEADDR: c_int = 2; pub const SO_TYPE: c_int = 3; pub const SO_ERROR: c_int = 4; pub const SO_DONTROUTE: c_int = 5; pub const SO_BROADCAST: c_int = 6; pub const SO_SNDBUF: c_int = 7; pub const SO_RCVBUF: c_int = 8; pub const SO_KEEPALIVE: c_int = 9; pub const SO_OOBINLINE: c_int = 10; pub const SO_NO_CHECK: c_int = 11; pub const SO_PRIORITY: c_int = 12; pub const SO_LINGER: c_int = 13; pub const SO_BSDCOMPAT: c_int = 14; pub const SO_REUSEPORT: c_int = 15; pub const SO_PASSCRED: c_int = 16; pub const SO_PEERCRED: c_int = 17; pub const SO_RCVLOWAT: c_int = 18; pub const SO_SNDLOWAT: c_int = 19; pub const SO_RCVTIMEO: c_int = 20; pub const SO_SNDTIMEO: c_int = 21; pub const SO_ACCEPTCONN: c_int = 30; pub const SO_SNDBUFFORCE: c_int = 32; pub const SO_RCVBUFFORCE: c_int = 33; pub const SO_PROTOCOL: c_int = 38; pub const SO_DOMAIN: c_int = 39; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const MAP_HUGETLB: c_int = 0x040000; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const TCGETS: c_int = 0x5401; pub const TCSETS: c_int = 0x5402; pub const TCSETSW: c_int = 0x5403; pub const TCSETSF: c_int = 0x5404; pub const TCGETA: c_int = 0x5405; pub const TCSETA: c_int = 0x5406; pub const TCSETAW: c_int = 0x5407; pub const TCSETAF: c_int = 0x5408; pub const TCSBRK: c_int = 0x5409; pub const TCXONC: c_int = 0x540A; pub const TCFLSH: c_int = 0x540B; pub const TIOCGSOFTCAR: c_int = 0x5419; pub const TIOCSSOFTCAR: c_int = 0x541A; pub const TIOCLINUX: c_int = 0x541C; pub const TIOCGSERIAL: c_int = 0x541E; pub const TIOCEXCL: c_int = 0x540C; pub const TIOCNXCL: c_int = 0x540D; pub const TIOCSCTTY: c_int = 0x540E; pub const TIOCGPGRP: c_int = 0x540F; pub const TIOCSPGRP: c_int = 0x5410; pub const TIOCOUTQ: c_int = 0x5411; pub const TIOCSTI: c_int = 0x5412; pub const TIOCGWINSZ: c_int = 0x5413; pub const TIOCSWINSZ: c_int = 0x5414; pub const TIOCMGET: c_int = 0x5415; pub const TIOCMBIS: c_int = 0x5416; pub const TIOCMBIC: c_int = 0x5417; pub const TIOCMSET: c_int = 0x5418; pub const FIONREAD: c_int = 0x541B; pub const TIOCCONS: c_int = 0x541D; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const TIOCM_LE: c_int = 0x001; pub const TIOCM_DTR: c_int = 0x002; pub const TIOCM_RTS: c_int = 0x004; pub const TIOCM_ST: c_int = 0x008; pub const TIOCM_SR: c_int = 0x010; pub const TIOCM_CTS: c_int = 0x020; pub const TIOCM_CAR: c_int = 0x040; pub const TIOCM_RNG: c_int = 0x080; pub const TIOCM_DSR: c_int = 0x100; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const O_DIRECTORY: c_int = 0x00080000; pub const O_DIRECT: c_int = 0x00000800; pub const O_LARGEFILE: c_int = 0x00001000; pub const O_NOFOLLOW: c_int = 0x00000080; pub const HUGETLB_FLAG_ENCODE_SHIFT: u32 = 26; pub const MAP_HUGE_SHIFT: u32 = 26; // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { const ULONG_SIZE: usize = 32; } else if #[cfg(target_pointer_width = "64")] { const ULONG_SIZE: usize = 64; } else { // Unknown target_pointer_width } } // END_PUB_CONST f! { pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { cmsg.offset(1) as *mut c_uchar } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as size_t) < mem::size_of::() { 0 as *mut cmsghdr } else if __CMSG_NEXT(cmsg).add(mem::size_of::()) >= __MHDR_END(mhdr) { 0 as *mut cmsghdr } else { __CMSG_NEXT(cmsg).cast() } } pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as size_t >= mem::size_of::() { (*mhdr).msg_control.cast() } else { 0 as *mut cmsghdr } } pub {const} fn CMSG_ALIGN(len: size_t) -> size_t { (len + mem::size_of::() - 1) & !(mem::size_of::() - 1) } pub {const} fn CMSG_SPACE(len: c_uint) -> c_uint { (CMSG_ALIGN(len as size_t) + CMSG_ALIGN(mem::size_of::())) as c_uint } pub {const} fn CMSG_LEN(len: c_uint) -> c_uint { (CMSG_ALIGN(mem::size_of::()) + len as size_t) as c_uint } } safe_f! { pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0x7f } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: c_int) -> bool { (status & 0x80) != 0 } pub {const} fn QCMD(cmd: c_int, type_: c_int) -> c_int { (cmd << 8) | (type_ & 0x00ff) } pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= (major & 0x00000fff) << 8; dev |= (major & 0xfffff000) << 32; dev |= (minor & 0x000000ff) << 0; dev |= (minor & 0xffffff00) << 12; dev } pub {const} fn major(dev: crate::dev_t) -> c_uint { let mut major = 0; major |= (dev & 0x00000000000fff00) >> 8; major |= (dev & 0xfffff00000000000) >> 32; major as c_uint } pub {const} fn minor(dev: crate::dev_t) -> c_uint { let mut minor = 0; minor |= (dev & 0x00000000000000ff) >> 0; minor |= (dev & 0x00000ffffff00000) >> 12; minor as c_uint } } fn __CMSG_LEN(cmsg: *const cmsghdr) -> ssize_t { ((unsafe { (*cmsg).cmsg_len as size_t } + mem::size_of::() - 1) & !(mem::size_of::() - 1)) as ssize_t } fn __CMSG_NEXT(cmsg: *const cmsghdr) -> *mut c_uchar { (unsafe { cmsg.offset(__CMSG_LEN(cmsg)) }) as *mut c_uchar } fn __MHDR_END(mhdr: *const msghdr) -> *mut c_uchar { unsafe { (*mhdr).msg_control.offset((*mhdr).msg_controllen as isize) }.cast() } // EXTERN_FN #[link(name = "c")] #[link(name = "fdio")] extern "C" {} #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} impl Copy for FILE {} impl Clone for FILE { fn clone(&self) -> FILE { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} // FIXME(fuchsia): fill this out with a struct impl Copy for fpos_t {} impl Clone for fpos_t { fn clone(&self) -> fpos_t { *self } } extern "C" { pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; pub fn feof(stream: *mut FILE) -> c_int; pub fn ferror(stream: *mut FILE) -> c_int; pub fn perror(s: *const c_char); pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn abort() -> !; pub fn exit(status: c_int) -> !; pub fn _exit(status: c_int) -> !; pub fn atexit(cb: extern "C" fn()) -> c_int; pub fn system(s: *const c_char) -> c_int; pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn getpwnam(name: *const c_char) -> *mut passwd; pub fn getpwuid(uid: crate::uid_t) -> *mut passwd; pub fn fprintf(stream: *mut crate::FILE, format: *const c_char, ...) -> c_int; pub fn printf(format: *const c_char, ...) -> c_int; pub fn snprintf(s: *mut c_char, n: size_t, format: *const c_char, ...) -> c_int; pub fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int; pub fn fscanf(stream: *mut crate::FILE, format: *const c_char, ...) -> c_int; pub fn scanf(format: *const c_char, ...) -> c_int; pub fn sscanf(s: *const c_char, format: *const c_char, ...) -> c_int; pub fn getchar_unlocked() -> c_int; pub fn putchar_unlocked(c: c_int) -> c_int; pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int; pub fn connect(socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int; pub fn listen(socket: c_int, backlog: c_int) -> c_int; pub fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; pub fn getpeername(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; pub fn getsockname(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; pub fn setsockopt( socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t, ) -> c_int; pub fn socketpair( domain: c_int, type_: c_int, protocol: c_int, socket_vector: *mut c_int, ) -> c_int; pub fn sendto( socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t, ) -> ssize_t; pub fn shutdown(socket: c_int, how: c_int) -> c_int; pub fn chmod(path: *const c_char, mode: mode_t) -> c_int; pub fn fchmod(fd: c_int, mode: mode_t) -> c_int; pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int; pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; pub fn pclose(stream: *mut crate::FILE) -> c_int; pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut crate::FILE; pub fn fileno(stream: *mut crate::FILE) -> c_int; pub fn open(path: *const c_char, oflag: c_int, ...) -> c_int; pub fn creat(path: *const c_char, mode: mode_t) -> c_int; pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int; pub fn opendir(dirname: *const c_char) -> *mut crate::DIR; pub fn readdir(dirp: *mut crate::DIR) -> *mut crate::dirent; pub fn readdir_r( dirp: *mut crate::DIR, entry: *mut crate::dirent, result: *mut *mut crate::dirent, ) -> c_int; pub fn closedir(dirp: *mut crate::DIR) -> c_int; pub fn rewinddir(dirp: *mut crate::DIR); pub fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int, ...) -> c_int; pub fn fchmodat( dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, flags: c_int, ) -> c_int; pub fn fchown(fd: c_int, owner: crate::uid_t, group: crate::gid_t) -> c_int; pub fn fchownat( dirfd: c_int, pathname: *const c_char, owner: crate::uid_t, group: crate::gid_t, flags: c_int, ) -> c_int; pub fn fstatat(dirfd: c_int, pathname: *const c_char, buf: *mut stat, flags: c_int) -> c_int; pub fn linkat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn mkdirat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn readlinkat( dirfd: c_int, pathname: *const c_char, buf: *mut c_char, bufsiz: size_t, ) -> ssize_t; pub fn renameat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, ) -> c_int; pub fn symlinkat(target: *const c_char, newdirfd: c_int, linkpath: *const c_char) -> c_int; pub fn unlinkat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int; pub fn access(path: *const c_char, amode: c_int) -> c_int; pub fn alarm(seconds: c_uint) -> c_uint; pub fn chdir(dir: *const c_char) -> c_int; pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int; pub fn lchown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int; pub fn close(fd: c_int) -> c_int; pub fn dup(fd: c_int) -> c_int; pub fn dup2(src: c_int, dst: c_int) -> c_int; pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> c_int; pub fn execle(path: *const c_char, arg0: *const c_char, ...) -> c_int; pub fn execlp(file: *const c_char, arg0: *const c_char, ...) -> c_int; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn execv(prog: *const c_char, argv: *const *const c_char) -> c_int; pub fn execve( prog: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int; pub fn fork() -> pid_t; pub fn fpathconf(filedes: c_int, name: c_int) -> c_long; pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; pub fn getgid() -> gid_t; pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int; pub fn getlogin() -> *mut c_char; pub fn getopt(argc: c_int, argv: *const *mut c_char, optstr: *const c_char) -> c_int; pub fn getpgid(pid: pid_t) -> pid_t; pub fn getpgrp() -> pid_t; pub fn getpid() -> pid_t; pub fn getppid() -> pid_t; pub fn getuid() -> uid_t; pub fn isatty(fd: c_int) -> c_int; pub fn link(src: *const c_char, dst: *const c_char) -> c_int; pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t; pub fn pathconf(path: *const c_char, name: c_int) -> c_long; pub fn pause() -> c_int; pub fn pipe(fds: *mut c_int) -> c_int; pub fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int; pub fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t; pub fn rmdir(path: *const c_char) -> c_int; pub fn seteuid(uid: uid_t) -> c_int; pub fn setegid(gid: gid_t) -> c_int; pub fn setgid(gid: gid_t) -> c_int; pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int; pub fn setsid() -> pid_t; pub fn setuid(uid: uid_t) -> c_int; pub fn sleep(secs: c_uint) -> c_uint; pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int; pub fn tcgetpgrp(fd: c_int) -> pid_t; pub fn tcsetpgrp(fd: c_int, pgrp: crate::pid_t) -> c_int; pub fn ttyname(fd: c_int) -> *mut c_char; pub fn unlink(c: *const c_char) -> c_int; pub fn wait(status: *mut c_int) -> pid_t; pub fn waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> pid_t; pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t; pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t, offset: off_t) -> ssize_t; pub fn umask(mask: mode_t) -> mode_t; pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; pub fn kill(pid: pid_t, sig: c_int) -> c_int; pub fn mlock(addr: *const c_void, len: size_t) -> c_int; pub fn munlock(addr: *const c_void, len: size_t) -> c_int; pub fn mlockall(flags: c_int) -> c_int; pub fn munlockall() -> c_int; pub fn mmap( addr: *mut c_void, len: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off_t, ) -> *mut c_void; pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; pub fn if_nametoindex(ifname: *const c_char) -> c_uint; pub fn if_indextoname(ifindex: c_uint, ifname: *mut c_char) -> *mut c_char; pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; pub fn fsync(fd: c_int) -> c_int; pub fn setenv(name: *const c_char, val: *const c_char, overwrite: c_int) -> c_int; pub fn unsetenv(name: *const c_char) -> c_int; pub fn symlink(path1: *const c_char, path2: *const c_char) -> c_int; pub fn ftruncate(fd: c_int, length: off_t) -> c_int; pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; pub fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char; pub fn flock(fd: c_int, operation: c_int) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn times(buf: *mut crate::tms) -> crate::clock_t; pub fn pthread_self() -> crate::pthread_t; pub fn pthread_join(native: crate::pthread_t, value: *mut *mut c_void) -> c_int; pub fn pthread_exit(value: *mut c_void) -> !; pub fn pthread_attr_init(attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_destroy(attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_getstacksize( attr: *const crate::pthread_attr_t, stacksize: *mut size_t, ) -> c_int; pub fn pthread_attr_setstacksize(attr: *mut crate::pthread_attr_t, stack_size: size_t) -> c_int; pub fn pthread_attr_setdetachstate(attr: *mut crate::pthread_attr_t, state: c_int) -> c_int; pub fn pthread_detach(thread: crate::pthread_t) -> c_int; pub fn sched_yield() -> c_int; pub fn pthread_key_create( key: *mut pthread_key_t, dtor: Option, ) -> c_int; pub fn pthread_key_delete(key: pthread_key_t) -> c_int; pub fn pthread_getspecific(key: pthread_key_t) -> *mut c_void; pub fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int; pub fn pthread_mutex_init( lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, ) -> c_int; pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int; pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int; pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: c_int) -> c_int; pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int; pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_cond_timedwait( cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int; pub fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> c_int; pub fn pthread_rwlock_init( lock: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t, ) -> c_int; pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> c_int; pub fn pthread_rwlock_rdlock(lock: *mut pthread_rwlock_t) -> c_int; pub fn pthread_rwlock_tryrdlock(lock: *mut pthread_rwlock_t) -> c_int; pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> c_int; pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> c_int; pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> c_int; pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int; pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> c_int; pub fn pthread_getname_np(thread: crate::pthread_t, name: *mut c_char, len: size_t) -> c_int; pub fn pthread_setname_np(thread: crate::pthread_t, name: *const c_char) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn getsockopt( sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut crate::socklen_t, ) -> c_int; pub fn raise(signum: c_int) -> c_int; pub fn sigaction(signum: c_int, act: *const sigaction, oldact: *mut sigaction) -> c_int; pub fn utimes(filename: *const c_char, times: *const crate::timeval) -> c_int; pub fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void; pub fn dlerror() -> *mut c_char; pub fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void; pub fn dlclose(handle: *mut c_void) -> c_int; pub fn dladdr(addr: *const c_void, info: *mut Dl_info) -> c_int; pub fn getaddrinfo( node: *const c_char, service: *const c_char, hints: *const addrinfo, res: *mut *mut addrinfo, ) -> c_int; pub fn freeaddrinfo(res: *mut addrinfo); pub fn gai_strerror(errcode: c_int) -> *const c_char; pub fn res_init() -> c_int; pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; pub fn mktime(tm: *mut tm) -> time_t; pub fn time(time: *mut time_t) -> time_t; pub fn gmtime(time_p: *const time_t) -> *mut tm; pub fn localtime(time_p: *const time_t) -> *mut tm; pub fn mknod(pathname: *const c_char, mode: crate::mode_t, dev: crate::dev_t) -> c_int; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn gethostname(name: *mut c_char, len: size_t) -> c_int; pub fn getservbyname(name: *const c_char, proto: *const c_char) -> *mut servent; pub fn getprotobyname(name: *const c_char) -> *mut protoent; pub fn getprotobynumber(proto: c_int) -> *mut protoent; pub fn usleep(secs: c_uint) -> c_int; pub fn send(socket: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t; pub fn recv(socket: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t; pub fn putenv(string: *mut c_char) -> c_int; pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int; pub fn select( nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *mut timeval, ) -> c_int; pub fn setlocale(category: c_int, locale: *const c_char) -> *mut c_char; pub fn localeconv() -> *mut lconv; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_wait(sem: *mut sem_t) -> c_int; pub fn sem_trywait(sem: *mut sem_t) -> c_int; pub fn sem_post(sem: *mut sem_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> c_int; pub fn fstatvfs(fd: c_int, buf: *mut statvfs) -> c_int; pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: size_t) -> ssize_t; pub fn sigemptyset(set: *mut sigset_t) -> c_int; pub fn sigaddset(set: *mut sigset_t, signum: c_int) -> c_int; pub fn sigfillset(set: *mut sigset_t) -> c_int; pub fn sigdelset(set: *mut sigset_t, signum: c_int) -> c_int; pub fn sigismember(set: *const sigset_t, signum: c_int) -> c_int; pub fn sigprocmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sigpending(set: *mut sigset_t) -> c_int; pub fn timegm(tm: *mut crate::tm) -> time_t; pub fn getsid(pid: pid_t) -> pid_t; pub fn sysconf(name: c_int) -> c_long; pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int; pub fn pselect( nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *const timespec, sigmask: *const sigset_t, ) -> c_int; pub fn fseeko(stream: *mut crate::FILE, offset: off_t, whence: c_int) -> c_int; pub fn ftello(stream: *mut crate::FILE) -> off_t; pub fn tcdrain(fd: c_int) -> c_int; pub fn cfgetispeed(termios: *const crate::termios) -> crate::speed_t; pub fn cfgetospeed(termios: *const crate::termios) -> crate::speed_t; pub fn cfmakeraw(termios: *mut crate::termios); pub fn cfsetispeed(termios: *mut crate::termios, speed: crate::speed_t) -> c_int; pub fn cfsetospeed(termios: *mut crate::termios, speed: crate::speed_t) -> c_int; pub fn cfsetspeed(termios: *mut crate::termios, speed: crate::speed_t) -> c_int; pub fn tcgetattr(fd: c_int, termios: *mut crate::termios) -> c_int; pub fn tcsetattr(fd: c_int, optional_actions: c_int, termios: *const crate::termios) -> c_int; pub fn tcflow(fd: c_int, action: c_int) -> c_int; pub fn tcflush(fd: c_int, action: c_int) -> c_int; pub fn tcgetsid(fd: c_int) -> crate::pid_t; pub fn tcsendbreak(fd: c_int, duration: c_int) -> c_int; pub fn mkstemp(template: *mut c_char) -> c_int; pub fn mkdtemp(template: *mut c_char) -> *mut c_char; pub fn tmpnam(ptr: *mut c_char) -> *mut c_char; pub fn openlog(ident: *const c_char, logopt: c_int, facility: c_int); pub fn closelog(); pub fn setlogmask(maskpri: c_int) -> c_int; pub fn syslog(priority: c_int, message: *const c_char, ...); pub fn grantpt(fd: c_int) -> c_int; pub fn posix_openpt(flags: c_int) -> c_int; pub fn ptsname(fd: c_int) -> *mut c_char; pub fn unlockpt(fd: c_int) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_settime(clk_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn pthread_getattr_np(native: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn memalign(align: size_t, size: size_t) -> *mut c_void; pub fn setgroups(ngroups: size_t, ptr: *const crate::gid_t) -> c_int; pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; pub fn freelocale(loc: crate::locale_t); pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn fdopendir(fd: c_int) -> *mut crate::DIR; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn accept4( fd: c_int, addr: *mut crate::sockaddr, len: *mut crate::socklen_t, flg: c_int, ) -> c_int; pub fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn clearenv() -> c_int; pub fn waitid( idtype: idtype_t, id: id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn setreuid(ruid: crate::uid_t, euid: crate::uid_t) -> c_int; pub fn setregid(rgid: crate::gid_t, egid: crate::gid_t) -> c_int; pub fn getresuid( ruid: *mut crate::uid_t, euid: *mut crate::uid_t, suid: *mut crate::uid_t, ) -> c_int; pub fn getresgid( rgid: *mut crate::gid_t, egid: *mut crate::gid_t, sgid: *mut crate::gid_t, ) -> c_int; pub fn acct(filename: *const c_char) -> c_int; pub fn brk(addr: *mut c_void) -> c_int; pub fn setresgid(rgid: crate::gid_t, egid: crate::gid_t, sgid: crate::gid_t) -> c_int; pub fn setresuid(ruid: crate::uid_t, euid: crate::uid_t, suid: crate::uid_t) -> c_int; pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *const termios, winp: *const crate::winsize, ) -> c_int; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn execvpe( file: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; pub fn fexecve(fd: c_int, argv: *const *const c_char, envp: *const *const c_char) -> c_int; pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int; pub fn lutimes(file: *const c_char, times: *const crate::timeval) -> c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; // System V IPC pub fn shmget(key: crate::key_t, size: size_t, shmflg: c_int) -> c_int; pub fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void; pub fn shmdt(shmaddr: *const c_void) -> c_int; pub fn shmctl(shmid: c_int, cmd: c_int, buf: *mut crate::shmid_ds) -> c_int; pub fn ftok(pathname: *const c_char, proj_id: c_int) -> crate::key_t; pub fn semget(key: crate::key_t, nsems: c_int, semflag: c_int) -> c_int; pub fn semop(semid: c_int, sops: *mut crate::sembuf, nsops: size_t) -> c_int; pub fn semctl(semid: c_int, semnum: c_int, cmd: c_int, ...) -> c_int; pub fn msgctl(msqid: c_int, cmd: c_int, buf: *mut msqid_ds) -> c_int; pub fn msgget(key: crate::key_t, msgflg: c_int) -> c_int; pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtyp: c_long, msgflg: c_int, ) -> ssize_t; pub fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: size_t, msgflg: c_int) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn __errno_location() -> *mut c_int; pub fn fallocate(fd: c_int, mode: c_int, offset: off_t, len: off_t) -> c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn readahead(fd: c_int, offset: off64_t, count: size_t) -> ssize_t; pub fn signalfd(fd: c_int, mask: *const crate::sigset_t, flags: c_int) -> c_int; pub fn timerfd_create(clockid: c_int, flags: c_int) -> c_int; pub fn timerfd_gettime(fd: c_int, curr_value: *mut itimerspec) -> c_int; pub fn timerfd_settime( fd: c_int, flags: c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> c_int; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn quotactl(cmd: c_int, special: *const c_char, id: c_int, data: *mut c_char) -> c_int; pub fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int; pub fn mkostemp(template: *mut c_char, flags: c_int) -> c_int; pub fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn nl_langinfo_l(item: crate::nl_item, locale: crate::locale_t) -> *mut c_char; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn reboot(how_to: c_int) -> c_int; pub fn setfsgid(gid: crate::gid_t) -> c_int; pub fn setfsuid(uid: crate::uid_t) -> c_int; // Not available now on Android pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn sync_file_range(fd: c_int, offset: off64_t, nbytes: off64_t, flags: c_uint) -> c_int; pub fn getifaddrs(ifap: *mut *mut crate::ifaddrs) -> c_int; pub fn freeifaddrs(ifa: *mut crate::ifaddrs); pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; pub fn globfree(pglob: *mut crate::glob_t); pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; pub fn futimes(fd: c_int, times: *const crate::timeval) -> c_int; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn bind( socket: c_int, address: *const crate::sockaddr, address_len: crate::socklen_t, ) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn sendmsg(fd: c_int, msg: *const crate::msghdr, flags: c_int) -> ssize_t; pub fn recvmsg(fd: c_int, msg: *mut crate::msghdr, flags: c_int) -> ssize_t; pub fn getdomainname(name: *mut c_char, len: size_t) -> c_int; pub fn setdomainname(name: *const c_char, len: size_t) -> c_int; pub fn vhangup() -> c_int; pub fn sendmmsg(sockfd: c_int, msgvec: *mut mmsghdr, vlen: c_uint, flags: c_int) -> c_int; pub fn recvmmsg( sockfd: c_int, msgvec: *mut mmsghdr, vlen: c_uint, flags: c_int, timeout: *mut crate::timespec, ) -> c_int; pub fn sync(); pub fn syscall(num: c_long, ...) -> c_long; pub fn sched_getaffinity( pid: crate::pid_t, cpusetsize: size_t, cpuset: *mut cpu_set_t, ) -> c_int; pub fn sched_setaffinity( pid: crate::pid_t, cpusetsize: size_t, cpuset: *const cpu_set_t, ) -> c_int; pub fn umount(target: *const c_char) -> c_int; pub fn sched_get_priority_max(policy: c_int) -> c_int; pub fn tee(fd_in: c_int, fd_out: c_int, len: size_t, flags: c_uint) -> ssize_t; pub fn settimeofday(tv: *const crate::timeval, tz: *const crate::timezone) -> c_int; pub fn splice( fd_in: c_int, off_in: *mut crate::loff_t, fd_out: c_int, off_out: *mut crate::loff_t, len: size_t, flags: c_uint, ) -> ssize_t; pub fn eventfd(init: c_uint, flags: c_int) -> c_int; pub fn sched_rr_get_interval(pid: crate::pid_t, tp: *mut crate::timespec) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const crate::sched_param) -> c_int; pub fn swapoff(puath: *const c_char) -> c_int; pub fn vmsplice(fd: c_int, iov: *const crate::iovec, nr_segs: size_t, flags: c_uint) -> ssize_t; pub fn mount( src: *const c_char, target: *const c_char, fstype: *const c_char, flags: c_ulong, data: *const c_void, ) -> c_int; pub fn personality(persona: c_ulong) -> c_int; pub fn sched_getparam(pid: crate::pid_t, param: *mut crate::sched_param) -> c_int; pub fn ppoll( fds: *mut crate::pollfd, nfds: nfds_t, timeout: *const crate::timespec, sigmask: *const sigset_t, ) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn clone( cb: extern "C" fn(*mut c_void) -> c_int, child_stack: *mut c_void, flags: c_int, arg: *mut c_void, ... ) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn sethostname(name: *const c_char, len: size_t) -> c_int; pub fn sched_get_priority_min(policy: c_int) -> c_int; pub fn umount2(target: *const c_char, flags: c_int) -> c_int; pub fn swapon(path: *const c_char, swapflags: c_int) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn getdtablesize() -> c_int; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn initgroups(user: *const c_char, group: crate::gid_t) -> c_int; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn pthread_cancel(thread: crate::pthread_t) -> c_int; pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut crate::group; pub fn getgrouplist( user: *const c_char, group: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn( info: *mut crate::dl_phdr_info, size: size_t, data: *mut c_void, ) -> c_int, >, data: *mut c_void, ) -> c_int; } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(any(target_arch = "x86_64"))] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(any(target_arch = "riscv64"))] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } libc/src/fuchsia/riscv64.rs0000644000175000017500000000234715105742312015400 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; // From psABI Calling Convention for RV64 pub type __u64 = c_ulonglong; pub type wchar_t = i32; pub type nlink_t = c_ulong; pub type blksize_t = c_long; pub type stat64 = stat; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 3], } // Not actually used, IPC calls just return ENOSYS pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } } libc/src/fuchsia/x86_64.rs0000644000175000017500000001105115105742312015026 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = c_long; pub type __u64 = c_ulonglong; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __reserved: [c_long; 3], } pub struct mcontext_t { __private: [u64; 32], } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __unused1: c_long, __unused2: c_long, } } s_no_extra_traits! { pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: crate::sigset_t, __private: [u8; 512], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask && self .__private .iter() .zip(other.__private.iter()) .all(|(a, b)| a == b) } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // FIXME(debug): .field("__private", &self.__private) .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); self.__private.hash(state); } } } } // offsets in user_regs_structs, from sys/reg.h pub const R15: c_int = 0; pub const R14: c_int = 1; pub const R13: c_int = 2; pub const R12: c_int = 3; pub const RBP: c_int = 4; pub const RBX: c_int = 5; pub const R11: c_int = 6; pub const R10: c_int = 7; pub const R9: c_int = 8; pub const R8: c_int = 9; pub const RAX: c_int = 10; pub const RCX: c_int = 11; pub const RDX: c_int = 12; pub const RSI: c_int = 13; pub const RDI: c_int = 14; pub const ORIG_RAX: c_int = 15; pub const RIP: c_int = 16; pub const CS: c_int = 17; pub const EFLAGS: c_int = 18; pub const RSP: c_int = 19; pub const SS: c_int = 20; pub const FS_BASE: c_int = 21; pub const GS_BASE: c_int = 22; pub const DS: c_int = 23; pub const ES: c_int = 24; pub const FS: c_int = 25; pub const GS: c_int = 26; pub const MAP_32BIT: c_int = 0x0040; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; libc/src/fuchsia/aarch64.rs0000644000175000017500000000403615105742312015325 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type __u64 = c_ulonglong; pub type wchar_t = u32; pub type nlink_t = c_ulong; pub type blksize_t = c_long; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad0: c_ulong, pub st_size: off_t, pub st_blksize: crate::blksize_t, __pad1: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_uint; 2], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad0: c_ulong, pub st_size: off_t, pub st_blksize: crate::blksize_t, __pad1: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_uint; 2], } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } } // From https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/third_party/ulib/musl/include/bits/signal.h;l=20-21;drc=0827b18ab9540c46f8037f407d17ea15a79e9ba7 pub const MINSIGSTKSZ: size_t = 6144; pub const SIGSTKSZ: size_t = 12288; libc/src/teeos/0000775000175000017500000000000015105742312013223 5ustar bdrungbdrunglibc/src/teeos/mod.rs0000644000175000017500000007232715105742312014361 0ustar bdrungbdrung//! Libc bindings for teeos //! //! Apparently the loader just dynamically links it anyway, but fails //! when linking is explicitly requested. #![allow(non_camel_case_types)] #![allow(non_snake_case)] use crate::prelude::*; pub type c_bool = i32; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type pid_t = c_int; pub type wchar_t = u32; // long double in C means A float point value, which has 128bit length. // but some bit maybe not used, so the real length of long double could be 80(x86) or 128(power pc/IEEE) // this is different from f128(not stable and not included default) in Rust, so we use u128 for FFI(Rust to C). // this is unstable and will cause to memfault/data abort. pub type c_longdouble = _CLongDouble; pub type pthread_t = c_ulong; pub type pthread_key_t = c_uint; pub type pthread_spinlock_t = c_int; pub type off_t = i64; pub type time_t = c_long; pub type clock_t = c_long; pub type clockid_t = c_int; pub type suseconds_t = c_long; pub type once_fn = extern "C" fn() -> c_void; pub type pthread_once_t = c_int; pub type va_list = *mut c_char; pub type wint_t = c_uint; pub type wctype_t = c_ulong; pub type cmpfunc = extern "C" fn(x: *const c_void, y: *const c_void) -> c_int; #[repr(align(16))] pub struct _CLongDouble(pub u128); #[repr(align(8))] #[repr(C)] pub struct pthread_cond_t { #[doc(hidden)] size: [u8; __SIZEOF_PTHREAD_COND_T], } #[repr(align(8))] #[repr(C)] pub struct pthread_mutex_t { #[doc(hidden)] size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } #[repr(align(4))] #[repr(C)] pub struct pthread_mutexattr_t { #[doc(hidden)] size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } #[repr(align(4))] #[repr(C)] pub struct pthread_condattr_t { #[doc(hidden)] size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], } #[repr(C)] pub struct pthread_attr_t { __size: [u64; 7], } #[repr(C)] pub struct cpu_set_t { bits: [c_ulong; 128 / core::mem::size_of::()], } #[repr(C)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } #[repr(C)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub __tm_gmtoff: c_long, pub __tm_zone: *const c_char, } #[repr(C)] pub struct mbstate_t { pub __opaque1: c_uint, pub __opaque2: c_uint, } #[repr(C)] pub struct sem_t { pub __val: [c_int; 4 * core::mem::size_of::() / core::mem::size_of::()], } #[repr(C)] pub struct div_t { pub quot: c_int, pub rem: c_int, } // fcntl pub const O_CREAT: u32 = 0o100; pub const O_EXCL: u32 = 0o200; pub const O_NOCTTY: u32 = 0o400; pub const O_TRUNC: u32 = 0o1000; pub const O_APPEND: u32 = 0o2000; pub const O_NONBLOCK: u32 = 0o4000; pub const O_DSYNC: u32 = 0o10000; pub const O_SYNC: u32 = 0o4010000; pub const O_RSYNC: u32 = 0o4010000; pub const O_DIRECTORY: u32 = 0o200000; pub const O_NOFOLLOW: u32 = 0o400000; pub const O_CLOEXEC: u32 = 0o2000000; pub const O_ASYNC: u32 = 0o20000; pub const O_DIRECT: u32 = 0o40000; pub const O_LARGEFILE: u32 = 0o100000; pub const O_NOATIME: u32 = 0o1000000; pub const O_PATH: u32 = 0o10000000; pub const O_TMPFILE: u32 = 0o20200000; pub const O_NDELAY: u32 = O_NONBLOCK; pub const F_DUPFD: u32 = 0; pub const F_GETFD: u32 = 1; pub const F_SETFD: u32 = 2; pub const F_GETFL: u32 = 3; pub const F_SETFL: u32 = 4; pub const F_SETOWN: u32 = 8; pub const F_GETOWN: u32 = 9; pub const F_SETSIG: u32 = 10; pub const F_GETSIG: u32 = 11; pub const F_GETLK: u32 = 12; pub const F_SETLK: u32 = 13; pub const F_SETLKW: u32 = 14; pub const F_SETOWN_EX: u32 = 15; pub const F_GETOWN_EX: u32 = 16; pub const F_GETOWNER_UIDS: u32 = 17; // mman pub const MAP_FAILED: u64 = 0xffffffffffffffff; pub const MAP_FIXED_NOREPLACE: u32 = 0x100000; pub const MAP_SHARED_VALIDATE: u32 = 0x03; pub const MAP_SHARED: u32 = 0x01; pub const MAP_PRIVATE: u32 = 0x02; pub const MAP_TYPE: u32 = 0x0f; pub const MAP_FIXED: u32 = 0x10; pub const MAP_ANON: u32 = 0x20; pub const MAP_ANONYMOUS: u32 = MAP_ANON; pub const MAP_NORESERVE: u32 = 0x4000; pub const MAP_GROWSDOWN: u32 = 0x0100; pub const MAP_DENYWRITE: u32 = 0x0800; pub const MAP_EXECUTABLE: u32 = 0x1000; pub const MAP_LOCKED: u32 = 0x2000; pub const MAP_POPULATE: u32 = 0x8000; pub const MAP_NONBLOCK: u32 = 0x10000; pub const MAP_STACK: u32 = 0x20000; pub const MAP_HUGETLB: u32 = 0x40000; pub const MAP_SYNC: u32 = 0x80000; pub const MAP_FILE: u32 = 0; pub const MAP_HUGE_SHIFT: u32 = 26; pub const MAP_HUGE_MASK: u32 = 0x3f; pub const MAP_HUGE_16KB: u32 = 14 << 26; pub const MAP_HUGE_64KB: u32 = 16 << 26; pub const MAP_HUGE_512KB: u32 = 19 << 26; pub const MAP_HUGE_1MB: u32 = 20 << 26; pub const MAP_HUGE_2MB: u32 = 21 << 26; pub const MAP_HUGE_8MB: u32 = 23 << 26; pub const MAP_HUGE_16MB: u32 = 24 << 26; pub const MAP_HUGE_32MB: u32 = 25 << 26; pub const MAP_HUGE_256MB: u32 = 28 << 26; pub const MAP_HUGE_512MB: u32 = 29 << 26; pub const MAP_HUGE_1GB: u32 = 30 << 26; pub const MAP_HUGE_2GB: u32 = 31 << 26; pub const MAP_HUGE_16GB: u32 = 34u32 << 26; pub const PROT_NONE: u32 = 0; pub const PROT_READ: u32 = 1; pub const PROT_WRITE: u32 = 2; pub const PROT_EXEC: u32 = 4; pub const PROT_GROWSDOWN: u32 = 0x01000000; pub const PROT_GROWSUP: u32 = 0x02000000; pub const MS_ASYNC: u32 = 1; pub const MS_INVALIDATE: u32 = 2; pub const MS_SYNC: u32 = 4; pub const MCL_CURRENT: u32 = 1; pub const MCL_FUTURE: u32 = 2; pub const MCL_ONFAULT: u32 = 4; pub const POSIX_MADV_NORMAL: u32 = 0; pub const POSIX_MADV_RANDOM: u32 = 1; pub const POSIX_MADV_SEQUENTIAL: u32 = 2; pub const POSIX_MADV_WILLNEED: u32 = 3; pub const POSIX_MADV_DONTNEED: u32 = 4; // wctype pub const WCTYPE_ALNUM: u64 = 1; pub const WCTYPE_ALPHA: u64 = 2; pub const WCTYPE_BLANK: u64 = 3; pub const WCTYPE_CNTRL: u64 = 4; pub const WCTYPE_DIGIT: u64 = 5; pub const WCTYPE_GRAPH: u64 = 6; pub const WCTYPE_LOWER: u64 = 7; pub const WCTYPE_PRINT: u64 = 8; pub const WCTYPE_PUNCT: u64 = 9; pub const WCTYPE_SPACE: u64 = 10; pub const WCTYPE_UPPER: u64 = 11; pub const WCTYPE_XDIGIT: u64 = 12; // locale pub const LC_CTYPE: i32 = 0; pub const LC_NUMERIC: i32 = 1; pub const LC_TIME: i32 = 2; pub const LC_COLLATE: i32 = 3; pub const LC_MONETARY: i32 = 4; pub const LC_MESSAGES: i32 = 5; pub const LC_ALL: i32 = 6; // pthread pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; // errno.h pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const EWOULDBLOCK: c_int = EAGAIN; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EDEADLOCK: c_int = EDEADLK; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EMULTIHOP: c_int = 72; pub const EDOTDOT: c_int = 73; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPOR: c_int = 93; pub const ESOCKTNOSUPPOR: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; // pthread_attr.h pub const TEESMP_THREAD_ATTR_CA_WILDCARD: c_int = 0; pub const TEESMP_THREAD_ATTR_CA_INHERIT: c_int = -1; pub const TEESMP_THREAD_ATTR_TASK_ID_INHERIT: c_int = -1; pub const TEESMP_THREAD_ATTR_HAS_SHADOW: c_int = 0x1; pub const TEESMP_THREAD_ATTR_NO_SHADOW: c_int = 0x0; // unistd.h pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_STREAM_MAX: c_int = 5; pub const _SC_TZNAME_MAX: c_int = 6; pub const _SC_JOB_CONTROL: c_int = 7; pub const _SC_SAVED_IDS: c_int = 8; pub const _SC_REALTIME_SIGNALS: c_int = 9; pub const _SC_PRIORITY_SCHEDULING: c_int = 10; pub const _SC_TIMERS: c_int = 11; pub const _SC_ASYNCHRONOUS_IO: c_int = 12; pub const _SC_PRIORITIZED_IO: c_int = 13; pub const _SC_SYNCHRONIZED_IO: c_int = 14; pub const _SC_FSYNC: c_int = 15; pub const _SC_MAPPED_FILES: c_int = 16; pub const _SC_MEMLOCK: c_int = 17; pub const _SC_MEMLOCK_RANGE: c_int = 18; pub const _SC_MEMORY_PROTECTION: c_int = 19; pub const _SC_MESSAGE_PASSING: c_int = 20; pub const _SC_SEMAPHORES: c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 22; pub const _SC_AIO_LISTIO_MAX: c_int = 23; pub const _SC_AIO_MAX: c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 25; pub const _SC_DELAYTIMER_MAX: c_int = 26; pub const _SC_MQ_OPEN_MAX: c_int = 27; pub const _SC_MQ_PRIO_MAX: c_int = 28; pub const _SC_VERSION: c_int = 29; pub const _SC_PAGE_SIZE: c_int = 30; pub const _SC_PAGESIZE: c_int = 30; /* !! */ pub const _SC_RTSIG_MAX: c_int = 31; pub const _SC_SEM_NSEMS_MAX: c_int = 32; pub const _SC_SEM_VALUE_MAX: c_int = 33; pub const _SC_SIGQUEUE_MAX: c_int = 34; pub const _SC_TIMER_MAX: c_int = 35; pub const _SC_BC_BASE_MAX: c_int = 36; pub const _SC_BC_DIM_MAX: c_int = 37; pub const _SC_BC_SCALE_MAX: c_int = 38; pub const _SC_BC_STRING_MAX: c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: c_int = 40; pub const _SC_EXPR_NEST_MAX: c_int = 42; pub const _SC_LINE_MAX: c_int = 43; pub const _SC_RE_DUP_MAX: c_int = 44; pub const _SC_2_VERSION: c_int = 46; pub const _SC_2_C_BIND: c_int = 47; pub const _SC_2_C_DEV: c_int = 48; pub const _SC_2_FORT_DEV: c_int = 49; pub const _SC_2_FORT_RUN: c_int = 50; pub const _SC_2_SW_DEV: c_int = 51; pub const _SC_2_LOCALEDEF: c_int = 52; pub const _SC_UIO_MAXIOV: c_int = 60; /* !! */ pub const _SC_IOV_MAX: c_int = 60; pub const _SC_THREADS: c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: c_int = 70; pub const _SC_LOGIN_NAME_MAX: c_int = 71; pub const _SC_TTY_NAME_MAX: c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73; pub const _SC_THREAD_KEYS_MAX: c_int = 74; pub const _SC_THREAD_STACK_MIN: c_int = 75; pub const _SC_THREAD_THREADS_MAX: c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: c_int = 82; pub const _SC_NPROCESSORS_CONF: c_int = 83; pub const _SC_NPROCESSORS_ONLN: c_int = 84; pub const _SC_PHYS_PAGES: c_int = 85; pub const _SC_AVPHYS_PAGES: c_int = 86; pub const _SC_ATEXIT_MAX: c_int = 87; pub const _SC_PASS_MAX: c_int = 88; pub const _SC_XOPEN_VERSION: c_int = 89; pub const _SC_XOPEN_XCU_VERSION: c_int = 90; pub const _SC_XOPEN_UNIX: c_int = 91; pub const _SC_XOPEN_CRYPT: c_int = 92; pub const _SC_XOPEN_ENH_I18N: c_int = 93; pub const _SC_XOPEN_SHM: c_int = 94; pub const _SC_2_CHAR_TERM: c_int = 95; pub const _SC_2_UPE: c_int = 97; pub const _SC_XOPEN_XPG2: c_int = 98; pub const _SC_XOPEN_XPG3: c_int = 99; pub const _SC_XOPEN_XPG4: c_int = 100; pub const _SC_NZERO: c_int = 109; pub const _SC_XBS5_ILP32_OFF32: c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 126; pub const _SC_XBS5_LP64_OFF64: c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 128; pub const _SC_XOPEN_LEGACY: c_int = 129; pub const _SC_XOPEN_REALTIME: c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131; pub const _SC_ADVISORY_INFO: c_int = 132; pub const _SC_BARRIERS: c_int = 133; pub const _SC_CLOCK_SELECTION: c_int = 137; pub const _SC_CPUTIME: c_int = 138; pub const _SC_THREAD_CPUTIME: c_int = 139; pub const _SC_MONOTONIC_CLOCK: c_int = 149; pub const _SC_READER_WRITER_LOCKS: c_int = 153; pub const _SC_SPIN_LOCKS: c_int = 154; pub const _SC_REGEXP: c_int = 155; pub const _SC_SHELL: c_int = 157; pub const _SC_SPAWN: c_int = 159; pub const _SC_SPORADIC_SERVER: c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 161; pub const _SC_TIMEOUTS: c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 165; pub const _SC_2_PBS: c_int = 168; pub const _SC_2_PBS_ACCOUNTING: c_int = 169; pub const _SC_2_PBS_LOCATE: c_int = 170; pub const _SC_2_PBS_MESSAGE: c_int = 171; pub const _SC_2_PBS_TRACK: c_int = 172; pub const _SC_SYMLOOP_MAX: c_int = 173; pub const _SC_STREAMS: c_int = 174; pub const _SC_2_PBS_CHECKPOINT: c_int = 175; pub const _SC_V6_ILP32_OFF32: c_int = 176; pub const _SC_V6_ILP32_OFFBIG: c_int = 177; pub const _SC_V6_LP64_OFF64: c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: c_int = 179; pub const _SC_HOST_NAME_MAX: c_int = 180; pub const _SC_TRACE: c_int = 181; pub const _SC_TRACE_EVENT_FILTER: c_int = 182; pub const _SC_TRACE_INHERIT: c_int = 183; pub const _SC_TRACE_LOG: c_int = 184; pub const _SC_IPV6: c_int = 235; pub const _SC_RAW_SOCKETS: c_int = 236; pub const _SC_V7_ILP32_OFF32: c_int = 237; pub const _SC_V7_ILP32_OFFBIG: c_int = 238; pub const _SC_V7_LP64_OFF64: c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: c_int = 240; pub const _SC_SS_REPL_MAX: c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 242; pub const _SC_TRACE_NAME_MAX: c_int = 243; pub const _SC_TRACE_SYS_MAX: c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 245; pub const _SC_XOPEN_STREAMS: c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 248; // limits.h pub const PTHREAD_KEYS_MAX: c_int = 128; pub const PTHREAD_STACK_MIN: c_int = 2048; pub const PTHREAD_DESTRUCTOR_ITERATIONS: c_int = 4; pub const SEM_VALUE_MAX: c_int = 0x7fffffff; pub const SEM_NSEMS_MAX: c_int = 256; pub const DELAYTIMER_MAX: c_int = 0x7fffffff; pub const MQ_PRIO_MAX: c_int = 32768; pub const LOGIN_NAME_MAX: c_int = 256; // time.h pub const CLOCK_REALTIME: clockid_t = 0; pub const CLOCK_MONOTONIC: clockid_t = 1; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_MUTEX_STALLED: c_int = 0; pub const PTHREAD_MUTEX_ROBUST: c_int = 1; extern "C" { // ---- ALLOC ----------------------------------------------------------------------------- pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn aligned_alloc(align: size_t, len: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; // ----- PTHREAD --------------------------------------------------------------------------- pub fn pthread_self() -> pthread_t; pub fn pthread_join(native: pthread_t, value: *mut *mut c_void) -> c_int; // detach or pthread_attr_setdetachstate must not be called! //pub fn pthread_detach(thread: pthread_t) -> c_int; pub fn pthread_exit(value: *mut c_void) -> !; pub fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int; pub fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> c_int; pub fn pthread_attr_getstack( attr: *const pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, stack_size: size_t) -> c_int; pub fn pthread_attr_getstacksize(attr: *const pthread_attr_t, size: *mut size_t) -> c_int; pub fn pthread_attr_settee( attr: *mut pthread_attr_t, ca: c_int, task_id: c_int, shadow: c_int, ) -> c_int; // C-TA API do not include this interface, but TA can use. pub fn sched_yield() -> c_int; pub fn pthread_key_create( key: *mut pthread_key_t, dtor: Option, ) -> c_int; pub fn pthread_key_delete(key: pthread_key_t) -> c_int; pub fn pthread_getspecific(key: pthread_key_t) -> *mut c_void; pub fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int; pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_init( lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, ) -> c_int; pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int; pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int; pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: c_int) -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int; pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_cond_timedwait( cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t, abstime: *const timespec, ) -> c_int; pub fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robustness: c_int) -> c_int; pub fn pthread_create( native: *mut pthread_t, attr: *const pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_setschedprio(native: pthread_t, priority: c_int) -> c_int; pub fn pthread_once(pot: *mut pthread_once_t, f: Option) -> c_int; pub fn pthread_equal(p1: pthread_t, p2: pthread_t) -> c_int; pub fn pthread_mutexattr_setprotocol(a: *mut pthread_mutexattr_t, protocol: c_int) -> c_int; pub fn pthread_attr_setstack( attr: *mut pthread_attr_t, stack: *mut c_void, size: size_t, ) -> c_int; pub fn pthread_setaffinity_np(td: pthread_t, size: size_t, set: *const cpu_set_t) -> c_int; pub fn pthread_getaffinity_np(td: pthread_t, size: size_t, set: *mut cpu_set_t) -> c_int; // stdio.h pub fn printf(fmt: *const c_char, ...) -> c_int; pub fn scanf(fmt: *const c_char, ...) -> c_int; pub fn snprintf(s: *mut c_char, n: size_t, fmt: *const c_char, ...) -> c_int; pub fn sprintf(s: *mut c_char, fmt: *const c_char, ...) -> c_int; pub fn vsnprintf(s: *mut c_char, n: size_t, fmt: *const c_char, ap: va_list) -> c_int; pub fn vsprintf(s: *mut c_char, fmt: *const c_char, ap: va_list) -> c_int; // Not available. //pub fn pthread_setname_np(thread: pthread_t, name: *const c_char) -> c_int; pub fn abort() -> !; // Not available. //pub fn prctl(op: c_int, ...) -> c_int; pub fn sched_getaffinity(pid: pid_t, cpusetsize: size_t, cpuset: *mut cpu_set_t) -> c_int; pub fn sched_setaffinity(pid: pid_t, cpusetsize: size_t, cpuset: *const cpu_set_t) -> c_int; // sysconf is currently only implemented as a stub. pub fn sysconf(name: c_int) -> c_long; // mman.h pub fn mmap( addr: *mut c_void, len: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off_t, ) -> *mut c_void; pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; // errno.h pub fn __errno_location() -> *mut c_int; pub fn strerror(e: c_int) -> *mut c_char; // time.h pub fn clock_gettime(clock_id: clockid_t, tp: *mut timespec) -> c_int; // unistd pub fn getpid() -> pid_t; // time pub fn gettimeofday(tv: *mut timeval, tz: *mut c_void) -> c_int; pub fn strftime( restrict: *mut c_char, sz: size_t, _restrict: *const c_char, __restrict: *const tm, ) -> size_t; pub fn time(t: *mut time_t) -> time_t; // sem pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, valp: *mut c_int) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn sem_open(name: *const c_char, flags: c_int, ...) -> *mut sem_t; pub fn sem_post(sem: *mut sem_t) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn sem_wait(sem: *mut sem_t) -> c_int; // locale pub fn setlocale(cat: c_int, name: *const c_char) -> *mut c_char; pub fn strcoll(l: *const c_char, r: *const c_char) -> c_int; pub fn strxfrm(dest: *mut c_char, src: *const c_char, n: size_t) -> size_t; pub fn strtod(s: *const c_char, p: *mut *mut c_char) -> c_double; // multibyte pub fn mbrtowc(wc: *mut wchar_t, src: *const c_char, n: size_t, st: *mut mbstate_t) -> size_t; pub fn wcrtomb(s: *mut c_char, wc: wchar_t, st: *mut mbstate_t) -> size_t; pub fn wctob(c: wint_t) -> c_int; // prng pub fn srandom(seed: c_uint); pub fn initstate(seed: c_uint, state: *mut c_char, size: size_t) -> *mut c_char; pub fn setstate(state: *mut c_char) -> *mut c_char; pub fn random() -> c_long; // string pub fn strchr(s: *const c_char, c: c_int) -> *mut c_char; pub fn strlen(cs: *const c_char) -> size_t; pub fn strcmp(l: *const c_char, r: *const c_char) -> c_int; pub fn strcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncmp(_l: *const c_char, r: *const c_char, n: size_t) -> c_int; pub fn strncpy(dest: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strnlen(cs: *const c_char, n: size_t) -> size_t; pub fn strrchr(s: *const c_char, c: c_int) -> *mut c_char; pub fn strstr(h: *const c_char, n: *const c_char) -> *mut c_char; pub fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t; pub fn wcslen(s: *const wchar_t) -> size_t; // ctype pub fn isalpha(c: c_int) -> c_int; pub fn isascii(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn iswctype(wc: wint_t, ttype: wctype_t) -> c_int; pub fn iswdigit(wc: wint_t) -> c_int; pub fn iswlower(wc: wint_t) -> c_int; pub fn iswspace(wc: wint_t) -> c_int; pub fn iswupper(wc: wint_t) -> c_int; pub fn towupper(wc: wint_t) -> wint_t; pub fn towlower(wc: wint_t) -> wint_t; // cmath pub fn atan(x: c_double) -> c_double; pub fn ceil(x: c_double) -> c_double; pub fn ceilf(x: c_float) -> c_float; pub fn exp(x: c_double) -> c_double; pub fn fabs(x: c_double) -> c_double; pub fn floor(x: c_double) -> c_double; pub fn frexp(x: c_double, e: *mut c_int) -> c_double; pub fn log(x: c_double) -> c_double; pub fn log2(x: c_double) -> c_double; pub fn pow(x: c_double, y: c_double) -> c_double; pub fn roundf(x: c_float) -> c_float; pub fn scalbn(x: c_double, n: c_int) -> c_double; pub fn sqrt(x: c_double) -> c_double; // stdlib pub fn abs(x: c_int) -> c_int; pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn bsearch( key: *const c_void, base: *const c_void, nel: size_t, width: size_t, cmp: cmpfunc, ) -> *mut c_void; pub fn div(num: c_int, den: c_int) -> div_t; pub fn ecvt(x: c_double, n: c_int, dp: *mut c_int, sign: *mut c_int) -> *mut c_char; pub fn imaxabs(a: intmax_t) -> intmax_t; pub fn llabs(a: c_longlong) -> c_longlong; pub fn qsort(base: *mut c_void, nel: size_t, width: size_t, cmp: cmpfunc); pub fn strtoul(s: *const c_char, p: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtol(s: *const c_char, p: *mut *mut c_char, base: c_int) -> c_long; pub fn wcstod(s: *const wchar_t, p: *mut *mut wchar_t) -> c_double; } pub fn errno() -> c_int { unsafe { *__errno_location() } } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> c_int { let mut s: u32 = 0; let size_of_mask = core::mem::size_of_val(&cpuset.bits[0]); for i in cpuset.bits[..(size / size_of_mask)].iter() { s += i.count_ones(); } s as c_int } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> c_int { CPU_COUNT_S(core::mem::size_of::(), cpuset) } libc/src/psp.rs0000644000175000017500000036573215105742312013272 0ustar bdrungbdrung//! PSP C type definitions //! //! These type declarations are not enough, as they must be ultimately resolved //! by the linker. Crates that use these definitions must, somewhere in the //! crate graph, include a stub provider crate such as the `psp` crate. use crate::prelude::*; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type SceKernelVTimerHandler = unsafe extern "C" fn( uid: SceUid, arg1: *mut SceKernelSysClock, arg2: *mut SceKernelSysClock, arg3: *mut c_void, ) -> u32; pub type SceKernelVTimerHandlerWide = unsafe extern "C" fn(uid: SceUid, arg1: i64, arg2: i64, arg3: *mut c_void) -> u32; pub type SceKernelThreadEventHandler = unsafe extern "C" fn(mask: i32, thid: SceUid, common: *mut c_void) -> i32; pub type SceKernelAlarmHandler = unsafe extern "C" fn(common: *mut c_void) -> u32; pub type SceKernelCallbackFunction = unsafe extern "C" fn(arg1: i32, arg2: i32, arg: *mut c_void) -> i32; pub type SceKernelThreadEntry = unsafe extern "C" fn(args: usize, argp: *mut c_void) -> i32; pub type PowerCallback = extern "C" fn(unknown: i32, power_info: i32); pub type IoPermissions = i32; pub type UmdCallback = fn(unknown: i32, event: i32) -> i32; pub type SceMpegRingbufferCb = Option i32>; pub type GuCallback = Option; pub type GuSwapBuffersCallback = Option; pub type SceNetAdhocctlHandler = Option; pub type AdhocMatchingCallback = Option< unsafe extern "C" fn( matching_id: i32, event: i32, mac: *mut u8, opt_len: i32, opt_data: *mut c_void, ), >; pub type SceNetApctlHandler = Option< unsafe extern "C" fn(oldState: i32, newState: i32, event: i32, error: i32, pArg: *mut c_void), >; pub type HttpMallocFunction = Option *mut c_void>; pub type HttpReallocFunction = Option *mut c_void>; pub type HttpFreeFunction = Option; pub type HttpPasswordCB = Option< unsafe extern "C" fn( request: i32, auth_type: HttpAuthType, realm: *const u8, username: *mut u8, password: *mut u8, need_entity: i32, entity_body: *mut *mut u8, entity_size: *mut usize, save: *mut i32, ) -> i32, >; pub type socklen_t = u32; e! { #[repr(u32)] pub enum AudioFormat { Stereo = 0, Mono = 0x10, } #[repr(u32)] pub enum DisplayMode { Lcd = 0, } #[repr(u32)] pub enum DisplayPixelFormat { Psm5650 = 0, Psm5551 = 1, Psm4444 = 2, Psm8888 = 3, } #[repr(u32)] pub enum DisplaySetBufSync { Immediate = 0, NextFrame = 1, } #[repr(i32)] pub enum AudioOutputFrequency { Khz48 = 48000, Khz44_1 = 44100, Khz32 = 32000, Khz24 = 24000, Khz22_05 = 22050, Khz16 = 16000, Khz12 = 12000, Khz11_025 = 11025, Khz8 = 8000, } #[repr(i32)] pub enum AudioInputFrequency { Khz44_1 = 44100, Khz22_05 = 22050, Khz11_025 = 11025, } #[repr(u32)] pub enum CtrlMode { Digital = 0, Analog, } #[repr(i32)] pub enum GeMatrixType { Bone0 = 0, Bone1, Bone2, Bone3, Bone4, Bone5, Bone6, Bone7, World, View, Projection, TexGen, } #[repr(i32)] pub enum GeListState { Done = 0, Queued, DrawingDone, StallReached, CancelDone, } #[repr(u8)] pub enum GeCommand { Nop = 0, Vaddr = 0x1, Iaddr = 0x2, Prim = 0x4, Bezier = 0x5, Spline = 0x6, BoundingBox = 0x7, Jump = 0x8, BJump = 0x9, Call = 0xa, Ret = 0xb, End = 0xc, Signal = 0xe, Finish = 0xf, Base = 0x10, VertexType = 0x12, OffsetAddr = 0x13, Origin = 0x14, Region1 = 0x15, Region2 = 0x16, LightingEnable = 0x17, LightEnable0 = 0x18, LightEnable1 = 0x19, LightEnable2 = 0x1a, LightEnable3 = 0x1b, DepthClampEnable = 0x1c, CullFaceEnable = 0x1d, TextureMapEnable = 0x1e, FogEnable = 0x1f, DitherEnable = 0x20, AlphaBlendEnable = 0x21, AlphaTestEnable = 0x22, ZTestEnable = 0x23, StencilTestEnable = 0x24, AntiAliasEnable = 0x25, PatchCullEnable = 0x26, ColorTestEnable = 0x27, LogicOpEnable = 0x28, BoneMatrixNumber = 0x2a, BoneMatrixData = 0x2b, MorphWeight0 = 0x2c, MorphWeight1 = 0x2d, MorphWeight2 = 0x2e, MorphWeight3 = 0x2f, MorphWeight4 = 0x30, MorphWeight5 = 0x31, MorphWeight6 = 0x32, MorphWeight7 = 0x33, PatchDivision = 0x36, PatchPrimitive = 0x37, PatchFacing = 0x38, WorldMatrixNumber = 0x3a, WorldMatrixData = 0x3b, ViewMatrixNumber = 0x3c, ViewMatrixData = 0x3d, ProjMatrixNumber = 0x3e, ProjMatrixData = 0x3f, TGenMatrixNumber = 0x40, TGenMatrixData = 0x41, ViewportXScale = 0x42, ViewportYScale = 0x43, ViewportZScale = 0x44, ViewportXCenter = 0x45, ViewportYCenter = 0x46, ViewportZCenter = 0x47, TexScaleU = 0x48, TexScaleV = 0x49, TexOffsetU = 0x4a, TexOffsetV = 0x4b, OffsetX = 0x4c, OffsetY = 0x4d, ShadeMode = 0x50, ReverseNormal = 0x51, MaterialUpdate = 0x53, MaterialEmissive = 0x54, MaterialAmbient = 0x55, MaterialDiffuse = 0x56, MaterialSpecular = 0x57, MaterialAlpha = 0x58, MaterialSpecularCoef = 0x5b, AmbientColor = 0x5c, AmbientAlpha = 0x5d, LightMode = 0x5e, LightType0 = 0x5f, LightType1 = 0x60, LightType2 = 0x61, LightType3 = 0x62, Light0X = 0x63, Light0Y, Light0Z, Light1X, Light1Y, Light1Z, Light2X, Light2Y, Light2Z, Light3X, Light3Y, Light3Z, Light0DirectionX = 0x6f, Light0DirectionY, Light0DirectionZ, Light1DirectionX, Light1DirectionY, Light1DirectionZ, Light2DirectionX, Light2DirectionY, Light2DirectionZ, Light3DirectionX, Light3DirectionY, Light3DirectionZ, Light0ConstantAtten = 0x7b, Light0LinearAtten, Light0QuadtraticAtten, Light1ConstantAtten, Light1LinearAtten, Light1QuadtraticAtten, Light2ConstantAtten, Light2LinearAtten, Light2QuadtraticAtten, Light3ConstantAtten, Light3LinearAtten, Light3QuadtraticAtten, Light0ExponentAtten = 0x87, Light1ExponentAtten, Light2ExponentAtten, Light3ExponentAtten, Light0CutoffAtten = 0x8b, Light1CutoffAtten, Light2CutoffAtten, Light3CutoffAtten, Light0Ambient = 0x8f, Light0Diffuse, Light0Specular, Light1Ambient, Light1Diffuse, Light1Specular, Light2Ambient, Light2Diffuse, Light2Specular, Light3Ambient, Light3Diffuse, Light3Specular, Cull = 0x9b, FrameBufPtr = 0x9c, FrameBufWidth = 0x9d, ZBufPtr = 0x9e, ZBufWidth = 0x9f, TexAddr0 = 0xa0, TexAddr1, TexAddr2, TexAddr3, TexAddr4, TexAddr5, TexAddr6, TexAddr7, TexBufWidth0 = 0xa8, TexBufWidth1, TexBufWidth2, TexBufWidth3, TexBufWidth4, TexBufWidth5, TexBufWidth6, TexBufWidth7, ClutAddr = 0xb0, ClutAddrUpper = 0xb1, TransferSrc, TransferSrcW, TransferDst, TransferDstW, TexSize0 = 0xb8, TexSize1, TexSize2, TexSize3, TexSize4, TexSize5, TexSize6, TexSize7, TexMapMode = 0xc0, TexShadeLs = 0xc1, TexMode = 0xc2, TexFormat = 0xc3, LoadClut = 0xc4, ClutFormat = 0xc5, TexFilter = 0xc6, TexWrap = 0xc7, TexLevel = 0xc8, TexFunc = 0xc9, TexEnvColor = 0xca, TexFlush = 0xcb, TexSync = 0xcc, Fog1 = 0xcd, Fog2 = 0xce, FogColor = 0xcf, TexLodSlope = 0xd0, FramebufPixFormat = 0xd2, ClearMode = 0xd3, Scissor1 = 0xd4, Scissor2 = 0xd5, MinZ = 0xd6, MaxZ = 0xd7, ColorTest = 0xd8, ColorRef = 0xd9, ColorTestmask = 0xda, AlphaTest = 0xdb, StencilTest = 0xdc, StencilOp = 0xdd, ZTest = 0xde, BlendMode = 0xdf, BlendFixedA = 0xe0, BlendFixedB = 0xe1, Dith0 = 0xe2, Dith1, Dith2, Dith3, LogicOp = 0xe6, ZWriteDisable = 0xe7, MaskRgb = 0xe8, MaskAlpha = 0xe9, TransferStart = 0xea, TransferSrcPos = 0xeb, TransferDstPos = 0xec, TransferSize = 0xee, Vscx = 0xf0, Vscy = 0xf1, Vscz = 0xf2, Vtcs = 0xf3, Vtct = 0xf4, Vtcq = 0xf5, Vcv = 0xf6, Vap = 0xf7, Vfc = 0xf8, Vscv = 0xf9, Unknown03 = 0x03, Unknown0D = 0x0d, Unknown11 = 0x11, Unknown29 = 0x29, Unknown34 = 0x34, Unknown35 = 0x35, Unknown39 = 0x39, Unknown4E = 0x4e, Unknown4F = 0x4f, Unknown52 = 0x52, Unknown59 = 0x59, Unknown5A = 0x5a, UnknownB6 = 0xb6, UnknownB7 = 0xb7, UnknownD1 = 0xd1, UnknownED = 0xed, UnknownEF = 0xef, UnknownFA = 0xfa, UnknownFB = 0xfb, UnknownFC = 0xfc, UnknownFD = 0xfd, UnknownFE = 0xfe, NopFF = 0xff, } #[repr(i32)] pub enum SceSysMemPartitionId { SceKernelUnknownPartition = 0, SceKernelPrimaryKernelPartition = 1, SceKernelPrimaryUserPartition = 2, SceKernelOtherKernelPartition1 = 3, SceKernelOtherKernelPartition2 = 4, SceKernelVshellPARTITION = 5, SceKernelScUserPartition = 6, SceKernelMeUserPartition = 7, SceKernelExtendedScKernelPartition = 8, SceKernelExtendedSc2KernelPartition = 9, SceKernelExtendedMeKernelPartition = 10, SceKernelVshellKernelPartition = 11, SceKernelExtendedKernelPartition = 12, } #[repr(i32)] pub enum SceSysMemBlockTypes { Low = 0, High, Addr, } #[repr(u32)] pub enum Interrupt { Gpio = 4, Ata = 5, Umd = 6, Mscm0 = 7, Wlan = 8, Audio = 10, I2c = 12, Sircs = 14, Systimer0 = 15, Systimer1 = 16, Systimer2 = 17, Systimer3 = 18, Thread0 = 19, Nand = 20, Dmacplus = 21, Dma0 = 22, Dma1 = 23, Memlmd = 24, Ge = 25, Vblank = 30, Mecodec = 31, Hpremote = 36, Mscm1 = 60, Mscm2 = 61, Thread1 = 65, Interrupt = 66, } #[repr(u32)] pub enum SubInterrupt { Gpio = Interrupt::Gpio as u32, Ata = Interrupt::Ata as u32, Umd = Interrupt::Umd as u32, Dmacplus = Interrupt::Dmacplus as u32, Ge = Interrupt::Ge as u32, Display = Interrupt::Vblank as u32, } #[repr(u32)] pub enum SceKernelIdListType { Thread = 1, Semaphore = 2, EventFlag = 3, Mbox = 4, Vpl = 5, Fpl = 6, Mpipe = 7, Callback = 8, ThreadEventHandler = 9, Alarm = 10, VTimer = 11, SleepThread = 64, DelayThread = 65, SuspendThread = 66, DormantThread = 67, } #[repr(i32)] pub enum UsbCamResolution { Px160_120 = 0, Px176_144 = 1, Px320_240 = 2, Px352_288 = 3, Px640_480 = 4, Px1024_768 = 5, Px1280_960 = 6, Px480_272 = 7, Px360_272 = 8, } #[repr(i32)] pub enum UsbCamResolutionEx { Px160_120 = 0, Px176_144 = 1, Px320_240 = 2, Px352_288 = 3, Px360_272 = 4, Px480_272 = 5, Px640_480 = 6, Px1024_768 = 7, Px1280_960 = 8, } #[repr(i32)] pub enum UsbCamDelay { NoDelay = 0, Delay10Sec = 1, Delay20Sec = 2, Delay30Sec = 3, } #[repr(i32)] pub enum UsbCamFrameRate { Fps3_75 = 0, Fps5 = 1, Fps7_5 = 2, Fps10 = 3, Fps15 = 4, Fps20 = 5, Fps30 = 6, Fps60 = 7, } #[repr(i32)] pub enum UsbCamWb { Auto = 0, Daylight = 1, Fluorescent = 2, Incadescent = 3, } #[repr(i32)] pub enum UsbCamEffectMode { Normal = 0, Negative = 1, Blackwhite = 2, Sepia = 3, Blue = 4, Red = 5, Green = 6, } #[repr(i32)] pub enum UsbCamEvLevel { Pos2_0 = 0, Pos1_7 = 1, Pos1_5 = 2, Pos1_3 = 3, Pos1_0 = 4, Pos0_7 = 5, Pos0_5 = 6, Pos0_3 = 7, Zero = 8, Neg0_3, Neg0_5, Neg0_7, Neg1_0, Neg1_3, Neg1_5, Neg1_7, Neg2_0, } #[repr(i32)] pub enum RtcCheckValidError { InvalidYear = -1, InvalidMonth = -2, InvalidDay = -3, InvalidHour = -4, InvalidMinutes = -5, InvalidSeconds = -6, InvalidMicroseconds = -7, } #[repr(u32)] pub enum PowerTick { All = 0, Suspend = 1, Display = 6, } #[repr(u32)] pub enum IoAssignPerms { RdWr = 0, RdOnly = 1, } #[repr(u32)] pub enum IoWhence { Set = 0, Cur = 1, End = 2, } #[repr(u32)] pub enum UmdType { Game = 0x10, Video = 0x20, Audio = 0x40, } #[repr(u32)] pub enum GuPrimitive { Points = 0, Lines = 1, LineStrip = 2, Triangles = 3, TriangleStrip = 4, TriangleFan = 5, Sprites = 6, } #[repr(u32)] pub enum PatchPrimitive { Points = 0, LineStrip = 2, TriangleStrip = 4, } #[repr(u32)] pub enum GuState { AlphaTest = 0, DepthTest = 1, ScissorTest = 2, StencilTest = 3, Blend = 4, CullFace = 5, Dither = 6, Fog = 7, ClipPlanes = 8, Texture2D = 9, Lighting = 10, Light0 = 11, Light1 = 12, Light2 = 13, Light3 = 14, LineSmooth = 15, PatchCullFace = 16, ColorTest = 17, ColorLogicOp = 18, FaceNormalReverse = 19, PatchFace = 20, Fragment2X = 21, } #[repr(u32)] pub enum MatrixMode { Projection = 0, View = 1, Model = 2, Texture = 3, } #[repr(u32)] pub enum TexturePixelFormat { Psm5650 = 0, Psm5551 = 1, Psm4444 = 2, Psm8888 = 3, PsmT4 = 4, PsmT8 = 5, PsmT16 = 6, PsmT32 = 7, PsmDxt1 = 8, PsmDxt3 = 9, PsmDxt5 = 10, } #[repr(u32)] pub enum SplineMode { FillFill = 0, OpenFill = 1, FillOpen = 2, OpenOpen = 3, } #[repr(u32)] pub enum ShadingModel { Flat = 0, Smooth = 1, } #[repr(u32)] pub enum LogicalOperation { Clear = 0, And = 1, AndReverse = 2, Copy = 3, AndInverted = 4, Noop = 5, Xor = 6, Or = 7, Nor = 8, Equiv = 9, Inverted = 10, OrReverse = 11, CopyInverted = 12, OrInverted = 13, Nand = 14, Set = 15, } #[repr(u32)] pub enum TextureFilter { Nearest = 0, Linear = 1, NearestMipmapNearest = 4, LinearMipmapNearest = 5, NearestMipmapLinear = 6, LinearMipmapLinear = 7, } #[repr(u32)] pub enum TextureMapMode { TextureCoords = 0, TextureMatrix = 1, EnvironmentMap = 2, } #[repr(u32)] pub enum TextureLevelMode { Auto = 0, Const = 1, Slope = 2, } #[repr(u32)] pub enum TextureProjectionMapMode { Position = 0, Uv = 1, NormalizedNormal = 2, Normal = 3, } #[repr(u32)] pub enum GuTexWrapMode { Repeat = 0, Clamp = 1, } #[repr(u32)] pub enum FrontFaceDirection { Clockwise = 0, CounterClockwise = 1, } #[repr(u32)] pub enum AlphaFunc { Never = 0, Always, Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual, } #[repr(u32)] pub enum StencilFunc { Never = 0, Always, Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual, } #[repr(u32)] pub enum ColorFunc { Never = 0, Always, Equal, NotEqual, } #[repr(u32)] pub enum DepthFunc { Never = 0, Always, Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual, } #[repr(u32)] pub enum TextureEffect { Modulate = 0, Decal = 1, Blend = 2, Replace = 3, Add = 4, } #[repr(u32)] pub enum TextureColorComponent { Rgb = 0, Rgba = 1, } #[repr(u32)] pub enum MipmapLevel { None = 0, Level1, Level2, Level3, Level4, Level5, Level6, Level7, } #[repr(u32)] pub enum BlendOp { Add = 0, Subtract = 1, ReverseSubtract = 2, Min = 3, Max = 4, Abs = 5, } #[repr(u32)] pub enum BlendSrc { SrcColor = 0, OneMinusSrcColor = 1, SrcAlpha = 2, OneMinusSrcAlpha = 3, Fix = 10, } #[repr(u32)] pub enum BlendDst { DstColor = 0, OneMinusDstColor = 1, DstAlpha = 4, OneMinusDstAlpha = 5, Fix = 10, } #[repr(u32)] pub enum StencilOperation { Keep = 0, Zero = 1, Replace = 2, Invert = 3, Incr = 4, Decr = 5, } #[repr(u32)] pub enum LightMode { SingleColor = 0, SeparateSpecularColor = 1, } #[repr(u32)] pub enum LightType { Directional = 0, Pointlight = 1, Spotlight = 2, } #[repr(u32)] pub enum GuContextType { Direct = 0, Call = 1, Send = 2, } #[repr(u32)] pub enum GuQueueMode { Tail = 0, Head = 1, } #[repr(u32)] pub enum GuSyncMode { Finish = 0, Signal = 1, Done = 2, List = 3, Send = 4, } #[repr(u32)] pub enum GuSyncBehavior { Wait = 0, NoWait = 1, } #[repr(u32)] pub enum GuCallbackId { Signal = 1, Finish = 4, } #[repr(u32)] pub enum SignalBehavior { Suspend = 1, Continue = 2, } #[repr(u32)] pub enum ClutPixelFormat { Psm5650 = 0, Psm5551 = 1, Psm4444 = 2, Psm8888 = 3, } #[repr(C)] pub enum KeyType { Directory = 1, Integer = 2, String = 3, Bytes = 4, } #[repr(u32)] pub enum UtilityMsgDialogMode { Error, Text, } #[repr(u32)] pub enum UtilityMsgDialogPressed { Unknown1, Yes, No, Back, } #[repr(u32)] pub enum UtilityDialogButtonAccept { Circle, Cross, } #[repr(u32)] pub enum SceUtilityOskInputLanguage { Default, Japanese, English, French, Spanish, German, Italian, Dutch, Portugese, Russian, Korean, } #[repr(u32)] pub enum SceUtilityOskInputType { All, LatinDigit, LatinSymbol, LatinLowercase = 4, LatinUppercase = 8, JapaneseDigit = 0x100, JapaneseSymbol = 0x200, JapaneseLowercase = 0x400, JapaneseUppercase = 0x800, JapaneseHiragana = 0x1000, JapaneseHalfWidthKatakana = 0x2000, JapaneseKatakana = 0x4000, JapaneseKanji = 0x8000, RussianLowercase = 0x10000, RussianUppercase = 0x20000, Korean = 0x40000, Url = 0x80000, } #[repr(u32)] pub enum SceUtilityOskState { None, Initializing, Initialized, Visible, Quit, Finished, } #[repr(u32)] pub enum SceUtilityOskResult { Unchanged, Cancelled, Changed, } #[repr(u32)] pub enum SystemParamLanguage { Japanese, English, French, Spanish, German, Italian, Dutch, Portugese, Russian, Korean, ChineseTraditional, ChineseSimplified, } #[repr(u32)] pub enum SystemParamId { StringNickname = 1, AdhocChannel, WlanPowerSave, DateFormat, TimeFormat, Timezone, DaylightSavings, Language, Unknown, } #[repr(u32)] pub enum SystemParamAdhocChannel { ChannelAutomatic = 0, Channel1 = 1, Channel6 = 6, Channel11 = 11, } #[repr(u32)] pub enum SystemParamWlanPowerSaveState { Off, On, } #[repr(u32)] pub enum SystemParamDateFormat { YYYYMMDD, MMDDYYYY, DDMMYYYY, } #[repr(u32)] pub enum SystemParamTimeFormat { Hour24, Hour12, } #[repr(u32)] pub enum SystemParamDaylightSavings { Std, Dst, } #[repr(u32)] pub enum AvModule { AvCodec, SasCore, Atrac3Plus, MpegBase, Mp3, Vaudio, Aac, G729, } #[repr(u32)] pub enum Module { NetCommon = 0x100, NetAdhoc, NetInet, NetParseUri, NetHttp, NetSsl, UsbPspCm = 0x200, UsbMic, UsbCam, UsbGps, AvCodec = 0x300, AvSascore, AvAtrac3Plus, AvMpegBase, AvMp3, AvVaudio, AvAac, AvG729, NpCommon = 0x400, NpService, NpMatching2, NpDrm = 0x500, Irda = 0x600, } #[repr(u32)] pub enum NetModule { NetCommon = 1, NetAdhoc, NetInet, NetParseUri, NetHttp, NetSsl, } #[repr(u32)] pub enum UsbModule { UsbPspCm = 1, UsbAcc, UsbMic, UsbCam, UsbGps, } #[repr(u32)] pub enum NetParam { Name, Ssid, Secure, WepKey, IsStaticIp, Ip, NetMask, Route, ManualDns, PrimaryDns, SecondaryDns, ProxyUser, ProxyPass, UseProxy, ProxyServer, ProxyPort, Unknown1, Unknown2, } #[repr(u32)] pub enum UtilityNetconfAction { ConnectAP, DisplayStatus, ConnectAdhoc, } #[repr(u32)] pub enum UtilitySavedataMode { AutoLoad, AutoSave, Load, Save, ListLoad, ListSave, ListDelete, Delete, } #[repr(u32)] pub enum UtilitySavedataFocus { Unknown1, FirstList, LastList, Latest, Oldest, Unknown2, Unknown3, FirstEmpty, LastEmpty, } #[repr(u32)] pub enum UtilityGameSharingMode { Single = 1, Multiple, } #[repr(u32)] pub enum UtilityGameSharingDataType { File = 1, Memory, } #[repr(u32)] pub enum UtilityHtmlViewerInterfaceMode { Full, Limited, None, } #[repr(u32)] pub enum UtilityHtmlViewerCookieMode { Disabled = 0, Enabled, Confirm, Default, } #[repr(u32)] pub enum UtilityHtmlViewerTextSize { Large, Normal, Small, } #[repr(u32)] pub enum UtilityHtmlViewerDisplayMode { Normal, Fit, SmartFit, } #[repr(u32)] pub enum UtilityHtmlViewerConnectMode { Last, ManualOnce, ManualAll, } #[repr(u32)] pub enum UtilityHtmlViewerDisconnectMode { Enable, Disable, Confirm, } #[repr(u32)] pub enum ScePspnetAdhocPtpState { Closed, Listen, SynSent, SynReceived, Established, } #[repr(u32)] pub enum AdhocMatchingMode { Host = 1, Client, Ptp, } #[repr(u32)] pub enum ApctlState { Disconnected, Scanning, Joining, GettingIp, GotIp, EapAuth, KeyExchange, } #[repr(u32)] pub enum ApctlEvent { ConnectRequest, ScanRequest, ScanComplete, Established, GetIp, DisconnectRequest, Error, Info, EapAuth, KeyExchange, Reconnect, } #[repr(u32)] pub enum ApctlInfo { ProfileName, Bssid, Ssid, SsidLength, SecurityType, Strength, Channel, PowerSave, Ip, SubnetMask, Gateway, PrimaryDns, SecondaryDns, UseProxy, ProxyUrl, ProxyPort, EapType, StartBrowser, Wifisp, } #[repr(u32)] pub enum ApctlInfoSecurityType { None, Wep, Wpa, } #[repr(u32)] pub enum HttpMethod { Get, Post, Head, } #[repr(u32)] pub enum HttpAuthType { Basic, Digest, } } s_paren! { #[repr(transparent)] pub struct SceUid(pub i32); #[repr(transparent)] #[allow(dead_code)] pub struct SceMpeg(*mut *mut c_void); #[repr(transparent)] #[allow(dead_code)] pub struct SceMpegStream(*mut c_void); #[repr(transparent)] pub struct Mp3Handle(pub i32); #[repr(transparent)] #[allow(dead_code)] pub struct RegHandle(u32); } s! { pub struct sockaddr { pub sa_len: u8, pub sa_family: u8, pub sa_data: [u8; 14], } pub struct in_addr { pub s_addr: u32, } pub struct AudioInputParams { pub unknown1: i32, pub gain: i32, pub unknown2: i32, pub unknown3: i32, pub unknown4: i32, pub unknown5: i32, } pub struct Atrac3BufferInfo { pub puc_write_position_first_buf: *mut u8, pub ui_writable_byte_first_buf: u32, pub ui_min_write_byte_first_buf: u32, pub ui_read_position_first_buf: u32, pub puc_write_position_second_buf: *mut u8, pub ui_writable_byte_second_buf: u32, pub ui_min_write_byte_second_buf: u32, pub ui_read_position_second_buf: u32, } pub struct SceCtrlData { pub timestamp: u32, pub buttons: i32, pub lx: u8, pub ly: u8, pub rsrv: [u8; 6], } pub struct SceCtrlLatch { pub ui_make: u32, pub ui_break: u32, pub ui_press: u32, pub ui_release: u32, } pub struct GeStack { pub stack: [u32; 8], } pub struct GeCallbackData { pub signal_func: Option, pub signal_arg: *mut c_void, pub finish_func: Option, pub finish_arg: *mut c_void, } pub struct GeListArgs { pub size: u32, pub context: *mut GeContext, pub num_stacks: u32, pub stacks: *mut GeStack, } pub struct GeBreakParam { pub buf: [u32; 4], } pub struct SceKernelLoadExecParam { pub size: usize, pub args: usize, pub argp: *mut c_void, pub key: *const u8, } pub struct timeval { pub tv_sec: i32, pub tv_usec: i32, } pub struct timezone { pub tz_minutes_west: i32, pub tz_dst_time: i32, } pub struct IntrHandlerOptionParam { size: i32, entry: u32, common: u32, gp: u32, intr_code: u16, sub_count: u16, intr_level: u16, enabled: u16, calls: u32, field_1c: u32, total_clock_lo: u32, total_clock_hi: u32, min_clock_lo: u32, min_clock_hi: u32, max_clock_lo: u32, max_clock_hi: u32, } pub struct SceKernelLMOption { pub size: usize, pub m_pid_text: SceUid, pub m_pid_data: SceUid, pub flags: u32, pub position: u8, pub access: u8, pub c_reserved: [u8; 2usize], } pub struct SceKernelSMOption { pub size: usize, pub m_pid_stack: SceUid, pub stack_size: usize, pub priority: i32, pub attribute: u32, } pub struct SceKernelModuleInfo { pub size: usize, pub n_segment: u8, pub reserved: [u8; 3usize], pub segment_addr: [i32; 4usize], pub segment_size: [i32; 4usize], pub entry_addr: u32, pub gp_value: u32, pub text_addr: u32, pub text_size: u32, pub data_size: u32, pub bss_size: u32, pub attribute: u16, pub version: [u8; 2usize], pub name: [u8; 28usize], } pub struct DebugProfilerRegs { pub enable: u32, pub systemck: u32, pub cpuck: u32, pub internal: u32, pub memory: u32, pub copz: u32, pub vfpu: u32, pub sleep: u32, pub bus_access: u32, pub uncached_load: u32, pub uncached_store: u32, pub cached_load: u32, pub cached_store: u32, pub i_miss: u32, pub d_miss: u32, pub d_writeback: u32, pub cop0_inst: u32, pub fpu_inst: u32, pub vfpu_inst: u32, pub local_bus: u32, } pub struct SceKernelSysClock { pub low: u32, pub hi: u32, } pub struct SceKernelThreadOptParam { pub size: usize, pub stack_mpid: SceUid, } pub struct SceKernelThreadInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub status: i32, pub entry: SceKernelThreadEntry, pub stack: *mut c_void, pub stack_size: i32, pub gp_reg: *mut c_void, pub init_priority: i32, pub current_priority: i32, pub wait_type: i32, pub wait_id: SceUid, pub wakeup_count: i32, pub exit_status: i32, pub run_clocks: SceKernelSysClock, pub intr_preempt_count: u32, pub thread_preempt_count: u32, pub release_count: u32, } pub struct SceKernelThreadRunStatus { pub size: usize, pub status: i32, pub current_priority: i32, pub wait_type: i32, pub wait_id: i32, pub wakeup_count: i32, pub run_clocks: SceKernelSysClock, pub intr_preempt_count: u32, pub thread_preempt_count: u32, pub release_count: u32, } pub struct SceKernelSemaOptParam { pub size: usize, } pub struct SceKernelSemaInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub init_count: i32, pub current_count: i32, pub max_count: i32, pub num_wait_threads: i32, } pub struct SceKernelEventFlagInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub init_pattern: u32, pub current_pattern: u32, pub num_wait_threads: i32, } pub struct SceKernelEventFlagOptParam { pub size: usize, } pub struct SceKernelMbxOptParam { pub size: usize, } pub struct SceKernelMbxInfo { pub size: usize, pub name: [u8; 32usize], pub attr: u32, pub num_wait_threads: i32, pub num_messages: i32, pub first_message: *mut c_void, } pub struct SceKernelVTimerInfo { pub size: usize, pub name: [u8; 32], pub active: i32, pub base: SceKernelSysClock, pub current: SceKernelSysClock, pub schedule: SceKernelSysClock, pub handler: SceKernelVTimerHandler, pub common: *mut c_void, } pub struct SceKernelThreadEventHandlerInfo { pub size: usize, pub name: [u8; 32], pub thread_id: SceUid, pub mask: i32, pub handler: SceKernelThreadEventHandler, pub common: *mut c_void, } pub struct SceKernelAlarmInfo { pub size: usize, pub schedule: SceKernelSysClock, pub handler: SceKernelAlarmHandler, pub common: *mut c_void, } pub struct SceKernelSystemStatus { pub size: usize, pub status: u32, pub idle_clocks: SceKernelSysClock, pub comes_out_of_idle_count: u32, pub thread_switch_count: u32, pub vfpu_switch_count: u32, } pub struct SceKernelMppInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub buf_size: i32, pub free_size: i32, pub num_send_wait_threads: i32, pub num_receive_wait_threads: i32, } pub struct SceKernelVplOptParam { pub size: usize, } pub struct SceKernelVplInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub pool_size: i32, pub free_size: i32, pub num_wait_threads: i32, } pub struct SceKernelFplOptParam { pub size: usize, } pub struct SceKernelFplInfo { pub size: usize, pub name: [u8; 32usize], pub attr: u32, pub block_size: i32, pub num_blocks: i32, pub free_blocks: i32, pub num_wait_threads: i32, } pub struct SceKernelVTimerOptParam { pub size: usize, } pub struct SceKernelCallbackInfo { pub size: usize, pub name: [u8; 32usize], pub thread_id: SceUid, pub callback: SceKernelCallbackFunction, pub common: *mut c_void, pub notify_count: i32, pub notify_arg: i32, } pub struct UsbCamSetupStillParam { pub size: i32, pub resolution: UsbCamResolution, pub jpeg_size: i32, pub reverse_flags: i32, pub delay: UsbCamDelay, pub comp_level: i32, } pub struct UsbCamSetupStillExParam { pub size: i32, pub unk: u32, pub resolution: UsbCamResolutionEx, pub jpeg_size: i32, pub comp_level: i32, pub unk2: u32, pub unk3: u32, pub flip: i32, pub mirror: i32, pub delay: UsbCamDelay, pub unk4: [u32; 5usize], } pub struct UsbCamSetupVideoParam { pub size: i32, pub resolution: UsbCamResolution, pub framerate: UsbCamFrameRate, pub white_balance: UsbCamWb, pub saturation: i32, pub brightness: i32, pub contrast: i32, pub sharpness: i32, pub effect_mode: UsbCamEffectMode, pub frame_size: i32, pub unk: u32, pub evl_evel: UsbCamEvLevel, } pub struct UsbCamSetupVideoExParam { pub size: i32, pub unk: u32, pub resolution: UsbCamResolutionEx, pub framerate: UsbCamFrameRate, pub unk2: u32, pub unk3: u32, pub white_balance: UsbCamWb, pub saturation: i32, pub brightness: i32, pub contrast: i32, pub sharpness: i32, pub unk4: u32, pub unk5: u32, pub unk6: [u32; 3usize], pub effect_mode: UsbCamEffectMode, pub unk7: u32, pub unk8: u32, pub unk9: u32, pub unk10: u32, pub unk11: u32, pub frame_size: i32, pub unk12: u32, pub ev_level: UsbCamEvLevel, } pub struct ScePspDateTime { pub year: u16, pub month: u16, pub day: u16, pub hour: u16, pub minutes: u16, pub seconds: u16, pub microseconds: u32, } pub struct SceIoStat { pub st_mode: i32, pub st_attr: i32, pub st_size: i64, pub st_ctime: ScePspDateTime, pub st_atime: ScePspDateTime, pub st_mtime: ScePspDateTime, pub st_private: [u32; 6usize], } pub struct UmdInfo { pub size: u32, pub type_: UmdType, } pub struct SceMpegRingbuffer { pub packets: i32, pub unk0: u32, pub unk1: u32, pub unk2: u32, pub unk3: u32, pub data: *mut c_void, pub callback: SceMpegRingbufferCb, pub cb_param: *mut c_void, pub unk4: u32, pub unk5: u32, pub sce_mpeg: *mut c_void, } pub struct SceMpegAu { pub pts_msb: u32, pub pts: u32, pub dts_msb: u32, pub dts: u32, pub es_buffer: u32, pub au_size: u32, } pub struct SceMpegAvcMode { pub unk0: i32, pub pixel_format: super::DisplayPixelFormat, } #[repr(align(64))] pub struct SceMpegLLI { pub src: *mut c_void, pub dst: *mut c_void, pub next: *mut c_void, pub size: i32, } #[repr(align(64))] pub struct SceMpegYCrCbBuffer { pub frame_buffer_height16: i32, pub frame_buffer_width16: i32, pub unknown: i32, pub unknown2: i32, pub y_buffer: *mut c_void, pub y_buffer2: *mut c_void, pub cr_buffer: *mut c_void, pub cb_buffer: *mut c_void, pub cr_buffer2: *mut c_void, pub cb_buffer2: *mut c_void, pub frame_height: i32, pub frame_width: i32, pub frame_buffer_width: i32, pub unknown3: [i32; 11usize], } pub struct ScePspSRect { pub x: i16, pub y: i16, pub w: i16, pub h: i16, } pub struct ScePspIRect { pub x: i32, pub y: i32, pub w: i32, pub h: i32, } pub struct ScePspL64Rect { pub x: u64, pub y: u64, pub w: u64, pub h: u64, } pub struct ScePspSVector2 { pub x: i16, pub y: i16, } pub struct ScePspIVector2 { pub x: i32, pub y: i32, } pub struct ScePspL64Vector2 { pub x: u64, pub y: u64, } pub struct ScePspSVector3 { pub x: i16, pub y: i16, pub z: i16, } pub struct ScePspIVector3 { pub x: i32, pub y: i32, pub z: i32, } pub struct ScePspL64Vector3 { pub x: u64, pub y: u64, pub z: u64, } pub struct ScePspSVector4 { pub x: i16, pub y: i16, pub z: i16, pub w: i16, } pub struct ScePspIVector4 { pub x: i32, pub y: i32, pub z: i32, pub w: i32, } pub struct ScePspL64Vector4 { pub x: u64, pub y: u64, pub z: u64, pub w: u64, } pub struct ScePspIMatrix2 { pub x: ScePspIVector2, pub y: ScePspIVector2, } pub struct ScePspIMatrix3 { pub x: ScePspIVector3, pub y: ScePspIVector3, pub z: ScePspIVector3, } #[repr(align(16))] pub struct ScePspIMatrix4 { pub x: ScePspIVector4, pub y: ScePspIVector4, pub z: ScePspIVector4, pub w: ScePspIVector4, } pub struct ScePspIMatrix4Unaligned { pub x: ScePspIVector4, pub y: ScePspIVector4, pub z: ScePspIVector4, pub w: ScePspIVector4, } pub struct SceMp3InitArg { pub mp3_stream_start: u32, pub unk1: u32, pub mp3_stream_end: u32, pub unk2: u32, pub mp3_buf: *mut c_void, pub mp3_buf_size: i32, pub pcm_buf: *mut c_void, pub pcm_buf_size: i32, } pub struct OpenPSID { pub data: [u8; 16usize], } pub struct UtilityDialogCommon { pub size: u32, pub language: SystemParamLanguage, pub button_accept: UtilityDialogButtonAccept, pub graphics_thread: i32, pub access_thread: i32, pub font_thread: i32, pub sound_thread: i32, pub result: i32, pub reserved: [i32; 4usize], } pub struct UtilityNetconfAdhoc { pub name: [u8; 8usize], pub timeout: u32, } pub struct UtilityNetconfData { pub base: UtilityDialogCommon, pub action: UtilityNetconfAction, pub adhocparam: *mut UtilityNetconfAdhoc, pub hotspot: i32, pub hotspot_connected: i32, pub wifisp: i32, } pub struct UtilitySavedataFileData { pub buf: *mut c_void, pub buf_size: usize, pub size: usize, pub unknown: i32, } pub struct UtilitySavedataListSaveNewData { pub icon0: UtilitySavedataFileData, pub title: *mut u8, } pub struct UtilityGameSharingParams { pub base: UtilityDialogCommon, pub unknown1: i32, pub unknown2: i32, pub name: [u8; 8usize], pub unknown3: i32, pub unknown4: i32, pub unknown5: i32, pub result: i32, pub filepath: *mut u8, pub mode: UtilityGameSharingMode, pub datatype: UtilityGameSharingDataType, pub data: *mut c_void, pub datasize: u32, } pub struct UtilityHtmlViewerParam { pub base: UtilityDialogCommon, pub memaddr: *mut c_void, pub memsize: u32, pub unknown1: i32, pub unknown2: i32, pub initialurl: *mut u8, pub numtabs: u32, pub interfacemode: UtilityHtmlViewerInterfaceMode, pub options: i32, pub dldirname: *mut u8, pub dlfilename: *mut u8, pub uldirname: *mut u8, pub ulfilename: *mut u8, pub cookiemode: UtilityHtmlViewerCookieMode, pub unknown3: u32, pub homeurl: *mut u8, pub textsize: UtilityHtmlViewerTextSize, pub displaymode: UtilityHtmlViewerDisplayMode, pub connectmode: UtilityHtmlViewerConnectMode, pub disconnectmode: UtilityHtmlViewerDisconnectMode, pub memused: u32, pub unknown4: [i32; 10usize], } pub struct SceUtilityOskData { pub unk_00: i32, pub unk_04: i32, pub language: SceUtilityOskInputLanguage, pub unk_12: i32, pub inputtype: SceUtilityOskInputType, pub lines: i32, pub unk_24: i32, pub desc: *mut u16, pub intext: *mut u16, pub outtextlength: i32, pub outtext: *mut u16, pub result: SceUtilityOskResult, pub outtextlimit: i32, } pub struct SceUtilityOskParams { pub base: UtilityDialogCommon, pub datacount: i32, pub data: *mut SceUtilityOskData, pub state: SceUtilityOskState, pub unk_60: i32, } pub struct SceNetMallocStat { pub pool: i32, pub maximum: i32, pub free: i32, } pub struct SceNetAdhocctlAdhocId { pub unknown: i32, pub adhoc_id: [u8; 9usize], pub unk: [u8; 3usize], } pub struct SceNetAdhocctlScanInfo { pub next: *mut SceNetAdhocctlScanInfo, pub channel: i32, pub name: [u8; 8usize], pub bssid: [u8; 6usize], pub unknown: [u8; 2usize], pub unknown2: i32, } pub struct SceNetAdhocctlGameModeInfo { pub count: i32, pub macs: [[u8; 6usize]; 16usize], } pub struct SceNetAdhocPtpStat { pub next: *mut SceNetAdhocPtpStat, pub ptp_id: i32, pub mac: [u8; 6usize], pub peermac: [u8; 6usize], pub port: u16, pub peerport: u16, pub sent_data: u32, pub rcvd_data: u32, pub state: ScePspnetAdhocPtpState, } pub struct SceNetAdhocPdpStat { pub next: *mut SceNetAdhocPdpStat, pub pdp_id: i32, pub mac: [u8; 6usize], pub port: u16, pub rcvd_data: u32, } pub struct AdhocPoolStat { pub size: i32, pub maxsize: i32, pub freesize: i32, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct GeContext { pub context: [u32; 512], } #[allow(missing_debug_implementations)] pub struct SceKernelUtilsSha1Context { pub h: [u32; 5usize], pub us_remains: u16, pub us_computed: u16, pub ull_total_len: u64, pub buf: [u8; 64usize], } #[allow(missing_debug_implementations)] pub struct SceKernelUtilsMt19937Context { pub count: u32, pub state: [u32; 624usize], } #[allow(missing_debug_implementations)] pub struct SceKernelUtilsMd5Context { pub h: [u32; 4usize], pub pad: u32, pub us_remains: u16, pub us_computed: u16, pub ull_total_len: u64, pub buf: [u8; 64usize], } #[allow(missing_debug_implementations)] pub struct SceIoDirent { pub d_stat: SceIoStat, pub d_name: [u8; 256usize], pub d_private: *mut c_void, pub dummy: i32, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFRect { pub x: f32, pub y: f32, pub w: f32, pub h: f32, } #[repr(align(16))] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFVector3 { pub x: f32, pub y: f32, pub z: f32, } #[repr(align(16))] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFVector4 { pub x: f32, pub y: f32, pub z: f32, pub w: f32, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFVector4Unaligned { pub x: f32, pub y: f32, pub z: f32, pub w: f32, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFVector2 { pub x: f32, pub y: f32, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFMatrix2 { pub x: ScePspFVector2, pub y: ScePspFVector2, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFMatrix3 { pub x: ScePspFVector3, pub y: ScePspFVector3, pub z: ScePspFVector3, } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(align(16))] pub struct ScePspFMatrix4 { pub x: ScePspFVector4, pub y: ScePspFVector4, pub z: ScePspFVector4, pub w: ScePspFVector4, } #[allow(missing_debug_implementations)] pub struct ScePspFMatrix4Unaligned { pub x: ScePspFVector4, pub y: ScePspFVector4, pub z: ScePspFVector4, pub w: ScePspFVector4, } #[allow(missing_debug_implementations)] pub union ScePspVector3 { pub fv: ScePspFVector3, pub iv: ScePspIVector3, pub f: [f32; 3usize], pub i: [i32; 3usize], } #[allow(missing_debug_implementations)] pub union ScePspVector4 { pub fv: ScePspFVector4, pub iv: ScePspIVector4, pub qw: u128, pub f: [f32; 4usize], pub i: [i32; 4usize], } #[allow(missing_debug_implementations)] pub union ScePspMatrix2 { pub fm: ScePspFMatrix2, pub im: ScePspIMatrix2, pub fv: [ScePspFVector2; 2usize], pub iv: [ScePspIVector2; 2usize], pub v: [ScePspVector2; 2usize], pub f: [[f32; 2usize]; 2usize], pub i: [[i32; 2usize]; 2usize], } #[allow(missing_debug_implementations)] pub union ScePspMatrix3 { pub fm: ScePspFMatrix3, pub im: ScePspIMatrix3, pub fv: [ScePspFVector3; 3usize], pub iv: [ScePspIVector3; 3usize], pub v: [ScePspVector3; 3usize], pub f: [[f32; 3usize]; 3usize], pub i: [[i32; 3usize]; 3usize], } #[allow(missing_debug_implementations)] pub union ScePspVector2 { pub fv: ScePspFVector2, pub iv: ScePspIVector2, pub f: [f32; 2usize], pub i: [i32; 2usize], } #[allow(missing_debug_implementations)] pub union ScePspMatrix4 { pub fm: ScePspFMatrix4, pub im: ScePspIMatrix4, pub fv: [ScePspFVector4; 4usize], pub iv: [ScePspIVector4; 4usize], pub v: [ScePspVector4; 4usize], pub f: [[f32; 4usize]; 4usize], pub i: [[i32; 4usize]; 4usize], } #[allow(missing_debug_implementations)] pub struct Key { pub key_type: KeyType, pub name: [u8; 256usize], pub name_len: u32, pub unk2: u32, pub unk3: u32, } #[allow(missing_debug_implementations)] pub struct UtilityMsgDialogParams { pub base: UtilityDialogCommon, pub unknown: i32, pub mode: UtilityMsgDialogMode, pub error_value: u32, pub message: [u8; 512usize], pub options: i32, pub button_pressed: UtilityMsgDialogPressed, } #[allow(missing_debug_implementations)] pub union UtilityNetData { pub as_uint: u32, pub as_string: [u8; 128usize], } #[allow(missing_debug_implementations)] pub struct UtilitySavedataSFOParam { pub title: [u8; 128usize], pub savedata_title: [u8; 128usize], pub detail: [u8; 1024usize], pub parental_level: u8, pub unknown: [u8; 3usize], } #[allow(missing_debug_implementations)] pub struct SceUtilitySavedataParam { pub base: UtilityDialogCommon, pub mode: UtilitySavedataMode, pub unknown1: i32, pub overwrite: i32, pub game_name: [u8; 13usize], pub reserved: [u8; 3usize], pub save_name: [u8; 20usize], pub save_name_list: *mut [u8; 20usize], pub file_name: [u8; 13usize], pub reserved1: [u8; 3usize], pub data_buf: *mut c_void, pub data_buf_size: usize, pub data_size: usize, pub sfo_param: UtilitySavedataSFOParam, pub icon0_file_data: UtilitySavedataFileData, pub icon1_file_data: UtilitySavedataFileData, pub pic1_file_data: UtilitySavedataFileData, pub snd0_file_data: UtilitySavedataFileData, pub new_data: *mut UtilitySavedataListSaveNewData, pub focus: UtilitySavedataFocus, pub unknown2: [i32; 4usize], pub key: [u8; 16], pub unknown3: [u8; 20], } #[allow(missing_debug_implementations)] pub struct SceNetAdhocctlPeerInfo { pub next: *mut SceNetAdhocctlPeerInfo, pub nickname: [u8; 128usize], pub mac: [u8; 6usize], pub unknown: [u8; 6usize], pub timestamp: u32, } #[allow(missing_debug_implementations)] pub struct SceNetAdhocctlParams { pub channel: i32, pub name: [u8; 8usize], pub bssid: [u8; 6usize], pub nickname: [u8; 128usize], } #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] pub union SceNetApctlInfo { pub name: [u8; 64usize], pub bssid: [u8; 6usize], pub ssid: [u8; 32usize], pub ssid_length: u32, pub security_type: u32, pub strength: u8, pub channel: u8, pub power_save: u8, pub ip: [u8; 16usize], pub sub_net_mask: [u8; 16usize], pub gateway: [u8; 16usize], pub primary_dns: [u8; 16usize], pub secondary_dns: [u8; 16usize], pub use_proxy: u32, pub proxy_url: [u8; 128usize], pub proxy_port: u16, pub eap_type: u32, pub start_browser: u32, pub wifisp: u32, } } pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const AUDIO_VOLUME_MAX: u32 = 0x8000; pub const AUDIO_CHANNEL_MAX: u32 = 8; pub const AUDIO_NEXT_CHANNEL: i32 = -1; pub const AUDIO_SAMPLE_MIN: u32 = 64; pub const AUDIO_SAMPLE_MAX: u32 = 65472; pub const PSP_CTRL_SELECT: i32 = 0x000001; pub const PSP_CTRL_START: i32 = 0x000008; pub const PSP_CTRL_UP: i32 = 0x000010; pub const PSP_CTRL_RIGHT: i32 = 0x000020; pub const PSP_CTRL_DOWN: i32 = 0x000040; pub const PSP_CTRL_LEFT: i32 = 0x000080; pub const PSP_CTRL_LTRIGGER: i32 = 0x000100; pub const PSP_CTRL_RTRIGGER: i32 = 0x000200; pub const PSP_CTRL_TRIANGLE: i32 = 0x001000; pub const PSP_CTRL_CIRCLE: i32 = 0x002000; pub const PSP_CTRL_CROSS: i32 = 0x004000; pub const PSP_CTRL_SQUARE: i32 = 0x008000; pub const PSP_CTRL_HOME: i32 = 0x010000; pub const PSP_CTRL_HOLD: i32 = 0x020000; pub const PSP_CTRL_NOTE: i32 = 0x800000; pub const PSP_CTRL_SCREEN: i32 = 0x400000; pub const PSP_CTRL_VOLUP: i32 = 0x100000; pub const PSP_CTRL_VOLDOWN: i32 = 0x200000; pub const PSP_CTRL_WLAN_UP: i32 = 0x040000; pub const PSP_CTRL_REMOTE: i32 = 0x080000; pub const PSP_CTRL_DISC: i32 = 0x1000000; pub const PSP_CTRL_MS: i32 = 0x2000000; pub const USB_CAM_PID: i32 = 0x282; pub const USB_BUS_DRIVER_NAME: &str = "USBBusDriver"; pub const USB_CAM_DRIVER_NAME: &str = "USBCamDriver"; pub const USB_CAM_MIC_DRIVER_NAME: &str = "USBCamMicDriver"; pub const USB_STOR_DRIVER_NAME: &str = "USBStor_Driver"; pub const ACTIVATED: i32 = 0x200; pub const CONNECTED: i32 = 0x020; pub const ESTABLISHED: i32 = 0x002; pub const USB_CAM_FLIP: i32 = 1; pub const USB_CAM_MIRROR: i32 = 0x100; pub const THREAD_ATTR_VFPU: i32 = 0x00004000; pub const THREAD_ATTR_USER: i32 = 0x80000000; pub const THREAD_ATTR_USBWLAN: i32 = 0xa0000000; pub const THREAD_ATTR_VSH: i32 = 0xc0000000; pub const THREAD_ATTR_SCRATCH_SRAM: i32 = 0x00008000; pub const THREAD_ATTR_NO_FILLSTACK: i32 = 0x00100000; pub const THREAD_ATTR_CLEAR_STACK: i32 = 0x00200000; pub const EVENT_WAIT_MULTIPLE: i32 = 0x200; pub const EVENT_WAIT_AND: i32 = 0; pub const EVENT_WAIT_OR: i32 = 1; pub const EVENT_WAIT_CLEAR: i32 = 0x20; pub const POWER_INFO_POWER_SWITCH: i32 = 0x80000000; pub const POWER_INFO_HOLD_SWITCH: i32 = 0x40000000; pub const POWER_INFO_STANDBY: i32 = 0x00080000; pub const POWER_INFO_RESUME_COMPLETE: i32 = 0x00040000; pub const POWER_INFO_RESUMING: i32 = 0x00020000; pub const POWER_INFO_SUSPENDING: i32 = 0x00010000; pub const POWER_INFO_AC_POWER: i32 = 0x00001000; pub const POWER_INFO_BATTERY_LOW: i32 = 0x00000100; pub const POWER_INFO_BATTERY_EXIST: i32 = 0x00000080; pub const POWER_INFO_BATTERY_POWER: i32 = 0x0000007; pub const FIO_S_IFLNK: i32 = 0x4000; pub const FIO_S_IFDIR: i32 = 0x1000; pub const FIO_S_IFREG: i32 = 0x2000; pub const FIO_S_ISUID: i32 = 0x0800; pub const FIO_S_ISGID: i32 = 0x0400; pub const FIO_S_ISVTX: i32 = 0x0200; pub const FIO_S_IRUSR: i32 = 0x0100; pub const FIO_S_IWUSR: i32 = 0x0080; pub const FIO_S_IXUSR: i32 = 0x0040; pub const FIO_S_IRGRP: i32 = 0x0020; pub const FIO_S_IWGRP: i32 = 0x0010; pub const FIO_S_IXGRP: i32 = 0x0008; pub const FIO_S_IROTH: i32 = 0x0004; pub const FIO_S_IWOTH: i32 = 0x0002; pub const FIO_S_IXOTH: i32 = 0x0001; pub const FIO_SO_IFLNK: i32 = 0x0008; pub const FIO_SO_IFDIR: i32 = 0x0010; pub const FIO_SO_IFREG: i32 = 0x0020; pub const FIO_SO_IROTH: i32 = 0x0004; pub const FIO_SO_IWOTH: i32 = 0x0002; pub const FIO_SO_IXOTH: i32 = 0x0001; pub const PSP_O_RD_ONLY: i32 = 0x0001; pub const PSP_O_WR_ONLY: i32 = 0x0002; pub const PSP_O_RD_WR: i32 = 0x0003; pub const PSP_O_NBLOCK: i32 = 0x0004; pub const PSP_O_DIR: i32 = 0x0008; pub const PSP_O_APPEND: i32 = 0x0100; pub const PSP_O_CREAT: i32 = 0x0200; pub const PSP_O_TRUNC: i32 = 0x0400; pub const PSP_O_EXCL: i32 = 0x0800; pub const PSP_O_NO_WAIT: i32 = 0x8000; pub const UMD_NOT_PRESENT: i32 = 0x01; pub const UMD_PRESENT: i32 = 0x02; pub const UMD_CHANGED: i32 = 0x04; pub const UMD_INITING: i32 = 0x08; pub const UMD_INITED: i32 = 0x10; pub const UMD_READY: i32 = 0x20; pub const PLAY_PAUSE: i32 = 0x1; pub const FORWARD: i32 = 0x4; pub const BACK: i32 = 0x8; pub const VOL_UP: i32 = 0x10; pub const VOL_DOWN: i32 = 0x20; pub const HOLD: i32 = 0x80; pub const GU_PI: f32 = 3.141593; pub const GU_TEXTURE_8BIT: i32 = 1; pub const GU_TEXTURE_16BIT: i32 = 2; pub const GU_TEXTURE_32BITF: i32 = 3; pub const GU_COLOR_5650: i32 = 4 << 2; pub const GU_COLOR_5551: i32 = 5 << 2; pub const GU_COLOR_4444: i32 = 6 << 2; pub const GU_COLOR_8888: i32 = 7 << 2; pub const GU_NORMAL_8BIT: i32 = 1 << 5; pub const GU_NORMAL_16BIT: i32 = 2 << 5; pub const GU_NORMAL_32BITF: i32 = 3 << 5; pub const GU_VERTEX_8BIT: i32 = 1 << 7; pub const GU_VERTEX_16BIT: i32 = 2 << 7; pub const GU_VERTEX_32BITF: i32 = 3 << 7; pub const GU_WEIGHT_8BIT: i32 = 1 << 9; pub const GU_WEIGHT_16BIT: i32 = 2 << 9; pub const GU_WEIGHT_32BITF: i32 = 3 << 9; pub const GU_INDEX_8BIT: i32 = 1 << 11; pub const GU_INDEX_16BIT: i32 = 2 << 11; pub const GU_WEIGHTS1: i32 = (((1 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS2: i32 = (((2 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS3: i32 = (((3 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS4: i32 = (((4 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS5: i32 = (((5 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS6: i32 = (((6 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS7: i32 = (((7 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS8: i32 = (((8 - 1) & 7) << 14) as i32; pub const GU_VERTICES1: i32 = (((1 - 1) & 7) << 18) as i32; pub const GU_VERTICES2: i32 = (((2 - 1) & 7) << 18) as i32; pub const GU_VERTICES3: i32 = (((3 - 1) & 7) << 18) as i32; pub const GU_VERTICES4: i32 = (((4 - 1) & 7) << 18) as i32; pub const GU_VERTICES5: i32 = (((5 - 1) & 7) << 18) as i32; pub const GU_VERTICES6: i32 = (((6 - 1) & 7) << 18) as i32; pub const GU_VERTICES7: i32 = (((7 - 1) & 7) << 18) as i32; pub const GU_VERTICES8: i32 = (((8 - 1) & 7) << 18) as i32; pub const GU_TRANSFORM_2D: i32 = 1 << 23; pub const GU_TRANSFORM_3D: i32 = 0; pub const GU_COLOR_BUFFER_BIT: i32 = 1; pub const GU_STENCIL_BUFFER_BIT: i32 = 2; pub const GU_DEPTH_BUFFER_BIT: i32 = 4; pub const GU_FAST_CLEAR_BIT: i32 = 16; pub const GU_AMBIENT: i32 = 1; pub const GU_DIFFUSE: i32 = 2; pub const GU_SPECULAR: i32 = 4; pub const GU_UNKNOWN_LIGHT_COMPONENT: i32 = 8; pub const SYSTEM_REGISTRY: [u8; 7] = *b"/system"; pub const REG_KEYNAME_SIZE: u32 = 27; pub const UTILITY_MSGDIALOG_ERROR: i32 = 0; pub const UTILITY_MSGDIALOG_TEXT: i32 = 1; pub const UTILITY_MSGDIALOG_YES_NO_BUTTONS: i32 = 0x10; pub const UTILITY_MSGDIALOG_DEFAULT_NO: i32 = 0x100; pub const UTILITY_HTMLVIEWER_OPEN_SCE_START_PAGE: i32 = 0x000001; pub const UTILITY_HTMLVIEWER_DISABLE_STARTUP_LIMITS: i32 = 0x000002; pub const UTILITY_HTMLVIEWER_DISABLE_EXIT_DIALOG: i32 = 0x000004; pub const UTILITY_HTMLVIEWER_DISABLE_CURSOR: i32 = 0x000008; pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_COMPLETE_DIALOG: i32 = 0x000010; pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_START_DIALOG: i32 = 0x000020; pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_DESTINATION_DIALOG: i32 = 0x000040; pub const UTILITY_HTMLVIEWER_LOCK_DOWNLOAD_DESTINATION_DIALOG: i32 = 0x000080; pub const UTILITY_HTMLVIEWER_DISABLE_TAB_DISPLAY: i32 = 0x000100; pub const UTILITY_HTMLVIEWER_ENABLE_ANALOG_HOLD: i32 = 0x000200; pub const UTILITY_HTMLVIEWER_ENABLE_FLASH: i32 = 0x000400; pub const UTILITY_HTMLVIEWER_DISABLE_LRTRIGGER: i32 = 0x000800; extern "C" { pub fn sceAudioChReserve(channel: i32, sample_count: i32, format: AudioFormat) -> i32; pub fn sceAudioChRelease(channel: i32) -> i32; pub fn sceAudioOutput(channel: i32, vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioOutputBlocking(channel: i32, vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioOutputPanned( channel: i32, left_vol: i32, right_vol: i32, buf: *mut c_void, ) -> i32; pub fn sceAudioOutputPannedBlocking( channel: i32, left_vol: i32, right_vol: i32, buf: *mut c_void, ) -> i32; pub fn sceAudioGetChannelRestLen(channel: i32) -> i32; pub fn sceAudioGetChannelRestLength(channel: i32) -> i32; pub fn sceAudioSetChannelDataLen(channel: i32, sample_count: i32) -> i32; pub fn sceAudioChangeChannelConfig(channel: i32, format: AudioFormat) -> i32; pub fn sceAudioChangeChannelVolume(channel: i32, left_vol: i32, right_vol: i32) -> i32; pub fn sceAudioOutput2Reserve(sample_count: i32) -> i32; pub fn sceAudioOutput2Release() -> i32; pub fn sceAudioOutput2ChangeLength(sample_count: i32) -> i32; pub fn sceAudioOutput2OutputBlocking(vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioOutput2GetRestSample() -> i32; pub fn sceAudioSRCChReserve( sample_count: i32, freq: AudioOutputFrequency, channels: i32, ) -> i32; pub fn sceAudioSRCChRelease() -> i32; pub fn sceAudioSRCOutputBlocking(vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioInputInit(unknown1: i32, gain: i32, unknown2: i32) -> i32; pub fn sceAudioInputInitEx(params: *mut AudioInputParams) -> i32; pub fn sceAudioInputBlocking(sample_count: i32, freq: AudioInputFrequency, buf: *mut c_void); pub fn sceAudioInput(sample_count: i32, freq: AudioInputFrequency, buf: *mut c_void); pub fn sceAudioGetInputLength() -> i32; pub fn sceAudioWaitInputEnd() -> i32; pub fn sceAudioPollInputEnd() -> i32; pub fn sceAtracGetAtracID(ui_codec_type: u32) -> i32; pub fn sceAtracSetDataAndGetID(buf: *mut c_void, bufsize: usize) -> i32; pub fn sceAtracDecodeData( atrac_id: i32, out_samples: *mut u16, out_n: *mut i32, out_end: *mut i32, out_remain_frame: *mut i32, ) -> i32; pub fn sceAtracGetRemainFrame(atrac_id: i32, out_remain_frame: *mut i32) -> i32; pub fn sceAtracGetStreamDataInfo( atrac_id: i32, write_pointer: *mut *mut u8, available_bytes: *mut u32, read_offset: *mut u32, ) -> i32; pub fn sceAtracAddStreamData(atrac_id: i32, bytes_to_add: u32) -> i32; pub fn sceAtracGetBitrate(atrac_id: i32, out_bitrate: *mut i32) -> i32; pub fn sceAtracSetLoopNum(atrac_id: i32, nloops: i32) -> i32; pub fn sceAtracReleaseAtracID(atrac_id: i32) -> i32; pub fn sceAtracGetNextSample(atrac_id: i32, out_n: *mut i32) -> i32; pub fn sceAtracGetMaxSample(atrac_id: i32, out_max: *mut i32) -> i32; pub fn sceAtracGetBufferInfoForReseting( atrac_id: i32, ui_sample: u32, pbuffer_info: *mut Atrac3BufferInfo, ) -> i32; pub fn sceAtracGetChannel(atrac_id: i32, pui_channel: *mut u32) -> i32; pub fn sceAtracGetInternalErrorInfo(atrac_id: i32, pi_result: *mut i32) -> i32; pub fn sceAtracGetLoopStatus( atrac_id: i32, pi_loop_num: *mut i32, pui_loop_status: *mut u32, ) -> i32; pub fn sceAtracGetNextDecodePosition(atrac_id: i32, pui_sample_position: *mut u32) -> i32; pub fn sceAtracGetSecondBufferInfo( atrac_id: i32, pui_position: *mut u32, pui_data_byte: *mut u32, ) -> i32; pub fn sceAtracGetSoundSample( atrac_id: i32, pi_end_sample: *mut i32, pi_loop_start_sample: *mut i32, pi_loop_end_sample: *mut i32, ) -> i32; pub fn sceAtracResetPlayPosition( atrac_id: i32, ui_sample: u32, ui_write_byte_first_buf: u32, ui_write_byte_second_buf: u32, ) -> i32; pub fn sceAtracSetData(atrac_id: i32, puc_buffer_addr: *mut u8, ui_buffer_byte: u32) -> i32; pub fn sceAtracSetHalfwayBuffer( atrac_id: i32, puc_buffer_addr: *mut u8, ui_read_byte: u32, ui_buffer_byte: u32, ) -> i32; pub fn sceAtracSetHalfwayBufferAndGetID( puc_buffer_addr: *mut u8, ui_read_byte: u32, ui_buffer_byte: u32, ) -> i32; pub fn sceAtracSetSecondBuffer( atrac_id: i32, puc_second_buffer_addr: *mut u8, ui_second_buffer_byte: u32, ) -> i32; pub fn sceCtrlSetSamplingCycle(cycle: i32) -> i32; pub fn sceCtrlGetSamplingCycle(pcycle: *mut i32) -> i32; pub fn sceCtrlSetSamplingMode(mode: CtrlMode) -> i32; pub fn sceCtrlGetSamplingMode(pmode: *mut i32) -> i32; pub fn sceCtrlPeekBufferPositive(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlPeekBufferNegative(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlReadBufferPositive(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlReadBufferNegative(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlPeekLatch(latch_data: *mut SceCtrlLatch) -> i32; pub fn sceCtrlReadLatch(latch_data: *mut SceCtrlLatch) -> i32; pub fn sceCtrlSetIdleCancelThreshold(idlereset: i32, idleback: i32) -> i32; pub fn sceCtrlGetIdleCancelThreshold(idlereset: *mut i32, idleback: *mut i32) -> i32; pub fn sceDisplaySetMode(mode: DisplayMode, width: usize, height: usize) -> u32; pub fn sceDisplayGetMode(pmode: *mut i32, pwidth: *mut i32, pheight: *mut i32) -> i32; pub fn sceDisplaySetFrameBuf( top_addr: *const u8, buffer_width: usize, pixel_format: DisplayPixelFormat, sync: DisplaySetBufSync, ) -> u32; pub fn sceDisplayGetFrameBuf( top_addr: *mut *mut c_void, buffer_width: *mut usize, pixel_format: *mut DisplayPixelFormat, sync: DisplaySetBufSync, ) -> i32; pub fn sceDisplayGetVcount() -> u32; pub fn sceDisplayWaitVblank() -> i32; pub fn sceDisplayWaitVblankCB() -> i32; pub fn sceDisplayWaitVblankStart() -> i32; pub fn sceDisplayWaitVblankStartCB() -> i32; pub fn sceDisplayGetAccumulatedHcount() -> i32; pub fn sceDisplayGetCurrentHcount() -> i32; pub fn sceDisplayGetFramePerSec() -> f32; pub fn sceDisplayIsForeground() -> i32; pub fn sceDisplayIsVblank() -> i32; pub fn sceGeEdramGetSize() -> u32; pub fn sceGeEdramGetAddr() -> *mut u8; pub fn sceGeEdramSetAddrTranslation(width: i32) -> i32; pub fn sceGeGetCmd(cmd: i32) -> u32; pub fn sceGeGetMtx(type_: GeMatrixType, matrix: *mut c_void) -> i32; pub fn sceGeGetStack(stack_id: i32, stack: *mut GeStack) -> i32; pub fn sceGeSaveContext(context: *mut GeContext) -> i32; pub fn sceGeRestoreContext(context: *const GeContext) -> i32; pub fn sceGeListEnQueue( list: *const c_void, stall: *mut c_void, cbid: i32, arg: *mut GeListArgs, ) -> i32; pub fn sceGeListEnQueueHead( list: *const c_void, stall: *mut c_void, cbid: i32, arg: *mut GeListArgs, ) -> i32; pub fn sceGeListDeQueue(qid: i32) -> i32; pub fn sceGeListUpdateStallAddr(qid: i32, stall: *mut c_void) -> i32; pub fn sceGeListSync(qid: i32, sync_type: i32) -> GeListState; pub fn sceGeDrawSync(sync_type: i32) -> GeListState; pub fn sceGeBreak(mode: i32, p_param: *mut GeBreakParam) -> i32; pub fn sceGeContinue() -> i32; pub fn sceGeSetCallback(cb: *mut GeCallbackData) -> i32; pub fn sceGeUnsetCallback(cbid: i32) -> i32; pub fn sceKernelExitGame(); pub fn sceKernelRegisterExitCallback(id: SceUid) -> i32; pub fn sceKernelLoadExec(file: *const u8, param: *mut SceKernelLoadExecParam) -> i32; pub fn sceKernelAllocPartitionMemory( partition: SceSysMemPartitionId, name: *const u8, type_: SceSysMemBlockTypes, size: u32, addr: *mut c_void, ) -> SceUid; pub fn sceKernelGetBlockHeadAddr(blockid: SceUid) -> *mut c_void; pub fn sceKernelFreePartitionMemory(blockid: SceUid) -> i32; pub fn sceKernelTotalFreeMemSize() -> usize; pub fn sceKernelMaxFreeMemSize() -> usize; pub fn sceKernelDevkitVersion() -> u32; pub fn sceKernelSetCompiledSdkVersion(version: u32) -> i32; pub fn sceKernelGetCompiledSdkVersion() -> u32; pub fn sceKernelLibcTime(t: *mut i32) -> i32; pub fn sceKernelLibcClock() -> u32; pub fn sceKernelLibcGettimeofday(tp: *mut timeval, tzp: *mut timezone) -> i32; pub fn sceKernelDcacheWritebackAll(); pub fn sceKernelDcacheWritebackInvalidateAll(); pub fn sceKernelDcacheWritebackRange(p: *const c_void, size: u32); pub fn sceKernelDcacheWritebackInvalidateRange(p: *const c_void, size: u32); pub fn sceKernelDcacheInvalidateRange(p: *const c_void, size: u32); pub fn sceKernelIcacheInvalidateAll(); pub fn sceKernelIcacheInvalidateRange(p: *const c_void, size: u32); pub fn sceKernelUtilsMt19937Init(ctx: *mut SceKernelUtilsMt19937Context, seed: u32) -> i32; pub fn sceKernelUtilsMt19937UInt(ctx: *mut SceKernelUtilsMt19937Context) -> u32; pub fn sceKernelUtilsMd5Digest(data: *mut u8, size: u32, digest: *mut u8) -> i32; pub fn sceKernelUtilsMd5BlockInit(ctx: *mut SceKernelUtilsMd5Context) -> i32; pub fn sceKernelUtilsMd5BlockUpdate( ctx: *mut SceKernelUtilsMd5Context, data: *mut u8, size: u32, ) -> i32; pub fn sceKernelUtilsMd5BlockResult(ctx: *mut SceKernelUtilsMd5Context, digest: *mut u8) -> i32; pub fn sceKernelUtilsSha1Digest(data: *mut u8, size: u32, digest: *mut u8) -> i32; pub fn sceKernelUtilsSha1BlockInit(ctx: *mut SceKernelUtilsSha1Context) -> i32; pub fn sceKernelUtilsSha1BlockUpdate( ctx: *mut SceKernelUtilsSha1Context, data: *mut u8, size: u32, ) -> i32; pub fn sceKernelUtilsSha1BlockResult( ctx: *mut SceKernelUtilsSha1Context, digest: *mut u8, ) -> i32; pub fn sceKernelRegisterSubIntrHandler( int_no: i32, no: i32, handler: *mut c_void, arg: *mut c_void, ) -> i32; pub fn sceKernelReleaseSubIntrHandler(int_no: i32, no: i32) -> i32; pub fn sceKernelEnableSubIntr(int_no: i32, no: i32) -> i32; pub fn sceKernelDisableSubIntr(int_no: i32, no: i32) -> i32; pub fn QueryIntrHandlerInfo( intr_code: SceUid, sub_intr_code: SceUid, data: *mut IntrHandlerOptionParam, ) -> i32; pub fn sceKernelCpuSuspendIntr() -> u32; pub fn sceKernelCpuResumeIntr(flags: u32); pub fn sceKernelCpuResumeIntrWithSync(flags: u32); pub fn sceKernelIsCpuIntrSuspended(flags: u32) -> i32; pub fn sceKernelIsCpuIntrEnable() -> i32; pub fn sceKernelLoadModule( path: *const u8, flags: i32, option: *mut SceKernelLMOption, ) -> SceUid; pub fn sceKernelLoadModuleMs( path: *const u8, flags: i32, option: *mut SceKernelLMOption, ) -> SceUid; pub fn sceKernelLoadModuleByID( fid: SceUid, flags: i32, option: *mut SceKernelLMOption, ) -> SceUid; pub fn sceKernelLoadModuleBufferUsbWlan( buf_size: usize, buf: *mut c_void, flags: i32, option: *mut SceKernelLMOption, ) -> SceUid; pub fn sceKernelStartModule( mod_id: SceUid, arg_size: usize, argp: *mut c_void, status: *mut i32, option: *mut SceKernelSMOption, ) -> i32; pub fn sceKernelStopModule( mod_id: SceUid, arg_size: usize, argp: *mut c_void, status: *mut i32, option: *mut SceKernelSMOption, ) -> i32; pub fn sceKernelUnloadModule(mod_id: SceUid) -> i32; pub fn sceKernelSelfStopUnloadModule(unknown: i32, arg_size: usize, argp: *mut c_void) -> i32; pub fn sceKernelStopUnloadSelfModule( arg_size: usize, argp: *mut c_void, status: *mut i32, option: *mut SceKernelSMOption, ) -> i32; pub fn sceKernelQueryModuleInfo(mod_id: SceUid, info: *mut SceKernelModuleInfo) -> i32; pub fn sceKernelGetModuleIdList( read_buf: *mut SceUid, read_buf_size: i32, id_count: *mut i32, ) -> i32; pub fn sceKernelVolatileMemLock(unk: i32, ptr: *mut *mut c_void, size: *mut i32) -> i32; pub fn sceKernelVolatileMemTryLock(unk: i32, ptr: *mut *mut c_void, size: *mut i32) -> i32; pub fn sceKernelVolatileMemUnlock(unk: i32) -> i32; pub fn sceKernelStdin() -> SceUid; pub fn sceKernelStdout() -> SceUid; pub fn sceKernelStderr() -> SceUid; pub fn sceKernelGetThreadmanIdType(uid: SceUid) -> SceKernelIdListType; pub fn sceKernelCreateThread( name: *const u8, entry: SceKernelThreadEntry, init_priority: i32, stack_size: i32, attr: i32, option: *mut SceKernelThreadOptParam, ) -> SceUid; pub fn sceKernelDeleteThread(thid: SceUid) -> i32; pub fn sceKernelStartThread(id: SceUid, arg_len: usize, arg_p: *mut c_void) -> i32; pub fn sceKernelExitThread(status: i32) -> i32; pub fn sceKernelExitDeleteThread(status: i32) -> i32; pub fn sceKernelTerminateThread(thid: SceUid) -> i32; pub fn sceKernelTerminateDeleteThread(thid: SceUid) -> i32; pub fn sceKernelSuspendDispatchThread() -> i32; pub fn sceKernelResumeDispatchThread(state: i32) -> i32; pub fn sceKernelSleepThread() -> i32; pub fn sceKernelSleepThreadCB() -> i32; pub fn sceKernelWakeupThread(thid: SceUid) -> i32; pub fn sceKernelCancelWakeupThread(thid: SceUid) -> i32; pub fn sceKernelSuspendThread(thid: SceUid) -> i32; pub fn sceKernelResumeThread(thid: SceUid) -> i32; pub fn sceKernelWaitThreadEnd(thid: SceUid, timeout: *mut u32) -> i32; pub fn sceKernelWaitThreadEndCB(thid: SceUid, timeout: *mut u32) -> i32; pub fn sceKernelDelayThread(delay: u32) -> i32; pub fn sceKernelDelayThreadCB(delay: u32) -> i32; pub fn sceKernelDelaySysClockThread(delay: *mut SceKernelSysClock) -> i32; pub fn sceKernelDelaySysClockThreadCB(delay: *mut SceKernelSysClock) -> i32; pub fn sceKernelChangeCurrentThreadAttr(unknown: i32, attr: i32) -> i32; pub fn sceKernelChangeThreadPriority(thid: SceUid, priority: i32) -> i32; pub fn sceKernelRotateThreadReadyQueue(priority: i32) -> i32; pub fn sceKernelReleaseWaitThread(thid: SceUid) -> i32; pub fn sceKernelGetThreadId() -> i32; pub fn sceKernelGetThreadCurrentPriority() -> i32; pub fn sceKernelGetThreadExitStatus(thid: SceUid) -> i32; pub fn sceKernelCheckThreadStack() -> i32; pub fn sceKernelGetThreadStackFreeSize(thid: SceUid) -> i32; pub fn sceKernelReferThreadStatus(thid: SceUid, info: *mut SceKernelThreadInfo) -> i32; pub fn sceKernelReferThreadRunStatus( thid: SceUid, status: *mut SceKernelThreadRunStatus, ) -> i32; pub fn sceKernelCreateSema( name: *const u8, attr: u32, init_val: i32, max_val: i32, option: *mut SceKernelSemaOptParam, ) -> SceUid; pub fn sceKernelDeleteSema(sema_id: SceUid) -> i32; pub fn sceKernelSignalSema(sema_id: SceUid, signal: i32) -> i32; pub fn sceKernelWaitSema(sema_id: SceUid, signal: i32, timeout: *mut u32) -> i32; pub fn sceKernelWaitSemaCB(sema_id: SceUid, signal: i32, timeout: *mut u32) -> i32; pub fn sceKernelPollSema(sema_id: SceUid, signal: i32) -> i32; pub fn sceKernelReferSemaStatus(sema_id: SceUid, info: *mut SceKernelSemaInfo) -> i32; pub fn sceKernelCreateEventFlag( name: *const u8, attr: i32, bits: i32, opt: *mut SceKernelEventFlagOptParam, ) -> SceUid; pub fn sceKernelSetEventFlag(ev_id: SceUid, bits: u32) -> i32; pub fn sceKernelClearEventFlag(ev_id: SceUid, bits: u32) -> i32; pub fn sceKernelPollEventFlag(ev_id: SceUid, bits: u32, wait: i32, out_bits: *mut u32) -> i32; pub fn sceKernelWaitEventFlag( ev_id: SceUid, bits: u32, wait: i32, out_bits: *mut u32, timeout: *mut u32, ) -> i32; pub fn sceKernelWaitEventFlagCB( ev_id: SceUid, bits: u32, wait: i32, out_bits: *mut u32, timeout: *mut u32, ) -> i32; pub fn sceKernelDeleteEventFlag(ev_id: SceUid) -> i32; pub fn sceKernelReferEventFlagStatus(event: SceUid, status: *mut SceKernelEventFlagInfo) -> i32; pub fn sceKernelCreateMbx( name: *const u8, attr: u32, option: *mut SceKernelMbxOptParam, ) -> SceUid; pub fn sceKernelDeleteMbx(mbx_id: SceUid) -> i32; pub fn sceKernelSendMbx(mbx_id: SceUid, message: *mut c_void) -> i32; pub fn sceKernelReceiveMbx(mbx_id: SceUid, message: *mut *mut c_void, timeout: *mut u32) -> i32; pub fn sceKernelReceiveMbxCB( mbx_id: SceUid, message: *mut *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelPollMbx(mbx_id: SceUid, pmessage: *mut *mut c_void) -> i32; pub fn sceKernelCancelReceiveMbx(mbx_id: SceUid, num: *mut i32) -> i32; pub fn sceKernelReferMbxStatus(mbx_id: SceUid, info: *mut SceKernelMbxInfo) -> i32; pub fn sceKernelSetAlarm( clock: u32, handler: SceKernelAlarmHandler, common: *mut c_void, ) -> SceUid; pub fn sceKernelSetSysClockAlarm( clock: *mut SceKernelSysClock, handler: *mut SceKernelAlarmHandler, common: *mut c_void, ) -> SceUid; pub fn sceKernelCancelAlarm(alarm_id: SceUid) -> i32; pub fn sceKernelReferAlarmStatus(alarm_id: SceUid, info: *mut SceKernelAlarmInfo) -> i32; pub fn sceKernelCreateCallback( name: *const u8, func: SceKernelCallbackFunction, arg: *mut c_void, ) -> SceUid; pub fn sceKernelReferCallbackStatus(cb: SceUid, status: *mut SceKernelCallbackInfo) -> i32; pub fn sceKernelDeleteCallback(cb: SceUid) -> i32; pub fn sceKernelNotifyCallback(cb: SceUid, arg2: i32) -> i32; pub fn sceKernelCancelCallback(cb: SceUid) -> i32; pub fn sceKernelGetCallbackCount(cb: SceUid) -> i32; pub fn sceKernelCheckCallback() -> i32; pub fn sceKernelGetThreadmanIdList( type_: SceKernelIdListType, read_buf: *mut SceUid, read_buf_size: i32, id_count: *mut i32, ) -> i32; pub fn sceKernelReferSystemStatus(status: *mut SceKernelSystemStatus) -> i32; pub fn sceKernelCreateMsgPipe( name: *const u8, part: i32, attr: i32, unk1: *mut c_void, opt: *mut c_void, ) -> SceUid; pub fn sceKernelDeleteMsgPipe(uid: SceUid) -> i32; pub fn sceKernelSendMsgPipe( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelSendMsgPipeCB( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelTrySendMsgPipe( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, ) -> i32; pub fn sceKernelReceiveMsgPipe( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelReceiveMsgPipeCB( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelTryReceiveMsgPipe( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, ) -> i32; pub fn sceKernelCancelMsgPipe(uid: SceUid, send: *mut i32, recv: *mut i32) -> i32; pub fn sceKernelReferMsgPipeStatus(uid: SceUid, info: *mut SceKernelMppInfo) -> i32; pub fn sceKernelCreateVpl( name: *const u8, part: i32, attr: i32, size: u32, opt: *mut SceKernelVplOptParam, ) -> SceUid; pub fn sceKernelDeleteVpl(uid: SceUid) -> i32; pub fn sceKernelAllocateVpl( uid: SceUid, size: u32, data: *mut *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelAllocateVplCB( uid: SceUid, size: u32, data: *mut *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelTryAllocateVpl(uid: SceUid, size: u32, data: *mut *mut c_void) -> i32; pub fn sceKernelFreeVpl(uid: SceUid, data: *mut c_void) -> i32; pub fn sceKernelCancelVpl(uid: SceUid, num: *mut i32) -> i32; pub fn sceKernelReferVplStatus(uid: SceUid, info: *mut SceKernelVplInfo) -> i32; pub fn sceKernelCreateFpl( name: *const u8, part: i32, attr: i32, size: u32, blocks: u32, opt: *mut SceKernelFplOptParam, ) -> i32; pub fn sceKernelDeleteFpl(uid: SceUid) -> i32; pub fn sceKernelAllocateFpl(uid: SceUid, data: *mut *mut c_void, timeout: *mut u32) -> i32; pub fn sceKernelAllocateFplCB(uid: SceUid, data: *mut *mut c_void, timeout: *mut u32) -> i32; pub fn sceKernelTryAllocateFpl(uid: SceUid, data: *mut *mut c_void) -> i32; pub fn sceKernelFreeFpl(uid: SceUid, data: *mut c_void) -> i32; pub fn sceKernelCancelFpl(uid: SceUid, pnum: *mut i32) -> i32; pub fn sceKernelReferFplStatus(uid: SceUid, info: *mut SceKernelFplInfo) -> i32; pub fn sceKernelUSec2SysClock(usec: u32, clock: *mut SceKernelSysClock) -> i32; pub fn sceKernelUSec2SysClockWide(usec: u32) -> i64; pub fn sceKernelSysClock2USec( clock: *mut SceKernelSysClock, low: *mut u32, high: *mut u32, ) -> i32; pub fn sceKernelSysClock2USecWide(clock: i64, low: *mut u32, high: *mut u32) -> i32; pub fn sceKernelGetSystemTime(time: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetSystemTimeWide() -> i64; pub fn sceKernelGetSystemTimeLow() -> u32; pub fn sceKernelCreateVTimer(name: *const u8, opt: *mut SceKernelVTimerOptParam) -> SceUid; pub fn sceKernelDeleteVTimer(uid: SceUid) -> i32; pub fn sceKernelGetVTimerBase(uid: SceUid, base: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetVTimerBaseWide(uid: SceUid) -> i64; pub fn sceKernelGetVTimerTime(uid: SceUid, time: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetVTimerTimeWide(uid: SceUid) -> i64; pub fn sceKernelSetVTimerTime(uid: SceUid, time: *mut SceKernelSysClock) -> i32; pub fn sceKernelSetVTimerTimeWide(uid: SceUid, time: i64) -> i64; pub fn sceKernelStartVTimer(uid: SceUid) -> i32; pub fn sceKernelStopVTimer(uid: SceUid) -> i32; pub fn sceKernelSetVTimerHandler( uid: SceUid, time: *mut SceKernelSysClock, handler: SceKernelVTimerHandler, common: *mut c_void, ) -> i32; pub fn sceKernelSetVTimerHandlerWide( uid: SceUid, time: i64, handler: SceKernelVTimerHandlerWide, common: *mut c_void, ) -> i32; pub fn sceKernelCancelVTimerHandler(uid: SceUid) -> i32; pub fn sceKernelReferVTimerStatus(uid: SceUid, info: *mut SceKernelVTimerInfo) -> i32; pub fn sceKernelRegisterThreadEventHandler( name: *const u8, thread_id: SceUid, mask: i32, handler: SceKernelThreadEventHandler, common: *mut c_void, ) -> SceUid; pub fn sceKernelReleaseThreadEventHandler(uid: SceUid) -> i32; pub fn sceKernelReferThreadEventHandlerStatus( uid: SceUid, info: *mut SceKernelThreadEventHandlerInfo, ) -> i32; pub fn sceKernelReferThreadProfiler() -> *mut DebugProfilerRegs; pub fn sceKernelReferGlobalProfiler() -> *mut DebugProfilerRegs; pub fn sceUsbStart(driver_name: *const u8, size: i32, args: *mut c_void) -> i32; pub fn sceUsbStop(driver_name: *const u8, size: i32, args: *mut c_void) -> i32; pub fn sceUsbActivate(pid: u32) -> i32; pub fn sceUsbDeactivate(pid: u32) -> i32; pub fn sceUsbGetState() -> i32; pub fn sceUsbGetDrvState(driver_name: *const u8) -> i32; } extern "C" { pub fn sceUsbCamSetupStill(param: *mut UsbCamSetupStillParam) -> i32; pub fn sceUsbCamSetupStillEx(param: *mut UsbCamSetupStillExParam) -> i32; pub fn sceUsbCamStillInputBlocking(buf: *mut u8, size: usize) -> i32; pub fn sceUsbCamStillInput(buf: *mut u8, size: usize) -> i32; pub fn sceUsbCamStillWaitInputEnd() -> i32; pub fn sceUsbCamStillPollInputEnd() -> i32; pub fn sceUsbCamStillCancelInput() -> i32; pub fn sceUsbCamStillGetInputLength() -> i32; pub fn sceUsbCamSetupVideo( param: *mut UsbCamSetupVideoParam, work_area: *mut c_void, work_area_size: i32, ) -> i32; pub fn sceUsbCamSetupVideoEx( param: *mut UsbCamSetupVideoExParam, work_area: *mut c_void, work_area_size: i32, ) -> i32; pub fn sceUsbCamStartVideo() -> i32; pub fn sceUsbCamStopVideo() -> i32; pub fn sceUsbCamReadVideoFrameBlocking(buf: *mut u8, size: usize) -> i32; pub fn sceUsbCamReadVideoFrame(buf: *mut u8, size: usize) -> i32; pub fn sceUsbCamWaitReadVideoFrameEnd() -> i32; pub fn sceUsbCamPollReadVideoFrameEnd() -> i32; pub fn sceUsbCamGetReadVideoFrameSize() -> i32; pub fn sceUsbCamSetSaturation(saturation: i32) -> i32; pub fn sceUsbCamSetBrightness(brightness: i32) -> i32; pub fn sceUsbCamSetContrast(contrast: i32) -> i32; pub fn sceUsbCamSetSharpness(sharpness: i32) -> i32; pub fn sceUsbCamSetImageEffectMode(effect_mode: UsbCamEffectMode) -> i32; pub fn sceUsbCamSetEvLevel(exposure_level: UsbCamEvLevel) -> i32; pub fn sceUsbCamSetReverseMode(reverse_flags: i32) -> i32; pub fn sceUsbCamSetZoom(zoom: i32) -> i32; pub fn sceUsbCamGetSaturation(saturation: *mut i32) -> i32; pub fn sceUsbCamGetBrightness(brightness: *mut i32) -> i32; pub fn sceUsbCamGetContrast(contrast: *mut i32) -> i32; pub fn sceUsbCamGetSharpness(sharpness: *mut i32) -> i32; pub fn sceUsbCamGetImageEffectMode(effect_mode: *mut UsbCamEffectMode) -> i32; pub fn sceUsbCamGetEvLevel(exposure_level: *mut UsbCamEvLevel) -> i32; pub fn sceUsbCamGetReverseMode(reverse_flags: *mut i32) -> i32; pub fn sceUsbCamGetZoom(zoom: *mut i32) -> i32; pub fn sceUsbCamAutoImageReverseSW(on: i32) -> i32; pub fn sceUsbCamGetAutoImageReverseState() -> i32; pub fn sceUsbCamGetLensDirection() -> i32; pub fn sceUsbstorBootRegisterNotify(event_flag: SceUid) -> i32; pub fn sceUsbstorBootUnregisterNotify(event_flag: u32) -> i32; pub fn sceUsbstorBootSetCapacity(size: u32) -> i32; pub fn scePowerRegisterCallback(slot: i32, cbid: SceUid) -> i32; pub fn scePowerUnregisterCallback(slot: i32) -> i32; pub fn scePowerIsPowerOnline() -> i32; pub fn scePowerIsBatteryExist() -> i32; pub fn scePowerIsBatteryCharging() -> i32; pub fn scePowerGetBatteryChargingStatus() -> i32; pub fn scePowerIsLowBattery() -> i32; pub fn scePowerGetBatteryLifePercent() -> i32; pub fn scePowerGetBatteryLifeTime() -> i32; pub fn scePowerGetBatteryTemp() -> i32; pub fn scePowerGetBatteryElec() -> i32; pub fn scePowerGetBatteryVolt() -> i32; pub fn scePowerSetCpuClockFrequency(cpufreq: i32) -> i32; pub fn scePowerSetBusClockFrequency(busfreq: i32) -> i32; pub fn scePowerGetCpuClockFrequency() -> i32; pub fn scePowerGetCpuClockFrequencyInt() -> i32; pub fn scePowerGetCpuClockFrequencyFloat() -> f32; pub fn scePowerGetBusClockFrequency() -> i32; pub fn scePowerGetBusClockFrequencyInt() -> i32; pub fn scePowerGetBusClockFrequencyFloat() -> f32; pub fn scePowerSetClockFrequency(pllfreq: i32, cpufreq: i32, busfreq: i32) -> i32; pub fn scePowerLock(unknown: i32) -> i32; pub fn scePowerUnlock(unknown: i32) -> i32; pub fn scePowerTick(t: PowerTick) -> i32; pub fn scePowerGetIdleTimer() -> i32; pub fn scePowerIdleTimerEnable(unknown: i32) -> i32; pub fn scePowerIdleTimerDisable(unknown: i32) -> i32; pub fn scePowerRequestStandby() -> i32; pub fn scePowerRequestSuspend() -> i32; pub fn sceWlanDevIsPowerOn() -> i32; pub fn sceWlanGetSwitchState() -> i32; pub fn sceWlanGetEtherAddr(ether_addr: *mut u8) -> i32; pub fn sceWlanDevAttach() -> i32; pub fn sceWlanDevDetach() -> i32; pub fn sceRtcGetTickResolution() -> u32; pub fn sceRtcGetCurrentTick(tick: *mut u64) -> i32; pub fn sceRtcGetCurrentClock(tm: *mut ScePspDateTime, tz: i32) -> i32; pub fn sceRtcGetCurrentClockLocalTime(tm: *mut ScePspDateTime) -> i32; pub fn sceRtcConvertUtcToLocalTime(tick_utc: *const u64, tick_local: *mut u64) -> i32; pub fn sceRtcConvertLocalTimeToUTC(tick_local: *const u64, tick_utc: *mut u64) -> i32; pub fn sceRtcIsLeapYear(year: i32) -> i32; pub fn sceRtcGetDaysInMonth(year: i32, month: i32) -> i32; pub fn sceRtcGetDayOfWeek(year: i32, month: i32, day: i32) -> i32; pub fn sceRtcCheckValid(date: *const ScePspDateTime) -> i32; pub fn sceRtcSetTick(date: *mut ScePspDateTime, tick: *const u64) -> i32; pub fn sceRtcGetTick(date: *const ScePspDateTime, tick: *mut u64) -> i32; pub fn sceRtcCompareTick(tick1: *const u64, tick2: *const u64) -> i32; pub fn sceRtcTickAddTicks(dest_tick: *mut u64, src_tick: *const u64, num_ticks: u64) -> i32; pub fn sceRtcTickAddMicroseconds(dest_tick: *mut u64, src_tick: *const u64, num_ms: u64) -> i32; pub fn sceRtcTickAddSeconds(dest_tick: *mut u64, src_tick: *const u64, num_seconds: u64) -> i32; pub fn sceRtcTickAddMinutes(dest_tick: *mut u64, src_tick: *const u64, num_minutes: u64) -> i32; pub fn sceRtcTickAddHours(dest_tick: *mut u64, src_tick: *const u64, num_hours: u64) -> i32; pub fn sceRtcTickAddDays(dest_tick: *mut u64, src_tick: *const u64, num_days: u64) -> i32; pub fn sceRtcTickAddWeeks(dest_tick: *mut u64, src_tick: *const u64, num_weeks: u64) -> i32; pub fn sceRtcTickAddMonths(dest_tick: *mut u64, src_tick: *const u64, num_months: u64) -> i32; pub fn sceRtcTickAddYears(dest_tick: *mut u64, src_tick: *const u64, num_years: u64) -> i32; pub fn sceRtcSetTime_t(date: *mut ScePspDateTime, time: u32) -> i32; pub fn sceRtcGetTime_t(date: *const ScePspDateTime, time: *mut u32) -> i32; pub fn sceRtcSetTime64_t(date: *mut ScePspDateTime, time: u64) -> i32; pub fn sceRtcGetTime64_t(date: *const ScePspDateTime, time: *mut u64) -> i32; pub fn sceRtcSetDosTime(date: *mut ScePspDateTime, dos_time: u32) -> i32; pub fn sceRtcGetDosTime(date: *mut ScePspDateTime, dos_time: u32) -> i32; pub fn sceRtcSetWin32FileTime(date: *mut ScePspDateTime, time: *mut u64) -> i32; pub fn sceRtcGetWin32FileTime(date: *mut ScePspDateTime, time: *mut u64) -> i32; pub fn sceRtcParseDateTime(dest_tick: *mut u64, date_string: *const u8) -> i32; pub fn sceRtcFormatRFC3339( psz_date_time: *mut char, p_utc: *const u64, time_zone_minutes: i32, ) -> i32; pub fn sceRtcFormatRFC3339LocalTime(psz_date_time: *mut char, p_utc: *const u64) -> i32; pub fn sceRtcParseRFC3339(p_utc: *mut u64, psz_date_time: *const u8) -> i32; pub fn sceRtcFormatRFC2822( psz_date_time: *mut char, p_utc: *const u64, time_zone_minutes: i32, ) -> i32; pub fn sceRtcFormatRFC2822LocalTime(psz_date_time: *mut char, p_utc: *const u64) -> i32; pub fn sceIoOpen(file: *const u8, flags: i32, permissions: IoPermissions) -> SceUid; pub fn sceIoOpenAsync(file: *const u8, flags: i32, permissions: IoPermissions) -> SceUid; pub fn sceIoClose(fd: SceUid) -> i32; pub fn sceIoCloseAsync(fd: SceUid) -> i32; pub fn sceIoRead(fd: SceUid, data: *mut c_void, size: u32) -> i32; pub fn sceIoReadAsync(fd: SceUid, data: *mut c_void, size: u32) -> i32; pub fn sceIoWrite(fd: SceUid, data: *const c_void, size: usize) -> i32; pub fn sceIoWriteAsync(fd: SceUid, data: *const c_void, size: u32) -> i32; pub fn sceIoLseek(fd: SceUid, offset: i64, whence: IoWhence) -> i64; pub fn sceIoLseekAsync(fd: SceUid, offset: i64, whence: IoWhence) -> i32; pub fn sceIoLseek32(fd: SceUid, offset: i32, whence: IoWhence) -> i32; pub fn sceIoLseek32Async(fd: SceUid, offset: i32, whence: IoWhence) -> i32; pub fn sceIoRemove(file: *const u8) -> i32; pub fn sceIoMkdir(dir: *const u8, mode: IoPermissions) -> i32; pub fn sceIoRmdir(path: *const u8) -> i32; pub fn sceIoChdir(path: *const u8) -> i32; pub fn sceIoRename(oldname: *const u8, newname: *const u8) -> i32; pub fn sceIoDopen(dirname: *const u8) -> SceUid; pub fn sceIoDread(fd: SceUid, dir: *mut SceIoDirent) -> i32; pub fn sceIoDclose(fd: SceUid) -> i32; pub fn sceIoDevctl( dev: *const u8, cmd: u32, indata: *mut c_void, inlen: i32, outdata: *mut c_void, outlen: i32, ) -> i32; pub fn sceIoAssign( dev1: *const u8, dev2: *const u8, dev3: *const u8, mode: IoAssignPerms, unk1: *mut c_void, unk2: i32, ) -> i32; pub fn sceIoUnassign(dev: *const u8) -> i32; pub fn sceIoGetstat(file: *const u8, stat: *mut SceIoStat) -> i32; pub fn sceIoChstat(file: *const u8, stat: *mut SceIoStat, bits: i32) -> i32; pub fn sceIoIoctl( fd: SceUid, cmd: u32, indata: *mut c_void, inlen: i32, outdata: *mut c_void, outlen: i32, ) -> i32; pub fn sceIoIoctlAsync( fd: SceUid, cmd: u32, indata: *mut c_void, inlen: i32, outdata: *mut c_void, outlen: i32, ) -> i32; pub fn sceIoSync(device: *const u8, unk: u32) -> i32; pub fn sceIoWaitAsync(fd: SceUid, res: *mut i64) -> i32; pub fn sceIoWaitAsyncCB(fd: SceUid, res: *mut i64) -> i32; pub fn sceIoPollAsync(fd: SceUid, res: *mut i64) -> i32; pub fn sceIoGetAsyncStat(fd: SceUid, poll: i32, res: *mut i64) -> i32; pub fn sceIoCancel(fd: SceUid) -> i32; pub fn sceIoGetDevType(fd: SceUid) -> i32; pub fn sceIoChangeAsyncPriority(fd: SceUid, pri: i32) -> i32; pub fn sceIoSetAsyncCallback(fd: SceUid, cb: SceUid, argp: *mut c_void) -> i32; pub fn sceJpegInitMJpeg() -> i32; pub fn sceJpegFinishMJpeg() -> i32; pub fn sceJpegCreateMJpeg(width: i32, height: i32) -> i32; pub fn sceJpegDeleteMJpeg() -> i32; pub fn sceJpegDecodeMJpeg(jpeg_buf: *mut u8, size: usize, rgba: *mut c_void, unk: u32) -> i32; pub fn sceUmdCheckMedium() -> i32; pub fn sceUmdGetDiscInfo(info: *mut UmdInfo) -> i32; pub fn sceUmdActivate(unit: i32, drive: *const u8) -> i32; pub fn sceUmdDeactivate(unit: i32, drive: *const u8) -> i32; pub fn sceUmdWaitDriveStat(state: i32) -> i32; pub fn sceUmdWaitDriveStatWithTimer(state: i32, timeout: u32) -> i32; pub fn sceUmdWaitDriveStatCB(state: i32, timeout: u32) -> i32; pub fn sceUmdCancelWaitDriveStat() -> i32; pub fn sceUmdGetDriveStat() -> i32; pub fn sceUmdGetErrorStat() -> i32; pub fn sceUmdRegisterUMDCallBack(cbid: i32) -> i32; pub fn sceUmdUnRegisterUMDCallBack(cbid: i32) -> i32; pub fn sceUmdReplacePermit() -> i32; pub fn sceUmdReplaceProhibit() -> i32; pub fn sceMpegInit() -> i32; pub fn sceMpegFinish(); pub fn sceMpegRingbufferQueryMemSize(packets: i32) -> i32; pub fn sceMpegRingbufferConstruct( ringbuffer: *mut SceMpegRingbuffer, packets: i32, data: *mut c_void, size: i32, callback: SceMpegRingbufferCb, cb_param: *mut c_void, ) -> i32; pub fn sceMpegRingbufferDestruct(ringbuffer: *mut SceMpegRingbuffer); pub fn sceMpegRingbufferAvailableSize(ringbuffer: *mut SceMpegRingbuffer) -> i32; pub fn sceMpegRingbufferPut( ringbuffer: *mut SceMpegRingbuffer, num_packets: i32, available: i32, ) -> i32; pub fn sceMpegQueryMemSize(unk: i32) -> i32; pub fn sceMpegCreate( handle: SceMpeg, data: *mut c_void, size: i32, ringbuffer: *mut SceMpegRingbuffer, frame_width: i32, unk1: i32, unk2: i32, ) -> i32; pub fn sceMpegDelete(handle: SceMpeg); pub fn sceMpegQueryStreamOffset(handle: SceMpeg, buffer: *mut c_void, offset: *mut i32) -> i32; pub fn sceMpegQueryStreamSize(buffer: *mut c_void, size: *mut i32) -> i32; pub fn sceMpegRegistStream(handle: SceMpeg, stream_id: i32, unk: i32) -> SceMpegStream; pub fn sceMpegUnRegistStream(handle: SceMpeg, stream: SceMpegStream); pub fn sceMpegFlushAllStream(handle: SceMpeg) -> i32; pub fn sceMpegMallocAvcEsBuf(handle: SceMpeg) -> *mut c_void; pub fn sceMpegFreeAvcEsBuf(handle: SceMpeg, buf: *mut c_void); pub fn sceMpegQueryAtracEsSize(handle: SceMpeg, es_size: *mut i32, out_size: *mut i32) -> i32; pub fn sceMpegInitAu(handle: SceMpeg, es_buffer: *mut c_void, au: *mut SceMpegAu) -> i32; pub fn sceMpegGetAvcAu( handle: SceMpeg, stream: SceMpegStream, au: *mut SceMpegAu, unk: *mut i32, ) -> i32; pub fn sceMpegAvcDecodeMode(handle: SceMpeg, mode: *mut SceMpegAvcMode) -> i32; pub fn sceMpegAvcDecode( handle: SceMpeg, au: *mut SceMpegAu, iframe_width: i32, buffer: *mut c_void, init: *mut i32, ) -> i32; pub fn sceMpegAvcDecodeStop( handle: SceMpeg, frame_width: i32, buffer: *mut c_void, status: *mut i32, ) -> i32; pub fn sceMpegGetAtracAu( handle: SceMpeg, stream: SceMpegStream, au: *mut SceMpegAu, unk: *mut c_void, ) -> i32; pub fn sceMpegAtracDecode( handle: SceMpeg, au: *mut SceMpegAu, buffer: *mut c_void, init: i32, ) -> i32; pub fn sceMpegBaseYCrCbCopyVme(yuv_buffer: *mut c_void, buffer: *mut i32, type_: i32) -> i32; pub fn sceMpegBaseCscInit(width: i32) -> i32; pub fn sceMpegBaseCscVme( rgb_buffer: *mut c_void, rgb_buffer2: *mut c_void, width: i32, y_cr_cb_buffer: *mut SceMpegYCrCbBuffer, ) -> i32; pub fn sceMpegbase_BEA18F91(lli: *mut SceMpegLLI) -> i32; pub fn sceHprmPeekCurrentKey(key: *mut i32) -> i32; pub fn sceHprmPeekLatch(latch: *mut [u32; 4]) -> i32; pub fn sceHprmReadLatch(latch: *mut [u32; 4]) -> i32; pub fn sceHprmIsHeadphoneExist() -> i32; pub fn sceHprmIsRemoteExist() -> i32; pub fn sceHprmIsMicrophoneExist() -> i32; pub fn sceGuDepthBuffer(zbp: *mut c_void, zbw: i32); pub fn sceGuDispBuffer(width: i32, height: i32, dispbp: *mut c_void, dispbw: i32); pub fn sceGuDrawBuffer(psm: DisplayPixelFormat, fbp: *mut c_void, fbw: i32); pub fn sceGuDrawBufferList(psm: DisplayPixelFormat, fbp: *mut c_void, fbw: i32); pub fn sceGuDisplay(state: bool) -> bool; pub fn sceGuDepthFunc(function: DepthFunc); pub fn sceGuDepthMask(mask: i32); pub fn sceGuDepthOffset(offset: i32); pub fn sceGuDepthRange(near: i32, far: i32); pub fn sceGuFog(near: f32, far: f32, color: u32); pub fn sceGuInit(); pub fn sceGuTerm(); pub fn sceGuBreak(mode: i32); pub fn sceGuContinue(); pub fn sceGuSetCallback(signal: GuCallbackId, callback: GuCallback) -> GuCallback; pub fn sceGuSignal(behavior: SignalBehavior, signal: i32); pub fn sceGuSendCommandf(cmd: GeCommand, argument: f32); pub fn sceGuSendCommandi(cmd: GeCommand, argument: i32); pub fn sceGuGetMemory(size: i32) -> *mut c_void; pub fn sceGuStart(context_type: GuContextType, list: *mut c_void); pub fn sceGuFinish() -> i32; pub fn sceGuFinishId(id: u32) -> i32; pub fn sceGuCallList(list: *const c_void); pub fn sceGuCallMode(mode: i32); pub fn sceGuCheckList() -> i32; pub fn sceGuSendList(mode: GuQueueMode, list: *const c_void, context: *mut GeContext); pub fn sceGuSwapBuffers() -> *mut c_void; pub fn sceGuSync(mode: GuSyncMode, behavior: GuSyncBehavior) -> GeListState; pub fn sceGuDrawArray( prim: GuPrimitive, vtype: i32, count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGuBeginObject( vtype: i32, count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGuEndObject(); pub fn sceGuSetStatus(state: GuState, status: i32); pub fn sceGuGetStatus(state: GuState) -> bool; pub fn sceGuSetAllStatus(status: i32); pub fn sceGuGetAllStatus() -> i32; pub fn sceGuEnable(state: GuState); pub fn sceGuDisable(state: GuState); pub fn sceGuLight(light: i32, type_: LightType, components: i32, position: &ScePspFVector3); pub fn sceGuLightAtt(light: i32, atten0: f32, atten1: f32, atten2: f32); pub fn sceGuLightColor(light: i32, component: i32, color: u32); pub fn sceGuLightMode(mode: LightMode); pub fn sceGuLightSpot(light: i32, direction: &ScePspFVector3, exponent: f32, cutoff: f32); pub fn sceGuClear(flags: i32); pub fn sceGuClearColor(color: u32); pub fn sceGuClearDepth(depth: u32); pub fn sceGuClearStencil(stencil: u32); pub fn sceGuPixelMask(mask: u32); pub fn sceGuColor(color: u32); pub fn sceGuColorFunc(func: ColorFunc, color: u32, mask: u32); pub fn sceGuColorMaterial(components: i32); pub fn sceGuAlphaFunc(func: AlphaFunc, value: i32, mask: i32); pub fn sceGuAmbient(color: u32); pub fn sceGuAmbientColor(color: u32); pub fn sceGuBlendFunc(op: BlendOp, src: BlendSrc, dest: BlendDst, src_fix: u32, dest_fix: u32); pub fn sceGuMaterial(components: i32, color: u32); pub fn sceGuModelColor(emissive: u32, ambient: u32, diffuse: u32, specular: u32); pub fn sceGuStencilFunc(func: StencilFunc, ref_: i32, mask: i32); pub fn sceGuStencilOp(fail: StencilOperation, zfail: StencilOperation, zpass: StencilOperation); pub fn sceGuSpecular(power: f32); pub fn sceGuFrontFace(order: FrontFaceDirection); pub fn sceGuLogicalOp(op: LogicalOperation); pub fn sceGuSetDither(matrix: &ScePspIMatrix4); pub fn sceGuShadeModel(mode: ShadingModel); pub fn sceGuCopyImage( psm: DisplayPixelFormat, sx: i32, sy: i32, width: i32, height: i32, srcw: i32, src: *mut c_void, dx: i32, dy: i32, destw: i32, dest: *mut c_void, ); pub fn sceGuTexEnvColor(color: u32); pub fn sceGuTexFilter(min: TextureFilter, mag: TextureFilter); pub fn sceGuTexFlush(); pub fn sceGuTexFunc(tfx: TextureEffect, tcc: TextureColorComponent); pub fn sceGuTexImage( mipmap: MipmapLevel, width: i32, height: i32, tbw: i32, tbp: *const c_void, ); pub fn sceGuTexLevelMode(mode: TextureLevelMode, bias: f32); pub fn sceGuTexMapMode(mode: TextureMapMode, a1: u32, a2: u32); pub fn sceGuTexMode(tpsm: TexturePixelFormat, maxmips: i32, a2: i32, swizzle: i32); pub fn sceGuTexOffset(u: f32, v: f32); pub fn sceGuTexProjMapMode(mode: TextureProjectionMapMode); pub fn sceGuTexScale(u: f32, v: f32); pub fn sceGuTexSlope(slope: f32); pub fn sceGuTexSync(); pub fn sceGuTexWrap(u: GuTexWrapMode, v: GuTexWrapMode); pub fn sceGuClutLoad(num_blocks: i32, cbp: *const c_void); pub fn sceGuClutMode(cpsm: ClutPixelFormat, shift: u32, mask: u32, a3: u32); pub fn sceGuOffset(x: u32, y: u32); pub fn sceGuScissor(x: i32, y: i32, w: i32, h: i32); pub fn sceGuViewport(cx: i32, cy: i32, width: i32, height: i32); pub fn sceGuDrawBezier( v_type: i32, u_count: i32, v_count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGuPatchDivide(ulevel: u32, vlevel: u32); pub fn sceGuPatchFrontFace(a0: u32); pub fn sceGuPatchPrim(prim: PatchPrimitive); pub fn sceGuDrawSpline( v_type: i32, u_count: i32, v_count: i32, u_edge: i32, v_edge: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGuSetMatrix(type_: MatrixMode, matrix: &ScePspFMatrix4); pub fn sceGuBoneMatrix(index: u32, matrix: &ScePspFMatrix4); pub fn sceGuMorphWeight(index: i32, weight: f32); pub fn sceGuDrawArrayN( primitive_type: GuPrimitive, v_type: i32, count: i32, a3: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumDrawArray( prim: GuPrimitive, v_type: i32, count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumDrawArrayN( prim: GuPrimitive, v_type: i32, count: i32, a3: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumDrawBezier( v_type: i32, u_count: i32, v_count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumDrawSpline( v_type: i32, u_count: i32, v_count: i32, u_edge: i32, v_edge: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumFastInverse(); pub fn sceGumFullInverse(); pub fn sceGumLoadIdentity(); pub fn sceGumLoadMatrix(m: &ScePspFMatrix4); pub fn sceGumLookAt(eye: &ScePspFVector3, center: &ScePspFVector3, up: &ScePspFVector3); pub fn sceGumMatrixMode(mode: MatrixMode); pub fn sceGumMultMatrix(m: &ScePspFMatrix4); pub fn sceGumOrtho(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32); pub fn sceGumPerspective(fovy: f32, aspect: f32, near: f32, far: f32); pub fn sceGumPopMatrix(); pub fn sceGumPushMatrix(); pub fn sceGumRotateX(angle: f32); pub fn sceGumRotateY(angle: f32); pub fn sceGumRotateZ(angle: f32); pub fn sceGumRotateXYZ(v: &ScePspFVector3); pub fn sceGumRotateZYX(v: &ScePspFVector3); pub fn sceGumScale(v: &ScePspFVector3); pub fn sceGumStoreMatrix(m: &mut ScePspFMatrix4); pub fn sceGumTranslate(v: &ScePspFVector3); pub fn sceGumUpdateMatrix(); pub fn sceMp3ReserveMp3Handle(args: *mut SceMp3InitArg) -> i32; pub fn sceMp3ReleaseMp3Handle(handle: Mp3Handle) -> i32; pub fn sceMp3InitResource() -> i32; pub fn sceMp3TermResource() -> i32; pub fn sceMp3Init(handle: Mp3Handle) -> i32; pub fn sceMp3Decode(handle: Mp3Handle, dst: *mut *mut i16) -> i32; pub fn sceMp3GetInfoToAddStreamData( handle: Mp3Handle, dst: *mut *mut u8, to_write: *mut i32, src_pos: *mut i32, ) -> i32; pub fn sceMp3NotifyAddStreamData(handle: Mp3Handle, size: i32) -> i32; pub fn sceMp3CheckStreamDataNeeded(handle: Mp3Handle) -> i32; pub fn sceMp3SetLoopNum(handle: Mp3Handle, loop_: i32) -> i32; pub fn sceMp3GetLoopNum(handle: Mp3Handle) -> i32; pub fn sceMp3GetSumDecodedSample(handle: Mp3Handle) -> i32; pub fn sceMp3GetMaxOutputSample(handle: Mp3Handle) -> i32; pub fn sceMp3GetSamplingRate(handle: Mp3Handle) -> i32; pub fn sceMp3GetBitRate(handle: Mp3Handle) -> i32; pub fn sceMp3GetMp3ChannelNum(handle: Mp3Handle) -> i32; pub fn sceMp3ResetPlayPosition(handle: Mp3Handle) -> i32; pub fn sceRegOpenRegistry(reg: *mut Key, mode: i32, handle: *mut RegHandle) -> i32; pub fn sceRegFlushRegistry(handle: RegHandle) -> i32; pub fn sceRegCloseRegistry(handle: RegHandle) -> i32; pub fn sceRegOpenCategory( handle: RegHandle, name: *const u8, mode: i32, dir_handle: *mut RegHandle, ) -> i32; pub fn sceRegRemoveCategory(handle: RegHandle, name: *const u8) -> i32; pub fn sceRegCloseCategory(dir_handle: RegHandle) -> i32; pub fn sceRegFlushCategory(dir_handle: RegHandle) -> i32; pub fn sceRegGetKeyInfo( dir_handle: RegHandle, name: *const u8, key_handle: *mut RegHandle, type_: *mut KeyType, size: *mut usize, ) -> i32; pub fn sceRegGetKeyInfoByName( dir_handle: RegHandle, name: *const u8, type_: *mut KeyType, size: *mut usize, ) -> i32; pub fn sceRegGetKeyValue( dir_handle: RegHandle, key_handle: RegHandle, buf: *mut c_void, size: usize, ) -> i32; pub fn sceRegGetKeyValueByName( dir_handle: RegHandle, name: *const u8, buf: *mut c_void, size: usize, ) -> i32; pub fn sceRegSetKeyValue( dir_handle: RegHandle, name: *const u8, buf: *const c_void, size: usize, ) -> i32; pub fn sceRegGetKeysNum(dir_handle: RegHandle, num: *mut i32) -> i32; pub fn sceRegGetKeys(dir_handle: RegHandle, buf: *mut u8, num: i32) -> i32; pub fn sceRegCreateKey(dir_handle: RegHandle, name: *const u8, type_: i32, size: usize) -> i32; pub fn sceRegRemoveRegistry(key: *mut Key) -> i32; pub fn sceOpenPSIDGetOpenPSID(openpsid: *mut OpenPSID) -> i32; pub fn sceUtilityMsgDialogInitStart(params: *mut UtilityMsgDialogParams) -> i32; pub fn sceUtilityMsgDialogShutdownStart(); pub fn sceUtilityMsgDialogGetStatus() -> i32; pub fn sceUtilityMsgDialogUpdate(n: i32); pub fn sceUtilityMsgDialogAbort() -> i32; pub fn sceUtilityNetconfInitStart(data: *mut UtilityNetconfData) -> i32; pub fn sceUtilityNetconfShutdownStart() -> i32; pub fn sceUtilityNetconfUpdate(unknown: i32) -> i32; pub fn sceUtilityNetconfGetStatus() -> i32; pub fn sceUtilityCheckNetParam(id: i32) -> i32; pub fn sceUtilityGetNetParam(conf: i32, param: NetParam, data: *mut UtilityNetData) -> i32; pub fn sceUtilitySavedataInitStart(params: *mut SceUtilitySavedataParam) -> i32; pub fn sceUtilitySavedataGetStatus() -> i32; pub fn sceUtilitySavedataShutdownStart() -> i32; pub fn sceUtilitySavedataUpdate(unknown: i32); pub fn sceUtilityGameSharingInitStart(params: *mut UtilityGameSharingParams) -> i32; pub fn sceUtilityGameSharingShutdownStart(); pub fn sceUtilityGameSharingGetStatus() -> i32; pub fn sceUtilityGameSharingUpdate(n: i32); pub fn sceUtilityHtmlViewerInitStart(params: *mut UtilityHtmlViewerParam) -> i32; pub fn sceUtilityHtmlViewerShutdownStart() -> i32; pub fn sceUtilityHtmlViewerUpdate(n: i32) -> i32; pub fn sceUtilityHtmlViewerGetStatus() -> i32; pub fn sceUtilitySetSystemParamInt(id: SystemParamId, value: i32) -> i32; pub fn sceUtilitySetSystemParamString(id: SystemParamId, str: *const u8) -> i32; pub fn sceUtilityGetSystemParamInt(id: SystemParamId, value: *mut i32) -> i32; pub fn sceUtilityGetSystemParamString(id: SystemParamId, str: *mut u8, len: i32) -> i32; pub fn sceUtilityOskInitStart(params: *mut SceUtilityOskParams) -> i32; pub fn sceUtilityOskShutdownStart() -> i32; pub fn sceUtilityOskUpdate(n: i32) -> i32; pub fn sceUtilityOskGetStatus() -> i32; pub fn sceUtilityLoadNetModule(module: NetModule) -> i32; pub fn sceUtilityUnloadNetModule(module: NetModule) -> i32; pub fn sceUtilityLoadAvModule(module: AvModule) -> i32; pub fn sceUtilityUnloadAvModule(module: AvModule) -> i32; pub fn sceUtilityLoadUsbModule(module: UsbModule) -> i32; pub fn sceUtilityUnloadUsbModule(module: UsbModule) -> i32; pub fn sceUtilityLoadModule(module: Module) -> i32; pub fn sceUtilityUnloadModule(module: Module) -> i32; pub fn sceUtilityCreateNetParam(conf: i32) -> i32; pub fn sceUtilitySetNetParam(param: NetParam, val: *const c_void) -> i32; pub fn sceUtilityCopyNetParam(src: i32, dest: i32) -> i32; pub fn sceUtilityDeleteNetParam(conf: i32) -> i32; pub fn sceNetInit( poolsize: i32, calloutprio: i32, calloutstack: i32, netintrprio: i32, netintrstack: i32, ) -> i32; pub fn sceNetTerm() -> i32; pub fn sceNetFreeThreadinfo(thid: i32) -> i32; pub fn sceNetThreadAbort(thid: i32) -> i32; pub fn sceNetEtherStrton(name: *mut u8, mac: *mut u8); pub fn sceNetEtherNtostr(mac: *mut u8, name: *mut u8); pub fn sceNetGetLocalEtherAddr(mac: *mut u8) -> i32; pub fn sceNetGetMallocStat(stat: *mut SceNetMallocStat) -> i32; pub fn sceNetAdhocctlInit( stacksize: i32, priority: i32, adhoc_id: *mut SceNetAdhocctlAdhocId, ) -> i32; pub fn sceNetAdhocctlTerm() -> i32; pub fn sceNetAdhocctlConnect(name: *const u8) -> i32; pub fn sceNetAdhocctlDisconnect() -> i32; pub fn sceNetAdhocctlGetState(event: *mut i32) -> i32; pub fn sceNetAdhocctlCreate(name: *const u8) -> i32; pub fn sceNetAdhocctlJoin(scaninfo: *mut SceNetAdhocctlScanInfo) -> i32; pub fn sceNetAdhocctlGetAdhocId(id: *mut SceNetAdhocctlAdhocId) -> i32; pub fn sceNetAdhocctlCreateEnterGameMode( name: *const u8, unknown: i32, num: i32, macs: *mut u8, timeout: u32, unknown2: i32, ) -> i32; pub fn sceNetAdhocctlJoinEnterGameMode( name: *const u8, hostmac: *mut u8, timeout: u32, unknown: i32, ) -> i32; pub fn sceNetAdhocctlGetGameModeInfo(gamemodeinfo: *mut SceNetAdhocctlGameModeInfo) -> i32; pub fn sceNetAdhocctlExitGameMode() -> i32; pub fn sceNetAdhocctlGetPeerList(length: *mut i32, buf: *mut c_void) -> i32; pub fn sceNetAdhocctlGetPeerInfo( mac: *mut u8, size: i32, peerinfo: *mut SceNetAdhocctlPeerInfo, ) -> i32; pub fn sceNetAdhocctlScan() -> i32; pub fn sceNetAdhocctlGetScanInfo(length: *mut i32, buf: *mut c_void) -> i32; pub fn sceNetAdhocctlAddHandler(handler: SceNetAdhocctlHandler, unknown: *mut c_void) -> i32; pub fn sceNetAdhocctlDelHandler(id: i32) -> i32; pub fn sceNetAdhocctlGetNameByAddr(mac: *mut u8, nickname: *mut u8) -> i32; pub fn sceNetAdhocctlGetAddrByName( nickname: *mut u8, length: *mut i32, buf: *mut c_void, ) -> i32; pub fn sceNetAdhocctlGetParameter(params: *mut SceNetAdhocctlParams) -> i32; pub fn sceNetAdhocInit() -> i32; pub fn sceNetAdhocTerm() -> i32; pub fn sceNetAdhocPdpCreate(mac: *mut u8, port: u16, buf_size: u32, unk1: i32) -> i32; pub fn sceNetAdhocPdpDelete(id: i32, unk1: i32) -> i32; pub fn sceNetAdhocPdpSend( id: i32, dest_mac_addr: *mut u8, port: u16, data: *mut c_void, len: u32, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocPdpRecv( id: i32, src_mac_addr: *mut u8, port: *mut u16, data: *mut c_void, data_length: *mut c_void, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocGetPdpStat(size: *mut i32, stat: *mut SceNetAdhocPdpStat) -> i32; pub fn sceNetAdhocGameModeCreateMaster(data: *mut c_void, size: i32) -> i32; pub fn sceNetAdhocGameModeCreateReplica(mac: *mut u8, data: *mut c_void, size: i32) -> i32; pub fn sceNetAdhocGameModeUpdateMaster() -> i32; pub fn sceNetAdhocGameModeUpdateReplica(id: i32, unk1: i32) -> i32; pub fn sceNetAdhocGameModeDeleteMaster() -> i32; pub fn sceNetAdhocGameModeDeleteReplica(id: i32) -> i32; pub fn sceNetAdhocPtpOpen( srcmac: *mut u8, srcport: u16, destmac: *mut u8, destport: u16, buf_size: u32, delay: u32, count: i32, unk1: i32, ) -> i32; pub fn sceNetAdhocPtpConnect(id: i32, timeout: u32, nonblock: i32) -> i32; pub fn sceNetAdhocPtpListen( srcmac: *mut u8, srcport: u16, buf_size: u32, delay: u32, count: i32, queue: i32, unk1: i32, ) -> i32; pub fn sceNetAdhocPtpAccept( id: i32, mac: *mut u8, port: *mut u16, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocPtpSend( id: i32, data: *mut c_void, data_size: *mut i32, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocPtpRecv( id: i32, data: *mut c_void, data_size: *mut i32, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocPtpFlush(id: i32, timeout: u32, nonblock: i32) -> i32; pub fn sceNetAdhocPtpClose(id: i32, unk1: i32) -> i32; pub fn sceNetAdhocGetPtpStat(size: *mut i32, stat: *mut SceNetAdhocPtpStat) -> i32; } extern "C" { pub fn sceNetAdhocMatchingInit(memsize: i32) -> i32; pub fn sceNetAdhocMatchingTerm() -> i32; pub fn sceNetAdhocMatchingCreate( mode: AdhocMatchingMode, max_peers: i32, port: u16, buf_size: i32, hello_delay: u32, ping_delay: u32, init_count: i32, msg_delay: u32, callback: AdhocMatchingCallback, ) -> i32; pub fn sceNetAdhocMatchingDelete(matching_id: i32) -> i32; pub fn sceNetAdhocMatchingStart( matching_id: i32, evth_pri: i32, evth_stack: i32, inth_pri: i32, inth_stack: i32, opt_len: i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingStop(matching_id: i32) -> i32; pub fn sceNetAdhocMatchingSelectTarget( matching_id: i32, mac: *mut u8, opt_len: i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingCancelTarget(matching_id: i32, mac: *mut u8) -> i32; pub fn sceNetAdhocMatchingCancelTargetWithOpt( matching_id: i32, mac: *mut u8, opt_len: i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingSendData( matching_id: i32, mac: *mut u8, data_len: i32, data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingAbortSendData(matching_id: i32, mac: *mut u8) -> i32; pub fn sceNetAdhocMatchingSetHelloOpt( matching_id: i32, opt_len: i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingGetHelloOpt( matching_id: i32, opt_len: *mut i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingGetMembers( matching_id: i32, length: *mut i32, buf: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingGetPoolMaxAlloc() -> i32; pub fn sceNetAdhocMatchingGetPoolStat(poolstat: *mut AdhocPoolStat) -> i32; } extern "C" { pub fn sceNetApctlInit(stack_size: i32, init_priority: i32) -> i32; pub fn sceNetApctlTerm() -> i32; pub fn sceNetApctlGetInfo(code: ApctlInfo, pinfo: *mut SceNetApctlInfo) -> i32; pub fn sceNetApctlAddHandler(handler: SceNetApctlHandler, parg: *mut c_void) -> i32; pub fn sceNetApctlDelHandler(handler_id: i32) -> i32; pub fn sceNetApctlConnect(conn_index: i32) -> i32; pub fn sceNetApctlDisconnect() -> i32; pub fn sceNetApctlGetState(pstate: *mut ApctlState) -> i32; pub fn sceNetInetInit() -> i32; pub fn sceNetInetTerm() -> i32; pub fn sceNetInetAccept(s: i32, addr: *mut sockaddr, addr_len: *mut socklen_t) -> i32; pub fn sceNetInetBind(s: i32, my_addr: *const sockaddr, addr_len: socklen_t) -> i32; pub fn sceNetInetConnect(s: i32, serv_addr: *const sockaddr, addr_len: socklen_t) -> i32; pub fn sceNetInetGetsockopt( s: i32, level: i32, opt_name: i32, opt_val: *mut c_void, optl_en: *mut socklen_t, ) -> i32; pub fn sceNetInetListen(s: i32, backlog: i32) -> i32; pub fn sceNetInetRecv(s: i32, buf: *mut c_void, len: usize, flags: i32) -> usize; pub fn sceNetInetRecvfrom( s: i32, buf: *mut c_void, flags: usize, arg1: i32, from: *mut sockaddr, from_len: *mut socklen_t, ) -> usize; pub fn sceNetInetSend(s: i32, buf: *const c_void, len: usize, flags: i32) -> usize; pub fn sceNetInetSendto( s: i32, buf: *const c_void, len: usize, flags: i32, to: *const sockaddr, to_len: socklen_t, ) -> usize; pub fn sceNetInetSetsockopt( s: i32, level: i32, opt_name: i32, opt_val: *const c_void, opt_len: socklen_t, ) -> i32; pub fn sceNetInetShutdown(s: i32, how: i32) -> i32; pub fn sceNetInetSocket(domain: i32, type_: i32, protocol: i32) -> i32; pub fn sceNetInetClose(s: i32) -> i32; pub fn sceNetInetGetErrno() -> i32; pub fn sceSslInit(unknown1: i32) -> i32; pub fn sceSslEnd() -> i32; pub fn sceSslGetUsedMemoryMax(memory: *mut u32) -> i32; pub fn sceSslGetUsedMemoryCurrent(memory: *mut u32) -> i32; pub fn sceHttpInit(unknown1: u32) -> i32; pub fn sceHttpEnd() -> i32; pub fn sceHttpCreateTemplate(agent: *mut u8, unknown1: i32, unknown2: i32) -> i32; pub fn sceHttpDeleteTemplate(templateid: i32) -> i32; pub fn sceHttpCreateConnection( templateid: i32, host: *mut u8, unknown1: *mut u8, port: u16, unknown2: i32, ) -> i32; pub fn sceHttpCreateConnectionWithURL(templateid: i32, url: *const u8, unknown1: i32) -> i32; pub fn sceHttpDeleteConnection(connection_id: i32) -> i32; pub fn sceHttpCreateRequest( connection_id: i32, method: HttpMethod, path: *mut u8, content_length: u64, ) -> i32; pub fn sceHttpCreateRequestWithURL( connection_id: i32, method: HttpMethod, url: *mut u8, content_length: u64, ) -> i32; pub fn sceHttpDeleteRequest(request_id: i32) -> i32; pub fn sceHttpSendRequest(request_id: i32, data: *mut c_void, data_size: u32) -> i32; pub fn sceHttpAbortRequest(request_id: i32) -> i32; pub fn sceHttpReadData(request_id: i32, data: *mut c_void, data_size: u32) -> i32; pub fn sceHttpGetContentLength(request_id: i32, content_length: *mut u64) -> i32; pub fn sceHttpGetStatusCode(request_id: i32, status_code: *mut i32) -> i32; pub fn sceHttpSetResolveTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpSetResolveRetry(id: i32, count: i32) -> i32; pub fn sceHttpSetConnectTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpSetSendTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpSetRecvTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpEnableKeepAlive(id: i32) -> i32; pub fn sceHttpDisableKeepAlive(id: i32) -> i32; pub fn sceHttpEnableRedirect(id: i32) -> i32; pub fn sceHttpDisableRedirect(id: i32) -> i32; pub fn sceHttpEnableCookie(id: i32) -> i32; pub fn sceHttpDisableCookie(id: i32) -> i32; pub fn sceHttpSaveSystemCookie() -> i32; pub fn sceHttpLoadSystemCookie() -> i32; pub fn sceHttpAddExtraHeader(id: i32, name: *mut u8, value: *mut u8, unknown1: i32) -> i32; pub fn sceHttpDeleteHeader(id: i32, name: *const u8) -> i32; pub fn sceHttpsInit(unknown1: i32, unknown2: i32, unknown3: i32, unknown4: i32) -> i32; pub fn sceHttpsEnd() -> i32; pub fn sceHttpsLoadDefaultCert(unknown1: i32, unknown2: i32) -> i32; pub fn sceHttpDisableAuth(id: i32) -> i32; pub fn sceHttpDisableCache(id: i32) -> i32; pub fn sceHttpEnableAuth(id: i32) -> i32; pub fn sceHttpEnableCache(id: i32) -> i32; pub fn sceHttpEndCache() -> i32; pub fn sceHttpGetAllHeader(request: i32, header: *mut *mut u8, header_size: *mut u32) -> i32; pub fn sceHttpGetNetworkErrno(request: i32, err_num: *mut i32) -> i32; pub fn sceHttpGetProxy( id: i32, activate_flag: *mut i32, mode: *mut i32, proxy_host: *mut u8, len: usize, proxy_port: *mut u16, ) -> i32; pub fn sceHttpInitCache(max_size: usize) -> i32; pub fn sceHttpSetAuthInfoCB(id: i32, cbfunc: HttpPasswordCB) -> i32; pub fn sceHttpSetProxy( id: i32, activate_flag: i32, mode: i32, new_proxy_host: *const u8, new_proxy_port: u16, ) -> i32; pub fn sceHttpSetResHeaderMaxSize(id: i32, header_size: u32) -> i32; pub fn sceHttpSetMallocFunction( malloc_func: HttpMallocFunction, free_func: HttpFreeFunction, realloc_func: HttpReallocFunction, ) -> i32; pub fn sceNetResolverInit() -> i32; pub fn sceNetResolverCreate(rid: *mut i32, buf: *mut c_void, buf_length: u32) -> i32; pub fn sceNetResolverDelete(rid: i32) -> i32; pub fn sceNetResolverStartNtoA( rid: i32, hostname: *const u8, addr: *mut in_addr, timeout: u32, retry: i32, ) -> i32; pub fn sceNetResolverStartAtoN( rid: i32, addr: *const in_addr, hostname: *mut u8, hostname_len: u32, timeout: u32, retry: i32, ) -> i32; pub fn sceNetResolverStop(rid: i32) -> i32; pub fn sceNetResolverTerm() -> i32; } libc/src/switch.rs0000644000175000017500000000053015105742312013747 0ustar bdrungbdrung//! Switch C type definitions pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type off_t = i64; pub type wchar_t = u32; pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; libc/src/windows/0000775000175000017500000000000015105742312013576 5ustar bdrungbdrunglibc/src/windows/mod.rs0000644000175000017500000005110215105742312014720 0ustar bdrungbdrung//! Windows CRT definitions use crate::prelude::*; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type sighandler_t = usize; pub type wchar_t = u16; pub type clock_t = i32; pub type errno_t = c_int; cfg_if! { if #[cfg(all(target_arch = "x86", target_env = "gnu"))] { pub type time_t = i32; } else { pub type time_t = i64; } } pub type off_t = i32; pub type dev_t = u32; pub type ino_t = u16; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } pub type time64_t = i64; pub type SOCKET = crate::uintptr_t; s! { // note this is the struct called stat64 in Windows. Not stat, nor stati64. pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: u16, pub st_nlink: c_short, pub st_uid: c_short, pub st_gid: c_short, pub st_rdev: dev_t, pub st_size: i64, pub st_atime: time64_t, pub st_mtime: time64_t, pub st_ctime: time64_t, } // note that this is called utimbuf64 in Windows pub struct utimbuf { pub actime: time64_t, pub modtime: time64_t, } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, } pub struct timeval { pub tv_sec: c_long, pub tv_usec: c_long, } pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } pub struct sockaddr { pub sa_family: c_ushort, pub sa_data: [c_char; 14], } } pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 32767; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 4; pub const _IOLBF: c_int = 64; pub const BUFSIZ: c_uint = 512; pub const FOPEN_MAX: c_uint = 20; pub const FILENAME_MAX: c_uint = 260; // fcntl.h pub const O_RDONLY: c_int = 0x0000; pub const O_WRONLY: c_int = 0x0001; pub const O_RDWR: c_int = 0x0002; pub const O_APPEND: c_int = 0x0008; pub const O_CREAT: c_int = 0x0100; pub const O_TRUNC: c_int = 0x0200; pub const O_EXCL: c_int = 0x0400; pub const O_TEXT: c_int = 0x4000; pub const O_BINARY: c_int = 0x8000; pub const _O_WTEXT: c_int = 0x10000; pub const _O_U16TEXT: c_int = 0x20000; pub const _O_U8TEXT: c_int = 0x40000; pub const O_RAW: c_int = O_BINARY; pub const O_NOINHERIT: c_int = 0x0080; pub const O_TEMPORARY: c_int = 0x0040; pub const _O_SHORT_LIVED: c_int = 0x1000; pub const _O_OBTAIN_DIR: c_int = 0x2000; pub const O_SEQUENTIAL: c_int = 0x0020; pub const O_RANDOM: c_int = 0x0010; pub const S_IFCHR: c_int = 0o2_0000; pub const S_IFDIR: c_int = 0o4_0000; pub const S_IFREG: c_int = 0o10_0000; pub const S_IFMT: c_int = 0o17_0000; pub const S_IEXEC: c_int = 0o0100; pub const S_IWRITE: c_int = 0o0200; pub const S_IREAD: c_int = 0o0400; pub const LC_ALL: c_int = 0; pub const LC_COLLATE: c_int = 1; pub const LC_CTYPE: c_int = 2; pub const LC_MONETARY: c_int = 3; pub const LC_NUMERIC: c_int = 4; pub const LC_TIME: c_int = 5; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EDEADLK: c_int = 36; pub const EDEADLOCK: c_int = 36; pub const ENAMETOOLONG: c_int = 38; pub const ENOLCK: c_int = 39; pub const ENOSYS: c_int = 40; pub const ENOTEMPTY: c_int = 41; pub const EILSEQ: c_int = 42; pub const STRUNCATE: c_int = 80; // POSIX Supplement (from errno.h) pub const EADDRINUSE: c_int = 100; pub const EADDRNOTAVAIL: c_int = 101; pub const EAFNOSUPPORT: c_int = 102; pub const EALREADY: c_int = 103; pub const EBADMSG: c_int = 104; pub const ECANCELED: c_int = 105; pub const ECONNABORTED: c_int = 106; pub const ECONNREFUSED: c_int = 107; pub const ECONNRESET: c_int = 108; pub const EDESTADDRREQ: c_int = 109; pub const EHOSTUNREACH: c_int = 110; pub const EIDRM: c_int = 111; pub const EINPROGRESS: c_int = 112; pub const EISCONN: c_int = 113; pub const ELOOP: c_int = 114; pub const EMSGSIZE: c_int = 115; pub const ENETDOWN: c_int = 116; pub const ENETRESET: c_int = 117; pub const ENETUNREACH: c_int = 118; pub const ENOBUFS: c_int = 119; pub const ENODATA: c_int = 120; pub const ENOLINK: c_int = 121; pub const ENOMSG: c_int = 122; pub const ENOPROTOOPT: c_int = 123; pub const ENOSR: c_int = 124; pub const ENOSTR: c_int = 125; pub const ENOTCONN: c_int = 126; pub const ENOTRECOVERABLE: c_int = 127; pub const ENOTSOCK: c_int = 128; pub const ENOTSUP: c_int = 129; pub const EOPNOTSUPP: c_int = 130; pub const EOVERFLOW: c_int = 132; pub const EOWNERDEAD: c_int = 133; pub const EPROTO: c_int = 134; pub const EPROTONOSUPPORT: c_int = 135; pub const EPROTOTYPE: c_int = 136; pub const ETIME: c_int = 137; pub const ETIMEDOUT: c_int = 138; pub const ETXTBSY: c_int = 139; pub const EWOULDBLOCK: c_int = 140; // signal codes pub const SIGINT: c_int = 2; pub const SIGILL: c_int = 4; pub const SIGFPE: c_int = 8; pub const SIGSEGV: c_int = 11; pub const SIGTERM: c_int = 15; pub const SIGABRT: c_int = 22; pub const NSIG: c_int = 23; pub const SIG_ERR: c_int = -1; pub const SIG_DFL: crate::sighandler_t = 0; pub const SIG_IGN: crate::sighandler_t = 1; pub const SIG_GET: crate::sighandler_t = 2; pub const SIG_SGE: crate::sighandler_t = 3; pub const SIG_ACK: crate::sighandler_t = 4; // DIFF(main): removed in 458c58f409 // FIXME(msrv): done by `std` starting in 1.79.0 // inline comment below appeases style checker #[cfg(all(target_env = "msvc", feature = "rustc-dep-of-std"))] // " if " #[link(name = "msvcrt", cfg(not(target_feature = "crt-static")))] #[link(name = "libcmt", cfg(target_feature = "crt-static"))] extern "C" {} #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} impl Copy for FILE {} impl Clone for FILE { fn clone(&self) -> FILE { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} // FIXME(windows): fill this out with a struct impl Copy for fpos_t {} impl Clone for fpos_t { fn clone(&self) -> fpos_t { *self } } // Special handling for all print and scan type functions because of https://github.com/rust-lang/libc/issues/2860 cfg_if! { if #[cfg(not(feature = "rustc-dep-of-std"))] { #[cfg_attr( all(windows, target_env = "msvc"), link(name = "legacy_stdio_definitions") )] extern "C" { pub fn printf(format: *const c_char, ...) -> c_int; pub fn fprintf(stream: *mut FILE, format: *const c_char, ...) -> c_int; } } } extern "C" { pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; pub fn feof(stream: *mut FILE) -> c_int; pub fn ferror(stream: *mut FILE) -> c_int; pub fn perror(s: *const c_char); pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn _msize(p: *mut c_void) -> size_t; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn abort() -> !; pub fn exit(status: c_int) -> !; pub fn _exit(status: c_int) -> !; pub fn atexit(cb: extern "C" fn()) -> c_int; pub fn system(s: *const c_char) -> c_int; pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; pub fn raise(signum: c_int) -> c_int; #[link_name = "_gmtime64_s"] pub fn gmtime_s(destTime: *mut tm, srcTime: *const time_t) -> c_int; #[link_name = "_localtime64_s"] pub fn localtime_s(tmDest: *mut tm, sourceTime: *const time_t) -> crate::errno_t; #[link_name = "_time64"] pub fn time(destTime: *mut time_t) -> time_t; #[link_name = "_chmod"] pub fn chmod(path: *const c_char, mode: c_int) -> c_int; #[link_name = "_wchmod"] pub fn wchmod(path: *const wchar_t, mode: c_int) -> c_int; #[link_name = "_mkdir"] pub fn mkdir(path: *const c_char) -> c_int; #[link_name = "_wrmdir"] pub fn wrmdir(path: *const wchar_t) -> c_int; #[link_name = "_fstat64"] pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; #[link_name = "_stat64"] pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; #[link_name = "_wstat64"] pub fn wstat(path: *const wchar_t, buf: *mut stat) -> c_int; #[link_name = "_wutime64"] pub fn wutime(file: *const wchar_t, buf: *mut utimbuf) -> c_int; #[link_name = "_popen"] pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; #[link_name = "_pclose"] pub fn pclose(stream: *mut crate::FILE) -> c_int; #[link_name = "_fdopen"] pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut crate::FILE; #[link_name = "_fileno"] pub fn fileno(stream: *mut crate::FILE) -> c_int; #[link_name = "_open"] pub fn open(path: *const c_char, oflag: c_int, ...) -> c_int; #[link_name = "_wopen"] pub fn wopen(path: *const wchar_t, oflag: c_int, ...) -> c_int; #[link_name = "_creat"] pub fn creat(path: *const c_char, mode: c_int) -> c_int; #[link_name = "_access"] pub fn access(path: *const c_char, amode: c_int) -> c_int; #[link_name = "_chdir"] pub fn chdir(dir: *const c_char) -> c_int; #[link_name = "_close"] pub fn close(fd: c_int) -> c_int; #[link_name = "_dup"] pub fn dup(fd: c_int) -> c_int; #[link_name = "_dup2"] pub fn dup2(src: c_int, dst: c_int) -> c_int; #[link_name = "_execl"] pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexecl"] pub fn wexecl(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execle"] pub fn execle(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexecle"] pub fn wexecle(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execlp"] pub fn execlp(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexeclp"] pub fn wexeclp(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execlpe"] pub fn execlpe(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexeclpe"] pub fn wexeclpe(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execv"] // DIFF(main): changed to `intptr_t` in e77f551de9 pub fn execv(prog: *const c_char, argv: *const *const c_char) -> intptr_t; #[link_name = "_execve"] pub fn execve( prog: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; #[link_name = "_execvp"] pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int; #[link_name = "_execvpe"] pub fn execvpe( c: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; #[link_name = "_wexecv"] pub fn wexecv(prog: *const wchar_t, argv: *const *const wchar_t) -> intptr_t; #[link_name = "_wexecve"] pub fn wexecve( prog: *const wchar_t, argv: *const *const wchar_t, envp: *const *const wchar_t, ) -> intptr_t; #[link_name = "_wexecvp"] pub fn wexecvp(c: *const wchar_t, argv: *const *const wchar_t) -> intptr_t; #[link_name = "_wexecvpe"] pub fn wexecvpe( c: *const wchar_t, argv: *const *const wchar_t, envp: *const *const wchar_t, ) -> intptr_t; #[link_name = "_getcwd"] pub fn getcwd(buf: *mut c_char, size: c_int) -> *mut c_char; #[link_name = "_getpid"] pub fn getpid() -> c_int; #[link_name = "_isatty"] pub fn isatty(fd: c_int) -> c_int; #[link_name = "_lseek"] pub fn lseek(fd: c_int, offset: c_long, origin: c_int) -> c_long; #[link_name = "_lseeki64"] pub fn lseek64(fd: c_int, offset: c_longlong, origin: c_int) -> c_longlong; #[link_name = "_pipe"] pub fn pipe(fds: *mut c_int, psize: c_uint, textmode: c_int) -> c_int; #[link_name = "_read"] pub fn read(fd: c_int, buf: *mut c_void, count: c_uint) -> c_int; #[link_name = "_rmdir"] pub fn rmdir(path: *const c_char) -> c_int; #[link_name = "_unlink"] pub fn unlink(c: *const c_char) -> c_int; #[link_name = "_write"] pub fn write(fd: c_int, buf: *const c_void, count: c_uint) -> c_int; #[link_name = "_commit"] pub fn commit(fd: c_int) -> c_int; #[link_name = "_get_osfhandle"] pub fn get_osfhandle(fd: c_int) -> intptr_t; #[link_name = "_open_osfhandle"] pub fn open_osfhandle(osfhandle: intptr_t, flags: c_int) -> c_int; pub fn setlocale(category: c_int, locale: *const c_char) -> *mut c_char; #[link_name = "_wsetlocale"] pub fn wsetlocale(category: c_int, locale: *const wchar_t) -> *mut wchar_t; #[link_name = "_aligned_malloc"] pub fn aligned_malloc(size: size_t, alignment: size_t) -> *mut c_void; #[link_name = "_aligned_free"] pub fn aligned_free(ptr: *mut c_void); #[link_name = "_aligned_realloc"] pub fn aligned_realloc(memblock: *mut c_void, size: size_t, alignment: size_t) -> *mut c_void; #[link_name = "_putenv"] pub fn putenv(envstring: *const c_char) -> c_int; #[link_name = "_wputenv"] pub fn wputenv(envstring: *const crate::wchar_t) -> c_int; #[link_name = "_putenv_s"] pub fn putenv_s(envstring: *const c_char, value_string: *const c_char) -> crate::errno_t; #[link_name = "_wputenv_s"] pub fn wputenv_s( envstring: *const crate::wchar_t, value_string: *const crate::wchar_t, ) -> crate::errno_t; } extern "system" { pub fn listen(s: SOCKET, backlog: c_int) -> c_int; pub fn accept(s: SOCKET, addr: *mut crate::sockaddr, addrlen: *mut c_int) -> SOCKET; pub fn bind(s: SOCKET, name: *const crate::sockaddr, namelen: c_int) -> c_int; pub fn connect(s: SOCKET, name: *const crate::sockaddr, namelen: c_int) -> c_int; pub fn getpeername(s: SOCKET, name: *mut crate::sockaddr, nameln: *mut c_int) -> c_int; pub fn getsockname(s: SOCKET, name: *mut crate::sockaddr, nameln: *mut c_int) -> c_int; pub fn getsockopt( s: SOCKET, level: c_int, optname: c_int, optval: *mut c_char, optlen: *mut c_int, ) -> c_int; pub fn recvfrom( s: SOCKET, buf: *mut c_char, len: c_int, flags: c_int, from: *mut crate::sockaddr, fromlen: *mut c_int, ) -> c_int; pub fn sendto( s: SOCKET, buf: *const c_char, len: c_int, flags: c_int, to: *const crate::sockaddr, tolen: c_int, ) -> c_int; pub fn setsockopt( s: SOCKET, level: c_int, optname: c_int, optval: *const c_char, optlen: c_int, ) -> c_int; pub fn socket(af: c_int, socket_type: c_int, protocol: c_int) -> SOCKET; } cfg_if! { if #[cfg(all(target_env = "gnu"))] { mod gnu; pub use self::gnu::*; } else if #[cfg(all(target_env = "msvc"))] { mod msvc; pub use self::msvc::*; } else { // Unknown target_env } } libc/src/windows/msvc/0000775000175000017500000000000015105742312014546 5ustar bdrungbdrunglibc/src/windows/msvc/mod.rs0000644000175000017500000000112215105742312015665 0ustar bdrungbdrunguse crate::prelude::*; pub const L_tmpnam: c_uint = 260; pub const TMP_MAX: c_uint = 0x7fff_ffff; // POSIX Supplement (from errno.h) // This particular error code is only currently available in msvc toolchain pub const EOTHER: c_int = 131; extern "C" { #[link_name = "_stricmp"] pub fn stricmp(s1: *const c_char, s2: *const c_char) -> c_int; #[link_name = "_strnicmp"] pub fn strnicmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; #[link_name = "_memccpy"] pub fn memccpy(dest: *mut c_void, src: *const c_void, c: c_int, count: size_t) -> *mut c_void; } libc/src/windows/gnu/0000775000175000017500000000000015105742312014367 5ustar bdrungbdrunglibc/src/windows/gnu/mod.rs0000644000175000017500000000225015105742312015511 0ustar bdrungbdrunguse crate::prelude::*; cfg_if! { if #[cfg(target_pointer_width = "64")] { s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } } } else if #[cfg(target_pointer_width = "32")] { s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [i64; 6], } } } } pub const L_tmpnam: c_uint = 14; pub const TMP_MAX: c_uint = 0x7fff; // stdio file descriptor numbers pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; extern "C" { pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; // NOTE: For MSVC target, `wmemchr` is only a inline function in `` // header file. We cannot find a way to link to that symbol from Rust. pub fn wmemchr(cx: *const crate::wchar_t, c: crate::wchar_t, n: size_t) -> *mut crate::wchar_t; } libc/src/vxworks/0000775000175000017500000000000015105742312013627 5ustar bdrungbdrunglibc/src/vxworks/mod.rs0000644000175000017500000017732115105742312014765 0ustar bdrungbdrung//! Interface to VxWorks C library use core::mem::size_of; use core::ptr::null_mut; use crate::prelude::*; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} impl Copy for DIR {} impl Clone for DIR { fn clone(&self) -> DIR { *self } } pub type intmax_t = i64; pub type uintmax_t = u64; pub type uintptr_t = usize; pub type intptr_t = isize; pub type ptrdiff_t = isize; pub type size_t = crate::uintptr_t; pub type ssize_t = intptr_t; pub type pid_t = c_int; pub type in_addr_t = u32; pub type sighandler_t = size_t; pub type cpuset_t = u32; pub type blkcnt_t = c_long; pub type blksize_t = c_long; pub type ino_t = c_ulong; pub type rlim_t = c_ulong; pub type suseconds_t = c_long; pub type time_t = c_longlong; pub type errno_t = c_int; pub type useconds_t = c_ulong; pub type socklen_t = c_uint; pub type pthread_t = c_ulong; pub type clockid_t = c_int; //defined for the structs pub type dev_t = c_ulong; pub type mode_t = c_int; pub type nlink_t = c_ulong; pub type uid_t = c_ushort; pub type gid_t = c_ushort; pub type sigset_t = c_ulonglong; pub type key_t = c_long; pub type nfds_t = c_uint; pub type stat64 = crate::stat; pub type pthread_key_t = c_ulong; // From b_off_t.h pub type off_t = c_longlong; pub type off64_t = off_t; // From b_BOOL.h pub type BOOL = c_int; // From vxWind.h .. pub type _Vx_OBJ_HANDLE = c_int; pub type _Vx_TASK_ID = crate::_Vx_OBJ_HANDLE; pub type _Vx_MSG_Q_ID = crate::_Vx_OBJ_HANDLE; pub type _Vx_SEM_ID_KERNEL = crate::_Vx_OBJ_HANDLE; pub type _Vx_RTP_ID = crate::_Vx_OBJ_HANDLE; pub type _Vx_SD_ID = crate::_Vx_OBJ_HANDLE; pub type _Vx_CONDVAR_ID = crate::_Vx_OBJ_HANDLE; pub type _Vx_SEM_ID = *mut crate::_Vx_semaphore; pub type OBJ_HANDLE = crate::_Vx_OBJ_HANDLE; pub type TASK_ID = crate::OBJ_HANDLE; pub type MSG_Q_ID = crate::OBJ_HANDLE; pub type SEM_ID_KERNEL = crate::OBJ_HANDLE; pub type RTP_ID = crate::OBJ_HANDLE; pub type SD_ID = crate::OBJ_HANDLE; pub type CONDVAR_ID = crate::OBJ_HANDLE; pub type STATUS = crate::OBJ_HANDLE; // From vxTypes.h pub type _Vx_usr_arg_t = isize; pub type _Vx_exit_code_t = isize; pub type _Vx_ticks_t = c_uint; pub type _Vx_ticks64_t = c_ulonglong; pub type sa_family_t = c_uchar; // mqueue.h pub type mqd_t = c_int; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum _Vx_semaphore {} impl Copy for _Vx_semaphore {} impl Clone for _Vx_semaphore { fn clone(&self) -> _Vx_semaphore { *self } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { self.si_addr } pub unsafe fn si_value(&self) -> crate::sigval { self.si_value } pub unsafe fn si_pid(&self) -> crate::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> c_int { self.si_status } } s! { // b_pthread_condattr_t.h pub struct pthread_condattr_t { pub condAttrStatus: c_int, pub condAttrPshared: c_int, pub condAttrClockId: crate::clockid_t, } // b_pthread_cond_t.h pub struct pthread_cond_t { pub condSemId: crate::_Vx_SEM_ID, pub condValid: c_int, pub condInitted: c_int, pub condRefCount: c_int, pub condMutex: *mut crate::pthread_mutex_t, pub condAttr: crate::pthread_condattr_t, pub condSemName: [c_char; _PTHREAD_SHARED_SEM_NAME_MAX], } // b_pthread_rwlockattr_t.h pub struct pthread_rwlockattr_t { pub rwlockAttrStatus: c_int, pub rwlockAttrPshared: c_int, pub rwlockAttrMaxReaders: c_uint, pub rwlockAttrConformOpt: c_uint, } // b_pthread_rwlock_t.h pub struct pthread_rwlock_t { pub rwlockSemId: crate::_Vx_SEM_ID, pub rwlockReadersRefCount: c_uint, pub rwlockValid: c_int, pub rwlockInitted: c_int, pub rwlockAttr: crate::pthread_rwlockattr_t, pub rwlockSemName: [c_char; _PTHREAD_SHARED_SEM_NAME_MAX], } // b_struct_timeval.h pub struct timeval { pub tv_sec: crate::time_t, pub tv_usec: crate::suseconds_t, } // socket.h pub struct linger { pub l_onoff: c_int, pub l_linger: c_int, } pub struct sockaddr { pub sa_len: c_uchar, pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } // poll.h pub struct pollfd { pub fd: c_int, pub events: c_short, pub revents: c_short, } // resource.h pub struct rlimit { pub rlim_cur: crate::rlim_t, pub rlim_max: crate::rlim_t, } // stat.h pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atime: crate::time_t, pub st_mtime: crate::time_t, pub st_ctime: crate::time_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_attrib: c_uchar, pub st_reserved1: c_int, pub st_reserved2: c_int, pub st_reserved3: c_int, pub st_reserved4: c_int, } //b_struct__Timespec.h pub struct _Timespec { pub tv_sec: crate::time_t, pub tv_nsec: c_long, } // b_struct__Sched_param.h pub struct sched_param { pub sched_priority: c_int, /* scheduling priority */ pub sched_ss_low_priority: c_int, /* low scheduling priority */ pub sched_ss_repl_period: crate::_Timespec, /* replenishment period */ pub sched_ss_init_budget: crate::_Timespec, /* initial budget */ pub sched_ss_max_repl: c_int, /* max pending replenishment */ } // b_pthread_attr_t.h pub struct pthread_attr_t { pub threadAttrStatus: c_int, pub threadAttrStacksize: size_t, pub threadAttrStackaddr: *mut c_void, pub threadAttrGuardsize: size_t, pub threadAttrDetachstate: c_int, pub threadAttrContentionscope: c_int, pub threadAttrInheritsched: c_int, pub threadAttrSchedpolicy: c_int, pub threadAttrName: *mut c_char, pub threadAttrOptions: c_int, pub threadAttrSchedparam: crate::sched_param, } // signal.h pub struct sigaction { pub sa_u: crate::sa_u_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, } // b_stack_t.h pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } // signal.h pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_value: crate::sigval, pub si_errno: c_int, pub si_status: c_int, pub si_addr: *mut c_void, pub si_uid: crate::uid_t, pub si_pid: crate::pid_t, } // pthread.h (krnl) // b_pthread_mutexattr_t.h (usr) pub struct pthread_mutexattr_t { mutexAttrStatus: c_int, mutexAttrPshared: c_int, mutexAttrProtocol: c_int, mutexAttrPrioceiling: c_int, mutexAttrType: c_int, } // pthread.h (krnl) // b_pthread_mutex_t.h (usr) pub struct pthread_mutex_t { pub mutexSemId: crate::_Vx_SEM_ID, /*_Vx_SEM_ID ..*/ pub mutexValid: c_int, pub mutexInitted: c_int, pub mutexCondRefCount: c_int, pub mutexSavPriority: c_int, pub mutexAttr: crate::pthread_mutexattr_t, pub mutexSemName: [c_char; _PTHREAD_SHARED_SEM_NAME_MAX], } // b_struct_timespec.h pub struct timespec { pub tv_sec: crate::time_t, pub tv_nsec: c_long, } // time.h pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, } // in.h pub struct in_addr { pub s_addr: in_addr_t, } // in.h pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } // in6.h #[repr(align(4))] pub struct in6_addr { pub s6_addr: [u8; 16], } // in6.h pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } // netdb.h pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: size_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut crate::addrinfo, } // in.h pub struct sockaddr_in { pub sin_len: u8, pub sin_family: u8, pub sin_port: u16, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } // in6.h pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: u8, pub sin6_port: u16, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct mq_attr { pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_flags: c_long, pub mq_curmsgs: c_long, } } s_no_extra_traits! { // dirent.h pub struct dirent { pub d_ino: crate::ino_t, pub d_name: [c_char; _PARM_NAME_MAX as usize + 1], pub d_type: c_uchar, } pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char; 104], } // rtpLibCommon.h pub struct RTP_DESC { pub status: c_int, pub options: u32, pub entrAddr: *mut c_void, pub initTaskId: crate::TASK_ID, pub parentId: crate::RTP_ID, pub pathName: [c_char; VX_RTP_NAME_LENGTH as usize + 1], pub taskCnt: c_int, pub textStart: *mut c_void, pub textEnd: *mut c_void, } // socket.h pub struct sockaddr_storage { pub ss_len: c_uchar, pub ss_family: crate::sa_family_t, pub __ss_pad1: [c_char; _SS_PAD1SIZE], pub __ss_align: i32, pub __ss_pad2: [c_char; _SS_PAD2SIZE], } pub union sa_u_t { pub sa_handler: Option !>, pub sa_sigaction: Option !>, } pub union sigval { pub sival_int: c_int, pub sival_ptr: *mut c_void, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_name", &&self.d_name[..]) .field("d_type", &self.d_type) .finish() } } impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_len", &self.sun_len) .field("sun_family", &self.sun_family) .field("sun_path", &&self.sun_path[..]) .finish() } } impl fmt::Debug for RTP_DESC { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("RTP_DESC") .field("status", &self.status) .field("options", &self.options) .field("entrAddr", &self.entrAddr) .field("initTaskId", &self.initTaskId) .field("parentId", &self.parentId) .field("pathName", &&self.pathName[..]) .field("taskCnt", &self.taskCnt) .field("textStart", &self.textStart) .field("textEnd", &self.textEnd) .finish() } } impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &&self.__ss_pad1[..]) .field("__ss_align", &self.__ss_align) .field("__ss_pad2", &&self.__ss_pad2[..]) .finish() } } impl PartialEq for sa_u_t { fn eq(&self, other: &sa_u_t) -> bool { unsafe { let h1 = match self.sa_handler { Some(handler) => handler as usize, None => 0 as usize, }; let h2 = match other.sa_handler { Some(handler) => handler as usize, None => 0 as usize, }; h1 == h2 } } } impl Eq for sa_u_t {} impl hash::Hash for sa_u_t { fn hash(&self, state: &mut H) { unsafe { let h = match self.sa_handler { Some(handler) => handler as usize, None => 0 as usize, }; h.hash(state) } } } impl PartialEq for sigval { fn eq(&self, other: &sigval) -> bool { unsafe { self.sival_ptr as usize == other.sival_ptr as usize } } } impl Eq for sigval {} impl hash::Hash for sigval { fn hash(&self, state: &mut H) { unsafe { (self.sival_ptr as usize).hash(state) }; } } } } pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const EXIT_SUCCESS: c_int = 0; pub const EXIT_FAILURE: c_int = 1; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; // FIXME(vxworks): This is not defined in vxWorks, but we have to define it here // to make the building pass for getrandom and std pub const RTLD_DEFAULT: *mut c_void = 0i64 as *mut c_void; //Clock Lib Stuff pub const CLOCK_REALTIME: c_int = 0x0; pub const CLOCK_MONOTONIC: c_int = 0x1; pub const CLOCK_PROCESS_CPUTIME_ID: c_int = 0x2; pub const CLOCK_THREAD_CPUTIME_ID: c_int = 0x3; pub const TIMER_ABSTIME: c_int = 0x1; pub const TIMER_RELTIME: c_int = 0x0; // PTHREAD STUFF pub const PTHREAD_INITIALIZED_OBJ: c_int = 0xF70990EF; pub const PTHREAD_DESTROYED_OBJ: c_int = -1; pub const PTHREAD_VALID_OBJ: c_int = 0xEC542A37; pub const PTHREAD_INVALID_OBJ: c_int = -1; pub const PTHREAD_UNUSED_YET_OBJ: c_int = -1; pub const PTHREAD_PRIO_NONE: c_int = 0; pub const PTHREAD_PRIO_INHERIT: c_int = 1; pub const PTHREAD_PRIO_PROTECT: c_int = 2; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_STACK_MIN: usize = 4096; pub const _PTHREAD_SHARED_SEM_NAME_MAX: usize = 30; //sched.h pub const SCHED_FIFO: c_int = 0x01; pub const SCHED_RR: c_int = 0x02; pub const SCHED_OTHER: c_int = 0x04; pub const SCHED_SPORADIC: c_int = 0x08; pub const PRIO_PROCESS: c_uint = 0; pub const SCHED_FIFO_HIGH_PRI: c_int = 255; pub const SCHED_FIFO_LOW_PRI: c_int = 0; pub const SCHED_RR_HIGH_PRI: c_int = 255; pub const SCHED_RR_LOW_PRI: c_int = 0; pub const SCHED_SPORADIC_HIGH_PRI: c_int = 255; pub const SCHED_SPORADIC_LOW_PRI: c_int = 0; // ERRNO STUFF pub const ERROR: c_int = -1; pub const OK: c_int = 0; pub const EPERM: c_int = 1; /* Not owner */ pub const ENOENT: c_int = 2; /* No such file or directory */ pub const ESRCH: c_int = 3; /* No such process */ pub const EINTR: c_int = 4; /* Interrupted system call */ pub const EIO: c_int = 5; /* I/O error */ pub const ENXIO: c_int = 6; /* No such device or address */ pub const E2BIG: c_int = 7; /* Arg list too long */ pub const ENOEXEC: c_int = 8; /* Exec format error */ pub const EBADF: c_int = 9; /* Bad file number */ pub const ECHILD: c_int = 10; /* No children */ pub const EAGAIN: c_int = 11; /* No more processes */ pub const ENOMEM: c_int = 12; /* Not enough core */ pub const EACCES: c_int = 13; /* Permission denied */ pub const EFAULT: c_int = 14; pub const ENOTEMPTY: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ENAMETOOLONG: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDEADLK: c_int = 33; pub const ENOLCK: c_int = 34; pub const ENOTSUP: c_int = 35; pub const EMSGSIZE: c_int = 36; pub const EDOM: c_int = 37; pub const ERANGE: c_int = 38; pub const EDOOM: c_int = 39; pub const EDESTADDRREQ: c_int = 40; pub const EPROTOTYPE: c_int = 41; pub const ENOPROTOOPT: c_int = 42; pub const EPROTONOSUPPORT: c_int = 43; pub const ESOCKTNOSUPPORT: c_int = 44; pub const EOPNOTSUPP: c_int = 45; pub const EPFNOSUPPORT: c_int = 46; pub const EAFNOSUPPORT: c_int = 47; pub const EADDRINUSE: c_int = 48; pub const EADDRNOTAVAIL: c_int = 49; pub const ENOTSOCK: c_int = 50; pub const ENETUNREACH: c_int = 51; pub const ENETRESET: c_int = 52; pub const ECONNABORTED: c_int = 53; pub const ECONNRESET: c_int = 54; pub const ENOBUFS: c_int = 55; pub const EISCONN: c_int = 56; pub const ENOTCONN: c_int = 57; pub const ESHUTDOWN: c_int = 58; pub const ETOOMANYREFS: c_int = 59; pub const ETIMEDOUT: c_int = 60; pub const ECONNREFUSED: c_int = 61; pub const ENETDOWN: c_int = 62; pub const ETXTBSY: c_int = 63; pub const ELOOP: c_int = 64; pub const EHOSTUNREACH: c_int = 65; pub const ENOTBLK: c_int = 66; pub const EHOSTDOWN: c_int = 67; pub const EINPROGRESS: c_int = 68; pub const EALREADY: c_int = 69; pub const EWOULDBLOCK: c_int = 70; pub const ENOSYS: c_int = 71; pub const ECANCELED: c_int = 72; pub const ENOSR: c_int = 74; pub const ENOSTR: c_int = 75; pub const EPROTO: c_int = 76; pub const EBADMSG: c_int = 77; pub const ENODATA: c_int = 78; pub const ETIME: c_int = 79; pub const ENOMSG: c_int = 80; pub const EFPOS: c_int = 81; pub const EILSEQ: c_int = 82; pub const EDQUOT: c_int = 83; pub const EIDRM: c_int = 84; pub const EOVERFLOW: c_int = 85; pub const EMULTIHOP: c_int = 86; pub const ENOLINK: c_int = 87; pub const ESTALE: c_int = 88; pub const EOWNERDEAD: c_int = 89; pub const ENOTRECOVERABLE: c_int = 90; // NFS errnos: Refer to pkgs_v2/storage/fs/nfs/h/nfs/nfsCommon.h const M_nfsStat: c_int = 48 << 16; enum nfsstat { NFSERR_REMOTE = 71, NFSERR_WFLUSH = 99, NFSERR_BADHANDLE = 10001, NFSERR_NOT_SYNC = 10002, NFSERR_BAD_COOKIE = 10003, NFSERR_TOOSMALL = 10005, NFSERR_BADTYPE = 10007, NFSERR_JUKEBOX = 10008, } pub const S_nfsLib_NFS_OK: c_int = OK; pub const S_nfsLib_NFSERR_PERM: c_int = EPERM; pub const S_nfsLib_NFSERR_NOENT: c_int = ENOENT; pub const S_nfsLib_NFSERR_IO: c_int = EIO; pub const S_nfsLib_NFSERR_NXIO: c_int = ENXIO; pub const S_nfsLib_NFSERR_ACCESS: c_int = EACCES; pub const S_nfsLib_NFSERR_EXIST: c_int = EEXIST; pub const S_nfsLib_NFSERR_ENODEV: c_int = ENODEV; pub const S_nfsLib_NFSERR_NOTDIR: c_int = ENOTDIR; pub const S_nfsLib_NFSERR_ISDIR: c_int = EISDIR; pub const S_nfsLib_NFSERR_INVAL: c_int = EINVAL; pub const S_nfsLib_NFSERR_FBIG: c_int = EFBIG; pub const S_nfsLib_NFSERR_NOSPC: c_int = ENOSPC; pub const S_nfsLib_NFSERR_ROFS: c_int = EROFS; pub const S_nfsLib_NFSERR_NAMETOOLONG: c_int = ENAMETOOLONG; pub const S_nfsLib_NFSERR_NOTEMPTY: c_int = ENOTEMPTY; pub const S_nfsLib_NFSERR_DQUOT: c_int = EDQUOT; pub const S_nfsLib_NFSERR_STALE: c_int = ESTALE; pub const S_nfsLib_NFSERR_WFLUSH: c_int = M_nfsStat | nfsstat::NFSERR_WFLUSH as c_int; pub const S_nfsLib_NFSERR_REMOTE: c_int = M_nfsStat | nfsstat::NFSERR_REMOTE as c_int; pub const S_nfsLib_NFSERR_BADHANDLE: c_int = M_nfsStat | nfsstat::NFSERR_BADHANDLE as c_int; pub const S_nfsLib_NFSERR_NOT_SYNC: c_int = M_nfsStat | nfsstat::NFSERR_NOT_SYNC as c_int; pub const S_nfsLib_NFSERR_BAD_COOKIE: c_int = M_nfsStat | nfsstat::NFSERR_BAD_COOKIE as c_int; pub const S_nfsLib_NFSERR_NOTSUPP: c_int = EOPNOTSUPP; pub const S_nfsLib_NFSERR_TOOSMALL: c_int = M_nfsStat | nfsstat::NFSERR_TOOSMALL as c_int; pub const S_nfsLib_NFSERR_SERVERFAULT: c_int = EIO; pub const S_nfsLib_NFSERR_BADTYPE: c_int = M_nfsStat | nfsstat::NFSERR_BADTYPE as c_int; pub const S_nfsLib_NFSERR_JUKEBOX: c_int = M_nfsStat | nfsstat::NFSERR_JUKEBOX as c_int; // internal offset values for below constants const taskErrorBase: c_int = 0x00030000; const semErrorBase: c_int = 0x00160000; const objErrorBase: c_int = 0x003d0000; // taskLibCommon.h pub const S_taskLib_NAME_NOT_FOUND: c_int = taskErrorBase + 0x0065; pub const S_taskLib_TASK_HOOK_TABLE_FULL: c_int = taskErrorBase + 0x0066; pub const S_taskLib_TASK_HOOK_NOT_FOUND: c_int = taskErrorBase + 0x0067; pub const S_taskLib_ILLEGAL_PRIORITY: c_int = taskErrorBase + 0x0068; // FIXME(vxworks): could also be useful for TASK_DESC type pub const VX_TASK_NAME_LENGTH: c_int = 31; // semLibCommon.h pub const S_semLib_INVALID_STATE: c_int = semErrorBase + 0x0065; pub const S_semLib_INVALID_OPTION: c_int = semErrorBase + 0x0066; pub const S_semLib_INVALID_QUEUE_TYPE: c_int = semErrorBase + 0x0067; pub const S_semLib_INVALID_OPERATION: c_int = semErrorBase + 0x0068; // objLibCommon.h pub const S_objLib_OBJ_ID_ERROR: c_int = objErrorBase + 0x0001; pub const S_objLib_OBJ_UNAVAILABLE: c_int = objErrorBase + 0x0002; pub const S_objLib_OBJ_DELETED: c_int = objErrorBase + 0x0003; pub const S_objLib_OBJ_TIMEOUT: c_int = objErrorBase + 0x0004; pub const S_objLib_OBJ_NO_METHOD: c_int = objErrorBase + 0x0005; // in.h pub const IPPROTO_IP: c_int = 0; pub const IPPROTO_IPV6: c_int = 41; pub const IP_TTL: c_int = 4; pub const IP_MULTICAST_IF: c_int = 9; pub const IP_MULTICAST_TTL: c_int = 10; pub const IP_MULTICAST_LOOP: c_int = 11; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; // in6.h pub const IPV6_V6ONLY: c_int = 1; pub const IPV6_UNICAST_HOPS: c_int = 4; pub const IPV6_MULTICAST_IF: c_int = 9; pub const IPV6_MULTICAST_HOPS: c_int = 10; pub const IPV6_MULTICAST_LOOP: c_int = 11; pub const IPV6_ADD_MEMBERSHIP: c_int = 12; pub const IPV6_DROP_MEMBERSHIP: c_int = 13; // STAT Stuff pub const S_IFMT: c_int = 0o17_0000; pub const S_IFIFO: c_int = 0o1_0000; pub const S_IFCHR: c_int = 0o2_0000; pub const S_IFDIR: c_int = 0o4_0000; pub const S_IFBLK: c_int = 0o6_0000; pub const S_IFREG: c_int = 0o10_0000; pub const S_IFLNK: c_int = 0o12_0000; pub const S_IFSHM: c_int = 0o13_0000; pub const S_IFSOCK: c_int = 0o14_0000; pub const S_ISUID: c_int = 0o4000; pub const S_ISGID: c_int = 0o2000; pub const S_ISTXT: c_int = 0o1000; pub const S_ISVTX: c_int = 0o1000; pub const S_IRUSR: c_int = 0o0400; pub const S_IWUSR: c_int = 0o0200; pub const S_IXUSR: c_int = 0o0100; pub const S_IRWXU: c_int = 0o0700; pub const S_IRGRP: c_int = 0o0040; pub const S_IWGRP: c_int = 0o0020; pub const S_IXGRP: c_int = 0o0010; pub const S_IRWXG: c_int = 0o0070; pub const S_IROTH: c_int = 0o0004; pub const S_IWOTH: c_int = 0o0002; pub const S_IXOTH: c_int = 0o0001; pub const S_IRWXO: c_int = 0o0007; // socket.h pub const SOL_SOCKET: c_int = 0xffff; pub const SOMAXCONN: c_int = 128; pub const SO_DEBUG: c_int = 0x0001; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_RCVLOWAT: c_int = 0x0012; pub const SO_SNDLOWAT: c_int = 0x0013; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_ACCEPTCONN: c_int = 0x001e; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_USELOOPBACK: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_VLAN: c_int = 0x8000; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; pub const SO_TYPE: c_int = 0x1008; pub const SO_BINDTODEVICE: c_int = 0x1010; pub const SO_OOBINLINE: c_int = 0x1011; pub const SO_CONNTIMEO: c_int = 0x100a; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_SEQPACKET: c_int = 5; pub const SOCK_PACKET: c_int = 10; pub const _SS_MAXSIZE: usize = 128; pub const _SS_ALIGNSIZE: usize = size_of::(); pub const _SS_PAD1SIZE: usize = _SS_ALIGNSIZE - size_of::() - size_of::(); pub const _SS_PAD2SIZE: usize = _SS_MAXSIZE - size_of::() - size_of::() - _SS_PAD1SIZE - _SS_ALIGNSIZE; pub const MSG_OOB: c_int = 0x0001; pub const MSG_PEEK: c_int = 0x0002; pub const MSG_DONTROUTE: c_int = 0x0004; pub const MSG_EOR: c_int = 0x0008; pub const MSG_TRUNC: c_int = 0x0010; pub const MSG_CTRUNC: c_int = 0x0020; pub const MSG_WAITALL: c_int = 0x0040; pub const MSG_DONTWAIT: c_int = 0x0080; pub const MSG_EOF: c_int = 0x0100; pub const MSG_EXP: c_int = 0x0200; pub const MSG_MBUF: c_int = 0x0400; pub const MSG_NOTIFICATION: c_int = 0x0800; pub const MSG_COMPAT: c_int = 0x8000; pub const AF_UNSPEC: c_int = 0; pub const AF_LOCAL: c_int = 1; pub const AF_UNIX: c_int = AF_LOCAL; pub const AF_INET: c_int = 2; pub const AF_NETLINK: c_int = 16; pub const AF_ROUTE: c_int = 17; pub const AF_LINK: c_int = 18; pub const AF_PACKET: c_int = 19; pub const pseudo_AF_KEY: c_int = 27; pub const AF_KEY: c_int = pseudo_AF_KEY; pub const AF_INET6: c_int = 28; pub const AF_SOCKDEV: c_int = 31; pub const AF_TIPC: c_int = 33; pub const AF_MIPC: c_int = 34; pub const AF_MIPC_SAFE: c_int = 35; pub const AF_MAX: c_int = 37; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const IPPROTO_TCP: c_int = 6; pub const TCP_NODELAY: c_int = 1; pub const TCP_MAXSEG: c_int = 2; pub const TCP_NOPUSH: c_int = 3; pub const TCP_KEEPIDLE: c_int = 4; pub const TCP_KEEPINTVL: c_int = 5; pub const TCP_KEEPCNT: c_int = 6; // ioLib.h pub const FIONREAD: c_int = 0x40040001; pub const FIOFLUSH: c_int = 2; pub const FIOOPTIONS: c_int = 3; pub const FIOBAUDRATE: c_int = 4; pub const FIODISKFORMAT: c_int = 5; pub const FIODISKINIT: c_int = 6; pub const FIOSEEK: c_int = 7; pub const FIOWHERE: c_int = 8; pub const FIODIRENTRY: c_int = 9; pub const FIORENAME: c_int = 10; pub const FIOREADYCHANGE: c_int = 11; pub const FIODISKCHANGE: c_int = 13; pub const FIOCANCEL: c_int = 14; pub const FIOSQUEEZE: c_int = 15; pub const FIOGETNAME: c_int = 18; pub const FIONBIO: c_int = 0x90040010; // limits.h pub const PATH_MAX: c_int = _PARM_PATH_MAX; pub const _POSIX_PATH_MAX: c_int = 256; // Some poll stuff pub const POLLIN: c_short = 0x0001; pub const POLLPRI: c_short = 0x0002; pub const POLLOUT: c_short = 0x0004; pub const POLLRDNORM: c_short = 0x0040; pub const POLLWRNORM: c_short = POLLOUT; pub const POLLRDBAND: c_short = 0x0080; pub const POLLWRBAND: c_short = 0x0100; pub const POLLERR: c_short = 0x0008; pub const POLLHUP: c_short = 0x0010; pub const POLLNVAL: c_short = 0x0020; // fnctlcom.h pub const FD_CLOEXEC: c_int = 1; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const F_GETOWN: c_int = 5; pub const F_SETOWN: c_int = 6; pub const F_GETLK: c_int = 7; pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; pub const F_DUPFD_CLOEXEC: c_int = 14; // signal.h pub const SIG_DFL: sighandler_t = 0 as sighandler_t; pub const SIG_IGN: sighandler_t = 1 as sighandler_t; pub const SIG_ERR: sighandler_t = -1 as isize as sighandler_t; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGBUS: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGFMT: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGCNCL: c_int = 16; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGCONT: c_int = 19; pub const SIGCHLD: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGPOLL: c_int = 32; pub const SIGPROF: c_int = 33; pub const SIGSYS: c_int = 34; pub const SIGURG: c_int = 35; pub const SIGVTALRM: c_int = 36; pub const SIGXCPU: c_int = 37; pub const SIGXFSZ: c_int = 38; pub const SIGRTMIN: c_int = 48; pub const SIGIO: c_int = SIGRTMIN; pub const SIGWINCH: c_int = SIGRTMIN + 5; pub const SIGLOST: c_int = SIGRTMIN + 6; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const SIG_SETMASK: c_int = 3; pub const SA_NOCLDSTOP: c_int = 0x0001; pub const SA_SIGINFO: c_int = 0x0002; pub const SA_ONSTACK: c_int = 0x0004; pub const SA_INTERRUPT: c_int = 0x0008; pub const SA_RESETHAND: c_int = 0x0010; pub const SA_RESTART: c_int = 0x0020; pub const SA_NODEFER: c_int = 0x0040; pub const SA_NOCLDWAIT: c_int = 0x0080; pub const SI_SYNC: c_int = 0; pub const SI_USER: c_int = -1; pub const SI_QUEUE: c_int = -2; pub const SI_TIMER: c_int = -3; pub const SI_ASYNCIO: c_int = -4; pub const SI_MESGQ: c_int = -5; pub const SI_CHILD: c_int = -6; pub const SI_KILL: c_int = SI_USER; // vxParams.h definitions pub const _PARM_NAME_MAX: c_int = 255; pub const _PARM_PATH_MAX: c_int = 1024; // WAIT STUFF pub const WNOHANG: c_int = 0x01; pub const WUNTRACED: c_int = 0x02; const PTHREAD_MUTEXATTR_INITIALIZER: pthread_mutexattr_t = pthread_mutexattr_t { mutexAttrStatus: PTHREAD_INITIALIZED_OBJ, mutexAttrProtocol: PTHREAD_PRIO_NONE, mutexAttrPrioceiling: 0, mutexAttrType: PTHREAD_MUTEX_DEFAULT, mutexAttrPshared: 1, }; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { mutexSemId: null_mut(), mutexValid: PTHREAD_VALID_OBJ, mutexInitted: PTHREAD_UNUSED_YET_OBJ, mutexCondRefCount: 0, mutexSavPriority: -1, mutexAttr: PTHREAD_MUTEXATTR_INITIALIZER, mutexSemName: [0; _PTHREAD_SHARED_SEM_NAME_MAX], }; const PTHREAD_CONDATTR_INITIALIZER: pthread_condattr_t = pthread_condattr_t { condAttrStatus: 0xf70990ef, condAttrPshared: 1, condAttrClockId: CLOCK_REALTIME, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { condSemId: null_mut(), condValid: PTHREAD_VALID_OBJ, condInitted: PTHREAD_UNUSED_YET_OBJ, condRefCount: 0, condMutex: null_mut(), condAttr: PTHREAD_CONDATTR_INITIALIZER, condSemName: [0; _PTHREAD_SHARED_SEM_NAME_MAX], }; const PTHREAD_RWLOCKATTR_INITIALIZER: pthread_rwlockattr_t = pthread_rwlockattr_t { rwlockAttrStatus: PTHREAD_INITIALIZED_OBJ, rwlockAttrPshared: 1, rwlockAttrMaxReaders: 0, rwlockAttrConformOpt: 1, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { rwlockSemId: null_mut(), rwlockReadersRefCount: 0, rwlockValid: PTHREAD_VALID_OBJ, rwlockInitted: PTHREAD_UNUSED_YET_OBJ, rwlockAttr: PTHREAD_RWLOCKATTR_INITIALIZER, rwlockSemName: [0; _PTHREAD_SHARED_SEM_NAME_MAX], }; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; // rtpLibCommon.h pub const VX_RTP_NAME_LENGTH: c_int = 255; pub const RTP_ID_ERROR: crate::RTP_ID = -1; // h/public/unistd.h pub const _SC_GETPW_R_SIZE_MAX: c_int = 21; // Via unistd.h pub const _SC_PAGESIZE: c_int = 39; pub const O_ACCMODE: c_int = 3; pub const O_CLOEXEC: c_int = 0x100000; // fcntlcom pub const O_EXCL: c_int = 0x0800; pub const O_CREAT: c_int = 0x0200; pub const O_TRUNC: c_int = 0x0400; pub const O_APPEND: c_int = 0x0008; pub const O_RDWR: c_int = 0x0002; pub const O_WRONLY: c_int = 0x0001; pub const O_RDONLY: c_int = 0; pub const O_NONBLOCK: c_int = 0x4000; // mman.h pub const PROT_NONE: c_int = 0x0000; pub const PROT_READ: c_int = 0x0001; pub const PROT_WRITE: c_int = 0x0002; pub const PROT_EXEC: c_int = 0x0004; pub const MAP_SHARED: c_int = 0x0001; pub const MAP_PRIVATE: c_int = 0x0002; pub const MAP_ANON: c_int = 0x0004; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const MAP_FIXED: c_int = 0x0010; pub const MAP_CONTIG: c_int = 0x0020; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} impl Copy for FILE {} impl Clone for FILE { fn clone(&self) -> FILE { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} // FIXME(vxworks): fill this out with a struct impl Copy for fpos_t {} impl Clone for fpos_t { fn clone(&self) -> fpos_t { *self } } f! { pub {const} fn CMSG_ALIGN(len: usize) -> usize { len + mem::size_of::() - 1 & !(mem::size_of::() - 1) } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { let next = cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize) + CMSG_ALIGN(mem::size_of::()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next <= max { (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize > 0 { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(CMSG_ALIGN(mem::size_of::()) as isize) } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(mem::size_of::())) as c_uint } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { CMSG_ALIGN(mem::size_of::()) as c_uint + length } } extern "C" { pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; pub fn feof(stream: *mut FILE) -> c_int; pub fn ferror(stream: *mut FILE) -> c_int; pub fn perror(s: *const c_char); pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn abort() -> !; pub fn exit(status: c_int) -> !; pub fn atexit(cb: extern "C" fn()) -> c_int; pub fn system(s: *const c_char) -> c_int; pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; } extern "C" { pub fn fprintf(stream: *mut crate::FILE, format: *const c_char, ...) -> c_int; pub fn printf(format: *const c_char, ...) -> c_int; pub fn snprintf(s: *mut c_char, n: size_t, format: *const c_char, ...) -> c_int; pub fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int; pub fn fscanf(stream: *mut crate::FILE, format: *const c_char, ...) -> c_int; pub fn scanf(format: *const c_char, ...) -> c_int; pub fn sscanf(s: *const c_char, format: *const c_char, ...) -> c_int; pub fn getchar_unlocked() -> c_int; pub fn putchar_unlocked(c: c_int) -> c_int; pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut crate::FILE; pub fn fileno(stream: *mut crate::FILE) -> c_int; pub fn creat(path: *const c_char, mode: mode_t) -> c_int; pub fn rewinddir(dirp: *mut crate::DIR); pub fn fchown(fd: c_int, owner: crate::uid_t, group: crate::gid_t) -> c_int; pub fn access(path: *const c_char, amode: c_int) -> c_int; pub fn alarm(seconds: c_uint) -> c_uint; pub fn fchdir(dirfd: c_int) -> c_int; pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int; pub fn fpathconf(filedes: c_int, name: c_int) -> c_long; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int; pub fn getlogin() -> *mut c_char; pub fn getopt(argc: c_int, argv: *const *mut c_char, optstr: *const c_char) -> c_int; pub fn pathconf(path: *const c_char, name: c_int) -> c_long; pub fn pause() -> c_int; pub fn seteuid(uid: uid_t) -> c_int; pub fn setegid(gid: gid_t) -> c_int; pub fn sleep(secs: c_uint) -> c_uint; pub fn ttyname(fd: c_int) -> *mut c_char; pub fn wait(status: *mut c_int) -> pid_t; pub fn umask(mask: mode_t) -> mode_t; pub fn mlock(addr: *const c_void, len: size_t) -> c_int; pub fn mlockall(flags: c_int) -> c_int; pub fn munlock(addr: *const c_void, len: size_t) -> c_int; pub fn munlockall() -> c_int; pub fn mmap( addr: *mut c_void, len: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off_t, ) -> *mut c_void; pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn truncate(path: *const c_char, length: off_t) -> c_int; pub fn shm_open(name: *const c_char, oflag: c_int, mode: crate::mode_t) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn pthread_exit(value: *mut c_void) -> !; pub fn pthread_attr_setdetachstate(attr: *mut crate::pthread_attr_t, state: c_int) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn sigaddset(set: *mut sigset_t, signum: c_int) -> c_int; pub fn sigaction(signum: c_int, act: *const sigaction, oldact: *mut sigaction) -> c_int; pub fn utimes(filename: *const c_char, times: *const crate::timeval) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; #[link_name = "_rtld_dlopen"] pub fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void; #[link_name = "_rtld_dlerror"] pub fn dlerror() -> *mut c_char; #[link_name = "_rtld_dlsym"] pub fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void; #[link_name = "_rtld_dlclose"] pub fn dlclose(handle: *mut c_void) -> c_int; #[link_name = "_rtld_dladdr"] pub fn dladdr(addr: *mut c_void, info: *mut Dl_info) -> c_int; // time.h pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; pub fn mktime(tm: *mut tm) -> time_t; pub fn time(time: *mut time_t) -> time_t; pub fn gmtime(time_p: *const time_t) -> *mut tm; pub fn localtime(time_p: *const time_t) -> *mut tm; pub fn timegm(tm: *mut tm) -> time_t; pub fn difftime(time1: time_t, time0: time_t) -> c_double; pub fn gethostname(name: *mut c_char, len: size_t) -> c_int; pub fn usleep(secs: crate::useconds_t) -> c_int; pub fn putenv(string: *mut c_char) -> c_int; pub fn setlocale(category: c_int, locale: *const c_char) -> *mut c_char; pub fn sigprocmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sigpending(set: *mut sigset_t) -> c_int; pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int; pub fn fseeko(stream: *mut crate::FILE, offset: off_t, whence: c_int) -> c_int; pub fn ftello(stream: *mut crate::FILE) -> off_t; pub fn mkstemp(template: *mut c_char) -> c_int; pub fn tmpnam(ptr: *mut c_char) -> *mut c_char; pub fn openlog(ident: *const c_char, logopt: c_int, facility: c_int); pub fn closelog(); pub fn setlogmask(maskpri: c_int) -> c_int; pub fn syslog(priority: c_int, message: *const c_char, ...); pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; } extern "C" { // stdlib.h pub fn memalign(block_size: size_t, size_arg: size_t) -> *mut c_void; // ioLib.h pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; // ioLib.h pub fn chdir(attr: *const c_char) -> c_int; // pthread.h pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int; // pthread.h pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int; // pthread.h pub fn pthread_mutexattr_settype(pAttr: *mut crate::pthread_mutexattr_t, pType: c_int) -> c_int; // pthread.h pub fn pthread_mutex_init( mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, ) -> c_int; // pthread.h pub fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> c_int; // pthread.h pub fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int; // pthread.h pub fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int; // pthread.h pub fn pthread_mutex_timedlock(attr: *mut pthread_mutex_t, spec: *const timespec) -> c_int; // pthread.h pub fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int; // pthread.h pub fn pthread_attr_setname(pAttr: *mut crate::pthread_attr_t, name: *mut c_char) -> c_int; // pthread.h pub fn pthread_attr_setstacksize(attr: *mut crate::pthread_attr_t, stacksize: size_t) -> c_int; // pthread.h pub fn pthread_attr_getstacksize( attr: *const crate::pthread_attr_t, size: *mut size_t, ) -> c_int; // pthread.h pub fn pthread_attr_init(attr: *mut crate::pthread_attr_t) -> c_int; // pthread.h pub fn pthread_create( pThread: *mut crate::pthread_t, pAttr: *const crate::pthread_attr_t, start_routine: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; //pthread.h pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; //pthread.h pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut crate::sched_param, ) -> c_int; //pthread.h pub fn pthread_attr_setinheritsched( attr: *mut crate::pthread_attr_t, inheritsched: c_int, ) -> c_int; //pthread.h pub fn pthread_attr_setschedpolicy(attr: *mut crate::pthread_attr_t, policy: c_int) -> c_int; // pthread.h pub fn pthread_attr_destroy(thread: *mut crate::pthread_attr_t) -> c_int; // pthread.h pub fn pthread_detach(thread: crate::pthread_t) -> c_int; // int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; // stat.h pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; // stat.h pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; // unistd.h pub fn ftruncate(fd: c_int, length: off_t) -> c_int; // dirent.h pub fn readdir_r( pDir: *mut crate::DIR, entry: *mut crate::dirent, result: *mut *mut crate::dirent, ) -> c_int; // dirent.h pub fn readdir(pDir: *mut crate::DIR) -> *mut crate::dirent; // fcntl.h or // ioLib.h pub fn open(path: *const c_char, oflag: c_int, ...) -> c_int; // poll.h pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int; // pthread.h pub fn pthread_condattr_init(attr: *mut crate::pthread_condattr_t) -> c_int; // pthread.h pub fn pthread_condattr_destroy(attr: *mut crate::pthread_condattr_t) -> c_int; // pthread.h pub fn pthread_condattr_getclock( pAttr: *const crate::pthread_condattr_t, pClockId: *mut crate::clockid_t, ) -> c_int; // pthread.h pub fn pthread_condattr_setclock( pAttr: *mut crate::pthread_condattr_t, clockId: crate::clockid_t, ) -> c_int; // pthread.h pub fn pthread_cond_init( cond: *mut crate::pthread_cond_t, attr: *const crate::pthread_condattr_t, ) -> c_int; // pthread.h pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int; // pthread.h pub fn pthread_cond_signal(cond: *mut crate::pthread_cond_t) -> c_int; // pthread.h pub fn pthread_cond_broadcast(cond: *mut crate::pthread_cond_t) -> c_int; // pthread.h pub fn pthread_cond_wait( cond: *mut crate::pthread_cond_t, mutex: *mut crate::pthread_mutex_t, ) -> c_int; // pthread.h pub fn pthread_rwlockattr_init(attr: *mut crate::pthread_rwlockattr_t) -> c_int; // pthread.h pub fn pthread_rwlockattr_destroy(attr: *mut crate::pthread_rwlockattr_t) -> c_int; // pthread.h pub fn pthread_rwlockattr_setmaxreaders( attr: *mut crate::pthread_rwlockattr_t, attr2: c_uint, ) -> c_int; // pthread.h pub fn pthread_rwlock_init( attr: *mut crate::pthread_rwlock_t, host: *const crate::pthread_rwlockattr_t, ) -> c_int; // pthread.h pub fn pthread_rwlock_destroy(attr: *mut crate::pthread_rwlock_t) -> c_int; // pthread.h pub fn pthread_rwlock_rdlock(attr: *mut crate::pthread_rwlock_t) -> c_int; // pthread.h pub fn pthread_rwlock_tryrdlock(attr: *mut crate::pthread_rwlock_t) -> c_int; // pthread.h pub fn pthread_rwlock_timedrdlock( attr: *mut crate::pthread_rwlock_t, host: *const crate::timespec, ) -> c_int; // pthread.h pub fn pthread_rwlock_wrlock(attr: *mut crate::pthread_rwlock_t) -> c_int; // pthread.h pub fn pthread_rwlock_trywrlock(attr: *mut crate::pthread_rwlock_t) -> c_int; // pthread.h pub fn pthread_rwlock_timedwrlock( attr: *mut crate::pthread_rwlock_t, host: *const crate::timespec, ) -> c_int; // pthread.h pub fn pthread_rwlock_unlock(attr: *mut crate::pthread_rwlock_t) -> c_int; // pthread.h pub fn pthread_key_create( key: *mut crate::pthread_key_t, dtor: Option, ) -> c_int; // pthread.h pub fn pthread_key_delete(key: crate::pthread_key_t) -> c_int; // pthread.h pub fn pthread_setspecific(key: crate::pthread_key_t, value: *const c_void) -> c_int; // pthread.h pub fn pthread_getspecific(key: crate::pthread_key_t) -> *mut c_void; // pthread.h pub fn pthread_cond_timedwait( cond: *mut crate::pthread_cond_t, mutex: *mut crate::pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; // pthread.h pub fn pthread_attr_getname(attr: *mut crate::pthread_attr_t, name: *mut *mut c_char) -> c_int; // pthread.h pub fn pthread_join(thread: crate::pthread_t, status: *mut *mut c_void) -> c_int; // pthread.h pub fn pthread_self() -> crate::pthread_t; // clockLib.h pub fn clock_gettime(clock_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; // clockLib.h pub fn clock_settime(clock_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; // clockLib.h pub fn clock_getres(clock_id: crate::clockid_t, res: *mut crate::timespec) -> c_int; // clockLib.h pub fn clock_nanosleep( clock_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; // timerLib.h pub fn nanosleep(rqtp: *const crate::timespec, rmtp: *mut crate::timespec) -> c_int; // socket.h pub fn accept(s: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t) -> c_int; // socket.h pub fn bind(fd: c_int, addr: *const sockaddr, len: socklen_t) -> c_int; // socket.h pub fn connect(s: c_int, name: *const crate::sockaddr, namelen: crate::socklen_t) -> c_int; // socket.h pub fn getpeername( s: c_int, name: *mut crate::sockaddr, namelen: *mut crate::socklen_t, ) -> c_int; // socket.h pub fn getsockname(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; // socket.h pub fn getsockopt( sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut crate::socklen_t, ) -> c_int; // socket.h pub fn listen(socket: c_int, backlog: c_int) -> c_int; // socket.h pub fn recv(s: c_int, buf: *mut c_void, bufLen: size_t, flags: c_int) -> ssize_t; // socket.h pub fn recvfrom( s: c_int, buf: *mut c_void, bufLen: size_t, flags: c_int, from: *mut crate::sockaddr, pFromLen: *mut crate::socklen_t, ) -> ssize_t; pub fn recvmsg(socket: c_int, mp: *mut crate::msghdr, flags: c_int) -> ssize_t; // socket.h pub fn send(socket: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t; pub fn sendmsg(socket: c_int, mp: *const crate::msghdr, flags: c_int) -> ssize_t; // socket.h pub fn sendto( socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t, ) -> ssize_t; // socket.h pub fn setsockopt( socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t, ) -> c_int; // socket.h pub fn shutdown(s: c_int, how: c_int) -> c_int; // socket.h pub fn socket(domain: c_int, _type: c_int, protocol: c_int) -> c_int; // icotl.h pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int; // fcntl.h pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int; // ntp_rfc2553.h for kernel // netdb.h for user pub fn gai_strerror(errcode: c_int) -> *mut c_char; // ioLib.h or // unistd.h pub fn close(fd: c_int) -> c_int; // ioLib.h or // unistd.h pub fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t; // ioLib.h or // unistd.h pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; // ioLib.h or // unistd.h pub fn isatty(fd: c_int) -> c_int; // ioLib.h or // unistd.h pub fn dup(src: c_int) -> c_int; // ioLib.h or // unistd.h pub fn dup2(src: c_int, dst: c_int) -> c_int; // ioLib.h or // unistd.h pub fn pipe(fds: *mut c_int) -> c_int; // ioLib.h or // unistd.h pub fn unlink(pathname: *const c_char) -> c_int; // unistd.h and // ioLib.h pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t; // netdb.h pub fn getaddrinfo( node: *const c_char, service: *const c_char, hints: *const addrinfo, res: *mut *mut addrinfo, ) -> c_int; // netdb.h pub fn freeaddrinfo(res: *mut addrinfo); // signal.h pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; // unistd.h pub fn getpid() -> pid_t; // unistd.h pub fn getppid() -> pid_t; // wait.h pub fn waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> pid_t; // unistd.h pub fn sysconf(attr: c_int) -> c_long; // stdlib.h pub fn setenv( // setenv.c envVarName: *const c_char, envVarValue: *const c_char, overwrite: c_int, ) -> c_int; // stdlib.h pub fn unsetenv( // setenv.c envVarName: *const c_char, ) -> c_int; // stdlib.h pub fn realpath(fileName: *const c_char, resolvedName: *mut c_char) -> *mut c_char; // unistd.h pub fn link(src: *const c_char, dst: *const c_char) -> c_int; // unistd.h pub fn readlink(path: *const c_char, buf: *mut c_char, bufsize: size_t) -> ssize_t; // unistd.h pub fn symlink(path1: *const c_char, path2: *const c_char) -> c_int; // dirent.h pub fn opendir(name: *const c_char) -> *mut crate::DIR; // unistd.h pub fn rmdir(path: *const c_char) -> c_int; // stat.h pub fn mkdir(dirName: *const c_char, mode: crate::mode_t) -> c_int; // stat.h pub fn chmod(path: *const c_char, mode: crate::mode_t) -> c_int; // stat.h pub fn fchmod(attr1: c_int, attr2: crate::mode_t) -> c_int; // unistd.h pub fn fsync(fd: c_int) -> c_int; // dirent.h pub fn closedir(ptr: *mut crate::DIR) -> c_int; //sched.h pub fn sched_get_priority_max(policy: c_int) -> c_int; //sched.h pub fn sched_get_priority_min(policy: c_int) -> c_int; //sched.h pub fn sched_setparam(pid: crate::pid_t, param: *const crate::sched_param) -> c_int; //sched.h pub fn sched_getparam(pid: crate::pid_t, param: *mut crate::sched_param) -> c_int; //sched.h pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; //sched.h pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; //sched.h pub fn sched_rr_get_interval(pid: crate::pid_t, tp: *mut crate::timespec) -> c_int; // sched.h pub fn sched_yield() -> c_int; // errnoLib.h pub fn errnoSet(err: c_int) -> c_int; // errnoLib.h pub fn errnoGet() -> c_int; // unistd.h pub fn _exit(status: c_int) -> !; // unistd.h pub fn setgid(gid: crate::gid_t) -> c_int; // unistd.h pub fn getgid() -> crate::gid_t; // unistd.h pub fn setuid(uid: crate::uid_t) -> c_int; // unistd.h pub fn getuid() -> crate::uid_t; // signal.h pub fn sigemptyset(__set: *mut sigset_t) -> c_int; // pthread.h for kernel // signal.h for user pub fn pthread_sigmask(__how: c_int, __set: *const sigset_t, __oset: *mut sigset_t) -> c_int; // signal.h for user pub fn kill(__pid: pid_t, __signo: c_int) -> c_int; // signal.h for user pub fn sigqueue(__pid: pid_t, __signo: c_int, __value: crate::sigval) -> c_int; // signal.h for user pub fn _sigqueue( rtpId: crate::RTP_ID, signo: c_int, pValue: *const crate::sigval, sigCode: c_int, ) -> c_int; // signal.h pub fn taskKill(taskId: crate::TASK_ID, signo: c_int) -> c_int; // signal.h pub fn raise(__signo: c_int) -> c_int; // taskLibCommon.h pub fn taskIdSelf() -> crate::TASK_ID; pub fn taskDelay(ticks: crate::_Vx_ticks_t) -> c_int; // taskLib.h pub fn taskNameSet(task_id: crate::TASK_ID, task_name: *mut c_char) -> c_int; pub fn taskNameGet(task_id: crate::TASK_ID, buf_name: *mut c_char, bufsize: size_t) -> c_int; // rtpLibCommon.h pub fn rtpInfoGet(rtpId: crate::RTP_ID, rtpStruct: *mut crate::RTP_DESC) -> c_int; pub fn rtpSpawn( pubrtpFileName: *const c_char, argv: *mut *const c_char, envp: *mut *const c_char, priority: c_int, uStackSize: size_t, options: c_int, taskOptions: c_int, ) -> RTP_ID; // ioLib.h pub fn _realpath(fileName: *const c_char, resolvedName: *mut c_char) -> *mut c_char; // pathLib.h pub fn _pathIsAbsolute(filepath: *const c_char, pNameTail: *mut *const c_char) -> BOOL; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; // randomNumGen.h pub fn randBytes(buf: *mut c_uchar, length: c_int) -> c_int; pub fn randABytes(buf: *mut c_uchar, length: c_int) -> c_int; pub fn randUBytes(buf: *mut c_uchar, length: c_int) -> c_int; pub fn randSecure() -> c_int; // mqueue.h pub fn mq_open(name: *const c_char, oflag: c_int, ...) -> crate::mqd_t; pub fn mq_close(mqd: crate::mqd_t) -> c_int; pub fn mq_unlink(name: *const c_char) -> c_int; pub fn mq_receive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, ) -> ssize_t; pub fn mq_timedreceive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, abs_timeout: *const crate::timespec, ) -> ssize_t; pub fn mq_send( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, ) -> c_int; pub fn mq_timedsend( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, abs_timeout: *const crate::timespec, ) -> c_int; pub fn mq_getattr(mqd: crate::mqd_t, attr: *mut crate::mq_attr) -> c_int; pub fn mq_setattr( mqd: crate::mqd_t, newattr: *const crate::mq_attr, oldattr: *mut crate::mq_attr, ) -> c_int; // vxCpuLib.h pub fn vxCpuEnabledGet() -> crate::cpuset_t; // Get set of running CPU's in the system pub fn vxCpuConfiguredGet() -> crate::cpuset_t; // Get set of Configured CPU's in the system } //Dummy functions, these don't really exist in VxWorks. // wait.h macros safe_f! { pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0xFF00) == 0 } pub {const} fn WIFSIGNALED(status: c_int) -> bool { (status & 0xFF00) != 0 } pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xFF0000) != 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { status & 0xFF } pub {const} fn WTERMSIG(status: c_int) -> c_int { (status >> 8) & 0xFF } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status >> 16) & 0xFF } } pub fn pread(_fd: c_int, _buf: *mut c_void, _count: size_t, _offset: off64_t) -> ssize_t { -1 } pub fn pwrite(_fd: c_int, _buf: *const c_void, _count: size_t, _offset: off64_t) -> ssize_t { -1 } pub fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int { // check to see if align is a power of 2 and if align is a multiple // of sizeof(void *) if (align & align - 1 != 0) || (align as usize % size_of::() != 0) { return crate::EINVAL; } unsafe { // posix_memalign should not set errno let e = crate::errnoGet(); let temp = memalign(align, size); crate::errnoSet(e as c_int); if temp.is_null() { crate::ENOMEM } else { *memptr = temp; 0 } } } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "powerpc64")] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(target_arch = "riscv32")] { mod riscv32; pub use self::riscv32::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } libc/src/vxworks/arm.rs0000644000175000017500000000003015105742312014743 0ustar bdrungbdrungpub type wchar_t = u32; libc/src/vxworks/riscv64.rs0000644000175000017500000000003015105742312015464 0ustar bdrungbdrungpub type wchar_t = i32; libc/src/vxworks/powerpc.rs0000644000175000017500000000003015105742312015643 0ustar bdrungbdrungpub type wchar_t = u32; libc/src/vxworks/riscv32.rs0000644000175000017500000000003015105742312015457 0ustar bdrungbdrungpub type wchar_t = i32; libc/src/vxworks/x86.rs0000644000175000017500000000003015105742312014611 0ustar bdrungbdrungpub type wchar_t = i32; libc/src/vxworks/powerpc64.rs0000644000175000017500000000003015105742312016015 0ustar bdrungbdrungpub type wchar_t = u32; libc/src/vxworks/x86_64.rs0000644000175000017500000000003015105742312015122 0ustar bdrungbdrungpub type wchar_t = i32; libc/src/vxworks/aarch64.rs0000644000175000017500000000003015105742312015414 0ustar bdrungbdrungpub type wchar_t = u32; libc/src/wasi/0000775000175000017500000000000015105742312013047 5ustar bdrungbdrunglibc/src/wasi/mod.rs0000644000175000017500000007727715105742312014216 0ustar bdrungbdrung//! [wasi-libc](https://github.com/WebAssembly/wasi-libc) definitions. //! //! `wasi-libc` project provides multiple libraries including emulated features, but we list only //! basic features with `libc.a` here. use core::iter::Iterator; use crate::prelude::*; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ssize_t = isize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type off_t = i64; pub type pid_t = i32; pub type clock_t = c_longlong; pub type time_t = c_longlong; pub type ino_t = u64; pub type sigset_t = c_uchar; pub type suseconds_t = c_longlong; pub type mode_t = u32; pub type dev_t = u64; pub type uid_t = u32; pub type gid_t = u32; pub type nlink_t = u64; pub type blksize_t = c_long; pub type blkcnt_t = i64; pub type nfds_t = c_ulong; pub type wchar_t = i32; pub type nl_item = c_int; pub type __wasi_rights_t = u64; pub type locale_t = *mut __locale_struct; s_no_extra_traits! { #[repr(align(16))] #[allow(missing_debug_implementations)] pub struct max_align_t { priv_: [f64; 4], } } #[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} #[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} #[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum __locale_struct {} s_paren! { // in wasi-libc clockid_t is const struct __clockid* (where __clockid is an opaque struct), // but that's an implementation detail that we don't want to have to deal with #[repr(transparent)] #[allow(dead_code)] pub struct clockid_t(*const u8); } unsafe impl Send for clockid_t {} unsafe impl Sync for clockid_t {} s! { #[repr(align(8))] pub struct fpos_t { data: [u8; 16], } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub __tm_gmtoff: c_int, pub __tm_zone: *const c_char, pub __tm_nsec: c_int, } pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } pub struct tms { pub tms_utime: clock_t, pub tms_stime: clock_t, pub tms_cutime: clock_t, pub tms_cstime: clock_t, } pub struct itimerspec { pub it_interval: timespec, pub it_value: timespec, } pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct pollfd { pub fd: c_int, pub events: c_short, pub revents: c_short, } pub struct rusage { pub ru_utime: timeval, pub ru_stime: timeval, } pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_nlink: nlink_t, pub st_mode: mode_t, pub st_uid: uid_t, pub st_gid: gid_t, __pad0: c_uint, pub st_rdev: dev_t, pub st_size: off_t, pub st_blksize: blksize_t, pub st_blocks: blkcnt_t, pub st_atim: timespec, pub st_mtim: timespec, pub st_ctim: timespec, __reserved: [c_longlong; 3], } pub struct fd_set { __nfds: usize, __fds: [c_int; FD_SETSIZE as usize], } } // Declare dirent outside of s! so that it doesn't implement Copy, Eq, Hash, // etc., since it contains a flexible array member with a dynamic size. #[repr(C)] #[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct dirent { pub d_ino: ino_t, pub d_type: c_uchar, /// d_name is declared in WASI libc as a flexible array member, which /// can't be directly expressed in Rust. As an imperfect workaround, /// declare it as a zero-length array instead. pub d_name: [c_char; 0], } pub const EXIT_SUCCESS: c_int = 0; pub const EXIT_FAILURE: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const FD_CLOEXEC: c_int = 1; pub const FD_SETSIZE: size_t = 1024; pub const O_APPEND: c_int = 0x0001; pub const O_DSYNC: c_int = 0x0002; pub const O_NONBLOCK: c_int = 0x0004; pub const O_RSYNC: c_int = 0x0008; pub const O_SYNC: c_int = 0x0010; pub const O_CREAT: c_int = 0x0001 << 12; pub const O_DIRECTORY: c_int = 0x0002 << 12; pub const O_EXCL: c_int = 0x0004 << 12; pub const O_TRUNC: c_int = 0x0008 << 12; pub const O_NOFOLLOW: c_int = 0x01000000; pub const O_EXEC: c_int = 0x02000000; pub const O_RDONLY: c_int = 0x04000000; pub const O_SEARCH: c_int = 0x08000000; pub const O_WRONLY: c_int = 0x10000000; pub const O_CLOEXEC: c_int = 0x0; pub const O_RDWR: c_int = O_WRONLY | O_RDONLY; pub const O_ACCMODE: c_int = O_EXEC | O_RDWR | O_SEARCH; pub const O_NOCTTY: c_int = 0x0; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_RANDOM: c_int = 2; pub const POSIX_FADV_SEQUENTIAL: c_int = 1; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const AT_FDCWD: c_int = -2; pub const AT_EACCESS: c_int = 0x0; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x1; pub const AT_SYMLINK_FOLLOW: c_int = 0x2; pub const AT_REMOVEDIR: c_int = 0x4; pub const UTIME_OMIT: c_long = 0xfffffffe; pub const UTIME_NOW: c_long = 0xffffffff; pub const S_IFIFO: mode_t = 0o1_0000; pub const S_IFCHR: mode_t = 0o2_0000; pub const S_IFBLK: mode_t = 0o6_0000; pub const S_IFDIR: mode_t = 0o4_0000; pub const S_IFREG: mode_t = 0o10_0000; pub const S_IFLNK: mode_t = 0o12_0000; pub const S_IFSOCK: mode_t = 0o14_0000; pub const S_IFMT: mode_t = 0o17_0000; pub const S_IRWXO: mode_t = 0o0007; pub const S_IXOTH: mode_t = 0o0001; pub const S_IWOTH: mode_t = 0o0002; pub const S_IROTH: mode_t = 0o0004; pub const S_IRWXG: mode_t = 0o0070; pub const S_IXGRP: mode_t = 0o0010; pub const S_IWGRP: mode_t = 0o0020; pub const S_IRGRP: mode_t = 0o0040; pub const S_IRWXU: mode_t = 0o0700; pub const S_IXUSR: mode_t = 0o0100; pub const S_IWUSR: mode_t = 0o0200; pub const S_IRUSR: mode_t = 0o0400; pub const S_ISVTX: mode_t = 0o1000; pub const S_ISGID: mode_t = 0o2000; pub const S_ISUID: mode_t = 0o4000; pub const DT_UNKNOWN: u8 = 0; pub const DT_BLK: u8 = 1; pub const DT_CHR: u8 = 2; pub const DT_DIR: u8 = 3; pub const DT_REG: u8 = 4; pub const DT_LNK: u8 = 7; pub const FIONREAD: c_int = 1; pub const FIONBIO: c_int = 2; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const POLLIN: c_short = 0x1; pub const POLLOUT: c_short = 0x2; pub const POLLERR: c_short = 0x1000; pub const POLLHUP: c_short = 0x2000; pub const POLLNVAL: c_short = 0x4000; pub const POLLRDNORM: c_short = 0x1; pub const POLLWRNORM: c_short = 0x2; pub const E2BIG: c_int = 1; pub const EACCES: c_int = 2; pub const EADDRINUSE: c_int = 3; pub const EADDRNOTAVAIL: c_int = 4; pub const EAFNOSUPPORT: c_int = 5; pub const EAGAIN: c_int = 6; pub const EALREADY: c_int = 7; pub const EBADF: c_int = 8; pub const EBADMSG: c_int = 9; pub const EBUSY: c_int = 10; pub const ECANCELED: c_int = 11; pub const ECHILD: c_int = 12; pub const ECONNABORTED: c_int = 13; pub const ECONNREFUSED: c_int = 14; pub const ECONNRESET: c_int = 15; pub const EDEADLK: c_int = 16; pub const EDESTADDRREQ: c_int = 17; pub const EDOM: c_int = 18; pub const EDQUOT: c_int = 19; pub const EEXIST: c_int = 20; pub const EFAULT: c_int = 21; pub const EFBIG: c_int = 22; pub const EHOSTUNREACH: c_int = 23; pub const EIDRM: c_int = 24; pub const EILSEQ: c_int = 25; pub const EINPROGRESS: c_int = 26; pub const EINTR: c_int = 27; pub const EINVAL: c_int = 28; pub const EIO: c_int = 29; pub const EISCONN: c_int = 30; pub const EISDIR: c_int = 31; pub const ELOOP: c_int = 32; pub const EMFILE: c_int = 33; pub const EMLINK: c_int = 34; pub const EMSGSIZE: c_int = 35; pub const EMULTIHOP: c_int = 36; pub const ENAMETOOLONG: c_int = 37; pub const ENETDOWN: c_int = 38; pub const ENETRESET: c_int = 39; pub const ENETUNREACH: c_int = 40; pub const ENFILE: c_int = 41; pub const ENOBUFS: c_int = 42; pub const ENODEV: c_int = 43; pub const ENOENT: c_int = 44; pub const ENOEXEC: c_int = 45; pub const ENOLCK: c_int = 46; pub const ENOLINK: c_int = 47; pub const ENOMEM: c_int = 48; pub const ENOMSG: c_int = 49; pub const ENOPROTOOPT: c_int = 50; pub const ENOSPC: c_int = 51; pub const ENOSYS: c_int = 52; pub const ENOTCONN: c_int = 53; pub const ENOTDIR: c_int = 54; pub const ENOTEMPTY: c_int = 55; pub const ENOTRECOVERABLE: c_int = 56; pub const ENOTSOCK: c_int = 57; pub const ENOTSUP: c_int = 58; pub const ENOTTY: c_int = 59; pub const ENXIO: c_int = 60; pub const EOVERFLOW: c_int = 61; pub const EOWNERDEAD: c_int = 62; pub const EPERM: c_int = 63; pub const EPIPE: c_int = 64; pub const EPROTO: c_int = 65; pub const EPROTONOSUPPORT: c_int = 66; pub const EPROTOTYPE: c_int = 67; pub const ERANGE: c_int = 68; pub const EROFS: c_int = 69; pub const ESPIPE: c_int = 70; pub const ESRCH: c_int = 71; pub const ESTALE: c_int = 72; pub const ETIMEDOUT: c_int = 73; pub const ETXTBSY: c_int = 74; pub const EXDEV: c_int = 75; pub const ENOTCAPABLE: c_int = 76; pub const EOPNOTSUPP: c_int = ENOTSUP; pub const EWOULDBLOCK: c_int = EAGAIN; pub const _SC_PAGESIZE: c_int = 30; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_IOV_MAX: c_int = 60; pub const _SC_SYMLOOP_MAX: c_int = 173; cfg_if! { if #[cfg(libc_ctest)] { // skip these constants when this is active because `ctest` currently // panics on parsing the constants below } else { // `addr_of!(EXTERN_STATIC)` is now safe; remove `unsafe` when MSRV >= 1.82 #[allow(unused_unsafe)] pub static CLOCK_MONOTONIC: clockid_t = unsafe { clockid_t(core::ptr::addr_of!(_CLOCK_MONOTONIC)) }; #[allow(unused_unsafe)] pub static CLOCK_PROCESS_CPUTIME_ID: clockid_t = unsafe { clockid_t(core::ptr::addr_of!(_CLOCK_PROCESS_CPUTIME_ID)) }; #[allow(unused_unsafe)] pub static CLOCK_REALTIME: clockid_t = unsafe { clockid_t(core::ptr::addr_of!(_CLOCK_REALTIME)) }; #[allow(unused_unsafe)] pub static CLOCK_THREAD_CPUTIME_ID: clockid_t = unsafe { clockid_t(core::ptr::addr_of!(_CLOCK_THREAD_CPUTIME_ID)) }; } } pub const ABDAY_1: crate::nl_item = 0x20000; pub const ABDAY_2: crate::nl_item = 0x20001; pub const ABDAY_3: crate::nl_item = 0x20002; pub const ABDAY_4: crate::nl_item = 0x20003; pub const ABDAY_5: crate::nl_item = 0x20004; pub const ABDAY_6: crate::nl_item = 0x20005; pub const ABDAY_7: crate::nl_item = 0x20006; pub const DAY_1: crate::nl_item = 0x20007; pub const DAY_2: crate::nl_item = 0x20008; pub const DAY_3: crate::nl_item = 0x20009; pub const DAY_4: crate::nl_item = 0x2000A; pub const DAY_5: crate::nl_item = 0x2000B; pub const DAY_6: crate::nl_item = 0x2000C; pub const DAY_7: crate::nl_item = 0x2000D; pub const ABMON_1: crate::nl_item = 0x2000E; pub const ABMON_2: crate::nl_item = 0x2000F; pub const ABMON_3: crate::nl_item = 0x20010; pub const ABMON_4: crate::nl_item = 0x20011; pub const ABMON_5: crate::nl_item = 0x20012; pub const ABMON_6: crate::nl_item = 0x20013; pub const ABMON_7: crate::nl_item = 0x20014; pub const ABMON_8: crate::nl_item = 0x20015; pub const ABMON_9: crate::nl_item = 0x20016; pub const ABMON_10: crate::nl_item = 0x20017; pub const ABMON_11: crate::nl_item = 0x20018; pub const ABMON_12: crate::nl_item = 0x20019; pub const MON_1: crate::nl_item = 0x2001A; pub const MON_2: crate::nl_item = 0x2001B; pub const MON_3: crate::nl_item = 0x2001C; pub const MON_4: crate::nl_item = 0x2001D; pub const MON_5: crate::nl_item = 0x2001E; pub const MON_6: crate::nl_item = 0x2001F; pub const MON_7: crate::nl_item = 0x20020; pub const MON_8: crate::nl_item = 0x20021; pub const MON_9: crate::nl_item = 0x20022; pub const MON_10: crate::nl_item = 0x20023; pub const MON_11: crate::nl_item = 0x20024; pub const MON_12: crate::nl_item = 0x20025; pub const AM_STR: crate::nl_item = 0x20026; pub const PM_STR: crate::nl_item = 0x20027; pub const D_T_FMT: crate::nl_item = 0x20028; pub const D_FMT: crate::nl_item = 0x20029; pub const T_FMT: crate::nl_item = 0x2002A; pub const T_FMT_AMPM: crate::nl_item = 0x2002B; pub const ERA: crate::nl_item = 0x2002C; pub const ERA_D_FMT: crate::nl_item = 0x2002E; pub const ALT_DIGITS: crate::nl_item = 0x2002F; pub const ERA_D_T_FMT: crate::nl_item = 0x20030; pub const ERA_T_FMT: crate::nl_item = 0x20031; pub const CODESET: crate::nl_item = 14; pub const CRNCYSTR: crate::nl_item = 0x4000F; pub const RADIXCHAR: crate::nl_item = 0x10000; pub const THOUSEP: crate::nl_item = 0x10001; pub const YESEXPR: crate::nl_item = 0x50000; pub const NOEXPR: crate::nl_item = 0x50001; pub const YESSTR: crate::nl_item = 0x50002; pub const NOSTR: crate::nl_item = 0x50003; f! { pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let set = &*set; let n = set.__nfds; return set.__fds[..n].iter().any(|p| *p == fd); } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let set = &mut *set; let n = set.__nfds; if !set.__fds[..n].iter().any(|p| *p == fd) { set.__nfds = n + 1; set.__fds[n] = fd; } } pub fn FD_ZERO(set: *mut fd_set) -> () { (*set).__nfds = 0; return; } } #[cfg_attr( feature = "rustc-dep-of-std", link( name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") ) )] #[cfg_attr( feature = "rustc-dep-of-std", link(name = "c", cfg(not(target_feature = "crt-static"))) )] extern "C" { pub fn _Exit(code: c_int) -> !; pub fn _exit(code: c_int) -> !; pub fn abort() -> !; pub fn aligned_alloc(a: size_t, b: size_t) -> *mut c_void; pub fn calloc(amt: size_t, amt2: size_t) -> *mut c_void; pub fn exit(code: c_int) -> !; pub fn free(ptr: *mut c_void); pub fn getenv(s: *const c_char) -> *mut c_char; pub fn malloc(amt: size_t) -> *mut c_void; pub fn malloc_usable_size(ptr: *mut c_void) -> size_t; pub fn sbrk(increment: intptr_t) -> *mut c_void; pub fn rand() -> c_int; pub fn read(fd: c_int, ptr: *mut c_void, size: size_t) -> ssize_t; pub fn realloc(ptr: *mut c_void, amt: size_t) -> *mut c_void; pub fn setenv(k: *const c_char, v: *const c_char, a: c_int) -> c_int; pub fn unsetenv(k: *const c_char) -> c_int; pub fn clearenv() -> c_int; pub fn write(fd: c_int, ptr: *const c_void, size: size_t) -> ssize_t; pub static mut environ: *mut *mut c_char; pub fn fopen(a: *const c_char, b: *const c_char) -> *mut FILE; pub fn freopen(a: *const c_char, b: *const c_char, f: *mut FILE) -> *mut FILE; pub fn fclose(f: *mut FILE) -> c_int; pub fn remove(a: *const c_char) -> c_int; pub fn rename(a: *const c_char, b: *const c_char) -> c_int; pub fn feof(f: *mut FILE) -> c_int; pub fn ferror(f: *mut FILE) -> c_int; pub fn fflush(f: *mut FILE) -> c_int; pub fn clearerr(f: *mut FILE); pub fn fseek(f: *mut FILE, b: c_long, c: c_int) -> c_int; pub fn ftell(f: *mut FILE) -> c_long; pub fn rewind(f: *mut FILE); pub fn fgetpos(f: *mut FILE, pos: *mut fpos_t) -> c_int; pub fn fsetpos(f: *mut FILE, pos: *const fpos_t) -> c_int; pub fn fread(buf: *mut c_void, a: size_t, b: size_t, f: *mut FILE) -> size_t; pub fn fwrite(buf: *const c_void, a: size_t, b: size_t, f: *mut FILE) -> size_t; pub fn fgetc(f: *mut FILE) -> c_int; pub fn getc(f: *mut FILE) -> c_int; pub fn getchar() -> c_int; pub fn ungetc(a: c_int, f: *mut FILE) -> c_int; pub fn fputc(a: c_int, f: *mut FILE) -> c_int; pub fn putc(a: c_int, f: *mut FILE) -> c_int; pub fn putchar(a: c_int) -> c_int; pub fn fputs(a: *const c_char, f: *mut FILE) -> c_int; pub fn puts(a: *const c_char) -> c_int; pub fn perror(a: *const c_char); pub fn srand(a: c_uint); pub fn atexit(a: extern "C" fn()) -> c_int; pub fn at_quick_exit(a: extern "C" fn()) -> c_int; pub fn quick_exit(a: c_int) -> !; pub fn posix_memalign(a: *mut *mut c_void, b: size_t, c: size_t) -> c_int; pub fn rand_r(a: *mut c_uint) -> c_int; pub fn random() -> c_long; pub fn srandom(a: c_uint); pub fn putenv(a: *mut c_char) -> c_int; pub fn clock() -> clock_t; pub fn time(a: *mut time_t) -> time_t; pub fn difftime(a: time_t, b: time_t) -> c_double; pub fn mktime(a: *mut tm) -> time_t; pub fn strftime(a: *mut c_char, b: size_t, c: *const c_char, d: *const tm) -> size_t; pub fn gmtime(a: *const time_t) -> *mut tm; pub fn gmtime_r(a: *const time_t, b: *mut tm) -> *mut tm; pub fn localtime(a: *const time_t) -> *mut tm; pub fn localtime_r(a: *const time_t, b: *mut tm) -> *mut tm; pub fn asctime_r(a: *const tm, b: *mut c_char) -> *mut c_char; pub fn ctime_r(a: *const time_t, b: *mut c_char) -> *mut c_char; static _CLOCK_MONOTONIC: u8; static _CLOCK_PROCESS_CPUTIME_ID: u8; static _CLOCK_REALTIME: u8; static _CLOCK_THREAD_CPUTIME_ID: u8; pub fn nanosleep(a: *const timespec, b: *mut timespec) -> c_int; pub fn clock_getres(a: clockid_t, b: *mut timespec) -> c_int; pub fn clock_gettime(a: clockid_t, b: *mut timespec) -> c_int; pub fn clock_nanosleep(a: clockid_t, a2: c_int, b: *const timespec, c: *mut timespec) -> c_int; pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strndup(cs: *const c_char, n: size_t) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn fprintf(stream: *mut crate::FILE, format: *const c_char, ...) -> c_int; pub fn printf(format: *const c_char, ...) -> c_int; pub fn snprintf(s: *mut c_char, n: size_t, format: *const c_char, ...) -> c_int; pub fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int; pub fn fscanf(stream: *mut crate::FILE, format: *const c_char, ...) -> c_int; pub fn scanf(format: *const c_char, ...) -> c_int; pub fn sscanf(s: *const c_char, format: *const c_char, ...) -> c_int; pub fn getchar_unlocked() -> c_int; pub fn putchar_unlocked(c: c_int) -> c_int; pub fn shutdown(socket: c_int, how: c_int) -> c_int; pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int; pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut crate::FILE; pub fn fileno(stream: *mut crate::FILE) -> c_int; pub fn open(path: *const c_char, oflag: c_int, ...) -> c_int; pub fn creat(path: *const c_char, mode: mode_t) -> c_int; pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int; pub fn opendir(dirname: *const c_char) -> *mut crate::DIR; pub fn fdopendir(fd: c_int) -> *mut crate::DIR; pub fn readdir(dirp: *mut crate::DIR) -> *mut crate::dirent; pub fn closedir(dirp: *mut crate::DIR) -> c_int; pub fn rewinddir(dirp: *mut crate::DIR); pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int, ...) -> c_int; pub fn fstatat(dirfd: c_int, pathname: *const c_char, buf: *mut stat, flags: c_int) -> c_int; pub fn linkat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn mkdirat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn readlinkat( dirfd: c_int, pathname: *const c_char, buf: *mut c_char, bufsiz: size_t, ) -> ssize_t; pub fn renameat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, ) -> c_int; pub fn symlinkat(target: *const c_char, newdirfd: c_int, linkpath: *const c_char) -> c_int; pub fn unlinkat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int; pub fn access(path: *const c_char, amode: c_int) -> c_int; pub fn close(fd: c_int) -> c_int; pub fn fpathconf(filedes: c_int, name: c_int) -> c_long; pub fn getopt(argc: c_int, argv: *const *mut c_char, optstr: *const c_char) -> c_int; pub fn isatty(fd: c_int) -> c_int; pub fn link(src: *const c_char, dst: *const c_char) -> c_int; pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t; pub fn pathconf(path: *const c_char, name: c_int) -> c_long; pub fn rmdir(path: *const c_char) -> c_int; pub fn sleep(secs: c_uint) -> c_uint; pub fn unlink(c: *const c_char) -> c_int; pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t; pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t, offset: off_t) -> ssize_t; pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; pub fn fsync(fd: c_int) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; pub fn symlink(path1: *const c_char, path2: *const c_char) -> c_int; pub fn truncate(path: *const c_char, length: off_t) -> c_int; pub fn ftruncate(fd: c_int, length: off_t) -> c_int; pub fn getrusage(resource: c_int, usage: *mut rusage) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn times(buf: *mut crate::tms) -> crate::clock_t; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn usleep(secs: c_uint) -> c_int; pub fn send(socket: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t; pub fn recv(socket: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t; pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int; pub fn setlocale(category: c_int, locale: *const c_char) -> *mut c_char; pub fn localeconv() -> *mut lconv; pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: size_t) -> ssize_t; pub fn timegm(tm: *mut crate::tm) -> time_t; pub fn sysconf(name: c_int) -> c_long; pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int; pub fn fseeko(stream: *mut crate::FILE, offset: off_t, whence: c_int) -> c_int; pub fn ftello(stream: *mut crate::FILE) -> off_t; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; pub fn freelocale(loc: crate::locale_t); pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn sched_yield() -> c_int; pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; pub fn chdir(dir: *const c_char) -> c_int; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn nl_langinfo_l(item: crate::nl_item, loc: crate::locale_t) -> *mut c_char; pub fn select( nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *const timeval, ) -> c_int; pub fn __wasilibc_register_preopened_fd(fd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_fd_renumber(fd: c_int, newfd: c_int) -> c_int; pub fn __wasilibc_unlinkat(fd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_rmdirat(fd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_find_relpath( path: *const c_char, abs_prefix: *mut *const c_char, relative_path: *mut *mut c_char, relative_path_len: usize, ) -> c_int; pub fn __wasilibc_tell(fd: c_int) -> off_t; pub fn __wasilibc_nocwd___wasilibc_unlinkat(dirfd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_nocwd___wasilibc_rmdirat(dirfd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_nocwd_linkat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn __wasilibc_nocwd_symlinkat( target: *const c_char, dirfd: c_int, path: *const c_char, ) -> c_int; pub fn __wasilibc_nocwd_readlinkat( dirfd: c_int, path: *const c_char, buf: *mut c_char, bufsize: usize, ) -> isize; pub fn __wasilibc_nocwd_faccessat( dirfd: c_int, path: *const c_char, mode: c_int, flags: c_int, ) -> c_int; pub fn __wasilibc_nocwd_renameat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, ) -> c_int; pub fn __wasilibc_nocwd_openat_nomode(dirfd: c_int, path: *const c_char, flags: c_int) -> c_int; pub fn __wasilibc_nocwd_fstatat( dirfd: c_int, path: *const c_char, buf: *mut stat, flags: c_int, ) -> c_int; pub fn __wasilibc_nocwd_mkdirat_nomode(dirfd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_nocwd_utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flags: c_int, ) -> c_int; pub fn __wasilibc_nocwd_opendirat(dirfd: c_int, path: *const c_char) -> *mut crate::DIR; pub fn __wasilibc_access(pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn __wasilibc_stat(pathname: *const c_char, buf: *mut stat, flags: c_int) -> c_int; pub fn __wasilibc_utimens( pathname: *const c_char, times: *const crate::timespec, flags: c_int, ) -> c_int; pub fn __wasilibc_link(oldpath: *const c_char, newpath: *const c_char, flags: c_int) -> c_int; pub fn __wasilibc_link_oldat( olddirfd: c_int, oldpath: *const c_char, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn __wasilibc_link_newat( oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn __wasilibc_rename_oldat( olddirfd: c_int, oldpath: *const c_char, newpath: *const c_char, ) -> c_int; pub fn __wasilibc_rename_newat( oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, ) -> c_int; pub fn arc4random() -> u32; pub fn arc4random_buf(a: *mut c_void, b: size_t); pub fn arc4random_uniform(a: u32) -> u32; pub fn __errno_location() -> *mut c_int; } cfg_if! { if #[cfg(target_env = "p2")] { mod p2; pub use self::p2::*; } } libc/src/wasi/p2.rs0000644000175000017500000001162315105742312013737 0ustar bdrungbdrunguse crate::prelude::*; pub type sa_family_t = c_ushort; pub type in_port_t = c_ushort; pub type in_addr_t = c_uint; pub type socklen_t = c_uint; s! { #[repr(align(16))] pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [c_char; 0], } pub struct in_addr { pub s_addr: in_addr_t, } #[repr(align(16))] pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, } #[repr(align(4))] pub struct in6_addr { pub s6_addr: [c_uchar; 16], } #[repr(align(16))] pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: c_uint, pub sin6_addr: in6_addr, pub sin6_scope_id: c_uint, } #[repr(align(16))] pub struct sockaddr_storage { pub ss_family: sa_family_t, pub __ss_data: [c_char; 32], } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, pub ai_addr: *mut sockaddr, pub ai_canonname: *mut c_char, pub ai_next: *mut addrinfo, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: c_uint, } pub struct linger { pub l_onoff: c_int, pub l_linger: c_int, } } pub const SHUT_RD: c_int = 1 << 0; pub const SHUT_WR: c_int = 1 << 1; pub const SHUT_RDWR: c_int = SHUT_RD | SHUT_WR; pub const MSG_NOSIGNAL: c_int = 0x4000; pub const MSG_PEEK: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 2; pub const SO_TYPE: c_int = 3; pub const SO_ERROR: c_int = 4; pub const SO_BROADCAST: c_int = 6; pub const SO_SNDBUF: c_int = 7; pub const SO_RCVBUF: c_int = 8; pub const SO_KEEPALIVE: c_int = 9; pub const SO_LINGER: c_int = 13; pub const SO_ACCEPTCONN: c_int = 30; pub const SO_PROTOCOL: c_int = 38; pub const SO_DOMAIN: c_int = 39; pub const SO_RCVTIMEO: c_int = 66; pub const SO_SNDTIMEO: c_int = 67; pub const SOCK_DGRAM: c_int = 5; pub const SOCK_STREAM: c_int = 6; pub const SOCK_NONBLOCK: c_int = 0x00004000; pub const SOL_SOCKET: c_int = 0x7fffffff; pub const AF_UNSPEC: c_int = 0; pub const AF_INET: c_int = 1; pub const AF_INET6: c_int = 2; pub const IPPROTO_IP: c_int = 0; pub const IPPROTO_TCP: c_int = 6; pub const IPPROTO_UDP: c_int = 17; pub const IPPROTO_IPV6: c_int = 41; pub const IP_TTL: c_int = 2; pub const IP_MULTICAST_TTL: c_int = 33; pub const IP_MULTICAST_LOOP: c_int = 34; pub const IP_ADD_MEMBERSHIP: c_int = 35; pub const IP_DROP_MEMBERSHIP: c_int = 36; pub const IPV6_UNICAST_HOPS: c_int = 16; pub const IPV6_MULTICAST_LOOP: c_int = 19; pub const IPV6_JOIN_GROUP: c_int = 20; pub const IPV6_LEAVE_GROUP: c_int = 21; pub const IPV6_V6ONLY: c_int = 26; pub const IPV6_ADD_MEMBERSHIP: c_int = IPV6_JOIN_GROUP; pub const IPV6_DROP_MEMBERSHIP: c_int = IPV6_LEAVE_GROUP; pub const TCP_NODELAY: c_int = 1; pub const TCP_KEEPIDLE: c_int = 4; pub const TCP_KEEPINTVL: c_int = 5; pub const TCP_KEEPCNT: c_int = 6; pub const EAI_SYSTEM: c_int = -11; extern "C" { pub fn socket(domain: c_int, type_: c_int, protocol: c_int) -> c_int; pub fn connect(fd: c_int, name: *const sockaddr, addrlen: socklen_t) -> c_int; pub fn bind(socket: c_int, addr: *const sockaddr, addrlen: socklen_t) -> c_int; pub fn listen(socket: c_int, backlog: c_int) -> c_int; pub fn accept(socket: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> c_int; pub fn accept4( socket: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t, flags: c_int, ) -> c_int; pub fn getsockname(socket: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> c_int; pub fn getpeername(socket: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t) -> c_int; pub fn sendto( socket: c_int, buffer: *const c_void, length: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t, ) -> ssize_t; pub fn recvfrom( socket: c_int, buffer: *mut c_void, length: size_t, flags: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t, ) -> ssize_t; pub fn getsockopt( sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t, ) -> c_int; pub fn setsockopt( sockfd: c_int, level: c_int, optname: c_int, optval: *const c_void, optlen: socklen_t, ) -> c_int; pub fn getaddrinfo( host: *const c_char, serv: *const c_char, hint: *const addrinfo, res: *mut *mut addrinfo, ) -> c_int; pub fn freeaddrinfo(p: *mut addrinfo); pub fn gai_strerror(ecode: c_int) -> *const c_char; } libc/src/xous.rs0000644000175000017500000000055615105742312013454 0ustar bdrungbdrung//! Xous C type definitions use crate::prelude::*; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type off_t = i64; pub type wchar_t = u32; pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; libc/src/sgx.rs0000644000175000017500000000047615105742312013260 0ustar bdrungbdrung//! SGX C types definition use crate::prelude::*; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; libc/src/trusty.rs0000644000175000017500000000372015105742312014024 0ustar bdrungbdrunguse crate::prelude::*; pub type size_t = usize; pub type ssize_t = isize; pub type off_t = i64; pub type c_uint8_t = u8; pub type c_uint16_t = u16; pub type c_uint32_t = u32; pub type c_uint64_t = u64; pub type c_int8_t = i8; pub type c_int16_t = i16; pub type c_int32_t = i32; pub type c_int64_t = i64; pub type intptr_t = isize; pub type uintptr_t = usize; pub type time_t = c_long; pub type clockid_t = c_int; s! { pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } } pub const PROT_READ: i32 = 1; pub const PROT_WRITE: i32 = 2; // Trusty only supports `CLOCK_BOOTTIME`. pub const CLOCK_BOOTTIME: clockid_t = 7; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const AT_PAGESZ: c_ulong = 6; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; extern "C" { pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn memalign(align: size_t, size: size_t) -> *mut c_void; pub fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int; pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn close(fd: c_int) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn getauxval(type_: c_ulong) -> c_ulong; pub fn mmap( addr: *mut c_void, len: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off_t, ) -> *mut c_void; pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn nanosleep(rqtp: *const crate::timespec, rmtp: *mut crate::timespec) -> c_int; } libc/src/solid/0000775000175000017500000000000015105742312013216 5ustar bdrungbdrunglibc/src/solid/mod.rs0000644000175000017500000007714415105742312014356 0ustar bdrungbdrung//! Interface to the [SOLID] C library //! //! [SOLID]: https://solid.kmckk.com/ use crate::prelude::*; pub type intmax_t = i64; pub type uintmax_t = u64; pub type uintptr_t = usize; pub type intptr_t = isize; pub type ptrdiff_t = isize; pub type size_t = crate::uintptr_t; pub type ssize_t = intptr_t; pub type clock_t = c_uint; pub type time_t = i64; pub type clockid_t = c_int; pub type timer_t = c_int; pub type suseconds_t = c_int; pub type useconds_t = c_uint; pub type sighandler_t = size_t; // sys/ansi.h pub type __caddr_t = *mut c_char; pub type __gid_t = u32; pub type __in_addr_t = u32; pub type __in_port_t = u16; pub type __mode_t = u32; pub type __off_t = i64; pub type __pid_t = i32; pub type __sa_family_t = u8; pub type __socklen_t = c_uint; pub type __uid_t = u32; pub type __fsblkcnt_t = u64; pub type __fsfilcnt_t = u64; // locale.h pub type locale_t = usize; // nl_types.h pub type nl_item = c_long; // sys/types.h pub type __va_list = *mut c_char; pub type u_int8_t = u8; pub type u_int16_t = u16; pub type u_int32_t = u32; pub type u_int64_t = u64; pub type u_char = c_uchar; pub type u_short = c_ushort; pub type u_int = c_uint; pub type u_long = c_ulong; pub type unchar = c_uchar; pub type ushort = c_ushort; pub type uint = c_uint; pub type ulong = c_ulong; pub type u_quad_t = u64; pub type quad_t = i64; pub type qaddr_t = *mut quad_t; pub type longlong_t = i64; pub type u_longlong_t = u64; pub type blkcnt_t = i64; pub type blksize_t = i32; pub type fsblkcnt_t = __fsblkcnt_t; pub type fsfilcnt_t = __fsfilcnt_t; pub type caddr_t = __caddr_t; pub type daddr_t = i64; pub type dev_t = u64; pub type fixpt_t = u32; pub type gid_t = __gid_t; pub type idtype_t = c_int; pub type id_t = u32; pub type ino_t = u64; pub type key_t = c_long; pub type mode_t = __mode_t; pub type nlink_t = u32; pub type off_t = __off_t; pub type pid_t = __pid_t; pub type lwpid_t = i32; pub type rlim_t = u64; pub type segsz_t = i32; pub type swblk_t = i32; pub type mqd_t = c_int; pub type cpuid_t = c_ulong; pub type psetid_t = c_int; s! { // stat.h pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: c_short, pub st_nlink: c_short, pub st_uid: c_short, pub st_gid: c_short, pub st_rdev: dev_t, pub st_size: off_t, pub st_atime: time_t, pub st_mtime: time_t, pub st_ctime: time_t, pub st_blksize: blksize_t, } // time.h pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *mut c_char, } // stdlib.h pub struct qdiv_t { pub quot: quad_t, pub rem: quad_t, } pub struct lldiv_t { pub quot: c_longlong, pub rem: c_longlong, } pub struct div_t { pub quot: c_int, pub rem: c_int, } pub struct ldiv_t { pub quot: c_long, pub rem: c_long, } // locale.h pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_n_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct timeval { pub tv_sec: c_long, pub tv_usec: c_long, } } pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 0x7fffffff; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const BUFSIZ: c_uint = 1024; pub const FOPEN_MAX: c_uint = 20; pub const FILENAME_MAX: c_uint = 1024; pub const O_RDONLY: c_int = 1; pub const O_WRONLY: c_int = 2; pub const O_RDWR: c_int = 4; pub const O_APPEND: c_int = 8; pub const O_CREAT: c_int = 0x10; pub const O_EXCL: c_int = 0x400; pub const O_TEXT: c_int = 0x100; pub const O_BINARY: c_int = 0x200; pub const O_TRUNC: c_int = 0x20; pub const S_IEXEC: c_short = 0o0100; pub const S_IWRITE: c_short = 0o0200; pub const S_IREAD: c_short = 0o0400; pub const S_IFCHR: c_short = 0o2_0000; pub const S_IFDIR: c_short = 0o4_0000; pub const S_IFMT: c_short = 0o16_0000; pub const S_IFIFO: c_short = 0o1_0000; pub const S_IFBLK: c_short = 0o6_0000; pub const S_IFREG: c_short = 0o10_0000; pub const LC_ALL: c_int = 0; pub const LC_COLLATE: c_int = 1; pub const LC_CTYPE: c_int = 2; pub const LC_MONETARY: c_int = 3; pub const LC_NUMERIC: c_int = 4; pub const LC_TIME: c_int = 5; pub const LC_MESSAGES: c_int = 6; pub const _LC_LAST: c_int = 7; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const EWOULDBLOCK: c_int = EAGAIN; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EDEADLOCK: c_int = EDEADLK; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EMULTIHOP: c_int = 72; pub const EDOTDOT: c_int = 73; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ENOTSUP: c_int = 132; pub const EFTYPE: c_int = 133; // signal codes pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGIOT: c_int = SIGABRT; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGBUS: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGSYS: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGURG: c_int = 16; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGCONT: c_int = 19; pub const SIGCHLD: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGIO: c_int = 23; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGINFO: c_int = 29; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGPWR: c_int = 32; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} impl Copy for FILE {} impl Clone for FILE { fn clone(&self) -> FILE { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} impl Copy for fpos_t {} impl Clone for fpos_t { fn clone(&self) -> fpos_t { *self } } extern "C" { // ctype.h pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; // stdio.h pub fn __get_stdio_file(fileno: c_int) -> *mut FILE; pub fn clearerr(arg1: *mut FILE); pub fn fclose(arg1: *mut FILE) -> c_int; pub fn feof(arg1: *mut FILE) -> c_int; pub fn ferror(arg1: *mut FILE) -> c_int; pub fn fflush(arg1: *mut FILE) -> c_int; pub fn fgetc(arg1: *mut FILE) -> c_int; pub fn fgets(arg1: *mut c_char, arg2: c_int, arg3: *mut FILE) -> *mut c_char; pub fn fopen(arg1: *const c_char, arg2: *const c_char) -> *mut FILE; pub fn fprintf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; pub fn fputc(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn fputs(arg1: *const c_char, arg2: *mut FILE) -> c_int; pub fn fread(arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: *mut FILE) -> size_t; pub fn freopen(arg1: *const c_char, arg2: *const c_char, arg3: *mut FILE) -> *mut FILE; pub fn fscanf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; pub fn fseek(arg1: *mut FILE, arg2: c_long, arg3: c_int) -> c_int; pub fn ftell(arg1: *mut FILE) -> c_long; pub fn fwrite(arg1: *const c_void, arg2: size_t, arg3: size_t, arg4: *mut FILE) -> size_t; pub fn getc(arg1: *mut FILE) -> c_int; pub fn getchar() -> c_int; pub fn perror(arg1: *const c_char); pub fn printf(arg1: *const c_char, ...) -> c_int; pub fn putc(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn putchar(arg1: c_int) -> c_int; pub fn puts(arg1: *const c_char) -> c_int; pub fn remove(arg1: *const c_char) -> c_int; pub fn rewind(arg1: *mut FILE); pub fn scanf(arg1: *const c_char, ...) -> c_int; pub fn setbuf(arg1: *mut FILE, arg2: *mut c_char); pub fn setvbuf(arg1: *mut FILE, arg2: *mut c_char, arg3: c_int, arg4: size_t) -> c_int; pub fn sscanf(arg1: *const c_char, arg2: *const c_char, ...) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn ungetc(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn vfprintf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vprintf(arg1: *const c_char, arg2: __va_list) -> c_int; pub fn gets(arg1: *mut c_char) -> *mut c_char; pub fn sprintf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; pub fn tmpnam(arg1: *const c_char) -> *mut c_char; pub fn vsprintf(arg1: *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn rename(arg1: *const c_char, arg2: *const c_char) -> c_int; pub fn asiprintf(arg1: *mut *mut c_char, arg2: *const c_char, ...) -> c_int; pub fn fiprintf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; pub fn fiscanf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; pub fn iprintf(arg1: *const c_char, ...) -> c_int; pub fn iscanf(arg1: *const c_char, ...) -> c_int; pub fn siprintf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; pub fn siscanf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; pub fn sniprintf(arg1: *mut c_char, arg2: size_t, arg3: *const c_char, ...) -> c_int; pub fn vasiprintf(arg1: *mut *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vfiprintf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vfiscanf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn viprintf(arg1: *const c_char, arg2: __va_list) -> c_int; pub fn viscanf(arg1: *const c_char, arg2: __va_list) -> c_int; pub fn vsiprintf(arg1: *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vsiscanf(arg1: *const c_char, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vsniprintf( arg1: *mut c_char, arg2: size_t, arg3: *const c_char, arg4: __va_list, ) -> c_int; pub fn vdiprintf(arg1: c_int, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn diprintf(arg1: c_int, arg2: *const c_char, ...) -> c_int; pub fn fgetpos(arg1: *mut FILE, arg2: *mut fpos_t) -> c_int; pub fn fsetpos(arg1: *mut FILE, arg2: *const fpos_t) -> c_int; pub fn fdopen(arg1: c_int, arg2: *const c_char) -> *mut FILE; pub fn fileno(arg1: *mut FILE) -> c_int; pub fn flockfile(arg1: *mut FILE); pub fn ftrylockfile(arg1: *mut FILE) -> c_int; pub fn funlockfile(arg1: *mut FILE); pub fn getc_unlocked(arg1: *mut FILE) -> c_int; pub fn getchar_unlocked() -> c_int; pub fn putc_unlocked(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn putchar_unlocked(arg1: c_int) -> c_int; pub fn snprintf(arg1: *mut c_char, arg2: size_t, arg3: *const c_char, ...) -> c_int; pub fn vsnprintf( arg1: *mut c_char, arg2: size_t, arg3: *const c_char, arg4: __va_list, ) -> c_int; pub fn getw(arg1: *mut FILE) -> c_int; pub fn putw(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn tempnam(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; pub fn fseeko(stream: *mut FILE, offset: off_t, whence: c_int) -> c_int; pub fn ftello(stream: *mut FILE) -> off_t; // stdlib.h pub fn atof(arg1: *const c_char) -> f64; pub fn strtod(arg1: *const c_char, arg2: *mut *mut c_char) -> f64; pub fn drand48() -> f64; pub fn erand48(arg1: *mut c_ushort) -> f64; pub fn strtof(arg1: *const c_char, arg2: *mut *mut c_char) -> f32; pub fn strtold(arg1: *const c_char, arg2: *mut *mut c_char) -> f64; pub fn strtod_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f64; pub fn strtof_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f32; pub fn strtold_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f64; pub fn _Exit(arg1: c_int) -> !; pub fn abort() -> !; pub fn abs(arg1: c_int) -> c_int; pub fn atexit(arg1: Option) -> c_int; pub fn atoi(arg1: *const c_char) -> c_int; pub fn atol(arg1: *const c_char) -> c_long; pub fn itoa(arg1: c_int, arg2: *mut c_char, arg3: c_int) -> *mut c_char; pub fn ltoa(arg1: c_long, arg2: *mut c_char, arg3: c_int) -> *mut c_char; pub fn ultoa(arg1: c_ulong, arg2: *mut c_char, arg3: c_int) -> *mut c_char; pub fn bsearch( arg1: *const c_void, arg2: *const c_void, arg3: size_t, arg4: size_t, arg5: Option c_int>, ) -> *mut c_void; pub fn calloc(arg1: size_t, arg2: size_t) -> *mut c_void; pub fn div(arg1: c_int, arg2: c_int) -> div_t; pub fn exit(arg1: c_int) -> !; pub fn free(arg1: *mut c_void); pub fn getenv(arg1: *const c_char) -> *mut c_char; pub fn labs(arg1: c_long) -> c_long; pub fn ldiv(arg1: c_long, arg2: c_long) -> ldiv_t; pub fn malloc(arg1: size_t) -> *mut c_void; pub fn qsort( arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: Option c_int>, ); pub fn rand() -> c_int; pub fn realloc(arg1: *mut c_void, arg2: size_t) -> *mut c_void; pub fn srand(arg1: c_uint); pub fn strtol(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_long; pub fn strtoul(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_ulong; pub fn mblen(arg1: *const c_char, arg2: size_t) -> c_int; pub fn mbstowcs(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t) -> size_t; pub fn wctomb(arg1: *mut c_char, arg2: wchar_t) -> c_int; pub fn mbtowc(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t) -> c_int; pub fn wcstombs(arg1: *mut c_char, arg2: *const wchar_t, arg3: size_t) -> size_t; pub fn rand_r(arg1: *mut c_uint) -> c_int; pub fn jrand48(arg1: *mut c_ushort) -> c_long; pub fn lcong48(arg1: *mut c_ushort); pub fn lrand48() -> c_long; pub fn mrand48() -> c_long; pub fn nrand48(arg1: *mut c_ushort) -> c_long; pub fn seed48(arg1: *mut c_ushort) -> *mut c_ushort; pub fn srand48(arg1: c_long); pub fn putenv(arg1: *mut c_char) -> c_int; pub fn a64l(arg1: *const c_char) -> c_long; pub fn l64a(arg1: c_long) -> *mut c_char; pub fn random() -> c_long; pub fn setstate(arg1: *mut c_char) -> *mut c_char; pub fn initstate(arg1: c_uint, arg2: *mut c_char, arg3: size_t) -> *mut c_char; pub fn srandom(arg1: c_uint); pub fn mkostemp(arg1: *mut c_char, arg2: c_int) -> c_int; pub fn mkostemps(arg1: *mut c_char, arg2: c_int, arg3: c_int) -> c_int; pub fn mkdtemp(arg1: *mut c_char) -> *mut c_char; pub fn mkstemp(arg1: *mut c_char) -> c_int; pub fn mktemp(arg1: *mut c_char) -> *mut c_char; pub fn atoll(arg1: *const c_char) -> c_longlong; pub fn llabs(arg1: c_longlong) -> c_longlong; pub fn lldiv(arg1: c_longlong, arg2: c_longlong) -> lldiv_t; pub fn strtoll(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_longlong; pub fn strtoull(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_ulonglong; pub fn aligned_alloc(arg1: size_t, arg2: size_t) -> *mut c_void; pub fn at_quick_exit(arg1: Option) -> c_int; pub fn quick_exit(arg1: c_int); pub fn setenv(arg1: *const c_char, arg2: *const c_char, arg3: c_int) -> c_int; pub fn unsetenv(arg1: *const c_char) -> c_int; pub fn humanize_number( arg1: *mut c_char, arg2: size_t, arg3: i64, arg4: *const c_char, arg5: c_int, arg6: c_int, ) -> c_int; pub fn dehumanize_number(arg1: *const c_char, arg2: *mut i64) -> c_int; pub fn getenv_r(arg1: *const c_char, arg2: *mut c_char, arg3: size_t) -> c_int; pub fn heapsort( arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: Option c_int>, ) -> c_int; pub fn mergesort( arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: Option c_int>, ) -> c_int; pub fn radixsort( arg1: *mut *const c_uchar, arg2: c_int, arg3: *const c_uchar, arg4: c_uint, ) -> c_int; pub fn sradixsort( arg1: *mut *const c_uchar, arg2: c_int, arg3: *const c_uchar, arg4: c_uint, ) -> c_int; pub fn getprogname() -> *const c_char; pub fn setprogname(arg1: *const c_char); pub fn qabs(arg1: quad_t) -> quad_t; pub fn strtoq(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> quad_t; pub fn strtouq(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> u_quad_t; pub fn strsuftoll( arg1: *const c_char, arg2: *const c_char, arg3: c_longlong, arg4: c_longlong, ) -> c_longlong; pub fn strsuftollx( arg1: *const c_char, arg2: *const c_char, arg3: c_longlong, arg4: c_longlong, arg5: *mut c_char, arg6: size_t, ) -> c_longlong; pub fn l64a_r(arg1: c_long, arg2: *mut c_char, arg3: c_int) -> c_int; pub fn qdiv(arg1: quad_t, arg2: quad_t) -> qdiv_t; pub fn strtol_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> c_long; pub fn strtoul_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> c_ulong; pub fn strtoll_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> c_longlong; pub fn strtoull_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> c_ulonglong; pub fn strtoq_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> quad_t; pub fn strtouq_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> u_quad_t; pub fn _mb_cur_max_l(arg1: locale_t) -> size_t; pub fn mblen_l(arg1: *const c_char, arg2: size_t, arg3: locale_t) -> c_int; pub fn mbstowcs_l( arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t, arg4: locale_t, ) -> size_t; pub fn wctomb_l(arg1: *mut c_char, arg2: wchar_t, arg3: locale_t) -> c_int; pub fn mbtowc_l(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t, arg4: locale_t) -> c_int; pub fn wcstombs_l( arg1: *mut c_char, arg2: *const wchar_t, arg3: size_t, arg4: locale_t, ) -> size_t; // string.h pub fn memchr(arg1: *const c_void, arg2: c_int, arg3: size_t) -> *mut c_void; pub fn memcmp(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; pub fn memcpy(arg1: *mut c_void, arg2: *const c_void, arg3: size_t) -> *mut c_void; pub fn memmove(arg1: *mut c_void, arg2: *const c_void, arg3: size_t) -> *mut c_void; pub fn memset(arg1: *mut c_void, arg2: c_int, arg3: size_t) -> *mut c_void; pub fn strcat(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn strchr(arg1: *const c_char, arg2: c_int) -> *mut c_char; pub fn strcmp(arg1: *const c_char, arg2: *const c_char) -> c_int; pub fn strcoll(arg1: *const c_char, arg2: *const c_char) -> c_int; pub fn strcpy(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn strcspn(arg1: *const c_char, arg2: *const c_char) -> size_t; pub fn strerror(arg1: c_int) -> *mut c_char; pub fn strlen(arg1: *const c_char) -> size_t; pub fn strncat(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; pub fn strncmp(arg1: *const c_char, arg2: *const c_char, arg3: size_t) -> c_int; pub fn strncpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; pub fn strpbrk(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; pub fn strrchr(arg1: *const c_char, arg2: c_int) -> *mut c_char; pub fn strspn(arg1: *const c_char, arg2: *const c_char) -> size_t; pub fn strstr(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; pub fn strtok(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn strtok_r(arg1: *mut c_char, arg2: *const c_char, arg3: *mut *mut c_char) -> *mut c_char; pub fn strerror_r(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> c_int; pub fn strxfrm(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; pub fn memccpy( arg1: *mut c_void, arg2: *const c_void, arg3: c_int, arg4: size_t, ) -> *mut c_void; pub fn strdup(arg1: *const c_char) -> *mut c_char; pub fn stpcpy(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn stpncpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; pub fn strnlen(arg1: *const c_char, arg2: size_t) -> size_t; pub fn memmem( arg1: *const c_void, arg2: size_t, arg3: *const c_void, arg4: size_t, ) -> *mut c_void; pub fn strcasestr(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; pub fn strlcat(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; pub fn strlcpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; pub fn strsep(arg1: *mut *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn stresep(arg1: *mut *mut c_char, arg2: *const c_char, arg3: c_int) -> *mut c_char; pub fn strndup(arg1: *const c_char, arg2: size_t) -> *mut c_char; pub fn memrchr(arg1: *const c_void, arg2: c_int, arg3: size_t) -> *mut c_void; pub fn explicit_memset(arg1: *mut c_void, arg2: c_int, arg3: size_t) -> *mut c_void; pub fn consttime_memequal(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; pub fn strcoll_l(arg1: *const c_char, arg2: *const c_char, arg3: locale_t) -> c_int; pub fn strxfrm_l( arg1: *mut c_char, arg2: *const c_char, arg3: size_t, arg4: locale_t, ) -> size_t; pub fn strerror_l(arg1: c_int, arg2: locale_t) -> *mut c_char; // strings.h pub fn bcmp(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; pub fn bcopy(arg1: *const c_void, arg2: *mut c_void, arg3: size_t); pub fn bzero(arg1: *mut c_void, arg2: size_t); pub fn ffs(arg1: c_int) -> c_int; pub fn popcount(arg1: c_uint) -> c_uint; pub fn popcountl(arg1: c_ulong) -> c_uint; pub fn popcountll(arg1: c_ulonglong) -> c_uint; pub fn popcount32(arg1: u32) -> c_uint; pub fn popcount64(arg1: u64) -> c_uint; pub fn rindex(arg1: *const c_char, arg2: c_int) -> *mut c_char; pub fn strcasecmp(arg1: *const c_char, arg2: *const c_char) -> c_int; pub fn strncasecmp(arg1: *const c_char, arg2: *const c_char, arg3: size_t) -> c_int; // signal.h pub fn signal(arg1: c_int, arg2: sighandler_t) -> sighandler_t; pub fn raise(arg1: c_int) -> c_int; // time.h pub fn asctime(arg1: *const tm) -> *mut c_char; pub fn clock() -> clock_t; pub fn ctime(arg1: *const time_t) -> *mut c_char; pub fn difftime(arg1: time_t, arg2: time_t) -> f64; pub fn gmtime(arg1: *const time_t) -> *mut tm; pub fn localtime(arg1: *const time_t) -> *mut tm; pub fn time(arg1: *mut time_t) -> time_t; pub fn mktime(arg1: *mut tm) -> time_t; pub fn strftime( arg1: *mut c_char, arg2: size_t, arg3: *const c_char, arg4: *const tm, ) -> size_t; pub fn utime(arg1: *const c_char, arg2: *mut time_t) -> c_int; pub fn asctime_r(arg1: *const tm, arg2: *mut c_char) -> *mut c_char; pub fn ctime_r(arg1: *const time_t, arg2: *mut c_char) -> *mut c_char; pub fn gmtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; pub fn localtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; // sys/stat.h pub fn stat(arg1: *const c_char, arg2: *mut stat) -> c_int; pub fn lstat(arg1: *const c_char, arg2: *mut stat) -> c_int; pub fn fstat(arg1: c_int, arg2: *mut stat) -> c_int; pub fn chmod(arg1: *const c_char, arg2: __mode_t) -> c_int; pub fn mkdir(arg1: *const c_char, arg2: __mode_t) -> c_int; // fcntl.h pub fn open(arg1: *const c_char, arg2: c_int, ...) -> c_int; pub fn creat(arg1: *const c_char, arg2: c_int) -> c_int; pub fn close(arg1: c_int) -> c_int; pub fn read(arg1: c_int, arg2: *mut c_void, arg3: c_int) -> c_int; pub fn write(arg1: c_int, arg2: *const c_void, arg3: c_int) -> c_int; pub fn unlink(arg1: *const c_char) -> c_int; pub fn tell(arg1: c_int) -> c_long; pub fn dup(arg1: c_int) -> c_int; pub fn dup2(arg1: c_int, arg2: c_int) -> c_int; pub fn access(arg1: *const c_char, arg2: c_int) -> c_int; pub fn rmdir(arg1: *const c_char) -> c_int; pub fn chdir(arg1: *const c_char) -> c_int; pub fn _exit(arg1: c_int); pub fn getwd(arg1: *mut c_char) -> *mut c_char; pub fn getcwd(arg1: *mut c_char, arg2: size_t) -> *mut c_char; pub static mut optarg: *mut c_char; pub static mut opterr: c_int; pub static mut optind: c_int; pub static mut optopt: c_int; pub static mut optreset: c_int; pub fn getopt(arg1: c_int, arg2: *mut *mut c_char, arg3: *const c_char) -> c_int; pub static mut suboptarg: *mut c_char; pub fn getsubopt( arg1: *mut *mut c_char, arg2: *const *mut c_char, arg3: *mut *mut c_char, ) -> c_int; pub fn fcntl(arg1: c_int, arg2: c_int, ...) -> c_int; pub fn getpid() -> pid_t; pub fn sleep(arg1: c_uint) -> c_uint; pub fn usleep(arg1: useconds_t) -> c_int; // locale.h pub fn localeconv() -> *mut lconv; pub fn setlocale(arg1: c_int, arg2: *const c_char) -> *mut c_char; pub fn duplocale(arg1: locale_t) -> locale_t; pub fn freelocale(arg1: locale_t); pub fn localeconv_l(arg1: locale_t) -> *mut lconv; pub fn newlocale(arg1: c_int, arg2: *const c_char, arg3: locale_t) -> locale_t; // langinfo.h pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn nl_langinfo_l(item: crate::nl_item, locale: locale_t) -> *mut c_char; // malloc.h pub fn memalign(align: size_t, size: size_t) -> *mut c_void; // sys/types.h pub fn lseek(arg1: c_int, arg2: __off_t, arg3: c_int) -> __off_t; } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(any(target_arch = "arm"))] { mod arm; pub use self::arm::*; } else { // Unknown target_arch } } libc/src/solid/arm.rs0000644000175000017500000000003015105742312014332 0ustar bdrungbdrungpub type wchar_t = u32; libc/src/solid/aarch64.rs0000644000175000017500000000003015105742312015003 0ustar bdrungbdrungpub type wchar_t = u32; libc/src/macros.rs0000644000175000017500000003025215105742312013736 0ustar bdrungbdrung/// A macro for defining #[cfg] if-else statements. /// /// This is similar to the `if/elif` C preprocessor macro by allowing definition /// of a cascade of `#[cfg]` cases, emitting the implementation which matches /// first. /// /// This allows you to conveniently provide a long list #[cfg]'d blocks of code /// without having to rewrite each clause multiple times. macro_rules! cfg_if { // match if/else chains with a final `else` ($( if #[cfg($($meta:meta),*)] { $($it:item)* } ) else * else { $($it2:item)* }) => { cfg_if! { @__items () ; $( ( ($($meta),*) ($($it)*) ), )* ( () ($($it2)*) ), } }; // match if/else chains lacking a final `else` ( if #[cfg($($i_met:meta),*)] { $($i_it:item)* } $( else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } )* ) => { cfg_if! { @__items () ; ( ($($i_met),*) ($($i_it)*) ), $( ( ($($e_met),*) ($($e_it)*) ), )* ( () () ), } }; // Internal and recursive macro to emit all the items // // Collects all the negated `cfg`s in a list at the beginning and after the // semicolon is all the remaining items (@__items ($($not:meta,)*) ; ) => {}; (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { // Emit all items within one block, applying an appropriate #[cfg]. The // #[cfg] will require all `$m` matchers specified and must also negate // all previous matchers. cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } // Recurse to emit all other items in `$rest`, and when we do so add all // our `$m` matchers to the list of `$not` matchers as future emissions // will have to negate everything we just matched as well. cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } }; // Internal macro to Apply a cfg attribute to a list of items (@__apply $m:meta, $($it:item)*) => { $(#[$m] $it)* }; } /// Create an internal crate prelude with `core` reexports and common types. macro_rules! prelude { () => { /// Frequently-used types that are available on all platforms /// /// We need to reexport the core types so this works with `rust-dep-of-std`. mod prelude { // Exports from `core` #[allow(unused_imports)] pub(crate) use ::core::clone::Clone; #[allow(unused_imports)] pub(crate) use ::core::marker::{Copy, Send, Sync}; #[allow(unused_imports)] pub(crate) use ::core::option::Option; #[allow(unused_imports)] pub(crate) use ::core::{fmt, hash, iter, mem}; // Commonly used types defined in this crate #[allow(unused_imports)] pub(crate) use crate::{ c_char, c_double, c_float, c_int, c_long, c_longlong, c_short, c_uchar, c_uint, c_ulong, c_ulonglong, c_ushort, c_void, intptr_t, size_t, ssize_t, uintptr_t, }; } }; } /// Implement `Clone` and `Copy` for a struct, as well as `Debug`, `Eq`, `Hash`, and /// `PartialEq` if the `extra_traits` feature is enabled. /// /// Use [`s_no_extra_traits`] for structs where the `extra_traits` feature does not /// make sense, and for unions. macro_rules! s { ($( $(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* } )*) => ($( s!(it: $(#[$attr])* pub $t $i { $($field)* }); )*); (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => ( compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead"); ); (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => ( __item! { #[repr(C)] #[cfg_attr( feature = "extra_traits", ::core::prelude::v1::derive(Debug, Eq, Hash, PartialEq) )] #[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)] #[allow(deprecated)] $(#[$attr])* pub struct $i { $($field)* } } ); } /// Implement `Clone` and `Copy` for a tuple struct, as well as `Debug`, `Eq`, `Hash`, /// and `PartialEq` if the `extra_traits` feature is enabled. /// /// This is the same as [`s`] but works for tuple structs. macro_rules! s_paren { ($( $(#[$attr:meta])* pub struct $i:ident ( $($field:tt)* ); )*) => ($( __item! { #[cfg_attr( feature = "extra_traits", ::core::prelude::v1::derive(Debug, Eq, Hash, PartialEq) )] #[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)] $(#[$attr])* pub struct $i ( $($field)* ); } )*); } /// Implement `Clone` and `Copy` for a struct with no `extra_traits` feature. /// /// Most items will prefer to use [`s`]. macro_rules! s_no_extra_traits { ($( $(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* } )*) => ($( s_no_extra_traits!(it: $(#[$attr])* pub $t $i { $($field)* }); )*); (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => ( __item! { #[repr(C)] #[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)] $(#[$attr])* pub union $i { $($field)* } } #[cfg(feature = "extra_traits")] impl ::core::fmt::Debug for $i { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { f.debug_struct(::core::stringify!($i)).finish_non_exhaustive() } } ); (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => ( __item! { #[repr(C)] #[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)] $(#[$attr])* pub struct $i { $($field)* } } ); } /// Specify that an enum should have no traits that aren't specified in the macro /// invocation, i.e. no `Clone` or `Copy`. macro_rules! missing { ($( $(#[$attr:meta])* pub enum $i:ident {} )*) => ($( $(#[$attr])* #[allow(missing_copy_implementations)] pub enum $i { } )*); } /// Implement `Clone` and `Copy` for an enum, as well as `Debug`, `Eq`, `Hash`, and /// `PartialEq` if the `extra_traits` feature is enabled. macro_rules! e { ($( $(#[$attr:meta])* pub enum $i:ident { $($field:tt)* } )*) => ($( __item! { #[cfg_attr( feature = "extra_traits", ::core::prelude::v1::derive(Debug, Eq, Hash, PartialEq) )] #[::core::prelude::v1::derive(::core::clone::Clone, ::core::marker::Copy)] $(#[$attr])* pub enum $i { $($field)* } } )*); } // This is a pretty horrible hack to allow us to conditionally mark some functions as 'const', // without requiring users of this macro to care "libc_const_extern_fn". // // When 'libc_const_extern_fn' is enabled, we emit the captured 'const' keyword in the expanded // function. // // When 'libc_const_extern_fn' is disabled, we always emit a plain 'pub unsafe extern fn'. // Note that the expression matched by the macro is exactly the same - this allows // users of this macro to work whether or not 'libc_const_extern_fn' is enabled // // Unfortunately, we need to duplicate most of this macro between the 'cfg_if' blocks. // This is because 'const unsafe extern fn' won't even parse on older compilers, // so we need to avoid emitting it at all of 'libc_const_extern_fn'. // // Specifically, moving the 'cfg_if' into the macro body will *not* work. Doing so would cause the // '#[cfg(libc_const_extern_fn)]' to be emitted into user code. The 'cfg' gate will not stop Rust // from trying to parse the 'pub const unsafe extern fn', so users would get a compiler error even // when the 'libc_const_extern_fn' feature is disabled. // FIXME(ctest): ctest can't handle `const extern` functions, we should be able to remove this // cfg completely. // FIXME(ctest): ctest can't handle `$(,)?` so we use `$(,)*` which isn't quite correct. cfg_if! { if #[cfg(libc_const_extern_fn)] { /// Define an `unsafe` function that is const as long as `libc_const_extern_fn` is enabled. macro_rules! f { ($( $(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block )*) => ($( #[inline] $(#[$attr])* pub $($constness)* unsafe extern "C" fn $i($($arg: $argty),*) -> $ret $body )*) } /// Define a safe function that is const as long as `libc_const_extern_fn` is enabled. macro_rules! safe_f { ($( $(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block )*) => ($( #[inline] $(#[$attr])* pub $($constness)* extern "C" fn $i($($arg: $argty),*) -> $ret $body )*) } /// A nonpublic function that is const as long as `libc_const_extern_fn` is enabled. macro_rules! const_fn { ($( $(#[$attr:meta])* $({$constness:ident})* fn $i:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block )*) => ($( #[inline] $(#[$attr])* $($constness)* fn $i($($arg: $argty),*) -> $ret $body )*) } } else { /// Define an `unsafe` function that is const as long as `libc_const_extern_fn` is enabled. macro_rules! f { ($( $(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block )*) => ($( #[inline] $(#[$attr])* pub unsafe extern "C" fn $i($($arg: $argty),*) -> $ret $body )*) } /// Define a safe function that is const as long as `libc_const_extern_fn` is enabled. macro_rules! safe_f { ($( $(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block )*) => ($( #[inline] $(#[$attr])* pub extern "C" fn $i($($arg: $argty),*) -> $ret $body )*) } /// A nonpublic function that is const as long as `libc_const_extern_fn` is enabled. macro_rules! const_fn { ($( $(#[$attr:meta])* $({$constness:ident})* fn $i:ident($($arg:ident: $argty:ty),* $(,)*) -> $ret:ty $body:block )*) => ($( #[inline] $(#[$attr])* fn $i($($arg: $argty),*) -> $ret $body )*) } } } macro_rules! __item { ($i:item) => { $i }; } // This macro is used to deprecate items that should be accessed via the mach2 crate macro_rules! deprecated_mach { (pub const $id:ident: $ty:ty = $expr:expr;) => { #[deprecated( since = "0.2.55", note = "Use the `mach2` crate instead", )] #[allow(deprecated)] pub const $id: $ty = $expr; }; ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => { $( deprecated_mach!( pub const $id: $ty = $expr; ); )* }; (pub type $id:ident = $ty:ty;) => { #[deprecated( since = "0.2.55", note = "Use the `mach2` crate instead", )] #[allow(deprecated)] pub type $id = $ty; }; ($(pub type $id:ident = $ty:ty;)*) => { $( deprecated_mach!( pub type $id = $ty; ); )* } } libc/src/hermit.rs0000644000175000017500000003565315105742312013754 0ustar bdrungbdrung//! Hermit C type definitions use crate::prelude::*; pub type intmax_t = i64; pub type uintmax_t = u64; pub type intptr_t = isize; pub type uintptr_t = usize; pub type size_t = usize; pub type ssize_t = isize; pub type ptrdiff_t = isize; pub type clockid_t = i32; pub type in_addr_t = u32; pub type in_port_t = u16; pub type mode_t = u32; pub type nfds_t = usize; pub type pid_t = i32; pub type sa_family_t = u8; pub type socklen_t = u32; pub type time_t = i64; s! { pub struct addrinfo { pub ai_flags: i32, pub ai_family: i32, pub ai_socktype: i32, pub ai_protocol: i32, pub ai_addrlen: socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } pub struct dirent64 { pub d_ino: u64, pub d_off: i64, pub d_reclen: u16, pub d_type: u8, pub d_name: [c_char; 256], } #[repr(align(4))] pub struct in6_addr { pub s6_addr: [u8; 16], } pub struct in_addr { pub s_addr: in_addr_t, } pub struct iovec { iov_base: *mut c_void, iov_len: usize, } pub struct pollfd { pub fd: i32, pub events: i16, pub revents: i16, } pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [c_char; 8], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, __ss_pad1: [u8; 6], __ss_align: i64, __ss_pad2: [u8; 112], } pub struct stat { pub st_dev: u64, pub st_ino: u64, pub st_nlink: u64, pub st_mode: mode_t, pub st_uid: u32, pub st_gid: u32, pub st_rdev: u64, pub st_size: i64, pub st_blksize: i64, pub st_blocks: i64, pub st_atim: timespec, pub st_mtim: timespec, pub st_ctim: timespec, } pub struct timespec { pub tv_sec: time_t, pub tv_nsec: i32, } } pub const AF_UNSPEC: i32 = 0; pub const AF_INET: i32 = 3; pub const AF_INET6: i32 = 1; pub const AF_VSOCK: i32 = 2; pub const CLOCK_REALTIME: clockid_t = 1; pub const CLOCK_MONOTONIC: clockid_t = 4; pub const DT_UNKNOWN: u8 = 0; pub const DT_FIFO: u8 = 1; pub const DT_CHR: u8 = 2; pub const DT_DIR: u8 = 4; pub const DT_BLK: u8 = 6; pub const DT_REG: u8 = 8; pub const DT_LNK: u8 = 10; pub const DT_SOCK: u8 = 12; pub const DT_WHT: u8 = 14; pub const EAI_AGAIN: i32 = 2; pub const EAI_BADFLAGS: i32 = 3; pub const EAI_FAIL: i32 = 4; pub const EAI_FAMILY: i32 = 5; pub const EAI_MEMORY: i32 = 6; pub const EAI_NODATA: i32 = 7; pub const EAI_NONAME: i32 = 8; pub const EAI_SERVICE: i32 = 9; pub const EAI_SOCKTYPE: i32 = 10; pub const EAI_SYSTEM: i32 = 11; pub const EAI_OVERFLOW: i32 = 14; pub const EFD_SEMAPHORE: i16 = 0o1; pub const EFD_NONBLOCK: i16 = 0o4000; pub const EFD_CLOEXEC: i16 = 0o40000; pub const F_DUPFD: i32 = 0; pub const F_GETFD: i32 = 1; pub const F_SETFD: i32 = 2; pub const F_GETFL: i32 = 3; pub const F_SETFL: i32 = 4; pub const FD_CLOEXEC: i32 = 1; pub const FIONBIO: i32 = 0x8008667e; pub const FUTEX_RELATIVE_TIMEOUT: u32 = 1; pub const IP_TOS: i32 = 1; pub const IP_TTL: i32 = 2; pub const IP_ADD_MEMBERSHIP: i32 = 3; pub const IP_DROP_MEMBERSHIP: i32 = 4; pub const IP_MULTICAST_TTL: i32 = 5; pub const IP_MULTICAST_LOOP: i32 = 7; pub const IPPROTO_IP: i32 = 0; pub const IPPROTO_TCP: i32 = 6; pub const IPPROTO_UDP: i32 = 17; pub const IPPROTO_IPV6: i32 = 41; pub const IPV6_ADD_MEMBERSHIP: i32 = 12; pub const IPV6_DROP_MEMBERSHIP: i32 = 13; pub const IPV6_MULTICAST_LOOP: i32 = 19; pub const IPV6_V6ONLY: i32 = 27; pub const MSG_PEEK: i32 = 1; pub const O_RDONLY: i32 = 0o0; pub const O_WRONLY: i32 = 0o1; pub const O_RDWR: i32 = 0o2; pub const O_CREAT: i32 = 0o100; pub const O_EXCL: i32 = 0o200; pub const O_TRUNC: i32 = 0o1000; pub const O_APPEND: i32 = 0o2000; pub const O_NONBLOCK: i32 = 0o4000; pub const O_DIRECTORY: i32 = 0o200000; pub const POLLIN: i16 = 0x1; pub const POLLPRI: i16 = 0x2; pub const POLLOUT: i16 = 0x4; pub const POLLERR: i16 = 0x8; pub const POLLHUP: i16 = 0x10; pub const POLLNVAL: i16 = 0x20; pub const POLLRDNORM: i16 = 0x040; pub const POLLRDBAND: i16 = 0x080; pub const POLLWRNORM: i16 = 0x0100; pub const POLLWRBAND: i16 = 0x0200; pub const POLLRDHUP: i16 = 0x2000; pub const S_IRWXU: mode_t = 0o0700; pub const S_IRUSR: mode_t = 0o0400; pub const S_IWUSR: mode_t = 0o0200; pub const S_IXUSR: mode_t = 0o0100; pub const S_IRWXG: mode_t = 0o0070; pub const S_IRGRP: mode_t = 0o0040; pub const S_IWGRP: mode_t = 0o0020; pub const S_IXGRP: mode_t = 0o0010; pub const S_IRWXO: mode_t = 0o0007; pub const S_IROTH: mode_t = 0o0004; pub const S_IWOTH: mode_t = 0o0002; pub const S_IXOTH: mode_t = 0o0001; pub const S_IFMT: mode_t = 0o17_0000; pub const S_IFSOCK: mode_t = 0o14_0000; pub const S_IFLNK: mode_t = 0o12_0000; pub const S_IFREG: mode_t = 0o10_0000; pub const S_IFBLK: mode_t = 0o6_0000; pub const S_IFDIR: mode_t = 0o4_0000; pub const S_IFCHR: mode_t = 0o2_0000; pub const S_IFIFO: mode_t = 0o1_0000; pub const SHUT_RD: i32 = 0; pub const SHUT_WR: i32 = 1; pub const SHUT_RDWR: i32 = 2; pub const SO_REUSEADDR: i32 = 0x0004; pub const SO_KEEPALIVE: i32 = 0x0008; pub const SO_BROADCAST: i32 = 0x0020; pub const SO_LINGER: i32 = 0x0080; pub const SO_SNDBUF: i32 = 0x1001; pub const SO_RCVBUF: i32 = 0x1002; pub const SO_SNDTIMEO: i32 = 0x1005; pub const SO_RCVTIMEO: i32 = 0x1006; pub const SO_ERROR: i32 = 0x1007; pub const SOCK_STREAM: i32 = 1; pub const SOCK_DGRAM: i32 = 2; pub const SOCK_NONBLOCK: i32 = 0o4000; pub const SOCK_CLOEXEC: i32 = 0o40000; pub const SOL_SOCKET: i32 = 4095; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const TCP_NODELAY: i32 = 1; pub const EPERM: i32 = 1; pub const ENOENT: i32 = 2; pub const ESRCH: i32 = 3; pub const EINTR: i32 = 4; pub const EIO: i32 = 5; pub const ENXIO: i32 = 6; pub const E2BIG: i32 = 7; pub const ENOEXEC: i32 = 8; pub const EBADF: i32 = 9; pub const ECHILD: i32 = 10; pub const EAGAIN: i32 = 11; pub const ENOMEM: i32 = 12; pub const EACCES: i32 = 13; pub const EFAULT: i32 = 14; pub const ENOTBLK: i32 = 15; pub const EBUSY: i32 = 16; pub const EEXIST: i32 = 17; pub const EXDEV: i32 = 18; pub const ENODEV: i32 = 19; pub const ENOTDIR: i32 = 20; pub const EISDIR: i32 = 21; pub const EINVAL: i32 = 22; pub const ENFILE: i32 = 23; pub const EMFILE: i32 = 24; pub const ENOTTY: i32 = 25; pub const ETXTBSY: i32 = 26; pub const EFBIG: i32 = 27; pub const ENOSPC: i32 = 28; pub const ESPIPE: i32 = 29; pub const EROFS: i32 = 30; pub const EMLINK: i32 = 31; pub const EPIPE: i32 = 32; pub const EDOM: i32 = 33; pub const ERANGE: i32 = 34; pub const EDEADLK: i32 = 35; pub const ENAMETOOLONG: i32 = 36; pub const ENOLCK: i32 = 37; pub const ENOSYS: i32 = 38; pub const ENOTEMPTY: i32 = 39; pub const ELOOP: i32 = 40; pub const EWOULDBLOCK: i32 = EAGAIN; pub const ENOMSG: i32 = 42; pub const EIDRM: i32 = 43; pub const ECHRNG: i32 = 44; pub const EL2NSYNC: i32 = 45; pub const EL3HLT: i32 = 46; pub const EL3RST: i32 = 47; pub const ELNRNG: i32 = 48; pub const EUNATCH: i32 = 49; pub const ENOCSI: i32 = 50; pub const EL2HLT: i32 = 51; pub const EBADE: i32 = 52; pub const EBADR: i32 = 53; pub const EXFULL: i32 = 54; pub const ENOANO: i32 = 55; pub const EBADRQC: i32 = 56; pub const EBADSLT: i32 = 57; pub const EDEADLOCK: i32 = EDEADLK; pub const EBFONT: i32 = 59; pub const ENOSTR: i32 = 60; pub const ENODATA: i32 = 61; pub const ETIME: i32 = 62; pub const ENOSR: i32 = 63; pub const ENONET: i32 = 64; pub const ENOPKG: i32 = 65; pub const EREMOTE: i32 = 66; pub const ENOLINK: i32 = 67; pub const EADV: i32 = 68; pub const ESRMNT: i32 = 69; pub const ECOMM: i32 = 70; pub const EPROTO: i32 = 71; pub const EMULTIHOP: i32 = 72; pub const EDOTDOT: i32 = 73; pub const EBADMSG: i32 = 74; pub const EOVERFLOW: i32 = 75; pub const ENOTUNIQ: i32 = 76; pub const EBADFD: i32 = 77; pub const EREMCHG: i32 = 78; pub const ELIBACC: i32 = 79; pub const ELIBBAD: i32 = 80; pub const ELIBSCN: i32 = 81; pub const ELIBMAX: i32 = 82; pub const ELIBEXEC: i32 = 83; pub const EILSEQ: i32 = 84; pub const ERESTART: i32 = 85; pub const ESTRPIPE: i32 = 86; pub const EUSERS: i32 = 87; pub const ENOTSOCK: i32 = 88; pub const EDESTADDRREQ: i32 = 89; pub const EMSGSIZE: i32 = 90; pub const EPROTOTYPE: i32 = 91; pub const ENOPROTOOPT: i32 = 92; pub const EPROTONOSUPPORT: i32 = 93; pub const ESOCKTNOSUPPORT: i32 = 94; pub const EOPNOTSUPP: i32 = 95; pub const EPFNOSUPPORT: i32 = 96; pub const EAFNOSUPPORT: i32 = 97; pub const EADDRINUSE: i32 = 98; pub const EADDRNOTAVAIL: i32 = 99; pub const ENETDOWN: i32 = 100; pub const ENETUNREACH: i32 = 101; pub const ENETRESET: i32 = 102; pub const ECONNABORTED: i32 = 103; pub const ECONNRESET: i32 = 104; pub const ENOBUFS: i32 = 105; pub const EISCONN: i32 = 106; pub const ENOTCONN: i32 = 107; pub const ESHUTDOWN: i32 = 108; pub const ETOOMANYREFS: i32 = 109; pub const ETIMEDOUT: i32 = 110; pub const ECONNREFUSED: i32 = 111; pub const EHOSTDOWN: i32 = 112; pub const EHOSTUNREACH: i32 = 113; pub const EALREADY: i32 = 114; pub const EINPROGRESS: i32 = 115; pub const ESTALE: i32 = 116; pub const EUCLEAN: i32 = 117; pub const ENOTNAM: i32 = 118; pub const ENAVAIL: i32 = 119; pub const EISNAM: i32 = 120; pub const EREMOTEIO: i32 = 121; pub const EDQUOT: i32 = 122; pub const ENOMEDIUM: i32 = 123; pub const EMEDIUMTYPE: i32 = 124; pub const ECANCELED: i32 = 125; pub const ENOKEY: i32 = 126; pub const EKEYEXPIRED: i32 = 127; pub const EKEYREVOKED: i32 = 128; pub const EKEYREJECTED: i32 = 129; pub const EOWNERDEAD: i32 = 130; pub const ENOTRECOVERABLE: i32 = 131; pub const ERFKILL: i32 = 132; pub const EHWPOISON: i32 = 133; extern "C" { #[link_name = "sys_alloc"] pub fn alloc(size: usize, align: usize) -> *mut u8; #[link_name = "sys_alloc_zeroed"] pub fn alloc_zeroed(size: usize, align: usize) -> *mut u8; #[link_name = "sys_realloc"] pub fn realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8; #[link_name = "sys_dealloc"] pub fn dealloc(ptr: *mut u8, size: usize, align: usize); #[link_name = "sys_exit"] pub fn exit(status: i32) -> !; #[link_name = "sys_abort"] pub fn abort() -> !; #[link_name = "sys_errno"] pub fn errno() -> i32; #[link_name = "sys_clock_gettime"] pub fn clock_gettime(clockid: clockid_t, tp: *mut timespec) -> i32; #[link_name = "sys_nanosleep"] pub fn nanosleep(req: *const timespec) -> i32; #[link_name = "sys_available_parallelism"] pub fn available_parallelism() -> usize; #[link_name = "sys_futex_wait"] pub fn futex_wait( address: *mut u32, expected: u32, timeout: *const timespec, flags: u32, ) -> i32; #[link_name = "sys_futex_wake"] pub fn futex_wake(address: *mut u32, count: i32) -> i32; #[link_name = "sys_stat"] pub fn stat(path: *const c_char, stat: *mut stat) -> i32; #[link_name = "sys_fstat"] pub fn fstat(fd: i32, stat: *mut stat) -> i32; #[link_name = "sys_lstat"] pub fn lstat(path: *const c_char, stat: *mut stat) -> i32; #[link_name = "sys_open"] pub fn open(path: *const c_char, flags: i32, mode: mode_t) -> i32; #[link_name = "sys_unlink"] pub fn unlink(path: *const c_char) -> i32; #[link_name = "sys_mkdir"] pub fn mkdir(path: *const c_char, mode: mode_t) -> i32; #[link_name = "sys_rmdir"] pub fn rmdir(path: *const c_char) -> i32; #[link_name = "sys_read"] pub fn read(fd: i32, buf: *mut u8, len: usize) -> isize; #[link_name = "sys_write"] pub fn write(fd: i32, buf: *const u8, len: usize) -> isize; #[link_name = "sys_readv"] pub fn readv(fd: i32, iov: *const iovec, iovcnt: usize) -> isize; #[link_name = "sys_writev"] pub fn writev(fd: i32, iov: *const iovec, iovcnt: usize) -> isize; #[link_name = "sys_close"] pub fn close(fd: i32) -> i32; #[link_name = "sys_dup"] pub fn dup(fd: i32) -> i32; #[link_name = "sys_fcntl"] pub fn fcntl(fd: i32, cmd: i32, arg: i32) -> i32; #[link_name = "sys_getdents64"] pub fn getdents64(fd: i32, dirp: *mut dirent64, count: usize) -> isize; #[link_name = "sys_getaddrinfo"] pub fn getaddrinfo( nodename: *const c_char, servname: *const c_char, hints: *const addrinfo, res: *mut *mut addrinfo, ) -> i32; #[link_name = "sys_freeaddrinfo"] pub fn freeaddrinfo(ai: *mut addrinfo); #[link_name = "sys_socket"] pub fn socket(domain: i32, ty: i32, protocol: i32) -> i32; #[link_name = "sys_bind"] pub fn bind(sockfd: i32, addr: *const sockaddr, addrlen: socklen_t) -> i32; #[link_name = "sys_listen"] pub fn listen(sockfd: i32, backlog: i32) -> i32; #[link_name = "sys_accept"] pub fn accept(sockfd: i32, addr: *mut sockaddr, addrlen: *mut socklen_t) -> i32; #[link_name = "sys_connect"] pub fn connect(sockfd: i32, addr: *const sockaddr, addrlen: socklen_t) -> i32; #[link_name = "sys_recv"] pub fn recv(sockfd: i32, buf: *mut u8, len: usize, flags: i32) -> isize; #[link_name = "sys_recvfrom"] pub fn recvfrom( sockfd: i32, buf: *mut c_void, len: usize, flags: i32, addr: *mut sockaddr, addrlen: *mut socklen_t, ) -> isize; #[link_name = "sys_send"] pub fn send(sockfd: i32, buf: *const c_void, len: usize, flags: i32) -> isize; #[link_name = "sys_sendto"] pub fn sendto( sockfd: i32, buf: *const c_void, len: usize, flags: i32, to: *const sockaddr, tolen: socklen_t, ) -> isize; #[link_name = "sys_getpeername"] pub fn getpeername(sockfd: i32, addr: *mut sockaddr, addrlen: *mut socklen_t) -> i32; #[link_name = "sys_getsockname"] pub fn getsockname(sockfd: i32, addr: *mut sockaddr, addrlen: *mut socklen_t) -> i32; #[link_name = "sys_getsockopt"] pub fn getsockopt( sockfd: i32, level: i32, optname: i32, optval: *mut c_void, optlen: *mut socklen_t, ) -> i32; #[link_name = "sys_setsockopt"] pub fn setsockopt( sockfd: i32, level: i32, optname: i32, optval: *const c_void, optlen: socklen_t, ) -> i32; #[link_name = "sys_ioctl"] pub fn ioctl(sockfd: i32, cmd: i32, argp: *mut c_void) -> i32; #[link_name = "sys_shutdown"] pub fn shutdown(sockfd: i32, how: i32) -> i32; #[link_name = "sys_eventfd"] pub fn eventfd(initval: u64, flags: i16) -> i32; #[link_name = "sys_poll"] pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: i32) -> i32; } libc/src/unix/0000775000175000017500000000000015105742312013067 5ustar bdrungbdrunglibc/src/unix/hurd/0000775000175000017500000000000015105742312014031 5ustar bdrungbdrunglibc/src/unix/hurd/mod.rs0000644000175000017500000045702515105742312015171 0ustar bdrungbdrung#![allow(dead_code)] use crate::c_schar; use crate::prelude::*; // types pub type __s16_type = c_short; pub type __u16_type = c_ushort; pub type __s32_type = c_int; pub type __u32_type = c_uint; pub type __slongword_type = c_long; pub type __ulongword_type = c_ulong; pub type __u_char = c_uchar; pub type __u_short = c_ushort; pub type __u_int = c_uint; pub type __u_long = c_ulong; pub type __int8_t = c_schar; pub type __uint8_t = c_uchar; pub type __int16_t = c_short; pub type __uint16_t = c_ushort; pub type __int32_t = c_int; pub type __uint32_t = c_uint; pub type __int_least8_t = __int8_t; pub type __uint_least8_t = __uint8_t; pub type __int_least16_t = __int16_t; pub type __uint_least16_t = __uint16_t; pub type __int_least32_t = __int32_t; pub type __uint_least32_t = __uint32_t; pub type __int_least64_t = __int64_t; pub type __uint_least64_t = __uint64_t; pub type __dev_t = __uword_type; pub type __uid_t = __u32_type; pub type __gid_t = __u32_type; pub type __ino_t = __ulongword_type; pub type __ino64_t = __uquad_type; pub type __mode_t = __u32_type; pub type __nlink_t = __uword_type; pub type __off_t = __slongword_type; pub type __off64_t = __squad_type; pub type __pid_t = __s32_type; pub type __rlim_t = __ulongword_type; pub type __rlim64_t = __uquad_type; pub type __blkcnt_t = __slongword_type; pub type __blkcnt64_t = __squad_type; pub type __fsblkcnt_t = __ulongword_type; pub type __fsblkcnt64_t = __uquad_type; pub type __fsfilcnt_t = __ulongword_type; pub type __fsfilcnt64_t = __uquad_type; pub type __fsword_t = __sword_type; pub type __id_t = __u32_type; pub type __clock_t = __slongword_type; pub type __time_t = __slongword_type; pub type __useconds_t = __u32_type; pub type __suseconds_t = __slongword_type; pub type __suseconds64_t = __squad_type; pub type __daddr_t = __s32_type; pub type __key_t = __s32_type; pub type __clockid_t = __s32_type; pub type __timer_t = __uword_type; pub type __blksize_t = __slongword_type; pub type __fsid_t = __uquad_type; pub type __ssize_t = __sword_type; pub type __syscall_slong_t = __slongword_type; pub type __syscall_ulong_t = __ulongword_type; pub type __cpu_mask = __ulongword_type; pub type __loff_t = __off64_t; pub type __caddr_t = *mut c_char; pub type __intptr_t = __sword_type; pub type __ptrdiff_t = __sword_type; pub type __socklen_t = __u32_type; pub type __sig_atomic_t = c_int; pub type __time64_t = __int64_t; pub type wchar_t = c_int; pub type wint_t = c_uint; pub type gid_t = __gid_t; pub type uid_t = __uid_t; pub type off_t = __off_t; pub type off64_t = __off64_t; pub type useconds_t = __useconds_t; pub type pid_t = __pid_t; pub type socklen_t = __socklen_t; pub type in_addr_t = u32; pub type _Float32 = f32; pub type _Float64 = f64; pub type _Float32x = f64; pub type _Float64x = f64; pub type __locale_t = *mut __locale_struct; pub type locale_t = __locale_t; pub type u_char = __u_char; pub type u_short = __u_short; pub type u_int = __u_int; pub type u_long = __u_long; pub type quad_t = __quad_t; pub type u_quad_t = __u_quad_t; pub type fsid_t = __fsid_t; pub type loff_t = __loff_t; pub type ino_t = __ino_t; pub type ino64_t = __ino64_t; pub type dev_t = __dev_t; pub type mode_t = __mode_t; pub type nlink_t = __nlink_t; pub type id_t = __id_t; pub type daddr_t = __daddr_t; pub type caddr_t = __caddr_t; pub type key_t = __key_t; pub type clock_t = __clock_t; pub type clockid_t = __clockid_t; pub type time_t = __time_t; pub type timer_t = __timer_t; pub type suseconds_t = __suseconds_t; pub type ulong = c_ulong; pub type ushort = c_ushort; pub type uint = c_uint; pub type u_int8_t = __uint8_t; pub type u_int16_t = __uint16_t; pub type u_int32_t = __uint32_t; pub type u_int64_t = __uint64_t; pub type register_t = c_int; pub type __sigset_t = c_ulong; pub type sigset_t = __sigset_t; pub type __fd_mask = c_long; pub type fd_mask = __fd_mask; pub type blksize_t = __blksize_t; pub type blkcnt_t = __blkcnt_t; pub type fsblkcnt_t = __fsblkcnt_t; pub type fsfilcnt_t = __fsfilcnt_t; pub type blkcnt64_t = __blkcnt64_t; pub type fsblkcnt64_t = __fsblkcnt64_t; pub type fsfilcnt64_t = __fsfilcnt64_t; pub type __pthread_spinlock_t = c_int; pub type __tss_t = c_int; pub type __thrd_t = c_long; pub type __pthread_t = c_long; pub type pthread_t = __pthread_t; pub type __pthread_process_shared = c_uint; pub type __pthread_inheritsched = c_uint; pub type __pthread_contentionscope = c_uint; pub type __pthread_detachstate = c_uint; pub type pthread_attr_t = __pthread_attr; pub type __pthread_mutex_protocol = c_uint; pub type __pthread_mutex_type = c_uint; pub type __pthread_mutex_robustness = c_uint; pub type pthread_mutexattr_t = __pthread_mutexattr; pub type pthread_mutex_t = __pthread_mutex; pub type pthread_condattr_t = __pthread_condattr; pub type pthread_cond_t = __pthread_cond; pub type pthread_spinlock_t = __pthread_spinlock_t; pub type pthread_rwlockattr_t = __pthread_rwlockattr; pub type pthread_rwlock_t = __pthread_rwlock; pub type pthread_barrierattr_t = __pthread_barrierattr; pub type pthread_barrier_t = __pthread_barrier; pub type __pthread_key = c_int; pub type pthread_key_t = __pthread_key; pub type pthread_once_t = __pthread_once; pub type __rlimit_resource = c_uint; pub type __rlimit_resource_t = __rlimit_resource; pub type rlim_t = __rlim_t; pub type rlim64_t = __rlim64_t; pub type __rusage_who = c_int; pub type __priority_which = c_uint; pub type sa_family_t = c_uchar; pub type in_port_t = u16; pub type __sigval_t = crate::sigval; pub type sigevent_t = sigevent; pub type nfds_t = c_ulong; pub type tcflag_t = c_uint; pub type cc_t = c_uchar; pub type speed_t = c_int; pub type sigval_t = crate::sigval; pub type greg_t = c_int; pub type gregset_t = [greg_t; 19usize]; pub type __ioctl_dir = c_uint; pub type __ioctl_datum = c_uint; pub type __error_t_codes = c_int; pub type int_least8_t = __int_least8_t; pub type int_least16_t = __int_least16_t; pub type int_least32_t = __int_least32_t; pub type int_least64_t = __int_least64_t; pub type uint_least8_t = __uint_least8_t; pub type uint_least16_t = __uint_least16_t; pub type uint_least32_t = __uint_least32_t; pub type uint_least64_t = __uint_least64_t; pub type int_fast8_t = c_schar; pub type uint_fast8_t = c_uchar; pub type intmax_t = __intmax_t; pub type uintmax_t = __uintmax_t; pub type tcp_seq = u32; pub type tcp_ca_state = c_uint; pub type idtype_t = c_uint; pub type mqd_t = c_int; pub type Lmid_t = c_long; pub type regoff_t = c_int; pub type nl_item = c_int; pub type iconv_t = *mut c_void; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos64_t {} // FIXME(hurd): fill this out with a struct impl Copy for fpos64_t {} impl Clone for fpos64_t { fn clone(&self) -> fpos64_t { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } // structs s! { pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: c_int, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, pub imr_sourceaddr: in_addr, } pub struct sockaddr { pub sa_len: c_uchar, pub sa_family: sa_family_t, pub sa_data: [c_char; 14usize], } pub struct in_addr { pub s_addr: in_addr_t, } pub struct sockaddr_in { pub sin_len: c_uchar, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_uchar; 8usize], } pub struct sockaddr_in6 { pub sin6_len: c_uchar, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_un { pub sun_len: c_uchar, pub sun_family: sa_family_t, pub sun_path: [c_char; 108usize], } pub struct sockaddr_storage { pub ss_len: c_uchar, pub ss_family: sa_family_t, pub __ss_padding: [c_char; 122usize], pub __ss_align: __uint32_t, } pub struct sockaddr_at { pub _address: u8, } pub struct sockaddr_ax25 { pub _address: u8, } pub struct sockaddr_x25 { pub _address: u8, } pub struct sockaddr_dl { pub _address: u8, } pub struct sockaddr_eon { pub _address: u8, } pub struct sockaddr_inarp { pub _address: u8, } pub struct sockaddr_ipx { pub _address: u8, } pub struct sockaddr_iso { pub _address: u8, } pub struct sockaddr_ns { pub _address: u8, } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: crate::socklen_t, pub ai_addr: *mut sockaddr, pub ai_canonname: *mut c_char, pub ai_next: *mut addrinfo, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct dirent { pub d_ino: __ino_t, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_namlen: c_uchar, pub d_name: [c_char; 1usize], } pub struct dirent64 { pub d_ino: __ino64_t, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_namlen: c_uchar, pub d_name: [c_char; 1usize], } pub struct fd_set { pub fds_bits: [__fd_mask; 8usize], } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_cc: [crate::cc_t; 20usize], pub __ispeed: crate::speed_t, pub __ospeed: crate::speed_t, } pub struct mallinfo { pub arena: c_int, pub ordblks: c_int, pub smblks: c_int, pub hblks: c_int, pub hblkhd: c_int, pub usmblks: c_int, pub fsmblks: c_int, pub uordblks: c_int, pub fordblks: c_int, pub keepcost: c_int, } pub struct mallinfo2 { pub arena: size_t, pub ordblks: size_t, pub smblks: size_t, pub hblks: size_t, pub hblkhd: size_t, pub usmblks: size_t, pub fsmblks: size_t, pub uordblks: size_t, pub fordblks: size_t, pub keepcost: size_t, } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: __sigset_t, pub sa_flags: c_int, } pub struct sigevent { pub sigev_value: crate::sigval, pub sigev_signo: c_int, pub sigev_notify: c_int, __unused1: *mut c_void, //actually a function pointer pub sigev_notify_attributes: *mut pthread_attr_t, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, pub si_pid: __pid_t, pub si_uid: __uid_t, pub si_addr: *mut c_void, pub si_status: c_int, pub si_band: c_long, pub si_value: crate::sigval, } pub struct timespec { pub tv_sec: __time_t, pub tv_nsec: __syscall_slong_t, } pub struct __timeval { pub tv_sec: i32, pub tv_usec: i32, } pub struct __locale_data { pub _address: u8, } pub struct stat { pub st_fstype: c_int, pub st_dev: __fsid_t, /* Actually st_fsid */ pub st_ino: __ino_t, pub st_gen: c_uint, pub st_rdev: __dev_t, pub st_mode: __mode_t, pub st_nlink: __nlink_t, pub st_uid: __uid_t, pub st_gid: __gid_t, pub st_size: __off_t, pub st_atim: crate::timespec, pub st_mtim: crate::timespec, pub st_ctim: crate::timespec, pub st_blksize: __blksize_t, pub st_blocks: __blkcnt_t, pub st_author: __uid_t, pub st_flags: c_uint, pub st_spare: [c_int; 11usize], } pub struct stat64 { pub st_fstype: c_int, pub st_dev: __fsid_t, /* Actually st_fsid */ pub st_ino: __ino64_t, pub st_gen: c_uint, pub st_rdev: __dev_t, pub st_mode: __mode_t, pub st_nlink: __nlink_t, pub st_uid: __uid_t, pub st_gid: __gid_t, pub st_size: __off64_t, pub st_atim: crate::timespec, pub st_mtim: crate::timespec, pub st_ctim: crate::timespec, pub st_blksize: __blksize_t, pub st_blocks: __blkcnt64_t, pub st_author: __uid_t, pub st_flags: c_uint, pub st_spare: [c_int; 8usize], } pub struct statx { pub stx_mask: u32, pub stx_blksize: u32, pub stx_attributes: u64, pub stx_nlink: u32, pub stx_uid: u32, pub stx_gid: u32, pub stx_mode: u16, __statx_pad1: [u16; 1], pub stx_ino: u64, pub stx_size: u64, pub stx_blocks: u64, pub stx_attributes_mask: u64, pub stx_atime: crate::statx_timestamp, pub stx_btime: crate::statx_timestamp, pub stx_ctime: crate::statx_timestamp, pub stx_mtime: crate::statx_timestamp, pub stx_rdev_major: u32, pub stx_rdev_minor: u32, pub stx_dev_major: u32, pub stx_dev_minor: u32, __statx_pad2: [u64; 14], } pub struct statx_timestamp { pub tv_sec: i64, pub tv_nsec: u32, pub __statx_timestamp_pad1: [i32; 1], } pub struct statfs { pub f_type: c_uint, pub f_bsize: c_ulong, pub f_blocks: __fsblkcnt_t, pub f_bfree: __fsblkcnt_t, pub f_bavail: __fsblkcnt_t, pub f_files: __fsblkcnt_t, pub f_ffree: __fsblkcnt_t, pub f_fsid: __fsid_t, pub f_namelen: c_ulong, pub f_favail: __fsfilcnt_t, pub f_frsize: c_ulong, pub f_flag: c_ulong, pub f_spare: [c_uint; 3usize], } pub struct statfs64 { pub f_type: c_uint, pub f_bsize: c_ulong, pub f_blocks: __fsblkcnt64_t, pub f_bfree: __fsblkcnt64_t, pub f_bavail: __fsblkcnt64_t, pub f_files: __fsblkcnt64_t, pub f_ffree: __fsblkcnt64_t, pub f_fsid: __fsid_t, pub f_namelen: c_ulong, pub f_favail: __fsfilcnt64_t, pub f_frsize: c_ulong, pub f_flag: c_ulong, pub f_spare: [c_uint; 3usize], } pub struct statvfs { pub __f_type: c_uint, pub f_bsize: c_ulong, pub f_blocks: __fsblkcnt_t, pub f_bfree: __fsblkcnt_t, pub f_bavail: __fsblkcnt_t, pub f_files: __fsfilcnt_t, pub f_ffree: __fsfilcnt_t, pub f_fsid: __fsid_t, pub f_namemax: c_ulong, pub f_favail: __fsfilcnt_t, pub f_frsize: c_ulong, pub f_flag: c_ulong, pub f_spare: [c_uint; 3usize], } pub struct statvfs64 { pub __f_type: c_uint, pub f_bsize: c_ulong, pub f_blocks: __fsblkcnt64_t, pub f_bfree: __fsblkcnt64_t, pub f_bavail: __fsblkcnt64_t, pub f_files: __fsfilcnt64_t, pub f_ffree: __fsfilcnt64_t, pub f_fsid: __fsid_t, pub f_namemax: c_ulong, pub f_favail: __fsfilcnt64_t, pub f_frsize: c_ulong, pub f_flag: c_ulong, pub f_spare: [c_uint; 3usize], } pub struct aiocb { pub aio_fildes: c_int, pub aio_lio_opcode: c_int, pub aio_reqprio: c_int, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_sigevent: crate::sigevent, __next_prio: *mut aiocb, __abs_prio: c_int, __policy: c_int, __error_code: c_int, __return_value: ssize_t, pub aio_offset: off_t, #[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))] __unused1: [c_char; 4], __glibc_reserved: [c_char; 32], } pub struct mq_attr { pub mq_flags: c_long, pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_curmsgs: c_long, } pub struct __exit_status { pub e_termination: c_short, pub e_exit: c_short, } #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { __size: [c_char; 20usize], } pub struct __pthread { pub _address: u8, } pub struct __pthread_mutexattr { pub __prioceiling: c_int, pub __protocol: __pthread_mutex_protocol, pub __pshared: __pthread_process_shared, pub __mutex_type: __pthread_mutex_type, } pub struct __pthread_mutex { pub __lock: c_uint, pub __owner_id: c_uint, pub __cnt: c_uint, pub __shpid: c_int, pub __type: c_int, pub __flags: c_int, pub __reserved1: c_uint, pub __reserved2: c_uint, } pub struct __pthread_condattr { pub __pshared: __pthread_process_shared, pub __clock: __clockid_t, } pub struct __pthread_rwlockattr { pub __pshared: __pthread_process_shared, } pub struct __pthread_barrierattr { pub __pshared: __pthread_process_shared, } pub struct __pthread_once { pub __run: c_int, pub __lock: __pthread_spinlock_t, } pub struct __pthread_cond { pub __lock: __pthread_spinlock_t, pub __queue: *mut __pthread, pub __attr: *mut __pthread_condattr, pub __wrefs: c_uint, pub __data: *mut c_void, } pub struct __pthread_attr { pub __schedparam: sched_param, pub __stackaddr: *mut c_void, pub __stacksize: size_t, pub __guardsize: size_t, pub __detachstate: __pthread_detachstate, pub __inheritsched: __pthread_inheritsched, pub __contentionscope: __pthread_contentionscope, pub __schedpolicy: c_int, } pub struct __pthread_rwlock { pub __held: __pthread_spinlock_t, pub __lock: __pthread_spinlock_t, pub __readers: c_int, pub __readerqueue: *mut __pthread, pub __writerqueue: *mut __pthread, pub __attr: *mut __pthread_rwlockattr, pub __data: *mut c_void, } pub struct __pthread_barrier { pub __lock: __pthread_spinlock_t, pub __queue: *mut __pthread, pub __pending: c_uint, pub __count: c_uint, pub __attr: *mut __pthread_barrierattr, pub __data: *mut c_void, } pub struct seminfo { pub semmap: c_int, pub semmni: c_int, pub semmns: c_int, pub semmnu: c_int, pub semmsl: c_int, pub semopm: c_int, pub semume: c_int, pub semusz: c_int, pub semvmx: c_int, pub semaem: c_int, } pub struct _IO_FILE { _unused: [u8; 0], } pub struct sched_param { pub sched_priority: c_int, } pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: __uid_t, pub pw_gid: __gid_t, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct spwd { pub sp_namp: *mut c_char, pub sp_pwdp: *mut c_char, pub sp_lstchg: c_long, pub sp_min: c_long, pub sp_max: c_long, pub sp_warn: c_long, pub sp_inact: c_long, pub sp_expire: c_long, pub sp_flag: c_ulong, } pub struct itimerspec { pub it_interval: crate::timespec, pub it_value: crate::timespec, } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *const c_char, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, pub ifa_addr: *mut crate::sockaddr, pub ifa_netmask: *mut crate::sockaddr, pub ifa_ifu: *mut crate::sockaddr, // FIXME(union) This should be a union pub ifa_data: *mut c_void, } pub struct arpreq { pub arp_pa: crate::sockaddr, pub arp_ha: crate::sockaddr, pub arp_flags: c_int, pub arp_netmask: crate::sockaddr, pub arp_dev: [c_char; 16], } pub struct arpreq_old { pub arp_pa: crate::sockaddr, pub arp_ha: crate::sockaddr, pub arp_flags: c_int, pub arp_netmask: crate::sockaddr, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct arpd_request { pub req: c_ushort, pub ip: u32, pub dev: c_ulong, pub stamp: c_ulong, pub updated: c_ulong, pub ha: [c_uchar; crate::MAX_ADDR_LEN], } pub struct mmsghdr { pub msg_hdr: crate::msghdr, pub msg_len: c_uint, } pub struct ifreq { /// interface name, e.g. "en0" pub ifr_name: [c_char; crate::IFNAMSIZ], pub ifr_ifru: crate::sockaddr, } pub struct __locale_struct { pub __locales: [*mut __locale_data; 13usize], pub __ctype_b: *const c_ushort, pub __ctype_tolower: *const c_int, pub __ctype_toupper: *const c_int, pub __names: [*const c_char; 13usize], } pub struct utsname { pub sysname: [c_char; _UTSNAME_LENGTH], pub nodename: [c_char; _UTSNAME_LENGTH], pub release: [c_char; _UTSNAME_LENGTH], pub version: [c_char; _UTSNAME_LENGTH], pub machine: [c_char; _UTSNAME_LENGTH], pub domainname: [c_char; _UTSNAME_LENGTH], } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct dl_phdr_info { pub dlpi_addr: Elf_Addr, pub dlpi_name: *const c_char, pub dlpi_phdr: *const Elf_Phdr, pub dlpi_phnum: Elf_Half, pub dlpi_adds: c_ulonglong, pub dlpi_subs: c_ulonglong, pub dlpi_tls_modid: size_t, pub dlpi_tls_data: *mut c_void, } pub struct flock { #[cfg(target_pointer_width = "32")] pub l_type: c_int, #[cfg(target_pointer_width = "32")] pub l_whence: c_int, #[cfg(target_pointer_width = "64")] pub l_type: c_short, #[cfg(target_pointer_width = "64")] pub l_whence: c_short, pub l_start: __off_t, pub l_len: __off_t, pub l_pid: __pid_t, } pub struct flock64 { #[cfg(target_pointer_width = "32")] pub l_type: c_int, #[cfg(target_pointer_width = "32")] pub l_whence: c_int, #[cfg(target_pointer_width = "64")] pub l_type: c_short, #[cfg(target_pointer_width = "64")] pub l_whence: c_short, pub l_start: __off_t, pub l_len: __off64_t, pub l_pid: __pid_t, } pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct glob64_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct regex_t { __buffer: *mut c_void, __allocated: size_t, __used: size_t, __syntax: c_ulong, __fastmap: *mut c_char, __translate: *mut c_char, __re_nsub: size_t, __bitfield: u8, } pub struct cpu_set_t { #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] bits: [u32; 32], #[cfg(not(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] bits: [u64; 16], } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } // System V IPC pub struct msginfo { pub msgpool: c_int, pub msgmap: c_int, pub msgmax: c_int, pub msgmnb: c_int, pub msgmni: c_int, pub msgssz: c_int, pub msgtql: c_int, pub msgseg: c_ushort, } pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } pub struct mntent { pub mnt_fsname: *mut c_char, pub mnt_dir: *mut c_char, pub mnt_type: *mut c_char, pub mnt_opts: *mut c_char, pub mnt_freq: c_int, pub mnt_passno: c_int, } pub struct posix_spawn_file_actions_t { __allocated: c_int, __used: c_int, __actions: *mut c_int, __pad: [c_int; 16], } pub struct posix_spawnattr_t { __flags: c_short, __pgrp: crate::pid_t, __sd: crate::sigset_t, __ss: crate::sigset_t, __sp: crate::sched_param, __policy: c_int, __pad: [c_int; 16], } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct option { pub name: *const c_char, pub has_arg: c_int, pub flag: *mut c_int, pub val: c_int, } } s_no_extra_traits! { pub struct utmpx { pub ut_type: c_short, pub ut_pid: crate::pid_t, pub ut_line: [c_char; __UT_LINESIZE], pub ut_id: [c_char; 4], pub ut_user: [c_char; __UT_NAMESIZE], pub ut_host: [c_char; __UT_HOSTSIZE], pub ut_exit: __exit_status, #[cfg(any(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] pub ut_session: c_long, #[cfg(any(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] pub ut_tv: crate::timeval, #[cfg(not(any(all(target_pointer_width = "32", not(target_arch = "x86_64")))))] pub ut_session: i32, #[cfg(not(any(all(target_pointer_width = "32", not(target_arch = "x86_64")))))] pub ut_tv: __timeval, pub ut_addr_v6: [i32; 4], __glibc_reserved: [c_char; 20], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_user == other.ut_user && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_addr_v6 == other.ut_addr_v6 && self.__glibc_reserved == other.__glibc_reserved } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_line", &self.ut_line) .field("ut_id", &self.ut_id) .field("ut_user", &self.ut_user) // FIXME(debug): .field("ut_host", &self.ut_host) .field("ut_exit", &self.ut_exit) .field("ut_session", &self.ut_session) .field("ut_tv", &self.ut_tv) .field("ut_addr_v6", &self.ut_addr_v6) .field("__glibc_reserved", &self.__glibc_reserved) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_user.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_addr_v6.hash(state); self.__glibc_reserved.hash(state); } } } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { self.si_addr } pub unsafe fn si_value(&self) -> crate::sigval { self.si_value } pub unsafe fn si_pid(&self) -> crate::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> c_int { self.si_status } } // const // aio.h pub const AIO_CANCELED: c_int = 0; pub const AIO_NOTCANCELED: c_int = 1; pub const AIO_ALLDONE: c_int = 2; pub const LIO_READ: c_int = 0; pub const LIO_WRITE: c_int = 1; pub const LIO_NOP: c_int = 2; pub const LIO_WAIT: c_int = 0; pub const LIO_NOWAIT: c_int = 1; // glob.h pub const GLOB_ERR: c_int = 1 << 0; pub const GLOB_MARK: c_int = 1 << 1; pub const GLOB_NOSORT: c_int = 1 << 2; pub const GLOB_DOOFFS: c_int = 1 << 3; pub const GLOB_NOCHECK: c_int = 1 << 4; pub const GLOB_APPEND: c_int = 1 << 5; pub const GLOB_NOESCAPE: c_int = 1 << 6; pub const GLOB_NOSPACE: c_int = 1; pub const GLOB_ABORTED: c_int = 2; pub const GLOB_NOMATCH: c_int = 3; pub const GLOB_PERIOD: c_int = 1 << 7; pub const GLOB_ALTDIRFUNC: c_int = 1 << 9; pub const GLOB_BRACE: c_int = 1 << 10; pub const GLOB_NOMAGIC: c_int = 1 << 11; pub const GLOB_TILDE: c_int = 1 << 12; pub const GLOB_ONLYDIR: c_int = 1 << 13; pub const GLOB_TILDE_CHECK: c_int = 1 << 14; // ipc.h pub const IPC_PRIVATE: crate::key_t = 0; pub const IPC_CREAT: c_int = 0o1000; pub const IPC_EXCL: c_int = 0o2000; pub const IPC_NOWAIT: c_int = 0o4000; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 1; pub const IPC_STAT: c_int = 2; pub const IPC_INFO: c_int = 3; pub const MSG_STAT: c_int = 11; pub const MSG_INFO: c_int = 12; pub const MSG_NOERROR: c_int = 0o10000; pub const MSG_EXCEPT: c_int = 0o20000; // shm.h pub const SHM_R: c_int = 0o400; pub const SHM_W: c_int = 0o200; pub const SHM_RDONLY: c_int = 0o10000; pub const SHM_RND: c_int = 0o20000; pub const SHM_REMAP: c_int = 0o40000; pub const SHM_LOCK: c_int = 11; pub const SHM_UNLOCK: c_int = 12; // unistd.h pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const __FD_SETSIZE: usize = 256; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const F_OK: c_int = 0; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const SEEK_DATA: c_int = 3; pub const SEEK_HOLE: c_int = 4; pub const L_SET: c_int = 0; pub const L_INCR: c_int = 1; pub const L_XTND: c_int = 2; pub const F_ULOCK: c_int = 0; pub const F_LOCK: c_int = 1; pub const F_TLOCK: c_int = 2; pub const F_TEST: c_int = 3; pub const CLOSE_RANGE_CLOEXEC: c_int = 4; // stdio.h pub const EOF: c_int = -1; // stdlib.h pub const WNOHANG: c_int = 1; pub const WUNTRACED: c_int = 2; pub const WSTOPPED: c_int = 2; pub const WCONTINUED: c_int = 4; pub const WNOWAIT: c_int = 8; pub const WEXITED: c_int = 16; pub const __W_CONTINUED: c_int = 65535; pub const __WCOREFLAG: c_int = 128; pub const RAND_MAX: c_int = 2147483647; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const __LITTLE_ENDIAN: usize = 1234; pub const __BIG_ENDIAN: usize = 4321; pub const __PDP_ENDIAN: usize = 3412; pub const __BYTE_ORDER: usize = 1234; pub const __FLOAT_WORD_ORDER: usize = 1234; pub const LITTLE_ENDIAN: usize = 1234; pub const BIG_ENDIAN: usize = 4321; pub const PDP_ENDIAN: usize = 3412; pub const BYTE_ORDER: usize = 1234; // sys/select.h pub const FD_SETSIZE: usize = 256; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 32; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 28; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 24; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 16; pub const __SIZEOF_PTHREAD_COND_T: usize = 20; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_ONCE_T: usize = 8; pub const __PTHREAD_SPIN_LOCK_INITIALIZER: c_int = 0; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; // sys/resource.h pub const RLIM_INFINITY: crate::rlim_t = 2147483647; pub const RLIM64_INFINITY: crate::rlim64_t = 9223372036854775807; pub const RLIM_SAVED_MAX: crate::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: crate::rlim_t = RLIM_INFINITY; pub const PRIO_MIN: c_int = -20; pub const PRIO_MAX: c_int = 20; // pwd.h pub const NSS_BUFLEN_PASSWD: usize = 1024; // sys/socket.h pub const SOCK_TYPE_MASK: usize = 15; pub const PF_UNSPEC: c_int = 0; pub const PF_LOCAL: c_int = 1; pub const PF_UNIX: c_int = 1; pub const PF_FILE: c_int = 1; pub const PF_INET: c_int = 2; pub const PF_IMPLINK: c_int = 3; pub const PF_PUP: c_int = 4; pub const PF_CHAOS: c_int = 5; pub const PF_NS: c_int = 6; pub const PF_ISO: c_int = 7; pub const PF_OSI: c_int = 7; pub const PF_ECMA: c_int = 8; pub const PF_DATAKIT: c_int = 9; pub const PF_CCITT: c_int = 10; pub const PF_SNA: c_int = 11; pub const PF_DECnet: c_int = 12; pub const PF_DLI: c_int = 13; pub const PF_LAT: c_int = 14; pub const PF_HYLINK: c_int = 15; pub const PF_APPLETALK: c_int = 16; pub const PF_ROUTE: c_int = 17; pub const PF_XTP: c_int = 19; pub const PF_COIP: c_int = 20; pub const PF_CNT: c_int = 21; pub const PF_RTIP: c_int = 22; pub const PF_IPX: c_int = 23; pub const PF_SIP: c_int = 24; pub const PF_PIP: c_int = 25; pub const PF_INET6: c_int = 26; pub const PF_MAX: c_int = 27; pub const AF_UNSPEC: c_int = 0; pub const AF_LOCAL: c_int = 1; pub const AF_UNIX: c_int = 1; pub const AF_FILE: c_int = 1; pub const AF_INET: c_int = 2; pub const AF_IMPLINK: c_int = 3; pub const AF_PUP: c_int = 4; pub const AF_CHAOS: c_int = 5; pub const AF_NS: c_int = 6; pub const AF_ISO: c_int = 7; pub const AF_OSI: c_int = 7; pub const AF_ECMA: c_int = 8; pub const AF_DATAKIT: c_int = 9; pub const AF_CCITT: c_int = 10; pub const AF_SNA: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_DLI: c_int = 13; pub const AF_LAT: c_int = 14; pub const AF_HYLINK: c_int = 15; pub const AF_APPLETALK: c_int = 16; pub const AF_ROUTE: c_int = 17; pub const pseudo_AF_XTP: c_int = 19; pub const AF_COIP: c_int = 20; pub const AF_CNT: c_int = 21; pub const pseudo_AF_RTIP: c_int = 22; pub const AF_IPX: c_int = 23; pub const AF_SIP: c_int = 24; pub const pseudo_AF_PIP: c_int = 25; pub const AF_INET6: c_int = 26; pub const AF_MAX: c_int = 27; pub const SOMAXCONN: c_int = 4096; pub const _SS_SIZE: usize = 128; pub const CMGROUP_MAX: usize = 16; pub const SOL_SOCKET: c_int = 65535; // sys/time.h pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; pub const ITIMER_PROF: c_int = 2; // netinet/in.h pub const SOL_IP: c_int = 0; pub const SOL_TCP: c_int = 6; pub const SOL_UDP: c_int = 17; pub const SOL_IPV6: c_int = 41; pub const SOL_ICMPV6: c_int = 58; pub const IP_OPTIONS: c_int = 1; pub const IP_HDRINCL: c_int = 2; pub const IP_TOS: c_int = 3; pub const IP_TTL: c_int = 4; pub const IP_RECVOPTS: c_int = 5; pub const IP_RECVRETOPTS: c_int = 6; pub const IP_RECVDSTADDR: c_int = 7; pub const IP_RETOPTS: c_int = 8; pub const IP_MULTICAST_IF: c_int = 9; pub const IP_MULTICAST_TTL: c_int = 10; pub const IP_MULTICAST_LOOP: c_int = 11; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IPV6_ADDRFORM: c_int = 1; pub const IPV6_2292PKTINFO: c_int = 2; pub const IPV6_2292HOPOPTS: c_int = 3; pub const IPV6_2292DSTOPTS: c_int = 4; pub const IPV6_2292RTHDR: c_int = 5; pub const IPV6_2292PKTOPTIONS: c_int = 6; pub const IPV6_CHECKSUM: c_int = 7; pub const IPV6_2292HOPLIMIT: c_int = 8; pub const IPV6_RXINFO: c_int = 2; pub const IPV6_TXINFO: c_int = 2; pub const SCM_SRCINFO: c_int = 2; pub const IPV6_UNICAST_HOPS: c_int = 16; pub const IPV6_MULTICAST_IF: c_int = 17; pub const IPV6_MULTICAST_HOPS: c_int = 18; pub const IPV6_MULTICAST_LOOP: c_int = 19; pub const IPV6_JOIN_GROUP: c_int = 20; pub const IPV6_LEAVE_GROUP: c_int = 21; pub const IPV6_ROUTER_ALERT: c_int = 22; pub const IPV6_MTU_DISCOVER: c_int = 23; pub const IPV6_MTU: c_int = 24; pub const IPV6_RECVERR: c_int = 25; pub const IPV6_V6ONLY: c_int = 26; pub const IPV6_JOIN_ANYCAST: c_int = 27; pub const IPV6_LEAVE_ANYCAST: c_int = 28; pub const IPV6_RECVPKTINFO: c_int = 49; pub const IPV6_PKTINFO: c_int = 50; pub const IPV6_RECVHOPLIMIT: c_int = 51; pub const IPV6_HOPLIMIT: c_int = 52; pub const IPV6_RECVHOPOPTS: c_int = 53; pub const IPV6_HOPOPTS: c_int = 54; pub const IPV6_RTHDRDSTOPTS: c_int = 55; pub const IPV6_RECVRTHDR: c_int = 56; pub const IPV6_RTHDR: c_int = 57; pub const IPV6_RECVDSTOPTS: c_int = 58; pub const IPV6_DSTOPTS: c_int = 59; pub const IPV6_RECVPATHMTU: c_int = 60; pub const IPV6_PATHMTU: c_int = 61; pub const IPV6_DONTFRAG: c_int = 62; pub const IPV6_RECVTCLASS: c_int = 66; pub const IPV6_TCLASS: c_int = 67; pub const IPV6_ADDR_PREFERENCES: c_int = 72; pub const IPV6_MINHOPCOUNT: c_int = 73; pub const IPV6_ADD_MEMBERSHIP: c_int = 20; pub const IPV6_DROP_MEMBERSHIP: c_int = 21; pub const IPV6_RXHOPOPTS: c_int = 3; pub const IPV6_RXDSTOPTS: c_int = 4; pub const IPV6_RTHDR_LOOSE: c_int = 0; pub const IPV6_RTHDR_STRICT: c_int = 1; pub const IPV6_RTHDR_TYPE_0: c_int = 0; pub const IN_CLASSA_NET: u32 = 4278190080; pub const IN_CLASSA_NSHIFT: usize = 24; pub const IN_CLASSA_HOST: u32 = 16777215; pub const IN_CLASSA_MAX: u32 = 128; pub const IN_CLASSB_NET: u32 = 4294901760; pub const IN_CLASSB_NSHIFT: usize = 16; pub const IN_CLASSB_HOST: u32 = 65535; pub const IN_CLASSB_MAX: u32 = 65536; pub const IN_CLASSC_NET: u32 = 4294967040; pub const IN_CLASSC_NSHIFT: usize = 8; pub const IN_CLASSC_HOST: u32 = 255; pub const IN_LOOPBACKNET: u32 = 127; pub const INET_ADDRSTRLEN: usize = 16; pub const INET6_ADDRSTRLEN: usize = 46; // netinet/ip.h pub const IPTOS_TOS_MASK: u8 = 0x1E; pub const IPTOS_PREC_MASK: u8 = 0xE0; pub const IPTOS_ECN_NOT_ECT: u8 = 0x00; pub const IPTOS_LOWDELAY: u8 = 0x10; pub const IPTOS_THROUGHPUT: u8 = 0x08; pub const IPTOS_RELIABILITY: u8 = 0x04; pub const IPTOS_MINCOST: u8 = 0x02; pub const IPTOS_PREC_NETCONTROL: u8 = 0xe0; pub const IPTOS_PREC_INTERNETCONTROL: u8 = 0xc0; pub const IPTOS_PREC_CRITIC_ECP: u8 = 0xa0; pub const IPTOS_PREC_FLASHOVERRIDE: u8 = 0x80; pub const IPTOS_PREC_FLASH: u8 = 0x60; pub const IPTOS_PREC_IMMEDIATE: u8 = 0x40; pub const IPTOS_PREC_PRIORITY: u8 = 0x20; pub const IPTOS_PREC_ROUTINE: u8 = 0x00; pub const IPTOS_ECN_MASK: u8 = 0x03; pub const IPTOS_ECN_ECT1: u8 = 0x01; pub const IPTOS_ECN_ECT0: u8 = 0x02; pub const IPTOS_ECN_CE: u8 = 0x03; pub const IPOPT_COPY: u8 = 0x80; pub const IPOPT_CLASS_MASK: u8 = 0x60; pub const IPOPT_NUMBER_MASK: u8 = 0x1f; pub const IPOPT_CONTROL: u8 = 0x00; pub const IPOPT_RESERVED1: u8 = 0x20; pub const IPOPT_MEASUREMENT: u8 = 0x40; pub const IPOPT_RESERVED2: u8 = 0x60; pub const IPOPT_END: u8 = 0 | IPOPT_CONTROL; pub const IPOPT_NOOP: u8 = 1 | IPOPT_CONTROL; pub const IPOPT_SEC: u8 = 2 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_LSRR: u8 = 3 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_TIMESTAMP: u8 = 4 | IPOPT_MEASUREMENT; pub const IPOPT_RR: u8 = 7 | IPOPT_CONTROL; pub const IPOPT_SID: u8 = 8 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_SSRR: u8 = 9 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_RA: u8 = 20 | IPOPT_CONTROL | IPOPT_COPY; pub const IPVERSION: u8 = 4; pub const MAXTTL: u8 = 255; pub const IPDEFTTL: u8 = 64; pub const IPOPT_OPTVAL: u8 = 0; pub const IPOPT_OLEN: u8 = 1; pub const IPOPT_OFFSET: u8 = 2; pub const IPOPT_MINOFF: u8 = 4; pub const MAX_IPOPTLEN: u8 = 40; pub const IPOPT_NOP: u8 = IPOPT_NOOP; pub const IPOPT_EOL: u8 = IPOPT_END; pub const IPOPT_TS: u8 = IPOPT_TIMESTAMP; pub const IPOPT_TS_TSONLY: u8 = 0; pub const IPOPT_TS_TSANDADDR: u8 = 1; pub const IPOPT_TS_PRESPEC: u8 = 3; // net/if_arp.h pub const ARPOP_REQUEST: u16 = 1; pub const ARPOP_REPLY: u16 = 2; pub const ARPOP_RREQUEST: u16 = 3; pub const ARPOP_RREPLY: u16 = 4; pub const ARPOP_InREQUEST: u16 = 8; pub const ARPOP_InREPLY: u16 = 9; pub const ARPOP_NAK: u16 = 10; pub const MAX_ADDR_LEN: usize = 7; pub const ARPD_UPDATE: c_ushort = 0x01; pub const ARPD_LOOKUP: c_ushort = 0x02; pub const ARPD_FLUSH: c_ushort = 0x03; pub const ATF_MAGIC: c_int = 0x80; pub const ATF_NETMASK: c_int = 0x20; pub const ATF_DONTPUB: c_int = 0x40; pub const ARPHRD_NETROM: u16 = 0; pub const ARPHRD_ETHER: u16 = 1; pub const ARPHRD_EETHER: u16 = 2; pub const ARPHRD_AX25: u16 = 3; pub const ARPHRD_PRONET: u16 = 4; pub const ARPHRD_CHAOS: u16 = 5; pub const ARPHRD_IEEE802: u16 = 6; pub const ARPHRD_ARCNET: u16 = 7; pub const ARPHRD_APPLETLK: u16 = 8; pub const ARPHRD_DLCI: u16 = 15; pub const ARPHRD_ATM: u16 = 19; pub const ARPHRD_METRICOM: u16 = 23; pub const ARPHRD_IEEE1394: u16 = 24; pub const ARPHRD_EUI64: u16 = 27; pub const ARPHRD_INFINIBAND: u16 = 32; pub const ARPHRD_SLIP: u16 = 256; pub const ARPHRD_CSLIP: u16 = 257; pub const ARPHRD_SLIP6: u16 = 258; pub const ARPHRD_CSLIP6: u16 = 259; pub const ARPHRD_RSRVD: u16 = 260; pub const ARPHRD_ADAPT: u16 = 264; pub const ARPHRD_ROSE: u16 = 270; pub const ARPHRD_X25: u16 = 271; pub const ARPHRD_HWX25: u16 = 272; pub const ARPHRD_CAN: u16 = 280; pub const ARPHRD_PPP: u16 = 512; pub const ARPHRD_CISCO: u16 = 513; pub const ARPHRD_HDLC: u16 = ARPHRD_CISCO; pub const ARPHRD_LAPB: u16 = 516; pub const ARPHRD_DDCMP: u16 = 517; pub const ARPHRD_RAWHDLC: u16 = 518; pub const ARPHRD_TUNNEL: u16 = 768; pub const ARPHRD_TUNNEL6: u16 = 769; pub const ARPHRD_FRAD: u16 = 770; pub const ARPHRD_SKIP: u16 = 771; pub const ARPHRD_LOOPBACK: u16 = 772; pub const ARPHRD_LOCALTLK: u16 = 773; pub const ARPHRD_FDDI: u16 = 774; pub const ARPHRD_BIF: u16 = 775; pub const ARPHRD_SIT: u16 = 776; pub const ARPHRD_IPDDP: u16 = 777; pub const ARPHRD_IPGRE: u16 = 778; pub const ARPHRD_PIMREG: u16 = 779; pub const ARPHRD_HIPPI: u16 = 780; pub const ARPHRD_ASH: u16 = 781; pub const ARPHRD_ECONET: u16 = 782; pub const ARPHRD_IRDA: u16 = 783; pub const ARPHRD_FCPP: u16 = 784; pub const ARPHRD_FCAL: u16 = 785; pub const ARPHRD_FCPL: u16 = 786; pub const ARPHRD_FCFABRIC: u16 = 787; pub const ARPHRD_IEEE802_TR: u16 = 800; pub const ARPHRD_IEEE80211: u16 = 801; pub const ARPHRD_IEEE80211_PRISM: u16 = 802; pub const ARPHRD_IEEE80211_RADIOTAP: u16 = 803; pub const ARPHRD_IEEE802154: u16 = 804; pub const ARPHRD_VOID: u16 = 0xFFFF; pub const ARPHRD_NONE: u16 = 0xFFFE; // bits/posix1_lim.h pub const _POSIX_AIO_LISTIO_MAX: usize = 2; pub const _POSIX_AIO_MAX: usize = 1; pub const _POSIX_ARG_MAX: usize = 4096; pub const _POSIX_CHILD_MAX: usize = 25; pub const _POSIX_DELAYTIMER_MAX: usize = 32; pub const _POSIX_HOST_NAME_MAX: usize = 255; pub const _POSIX_LINK_MAX: usize = 8; pub const _POSIX_LOGIN_NAME_MAX: usize = 9; pub const _POSIX_MAX_CANON: usize = 255; pub const _POSIX_MAX_INPUT: usize = 255; pub const _POSIX_MQ_OPEN_MAX: usize = 8; pub const _POSIX_MQ_PRIO_MAX: usize = 32; pub const _POSIX_NAME_MAX: usize = 14; pub const _POSIX_NGROUPS_MAX: usize = 8; pub const _POSIX_OPEN_MAX: usize = 20; pub const _POSIX_FD_SETSIZE: usize = 20; pub const _POSIX_PATH_MAX: usize = 256; pub const _POSIX_PIPE_BUF: usize = 512; pub const _POSIX_RE_DUP_MAX: usize = 255; pub const _POSIX_RTSIG_MAX: usize = 8; pub const _POSIX_SEM_NSEMS_MAX: usize = 256; pub const _POSIX_SEM_VALUE_MAX: usize = 32767; pub const _POSIX_SIGQUEUE_MAX: usize = 32; pub const _POSIX_SSIZE_MAX: usize = 32767; pub const _POSIX_STREAM_MAX: usize = 8; pub const _POSIX_SYMLINK_MAX: usize = 255; pub const _POSIX_SYMLOOP_MAX: usize = 8; pub const _POSIX_TIMER_MAX: usize = 32; pub const _POSIX_TTY_NAME_MAX: usize = 9; pub const _POSIX_TZNAME_MAX: usize = 6; pub const _POSIX_QLIMIT: usize = 1; pub const _POSIX_HIWAT: usize = 512; pub const _POSIX_UIO_MAXIOV: usize = 16; pub const _POSIX_CLOCKRES_MIN: usize = 20000000; pub const NAME_MAX: usize = 255; pub const NGROUPS_MAX: usize = 256; pub const _POSIX_THREAD_KEYS_MAX: usize = 128; pub const _POSIX_THREAD_DESTRUCTOR_ITERATIONS: usize = 4; pub const _POSIX_THREAD_THREADS_MAX: usize = 64; pub const SEM_VALUE_MAX: c_int = 2147483647; pub const MAXNAMLEN: usize = 255; // netdb.h pub const _PATH_HEQUIV: &'static [u8; 17usize] = b"/etc/hosts.equiv\0"; pub const _PATH_HOSTS: &'static [u8; 11usize] = b"/etc/hosts\0"; pub const _PATH_NETWORKS: &'static [u8; 14usize] = b"/etc/networks\0"; pub const _PATH_NSSWITCH_CONF: &'static [u8; 19usize] = b"/etc/nsswitch.conf\0"; pub const _PATH_PROTOCOLS: &'static [u8; 15usize] = b"/etc/protocols\0"; pub const _PATH_SERVICES: &'static [u8; 14usize] = b"/etc/services\0"; pub const HOST_NOT_FOUND: c_int = 1; pub const TRY_AGAIN: c_int = 2; pub const NO_RECOVERY: c_int = 3; pub const NO_DATA: c_int = 4; pub const NETDB_INTERNAL: c_int = -1; pub const NETDB_SUCCESS: c_int = 0; pub const NO_ADDRESS: c_int = 4; pub const IPPORT_RESERVED: c_int = 1024; pub const SCOPE_DELIMITER: u8 = 37u8; pub const GAI_WAIT: c_int = 0; pub const GAI_NOWAIT: c_int = 1; pub const AI_PASSIVE: c_int = 1; pub const AI_CANONNAME: c_int = 2; pub const AI_NUMERICHOST: c_int = 4; pub const AI_V4MAPPED: c_int = 8; pub const AI_ALL: c_int = 16; pub const AI_ADDRCONFIG: c_int = 32; pub const AI_IDN: c_int = 64; pub const AI_CANONIDN: c_int = 128; pub const AI_NUMERICSERV: c_int = 1024; pub const EAI_BADFLAGS: c_int = -1; pub const EAI_NONAME: c_int = -2; pub const EAI_AGAIN: c_int = -3; pub const EAI_FAIL: c_int = -4; pub const EAI_FAMILY: c_int = -6; pub const EAI_SOCKTYPE: c_int = -7; pub const EAI_SERVICE: c_int = -8; pub const EAI_MEMORY: c_int = -10; pub const EAI_SYSTEM: c_int = -11; pub const EAI_OVERFLOW: c_int = -12; pub const EAI_NODATA: c_int = -5; pub const EAI_ADDRFAMILY: c_int = -9; pub const EAI_INPROGRESS: c_int = -100; pub const EAI_CANCELED: c_int = -101; pub const EAI_NOTCANCELED: c_int = -102; pub const EAI_ALLDONE: c_int = -103; pub const EAI_INTR: c_int = -104; pub const EAI_IDN_ENCODE: c_int = -105; pub const NI_MAXHOST: usize = 1025; pub const NI_MAXSERV: usize = 32; pub const NI_NUMERICHOST: c_int = 1; pub const NI_NUMERICSERV: c_int = 2; pub const NI_NOFQDN: c_int = 4; pub const NI_NAMEREQD: c_int = 8; pub const NI_DGRAM: c_int = 16; pub const NI_IDN: c_int = 32; // time.h pub const CLOCK_REALTIME: crate::clockid_t = 0; pub const CLOCK_MONOTONIC: crate::clockid_t = 1; pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 3; pub const CLOCK_MONOTONIC_RAW: crate::clockid_t = 4; pub const CLOCK_REALTIME_COARSE: crate::clockid_t = 5; pub const CLOCK_MONOTONIC_COARSE: crate::clockid_t = 6; pub const TIMER_ABSTIME: c_int = 1; pub const TIME_UTC: c_int = 1; // sys/poll.h pub const POLLIN: i16 = 1; pub const POLLPRI: i16 = 2; pub const POLLOUT: i16 = 4; pub const POLLRDNORM: i16 = 1; pub const POLLRDBAND: i16 = 2; pub const POLLWRNORM: i16 = 4; pub const POLLWRBAND: i16 = 4; pub const POLLERR: i16 = 8; pub const POLLHUP: i16 = 16; pub const POLLNVAL: i16 = 32; // locale.h pub const __LC_CTYPE: usize = 0; pub const __LC_NUMERIC: usize = 1; pub const __LC_TIME: usize = 2; pub const __LC_COLLATE: usize = 3; pub const __LC_MONETARY: usize = 4; pub const __LC_MESSAGES: usize = 5; pub const __LC_ALL: usize = 6; pub const __LC_PAPER: usize = 7; pub const __LC_NAME: usize = 8; pub const __LC_ADDRESS: usize = 9; pub const __LC_TELEPHONE: usize = 10; pub const __LC_MEASUREMENT: usize = 11; pub const __LC_IDENTIFICATION: usize = 12; pub const LC_CTYPE: c_int = 0; pub const LC_NUMERIC: c_int = 1; pub const LC_TIME: c_int = 2; pub const LC_COLLATE: c_int = 3; pub const LC_MONETARY: c_int = 4; pub const LC_MESSAGES: c_int = 5; pub const LC_ALL: c_int = 6; pub const LC_PAPER: c_int = 7; pub const LC_NAME: c_int = 8; pub const LC_ADDRESS: c_int = 9; pub const LC_TELEPHONE: c_int = 10; pub const LC_MEASUREMENT: c_int = 11; pub const LC_IDENTIFICATION: c_int = 12; pub const LC_CTYPE_MASK: c_int = 1; pub const LC_NUMERIC_MASK: c_int = 2; pub const LC_TIME_MASK: c_int = 4; pub const LC_COLLATE_MASK: c_int = 8; pub const LC_MONETARY_MASK: c_int = 16; pub const LC_MESSAGES_MASK: c_int = 32; pub const LC_PAPER_MASK: c_int = 128; pub const LC_NAME_MASK: c_int = 256; pub const LC_ADDRESS_MASK: c_int = 512; pub const LC_TELEPHONE_MASK: c_int = 1024; pub const LC_MEASUREMENT_MASK: c_int = 2048; pub const LC_IDENTIFICATION_MASK: c_int = 4096; pub const LC_ALL_MASK: c_int = 8127; pub const ABDAY_1: crate::nl_item = 0x20000; pub const ABDAY_2: crate::nl_item = 0x20001; pub const ABDAY_3: crate::nl_item = 0x20002; pub const ABDAY_4: crate::nl_item = 0x20003; pub const ABDAY_5: crate::nl_item = 0x20004; pub const ABDAY_6: crate::nl_item = 0x20005; pub const ABDAY_7: crate::nl_item = 0x20006; pub const DAY_1: crate::nl_item = 0x20007; pub const DAY_2: crate::nl_item = 0x20008; pub const DAY_3: crate::nl_item = 0x20009; pub const DAY_4: crate::nl_item = 0x2000A; pub const DAY_5: crate::nl_item = 0x2000B; pub const DAY_6: crate::nl_item = 0x2000C; pub const DAY_7: crate::nl_item = 0x2000D; pub const ABMON_1: crate::nl_item = 0x2000E; pub const ABMON_2: crate::nl_item = 0x2000F; pub const ABMON_3: crate::nl_item = 0x20010; pub const ABMON_4: crate::nl_item = 0x20011; pub const ABMON_5: crate::nl_item = 0x20012; pub const ABMON_6: crate::nl_item = 0x20013; pub const ABMON_7: crate::nl_item = 0x20014; pub const ABMON_8: crate::nl_item = 0x20015; pub const ABMON_9: crate::nl_item = 0x20016; pub const ABMON_10: crate::nl_item = 0x20017; pub const ABMON_11: crate::nl_item = 0x20018; pub const ABMON_12: crate::nl_item = 0x20019; pub const MON_1: crate::nl_item = 0x2001A; pub const MON_2: crate::nl_item = 0x2001B; pub const MON_3: crate::nl_item = 0x2001C; pub const MON_4: crate::nl_item = 0x2001D; pub const MON_5: crate::nl_item = 0x2001E; pub const MON_6: crate::nl_item = 0x2001F; pub const MON_7: crate::nl_item = 0x20020; pub const MON_8: crate::nl_item = 0x20021; pub const MON_9: crate::nl_item = 0x20022; pub const MON_10: crate::nl_item = 0x20023; pub const MON_11: crate::nl_item = 0x20024; pub const MON_12: crate::nl_item = 0x20025; pub const AM_STR: crate::nl_item = 0x20026; pub const PM_STR: crate::nl_item = 0x20027; pub const D_T_FMT: crate::nl_item = 0x20028; pub const D_FMT: crate::nl_item = 0x20029; pub const T_FMT: crate::nl_item = 0x2002A; pub const T_FMT_AMPM: crate::nl_item = 0x2002B; pub const ERA: crate::nl_item = 0x2002C; pub const ERA_D_FMT: crate::nl_item = 0x2002E; pub const ALT_DIGITS: crate::nl_item = 0x2002F; pub const ERA_D_T_FMT: crate::nl_item = 0x20030; pub const ERA_T_FMT: crate::nl_item = 0x20031; pub const CODESET: crate::nl_item = 14; pub const CRNCYSTR: crate::nl_item = 0x4000F; pub const RADIXCHAR: crate::nl_item = 0x10000; pub const THOUSEP: crate::nl_item = 0x10001; pub const YESEXPR: crate::nl_item = 0x50000; pub const NOEXPR: crate::nl_item = 0x50001; pub const YESSTR: crate::nl_item = 0x50002; pub const NOSTR: crate::nl_item = 0x50003; // reboot.h pub const RB_AUTOBOOT: c_int = 0x0; pub const RB_ASKNAME: c_int = 0x1; pub const RB_SINGLE: c_int = 0x2; pub const RB_KBD: c_int = 0x4; pub const RB_HALT: c_int = 0x8; pub const RB_INITNAME: c_int = 0x10; pub const RB_DFLTROOT: c_int = 0x20; pub const RB_NOBOOTRC: c_int = 0x20; pub const RB_ALTBOOT: c_int = 0x40; pub const RB_UNIPROC: c_int = 0x80; pub const RB_DEBUGGER: c_int = 0x1000; // semaphore.h pub const __SIZEOF_SEM_T: usize = 20; pub const SEM_FAILED: *mut crate::sem_t = 0 as *mut sem_t; // termios.h pub const IGNBRK: crate::tcflag_t = 1; pub const BRKINT: crate::tcflag_t = 2; pub const IGNPAR: crate::tcflag_t = 4; pub const PARMRK: crate::tcflag_t = 8; pub const INPCK: crate::tcflag_t = 16; pub const ISTRIP: crate::tcflag_t = 32; pub const INLCR: crate::tcflag_t = 64; pub const IGNCR: crate::tcflag_t = 128; pub const ICRNL: crate::tcflag_t = 256; pub const IXON: crate::tcflag_t = 512; pub const IXOFF: crate::tcflag_t = 1024; pub const IXANY: crate::tcflag_t = 2048; pub const IMAXBEL: crate::tcflag_t = 8192; pub const IUCLC: crate::tcflag_t = 16384; pub const OPOST: crate::tcflag_t = 1; pub const ONLCR: crate::tcflag_t = 2; pub const ONOEOT: crate::tcflag_t = 8; pub const OCRNL: crate::tcflag_t = 16; pub const ONOCR: crate::tcflag_t = 32; pub const ONLRET: crate::tcflag_t = 64; pub const NLDLY: crate::tcflag_t = 768; pub const NL0: crate::tcflag_t = 0; pub const NL1: crate::tcflag_t = 256; pub const TABDLY: crate::tcflag_t = 3076; pub const TAB0: crate::tcflag_t = 0; pub const TAB1: crate::tcflag_t = 1024; pub const TAB2: crate::tcflag_t = 2048; pub const TAB3: crate::tcflag_t = 4; pub const CRDLY: crate::tcflag_t = 12288; pub const CR0: crate::tcflag_t = 0; pub const CR1: crate::tcflag_t = 4096; pub const CR2: crate::tcflag_t = 8192; pub const CR3: crate::tcflag_t = 12288; pub const FFDLY: crate::tcflag_t = 16384; pub const FF0: crate::tcflag_t = 0; pub const FF1: crate::tcflag_t = 16384; pub const BSDLY: crate::tcflag_t = 32768; pub const BS0: crate::tcflag_t = 0; pub const BS1: crate::tcflag_t = 32768; pub const VTDLY: crate::tcflag_t = 65536; pub const VT0: crate::tcflag_t = 0; pub const VT1: crate::tcflag_t = 65536; pub const OLCUC: crate::tcflag_t = 131072; pub const OFILL: crate::tcflag_t = 262144; pub const OFDEL: crate::tcflag_t = 524288; pub const CIGNORE: crate::tcflag_t = 1; pub const CSIZE: crate::tcflag_t = 768; pub const CS5: crate::tcflag_t = 0; pub const CS6: crate::tcflag_t = 256; pub const CS7: crate::tcflag_t = 512; pub const CS8: crate::tcflag_t = 768; pub const CSTOPB: crate::tcflag_t = 1024; pub const CREAD: crate::tcflag_t = 2048; pub const PARENB: crate::tcflag_t = 4096; pub const PARODD: crate::tcflag_t = 8192; pub const HUPCL: crate::tcflag_t = 16384; pub const CLOCAL: crate::tcflag_t = 32768; pub const CRTSCTS: crate::tcflag_t = 65536; pub const CRTS_IFLOW: crate::tcflag_t = 65536; pub const CCTS_OFLOW: crate::tcflag_t = 65536; pub const CDTRCTS: crate::tcflag_t = 131072; pub const MDMBUF: crate::tcflag_t = 1048576; pub const CHWFLOW: crate::tcflag_t = 1245184; pub const ECHOKE: crate::tcflag_t = 1; pub const _ECHOE: crate::tcflag_t = 2; pub const ECHOE: crate::tcflag_t = 2; pub const _ECHOK: crate::tcflag_t = 4; pub const ECHOK: crate::tcflag_t = 4; pub const _ECHO: crate::tcflag_t = 8; pub const ECHO: crate::tcflag_t = 8; pub const _ECHONL: crate::tcflag_t = 16; pub const ECHONL: crate::tcflag_t = 16; pub const ECHOPRT: crate::tcflag_t = 32; pub const ECHOCTL: crate::tcflag_t = 64; pub const _ISIG: crate::tcflag_t = 128; pub const ISIG: crate::tcflag_t = 128; pub const _ICANON: crate::tcflag_t = 256; pub const ICANON: crate::tcflag_t = 256; pub const ALTWERASE: crate::tcflag_t = 512; pub const _IEXTEN: crate::tcflag_t = 1024; pub const IEXTEN: crate::tcflag_t = 1024; pub const EXTPROC: crate::tcflag_t = 2048; pub const _TOSTOP: crate::tcflag_t = 4194304; pub const TOSTOP: crate::tcflag_t = 4194304; pub const FLUSHO: crate::tcflag_t = 8388608; pub const NOKERNINFO: crate::tcflag_t = 33554432; pub const PENDIN: crate::tcflag_t = 536870912; pub const _NOFLSH: crate::tcflag_t = 2147483648; pub const NOFLSH: crate::tcflag_t = 2147483648; pub const VEOF: usize = 0; pub const VEOL: usize = 1; pub const VEOL2: usize = 2; pub const VERASE: usize = 3; pub const VWERASE: usize = 4; pub const VKILL: usize = 5; pub const VREPRINT: usize = 6; pub const VINTR: usize = 8; pub const VQUIT: usize = 9; pub const VSUSP: usize = 10; pub const VDSUSP: usize = 11; pub const VSTART: usize = 12; pub const VSTOP: usize = 13; pub const VLNEXT: usize = 14; pub const VDISCARD: usize = 15; pub const VMIN: usize = 16; pub const VTIME: usize = 17; pub const VSTATUS: usize = 18; pub const NCCS: usize = 20; pub const B0: crate::speed_t = 0; pub const B50: crate::speed_t = 50; pub const B75: crate::speed_t = 75; pub const B110: crate::speed_t = 110; pub const B134: crate::speed_t = 134; pub const B150: crate::speed_t = 150; pub const B200: crate::speed_t = 200; pub const B300: crate::speed_t = 300; pub const B600: crate::speed_t = 600; pub const B1200: crate::speed_t = 1200; pub const B1800: crate::speed_t = 1800; pub const B2400: crate::speed_t = 2400; pub const B4800: crate::speed_t = 4800; pub const B9600: crate::speed_t = 9600; pub const B7200: crate::speed_t = 7200; pub const B14400: crate::speed_t = 14400; pub const B19200: crate::speed_t = 19200; pub const B28800: crate::speed_t = 28800; pub const B38400: crate::speed_t = 38400; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 57600; pub const B76800: crate::speed_t = 76800; pub const B115200: crate::speed_t = 115200; pub const B230400: crate::speed_t = 230400; pub const B460800: crate::speed_t = 460800; pub const B500000: crate::speed_t = 500000; pub const B576000: crate::speed_t = 576000; pub const B921600: crate::speed_t = 921600; pub const B1000000: crate::speed_t = 1000000; pub const B1152000: crate::speed_t = 1152000; pub const B1500000: crate::speed_t = 1500000; pub const B2000000: crate::speed_t = 2000000; pub const B2500000: crate::speed_t = 2500000; pub const B3000000: crate::speed_t = 3000000; pub const B3500000: crate::speed_t = 3500000; pub const B4000000: crate::speed_t = 4000000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const TCSASOFT: c_int = 16; pub const TCIFLUSH: c_int = 1; pub const TCOFLUSH: c_int = 2; pub const TCIOFLUSH: c_int = 3; pub const TCOOFF: c_int = 1; pub const TCOON: c_int = 2; pub const TCIOFF: c_int = 3; pub const TCION: c_int = 4; pub const TTYDEF_IFLAG: crate::tcflag_t = 11042; pub const TTYDEF_LFLAG: crate::tcflag_t = 1483; pub const TTYDEF_CFLAG: crate::tcflag_t = 23040; pub const TTYDEF_SPEED: crate::tcflag_t = 9600; pub const CEOL: u8 = 0u8; pub const CERASE: u8 = 127; pub const CMIN: u8 = 1; pub const CQUIT: u8 = 28; pub const CTIME: u8 = 0; pub const CBRK: u8 = 0u8; // dlfcn.h pub const RTLD_DEFAULT: *mut c_void = 0i64 as *mut c_void; pub const RTLD_NEXT: *mut c_void = -1i64 as *mut c_void; pub const RTLD_LAZY: c_int = 1; pub const RTLD_NOW: c_int = 2; pub const RTLD_BINDING_MASK: c_int = 3; pub const RTLD_NOLOAD: c_int = 4; pub const RTLD_DEEPBIND: c_int = 8; pub const RTLD_GLOBAL: c_int = 256; pub const RTLD_LOCAL: c_int = 0; pub const RTLD_NODELETE: c_int = 4096; pub const DLFO_STRUCT_HAS_EH_DBASE: usize = 1; pub const DLFO_STRUCT_HAS_EH_COUNT: usize = 0; pub const LM_ID_BASE: c_long = 0; pub const LM_ID_NEWLM: c_long = -1; // bits/signum_generic.h pub const SIGINT: c_int = 2; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGFPE: c_int = 8; pub const SIGSEGV: c_int = 11; pub const SIGTERM: c_int = 15; pub const SIGHUP: c_int = 1; pub const SIGQUIT: c_int = 3; pub const SIGTRAP: c_int = 5; pub const SIGKILL: c_int = 9; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGIOT: c_int = 6; pub const SIGBUS: c_int = 10; pub const SIGSYS: c_int = 12; pub const SIGEMT: c_int = 7; pub const SIGINFO: c_int = 29; pub const SIGLOST: c_int = 32; pub const SIGURG: c_int = 16; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGCONT: c_int = 19; pub const SIGCHLD: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGPOLL: c_int = 23; pub const SIGXCPU: c_int = 24; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGXFSZ: c_int = 25; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGWINCH: c_int = 28; pub const SIGIO: c_int = 23; pub const SIGCLD: c_int = 20; pub const __SIGRTMIN: usize = 32; pub const __SIGRTMAX: usize = 32; pub const _NSIG: usize = 33; pub const NSIG: usize = 33; // bits/sigaction.h pub const SA_ONSTACK: c_int = 1; pub const SA_RESTART: c_int = 2; pub const SA_NODEFER: c_int = 16; pub const SA_RESETHAND: c_int = 4; pub const SA_NOCLDSTOP: c_int = 8; pub const SA_SIGINFO: c_int = 64; pub const SA_INTERRUPT: c_int = 0; pub const SA_NOMASK: c_int = 16; pub const SA_ONESHOT: c_int = 4; pub const SA_STACK: c_int = 1; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const SIG_SETMASK: c_int = 3; // bits/sigcontext.h pub const FPC_IE: u16 = 1; pub const FPC_IM: u16 = 1; pub const FPC_DE: u16 = 2; pub const FPC_DM: u16 = 2; pub const FPC_ZE: u16 = 4; pub const FPC_ZM: u16 = 4; pub const FPC_OE: u16 = 8; pub const FPC_OM: u16 = 8; pub const FPC_UE: u16 = 16; pub const FPC_PE: u16 = 32; pub const FPC_PC: u16 = 768; pub const FPC_PC_24: u16 = 0; pub const FPC_PC_53: u16 = 512; pub const FPC_PC_64: u16 = 768; pub const FPC_RC: u16 = 3072; pub const FPC_RC_RN: u16 = 0; pub const FPC_RC_RD: u16 = 1024; pub const FPC_RC_RU: u16 = 2048; pub const FPC_RC_CHOP: u16 = 3072; pub const FPC_IC: u16 = 4096; pub const FPC_IC_PROJ: u16 = 0; pub const FPC_IC_AFF: u16 = 4096; pub const FPS_IE: u16 = 1; pub const FPS_DE: u16 = 2; pub const FPS_ZE: u16 = 4; pub const FPS_OE: u16 = 8; pub const FPS_UE: u16 = 16; pub const FPS_PE: u16 = 32; pub const FPS_SF: u16 = 64; pub const FPS_ES: u16 = 128; pub const FPS_C0: u16 = 256; pub const FPS_C1: u16 = 512; pub const FPS_C2: u16 = 1024; pub const FPS_TOS: u16 = 14336; pub const FPS_TOS_SHIFT: u16 = 11; pub const FPS_C3: u16 = 16384; pub const FPS_BUSY: u16 = 32768; pub const FPE_INTOVF_TRAP: c_int = 1; pub const FPE_INTDIV_FAULT: c_int = 2; pub const FPE_FLTOVF_FAULT: c_int = 3; pub const FPE_FLTDIV_FAULT: c_int = 4; pub const FPE_FLTUND_FAULT: c_int = 5; pub const FPE_SUBRNG_FAULT: c_int = 7; pub const FPE_FLTDNR_FAULT: c_int = 8; pub const FPE_FLTINX_FAULT: c_int = 9; pub const FPE_EMERR_FAULT: c_int = 10; pub const FPE_EMBND_FAULT: c_int = 11; pub const ILL_INVOPR_FAULT: c_int = 1; pub const ILL_STACK_FAULT: c_int = 2; pub const ILL_FPEOPR_FAULT: c_int = 3; pub const DBG_SINGLE_TRAP: c_int = 1; pub const DBG_BRKPNT_FAULT: c_int = 2; pub const __NGREG: usize = 19; pub const NGREG: usize = 19; // bits/sigstack.h pub const MINSIGSTKSZ: usize = 8192; pub const SIGSTKSZ: usize = 40960; // sys/stat.h pub const __S_IFMT: mode_t = 0o17_0000; pub const __S_IFDIR: mode_t = 0o4_0000; pub const __S_IFCHR: mode_t = 0o2_0000; pub const __S_IFBLK: mode_t = 0o6_0000; pub const __S_IFREG: mode_t = 0o10_0000; pub const __S_IFLNK: mode_t = 0o12_0000; pub const __S_IFSOCK: mode_t = 0o14_0000; pub const __S_IFIFO: mode_t = 0o1_0000; pub const __S_ISUID: mode_t = 0o4000; pub const __S_ISGID: mode_t = 0o2000; pub const __S_ISVTX: mode_t = 0o1000; pub const __S_IREAD: mode_t = 0o0400; pub const __S_IWRITE: mode_t = 0o0200; pub const __S_IEXEC: mode_t = 0o0100; pub const S_INOCACHE: mode_t = 0o20_0000; pub const S_IUSEUNK: mode_t = 0o40_0000; pub const S_IUNKNOWN: mode_t = 0o700_0000; pub const S_IUNKSHIFT: mode_t = 0o0014; pub const S_IPTRANS: mode_t = 0o1000_0000; pub const S_IATRANS: mode_t = 0o2000_0000; pub const S_IROOT: mode_t = 0o4000_0000; pub const S_ITRANS: mode_t = 0o7000_0000; pub const S_IMMAP0: mode_t = 0o10000_0000; pub const CMASK: mode_t = 18; pub const UF_SETTABLE: c_uint = 65535; pub const UF_NODUMP: c_uint = 1; pub const UF_IMMUTABLE: c_uint = 2; pub const UF_APPEND: c_uint = 4; pub const UF_OPAQUE: c_uint = 8; pub const UF_NOUNLINK: c_uint = 16; pub const SF_SETTABLE: c_uint = 4294901760; pub const SF_ARCHIVED: c_uint = 65536; pub const SF_IMMUTABLE: c_uint = 131072; pub const SF_APPEND: c_uint = 262144; pub const SF_NOUNLINK: c_uint = 1048576; pub const SF_SNAPSHOT: c_uint = 2097152; pub const UTIME_NOW: c_long = -1; pub const UTIME_OMIT: c_long = -2; pub const S_IFMT: crate::mode_t = 0o17_0000; pub const S_IFDIR: crate::mode_t = 0o4_0000; pub const S_IFCHR: crate::mode_t = 0o2_0000; pub const S_IFBLK: crate::mode_t = 0o6_0000; pub const S_IFREG: crate::mode_t = 0o10_0000; pub const S_IFIFO: crate::mode_t = 0o1_0000; pub const S_IFLNK: crate::mode_t = 0o12_0000; pub const S_IFSOCK: crate::mode_t = 0o14_0000; pub const S_ISUID: crate::mode_t = 0o4000; pub const S_ISGID: crate::mode_t = 0o2000; pub const S_ISVTX: crate::mode_t = 0o1000; pub const S_IRUSR: crate::mode_t = 0o0400; pub const S_IWUSR: crate::mode_t = 0o0200; pub const S_IXUSR: crate::mode_t = 0o0100; pub const S_IRWXU: crate::mode_t = 0o0700; pub const S_IREAD: crate::mode_t = 0o0400; pub const S_IWRITE: crate::mode_t = 0o0200; pub const S_IEXEC: crate::mode_t = 0o0100; pub const S_IRGRP: crate::mode_t = 0o0040; pub const S_IWGRP: crate::mode_t = 0o0020; pub const S_IXGRP: crate::mode_t = 0o0010; pub const S_IRWXG: crate::mode_t = 0o0070; pub const S_IROTH: crate::mode_t = 0o0004; pub const S_IWOTH: crate::mode_t = 0o0002; pub const S_IXOTH: crate::mode_t = 0o0001; pub const S_IRWXO: crate::mode_t = 0o0007; pub const ACCESSPERMS: crate::mode_t = 511; pub const ALLPERMS: crate::mode_t = 4095; pub const DEFFILEMODE: crate::mode_t = 438; pub const S_BLKSIZE: usize = 512; pub const STATX_TYPE: c_uint = 1; pub const STATX_MODE: c_uint = 2; pub const STATX_NLINK: c_uint = 4; pub const STATX_UID: c_uint = 8; pub const STATX_GID: c_uint = 16; pub const STATX_ATIME: c_uint = 32; pub const STATX_MTIME: c_uint = 64; pub const STATX_CTIME: c_uint = 128; pub const STATX_INO: c_uint = 256; pub const STATX_SIZE: c_uint = 512; pub const STATX_BLOCKS: c_uint = 1024; pub const STATX_BASIC_STATS: c_uint = 2047; pub const STATX_ALL: c_uint = 4095; pub const STATX_BTIME: c_uint = 2048; pub const STATX_MNT_ID: c_uint = 4096; pub const STATX_DIOALIGN: c_uint = 8192; pub const STATX__RESERVED: c_uint = 2147483648; pub const STATX_ATTR_COMPRESSED: c_uint = 4; pub const STATX_ATTR_IMMUTABLE: c_uint = 16; pub const STATX_ATTR_APPEND: c_uint = 32; pub const STATX_ATTR_NODUMP: c_uint = 64; pub const STATX_ATTR_ENCRYPTED: c_uint = 2048; pub const STATX_ATTR_AUTOMOUNT: c_uint = 4096; pub const STATX_ATTR_MOUNT_ROOT: c_uint = 8192; pub const STATX_ATTR_VERITY: c_uint = 1048576; pub const STATX_ATTR_DAX: c_uint = 2097152; // sys/ioctl.h pub const TIOCM_LE: c_int = 1; pub const TIOCM_DTR: c_int = 2; pub const TIOCM_RTS: c_int = 4; pub const TIOCM_ST: c_int = 8; pub const TIOCM_SR: c_int = 16; pub const TIOCM_CTS: c_int = 32; pub const TIOCM_CAR: c_int = 64; pub const TIOCM_CD: c_int = 64; pub const TIOCM_RNG: c_int = 128; pub const TIOCM_RI: c_int = 128; pub const TIOCM_DSR: c_int = 256; pub const TIOCPKT_DATA: c_int = 0; pub const TIOCPKT_FLUSHREAD: c_int = 1; pub const TIOCPKT_FLUSHWRITE: c_int = 2; pub const TIOCPKT_STOP: c_int = 4; pub const TIOCPKT_START: c_int = 8; pub const TIOCPKT_NOSTOP: c_int = 16; pub const TIOCPKT_DOSTOP: c_int = 32; pub const TIOCPKT_IOCTL: c_int = 64; pub const TTYDISC: c_int = 0; pub const TABLDISC: c_int = 3; pub const SLIPDISC: c_int = 4; pub const TANDEM: crate::tcflag_t = 1; pub const CBREAK: crate::tcflag_t = 2; pub const LCASE: crate::tcflag_t = 4; pub const CRMOD: crate::tcflag_t = 16; pub const RAW: crate::tcflag_t = 32; pub const ODDP: crate::tcflag_t = 64; pub const EVENP: crate::tcflag_t = 128; pub const ANYP: crate::tcflag_t = 192; pub const NLDELAY: crate::tcflag_t = 768; pub const NL2: crate::tcflag_t = 512; pub const NL3: crate::tcflag_t = 768; pub const TBDELAY: crate::tcflag_t = 3072; pub const XTABS: crate::tcflag_t = 3072; pub const CRDELAY: crate::tcflag_t = 12288; pub const VTDELAY: crate::tcflag_t = 16384; pub const BSDELAY: crate::tcflag_t = 32768; pub const ALLDELAY: crate::tcflag_t = 65280; pub const CRTBS: crate::tcflag_t = 65536; pub const PRTERA: crate::tcflag_t = 131072; pub const CRTERA: crate::tcflag_t = 262144; pub const TILDE: crate::tcflag_t = 524288; pub const LITOUT: crate::tcflag_t = 2097152; pub const NOHANG: crate::tcflag_t = 16777216; pub const L001000: crate::tcflag_t = 33554432; pub const CRTKIL: crate::tcflag_t = 67108864; pub const PASS8: crate::tcflag_t = 134217728; pub const CTLECH: crate::tcflag_t = 268435456; pub const DECCTQ: crate::tcflag_t = 1073741824; pub const FIONBIO: c_ulong = 0xa008007e; pub const FIONREAD: c_ulong = 0x6008007f; pub const TIOCSWINSZ: c_ulong = 0x90200767; pub const TIOCGWINSZ: c_ulong = 0x50200768; pub const TIOCEXCL: c_ulong = 0x70d; pub const TIOCNXCL: c_ulong = 0x70e; pub const TIOCSCTTY: c_ulong = 0x761; pub const FIOCLEX: c_ulong = 1; // fcntl.h pub const O_EXEC: c_int = 4; pub const O_NORW: c_int = 0; pub const O_RDONLY: c_int = 1; pub const O_WRONLY: c_int = 2; pub const O_RDWR: c_int = 3; pub const O_ACCMODE: c_int = 3; pub const O_LARGEFILE: c_int = 0; pub const O_CREAT: c_int = 16; pub const O_EXCL: c_int = 32; pub const O_NOLINK: c_int = 64; pub const O_NOTRANS: c_int = 128; pub const O_NOFOLLOW: c_int = 1048576; pub const O_DIRECTORY: c_int = 2097152; pub const O_APPEND: c_int = 256; pub const O_ASYNC: c_int = 512; pub const O_FSYNC: c_int = 1024; pub const O_SYNC: c_int = 1024; pub const O_NOATIME: c_int = 2048; pub const O_SHLOCK: c_int = 131072; pub const O_EXLOCK: c_int = 262144; pub const O_DSYNC: c_int = 1024; pub const O_RSYNC: c_int = 1024; pub const O_NONBLOCK: c_int = 8; pub const O_NDELAY: c_int = 8; pub const O_HURD: c_int = 458751; pub const O_TRUNC: c_int = 65536; pub const O_CLOEXEC: c_int = 4194304; pub const O_IGNORE_CTTY: c_int = 524288; pub const O_TMPFILE: c_int = 8388608; pub const O_NOCTTY: c_int = 0; pub const FREAD: c_int = 1; pub const FWRITE: c_int = 2; pub const FASYNC: c_int = 512; pub const FCREAT: c_int = 16; pub const FEXCL: c_int = 32; pub const FTRUNC: c_int = 65536; pub const FNOCTTY: c_int = 0; pub const FFSYNC: c_int = 1024; pub const FSYNC: c_int = 1024; pub const FAPPEND: c_int = 256; pub const FNONBLOCK: c_int = 8; pub const FNDELAY: c_int = 8; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const F_GETOWN: c_int = 5; pub const F_SETOWN: c_int = 6; pub const F_GETLK: c_int = 7; pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; pub const F_GETLK64: c_int = 10; pub const F_SETLK64: c_int = 11; pub const F_SETLKW64: c_int = 12; pub const F_DUPFD_CLOEXEC: c_int = 1030; pub const FD_CLOEXEC: c_int = 1; pub const F_RDLCK: c_int = 1; pub const F_WRLCK: c_int = 2; pub const F_UNLCK: c_int = 3; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_RANDOM: c_int = 1; pub const POSIX_FADV_SEQUENTIAL: c_int = 2; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const AT_FDCWD: c_int = -100; pub const AT_SYMLINK_NOFOLLOW: c_int = 256; pub const AT_REMOVEDIR: c_int = 512; pub const AT_SYMLINK_FOLLOW: c_int = 1024; pub const AT_NO_AUTOMOUNT: c_int = 2048; pub const AT_EMPTY_PATH: c_int = 4096; pub const AT_STATX_SYNC_TYPE: c_int = 24576; pub const AT_STATX_SYNC_AS_STAT: c_int = 0; pub const AT_STATX_FORCE_SYNC: c_int = 8192; pub const AT_STATX_DONT_SYNC: c_int = 16384; pub const AT_RECURSIVE: c_int = 32768; pub const AT_EACCESS: c_int = 512; // sys/uio.h pub const RWF_HIPRI: c_int = 1; pub const RWF_DSYNC: c_int = 2; pub const RWF_SYNC: c_int = 4; pub const RWF_NOWAIT: c_int = 8; pub const RWF_APPEND: c_int = 16; // errno.h pub const EPERM: c_int = 1073741825; pub const ENOENT: c_int = 1073741826; pub const ESRCH: c_int = 1073741827; pub const EINTR: c_int = 1073741828; pub const EIO: c_int = 1073741829; pub const ENXIO: c_int = 1073741830; pub const E2BIG: c_int = 1073741831; pub const ENOEXEC: c_int = 1073741832; pub const EBADF: c_int = 1073741833; pub const ECHILD: c_int = 1073741834; pub const EDEADLK: c_int = 1073741835; pub const ENOMEM: c_int = 1073741836; pub const EACCES: c_int = 1073741837; pub const EFAULT: c_int = 1073741838; pub const ENOTBLK: c_int = 1073741839; pub const EBUSY: c_int = 1073741840; pub const EEXIST: c_int = 1073741841; pub const EXDEV: c_int = 1073741842; pub const ENODEV: c_int = 1073741843; pub const ENOTDIR: c_int = 1073741844; pub const EISDIR: c_int = 1073741845; pub const EINVAL: c_int = 1073741846; pub const EMFILE: c_int = 1073741848; pub const ENFILE: c_int = 1073741847; pub const ENOTTY: c_int = 1073741849; pub const ETXTBSY: c_int = 1073741850; pub const EFBIG: c_int = 1073741851; pub const ENOSPC: c_int = 1073741852; pub const ESPIPE: c_int = 1073741853; pub const EROFS: c_int = 1073741854; pub const EMLINK: c_int = 1073741855; pub const EPIPE: c_int = 1073741856; pub const EDOM: c_int = 1073741857; pub const ERANGE: c_int = 1073741858; pub const EAGAIN: c_int = 1073741859; pub const EWOULDBLOCK: c_int = 1073741859; pub const EINPROGRESS: c_int = 1073741860; pub const EALREADY: c_int = 1073741861; pub const ENOTSOCK: c_int = 1073741862; pub const EMSGSIZE: c_int = 1073741864; pub const EPROTOTYPE: c_int = 1073741865; pub const ENOPROTOOPT: c_int = 1073741866; pub const EPROTONOSUPPORT: c_int = 1073741867; pub const ESOCKTNOSUPPORT: c_int = 1073741868; pub const EOPNOTSUPP: c_int = 1073741869; pub const EPFNOSUPPORT: c_int = 1073741870; pub const EAFNOSUPPORT: c_int = 1073741871; pub const EADDRINUSE: c_int = 1073741872; pub const EADDRNOTAVAIL: c_int = 1073741873; pub const ENETDOWN: c_int = 1073741874; pub const ENETUNREACH: c_int = 1073741875; pub const ENETRESET: c_int = 1073741876; pub const ECONNABORTED: c_int = 1073741877; pub const ECONNRESET: c_int = 1073741878; pub const ENOBUFS: c_int = 1073741879; pub const EISCONN: c_int = 1073741880; pub const ENOTCONN: c_int = 1073741881; pub const EDESTADDRREQ: c_int = 1073741863; pub const ESHUTDOWN: c_int = 1073741882; pub const ETOOMANYREFS: c_int = 1073741883; pub const ETIMEDOUT: c_int = 1073741884; pub const ECONNREFUSED: c_int = 1073741885; pub const ELOOP: c_int = 1073741886; pub const ENAMETOOLONG: c_int = 1073741887; pub const EHOSTDOWN: c_int = 1073741888; pub const EHOSTUNREACH: c_int = 1073741889; pub const ENOTEMPTY: c_int = 1073741890; pub const EPROCLIM: c_int = 1073741891; pub const EUSERS: c_int = 1073741892; pub const EDQUOT: c_int = 1073741893; pub const ESTALE: c_int = 1073741894; pub const EREMOTE: c_int = 1073741895; pub const EBADRPC: c_int = 1073741896; pub const ERPCMISMATCH: c_int = 1073741897; pub const EPROGUNAVAIL: c_int = 1073741898; pub const EPROGMISMATCH: c_int = 1073741899; pub const EPROCUNAVAIL: c_int = 1073741900; pub const ENOLCK: c_int = 1073741901; pub const EFTYPE: c_int = 1073741903; pub const EAUTH: c_int = 1073741904; pub const ENEEDAUTH: c_int = 1073741905; pub const ENOSYS: c_int = 1073741902; pub const ELIBEXEC: c_int = 1073741907; pub const ENOTSUP: c_int = 1073741942; pub const EILSEQ: c_int = 1073741930; pub const EBACKGROUND: c_int = 1073741924; pub const EDIED: c_int = 1073741925; pub const EGREGIOUS: c_int = 1073741927; pub const EIEIO: c_int = 1073741928; pub const EGRATUITOUS: c_int = 1073741929; pub const EBADMSG: c_int = 1073741931; pub const EIDRM: c_int = 1073741932; pub const EMULTIHOP: c_int = 1073741933; pub const ENODATA: c_int = 1073741934; pub const ENOLINK: c_int = 1073741935; pub const ENOMSG: c_int = 1073741936; pub const ENOSR: c_int = 1073741937; pub const ENOSTR: c_int = 1073741938; pub const EOVERFLOW: c_int = 1073741939; pub const EPROTO: c_int = 1073741940; pub const ETIME: c_int = 1073741941; pub const ECANCELED: c_int = 1073741943; pub const EOWNERDEAD: c_int = 1073741944; pub const ENOTRECOVERABLE: c_int = 1073741945; pub const EMACH_SEND_IN_PROGRESS: c_int = 268435457; pub const EMACH_SEND_INVALID_DATA: c_int = 268435458; pub const EMACH_SEND_INVALID_DEST: c_int = 268435459; pub const EMACH_SEND_TIMED_OUT: c_int = 268435460; pub const EMACH_SEND_WILL_NOTIFY: c_int = 268435461; pub const EMACH_SEND_NOTIFY_IN_PROGRESS: c_int = 268435462; pub const EMACH_SEND_INTERRUPTED: c_int = 268435463; pub const EMACH_SEND_MSG_TOO_SMALL: c_int = 268435464; pub const EMACH_SEND_INVALID_REPLY: c_int = 268435465; pub const EMACH_SEND_INVALID_RIGHT: c_int = 268435466; pub const EMACH_SEND_INVALID_NOTIFY: c_int = 268435467; pub const EMACH_SEND_INVALID_MEMORY: c_int = 268435468; pub const EMACH_SEND_NO_BUFFER: c_int = 268435469; pub const EMACH_SEND_NO_NOTIFY: c_int = 268435470; pub const EMACH_SEND_INVALID_TYPE: c_int = 268435471; pub const EMACH_SEND_INVALID_HEADER: c_int = 268435472; pub const EMACH_RCV_IN_PROGRESS: c_int = 268451841; pub const EMACH_RCV_INVALID_NAME: c_int = 268451842; pub const EMACH_RCV_TIMED_OUT: c_int = 268451843; pub const EMACH_RCV_TOO_LARGE: c_int = 268451844; pub const EMACH_RCV_INTERRUPTED: c_int = 268451845; pub const EMACH_RCV_PORT_CHANGED: c_int = 268451846; pub const EMACH_RCV_INVALID_NOTIFY: c_int = 268451847; pub const EMACH_RCV_INVALID_DATA: c_int = 268451848; pub const EMACH_RCV_PORT_DIED: c_int = 268451849; pub const EMACH_RCV_IN_SET: c_int = 268451850; pub const EMACH_RCV_HEADER_ERROR: c_int = 268451851; pub const EMACH_RCV_BODY_ERROR: c_int = 268451852; pub const EKERN_INVALID_ADDRESS: c_int = 1; pub const EKERN_PROTECTION_FAILURE: c_int = 2; pub const EKERN_NO_SPACE: c_int = 3; pub const EKERN_INVALID_ARGUMENT: c_int = 4; pub const EKERN_FAILURE: c_int = 5; pub const EKERN_RESOURCE_SHORTAGE: c_int = 6; pub const EKERN_NOT_RECEIVER: c_int = 7; pub const EKERN_NO_ACCESS: c_int = 8; pub const EKERN_MEMORY_FAILURE: c_int = 9; pub const EKERN_MEMORY_ERROR: c_int = 10; pub const EKERN_NOT_IN_SET: c_int = 12; pub const EKERN_NAME_EXISTS: c_int = 13; pub const EKERN_ABORTED: c_int = 14; pub const EKERN_INVALID_NAME: c_int = 15; pub const EKERN_INVALID_TASK: c_int = 16; pub const EKERN_INVALID_RIGHT: c_int = 17; pub const EKERN_INVALID_VALUE: c_int = 18; pub const EKERN_UREFS_OVERFLOW: c_int = 19; pub const EKERN_INVALID_CAPABILITY: c_int = 20; pub const EKERN_RIGHT_EXISTS: c_int = 21; pub const EKERN_INVALID_HOST: c_int = 22; pub const EKERN_MEMORY_PRESENT: c_int = 23; pub const EKERN_WRITE_PROTECTION_FAILURE: c_int = 24; pub const EKERN_TERMINATED: c_int = 26; pub const EKERN_TIMEDOUT: c_int = 27; pub const EKERN_INTERRUPTED: c_int = 28; pub const EMIG_TYPE_ERROR: c_int = -300; pub const EMIG_REPLY_MISMATCH: c_int = -301; pub const EMIG_REMOTE_ERROR: c_int = -302; pub const EMIG_BAD_ID: c_int = -303; pub const EMIG_BAD_ARGUMENTS: c_int = -304; pub const EMIG_NO_REPLY: c_int = -305; pub const EMIG_EXCEPTION: c_int = -306; pub const EMIG_ARRAY_TOO_LARGE: c_int = -307; pub const EMIG_SERVER_DIED: c_int = -308; pub const EMIG_DESTROY_REQUEST: c_int = -309; pub const ED_IO_ERROR: c_int = 2500; pub const ED_WOULD_BLOCK: c_int = 2501; pub const ED_NO_SUCH_DEVICE: c_int = 2502; pub const ED_ALREADY_OPEN: c_int = 2503; pub const ED_DEVICE_DOWN: c_int = 2504; pub const ED_INVALID_OPERATION: c_int = 2505; pub const ED_INVALID_RECNUM: c_int = 2506; pub const ED_INVALID_SIZE: c_int = 2507; pub const ED_NO_MEMORY: c_int = 2508; pub const ED_READ_ONLY: c_int = 2509; pub const _HURD_ERRNOS: usize = 122; // sched.h pub const SCHED_OTHER: c_int = 0; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const _BITS_TYPES_STRUCT_SCHED_PARAM: usize = 1; pub const __CPU_SETSIZE: usize = 1024; pub const CPU_SETSIZE: usize = 1024; // pthread.h pub const PTHREAD_SPINLOCK_INITIALIZER: c_int = 0; pub const PTHREAD_CANCEL_DISABLE: c_int = 0; pub const PTHREAD_CANCEL_ENABLE: c_int = 1; pub const PTHREAD_CANCEL_DEFERRED: c_int = 0; pub const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 1; pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1; // netinet/tcp.h pub const TCP_NODELAY: c_int = 1; pub const TCP_MAXSEG: c_int = 2; pub const TCP_CORK: c_int = 3; pub const TCP_KEEPIDLE: c_int = 4; pub const TCP_KEEPINTVL: c_int = 5; pub const TCP_KEEPCNT: c_int = 6; pub const TCP_SYNCNT: c_int = 7; pub const TCP_LINGER2: c_int = 8; pub const TCP_DEFER_ACCEPT: c_int = 9; pub const TCP_WINDOW_CLAMP: c_int = 10; pub const TCP_INFO: c_int = 11; pub const TCP_QUICKACK: c_int = 12; pub const TCP_CONGESTION: c_int = 13; pub const TCP_MD5SIG: c_int = 14; pub const TCP_COOKIE_TRANSACTIONS: c_int = 15; pub const TCP_THIN_LINEAR_TIMEOUTS: c_int = 16; pub const TCP_THIN_DUPACK: c_int = 17; pub const TCP_USER_TIMEOUT: c_int = 18; pub const TCP_REPAIR: c_int = 19; pub const TCP_REPAIR_QUEUE: c_int = 20; pub const TCP_QUEUE_SEQ: c_int = 21; pub const TCP_REPAIR_OPTIONS: c_int = 22; pub const TCP_FASTOPEN: c_int = 23; pub const TCP_TIMESTAMP: c_int = 24; pub const TCP_NOTSENT_LOWAT: c_int = 25; pub const TCP_CC_INFO: c_int = 26; pub const TCP_SAVE_SYN: c_int = 27; pub const TCP_SAVED_SYN: c_int = 28; pub const TCP_REPAIR_WINDOW: c_int = 29; pub const TCP_FASTOPEN_CONNECT: c_int = 30; pub const TCP_ULP: c_int = 31; pub const TCP_MD5SIG_EXT: c_int = 32; pub const TCP_FASTOPEN_KEY: c_int = 33; pub const TCP_FASTOPEN_NO_COOKIE: c_int = 34; pub const TCP_ZEROCOPY_RECEIVE: c_int = 35; pub const TCP_INQ: c_int = 36; pub const TCP_CM_INQ: c_int = 36; pub const TCP_TX_DELAY: c_int = 37; pub const TCP_REPAIR_ON: c_int = 1; pub const TCP_REPAIR_OFF: c_int = 0; pub const TCP_REPAIR_OFF_NO_WP: c_int = -1; // stdint.h pub const INT8_MIN: i8 = -128; pub const INT16_MIN: i16 = -32768; pub const INT32_MIN: i32 = -2147483648; pub const INT8_MAX: i8 = 127; pub const INT16_MAX: i16 = 32767; pub const INT32_MAX: i32 = 2147483647; pub const UINT8_MAX: u8 = 255; pub const UINT16_MAX: u16 = 65535; pub const UINT32_MAX: u32 = 4294967295; pub const INT_LEAST8_MIN: int_least8_t = -128; pub const INT_LEAST16_MIN: int_least16_t = -32768; pub const INT_LEAST32_MIN: int_least32_t = -2147483648; pub const INT_LEAST8_MAX: int_least8_t = 127; pub const INT_LEAST16_MAX: int_least16_t = 32767; pub const INT_LEAST32_MAX: int_least32_t = 2147483647; pub const UINT_LEAST8_MAX: uint_least8_t = 255; pub const UINT_LEAST16_MAX: uint_least16_t = 65535; pub const UINT_LEAST32_MAX: uint_least32_t = 4294967295; pub const INT_FAST8_MIN: int_fast8_t = -128; pub const INT_FAST16_MIN: int_fast16_t = -2147483648; pub const INT_FAST32_MIN: int_fast32_t = -2147483648; pub const INT_FAST8_MAX: int_fast8_t = 127; pub const INT_FAST16_MAX: int_fast16_t = 2147483647; pub const INT_FAST32_MAX: int_fast32_t = 2147483647; pub const UINT_FAST8_MAX: uint_fast8_t = 255; pub const UINT_FAST16_MAX: uint_fast16_t = 4294967295; pub const UINT_FAST32_MAX: uint_fast32_t = 4294967295; pub const INTPTR_MIN: __intptr_t = -2147483648; pub const INTPTR_MAX: __intptr_t = 2147483647; pub const UINTPTR_MAX: usize = 4294967295; pub const PTRDIFF_MIN: __ptrdiff_t = -2147483648; pub const PTRDIFF_MAX: __ptrdiff_t = 2147483647; pub const SIG_ATOMIC_MIN: __sig_atomic_t = -2147483648; pub const SIG_ATOMIC_MAX: __sig_atomic_t = 2147483647; pub const SIZE_MAX: usize = 4294967295; pub const WINT_MIN: wint_t = 0; pub const WINT_MAX: wint_t = 4294967295; pub const INT8_WIDTH: usize = 8; pub const UINT8_WIDTH: usize = 8; pub const INT16_WIDTH: usize = 16; pub const UINT16_WIDTH: usize = 16; pub const INT32_WIDTH: usize = 32; pub const UINT32_WIDTH: usize = 32; pub const INT64_WIDTH: usize = 64; pub const UINT64_WIDTH: usize = 64; pub const INT_LEAST8_WIDTH: usize = 8; pub const UINT_LEAST8_WIDTH: usize = 8; pub const INT_LEAST16_WIDTH: usize = 16; pub const UINT_LEAST16_WIDTH: usize = 16; pub const INT_LEAST32_WIDTH: usize = 32; pub const UINT_LEAST32_WIDTH: usize = 32; pub const INT_LEAST64_WIDTH: usize = 64; pub const UINT_LEAST64_WIDTH: usize = 64; pub const INT_FAST8_WIDTH: usize = 8; pub const UINT_FAST8_WIDTH: usize = 8; pub const INT_FAST16_WIDTH: usize = 32; pub const UINT_FAST16_WIDTH: usize = 32; pub const INT_FAST32_WIDTH: usize = 32; pub const UINT_FAST32_WIDTH: usize = 32; pub const INT_FAST64_WIDTH: usize = 64; pub const UINT_FAST64_WIDTH: usize = 64; pub const INTPTR_WIDTH: usize = 32; pub const UINTPTR_WIDTH: usize = 32; pub const INTMAX_WIDTH: usize = 64; pub const UINTMAX_WIDTH: usize = 64; pub const PTRDIFF_WIDTH: usize = 32; pub const SIG_ATOMIC_WIDTH: usize = 32; pub const SIZE_WIDTH: usize = 32; pub const WCHAR_WIDTH: usize = 32; pub const WINT_WIDTH: usize = 32; pub const TH_FIN: u8 = 1; pub const TH_SYN: u8 = 2; pub const TH_RST: u8 = 4; pub const TH_PUSH: u8 = 8; pub const TH_ACK: u8 = 16; pub const TH_URG: u8 = 32; pub const TCPOPT_EOL: u8 = 0; pub const TCPOPT_NOP: u8 = 1; pub const TCPOPT_MAXSEG: u8 = 2; pub const TCPOLEN_MAXSEG: u8 = 4; pub const TCPOPT_WINDOW: u8 = 3; pub const TCPOLEN_WINDOW: u8 = 3; pub const TCPOPT_SACK_PERMITTED: u8 = 4; pub const TCPOLEN_SACK_PERMITTED: u8 = 2; pub const TCPOPT_SACK: u8 = 5; pub const TCPOPT_TIMESTAMP: u8 = 8; pub const TCPOLEN_TIMESTAMP: u8 = 10; pub const TCPOLEN_TSTAMP_APPA: u8 = 12; pub const TCPOPT_TSTAMP_HDR: u32 = 16844810; pub const TCP_MSS: usize = 512; pub const TCP_MAXWIN: usize = 65535; pub const TCP_MAX_WINSHIFT: usize = 14; pub const TCPI_OPT_TIMESTAMPS: u8 = 1; pub const TCPI_OPT_SACK: u8 = 2; pub const TCPI_OPT_WSCALE: u8 = 4; pub const TCPI_OPT_ECN: u8 = 8; pub const TCPI_OPT_ECN_SEEN: u8 = 16; pub const TCPI_OPT_SYN_DATA: u8 = 32; pub const TCP_MD5SIG_MAXKEYLEN: usize = 80; pub const TCP_MD5SIG_FLAG_PREFIX: usize = 1; pub const TCP_COOKIE_MIN: usize = 8; pub const TCP_COOKIE_MAX: usize = 16; pub const TCP_COOKIE_PAIR_SIZE: usize = 32; pub const TCP_COOKIE_IN_ALWAYS: c_int = 1; pub const TCP_COOKIE_OUT_NEVER: c_int = 2; pub const TCP_S_DATA_IN: c_int = 4; pub const TCP_S_DATA_OUT: c_int = 8; pub const TCP_MSS_DEFAULT: usize = 536; pub const TCP_MSS_DESIRED: usize = 1220; // sys/wait.h pub const WCOREFLAG: c_int = 128; pub const WAIT_ANY: pid_t = -1; pub const WAIT_MYPGRP: pid_t = 0; // sys/file.h pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_UN: c_int = 8; pub const LOCK_NB: c_int = 4; // sys/mman.h pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 4; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 1; pub const MAP_FILE: c_int = 1; pub const MAP_ANON: c_int = 2; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const MAP_TYPE: c_int = 15; pub const MAP_COPY: c_int = 32; pub const MAP_SHARED: c_int = 16; pub const MAP_PRIVATE: c_int = 0; pub const MAP_FIXED: c_int = 256; pub const MAP_NOEXTEND: c_int = 512; pub const MAP_HASSEMAPHORE: c_int = 1024; pub const MAP_INHERIT: c_int = 2048; pub const MAP_32BIT: c_int = 4096; pub const MAP_EXCL: c_int = 16384; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 1; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const POSIX_MADV_WONTNEED: c_int = 4; pub const MS_ASYNC: c_int = 1; pub const MS_SYNC: c_int = 0; pub const MS_INVALIDATE: c_int = 2; pub const MREMAP_MAYMOVE: c_int = 1; pub const MREMAP_FIXED: c_int = 2; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; // sys/xattr.h pub const XATTR_CREATE: c_int = 0x1; pub const XATTR_REPLACE: c_int = 0x2; // spawn.h pub const POSIX_SPAWN_USEVFORK: c_int = 64; pub const POSIX_SPAWN_SETSID: c_int = 128; // sys/syslog.h pub const LOG_CRON: c_int = 9 << 3; pub const LOG_AUTHPRIV: c_int = 10 << 3; pub const LOG_FTP: c_int = 11 << 3; pub const LOG_PERROR: c_int = 0x20; // net/if.h pub const IFF_UP: c_int = 0x1; pub const IFF_BROADCAST: c_int = 0x2; pub const IFF_DEBUG: c_int = 0x4; pub const IFF_LOOPBACK: c_int = 0x8; pub const IFF_POINTOPOINT: c_int = 0x10; pub const IFF_NOTRAILERS: c_int = 0x20; pub const IFF_RUNNING: c_int = 0x40; pub const IFF_NOARP: c_int = 0x80; pub const IFF_PROMISC: c_int = 0x100; pub const IFF_ALLMULTI: c_int = 0x200; pub const IFF_MASTER: c_int = 0x400; pub const IFF_SLAVE: c_int = 0x800; pub const IFF_MULTICAST: c_int = 0x1000; pub const IFF_PORTSEL: c_int = 0x2000; pub const IFF_AUTOMEDIA: c_int = 0x4000; pub const IFF_DYNAMIC: c_int = 0x8000; // random.h pub const GRND_NONBLOCK: c_uint = 1; pub const GRND_RANDOM: c_uint = 2; pub const GRND_INSECURE: c_uint = 4; pub const _PC_LINK_MAX: c_int = 0; pub const _PC_MAX_CANON: c_int = 1; pub const _PC_MAX_INPUT: c_int = 2; pub const _PC_NAME_MAX: c_int = 3; pub const _PC_PATH_MAX: c_int = 4; pub const _PC_PIPE_BUF: c_int = 5; pub const _PC_CHOWN_RESTRICTED: c_int = 6; pub const _PC_NO_TRUNC: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_SYNC_IO: c_int = 9; pub const _PC_ASYNC_IO: c_int = 10; pub const _PC_PRIO_IO: c_int = 11; pub const _PC_SOCK_MAXBUF: c_int = 12; pub const _PC_FILESIZEBITS: c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: c_int = 16; pub const _PC_REC_XFER_ALIGN: c_int = 17; pub const _PC_ALLOC_SIZE_MIN: c_int = 18; pub const _PC_SYMLINK_MAX: c_int = 19; pub const _PC_2_SYMLINKS: c_int = 20; pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_STREAM_MAX: c_int = 5; pub const _SC_TZNAME_MAX: c_int = 6; pub const _SC_JOB_CONTROL: c_int = 7; pub const _SC_SAVED_IDS: c_int = 8; pub const _SC_REALTIME_SIGNALS: c_int = 9; pub const _SC_PRIORITY_SCHEDULING: c_int = 10; pub const _SC_TIMERS: c_int = 11; pub const _SC_ASYNCHRONOUS_IO: c_int = 12; pub const _SC_PRIORITIZED_IO: c_int = 13; pub const _SC_SYNCHRONIZED_IO: c_int = 14; pub const _SC_FSYNC: c_int = 15; pub const _SC_MAPPED_FILES: c_int = 16; pub const _SC_MEMLOCK: c_int = 17; pub const _SC_MEMLOCK_RANGE: c_int = 18; pub const _SC_MEMORY_PROTECTION: c_int = 19; pub const _SC_MESSAGE_PASSING: c_int = 20; pub const _SC_SEMAPHORES: c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 22; pub const _SC_AIO_LISTIO_MAX: c_int = 23; pub const _SC_AIO_MAX: c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 25; pub const _SC_DELAYTIMER_MAX: c_int = 26; pub const _SC_MQ_OPEN_MAX: c_int = 27; pub const _SC_MQ_PRIO_MAX: c_int = 28; pub const _SC_VERSION: c_int = 29; pub const _SC_PAGESIZE: c_int = 30; pub const _SC_PAGE_SIZE: c_int = 30; pub const _SC_RTSIG_MAX: c_int = 31; pub const _SC_SEM_NSEMS_MAX: c_int = 32; pub const _SC_SEM_VALUE_MAX: c_int = 33; pub const _SC_SIGQUEUE_MAX: c_int = 34; pub const _SC_TIMER_MAX: c_int = 35; pub const _SC_BC_BASE_MAX: c_int = 36; pub const _SC_BC_DIM_MAX: c_int = 37; pub const _SC_BC_SCALE_MAX: c_int = 38; pub const _SC_BC_STRING_MAX: c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: c_int = 40; pub const _SC_EQUIV_CLASS_MAX: c_int = 41; pub const _SC_EXPR_NEST_MAX: c_int = 42; pub const _SC_LINE_MAX: c_int = 43; pub const _SC_RE_DUP_MAX: c_int = 44; pub const _SC_CHARCLASS_NAME_MAX: c_int = 45; pub const _SC_2_VERSION: c_int = 46; pub const _SC_2_C_BIND: c_int = 47; pub const _SC_2_C_DEV: c_int = 48; pub const _SC_2_FORT_DEV: c_int = 49; pub const _SC_2_FORT_RUN: c_int = 50; pub const _SC_2_SW_DEV: c_int = 51; pub const _SC_2_LOCALEDEF: c_int = 52; pub const _SC_PII: c_int = 53; pub const _SC_PII_XTI: c_int = 54; pub const _SC_PII_SOCKET: c_int = 55; pub const _SC_PII_INTERNET: c_int = 56; pub const _SC_PII_OSI: c_int = 57; pub const _SC_POLL: c_int = 58; pub const _SC_SELECT: c_int = 59; pub const _SC_UIO_MAXIOV: c_int = 60; pub const _SC_IOV_MAX: c_int = 60; pub const _SC_PII_INTERNET_STREAM: c_int = 61; pub const _SC_PII_INTERNET_DGRAM: c_int = 62; pub const _SC_PII_OSI_COTS: c_int = 63; pub const _SC_PII_OSI_CLTS: c_int = 64; pub const _SC_PII_OSI_M: c_int = 65; pub const _SC_T_IOV_MAX: c_int = 66; pub const _SC_THREADS: c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: c_int = 70; pub const _SC_LOGIN_NAME_MAX: c_int = 71; pub const _SC_TTY_NAME_MAX: c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73; pub const _SC_THREAD_KEYS_MAX: c_int = 74; pub const _SC_THREAD_STACK_MIN: c_int = 75; pub const _SC_THREAD_THREADS_MAX: c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: c_int = 82; pub const _SC_NPROCESSORS_CONF: c_int = 83; pub const _SC_NPROCESSORS_ONLN: c_int = 84; pub const _SC_PHYS_PAGES: c_int = 85; pub const _SC_AVPHYS_PAGES: c_int = 86; pub const _SC_ATEXIT_MAX: c_int = 87; pub const _SC_PASS_MAX: c_int = 88; pub const _SC_XOPEN_VERSION: c_int = 89; pub const _SC_XOPEN_XCU_VERSION: c_int = 90; pub const _SC_XOPEN_UNIX: c_int = 91; pub const _SC_XOPEN_CRYPT: c_int = 92; pub const _SC_XOPEN_ENH_I18N: c_int = 93; pub const _SC_XOPEN_SHM: c_int = 94; pub const _SC_2_CHAR_TERM: c_int = 95; pub const _SC_2_C_VERSION: c_int = 96; pub const _SC_2_UPE: c_int = 97; pub const _SC_XOPEN_XPG2: c_int = 98; pub const _SC_XOPEN_XPG3: c_int = 99; pub const _SC_XOPEN_XPG4: c_int = 100; pub const _SC_CHAR_BIT: c_int = 101; pub const _SC_CHAR_MAX: c_int = 102; pub const _SC_CHAR_MIN: c_int = 103; pub const _SC_INT_MAX: c_int = 104; pub const _SC_INT_MIN: c_int = 105; pub const _SC_LONG_BIT: c_int = 106; pub const _SC_WORD_BIT: c_int = 107; pub const _SC_MB_LEN_MAX: c_int = 108; pub const _SC_NZERO: c_int = 109; pub const _SC_SSIZE_MAX: c_int = 110; pub const _SC_SCHAR_MAX: c_int = 111; pub const _SC_SCHAR_MIN: c_int = 112; pub const _SC_SHRT_MAX: c_int = 113; pub const _SC_SHRT_MIN: c_int = 114; pub const _SC_UCHAR_MAX: c_int = 115; pub const _SC_UINT_MAX: c_int = 116; pub const _SC_ULONG_MAX: c_int = 117; pub const _SC_USHRT_MAX: c_int = 118; pub const _SC_NL_ARGMAX: c_int = 119; pub const _SC_NL_LANGMAX: c_int = 120; pub const _SC_NL_MSGMAX: c_int = 121; pub const _SC_NL_NMAX: c_int = 122; pub const _SC_NL_SETMAX: c_int = 123; pub const _SC_NL_TEXTMAX: c_int = 124; pub const _SC_XBS5_ILP32_OFF32: c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 126; pub const _SC_XBS5_LP64_OFF64: c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 128; pub const _SC_XOPEN_LEGACY: c_int = 129; pub const _SC_XOPEN_REALTIME: c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131; pub const _SC_ADVISORY_INFO: c_int = 132; pub const _SC_BARRIERS: c_int = 133; pub const _SC_BASE: c_int = 134; pub const _SC_C_LANG_SUPPORT: c_int = 135; pub const _SC_C_LANG_SUPPORT_R: c_int = 136; pub const _SC_CLOCK_SELECTION: c_int = 137; pub const _SC_CPUTIME: c_int = 138; pub const _SC_THREAD_CPUTIME: c_int = 139; pub const _SC_DEVICE_IO: c_int = 140; pub const _SC_DEVICE_SPECIFIC: c_int = 141; pub const _SC_DEVICE_SPECIFIC_R: c_int = 142; pub const _SC_FD_MGMT: c_int = 143; pub const _SC_FIFO: c_int = 144; pub const _SC_PIPE: c_int = 145; pub const _SC_FILE_ATTRIBUTES: c_int = 146; pub const _SC_FILE_LOCKING: c_int = 147; pub const _SC_FILE_SYSTEM: c_int = 148; pub const _SC_MONOTONIC_CLOCK: c_int = 149; pub const _SC_MULTI_PROCESS: c_int = 150; pub const _SC_SINGLE_PROCESS: c_int = 151; pub const _SC_NETWORKING: c_int = 152; pub const _SC_READER_WRITER_LOCKS: c_int = 153; pub const _SC_SPIN_LOCKS: c_int = 154; pub const _SC_REGEXP: c_int = 155; pub const _SC_REGEX_VERSION: c_int = 156; pub const _SC_SHELL: c_int = 157; pub const _SC_SIGNALS: c_int = 158; pub const _SC_SPAWN: c_int = 159; pub const _SC_SPORADIC_SERVER: c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 161; pub const _SC_SYSTEM_DATABASE: c_int = 162; pub const _SC_SYSTEM_DATABASE_R: c_int = 163; pub const _SC_TIMEOUTS: c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 165; pub const _SC_USER_GROUPS: c_int = 166; pub const _SC_USER_GROUPS_R: c_int = 167; pub const _SC_2_PBS: c_int = 168; pub const _SC_2_PBS_ACCOUNTING: c_int = 169; pub const _SC_2_PBS_LOCATE: c_int = 170; pub const _SC_2_PBS_MESSAGE: c_int = 171; pub const _SC_2_PBS_TRACK: c_int = 172; pub const _SC_SYMLOOP_MAX: c_int = 173; pub const _SC_STREAMS: c_int = 174; pub const _SC_2_PBS_CHECKPOINT: c_int = 175; pub const _SC_V6_ILP32_OFF32: c_int = 176; pub const _SC_V6_ILP32_OFFBIG: c_int = 177; pub const _SC_V6_LP64_OFF64: c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: c_int = 179; pub const _SC_HOST_NAME_MAX: c_int = 180; pub const _SC_TRACE: c_int = 181; pub const _SC_TRACE_EVENT_FILTER: c_int = 182; pub const _SC_TRACE_INHERIT: c_int = 183; pub const _SC_TRACE_LOG: c_int = 184; pub const _SC_LEVEL1_ICACHE_SIZE: c_int = 185; pub const _SC_LEVEL1_ICACHE_ASSOC: c_int = 186; pub const _SC_LEVEL1_ICACHE_LINESIZE: c_int = 187; pub const _SC_LEVEL1_DCACHE_SIZE: c_int = 188; pub const _SC_LEVEL1_DCACHE_ASSOC: c_int = 189; pub const _SC_LEVEL1_DCACHE_LINESIZE: c_int = 190; pub const _SC_LEVEL2_CACHE_SIZE: c_int = 191; pub const _SC_LEVEL2_CACHE_ASSOC: c_int = 192; pub const _SC_LEVEL2_CACHE_LINESIZE: c_int = 193; pub const _SC_LEVEL3_CACHE_SIZE: c_int = 194; pub const _SC_LEVEL3_CACHE_ASSOC: c_int = 195; pub const _SC_LEVEL3_CACHE_LINESIZE: c_int = 196; pub const _SC_LEVEL4_CACHE_SIZE: c_int = 197; pub const _SC_LEVEL4_CACHE_ASSOC: c_int = 198; pub const _SC_LEVEL4_CACHE_LINESIZE: c_int = 199; pub const _SC_IPV6: c_int = 235; pub const _SC_RAW_SOCKETS: c_int = 236; pub const _SC_V7_ILP32_OFF32: c_int = 237; pub const _SC_V7_ILP32_OFFBIG: c_int = 238; pub const _SC_V7_LP64_OFF64: c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: c_int = 240; pub const _SC_SS_REPL_MAX: c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 242; pub const _SC_TRACE_NAME_MAX: c_int = 243; pub const _SC_TRACE_SYS_MAX: c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 245; pub const _SC_XOPEN_STREAMS: c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 248; pub const _SC_MINSIGSTKSZ: c_int = 249; pub const _SC_SIGSTKSZ: c_int = 250; pub const _CS_PATH: c_int = 0; pub const _CS_V6_WIDTH_RESTRICTED_ENVS: c_int = 1; pub const _CS_GNU_LIBC_VERSION: c_int = 2; pub const _CS_GNU_LIBPTHREAD_VERSION: c_int = 3; pub const _CS_V5_WIDTH_RESTRICTED_ENVS: c_int = 4; pub const _CS_V7_WIDTH_RESTRICTED_ENVS: c_int = 5; pub const _CS_LFS_CFLAGS: c_int = 1000; pub const _CS_LFS_LDFLAGS: c_int = 1001; pub const _CS_LFS_LIBS: c_int = 1002; pub const _CS_LFS_LINTFLAGS: c_int = 1003; pub const _CS_LFS64_CFLAGS: c_int = 1004; pub const _CS_LFS64_LDFLAGS: c_int = 1005; pub const _CS_LFS64_LIBS: c_int = 1006; pub const _CS_LFS64_LINTFLAGS: c_int = 1007; pub const _CS_XBS5_ILP32_OFF32_CFLAGS: c_int = 1100; pub const _CS_XBS5_ILP32_OFF32_LDFLAGS: c_int = 1101; pub const _CS_XBS5_ILP32_OFF32_LIBS: c_int = 1102; pub const _CS_XBS5_ILP32_OFF32_LINTFLAGS: c_int = 1103; pub const _CS_XBS5_ILP32_OFFBIG_CFLAGS: c_int = 1104; pub const _CS_XBS5_ILP32_OFFBIG_LDFLAGS: c_int = 1105; pub const _CS_XBS5_ILP32_OFFBIG_LIBS: c_int = 1106; pub const _CS_XBS5_ILP32_OFFBIG_LINTFLAGS: c_int = 1107; pub const _CS_XBS5_LP64_OFF64_CFLAGS: c_int = 1108; pub const _CS_XBS5_LP64_OFF64_LDFLAGS: c_int = 1109; pub const _CS_XBS5_LP64_OFF64_LIBS: c_int = 1110; pub const _CS_XBS5_LP64_OFF64_LINTFLAGS: c_int = 1111; pub const _CS_XBS5_LPBIG_OFFBIG_CFLAGS: c_int = 1112; pub const _CS_XBS5_LPBIG_OFFBIG_LDFLAGS: c_int = 1113; pub const _CS_XBS5_LPBIG_OFFBIG_LIBS: c_int = 1114; pub const _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS: c_int = 1115; pub const _CS_POSIX_V6_ILP32_OFF32_CFLAGS: c_int = 1116; pub const _CS_POSIX_V6_ILP32_OFF32_LDFLAGS: c_int = 1117; pub const _CS_POSIX_V6_ILP32_OFF32_LIBS: c_int = 1118; pub const _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS: c_int = 1119; pub const _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS: c_int = 1120; pub const _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS: c_int = 1121; pub const _CS_POSIX_V6_ILP32_OFFBIG_LIBS: c_int = 1122; pub const _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS: c_int = 1123; pub const _CS_POSIX_V6_LP64_OFF64_CFLAGS: c_int = 1124; pub const _CS_POSIX_V6_LP64_OFF64_LDFLAGS: c_int = 1125; pub const _CS_POSIX_V6_LP64_OFF64_LIBS: c_int = 1126; pub const _CS_POSIX_V6_LP64_OFF64_LINTFLAGS: c_int = 1127; pub const _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS: c_int = 1128; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS: c_int = 1129; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LIBS: c_int = 1130; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS: c_int = 1131; pub const _CS_POSIX_V7_ILP32_OFF32_CFLAGS: c_int = 1132; pub const _CS_POSIX_V7_ILP32_OFF32_LDFLAGS: c_int = 1133; pub const _CS_POSIX_V7_ILP32_OFF32_LIBS: c_int = 1134; pub const _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS: c_int = 1135; pub const _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS: c_int = 1136; pub const _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS: c_int = 1137; pub const _CS_POSIX_V7_ILP32_OFFBIG_LIBS: c_int = 1138; pub const _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS: c_int = 1139; pub const _CS_POSIX_V7_LP64_OFF64_CFLAGS: c_int = 1140; pub const _CS_POSIX_V7_LP64_OFF64_LDFLAGS: c_int = 1141; pub const _CS_POSIX_V7_LP64_OFF64_LIBS: c_int = 1142; pub const _CS_POSIX_V7_LP64_OFF64_LINTFLAGS: c_int = 1143; pub const _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS: c_int = 1144; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS: c_int = 1145; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LIBS: c_int = 1146; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS: c_int = 1147; pub const _CS_V6_ENV: c_int = 1148; pub const _CS_V7_ENV: c_int = 1149; pub const PTHREAD_PROCESS_PRIVATE: __pthread_process_shared = 0; pub const PTHREAD_PROCESS_SHARED: __pthread_process_shared = 1; pub const PTHREAD_EXPLICIT_SCHED: __pthread_inheritsched = 0; pub const PTHREAD_INHERIT_SCHED: __pthread_inheritsched = 1; pub const PTHREAD_SCOPE_SYSTEM: __pthread_contentionscope = 0; pub const PTHREAD_SCOPE_PROCESS: __pthread_contentionscope = 1; pub const PTHREAD_CREATE_JOINABLE: __pthread_detachstate = 0; pub const PTHREAD_CREATE_DETACHED: __pthread_detachstate = 1; pub const PTHREAD_PRIO_NONE: __pthread_mutex_protocol = 0; pub const PTHREAD_PRIO_INHERIT: __pthread_mutex_protocol = 1; pub const PTHREAD_PRIO_PROTECT: __pthread_mutex_protocol = 2; pub const PTHREAD_MUTEX_TIMED: __pthread_mutex_type = 0; pub const PTHREAD_MUTEX_ERRORCHECK: __pthread_mutex_type = 1; pub const PTHREAD_MUTEX_RECURSIVE: __pthread_mutex_type = 2; pub const PTHREAD_MUTEX_STALLED: __pthread_mutex_robustness = 0; pub const PTHREAD_MUTEX_ROBUST: __pthread_mutex_robustness = 256; pub const RLIMIT_CPU: crate::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: crate::__rlimit_resource_t = 1; pub const RLIMIT_DATA: crate::__rlimit_resource_t = 2; pub const RLIMIT_STACK: crate::__rlimit_resource_t = 3; pub const RLIMIT_CORE: crate::__rlimit_resource_t = 4; pub const RLIMIT_RSS: crate::__rlimit_resource_t = 5; pub const RLIMIT_MEMLOCK: crate::__rlimit_resource_t = 6; pub const RLIMIT_NPROC: crate::__rlimit_resource_t = 7; pub const RLIMIT_OFILE: crate::__rlimit_resource_t = 8; pub const RLIMIT_NOFILE: crate::__rlimit_resource_t = 8; pub const RLIMIT_SBSIZE: crate::__rlimit_resource_t = 9; pub const RLIMIT_AS: crate::__rlimit_resource_t = 10; pub const RLIMIT_VMEM: crate::__rlimit_resource_t = 10; pub const RLIMIT_NLIMITS: crate::__rlimit_resource_t = 11; pub const RLIM_NLIMITS: crate::__rlimit_resource_t = 11; pub const RUSAGE_SELF: __rusage_who = 0; pub const RUSAGE_CHILDREN: __rusage_who = -1; pub const PRIO_PROCESS: __priority_which = 0; pub const PRIO_PGRP: __priority_which = 1; pub const PRIO_USER: __priority_which = 2; pub const __UT_LINESIZE: usize = 32; pub const __UT_NAMESIZE: usize = 32; pub const __UT_HOSTSIZE: usize = 256; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_SEQPACKET: c_int = 5; pub const SOCK_CLOEXEC: c_int = 4194304; pub const SOCK_NONBLOCK: c_int = 2048; pub const MSG_OOB: c_int = 1; pub const MSG_PEEK: c_int = 2; pub const MSG_DONTROUTE: c_int = 4; pub const MSG_EOR: c_int = 8; pub const MSG_TRUNC: c_int = 16; pub const MSG_CTRUNC: c_int = 32; pub const MSG_WAITALL: c_int = 64; pub const MSG_DONTWAIT: c_int = 128; pub const MSG_NOSIGNAL: c_int = 1024; pub const MSG_CMSG_CLOEXEC: c_int = 0x40000000; pub const SCM_RIGHTS: c_int = 1; pub const SCM_TIMESTAMP: c_int = 2; pub const SCM_CREDS: c_int = 3; pub const SO_DEBUG: c_int = 1; pub const SO_ACCEPTCONN: c_int = 2; pub const SO_REUSEADDR: c_int = 4; pub const SO_KEEPALIVE: c_int = 8; pub const SO_DONTROUTE: c_int = 16; pub const SO_BROADCAST: c_int = 32; pub const SO_USELOOPBACK: c_int = 64; pub const SO_LINGER: c_int = 128; pub const SO_OOBINLINE: c_int = 256; pub const SO_REUSEPORT: c_int = 512; pub const SO_SNDBUF: c_int = 4097; pub const SO_RCVBUF: c_int = 4098; pub const SO_SNDLOWAT: c_int = 4099; pub const SO_RCVLOWAT: c_int = 4100; pub const SO_SNDTIMEO: c_int = 4101; pub const SO_RCVTIMEO: c_int = 4102; pub const SO_ERROR: c_int = 4103; pub const SO_STYLE: c_int = 4104; pub const SO_TYPE: c_int = 4104; pub const IPPROTO_IP: c_int = 0; pub const IPPROTO_ICMP: c_int = 1; pub const IPPROTO_IGMP: c_int = 2; pub const IPPROTO_IPIP: c_int = 4; pub const IPPROTO_TCP: c_int = 6; pub const IPPROTO_EGP: c_int = 8; pub const IPPROTO_PUP: c_int = 12; pub const IPPROTO_UDP: c_int = 17; pub const IPPROTO_IDP: c_int = 22; pub const IPPROTO_TP: c_int = 29; pub const IPPROTO_DCCP: c_int = 33; pub const IPPROTO_IPV6: c_int = 41; pub const IPPROTO_RSVP: c_int = 46; pub const IPPROTO_GRE: c_int = 47; pub const IPPROTO_ESP: c_int = 50; pub const IPPROTO_AH: c_int = 51; pub const IPPROTO_MTP: c_int = 92; pub const IPPROTO_BEETPH: c_int = 94; pub const IPPROTO_ENCAP: c_int = 98; pub const IPPROTO_PIM: c_int = 103; pub const IPPROTO_COMP: c_int = 108; pub const IPPROTO_L2TP: c_int = 115; pub const IPPROTO_SCTP: c_int = 132; pub const IPPROTO_UDPLITE: c_int = 136; pub const IPPROTO_MPLS: c_int = 137; pub const IPPROTO_ETHERNET: c_int = 143; pub const IPPROTO_RAW: c_int = 255; pub const IPPROTO_MPTCP: c_int = 262; pub const IPPROTO_MAX: c_int = 263; pub const IPPROTO_HOPOPTS: c_int = 0; pub const IPPROTO_ROUTING: c_int = 43; pub const IPPROTO_FRAGMENT: c_int = 44; pub const IPPROTO_ICMPV6: c_int = 58; pub const IPPROTO_NONE: c_int = 59; pub const IPPROTO_DSTOPTS: c_int = 60; pub const IPPROTO_MH: c_int = 135; pub const IPPORT_ECHO: in_port_t = 7; pub const IPPORT_DISCARD: in_port_t = 9; pub const IPPORT_SYSTAT: in_port_t = 11; pub const IPPORT_DAYTIME: in_port_t = 13; pub const IPPORT_NETSTAT: in_port_t = 15; pub const IPPORT_FTP: in_port_t = 21; pub const IPPORT_TELNET: in_port_t = 23; pub const IPPORT_SMTP: in_port_t = 25; pub const IPPORT_TIMESERVER: in_port_t = 37; pub const IPPORT_NAMESERVER: in_port_t = 42; pub const IPPORT_WHOIS: in_port_t = 43; pub const IPPORT_MTP: in_port_t = 57; pub const IPPORT_TFTP: in_port_t = 69; pub const IPPORT_RJE: in_port_t = 77; pub const IPPORT_FINGER: in_port_t = 79; pub const IPPORT_TTYLINK: in_port_t = 87; pub const IPPORT_SUPDUP: in_port_t = 95; pub const IPPORT_EXECSERVER: in_port_t = 512; pub const IPPORT_LOGINSERVER: in_port_t = 513; pub const IPPORT_CMDSERVER: in_port_t = 514; pub const IPPORT_EFSSERVER: in_port_t = 520; pub const IPPORT_BIFFUDP: in_port_t = 512; pub const IPPORT_WHOSERVER: in_port_t = 513; pub const IPPORT_ROUTESERVER: in_port_t = 520; pub const IPPORT_USERRESERVED: in_port_t = 5000; pub const DT_UNKNOWN: c_uchar = 0; pub const DT_FIFO: c_uchar = 1; pub const DT_CHR: c_uchar = 2; pub const DT_DIR: c_uchar = 4; pub const DT_BLK: c_uchar = 6; pub const DT_REG: c_uchar = 8; pub const DT_LNK: c_uchar = 10; pub const DT_SOCK: c_uchar = 12; pub const DT_WHT: c_uchar = 14; pub const ST_RDONLY: c_ulong = 1; pub const ST_NOSUID: c_ulong = 2; pub const ST_NOEXEC: c_ulong = 8; pub const ST_SYNCHRONOUS: c_ulong = 16; pub const ST_NOATIME: c_ulong = 32; pub const ST_RELATIME: c_ulong = 64; pub const RTLD_DI_LMID: c_int = 1; pub const RTLD_DI_LINKMAP: c_int = 2; pub const RTLD_DI_CONFIGADDR: c_int = 3; pub const RTLD_DI_SERINFO: c_int = 4; pub const RTLD_DI_SERINFOSIZE: c_int = 5; pub const RTLD_DI_ORIGIN: c_int = 6; pub const RTLD_DI_PROFILENAME: c_int = 7; pub const RTLD_DI_PROFILEOUT: c_int = 8; pub const RTLD_DI_TLS_MODID: c_int = 9; pub const RTLD_DI_TLS_DATA: c_int = 10; pub const RTLD_DI_PHDR: c_int = 11; pub const RTLD_DI_MAX: c_int = 11; pub const SI_ASYNCIO: c_int = -4; pub const SI_MESGQ: c_int = -3; pub const SI_TIMER: c_int = -2; pub const SI_QUEUE: c_int = -1; pub const SI_USER: c_int = 0; pub const ILL_ILLOPC: c_int = 1; pub const ILL_ILLOPN: c_int = 2; pub const ILL_ILLADR: c_int = 3; pub const ILL_ILLTRP: c_int = 4; pub const ILL_PRVOPC: c_int = 5; pub const ILL_PRVREG: c_int = 6; pub const ILL_COPROC: c_int = 7; pub const ILL_BADSTK: c_int = 8; pub const FPE_INTDIV: c_int = 1; pub const FPE_INTOVF: c_int = 2; pub const FPE_FLTDIV: c_int = 3; pub const FPE_FLTOVF: c_int = 4; pub const FPE_FLTUND: c_int = 5; pub const FPE_FLTRES: c_int = 6; pub const FPE_FLTINV: c_int = 7; pub const FPE_FLTSUB: c_int = 8; pub const SEGV_MAPERR: c_int = 1; pub const SEGV_ACCERR: c_int = 2; pub const BUS_ADRALN: c_int = 1; pub const BUS_ADRERR: c_int = 2; pub const BUS_OBJERR: c_int = 3; pub const TRAP_BRKPT: c_int = 1; pub const TRAP_TRACE: c_int = 2; pub const CLD_EXITED: c_int = 1; pub const CLD_KILLED: c_int = 2; pub const CLD_DUMPED: c_int = 3; pub const CLD_TRAPPED: c_int = 4; pub const CLD_STOPPED: c_int = 5; pub const CLD_CONTINUED: c_int = 6; pub const POLL_IN: c_int = 1; pub const POLL_OUT: c_int = 2; pub const POLL_MSG: c_int = 3; pub const POLL_ERR: c_int = 4; pub const POLL_PRI: c_int = 5; pub const POLL_HUP: c_int = 6; pub const SIGEV_SIGNAL: c_int = 0; pub const SIGEV_NONE: c_int = 1; pub const SIGEV_THREAD: c_int = 2; pub const REG_GS: c_uint = 0; pub const REG_FS: c_uint = 1; pub const REG_ES: c_uint = 2; pub const REG_DS: c_uint = 3; pub const REG_EDI: c_uint = 4; pub const REG_ESI: c_uint = 5; pub const REG_EBP: c_uint = 6; pub const REG_ESP: c_uint = 7; pub const REG_EBX: c_uint = 8; pub const REG_EDX: c_uint = 9; pub const REG_ECX: c_uint = 10; pub const REG_EAX: c_uint = 11; pub const REG_TRAPNO: c_uint = 12; pub const REG_ERR: c_uint = 13; pub const REG_EIP: c_uint = 14; pub const REG_CS: c_uint = 15; pub const REG_EFL: c_uint = 16; pub const REG_UESP: c_uint = 17; pub const REG_SS: c_uint = 18; pub const IOC_VOID: __ioctl_dir = 0; pub const IOC_OUT: __ioctl_dir = 1; pub const IOC_IN: __ioctl_dir = 2; pub const IOC_INOUT: __ioctl_dir = 3; pub const IOC_8: __ioctl_datum = 0; pub const IOC_16: __ioctl_datum = 1; pub const IOC_32: __ioctl_datum = 2; pub const IOC_64: __ioctl_datum = 3; pub const TCP_ESTABLISHED: c_uint = 1; pub const TCP_SYN_SENT: c_uint = 2; pub const TCP_SYN_RECV: c_uint = 3; pub const TCP_FIN_WAIT1: c_uint = 4; pub const TCP_FIN_WAIT2: c_uint = 5; pub const TCP_TIME_WAIT: c_uint = 6; pub const TCP_CLOSE: c_uint = 7; pub const TCP_CLOSE_WAIT: c_uint = 8; pub const TCP_LAST_ACK: c_uint = 9; pub const TCP_LISTEN: c_uint = 10; pub const TCP_CLOSING: c_uint = 11; pub const TCP_CA_Open: tcp_ca_state = 0; pub const TCP_CA_Disorder: tcp_ca_state = 1; pub const TCP_CA_CWR: tcp_ca_state = 2; pub const TCP_CA_Recovery: tcp_ca_state = 3; pub const TCP_CA_Loss: tcp_ca_state = 4; pub const TCP_NO_QUEUE: c_uint = 0; pub const TCP_RECV_QUEUE: c_uint = 1; pub const TCP_SEND_QUEUE: c_uint = 2; pub const TCP_QUEUES_NR: c_uint = 3; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const SS_ONSTACK: c_int = 1; pub const SS_DISABLE: c_int = 4; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __lock: 0, __owner_id: 0, __cnt: 0, __shpid: 0, __type: PTHREAD_MUTEX_TIMED as c_int, __flags: 0, __reserved1: 0, __reserved2: 0, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __lock: __PTHREAD_SPIN_LOCK_INITIALIZER, __queue: 0i64 as *mut __pthread, __attr: 0i64 as *mut __pthread_condattr, __wrefs: 0, __data: 0i64 as *mut c_void, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __held: __PTHREAD_SPIN_LOCK_INITIALIZER, __lock: __PTHREAD_SPIN_LOCK_INITIALIZER, __readers: 0, __readerqueue: 0i64 as *mut __pthread, __writerqueue: 0i64 as *mut __pthread, __attr: 0i64 as *mut __pthread_rwlockattr, __data: 0i64 as *mut c_void, }; pub const PTHREAD_STACK_MIN: size_t = 0; // Non-public helper constants const _UTSNAME_LENGTH: usize = 1024; const_fn! { {const} fn CMSG_ALIGN(len: usize) -> usize { len + mem::size_of::() - 1 & !(mem::size_of::() - 1) } } // functions f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(CMSG_ALIGN(mem::size_of::()) as isize) } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(mem::size_of::())) as c_uint } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { CMSG_ALIGN(mem::size_of::()) as c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as usize) < mem::size_of::() { return 0 as *mut cmsghdr; }; let next = (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if (next.offset(1)) as usize > max || next as usize + CMSG_ALIGN((*next).cmsg_len as usize) > max { 0 as *mut cmsghdr } else { next as *mut cmsghdr } } pub fn CPU_ALLOC_SIZE(count: c_int) -> size_t { let _dummy: cpu_set_t = mem::zeroed(); let size_in_bits = 8 * mem::size_of_val(&_dummy.bits[0]); ((count as size_t + size_in_bits - 1) / 8) as size_t } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> c_int { let mut s: u32 = 0; let size_of_mask = mem::size_of_val(&cpuset.bits[0]); for i in cpuset.bits[..(size / size_of_mask)].iter() { s += i.count_ones(); } s as c_int } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> c_int { CPU_COUNT_S(mem::size_of::(), cpuset) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } pub fn IPTOS_TOS(tos: u8) -> u8 { tos & IPTOS_TOS_MASK } pub fn IPTOS_PREC(tos: u8) -> u8 { tos & IPTOS_PREC_MASK } pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } extern "C" { pub fn lutimes(file: *const c_char, times: *const crate::timeval) -> c_int; pub fn futimes(fd: c_int, times: *const crate::timeval) -> c_int; pub fn futimens(__fd: c_int, __times: *const crate::timespec) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn mkfifoat(__fd: c_int, __path: *const c_char, __mode: __mode_t) -> c_int; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn __libc_current_sigrtmin() -> c_int; pub fn __libc_current_sigrtmax() -> c_int; pub fn wait4( pid: crate::pid_t, status: *mut c_int, options: c_int, rusage: *mut crate::rusage, ) -> crate::pid_t; pub fn waitid( idtype: idtype_t, id: id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn sigwait(__set: *const sigset_t, __sig: *mut c_int) -> c_int; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn ioctl(__fd: c_int, __request: c_ulong, ...) -> c_int; pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; pub fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int; pub fn pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: off64_t) -> ssize_t; pub fn pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: off64_t) -> ssize_t; pub fn readv(__fd: c_int, __iovec: *const crate::iovec, __count: c_int) -> ssize_t; pub fn writev(__fd: c_int, __iovec: *const crate::iovec, __count: c_int) -> ssize_t; pub fn preadv( __fd: c_int, __iovec: *const crate::iovec, __count: c_int, __offset: __off_t, ) -> ssize_t; pub fn pwritev( __fd: c_int, __iovec: *const crate::iovec, __count: c_int, __offset: __off_t, ) -> ssize_t; pub fn preadv64(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t) -> ssize_t; pub fn pwritev64( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, ) -> ssize_t; pub fn fread_unlocked( buf: *mut c_void, size: size_t, nobj: size_t, stream: *mut crate::FILE, ) -> size_t; pub fn aio_read(aiocbp: *mut aiocb) -> c_int; pub fn aio_write(aiocbp: *mut aiocb) -> c_int; pub fn aio_fsync(op: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_error(aiocbp: *const aiocb) -> c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn aio_cancel(fd: c_int, aiocbp: *mut aiocb) -> c_int; pub fn lio_listio( mode: c_int, aiocb_list: *const *mut aiocb, nitems: c_int, sevp: *mut crate::sigevent, ) -> c_int; pub fn mq_open(name: *const c_char, oflag: c_int, ...) -> crate::mqd_t; pub fn mq_close(mqd: crate::mqd_t) -> c_int; pub fn mq_unlink(name: *const c_char) -> c_int; pub fn mq_receive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, ) -> ssize_t; pub fn mq_timedreceive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, abs_timeout: *const crate::timespec, ) -> ssize_t; pub fn mq_send( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, ) -> c_int; pub fn mq_timedsend( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, abs_timeout: *const crate::timespec, ) -> c_int; pub fn mq_getattr(mqd: crate::mqd_t, attr: *mut crate::mq_attr) -> c_int; pub fn mq_setattr( mqd: crate::mqd_t, newattr: *const crate::mq_attr, oldattr: *mut crate::mq_attr, ) -> c_int; pub fn lseek64(__fd: c_int, __offset: __off64_t, __whence: c_int) -> __off64_t; pub fn lseek(__fd: c_int, __offset: __off_t, __whence: c_int) -> __off_t; pub fn fgetpos64(stream: *mut crate::FILE, ptr: *mut fpos64_t) -> c_int; pub fn fseeko64(stream: *mut crate::FILE, offset: off64_t, whence: c_int) -> c_int; pub fn fsetpos64(stream: *mut crate::FILE, ptr: *const fpos64_t) -> c_int; pub fn ftello64(stream: *mut crate::FILE) -> off64_t; pub fn bind(__fd: c_int, __addr: *const sockaddr, __len: crate::socklen_t) -> c_int; pub fn accept4( fd: c_int, addr: *mut crate::sockaddr, len: *mut crate::socklen_t, flg: c_int, ) -> c_int; pub fn ppoll( fds: *mut crate::pollfd, nfds: nfds_t, timeout: *const crate::timespec, sigmask: *const sigset_t, ) -> c_int; pub fn recvmsg(__fd: c_int, __message: *mut msghdr, __flags: c_int) -> ssize_t; pub fn sendmsg(__fd: c_int, __message: *const msghdr, __flags: c_int) -> ssize_t; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn sendfile(out_fd: c_int, in_fd: c_int, offset: *mut off_t, count: size_t) -> ssize_t; pub fn sendfile64(out_fd: c_int, in_fd: c_int, offset: *mut off64_t, count: size_t) -> ssize_t; pub fn shutdown(__fd: c_int, __how: c_int) -> c_int; pub fn sethostname(name: *const c_char, len: size_t) -> c_int; pub fn getdomainname(name: *mut c_char, len: size_t) -> c_int; pub fn setdomainname(name: *const c_char, len: size_t) -> c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn getifaddrs(ifap: *mut *mut crate::ifaddrs) -> c_int; pub fn freeifaddrs(ifa: *mut crate::ifaddrs); pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn gethostid() -> c_long; pub fn sethostid(hostid: c_long) -> c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut crate::group; pub fn setspent(); pub fn endspent(); pub fn getspent() -> *mut spwd; pub fn getspnam(name: *const c_char) -> *mut spwd; pub fn getpwent_r( pwd: *mut crate::passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::passwd, ) -> c_int; pub fn getgrent_r( grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn fgetpwent_r( stream: *mut crate::FILE, pwd: *mut crate::passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::passwd, ) -> c_int; pub fn fgetgrent_r( stream: *mut crate::FILE, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn putpwent(p: *const crate::passwd, stream: *mut crate::FILE) -> c_int; pub fn putgrent(grp: *const crate::group, stream: *mut crate::FILE) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn fgetspent_r( fp: *mut crate::FILE, spbuf: *mut crate::spwd, buf: *mut c_char, buflen: size_t, spbufp: *mut *mut crate::spwd, ) -> c_int; pub fn sgetspent_r( s: *const c_char, spbuf: *mut crate::spwd, buf: *mut c_char, buflen: size_t, spbufp: *mut *mut crate::spwd, ) -> c_int; pub fn getspent_r( spbuf: *mut crate::spwd, buf: *mut c_char, buflen: size_t, spbufp: *mut *mut crate::spwd, ) -> c_int; pub fn getspnam_r( name: *const c_char, spbuf: *mut spwd, buf: *mut c_char, buflen: size_t, spbufp: *mut *mut spwd, ) -> c_int; // mntent.h pub fn getmntent_r( stream: *mut crate::FILE, mntbuf: *mut crate::mntent, buf: *mut c_char, buflen: c_int, ) -> *mut crate::mntent; pub fn utmpname(file: *const c_char) -> c_int; pub fn utmpxname(file: *const c_char) -> c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn getresuid( ruid: *mut crate::uid_t, euid: *mut crate::uid_t, suid: *mut crate::uid_t, ) -> c_int; pub fn getresgid( rgid: *mut crate::gid_t, egid: *mut crate::gid_t, sgid: *mut crate::gid_t, ) -> c_int; pub fn setresuid(ruid: crate::uid_t, euid: crate::uid_t, suid: crate::uid_t) -> c_int; pub fn setresgid(rgid: crate::gid_t, egid: crate::gid_t, sgid: crate::gid_t) -> c_int; pub fn initgroups(user: *const c_char, group: crate::gid_t) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrouplist( user: *const c_char, group: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn setgroups(ngroups: size_t, ptr: *const crate::gid_t) -> c_int; pub fn acct(filename: *const c_char) -> c_int; pub fn setmntent(filename: *const c_char, ty: *const c_char) -> *mut crate::FILE; pub fn getmntent(stream: *mut crate::FILE) -> *mut crate::mntent; pub fn addmntent(stream: *mut crate::FILE, mnt: *const crate::mntent) -> c_int; pub fn endmntent(streamp: *mut crate::FILE) -> c_int; pub fn hasmntopt(mnt: *const crate::mntent, opt: *const c_char) -> *mut c_char; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_kill(__threadid: crate::pthread_t, __signo: c_int) -> c_int; pub fn pthread_cancel(thread: crate::pthread_t) -> c_int; pub fn __pthread_equal(__t1: __pthread_t, __t2: __pthread_t) -> c_int; pub fn pthread_getattr_np(__thr: crate::pthread_t, __attr: *mut pthread_attr_t) -> c_int; pub fn pthread_attr_getguardsize( __attr: *const pthread_attr_t, __guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn pthread_attr_getstack( __attr: *const pthread_attr_t, __stackaddr: *mut *mut c_void, __stacksize: *mut size_t, ) -> c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: c_int) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_setclock( __attr: *mut pthread_condattr_t, __clock_id: __clockid_t, ) -> c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: c_int) -> c_int; pub fn pthread_once(control: *mut pthread_once_t, routine: extern "C" fn()) -> c_int; pub fn pthread_barrierattr_init(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_destroy(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_getpshared( attr: *const crate::pthread_barrierattr_t, shared: *mut c_int, ) -> c_int; pub fn pthread_barrierattr_setpshared( attr: *mut crate::pthread_barrierattr_t, shared: c_int, ) -> c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const crate::pthread_barrierattr_t, count: c_uint, ) -> c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_spin_init(lock: *mut crate::pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn pthread_sigmask( __how: c_int, __newmask: *const __sigset_t, __oldmask: *mut __sigset_t, ) -> c_int; pub fn sched_getparam(pid: crate::pid_t, param: *mut crate::sched_param) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const crate::sched_param) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut crate::sched_param, ) -> c_int; pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn pthread_getcpuclockid(thread: crate::pthread_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn clock_getres(__clock_id: clockid_t, __res: *mut crate::timespec) -> c_int; pub fn clock_gettime(__clock_id: clockid_t, __tp: *mut crate::timespec) -> c_int; pub fn clock_settime(__clock_id: clockid_t, __tp: *const crate::timespec) -> c_int; pub fn clock_getcpuclockid(pid: crate::pid_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut crate::timezone) -> c_int; pub fn settimeofday(tv: *const crate::timeval, tz: *const crate::timezone) -> c_int; pub fn asctime_r(tm: *const crate::tm, buf: *mut c_char) -> *mut c_char; pub fn ctime_r(timep: *const time_t, buf: *mut c_char) -> *mut c_char; pub fn strftime( s: *mut c_char, max: size_t, format: *const c_char, tm: *const crate::tm, ) -> size_t; pub fn strptime(s: *const c_char, format: *const c_char, tm: *mut crate::tm) -> *mut c_char; pub fn timer_create( clockid: crate::clockid_t, sevp: *mut crate::sigevent, timerid: *mut crate::timer_t, ) -> c_int; pub fn timer_delete(timerid: crate::timer_t) -> c_int; pub fn timer_getoverrun(timerid: crate::timer_t) -> c_int; pub fn timer_gettime(timerid: crate::timer_t, curr_value: *mut crate::itimerspec) -> c_int; pub fn timer_settime( timerid: crate::timer_t, flags: c_int, new_value: *const crate::itimerspec, old_value: *mut crate::itimerspec, ) -> c_int; pub fn fstat(__fd: c_int, __buf: *mut stat) -> c_int; pub fn fstat64(__fd: c_int, __buf: *mut stat64) -> c_int; pub fn fstatat(__fd: c_int, __file: *const c_char, __buf: *mut stat, __flag: c_int) -> c_int; pub fn fstatat64( __fd: c_int, __file: *const c_char, __buf: *mut stat64, __flag: c_int, ) -> c_int; pub fn statx( dirfd: c_int, pathname: *const c_char, flags: c_int, mask: c_uint, statxbuf: *mut statx, ) -> c_int; pub fn ftruncate(__fd: c_int, __length: __off_t) -> c_int; pub fn ftruncate64(__fd: c_int, __length: __off64_t) -> c_int; pub fn truncate64(__file: *const c_char, __length: __off64_t) -> c_int; pub fn lstat(__file: *const c_char, __buf: *mut stat) -> c_int; pub fn lstat64(__file: *const c_char, __buf: *mut stat64) -> c_int; pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; pub fn statfs64(__file: *const c_char, __buf: *mut statfs64) -> c_int; pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn fstatfs64(__fildes: c_int, __buf: *mut statfs64) -> c_int; pub fn statvfs(__file: *const c_char, __buf: *mut statvfs) -> c_int; pub fn statvfs64(__file: *const c_char, __buf: *mut statvfs64) -> c_int; pub fn fstatvfs(__fildes: c_int, __buf: *mut statvfs) -> c_int; pub fn fstatvfs64(__fildes: c_int, __buf: *mut statvfs64) -> c_int; pub fn open(__file: *const c_char, __oflag: c_int, ...) -> c_int; pub fn open64(__file: *const c_char, __oflag: c_int, ...) -> c_int; pub fn openat(__fd: c_int, __file: *const c_char, __oflag: c_int, ...) -> c_int; pub fn openat64(__fd: c_int, __file: *const c_char, __oflag: c_int, ...) -> c_int; pub fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn freopen64( filename: *const c_char, mode: *const c_char, file: *mut crate::FILE, ) -> *mut crate::FILE; pub fn creat64(path: *const c_char, mode: mode_t) -> c_int; pub fn mkostemp(template: *mut c_char, flags: c_int) -> c_int; pub fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int; pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; pub fn tmpfile64() -> *mut crate::FILE; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn getdtablesize() -> c_int; // Added in `glibc` 2.34 pub fn close_range(first: c_uint, last: c_uint, flags: c_int) -> c_int; pub fn openpty( __amaster: *mut c_int, __aslave: *mut c_int, __name: *mut c_char, __termp: *const termios, __winp: *const crate::winsize, ) -> c_int; pub fn forkpty( __amaster: *mut c_int, __name: *mut c_char, __termp: *const termios, __winp: *const crate::winsize, ) -> crate::pid_t; pub fn getpt() -> c_int; pub fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn login_tty(fd: c_int) -> c_int; pub fn ctermid(s: *mut c_char) -> *mut c_char; pub fn clearenv() -> c_int; pub fn execveat( dirfd: c_int, pathname: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char, flags: c_int, ) -> c_int; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn execvpe( file: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; pub fn fexecve(fd: c_int, argv: *const *const c_char, envp: *const *const c_char) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; // posix/spawn.h pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: crate::pid_t) -> c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut c_int, ) -> c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: c_int) -> c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut crate::sched_param, ) -> c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const crate::sched_param, ) -> c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int, ) -> c_int; // Added in `glibc` 2.29 pub fn posix_spawn_file_actions_addchdir_np( actions: *mut crate::posix_spawn_file_actions_t, path: *const c_char, ) -> c_int; // Added in `glibc` 2.29 pub fn posix_spawn_file_actions_addfchdir_np( actions: *mut crate::posix_spawn_file_actions_t, fd: c_int, ) -> c_int; // Added in `glibc` 2.34 pub fn posix_spawn_file_actions_addclosefrom_np( actions: *mut crate::posix_spawn_file_actions_t, from: c_int, ) -> c_int; // Added in `glibc` 2.35 pub fn posix_spawn_file_actions_addtcsetpgrp_np( actions: *mut crate::posix_spawn_file_actions_t, tcfd: c_int, ) -> c_int; pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn euidaccess(pathname: *const c_char, mode: c_int) -> c_int; pub fn eaccess(pathname: *const c_char, mode: c_int) -> c_int; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn stat(__file: *const c_char, __buf: *mut stat) -> c_int; pub fn stat64(__file: *const c_char, __buf: *mut stat64) -> c_int; pub fn readdir(dirp: *mut crate::DIR) -> *mut crate::dirent; pub fn readdir64(dirp: *mut crate::DIR) -> *mut crate::dirent64; pub fn readdir_r( dirp: *mut crate::DIR, entry: *mut crate::dirent, result: *mut *mut crate::dirent, ) -> c_int; pub fn readdir64_r( dirp: *mut crate::DIR, entry: *mut crate::dirent64, result: *mut *mut crate::dirent64, ) -> c_int; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; #[link_name = "__xpg_strerror_r"] pub fn strerror_r(__errnum: c_int, __buf: *mut c_char, __buflen: size_t) -> c_int; pub fn __errno_location() -> *mut c_int; pub fn mmap64( __addr: *mut c_void, __len: size_t, __prot: c_int, __flags: c_int, __fd: c_int, __offset: __off64_t, ) -> *mut c_void; pub fn mremap( addr: *mut c_void, len: size_t, new_len: size_t, flags: c_int, ... ) -> *mut c_void; pub fn mprotect(__addr: *mut c_void, __len: size_t, __prot: c_int) -> c_int; pub fn msync(__addr: *mut c_void, __len: size_t, __flags: c_int) -> c_int; pub fn sync(); pub fn syncfs(fd: c_int) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; pub fn fallocate64(fd: c_int, mode: c_int, offset: off64_t, len: off64_t) -> c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn posix_fallocate64(fd: c_int, offset: off64_t, len: off64_t) -> c_int; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int; pub fn posix_fadvise64(fd: c_int, offset: off64_t, len: off64_t, advise: c_int) -> c_int; pub fn madvise(__addr: *mut c_void, __len: size_t, __advice: c_int) -> c_int; pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn getrlimit(resource: crate::__rlimit_resource_t, rlim: *mut crate::rlimit) -> c_int; pub fn getrlimit64(resource: crate::__rlimit_resource_t, rlim: *mut crate::rlimit64) -> c_int; pub fn setrlimit(resource: crate::__rlimit_resource_t, rlim: *const crate::rlimit) -> c_int; pub fn setrlimit64(resource: crate::__rlimit_resource_t, rlim: *const crate::rlimit64) -> c_int; pub fn getpriority(which: crate::__priority_which, who: crate::id_t) -> c_int; pub fn setpriority(which: crate::__priority_which, who: crate::id_t, prio: c_int) -> c_int; pub fn getrandom(__buffer: *mut c_void, __length: size_t, __flags: c_uint) -> ssize_t; pub fn getentropy(__buffer: *mut c_void, __length: size_t) -> c_int; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; pub fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn drand48() -> c_double; pub fn erand48(xseed: *mut c_ushort) -> c_double; pub fn lrand48() -> c_long; pub fn nrand48(xseed: *mut c_ushort) -> c_long; pub fn mrand48() -> c_long; pub fn jrand48(xseed: *mut c_ushort) -> c_long; pub fn srand48(seed: c_long); pub fn seed48(xseed: *mut c_ushort) -> *mut c_ushort; pub fn lcong48(p: *mut c_ushort); pub fn qsort_r( base: *mut c_void, num: size_t, size: size_t, compar: Option c_int>, arg: *mut c_void, ); pub fn brk(addr: *mut c_void) -> c_int; pub fn sbrk(increment: intptr_t) -> *mut c_void; pub fn memalign(align: size_t, size: size_t) -> *mut c_void; pub fn mallopt(param: c_int, value: c_int) -> c_int; pub fn mallinfo() -> crate::mallinfo; pub fn mallinfo2() -> crate::mallinfo2; pub fn malloc_info(options: c_int, stream: *mut crate::FILE) -> c_int; pub fn malloc_usable_size(ptr: *mut c_void) -> size_t; pub fn malloc_trim(__pad: size_t) -> c_int; pub fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut c_char, inbytesleft: *mut size_t, outbuf: *mut *mut c_char, outbytesleft: *mut size_t, ) -> size_t; pub fn iconv_close(cd: iconv_t) -> c_int; pub fn getopt_long( argc: c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut c_int, ) -> c_int; pub fn backtrace(buf: *mut *mut c_void, sz: c_int) -> c_int; pub fn reboot(how_to: c_int) -> c_int; pub fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int; pub fn regexec( preg: *const crate::regex_t, input: *const c_char, nmatch: size_t, pmatch: *mut regmatch_t, eflags: c_int, ) -> c_int; pub fn regerror( errcode: c_int, preg: *const crate::regex_t, errbuf: *mut c_char, errbuf_size: size_t, ) -> size_t; pub fn regfree(preg: *mut crate::regex_t); pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; pub fn globfree(pglob: *mut crate::glob_t); pub fn glob64( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut glob64_t, ) -> c_int; pub fn globfree64(pglob: *mut glob64_t); pub fn getxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn lgetxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn fgetxattr( filedes: c_int, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn setxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn lsetxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn fsetxattr( filedes: c_int, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn listxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; pub fn llistxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; pub fn flistxattr(filedes: c_int, list: *mut c_char, size: size_t) -> ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> c_int; pub fn lremovexattr(path: *const c_char, name: *const c_char) -> c_int; pub fn fremovexattr(filedes: c_int, name: *const c_char) -> c_int; pub fn dirname(path: *mut c_char) -> *mut c_char; /// POSIX version of `basename(3)`, defined in `libgen.h`. #[link_name = "__xpg_basename"] pub fn posix_basename(path: *mut c_char) -> *mut c_char; /// GNU version of `basename(3)`, defined in `string.h`. #[link_name = "basename"] pub fn gnu_basename(path: *const c_char) -> *mut c_char; pub fn dlmopen(lmid: Lmid_t, filename: *const c_char, flag: c_int) -> *mut c_void; pub fn dlinfo(handle: *mut c_void, request: c_int, info: *mut c_void) -> c_int; pub fn dladdr1( addr: *const c_void, info: *mut crate::Dl_info, extra_info: *mut *mut c_void, flags: c_int, ) -> c_int; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; pub fn freelocale(loc: crate::locale_t); pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn nl_langinfo_l(item: crate::nl_item, locale: crate::locale_t) -> *mut c_char; pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn( info: *mut crate::dl_phdr_info, size: size_t, data: *mut c_void, ) -> c_int, >, data: *mut c_void, ) -> c_int; pub fn gnu_get_libc_release() -> *const c_char; pub fn gnu_get_libc_version() -> *const c_char; } safe_f! { pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= major << 8; dev |= minor; dev } pub {const} fn major(dev: crate::dev_t) -> c_uint { ((dev >> 8) & 0xff) as c_uint } pub {const} fn minor(dev: crate::dev_t) -> c_uint { (dev & 0xffff00ff) as c_uint } pub fn SIGRTMAX() -> c_int { unsafe { __libc_current_sigrtmax() } } pub fn SIGRTMIN() -> c_int { unsafe { __libc_current_sigrtmin() } } pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0x7f } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: c_int) -> bool { (status & 0x80) != 0 } pub {const} fn W_EXITCODE(ret: c_int, sig: c_int) -> c_int { (ret << 8) | sig } pub {const} fn W_STOPCODE(sig: c_int) -> c_int { (sig << 8) | 0x7f } pub {const} fn QCMD(cmd: c_int, type_: c_int) -> c_int { (cmd << 8) | (type_ & 0x00ff) } pub {const} fn IPOPT_COPIED(o: u8) -> u8 { o & IPOPT_COPY } pub {const} fn IPOPT_CLASS(o: u8) -> u8 { o & IPOPT_CLASS_MASK } pub {const} fn IPOPT_NUMBER(o: u8) -> u8 { o & IPOPT_NUMBER_MASK } pub {const} fn IPTOS_ECN(x: u8) -> u8 { x & crate::IPTOS_ECN_MASK } } cfg_if! { if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { mod b32; pub use self::b32::*; } } libc/src/unix/hurd/b32.rs0000644000175000017500000000507315105742312014770 0ustar bdrungbdrunguse crate::prelude::*; pub type __int64_t = c_longlong; pub type __uint64_t = c_ulonglong; pub type int_fast16_t = c_int; pub type int_fast32_t = c_int; pub type int_fast64_t = c_longlong; pub type uint_fast16_t = c_uint; pub type uint_fast32_t = c_uint; pub type uint_fast64_t = c_ulonglong; pub type __quad_t = c_longlong; pub type __u_quad_t = c_ulonglong; pub type __intmax_t = c_longlong; pub type __uintmax_t = c_ulonglong; pub type __squad_type = crate::__int64_t; pub type __uquad_type = crate::__uint64_t; pub type __sword_type = c_int; pub type __uword_type = c_uint; pub type __slong32_type = c_long; pub type __ulong32_type = c_ulong; pub type __s64_type = crate::__int64_t; pub type __u64_type = crate::__uint64_t; pub type __ipc_pid_t = c_ushort; pub type Elf32_Half = u16; pub type Elf32_Word = u32; pub type Elf32_Off = u32; pub type Elf32_Addr = u32; pub type Elf32_Section = u16; pub type Elf_Addr = crate::Elf32_Addr; pub type Elf_Half = crate::Elf32_Half; pub type Elf_Ehdr = crate::Elf32_Ehdr; pub type Elf_Phdr = crate::Elf32_Phdr; pub type Elf_Shdr = crate::Elf32_Shdr; pub type Elf_Sym = crate::Elf32_Sym; s! { pub struct Elf32_Ehdr { pub e_ident: [c_uchar; 16], pub e_type: Elf32_Half, pub e_machine: Elf32_Half, pub e_version: Elf32_Word, pub e_entry: Elf32_Addr, pub e_phoff: Elf32_Off, pub e_shoff: Elf32_Off, pub e_flags: Elf32_Word, pub e_ehsize: Elf32_Half, pub e_phentsize: Elf32_Half, pub e_phnum: Elf32_Half, pub e_shentsize: Elf32_Half, pub e_shnum: Elf32_Half, pub e_shstrndx: Elf32_Half, } pub struct Elf32_Shdr { pub sh_name: Elf32_Word, pub sh_type: Elf32_Word, pub sh_flags: Elf32_Word, pub sh_addr: Elf32_Addr, pub sh_offset: Elf32_Off, pub sh_size: Elf32_Word, pub sh_link: Elf32_Word, pub sh_info: Elf32_Word, pub sh_addralign: Elf32_Word, pub sh_entsize: Elf32_Word, } pub struct Elf32_Sym { pub st_name: Elf32_Word, pub st_value: Elf32_Addr, pub st_size: Elf32_Word, pub st_info: c_uchar, pub st_other: c_uchar, pub st_shndx: Elf32_Section, } pub struct Elf32_Phdr { pub p_type: crate::Elf32_Word, pub p_offset: crate::Elf32_Off, pub p_vaddr: crate::Elf32_Addr, pub p_paddr: crate::Elf32_Addr, pub p_filesz: crate::Elf32_Word, pub p_memsz: crate::Elf32_Word, pub p_flags: crate::Elf32_Word, pub p_align: crate::Elf32_Word, } } libc/src/unix/hurd/b64.rs0000644000175000017500000000506515105742312014776 0ustar bdrungbdrunguse crate::prelude::*; pub type __int64_t = c_long; pub type __uint64_t = c_ulong; pub type int_fast16_t = c_long; pub type int_fast32_t = c_long; pub type int_fast64_t = c_long; pub type uint_fast16_t = c_ulong; pub type uint_fast32_t = c_ulong; pub type uint_fast64_t = c_ulong; pub type __quad_t = c_long; pub type __u_quad_t = c_ulong; pub type __intmax_t = c_long; pub type __uintmax_t = c_ulong; pub type __squad_type = c_long; pub type __uquad_type = c_ulong; pub type __sword_type = c_long; pub type __uword_type = c_ulong; pub type __slong32_type = c_int; pub type __ulong32_type = c_uint; pub type __s64_type = c_long; pub type __u64_type = c_ulong; pub type __ipc_pid_t = c_int; pub type Elf64_Half = u16; pub type Elf64_Word = u32; pub type Elf64_Off = u64; pub type Elf64_Addr = u64; pub type Elf64_Xword = u64; pub type Elf64_Sxword = i64; pub type Elf64_Section = u16; pub type Elf_Addr = crate::Elf64_Addr; pub type Elf_Half = crate::Elf64_Half; pub type Elf_Ehdr = crate::Elf64_Ehdr; pub type Elf_Phdr = crate::Elf64_Phdr; pub type Elf_Shdr = crate::Elf64_Shdr; pub type Elf_Sym = crate::Elf64_Sym; s! { pub struct Elf64_Ehdr { pub e_ident: [c_uchar; 16], pub e_type: Elf64_Half, pub e_machine: Elf64_Half, pub e_version: Elf64_Word, pub e_entry: Elf64_Addr, pub e_phoff: Elf64_Off, pub e_shoff: Elf64_Off, pub e_flags: Elf64_Word, pub e_ehsize: Elf64_Half, pub e_phentsize: Elf64_Half, pub e_phnum: Elf64_Half, pub e_shentsize: Elf64_Half, pub e_shnum: Elf64_Half, pub e_shstrndx: Elf64_Half, } pub struct Elf64_Shdr { pub sh_name: Elf64_Word, pub sh_type: Elf64_Word, pub sh_flags: Elf64_Xword, pub sh_addr: Elf64_Addr, pub sh_offset: Elf64_Off, pub sh_size: Elf64_Xword, pub sh_link: Elf64_Word, pub sh_info: Elf64_Word, pub sh_addralign: Elf64_Xword, pub sh_entsize: Elf64_Xword, } pub struct Elf64_Sym { pub st_name: Elf64_Word, pub st_info: c_uchar, pub st_other: c_uchar, pub st_shndx: Elf64_Section, pub st_value: Elf64_Addr, pub st_size: Elf64_Xword, } pub struct Elf64_Phdr { pub p_type: crate::Elf64_Word, pub p_flags: crate::Elf64_Word, pub p_offset: crate::Elf64_Off, pub p_vaddr: crate::Elf64_Addr, pub p_paddr: crate::Elf64_Addr, pub p_filesz: crate::Elf64_Xword, pub p_memsz: crate::Elf64_Xword, pub p_align: crate::Elf64_Xword, } } libc/src/unix/mod.rs0000644000175000017500000020112315105742312014211 0ustar bdrungbdrung//! Definitions found commonly among almost all Unix derivatives //! //! More functions and definitions can be found in the more specific modules //! according to the platform in question. use crate::prelude::*; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type pid_t = i32; pub type in_addr_t = u32; pub type in_port_t = u16; pub type sighandler_t = size_t; pub type cc_t = c_uchar; cfg_if! { if #[cfg(any( target_os = "espidf", target_os = "horizon", target_os = "vita" ))] { pub type uid_t = c_ushort; pub type gid_t = c_ushort; } else if #[cfg(target_os = "nto")] { pub type uid_t = i32; pub type gid_t = i32; } else { pub type uid_t = u32; pub type gid_t = u32; } } missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} } pub type locale_t = *mut c_void; s! { pub struct group { pub gr_name: *mut c_char, pub gr_passwd: *mut c_char, pub gr_gid: crate::gid_t, pub gr_mem: *mut *mut c_char, } pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } // FIXME(time): Needs updates at least for glibc _TIME_BITS=64 pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } // linux x32 compatibility // See https://sourceware.org/bugzilla/show_bug.cgi?id=16437 pub struct timespec { pub tv_sec: time_t, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub tv_nsec: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub tv_nsec: c_long, } pub struct rlimit { pub rlim_cur: rlim_t, pub rlim_max: rlim_t, } pub struct rusage { pub ru_utime: timeval, pub ru_stime: timeval, pub ru_maxrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad1: u32, pub ru_ixrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad2: u32, pub ru_idrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad3: u32, pub ru_isrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad4: u32, pub ru_minflt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad5: u32, pub ru_majflt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad6: u32, pub ru_nswap: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad7: u32, pub ru_inblock: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad8: u32, pub ru_oublock: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad9: u32, pub ru_msgsnd: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad10: u32, pub ru_msgrcv: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad11: u32, pub ru_nsignals: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad12: u32, pub ru_nvcsw: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad13: u32, pub ru_nivcsw: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad14: u32, #[cfg(any(target_env = "musl", target_env = "ohos", target_os = "emscripten"))] __reserved: [c_long; 16], } pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, #[cfg(target_os = "android")] pub ipv6mr_interface: c_int, #[cfg(not(target_os = "android"))] pub ipv6mr_interface: c_uint, } #[cfg(not(target_os = "cygwin"))] pub struct hostent { pub h_name: *mut c_char, pub h_aliases: *mut *mut c_char, pub h_addrtype: c_int, pub h_length: c_int, pub h_addr_list: *mut *mut c_char, } pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct pollfd { pub fd: c_int, pub events: c_short, pub revents: c_short, } pub struct winsize { pub ws_row: c_ushort, pub ws_col: c_ushort, pub ws_xpixel: c_ushort, pub ws_ypixel: c_ushort, } #[cfg(not(target_os = "cygwin"))] pub struct linger { pub l_onoff: c_int, pub l_linger: c_int, } pub struct sigval { // Actually a union of an int and a void* pub sival_ptr: *mut c_void, } // pub struct itimerval { pub it_interval: crate::timeval, pub it_value: crate::timeval, } // pub struct tms { pub tms_utime: crate::clock_t, pub tms_stime: crate::clock_t, pub tms_cutime: crate::clock_t, pub tms_cstime: crate::clock_t, } pub struct servent { pub s_name: *mut c_char, pub s_aliases: *mut *mut c_char, #[cfg(target_os = "cygwin")] pub s_port: c_short, #[cfg(not(target_os = "cygwin"))] pub s_port: c_int, pub s_proto: *mut c_char, } pub struct protoent { pub p_name: *mut c_char, pub p_aliases: *mut *mut c_char, #[cfg(not(target_os = "cygwin"))] pub p_proto: c_int, #[cfg(target_os = "cygwin")] pub p_proto: c_short, } #[repr(align(4))] pub struct in6_addr { pub s6_addr: [u8; 16], } } pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const SIG_DFL: sighandler_t = 0 as sighandler_t; pub const SIG_IGN: sighandler_t = 1 as sighandler_t; pub const SIG_ERR: sighandler_t = !0 as sighandler_t; cfg_if! { if #[cfg(not(target_os = "nto"))] { pub const DT_UNKNOWN: u8 = 0; pub const DT_FIFO: u8 = 1; pub const DT_CHR: u8 = 2; pub const DT_DIR: u8 = 4; pub const DT_BLK: u8 = 6; pub const DT_REG: u8 = 8; pub const DT_LNK: u8 = 10; pub const DT_SOCK: u8 = 12; } } cfg_if! { if #[cfg(not(target_os = "redox"))] { pub const FD_CLOEXEC: c_int = 0x1; } } cfg_if! { if #[cfg(not(target_os = "nto"))] { pub const USRQUOTA: c_int = 0; pub const GRPQUOTA: c_int = 1; } } pub const SIGIOT: c_int = 6; pub const S_ISUID: crate::mode_t = 0o4000; pub const S_ISGID: crate::mode_t = 0o2000; pub const S_ISVTX: crate::mode_t = 0o1000; cfg_if! { if #[cfg(not(any( target_os = "haiku", target_os = "illumos", target_os = "solaris", target_os = "cygwin" )))] { pub const IF_NAMESIZE: size_t = 16; pub const IFNAMSIZ: size_t = IF_NAMESIZE; } } pub const LOG_EMERG: c_int = 0; pub const LOG_ALERT: c_int = 1; pub const LOG_CRIT: c_int = 2; pub const LOG_ERR: c_int = 3; pub const LOG_WARNING: c_int = 4; pub const LOG_NOTICE: c_int = 5; pub const LOG_INFO: c_int = 6; pub const LOG_DEBUG: c_int = 7; pub const LOG_KERN: c_int = 0; pub const LOG_USER: c_int = 1 << 3; pub const LOG_MAIL: c_int = 2 << 3; pub const LOG_DAEMON: c_int = 3 << 3; pub const LOG_AUTH: c_int = 4 << 3; pub const LOG_SYSLOG: c_int = 5 << 3; pub const LOG_LPR: c_int = 6 << 3; pub const LOG_NEWS: c_int = 7 << 3; pub const LOG_UUCP: c_int = 8 << 3; pub const LOG_LOCAL0: c_int = 16 << 3; pub const LOG_LOCAL1: c_int = 17 << 3; pub const LOG_LOCAL2: c_int = 18 << 3; pub const LOG_LOCAL3: c_int = 19 << 3; pub const LOG_LOCAL4: c_int = 20 << 3; pub const LOG_LOCAL5: c_int = 21 << 3; pub const LOG_LOCAL6: c_int = 22 << 3; pub const LOG_LOCAL7: c_int = 23 << 3; cfg_if! { if #[cfg(not(target_os = "haiku"))] { pub const LOG_PID: c_int = 0x01; pub const LOG_CONS: c_int = 0x02; pub const LOG_ODELAY: c_int = 0x04; pub const LOG_NDELAY: c_int = 0x08; pub const LOG_NOWAIT: c_int = 0x10; } } pub const LOG_PRIMASK: c_int = 7; pub const LOG_FACMASK: c_int = 0x3f8; cfg_if! { if #[cfg(not(target_os = "nto"))] { pub const PRIO_MIN: c_int = -20; pub const PRIO_MAX: c_int = 20; } } pub const IPPROTO_ICMP: c_int = 1; pub const IPPROTO_ICMPV6: c_int = 58; pub const IPPROTO_TCP: c_int = 6; pub const IPPROTO_UDP: c_int = 17; pub const IPPROTO_IP: c_int = 0; pub const IPPROTO_IPV6: c_int = 41; pub const INADDR_LOOPBACK: in_addr_t = 2130706433; pub const INADDR_ANY: in_addr_t = 0; pub const INADDR_BROADCAST: in_addr_t = 4294967295; pub const INADDR_NONE: in_addr_t = 4294967295; pub const IN6ADDR_LOOPBACK_INIT: in6_addr = in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], }; pub const IN6ADDR_ANY_INIT: in6_addr = in6_addr { s6_addr: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; pub const ARPOP_REQUEST: u16 = 1; pub const ARPOP_REPLY: u16 = 2; pub const ATF_COM: c_int = 0x02; pub const ATF_PERM: c_int = 0x04; pub const ATF_PUBL: c_int = 0x08; pub const ATF_USETRAILERS: c_int = 0x10; cfg_if! { if #[cfg(target_os = "nto")] { pub const FNM_PERIOD: c_int = 1 << 1; } else { pub const FNM_PERIOD: c_int = 1 << 2; } } pub const FNM_NOMATCH: c_int = 1; cfg_if! { if #[cfg(any(target_os = "illumos", target_os = "solaris",))] { pub const FNM_CASEFOLD: c_int = 1 << 3; } else { pub const FNM_CASEFOLD: c_int = 1 << 4; } } cfg_if! { if #[cfg(any( target_os = "macos", target_os = "freebsd", target_os = "android", target_os = "openbsd", target_os = "cygwin", ))] { pub const FNM_PATHNAME: c_int = 1 << 1; } else { pub const FNM_PATHNAME: c_int = 1 << 0; } } cfg_if! { if #[cfg(any( target_os = "macos", target_os = "freebsd", target_os = "android", target_os = "openbsd", ))] { pub const FNM_NOESCAPE: c_int = 1 << 0; } else if #[cfg(target_os = "nto")] { pub const FNM_NOESCAPE: c_int = 1 << 2; } else { pub const FNM_NOESCAPE: c_int = 1 << 1; } } extern "C" { pub static in6addr_loopback: in6_addr; pub static in6addr_any: in6_addr; } cfg_if! { if #[cfg(any( target_os = "l4re", target_os = "espidf", target_os = "nuttx" ))] { // required libraries are linked externally for these platforms: // * L4Re // * ESP-IDF // * NuttX } else if #[cfg(feature = "std")] { // cargo build, don't pull in anything extra as the std dep // already pulls in all libs. } else if #[cfg(all( any( all( target_os = "linux", any(target_env = "gnu", target_env = "uclibc") ), target_os = "cygwin" ), feature = "rustc-dep-of-std" ))] { #[link( name = "util", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "rt", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "pthread", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "m", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "dl", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link(name = "util", cfg(not(target_feature = "crt-static")))] #[link(name = "rt", cfg(not(target_feature = "crt-static")))] #[link(name = "pthread", cfg(not(target_feature = "crt-static")))] #[link(name = "m", cfg(not(target_feature = "crt-static")))] #[link(name = "dl", cfg(not(target_feature = "crt-static")))] #[link(name = "c", cfg(not(target_feature = "crt-static")))] extern "C" {} } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { #[cfg_attr( feature = "rustc-dep-of-std", link( name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") ) )] #[cfg_attr( feature = "rustc-dep-of-std", link(name = "c", cfg(not(target_feature = "crt-static"))) )] extern "C" {} } else if #[cfg(target_os = "emscripten")] { // Don't pass -lc to Emscripten, it breaks. See: // https://github.com/emscripten-core/emscripten/issues/22758 } else if #[cfg(all(target_os = "android", feature = "rustc-dep-of-std"))] { #[link( name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link( name = "m", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") )] #[link(name = "m", cfg(not(target_feature = "crt-static")))] #[link(name = "c", cfg(not(target_feature = "crt-static")))] extern "C" {} } else if #[cfg(any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", target_os = "android", target_os = "openbsd", target_os = "nto", ))] { #[link(name = "c")] #[link(name = "m")] extern "C" {} } else if #[cfg(target_os = "haiku")] { #[link(name = "root")] #[link(name = "network")] extern "C" {} } else if #[cfg(target_env = "newlib")] { #[link(name = "c")] #[link(name = "m")] extern "C" {} } else if #[cfg(target_env = "illumos")] { #[link(name = "c")] #[link(name = "m")] extern "C" {} } else if #[cfg(target_os = "redox")] { #[cfg_attr( feature = "rustc-dep-of-std", link( name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") ) )] #[cfg_attr( feature = "rustc-dep-of-std", link(name = "c", cfg(not(target_feature = "crt-static"))) )] extern "C" {} } else if #[cfg(target_os = "aix")] { #[link(name = "c")] #[link(name = "m")] #[link(name = "bsd")] #[link(name = "pthread")] extern "C" {} } else { #[link(name = "c")] #[link(name = "m")] #[link(name = "rt")] #[link(name = "pthread")] extern "C" {} } } cfg_if! { if #[cfg(not(target_env = "gnu"))] { missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} // FIXME(unix): fill this out with a struct } } } missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} } extern "C" { pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn qsort( base: *mut c_void, num: size_t, size: size_t, compar: Option c_int>, ); pub fn bsearch( key: *const c_void, base: *const c_void, num: size_t, size: size_t, compar: Option c_int>, ) -> *mut c_void; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fopen$UNIX2003" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "fopen64")] pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "freopen$UNIX2003" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "freopen64")] pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "tmpfile64")] pub fn tmpfile() -> *mut FILE; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fputs$UNIX2003" )] pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fwrite$UNIX2003" )] pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); #[cfg_attr(target_os = "netbsd", link_name = "__fgetpos50")] #[cfg_attr(gnu_file_offset_bits64, link_name = "fgetpos64")] pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__fsetpos50")] #[cfg_attr(gnu_file_offset_bits64, link_name = "fsetpos64")] pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; pub fn feof(stream: *mut FILE) -> c_int; pub fn ferror(stream: *mut FILE) -> c_int; pub fn clearerr(stream: *mut FILE); pub fn perror(s: *const c_char); pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "strtod$UNIX2003" )] pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn abort() -> !; pub fn exit(status: c_int) -> !; pub fn _exit(status: c_int) -> !; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "system$UNIX2003" )] pub fn system(s: *const c_char) -> c_int; pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn stpcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strndup(cs: *const c_char, n: size_t) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "strerror$UNIX2003" )] pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strtok_r(s: *mut c_char, t: *const c_char, p: *mut *mut c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn strsignal(sig: c_int) -> *mut c_char; pub fn wcslen(buf: *const wchar_t) -> size_t; pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memccpy(dest: *mut c_void, src: *const c_void, c: c_int, n: size_t) -> *mut c_void; } extern "C" { #[cfg_attr(target_os = "netbsd", link_name = "__getpwnam50")] pub fn getpwnam(name: *const c_char) -> *mut passwd; #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid50")] pub fn getpwuid(uid: crate::uid_t) -> *mut passwd; pub fn fprintf(stream: *mut crate::FILE, format: *const c_char, ...) -> c_int; pub fn printf(format: *const c_char, ...) -> c_int; pub fn snprintf(s: *mut c_char, n: size_t, format: *const c_char, ...) -> c_int; pub fn sprintf(s: *mut c_char, format: *const c_char, ...) -> c_int; #[cfg_attr( all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_fscanf" )] pub fn fscanf(stream: *mut crate::FILE, format: *const c_char, ...) -> c_int; #[cfg_attr( all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_scanf" )] pub fn scanf(format: *const c_char, ...) -> c_int; #[cfg_attr( all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_sscanf" )] pub fn sscanf(s: *const c_char, format: *const c_char, ...) -> c_int; pub fn getchar_unlocked() -> c_int; pub fn putchar_unlocked(c: c_int) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr(target_os = "netbsd", link_name = "__socket30")] #[cfg_attr(target_os = "illumos", link_name = "__xnet_socket")] #[cfg_attr(target_os = "solaris", link_name = "__xnet7_socket")] #[cfg_attr(target_os = "espidf", link_name = "lwip_socket")] pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "connect$UNIX2003" )] #[cfg_attr( any(target_os = "illumos", target_os = "solaris"), link_name = "__xnet_connect" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_connect")] pub fn connect(socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "listen$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_listen")] pub fn listen(socket: c_int, backlog: c_int) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "accept$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_accept")] pub fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getpeername$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_getpeername")] pub fn getpeername(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getsockname$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_getsockname")] pub fn getsockname(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int; #[cfg_attr(target_os = "espidf", link_name = "lwip_setsockopt")] pub fn setsockopt( socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t, ) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "socketpair$UNIX2003" )] #[cfg_attr( any(target_os = "illumos", target_os = "solaris"), link_name = "__xnet_socketpair" )] pub fn socketpair( domain: c_int, type_: c_int, protocol: c_int, socket_vector: *mut c_int, ) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sendto$UNIX2003" )] #[cfg_attr( any(target_os = "illumos", target_os = "solaris"), link_name = "__xnet_sendto" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_sendto")] pub fn sendto( socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t, ) -> ssize_t; #[cfg_attr(target_os = "espidf", link_name = "lwip_shutdown")] pub fn shutdown(socket: c_int, how: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "chmod$UNIX2003" )] pub fn chmod(path: *const c_char, mode: mode_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fchmod$UNIX2003" )] pub fn fchmod(fd: c_int, mode: mode_t) -> c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "fstat$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__fstat50")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "fstat@FBSD_1.0" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "fstat64")] pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "stat$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__stat50")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "stat@FBSD_1.0" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "stat64")] pub fn stat(path: *const c_char, buf: *mut stat) -> c_int; pub fn pclose(stream: *mut crate::FILE) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fdopen$UNIX2003" )] pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut crate::FILE; pub fn fileno(stream: *mut crate::FILE) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "open$UNIX2003" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "open64")] pub fn open(path: *const c_char, oflag: c_int, ...) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "creat$UNIX2003" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "creat64")] pub fn creat(path: *const c_char, mode: mode_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fcntl$UNIX2003" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "__fcntl_time64")] pub fn fcntl(fd: c_int, cmd: c_int, ...) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "opendir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "opendir$INODE64$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__opendir30")] pub fn opendir(dirname: *const c_char) -> *mut crate::DIR; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "readdir$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__readdir30")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "readdir@FBSD_1.0" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "readdir64")] pub fn readdir(dirp: *mut crate::DIR) -> *mut crate::dirent; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "closedir$UNIX2003" )] pub fn closedir(dirp: *mut crate::DIR) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "rewinddir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "rewinddir$INODE64$UNIX2003" )] pub fn rewinddir(dirp: *mut crate::DIR); pub fn fchmodat( dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, flags: c_int, ) -> c_int; pub fn fchown(fd: c_int, owner: crate::uid_t, group: crate::gid_t) -> c_int; pub fn fchownat( dirfd: c_int, pathname: *const c_char, owner: crate::uid_t, group: crate::gid_t, flags: c_int, ) -> c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "fstatat$INODE64" )] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "fstatat@FBSD_1.1" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "fstatat64")] pub fn fstatat(dirfd: c_int, pathname: *const c_char, buf: *mut stat, flags: c_int) -> c_int; pub fn linkat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn renameat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, ) -> c_int; pub fn symlinkat(target: *const c_char, newdirfd: c_int, linkpath: *const c_char) -> c_int; pub fn unlinkat(dirfd: c_int, pathname: *const c_char, flags: c_int) -> c_int; pub fn access(path: *const c_char, amode: c_int) -> c_int; pub fn alarm(seconds: c_uint) -> c_uint; pub fn chdir(dir: *const c_char) -> c_int; pub fn fchdir(dirfd: c_int) -> c_int; pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "lchown$UNIX2003" )] pub fn lchown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "close$NOCANCEL$UNIX2003" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "close$NOCANCEL" )] pub fn close(fd: c_int) -> c_int; pub fn dup(fd: c_int) -> c_int; pub fn dup2(src: c_int, dst: c_int) -> c_int; pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> c_int; pub fn execle(path: *const c_char, arg0: *const c_char, ...) -> c_int; pub fn execlp(file: *const c_char, arg0: *const c_char, ...) -> c_int; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn execv(prog: *const c_char, argv: *const *const c_char) -> c_int; pub fn execve( prog: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int; pub fn fork() -> pid_t; pub fn fpathconf(filedes: c_int, name: c_int) -> c_long; pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; pub fn getgid() -> gid_t; pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int; #[cfg_attr(target_os = "illumos", link_name = "getloginx")] pub fn getlogin() -> *mut c_char; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getopt$UNIX2003" )] pub fn getopt(argc: c_int, argv: *const *mut c_char, optstr: *const c_char) -> c_int; pub fn getpgid(pid: pid_t) -> pid_t; pub fn getpgrp() -> pid_t; pub fn getpid() -> pid_t; pub fn getppid() -> pid_t; pub fn getuid() -> uid_t; pub fn isatty(fd: c_int) -> c_int; #[cfg_attr(target_os = "solaris", link_name = "__link_xpg4")] pub fn link(src: *const c_char, dst: *const c_char) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "lseek64")] pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t; pub fn pathconf(path: *const c_char, name: c_int) -> c_long; pub fn pipe(fds: *mut c_int) -> c_int; pub fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int; pub fn aligned_alloc(alignment: size_t, size: size_t) -> *mut c_void; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "read$UNIX2003" )] pub fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t; pub fn rmdir(path: *const c_char) -> c_int; pub fn seteuid(uid: uid_t) -> c_int; pub fn setegid(gid: gid_t) -> c_int; pub fn setgid(gid: gid_t) -> c_int; pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int; pub fn setsid() -> pid_t; pub fn setuid(uid: uid_t) -> c_int; pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int; pub fn setregid(rgid: gid_t, egid: gid_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sleep$UNIX2003" )] pub fn sleep(secs: c_uint) -> c_uint; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "nanosleep$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__nanosleep50")] pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int; pub fn tcgetpgrp(fd: c_int) -> pid_t; pub fn tcsetpgrp(fd: c_int, pgrp: crate::pid_t) -> c_int; pub fn ttyname(fd: c_int) -> *mut c_char; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "ttyname_r$UNIX2003" )] #[cfg_attr( any(target_os = "illumos", target_os = "solaris"), link_name = "__posix_ttyname_r" )] pub fn ttyname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn unlink(c: *const c_char) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "wait$UNIX2003" )] pub fn wait(status: *mut c_int) -> pid_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "waitpid$UNIX2003" )] pub fn waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> pid_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "write$UNIX2003" )] pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pread$UNIX2003" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "pread64")] pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pwrite$UNIX2003" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "pwrite64")] pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t, offset: off_t) -> ssize_t; pub fn umask(mask: mode_t) -> mode_t; #[cfg_attr(target_os = "netbsd", link_name = "__utime50")] pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "kill$UNIX2003" )] pub fn kill(pid: pid_t, sig: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "killpg$UNIX2003" )] pub fn killpg(pgrp: pid_t, sig: c_int) -> c_int; pub fn mlock(addr: *const c_void, len: size_t) -> c_int; pub fn munlock(addr: *const c_void, len: size_t) -> c_int; pub fn mlockall(flags: c_int) -> c_int; pub fn munlockall() -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "mmap$UNIX2003" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "mmap64")] pub fn mmap( addr: *mut c_void, len: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off_t, ) -> *mut c_void; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "munmap$UNIX2003" )] pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; pub fn if_nametoindex(ifname: *const c_char) -> c_uint; pub fn if_indextoname(ifindex: c_uint, ifname: *mut c_char) -> *mut c_char; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "lstat$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__lstat50")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "lstat@FBSD_1.0" )] #[cfg_attr(gnu_file_offset_bits64, link_name = "lstat64")] pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fsync$UNIX2003" )] pub fn fsync(fd: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "setenv$UNIX2003" )] pub fn setenv(name: *const c_char, val: *const c_char, overwrite: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "unsetenv$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__unsetenv13")] pub fn unsetenv(name: *const c_char) -> c_int; pub fn symlink(path1: *const c_char, path2: *const c_char) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "truncate64")] pub fn truncate(path: *const c_char, length: off_t) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "ftruncate64")] pub fn ftruncate(fd: c_int, length: off_t) -> c_int; pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; #[cfg_attr(target_os = "netbsd", link_name = "__getrusage50")] pub fn getrusage(resource: c_int, usage: *mut rusage) -> c_int; #[cfg_attr( any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos" ), link_name = "realpath$DARWIN_EXTSN" )] pub fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char; #[cfg_attr(target_os = "netbsd", link_name = "__times13")] pub fn times(buf: *mut crate::tms) -> crate::clock_t; pub fn pthread_self() -> crate::pthread_t; pub fn pthread_equal(t1: crate::pthread_t, t2: crate::pthread_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_join$UNIX2003" )] pub fn pthread_join(native: crate::pthread_t, value: *mut *mut c_void) -> c_int; pub fn pthread_exit(value: *mut c_void) -> !; pub fn pthread_attr_init(attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_destroy(attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_getstacksize( attr: *const crate::pthread_attr_t, stacksize: *mut size_t, ) -> c_int; pub fn pthread_attr_setstacksize(attr: *mut crate::pthread_attr_t, stack_size: size_t) -> c_int; pub fn pthread_attr_setdetachstate(attr: *mut crate::pthread_attr_t, state: c_int) -> c_int; pub fn pthread_detach(thread: crate::pthread_t) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__libc_thr_yield")] pub fn sched_yield() -> c_int; pub fn pthread_key_create( key: *mut pthread_key_t, dtor: Option, ) -> c_int; pub fn pthread_key_delete(key: pthread_key_t) -> c_int; pub fn pthread_getspecific(key: pthread_key_t) -> *mut c_void; pub fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int; pub fn pthread_mutex_init( lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, ) -> c_int; pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_mutexattr_destroy$UNIX2003" )] pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int; pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_init$UNIX2003" )] pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_wait$UNIX2003" )] pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_timedwait$UNIX2003" )] pub fn pthread_cond_timedwait( cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int; pub fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_init$UNIX2003" )] pub fn pthread_rwlock_init( lock: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t, ) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_destroy$UNIX2003" )] pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_rdlock$UNIX2003" )] pub fn pthread_rwlock_rdlock(lock: *mut pthread_rwlock_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_tryrdlock$UNIX2003" )] pub fn pthread_rwlock_tryrdlock(lock: *mut pthread_rwlock_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_wrlock$UNIX2003" )] pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_trywrlock$UNIX2003" )] pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_unlock$UNIX2003" )] pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> c_int; pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int; pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> c_int; #[cfg_attr( any(target_os = "illumos", target_os = "solaris"), link_name = "__xnet_getsockopt" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_getsockopt")] pub fn getsockopt( sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut crate::socklen_t, ) -> c_int; pub fn raise(signum: c_int) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__utimes50")] pub fn utimes(filename: *const c_char, times: *const crate::timeval) -> c_int; pub fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void; pub fn dlerror() -> *mut c_char; pub fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void; pub fn dlclose(handle: *mut c_void) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr( any(target_os = "illumos", target_os = "solaris"), link_name = "__xnet_getaddrinfo" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_getaddrinfo")] pub fn getaddrinfo( node: *const c_char, service: *const c_char, hints: *const addrinfo, res: *mut *mut addrinfo, ) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr(target_os = "espidf", link_name = "lwip_freeaddrinfo")] pub fn freeaddrinfo(res: *mut addrinfo); pub fn hstrerror(errcode: c_int) -> *const c_char; pub fn gai_strerror(errcode: c_int) -> *const c_char; #[cfg_attr( any( all( target_os = "linux", not(any(target_env = "musl", target_env = "ohos")) ), target_os = "freebsd", target_os = "cygwin", target_os = "dragonfly", target_os = "haiku" ), link_name = "__res_init" )] #[cfg_attr( any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos" ), link_name = "res_9_init" )] pub fn res_init() -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__gmtime_r50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME(time): for `time_t` pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__localtime_r50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME(time): for `time_t` pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "mktime$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__mktime50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn mktime(tm: *mut tm) -> time_t; #[cfg_attr(target_os = "netbsd", link_name = "__time50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn time(time: *mut time_t) -> time_t; #[cfg_attr(target_os = "netbsd", link_name = "__gmtime50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME(time): for `time_t` pub fn gmtime(time_p: *const time_t) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__locatime50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME(time): for `time_t` pub fn localtime(time_p: *const time_t) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__difftime50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME(time): for `time_t` pub fn difftime(time1: time_t, time0: time_t) -> c_double; #[cfg_attr(target_os = "netbsd", link_name = "__timegm50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME(time): for `time_t` pub fn timegm(tm: *mut crate::tm) -> time_t; #[cfg_attr(target_os = "netbsd", link_name = "__mknod50")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "mknod@FBSD_1.0" )] pub fn mknod(pathname: *const c_char, mode: crate::mode_t, dev: crate::dev_t) -> c_int; pub fn gethostname(name: *mut c_char, len: size_t) -> c_int; pub fn endservent(); pub fn getservbyname(name: *const c_char, proto: *const c_char) -> *mut servent; pub fn getservbyport(port: c_int, proto: *const c_char) -> *mut servent; pub fn getservent() -> *mut servent; pub fn setservent(stayopen: c_int); pub fn getprotobyname(name: *const c_char) -> *mut protoent; pub fn getprotobynumber(proto: c_int) -> *mut protoent; pub fn chroot(name: *const c_char) -> c_int; #[cfg(target_os = "cygwin")] pub fn usleep(secs: useconds_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "usleep$UNIX2003" )] #[cfg(not(target_os = "cygwin"))] pub fn usleep(secs: c_uint) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "send$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_send")] pub fn send(socket: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "recv$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_recv")] pub fn recv(socket: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "putenv$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__putenv50")] pub fn putenv(string: *mut c_char) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "poll$UNIX2003" )] pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "select$1050" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "select$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__select50")] pub fn select( nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *mut timeval, ) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__setlocale50")] pub fn setlocale(category: c_int, locale: *const c_char) -> *mut c_char; pub fn localeconv() -> *mut lconv; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sem_wait$UNIX2003" )] pub fn sem_wait(sem: *mut sem_t) -> c_int; pub fn sem_trywait(sem: *mut sem_t) -> c_int; pub fn sem_post(sem: *mut sem_t) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "statvfs64")] pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "fstatvfs64")] pub fn fstatvfs(fd: c_int, buf: *mut statvfs) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] pub fn sigemptyset(set: *mut sigset_t) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] pub fn sigaddset(set: *mut sigset_t, signum: c_int) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigfillset14")] pub fn sigfillset(set: *mut sigset_t) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigdelset14")] pub fn sigdelset(set: *mut sigset_t, signum: c_int) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigismember14")] pub fn sigismember(set: *const sigset_t, signum: c_int) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigprocmask14")] pub fn sigprocmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigpending14")] pub fn sigpending(set: *mut sigset_t) -> c_int; #[cfg_attr(target_os = "solaris", link_name = "__sysconf_xpg7")] pub fn sysconf(name: c_int) -> c_long; pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "fseeko64")] pub fn fseeko(stream: *mut crate::FILE, offset: off_t, whence: c_int) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "ftello64")] pub fn ftello(stream: *mut crate::FILE) -> off_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "tcdrain$UNIX2003" )] pub fn tcdrain(fd: c_int) -> c_int; pub fn cfgetispeed(termios: *const crate::termios) -> crate::speed_t; pub fn cfgetospeed(termios: *const crate::termios) -> crate::speed_t; pub fn cfsetispeed(termios: *mut crate::termios, speed: crate::speed_t) -> c_int; pub fn cfsetospeed(termios: *mut crate::termios, speed: crate::speed_t) -> c_int; pub fn tcgetattr(fd: c_int, termios: *mut crate::termios) -> c_int; pub fn tcsetattr(fd: c_int, optional_actions: c_int, termios: *const crate::termios) -> c_int; pub fn tcflow(fd: c_int, action: c_int) -> c_int; pub fn tcflush(fd: c_int, action: c_int) -> c_int; pub fn tcgetsid(fd: c_int) -> crate::pid_t; pub fn tcsendbreak(fd: c_int, duration: c_int) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "mkstemp64")] pub fn mkstemp(template: *mut c_char) -> c_int; pub fn mkdtemp(template: *mut c_char) -> *mut c_char; pub fn tmpnam(ptr: *mut c_char) -> *mut c_char; pub fn openlog(ident: *const c_char, logopt: c_int, facility: c_int); pub fn closelog(); pub fn setlogmask(maskpri: c_int) -> c_int; #[cfg_attr(target_os = "macos", link_name = "syslog$DARWIN_EXTSN")] pub fn syslog(priority: c_int, message: *const c_char, ...); #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "nice$UNIX2003" )] pub fn nice(incr: c_int) -> c_int; pub fn grantpt(fd: c_int) -> c_int; pub fn posix_openpt(flags: c_int) -> c_int; pub fn ptsname(fd: c_int) -> *mut c_char; pub fn unlockpt(fd: c_int) -> c_int; pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; #[cfg_attr(gnu_file_offset_bits64, link_name = "lockf64")] pub fn lockf(fd: c_int, cmd: c_int, len: off_t) -> c_int; } safe_f! { // It seems htonl, etc are macros on macOS. So we have to reimplement them. So let's // reimplement them for all UNIX platforms pub {const} fn htonl(hostlong: u32) -> u32 { u32::to_be(hostlong) } pub {const} fn htons(hostshort: u16) -> u16 { u16::to_be(hostshort) } pub {const} fn ntohl(netlong: u32) -> u32 { u32::from_be(netlong) } pub {const} fn ntohs(netshort: u16) -> u16 { u16::from_be(netshort) } } cfg_if! { if #[cfg(not(any( target_os = "emscripten", target_os = "android", target_os = "haiku", target_os = "nto", target_os = "solaris", target_os = "cygwin" )))] { extern "C" { pub fn adjtime(delta: *const timeval, olddelta: *mut timeval) -> c_int; } } else if #[cfg(target_os = "solaris")] { extern "C" { pub fn adjtime(delta: *mut timeval, olddelta: *mut timeval) -> c_int; } } } cfg_if! { if #[cfg(not(any( target_os = "emscripten", target_os = "android", target_os = "nto" )))] { extern "C" { pub fn stpncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; } } } cfg_if! { if #[cfg(not(target_os = "android"))] { extern "C" { #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "confstr$UNIX2003" )] #[cfg_attr(target_os = "solaris", link_name = "__confstr_xpg7")] pub fn confstr(name: c_int, buf: *mut c_char, len: size_t) -> size_t; } } } cfg_if! { if #[cfg(not(target_os = "aix"))] { extern "C" { pub fn dladdr(addr: *const c_void, info: *mut Dl_info) -> c_int; } } } cfg_if! { if #[cfg(not(target_os = "solaris"))] { extern "C" { pub fn flock(fd: c_int, operation: c_int) -> c_int; } } } cfg_if! { if #[cfg(not(any(target_env = "uclibc", target_os = "nto")))] { extern "C" { pub fn open_wmemstream(ptr: *mut *mut wchar_t, sizeloc: *mut size_t) -> *mut FILE; } } } cfg_if! { if #[cfg(not(target_os = "redox"))] { extern "C" { pub fn getsid(pid: pid_t) -> pid_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pause$UNIX2003" )] pub fn pause() -> c_int; pub fn mkdirat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "openat64")] pub fn openat(dirfd: c_int, pathname: *const c_char, flags: c_int, ...) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "fdopendir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fdopendir$INODE64$UNIX2003" )] pub fn fdopendir(fd: c_int) -> *mut crate::DIR; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "readdir_r$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__readdir_r30")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "readdir_r@FBSD_1.0" )] #[allow(non_autolinks)] // FIXME(docs): `<>` breaks line length limit. /// The 64-bit libc on Solaris and illumos only has readdir_r. If a /// 32-bit Solaris or illumos target is ever created, it should use /// __posix_readdir_r. See libc(3LIB) on Solaris or illumos: /// https://illumos.org/man/3lib/libc /// https://docs.oracle.com/cd/E36784_01/html/E36873/libc-3lib.html /// https://www.unix.com/man-page/opensolaris/3LIB/libc/ #[cfg_attr(gnu_file_offset_bits64, link_name = "readdir64_r")] pub fn readdir_r( dirp: *mut crate::DIR, entry: *mut crate::dirent, result: *mut *mut crate::dirent, ) -> c_int; } } } cfg_if! { if #[cfg(target_os = "nto")] { extern "C" { pub fn readlinkat( dirfd: c_int, pathname: *const c_char, buf: *mut c_char, bufsiz: size_t, ) -> c_int; pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: size_t) -> c_int; pub fn pselect( nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *mut timespec, sigmask: *const sigset_t, ) -> c_int; pub fn sigaction(signum: c_int, act: *const sigaction, oldact: *mut sigaction) -> c_int; } } else { extern "C" { pub fn readlinkat( dirfd: c_int, pathname: *const c_char, buf: *mut c_char, bufsiz: size_t, ) -> ssize_t; pub fn fmemopen(buf: *mut c_void, size: size_t, mode: *const c_char) -> *mut FILE; pub fn open_memstream(ptr: *mut *mut c_char, sizeloc: *mut size_t) -> *mut FILE; pub fn atexit(cb: extern "C" fn()) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigaction14")] pub fn sigaction(signum: c_int, act: *const sigaction, oldact: *mut sigaction) -> c_int; pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: size_t) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "pselect$1050" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pselect$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__pselect50")] pub fn pselect( nfds: c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *const timespec, sigmask: *const sigset_t, ) -> c_int; } } } cfg_if! { if #[cfg(not(any( target_os = "solaris", target_os = "illumos", target_os = "nto", )))] { extern "C" { pub fn cfmakeraw(termios: *mut crate::termios); pub fn cfsetspeed(termios: *mut crate::termios, speed: crate::speed_t) -> c_int; } } } extern "C" { pub fn fnmatch(pattern: *const c_char, name: *const c_char, flags: c_int) -> c_int; } cfg_if! { if #[cfg(target_env = "newlib")] { mod newlib; pub use self::newlib::*; } else if #[cfg(any( target_os = "linux", target_os = "l4re", target_os = "android", target_os = "emscripten" ))] { mod linux_like; pub use self::linux_like::*; } else if #[cfg(any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd" ))] { mod bsd; pub use self::bsd::*; } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] { mod solarish; pub use self::solarish::*; } else if #[cfg(target_os = "haiku")] { mod haiku; pub use self::haiku::*; } else if #[cfg(target_os = "redox")] { mod redox; pub use self::redox::*; } else if #[cfg(target_os = "cygwin")] { mod cygwin; pub use self::cygwin::*; } else if #[cfg(target_os = "nto")] { mod nto; pub use self::nto::*; } else if #[cfg(target_os = "aix")] { mod aix; pub use self::aix::*; } else if #[cfg(target_os = "hurd")] { mod hurd; pub use self::hurd::*; } else if #[cfg(target_os = "nuttx")] { mod nuttx; pub use self::nuttx::*; } else { // Unknown target_os } } libc/src/unix/linux_like/0000775000175000017500000000000015105742312015232 5ustar bdrungbdrunglibc/src/unix/linux_like/mod.rs0000644000175000017500000022135615105742312016366 0ustar bdrungbdrunguse crate::prelude::*; pub type sa_family_t = u16; pub type speed_t = c_uint; pub type tcflag_t = c_uint; pub type clockid_t = c_int; pub type timer_t = *mut c_void; pub type key_t = c_int; pub type id_t = c_uint; missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} } s! { pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: c_int, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, pub imr_sourceaddr: in_addr, } pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } // The order of the `ai_addr` field in this struct is crucial // for converting between the Rust and C types. pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, #[cfg(any(target_os = "linux", target_os = "emscripten"))] pub ai_addr: *mut crate::sockaddr, pub ai_canonname: *mut c_char, #[cfg(target_os = "android")] pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut addrinfo, } pub struct sockaddr_ll { pub sll_family: c_ushort, pub sll_protocol: c_ushort, pub sll_ifindex: c_int, pub sll_hatype: c_ushort, pub sll_pkttype: c_uchar, pub sll_halen: c_uchar, pub sll_addr: [c_uchar; 8], } pub struct fd_set { fds_bits: [c_ulong; FD_SETSIZE as usize / ULONG_SIZE], } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *const c_char, } pub struct sched_param { pub sched_priority: c_int, #[cfg(any(target_env = "musl", target_os = "emscripten", target_env = "ohos"))] pub sched_ss_low_priority: c_int, #[cfg(any(target_env = "musl", target_os = "emscripten", target_env = "ohos"))] pub sched_ss_repl_period: crate::timespec, #[cfg(any(target_env = "musl", target_os = "emscripten", target_env = "ohos"))] pub sched_ss_init_budget: crate::timespec, #[cfg(any(target_env = "musl", target_os = "emscripten", target_env = "ohos"))] pub sched_ss_max_repl: c_int, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct in_pktinfo { pub ipi_ifindex: c_int, pub ipi_spec_dst: crate::in_addr, pub ipi_addr: crate::in_addr, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, pub ifa_addr: *mut crate::sockaddr, pub ifa_netmask: *mut crate::sockaddr, pub ifa_ifu: *mut crate::sockaddr, // FIXME(union) This should be a union pub ifa_data: *mut c_void, } pub struct in6_rtmsg { rtmsg_dst: crate::in6_addr, rtmsg_src: crate::in6_addr, rtmsg_gateway: crate::in6_addr, rtmsg_type: u32, rtmsg_dst_len: u16, rtmsg_src_len: u16, rtmsg_metric: u32, rtmsg_info: c_ulong, rtmsg_flags: u32, rtmsg_ifindex: c_int, } pub struct arpreq { pub arp_pa: crate::sockaddr, pub arp_ha: crate::sockaddr, pub arp_flags: c_int, pub arp_netmask: crate::sockaddr, pub arp_dev: [c_char; 16], } pub struct arpreq_old { pub arp_pa: crate::sockaddr, pub arp_ha: crate::sockaddr, pub arp_flags: c_int, pub arp_netmask: crate::sockaddr, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct mmsghdr { pub msg_hdr: crate::msghdr, pub msg_len: c_uint, } } cfg_if! { if #[cfg(any(target_env = "gnu", target_os = "android"))] { s! { pub struct statx { pub stx_mask: crate::__u32, pub stx_blksize: crate::__u32, pub stx_attributes: crate::__u64, pub stx_nlink: crate::__u32, pub stx_uid: crate::__u32, pub stx_gid: crate::__u32, pub stx_mode: crate::__u16, __statx_pad1: [crate::__u16; 1], pub stx_ino: crate::__u64, pub stx_size: crate::__u64, pub stx_blocks: crate::__u64, pub stx_attributes_mask: crate::__u64, pub stx_atime: statx_timestamp, pub stx_btime: statx_timestamp, pub stx_ctime: statx_timestamp, pub stx_mtime: statx_timestamp, pub stx_rdev_major: crate::__u32, pub stx_rdev_minor: crate::__u32, pub stx_dev_major: crate::__u32, pub stx_dev_minor: crate::__u32, pub stx_mnt_id: crate::__u64, pub stx_dio_mem_align: crate::__u32, pub stx_dio_offset_align: crate::__u32, __statx_pad3: [crate::__u64; 12], } pub struct statx_timestamp { pub tv_sec: crate::__s64, pub tv_nsec: crate::__u32, __statx_timestamp_pad1: [crate::__s32; 1], } } } } s_no_extra_traits! { #[cfg_attr( any( all( target_arch = "x86", not(target_env = "musl"), not(target_os = "android") ), target_arch = "x86_64" ), repr(packed) )] pub struct epoll_event { pub events: u32, pub u64: u64, } pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char; 108], } pub struct sockaddr_storage { pub ss_family: sa_family_t, #[cfg(target_pointer_width = "32")] __ss_pad2: [u8; 128 - 2 - 4], #[cfg(target_pointer_width = "64")] __ss_pad2: [u8; 128 - 2 - 8], __ss_align: size_t, } pub struct utsname { pub sysname: [c_char; 65], pub nodename: [c_char; 65], pub release: [c_char; 65], pub version: [c_char; 65], pub machine: [c_char; 65], pub domainname: [c_char; 65], } pub struct sigevent { pub sigev_value: crate::sigval, pub sigev_signo: c_int, pub sigev_notify: c_int, // Actually a union. We only expose sigev_notify_thread_id because it's // the most useful member pub sigev_notify_thread_id: c_int, #[cfg(target_pointer_width = "64")] __unused1: [c_int; 11], #[cfg(target_pointer_width = "32")] __unused1: [c_int; 12], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for epoll_event { fn eq(&self, other: &epoll_event) -> bool { self.events == other.events && self.u64 == other.u64 } } impl Eq for epoll_event {} impl fmt::Debug for epoll_event { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let events = self.events; let u64 = self.u64; f.debug_struct("epoll_event") .field("events", &events) .field("u64", &u64) .finish() } } impl hash::Hash for epoll_event { fn hash(&self, state: &mut H) { let events = self.events; let u64 = self.u64; events.hash(state); u64.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME(debug): .field("sun_path", &self.sun_path) .finish() } } impl hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_family == other.ss_family && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_family", &self.ss_family) .field("__ss_align", &self.__ss_align) // FIXME(debug): .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_family.hash(state); self.__ss_pad2.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) && self .domainname .iter() .zip(other.domainname.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl fmt::Debug for utsname { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utsname") // FIXME(debug): .field("sysname", &self.sysname) // FIXME(debug): .field("nodename", &self.nodename) // FIXME(debug): .field("release", &self.release) // FIXME(debug): .field("version", &self.version) // FIXME(debug): .field("machine", &self.machine) // FIXME(debug): .field("domainname", &self.domainname) .finish() } } impl hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); self.domainname.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_value == other.sigev_value && self.sigev_signo == other.sigev_signo && self.sigev_notify == other.sigev_notify && self.sigev_notify_thread_id == other.sigev_notify_thread_id } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_value", &self.sigev_value) .field("sigev_signo", &self.sigev_signo) .field("sigev_notify", &self.sigev_notify) .field("sigev_notify_thread_id", &self.sigev_notify_thread_id) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_value.hash(state); self.sigev_signo.hash(state); self.sigev_notify.hash(state); self.sigev_notify_thread_id.hash(state); } } } } // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { const ULONG_SIZE: usize = 32; } else if #[cfg(target_pointer_width = "64")] { const ULONG_SIZE: usize = 64; } else { // Unknown target_pointer_width } } pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 2147483647; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; // Linux-specific fcntls pub const F_SETLEASE: c_int = 1024; pub const F_GETLEASE: c_int = 1025; pub const F_NOTIFY: c_int = 1026; pub const F_CANCELLK: c_int = 1029; pub const F_DUPFD_CLOEXEC: c_int = 1030; pub const F_SETPIPE_SZ: c_int = 1031; pub const F_GETPIPE_SZ: c_int = 1032; pub const F_ADD_SEALS: c_int = 1033; pub const F_GET_SEALS: c_int = 1034; pub const F_SEAL_SEAL: c_int = 0x0001; pub const F_SEAL_SHRINK: c_int = 0x0002; pub const F_SEAL_GROW: c_int = 0x0004; pub const F_SEAL_WRITE: c_int = 0x0008; // FIXME(#235): Include file sealing fcntls once we have a way to verify them. pub const SIGTRAP: c_int = 5; pub const PTHREAD_CREATE_JOINABLE: c_int = 0; pub const PTHREAD_CREATE_DETACHED: c_int = 1; pub const CLOCK_REALTIME: crate::clockid_t = 0; pub const CLOCK_MONOTONIC: crate::clockid_t = 1; pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 3; pub const CLOCK_MONOTONIC_RAW: crate::clockid_t = 4; pub const CLOCK_REALTIME_COARSE: crate::clockid_t = 5; pub const CLOCK_MONOTONIC_COARSE: crate::clockid_t = 6; pub const CLOCK_BOOTTIME: crate::clockid_t = 7; pub const CLOCK_REALTIME_ALARM: crate::clockid_t = 8; pub const CLOCK_BOOTTIME_ALARM: crate::clockid_t = 9; pub const CLOCK_TAI: crate::clockid_t = 11; pub const TIMER_ABSTIME: c_int = 1; pub const RUSAGE_SELF: c_int = 0; pub const O_RDONLY: c_int = 0; pub const O_WRONLY: c_int = 1; pub const O_RDWR: c_int = 2; pub const SOCK_CLOEXEC: c_int = O_CLOEXEC; pub const S_IFIFO: crate::mode_t = 0o1_0000; pub const S_IFCHR: crate::mode_t = 0o2_0000; pub const S_IFBLK: crate::mode_t = 0o6_0000; pub const S_IFDIR: crate::mode_t = 0o4_0000; pub const S_IFREG: crate::mode_t = 0o10_0000; pub const S_IFLNK: crate::mode_t = 0o12_0000; pub const S_IFSOCK: crate::mode_t = 0o14_0000; pub const S_IFMT: crate::mode_t = 0o17_0000; pub const S_IRWXU: crate::mode_t = 0o0700; pub const S_IXUSR: crate::mode_t = 0o0100; pub const S_IWUSR: crate::mode_t = 0o0200; pub const S_IRUSR: crate::mode_t = 0o0400; pub const S_IRWXG: crate::mode_t = 0o0070; pub const S_IXGRP: crate::mode_t = 0o0010; pub const S_IWGRP: crate::mode_t = 0o0020; pub const S_IRGRP: crate::mode_t = 0o0040; pub const S_IRWXO: crate::mode_t = 0o0007; pub const S_IXOTH: crate::mode_t = 0o0001; pub const S_IWOTH: crate::mode_t = 0o0002; pub const S_IROTH: crate::mode_t = 0o0004; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSEGV: c_int = 11; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const XATTR_CREATE: c_int = 0x1; pub const XATTR_REPLACE: c_int = 0x2; cfg_if! { if #[cfg(target_os = "android")] { pub const RLIM64_INFINITY: c_ulonglong = !0; } else { pub const RLIM64_INFINITY: crate::rlim64_t = !0; } } cfg_if! { if #[cfg(target_env = "ohos")] { pub const LC_CTYPE: c_int = 0; pub const LC_NUMERIC: c_int = 1; pub const LC_TIME: c_int = 2; pub const LC_COLLATE: c_int = 3; pub const LC_MONETARY: c_int = 4; pub const LC_MESSAGES: c_int = 5; pub const LC_PAPER: c_int = 6; pub const LC_NAME: c_int = 7; pub const LC_ADDRESS: c_int = 8; pub const LC_TELEPHONE: c_int = 9; pub const LC_MEASUREMENT: c_int = 10; pub const LC_IDENTIFICATION: c_int = 11; pub const LC_ALL: c_int = 12; } else if #[cfg(not(target_env = "uclibc"))] { pub const LC_CTYPE: c_int = 0; pub const LC_NUMERIC: c_int = 1; pub const LC_TIME: c_int = 2; pub const LC_COLLATE: c_int = 3; pub const LC_MONETARY: c_int = 4; pub const LC_MESSAGES: c_int = 5; pub const LC_ALL: c_int = 6; } } pub const LC_CTYPE_MASK: c_int = 1 << LC_CTYPE; pub const LC_NUMERIC_MASK: c_int = 1 << LC_NUMERIC; pub const LC_TIME_MASK: c_int = 1 << LC_TIME; pub const LC_COLLATE_MASK: c_int = 1 << LC_COLLATE; pub const LC_MONETARY_MASK: c_int = 1 << LC_MONETARY; pub const LC_MESSAGES_MASK: c_int = 1 << LC_MESSAGES; // LC_ALL_MASK defined per platform pub const MAP_FILE: c_int = 0x0000; pub const MAP_SHARED: c_int = 0x0001; pub const MAP_PRIVATE: c_int = 0x0002; pub const MAP_FIXED: c_int = 0x0010; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; // MS_ flags for msync(2) pub const MS_ASYNC: c_int = 0x0001; pub const MS_INVALIDATE: c_int = 0x0002; pub const MS_SYNC: c_int = 0x0004; // MS_ flags for mount(2) pub const MS_RDONLY: c_ulong = 0x01; pub const MS_NOSUID: c_ulong = 0x02; pub const MS_NODEV: c_ulong = 0x04; pub const MS_NOEXEC: c_ulong = 0x08; pub const MS_SYNCHRONOUS: c_ulong = 0x10; pub const MS_REMOUNT: c_ulong = 0x20; pub const MS_MANDLOCK: c_ulong = 0x40; pub const MS_DIRSYNC: c_ulong = 0x80; pub const MS_NOATIME: c_ulong = 0x0400; pub const MS_NODIRATIME: c_ulong = 0x0800; pub const MS_BIND: c_ulong = 0x1000; pub const MS_MOVE: c_ulong = 0x2000; pub const MS_REC: c_ulong = 0x4000; pub const MS_SILENT: c_ulong = 0x8000; pub const MS_POSIXACL: c_ulong = 0x010000; pub const MS_UNBINDABLE: c_ulong = 0x020000; pub const MS_PRIVATE: c_ulong = 0x040000; pub const MS_SLAVE: c_ulong = 0x080000; pub const MS_SHARED: c_ulong = 0x100000; pub const MS_RELATIME: c_ulong = 0x200000; pub const MS_KERNMOUNT: c_ulong = 0x400000; pub const MS_I_VERSION: c_ulong = 0x800000; pub const MS_STRICTATIME: c_ulong = 0x1000000; pub const MS_LAZYTIME: c_ulong = 0x2000000; pub const MS_ACTIVE: c_ulong = 0x40000000; pub const MS_MGC_VAL: c_ulong = 0xc0ed0000; pub const MS_MGC_MSK: c_ulong = 0xffff0000; pub const SCM_RIGHTS: c_int = 0x01; pub const SCM_CREDENTIALS: c_int = 0x02; pub const PROT_GROWSDOWN: c_int = 0x1000000; pub const PROT_GROWSUP: c_int = 0x2000000; pub const MAP_TYPE: c_int = 0x000f; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const MADV_FREE: c_int = 8; pub const MADV_REMOVE: c_int = 9; pub const MADV_DONTFORK: c_int = 10; pub const MADV_DOFORK: c_int = 11; pub const MADV_MERGEABLE: c_int = 12; pub const MADV_UNMERGEABLE: c_int = 13; pub const MADV_HUGEPAGE: c_int = 14; pub const MADV_NOHUGEPAGE: c_int = 15; pub const MADV_DONTDUMP: c_int = 16; pub const MADV_DODUMP: c_int = 17; pub const MADV_WIPEONFORK: c_int = 18; pub const MADV_KEEPONFORK: c_int = 19; pub const MADV_COLD: c_int = 20; pub const MADV_PAGEOUT: c_int = 21; pub const MADV_HWPOISON: c_int = 100; cfg_if! { if #[cfg(not(target_os = "emscripten"))] { pub const MADV_POPULATE_READ: c_int = 22; pub const MADV_POPULATE_WRITE: c_int = 23; pub const MADV_DONTNEED_LOCKED: c_int = 24; } } pub const IFF_UP: c_int = 0x1; pub const IFF_BROADCAST: c_int = 0x2; pub const IFF_DEBUG: c_int = 0x4; pub const IFF_LOOPBACK: c_int = 0x8; pub const IFF_POINTOPOINT: c_int = 0x10; pub const IFF_NOTRAILERS: c_int = 0x20; pub const IFF_RUNNING: c_int = 0x40; pub const IFF_NOARP: c_int = 0x80; pub const IFF_PROMISC: c_int = 0x100; pub const IFF_ALLMULTI: c_int = 0x200; pub const IFF_MASTER: c_int = 0x400; pub const IFF_SLAVE: c_int = 0x800; pub const IFF_MULTICAST: c_int = 0x1000; pub const IFF_PORTSEL: c_int = 0x2000; pub const IFF_AUTOMEDIA: c_int = 0x4000; pub const IFF_DYNAMIC: c_int = 0x8000; pub const SOL_IP: c_int = 0; pub const SOL_TCP: c_int = 6; pub const SOL_UDP: c_int = 17; pub const SOL_IPV6: c_int = 41; pub const SOL_ICMPV6: c_int = 58; pub const SOL_RAW: c_int = 255; pub const SOL_DECNET: c_int = 261; pub const SOL_X25: c_int = 262; pub const SOL_PACKET: c_int = 263; pub const SOL_ATM: c_int = 264; pub const SOL_AAL: c_int = 265; pub const SOL_IRDA: c_int = 266; pub const SOL_NETBEUI: c_int = 267; pub const SOL_LLC: c_int = 268; pub const SOL_DCCP: c_int = 269; pub const SOL_NETLINK: c_int = 270; pub const SOL_TIPC: c_int = 271; pub const SOL_BLUETOOTH: c_int = 274; pub const SOL_ALG: c_int = 279; pub const AF_UNSPEC: c_int = 0; pub const AF_UNIX: c_int = 1; pub const AF_LOCAL: c_int = 1; pub const AF_INET: c_int = 2; pub const AF_AX25: c_int = 3; pub const AF_IPX: c_int = 4; pub const AF_APPLETALK: c_int = 5; pub const AF_NETROM: c_int = 6; pub const AF_BRIDGE: c_int = 7; pub const AF_ATMPVC: c_int = 8; pub const AF_X25: c_int = 9; pub const AF_INET6: c_int = 10; pub const AF_ROSE: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_NETBEUI: c_int = 13; pub const AF_SECURITY: c_int = 14; pub const AF_KEY: c_int = 15; pub const AF_NETLINK: c_int = 16; pub const AF_ROUTE: c_int = AF_NETLINK; pub const AF_PACKET: c_int = 17; pub const AF_ASH: c_int = 18; pub const AF_ECONET: c_int = 19; pub const AF_ATMSVC: c_int = 20; pub const AF_RDS: c_int = 21; pub const AF_SNA: c_int = 22; pub const AF_IRDA: c_int = 23; pub const AF_PPPOX: c_int = 24; pub const AF_WANPIPE: c_int = 25; pub const AF_LLC: c_int = 26; pub const AF_CAN: c_int = 29; pub const AF_TIPC: c_int = 30; pub const AF_BLUETOOTH: c_int = 31; pub const AF_IUCV: c_int = 32; pub const AF_RXRPC: c_int = 33; pub const AF_ISDN: c_int = 34; pub const AF_PHONET: c_int = 35; pub const AF_IEEE802154: c_int = 36; pub const AF_CAIF: c_int = 37; pub const AF_ALG: c_int = 38; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_UNIX: c_int = AF_UNIX; pub const PF_LOCAL: c_int = AF_LOCAL; pub const PF_INET: c_int = AF_INET; pub const PF_AX25: c_int = AF_AX25; pub const PF_IPX: c_int = AF_IPX; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_NETROM: c_int = AF_NETROM; pub const PF_BRIDGE: c_int = AF_BRIDGE; pub const PF_ATMPVC: c_int = AF_ATMPVC; pub const PF_X25: c_int = AF_X25; pub const PF_INET6: c_int = AF_INET6; pub const PF_ROSE: c_int = AF_ROSE; pub const PF_DECnet: c_int = AF_DECnet; pub const PF_NETBEUI: c_int = AF_NETBEUI; pub const PF_SECURITY: c_int = AF_SECURITY; pub const PF_KEY: c_int = AF_KEY; pub const PF_NETLINK: c_int = AF_NETLINK; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_PACKET: c_int = AF_PACKET; pub const PF_ASH: c_int = AF_ASH; pub const PF_ECONET: c_int = AF_ECONET; pub const PF_ATMSVC: c_int = AF_ATMSVC; pub const PF_RDS: c_int = AF_RDS; pub const PF_SNA: c_int = AF_SNA; pub const PF_IRDA: c_int = AF_IRDA; pub const PF_PPPOX: c_int = AF_PPPOX; pub const PF_WANPIPE: c_int = AF_WANPIPE; pub const PF_LLC: c_int = AF_LLC; pub const PF_CAN: c_int = AF_CAN; pub const PF_TIPC: c_int = AF_TIPC; pub const PF_BLUETOOTH: c_int = AF_BLUETOOTH; pub const PF_IUCV: c_int = AF_IUCV; pub const PF_RXRPC: c_int = AF_RXRPC; pub const PF_ISDN: c_int = AF_ISDN; pub const PF_PHONET: c_int = AF_PHONET; pub const PF_IEEE802154: c_int = AF_IEEE802154; pub const PF_CAIF: c_int = AF_CAIF; pub const PF_ALG: c_int = AF_ALG; pub const MSG_OOB: c_int = 1; pub const MSG_PEEK: c_int = 2; pub const MSG_DONTROUTE: c_int = 4; pub const MSG_CTRUNC: c_int = 8; pub const MSG_TRUNC: c_int = 0x20; pub const MSG_DONTWAIT: c_int = 0x40; pub const MSG_EOR: c_int = 0x80; pub const MSG_WAITALL: c_int = 0x100; pub const MSG_FIN: c_int = 0x200; pub const MSG_SYN: c_int = 0x400; pub const MSG_CONFIRM: c_int = 0x800; pub const MSG_RST: c_int = 0x1000; pub const MSG_ERRQUEUE: c_int = 0x2000; pub const MSG_NOSIGNAL: c_int = 0x4000; pub const MSG_MORE: c_int = 0x8000; pub const MSG_WAITFORONE: c_int = 0x10000; pub const MSG_FASTOPEN: c_int = 0x20000000; pub const MSG_CMSG_CLOEXEC: c_int = 0x40000000; pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const IP_TOS: c_int = 1; pub const IP_TTL: c_int = 2; pub const IP_HDRINCL: c_int = 3; pub const IP_OPTIONS: c_int = 4; pub const IP_ROUTER_ALERT: c_int = 5; pub const IP_RECVOPTS: c_int = 6; pub const IP_RETOPTS: c_int = 7; pub const IP_PKTINFO: c_int = 8; pub const IP_PKTOPTIONS: c_int = 9; pub const IP_MTU_DISCOVER: c_int = 10; pub const IP_RECVERR: c_int = 11; pub const IP_RECVTTL: c_int = 12; pub const IP_RECVTOS: c_int = 13; pub const IP_MTU: c_int = 14; pub const IP_FREEBIND: c_int = 15; pub const IP_IPSEC_POLICY: c_int = 16; pub const IP_XFRM_POLICY: c_int = 17; pub const IP_PASSSEC: c_int = 18; pub const IP_TRANSPARENT: c_int = 19; pub const IP_ORIGDSTADDR: c_int = 20; pub const IP_RECVORIGDSTADDR: c_int = IP_ORIGDSTADDR; pub const IP_MINTTL: c_int = 21; pub const IP_NODEFRAG: c_int = 22; pub const IP_CHECKSUM: c_int = 23; pub const IP_BIND_ADDRESS_NO_PORT: c_int = 24; pub const IP_MULTICAST_IF: c_int = 32; pub const IP_MULTICAST_TTL: c_int = 33; pub const IP_MULTICAST_LOOP: c_int = 34; pub const IP_ADD_MEMBERSHIP: c_int = 35; pub const IP_DROP_MEMBERSHIP: c_int = 36; pub const IP_UNBLOCK_SOURCE: c_int = 37; pub const IP_BLOCK_SOURCE: c_int = 38; pub const IP_ADD_SOURCE_MEMBERSHIP: c_int = 39; pub const IP_DROP_SOURCE_MEMBERSHIP: c_int = 40; pub const IP_MSFILTER: c_int = 41; pub const IP_MULTICAST_ALL: c_int = 49; pub const IP_UNICAST_IF: c_int = 50; pub const IP_DEFAULT_MULTICAST_TTL: c_int = 1; pub const IP_DEFAULT_MULTICAST_LOOP: c_int = 1; pub const IP_PMTUDISC_DONT: c_int = 0; pub const IP_PMTUDISC_WANT: c_int = 1; pub const IP_PMTUDISC_DO: c_int = 2; pub const IP_PMTUDISC_PROBE: c_int = 3; pub const IP_PMTUDISC_INTERFACE: c_int = 4; pub const IP_PMTUDISC_OMIT: c_int = 5; // IPPROTO_IP defined in src/unix/mod.rs /// Hop-by-hop option header pub const IPPROTO_HOPOPTS: c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: c_int = 2; /// for compatibility pub const IPPROTO_IPIP: c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// exterior gateway protocol pub const IPPROTO_EGP: c_int = 8; /// pup pub const IPPROTO_PUP: c_int = 12; // IPPROTO_UDP defined in src/unix/mod.rs /// xns idp pub const IPPROTO_IDP: c_int = 22; /// tp-4 w/ class negotiation pub const IPPROTO_TP: c_int = 29; /// DCCP pub const IPPROTO_DCCP: c_int = 33; // IPPROTO_IPV6 defined in src/unix/mod.rs /// IP6 routing header pub const IPPROTO_ROUTING: c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: c_int = 44; /// resource reservation pub const IPPROTO_RSVP: c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: c_int = 47; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: c_int = 51; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: c_int = 60; pub const IPPROTO_MTP: c_int = 92; /// encapsulation header pub const IPPROTO_ENCAP: c_int = 98; /// Protocol indep. multicast pub const IPPROTO_PIM: c_int = 103; /// IP Payload Comp. Protocol pub const IPPROTO_COMP: c_int = 108; /// SCTP pub const IPPROTO_SCTP: c_int = 132; pub const IPPROTO_MH: c_int = 135; pub const IPPROTO_UDPLITE: c_int = 136; /// raw IP packet pub const IPPROTO_RAW: c_int = 255; pub const IPPROTO_BEETPH: c_int = 94; pub const IPPROTO_MPLS: c_int = 137; /// Multipath TCP pub const IPPROTO_MPTCP: c_int = 262; /// Ethernet-within-IPv6 encapsulation. pub const IPPROTO_ETHERNET: c_int = 143; pub const MCAST_EXCLUDE: c_int = 0; pub const MCAST_INCLUDE: c_int = 1; pub const MCAST_JOIN_GROUP: c_int = 42; pub const MCAST_BLOCK_SOURCE: c_int = 43; pub const MCAST_UNBLOCK_SOURCE: c_int = 44; pub const MCAST_LEAVE_GROUP: c_int = 45; pub const MCAST_JOIN_SOURCE_GROUP: c_int = 46; pub const MCAST_LEAVE_SOURCE_GROUP: c_int = 47; pub const MCAST_MSFILTER: c_int = 48; pub const IPV6_ADDRFORM: c_int = 1; pub const IPV6_2292PKTINFO: c_int = 2; pub const IPV6_2292HOPOPTS: c_int = 3; pub const IPV6_2292DSTOPTS: c_int = 4; pub const IPV6_2292RTHDR: c_int = 5; pub const IPV6_2292PKTOPTIONS: c_int = 6; pub const IPV6_CHECKSUM: c_int = 7; pub const IPV6_2292HOPLIMIT: c_int = 8; pub const IPV6_NEXTHOP: c_int = 9; pub const IPV6_AUTHHDR: c_int = 10; pub const IPV6_UNICAST_HOPS: c_int = 16; pub const IPV6_MULTICAST_IF: c_int = 17; pub const IPV6_MULTICAST_HOPS: c_int = 18; pub const IPV6_MULTICAST_LOOP: c_int = 19; pub const IPV6_ADD_MEMBERSHIP: c_int = 20; pub const IPV6_DROP_MEMBERSHIP: c_int = 21; pub const IPV6_ROUTER_ALERT: c_int = 22; pub const IPV6_MTU_DISCOVER: c_int = 23; pub const IPV6_MTU: c_int = 24; pub const IPV6_RECVERR: c_int = 25; pub const IPV6_V6ONLY: c_int = 26; pub const IPV6_JOIN_ANYCAST: c_int = 27; pub const IPV6_LEAVE_ANYCAST: c_int = 28; pub const IPV6_IPSEC_POLICY: c_int = 34; pub const IPV6_XFRM_POLICY: c_int = 35; pub const IPV6_HDRINCL: c_int = 36; pub const IPV6_RECVPKTINFO: c_int = 49; pub const IPV6_PKTINFO: c_int = 50; pub const IPV6_RECVHOPLIMIT: c_int = 51; pub const IPV6_HOPLIMIT: c_int = 52; pub const IPV6_RECVHOPOPTS: c_int = 53; pub const IPV6_HOPOPTS: c_int = 54; pub const IPV6_RTHDRDSTOPTS: c_int = 55; pub const IPV6_RECVRTHDR: c_int = 56; pub const IPV6_RTHDR: c_int = 57; pub const IPV6_RECVDSTOPTS: c_int = 58; pub const IPV6_DSTOPTS: c_int = 59; pub const IPV6_RECVPATHMTU: c_int = 60; pub const IPV6_PATHMTU: c_int = 61; pub const IPV6_DONTFRAG: c_int = 62; pub const IPV6_RECVTCLASS: c_int = 66; pub const IPV6_TCLASS: c_int = 67; pub const IPV6_AUTOFLOWLABEL: c_int = 70; pub const IPV6_ADDR_PREFERENCES: c_int = 72; pub const IPV6_MINHOPCOUNT: c_int = 73; pub const IPV6_ORIGDSTADDR: c_int = 74; pub const IPV6_RECVORIGDSTADDR: c_int = IPV6_ORIGDSTADDR; pub const IPV6_TRANSPARENT: c_int = 75; pub const IPV6_UNICAST_IF: c_int = 76; pub const IPV6_PREFER_SRC_TMP: c_int = 0x0001; pub const IPV6_PREFER_SRC_PUBLIC: c_int = 0x0002; pub const IPV6_PREFER_SRC_PUBTMP_DEFAULT: c_int = 0x0100; pub const IPV6_PREFER_SRC_COA: c_int = 0x0004; pub const IPV6_PREFER_SRC_HOME: c_int = 0x0400; pub const IPV6_PREFER_SRC_CGA: c_int = 0x0008; pub const IPV6_PREFER_SRC_NONCGA: c_int = 0x0800; pub const IPV6_PMTUDISC_DONT: c_int = 0; pub const IPV6_PMTUDISC_WANT: c_int = 1; pub const IPV6_PMTUDISC_DO: c_int = 2; pub const IPV6_PMTUDISC_PROBE: c_int = 3; pub const IPV6_PMTUDISC_INTERFACE: c_int = 4; pub const IPV6_PMTUDISC_OMIT: c_int = 5; pub const TCP_NODELAY: c_int = 1; pub const TCP_MAXSEG: c_int = 2; pub const TCP_CORK: c_int = 3; pub const TCP_KEEPIDLE: c_int = 4; pub const TCP_KEEPINTVL: c_int = 5; pub const TCP_KEEPCNT: c_int = 6; pub const TCP_SYNCNT: c_int = 7; pub const TCP_LINGER2: c_int = 8; pub const TCP_DEFER_ACCEPT: c_int = 9; pub const TCP_WINDOW_CLAMP: c_int = 10; pub const TCP_INFO: c_int = 11; pub const TCP_QUICKACK: c_int = 12; pub const TCP_CONGESTION: c_int = 13; pub const TCP_MD5SIG: c_int = 14; cfg_if! { if #[cfg(all( target_os = "linux", any(target_env = "gnu", target_env = "musl", target_env = "ohos") ))] { // WARN: deprecated pub const TCP_COOKIE_TRANSACTIONS: c_int = 15; } } pub const TCP_THIN_LINEAR_TIMEOUTS: c_int = 16; pub const TCP_THIN_DUPACK: c_int = 17; pub const TCP_USER_TIMEOUT: c_int = 18; pub const TCP_REPAIR: c_int = 19; pub const TCP_REPAIR_QUEUE: c_int = 20; pub const TCP_QUEUE_SEQ: c_int = 21; pub const TCP_REPAIR_OPTIONS: c_int = 22; pub const TCP_FASTOPEN: c_int = 23; pub const TCP_TIMESTAMP: c_int = 24; pub const TCP_NOTSENT_LOWAT: c_int = 25; pub const TCP_CC_INFO: c_int = 26; pub const TCP_SAVE_SYN: c_int = 27; pub const TCP_SAVED_SYN: c_int = 28; cfg_if! { if #[cfg(not(target_os = "emscripten"))] { // NOTE: emscripten doesn't support these options yet. pub const TCP_REPAIR_WINDOW: c_int = 29; pub const TCP_FASTOPEN_CONNECT: c_int = 30; pub const TCP_ULP: c_int = 31; pub const TCP_MD5SIG_EXT: c_int = 32; pub const TCP_FASTOPEN_KEY: c_int = 33; pub const TCP_FASTOPEN_NO_COOKIE: c_int = 34; pub const TCP_ZEROCOPY_RECEIVE: c_int = 35; pub const TCP_INQ: c_int = 36; pub const TCP_CM_INQ: c_int = TCP_INQ; // NOTE: Some CI images doesn't have this option yet. // pub const TCP_TX_DELAY: c_int = 37; pub const TCP_MD5SIG_MAXKEYLEN: usize = 80; } } pub const SO_DEBUG: c_int = 1; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; pub const SS_ONSTACK: c_int = 1; pub const SS_DISABLE: c_int = 2; pub const PATH_MAX: c_int = 4096; pub const UIO_MAXIOV: c_int = 1024; pub const FD_SETSIZE: usize = 1024; pub const EPOLLIN: c_int = 0x1; pub const EPOLLPRI: c_int = 0x2; pub const EPOLLOUT: c_int = 0x4; pub const EPOLLERR: c_int = 0x8; pub const EPOLLHUP: c_int = 0x10; pub const EPOLLRDNORM: c_int = 0x40; pub const EPOLLRDBAND: c_int = 0x80; pub const EPOLLWRNORM: c_int = 0x100; pub const EPOLLWRBAND: c_int = 0x200; pub const EPOLLMSG: c_int = 0x400; pub const EPOLLRDHUP: c_int = 0x2000; pub const EPOLLEXCLUSIVE: c_int = 0x10000000; pub const EPOLLWAKEUP: c_int = 0x20000000; pub const EPOLLONESHOT: c_int = 0x40000000; pub const EPOLLET: c_int = 0x80000000; pub const EPOLL_CTL_ADD: c_int = 1; pub const EPOLL_CTL_MOD: c_int = 3; pub const EPOLL_CTL_DEL: c_int = 2; pub const MNT_FORCE: c_int = 0x1; pub const MNT_DETACH: c_int = 0x2; pub const MNT_EXPIRE: c_int = 0x4; pub const UMOUNT_NOFOLLOW: c_int = 0x8; pub const Q_GETFMT: c_int = 0x800004; pub const Q_GETINFO: c_int = 0x800005; pub const Q_SETINFO: c_int = 0x800006; pub const QIF_BLIMITS: u32 = 1; pub const QIF_SPACE: u32 = 2; pub const QIF_ILIMITS: u32 = 4; pub const QIF_INODES: u32 = 8; pub const QIF_BTIME: u32 = 16; pub const QIF_ITIME: u32 = 32; pub const QIF_LIMITS: u32 = 5; pub const QIF_USAGE: u32 = 10; pub const QIF_TIMES: u32 = 48; pub const QIF_ALL: u32 = 63; pub const Q_SYNC: c_int = 0x800001; pub const Q_QUOTAON: c_int = 0x800002; pub const Q_QUOTAOFF: c_int = 0x800003; pub const Q_GETQUOTA: c_int = 0x800007; pub const Q_SETQUOTA: c_int = 0x800008; pub const TCIOFF: c_int = 2; pub const TCION: c_int = 3; pub const TCOOFF: c_int = 0; pub const TCOON: c_int = 1; pub const TCIFLUSH: c_int = 0; pub const TCOFLUSH: c_int = 1; pub const TCIOFLUSH: c_int = 2; pub const NL0: crate::tcflag_t = 0x00000000; pub const NL1: crate::tcflag_t = 0x00000100; pub const TAB0: crate::tcflag_t = 0x00000000; pub const CR0: crate::tcflag_t = 0x00000000; pub const FF0: crate::tcflag_t = 0x00000000; pub const BS0: crate::tcflag_t = 0x00000000; pub const VT0: crate::tcflag_t = 0x00000000; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VLNEXT: usize = 15; pub const IGNBRK: crate::tcflag_t = 0x00000001; pub const BRKINT: crate::tcflag_t = 0x00000002; pub const IGNPAR: crate::tcflag_t = 0x00000004; pub const PARMRK: crate::tcflag_t = 0x00000008; pub const INPCK: crate::tcflag_t = 0x00000010; pub const ISTRIP: crate::tcflag_t = 0x00000020; pub const INLCR: crate::tcflag_t = 0x00000040; pub const IGNCR: crate::tcflag_t = 0x00000080; pub const ICRNL: crate::tcflag_t = 0x00000100; pub const IXANY: crate::tcflag_t = 0x00000800; pub const IMAXBEL: crate::tcflag_t = 0x00002000; pub const OPOST: crate::tcflag_t = 0x1; pub const CS5: crate::tcflag_t = 0x00000000; pub const CRTSCTS: crate::tcflag_t = 0x80000000; pub const ECHO: crate::tcflag_t = 0x00000008; pub const OCRNL: crate::tcflag_t = 0o000010; pub const ONOCR: crate::tcflag_t = 0o000020; pub const ONLRET: crate::tcflag_t = 0o000040; pub const OFILL: crate::tcflag_t = 0o000100; pub const OFDEL: crate::tcflag_t = 0o000200; pub const CLONE_VM: c_int = 0x100; pub const CLONE_FS: c_int = 0x200; pub const CLONE_FILES: c_int = 0x400; pub const CLONE_SIGHAND: c_int = 0x800; pub const CLONE_PTRACE: c_int = 0x2000; pub const CLONE_VFORK: c_int = 0x4000; pub const CLONE_PARENT: c_int = 0x8000; pub const CLONE_THREAD: c_int = 0x10000; pub const CLONE_NEWNS: c_int = 0x20000; pub const CLONE_SYSVSEM: c_int = 0x40000; pub const CLONE_SETTLS: c_int = 0x80000; pub const CLONE_PARENT_SETTID: c_int = 0x100000; pub const CLONE_CHILD_CLEARTID: c_int = 0x200000; pub const CLONE_DETACHED: c_int = 0x400000; pub const CLONE_UNTRACED: c_int = 0x800000; pub const CLONE_CHILD_SETTID: c_int = 0x01000000; pub const CLONE_NEWCGROUP: c_int = 0x02000000; pub const CLONE_NEWUTS: c_int = 0x04000000; pub const CLONE_NEWIPC: c_int = 0x08000000; pub const CLONE_NEWUSER: c_int = 0x10000000; pub const CLONE_NEWPID: c_int = 0x20000000; pub const CLONE_NEWNET: c_int = 0x40000000; pub const CLONE_IO: c_int = 0x80000000; pub const WNOHANG: c_int = 0x00000001; pub const WUNTRACED: c_int = 0x00000002; pub const WSTOPPED: c_int = WUNTRACED; pub const WEXITED: c_int = 0x00000004; pub const WCONTINUED: c_int = 0x00000008; pub const WNOWAIT: c_int = 0x01000000; // Options for personality(2). pub const ADDR_NO_RANDOMIZE: c_int = 0x0040000; pub const MMAP_PAGE_ZERO: c_int = 0x0100000; pub const ADDR_COMPAT_LAYOUT: c_int = 0x0200000; pub const READ_IMPLIES_EXEC: c_int = 0x0400000; pub const ADDR_LIMIT_32BIT: c_int = 0x0800000; pub const SHORT_INODE: c_int = 0x1000000; pub const WHOLE_SECONDS: c_int = 0x2000000; pub const STICKY_TIMEOUTS: c_int = 0x4000000; pub const ADDR_LIMIT_3GB: c_int = 0x8000000; // Options set using PTRACE_SETOPTIONS. pub const PTRACE_O_TRACESYSGOOD: c_int = 0x00000001; pub const PTRACE_O_TRACEFORK: c_int = 0x00000002; pub const PTRACE_O_TRACEVFORK: c_int = 0x00000004; pub const PTRACE_O_TRACECLONE: c_int = 0x00000008; pub const PTRACE_O_TRACEEXEC: c_int = 0x00000010; pub const PTRACE_O_TRACEVFORKDONE: c_int = 0x00000020; pub const PTRACE_O_TRACEEXIT: c_int = 0x00000040; pub const PTRACE_O_TRACESECCOMP: c_int = 0x00000080; pub const PTRACE_O_SUSPEND_SECCOMP: c_int = 0x00200000; pub const PTRACE_O_EXITKILL: c_int = 0x00100000; pub const PTRACE_O_MASK: c_int = 0x003000ff; // Wait extended result codes for the above trace options. pub const PTRACE_EVENT_FORK: c_int = 1; pub const PTRACE_EVENT_VFORK: c_int = 2; pub const PTRACE_EVENT_CLONE: c_int = 3; pub const PTRACE_EVENT_EXEC: c_int = 4; pub const PTRACE_EVENT_VFORK_DONE: c_int = 5; pub const PTRACE_EVENT_EXIT: c_int = 6; pub const PTRACE_EVENT_SECCOMP: c_int = 7; pub const __WNOTHREAD: c_int = 0x20000000; pub const __WALL: c_int = 0x40000000; pub const __WCLONE: c_int = 0x80000000; pub const SPLICE_F_MOVE: c_uint = 0x01; pub const SPLICE_F_NONBLOCK: c_uint = 0x02; pub const SPLICE_F_MORE: c_uint = 0x04; pub const SPLICE_F_GIFT: c_uint = 0x08; pub const RTLD_LOCAL: c_int = 0; pub const RTLD_LAZY: c_int = 1; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_RANDOM: c_int = 1; pub const POSIX_FADV_SEQUENTIAL: c_int = 2; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const AT_FDCWD: c_int = -100; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x100; pub const AT_REMOVEDIR: c_int = 0x200; pub const AT_SYMLINK_FOLLOW: c_int = 0x400; pub const AT_NO_AUTOMOUNT: c_int = 0x800; pub const AT_EMPTY_PATH: c_int = 0x1000; pub const AT_RECURSIVE: c_int = 0x8000; pub const LOG_CRON: c_int = 9 << 3; pub const LOG_AUTHPRIV: c_int = 10 << 3; pub const LOG_FTP: c_int = 11 << 3; pub const LOG_PERROR: c_int = 0x20; pub const PIPE_BUF: usize = 4096; pub const SI_LOAD_SHIFT: c_uint = 16; // si_code values pub const SI_USER: c_int = 0; pub const SI_KERNEL: c_int = 0x80; pub const SI_QUEUE: c_int = -1; cfg_if! { if #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] { pub const SI_TIMER: c_int = -2; pub const SI_MESGQ: c_int = -3; pub const SI_ASYNCIO: c_int = -4; } else { pub const SI_TIMER: c_int = -3; pub const SI_MESGQ: c_int = -4; pub const SI_ASYNCIO: c_int = -2; } } pub const SI_SIGIO: c_int = -5; pub const SI_TKILL: c_int = -6; pub const SI_ASYNCNL: c_int = -60; // si_code values for SIGBUS signal pub const BUS_ADRALN: c_int = 1; pub const BUS_ADRERR: c_int = 2; pub const BUS_OBJERR: c_int = 3; // Linux-specific si_code values for SIGBUS signal pub const BUS_MCEERR_AR: c_int = 4; pub const BUS_MCEERR_AO: c_int = 5; // si_code values for SIGTRAP pub const TRAP_BRKPT: c_int = 1; pub const TRAP_TRACE: c_int = 2; pub const TRAP_BRANCH: c_int = 3; pub const TRAP_HWBKPT: c_int = 4; pub const TRAP_UNK: c_int = 5; // si_code values for SIGCHLD signal pub const CLD_EXITED: c_int = 1; pub const CLD_KILLED: c_int = 2; pub const CLD_DUMPED: c_int = 3; pub const CLD_TRAPPED: c_int = 4; pub const CLD_STOPPED: c_int = 5; pub const CLD_CONTINUED: c_int = 6; pub const SIGEV_SIGNAL: c_int = 0; pub const SIGEV_NONE: c_int = 1; pub const SIGEV_THREAD: c_int = 2; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; cfg_if! { if #[cfg(not(target_os = "emscripten"))] { pub const P_PIDFD: idtype_t = 3; } } pub const UTIME_OMIT: c_long = 1073741822; pub const UTIME_NOW: c_long = 1073741823; pub const POLLIN: c_short = 0x1; pub const POLLPRI: c_short = 0x2; pub const POLLOUT: c_short = 0x4; pub const POLLERR: c_short = 0x8; pub const POLLHUP: c_short = 0x10; pub const POLLNVAL: c_short = 0x20; pub const POLLRDNORM: c_short = 0x040; pub const POLLRDBAND: c_short = 0x080; #[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] pub const POLLRDHUP: c_short = 0x2000; #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] pub const POLLRDHUP: c_short = 0x800; pub const IPTOS_LOWDELAY: u8 = 0x10; pub const IPTOS_THROUGHPUT: u8 = 0x08; pub const IPTOS_RELIABILITY: u8 = 0x04; pub const IPTOS_MINCOST: u8 = 0x02; pub const IPTOS_PREC_NETCONTROL: u8 = 0xe0; pub const IPTOS_PREC_INTERNETCONTROL: u8 = 0xc0; pub const IPTOS_PREC_CRITIC_ECP: u8 = 0xa0; pub const IPTOS_PREC_FLASHOVERRIDE: u8 = 0x80; pub const IPTOS_PREC_FLASH: u8 = 0x60; pub const IPTOS_PREC_IMMEDIATE: u8 = 0x40; pub const IPTOS_PREC_PRIORITY: u8 = 0x20; pub const IPTOS_PREC_ROUTINE: u8 = 0x00; pub const IPTOS_ECN_MASK: u8 = 0x03; pub const IPTOS_ECN_ECT1: u8 = 0x01; pub const IPTOS_ECN_ECT0: u8 = 0x02; pub const IPTOS_ECN_CE: u8 = 0x03; pub const IPOPT_COPY: u8 = 0x80; pub const IPOPT_CLASS_MASK: u8 = 0x60; pub const IPOPT_NUMBER_MASK: u8 = 0x1f; pub const IPOPT_CONTROL: u8 = 0x00; pub const IPOPT_RESERVED1: u8 = 0x20; pub const IPOPT_MEASUREMENT: u8 = 0x40; pub const IPOPT_RESERVED2: u8 = 0x60; pub const IPOPT_END: u8 = 0 | IPOPT_CONTROL; pub const IPOPT_NOOP: u8 = 1 | IPOPT_CONTROL; pub const IPOPT_SEC: u8 = 2 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_LSRR: u8 = 3 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_TIMESTAMP: u8 = 4 | IPOPT_MEASUREMENT; pub const IPOPT_RR: u8 = 7 | IPOPT_CONTROL; pub const IPOPT_SID: u8 = 8 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_SSRR: u8 = 9 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_RA: u8 = 20 | IPOPT_CONTROL | IPOPT_COPY; pub const IPVERSION: u8 = 4; pub const MAXTTL: u8 = 255; pub const IPDEFTTL: u8 = 64; pub const IPOPT_OPTVAL: u8 = 0; pub const IPOPT_OLEN: u8 = 1; pub const IPOPT_OFFSET: u8 = 2; pub const IPOPT_MINOFF: u8 = 4; pub const MAX_IPOPTLEN: u8 = 40; pub const IPOPT_NOP: u8 = IPOPT_NOOP; pub const IPOPT_EOL: u8 = IPOPT_END; pub const IPOPT_TS: u8 = IPOPT_TIMESTAMP; pub const IPOPT_TS_TSONLY: u8 = 0; pub const IPOPT_TS_TSANDADDR: u8 = 1; pub const IPOPT_TS_PRESPEC: u8 = 3; pub const ARPOP_RREQUEST: u16 = 3; pub const ARPOP_RREPLY: u16 = 4; pub const ARPOP_InREQUEST: u16 = 8; pub const ARPOP_InREPLY: u16 = 9; pub const ARPOP_NAK: u16 = 10; pub const ATF_NETMASK: c_int = 0x20; pub const ATF_DONTPUB: c_int = 0x40; pub const ARPHRD_NETROM: u16 = 0; pub const ARPHRD_ETHER: u16 = 1; pub const ARPHRD_EETHER: u16 = 2; pub const ARPHRD_AX25: u16 = 3; pub const ARPHRD_PRONET: u16 = 4; pub const ARPHRD_CHAOS: u16 = 5; pub const ARPHRD_IEEE802: u16 = 6; pub const ARPHRD_ARCNET: u16 = 7; pub const ARPHRD_APPLETLK: u16 = 8; pub const ARPHRD_DLCI: u16 = 15; pub const ARPHRD_ATM: u16 = 19; pub const ARPHRD_METRICOM: u16 = 23; pub const ARPHRD_IEEE1394: u16 = 24; pub const ARPHRD_EUI64: u16 = 27; pub const ARPHRD_INFINIBAND: u16 = 32; pub const ARPHRD_SLIP: u16 = 256; pub const ARPHRD_CSLIP: u16 = 257; pub const ARPHRD_SLIP6: u16 = 258; pub const ARPHRD_CSLIP6: u16 = 259; pub const ARPHRD_RSRVD: u16 = 260; pub const ARPHRD_ADAPT: u16 = 264; pub const ARPHRD_ROSE: u16 = 270; pub const ARPHRD_X25: u16 = 271; pub const ARPHRD_HWX25: u16 = 272; pub const ARPHRD_CAN: u16 = 280; pub const ARPHRD_PPP: u16 = 512; pub const ARPHRD_CISCO: u16 = 513; pub const ARPHRD_HDLC: u16 = ARPHRD_CISCO; pub const ARPHRD_LAPB: u16 = 516; pub const ARPHRD_DDCMP: u16 = 517; pub const ARPHRD_RAWHDLC: u16 = 518; pub const ARPHRD_TUNNEL: u16 = 768; pub const ARPHRD_TUNNEL6: u16 = 769; pub const ARPHRD_FRAD: u16 = 770; pub const ARPHRD_SKIP: u16 = 771; pub const ARPHRD_LOOPBACK: u16 = 772; pub const ARPHRD_LOCALTLK: u16 = 773; pub const ARPHRD_FDDI: u16 = 774; pub const ARPHRD_BIF: u16 = 775; pub const ARPHRD_SIT: u16 = 776; pub const ARPHRD_IPDDP: u16 = 777; pub const ARPHRD_IPGRE: u16 = 778; pub const ARPHRD_PIMREG: u16 = 779; pub const ARPHRD_HIPPI: u16 = 780; pub const ARPHRD_ASH: u16 = 781; pub const ARPHRD_ECONET: u16 = 782; pub const ARPHRD_IRDA: u16 = 783; pub const ARPHRD_FCPP: u16 = 784; pub const ARPHRD_FCAL: u16 = 785; pub const ARPHRD_FCPL: u16 = 786; pub const ARPHRD_FCFABRIC: u16 = 787; pub const ARPHRD_IEEE802_TR: u16 = 800; pub const ARPHRD_IEEE80211: u16 = 801; pub const ARPHRD_IEEE80211_PRISM: u16 = 802; pub const ARPHRD_IEEE80211_RADIOTAP: u16 = 803; pub const ARPHRD_IEEE802154: u16 = 804; pub const ARPHRD_VOID: u16 = 0xFFFF; pub const ARPHRD_NONE: u16 = 0xFFFE; cfg_if! { if #[cfg(target_os = "emscripten")] { // Emscripten does not define any `*_SUPER_MAGIC` constants. } else if #[cfg(not(target_arch = "s390x"))] { pub const ADFS_SUPER_MAGIC: c_long = 0x0000adf5; pub const AFFS_SUPER_MAGIC: c_long = 0x0000adff; pub const AFS_SUPER_MAGIC: c_long = 0x5346414f; pub const AUTOFS_SUPER_MAGIC: c_long = 0x0187; pub const BPF_FS_MAGIC: c_long = 0xcafe4a11; pub const BTRFS_SUPER_MAGIC: c_long = 0x9123683e; pub const CGROUP2_SUPER_MAGIC: c_long = 0x63677270; pub const CGROUP_SUPER_MAGIC: c_long = 0x27e0eb; pub const CODA_SUPER_MAGIC: c_long = 0x73757245; pub const CRAMFS_MAGIC: c_long = 0x28cd3d45; pub const DEBUGFS_MAGIC: c_long = 0x64626720; pub const DEVPTS_SUPER_MAGIC: c_long = 0x1cd1; pub const ECRYPTFS_SUPER_MAGIC: c_long = 0xf15f; pub const EFS_SUPER_MAGIC: c_long = 0x00414a53; pub const EXT2_SUPER_MAGIC: c_long = 0x0000ef53; pub const EXT3_SUPER_MAGIC: c_long = 0x0000ef53; pub const EXT4_SUPER_MAGIC: c_long = 0x0000ef53; pub const F2FS_SUPER_MAGIC: c_long = 0xf2f52010; pub const FUSE_SUPER_MAGIC: c_long = 0x65735546; pub const FUTEXFS_SUPER_MAGIC: c_long = 0xbad1dea; pub const HOSTFS_SUPER_MAGIC: c_long = 0x00c0ffee; pub const HPFS_SUPER_MAGIC: c_long = 0xf995e849; pub const HUGETLBFS_MAGIC: c_long = 0x958458f6; pub const ISOFS_SUPER_MAGIC: c_long = 0x00009660; pub const JFFS2_SUPER_MAGIC: c_long = 0x000072b6; pub const MINIX2_SUPER_MAGIC2: c_long = 0x00002478; pub const MINIX2_SUPER_MAGIC: c_long = 0x00002468; pub const MINIX3_SUPER_MAGIC: c_long = 0x4d5a; pub const MINIX_SUPER_MAGIC2: c_long = 0x0000138f; pub const MINIX_SUPER_MAGIC: c_long = 0x0000137f; pub const MSDOS_SUPER_MAGIC: c_long = 0x00004d44; pub const NCP_SUPER_MAGIC: c_long = 0x0000564c; pub const NFS_SUPER_MAGIC: c_long = 0x00006969; pub const NILFS_SUPER_MAGIC: c_long = 0x3434; pub const OCFS2_SUPER_MAGIC: c_long = 0x7461636f; pub const OPENPROM_SUPER_MAGIC: c_long = 0x00009fa1; pub const OVERLAYFS_SUPER_MAGIC: c_long = 0x794c7630; pub const PROC_SUPER_MAGIC: c_long = 0x00009fa0; pub const QNX4_SUPER_MAGIC: c_long = 0x0000002f; pub const QNX6_SUPER_MAGIC: c_long = 0x68191122; pub const RDTGROUP_SUPER_MAGIC: c_long = 0x7655821; pub const REISERFS_SUPER_MAGIC: c_long = 0x52654973; pub const SECURITYFS_MAGIC: c_long = 0x73636673; pub const SELINUX_MAGIC: c_long = 0xf97cff8c; pub const SMACK_MAGIC: c_long = 0x43415d53; pub const SMB_SUPER_MAGIC: c_long = 0x0000517b; pub const SYSFS_MAGIC: c_long = 0x62656572; pub const TMPFS_MAGIC: c_long = 0x01021994; pub const TRACEFS_MAGIC: c_long = 0x74726163; pub const UDF_SUPER_MAGIC: c_long = 0x15013346; pub const USBDEVICE_SUPER_MAGIC: c_long = 0x00009fa2; pub const XENFS_SUPER_MAGIC: c_long = 0xabba1974; pub const NSFS_MAGIC: c_long = 0x6e736673; } else if #[cfg(target_arch = "s390x")] { pub const ADFS_SUPER_MAGIC: c_uint = 0x0000adf5; pub const AFFS_SUPER_MAGIC: c_uint = 0x0000adff; pub const AFS_SUPER_MAGIC: c_uint = 0x5346414f; pub const AUTOFS_SUPER_MAGIC: c_uint = 0x0187; pub const BPF_FS_MAGIC: c_uint = 0xcafe4a11; pub const BTRFS_SUPER_MAGIC: c_uint = 0x9123683e; pub const CGROUP2_SUPER_MAGIC: c_uint = 0x63677270; pub const CGROUP_SUPER_MAGIC: c_uint = 0x27e0eb; pub const CODA_SUPER_MAGIC: c_uint = 0x73757245; pub const CRAMFS_MAGIC: c_uint = 0x28cd3d45; pub const DEBUGFS_MAGIC: c_uint = 0x64626720; pub const DEVPTS_SUPER_MAGIC: c_uint = 0x1cd1; pub const ECRYPTFS_SUPER_MAGIC: c_uint = 0xf15f; pub const EFS_SUPER_MAGIC: c_uint = 0x00414a53; pub const EXT2_SUPER_MAGIC: c_uint = 0x0000ef53; pub const EXT3_SUPER_MAGIC: c_uint = 0x0000ef53; pub const EXT4_SUPER_MAGIC: c_uint = 0x0000ef53; pub const F2FS_SUPER_MAGIC: c_uint = 0xf2f52010; pub const FUSE_SUPER_MAGIC: c_uint = 0x65735546; pub const FUTEXFS_SUPER_MAGIC: c_uint = 0xbad1dea; pub const HOSTFS_SUPER_MAGIC: c_uint = 0x00c0ffee; pub const HPFS_SUPER_MAGIC: c_uint = 0xf995e849; pub const HUGETLBFS_MAGIC: c_uint = 0x958458f6; pub const ISOFS_SUPER_MAGIC: c_uint = 0x00009660; pub const JFFS2_SUPER_MAGIC: c_uint = 0x000072b6; pub const MINIX2_SUPER_MAGIC2: c_uint = 0x00002478; pub const MINIX2_SUPER_MAGIC: c_uint = 0x00002468; pub const MINIX3_SUPER_MAGIC: c_uint = 0x4d5a; pub const MINIX_SUPER_MAGIC2: c_uint = 0x0000138f; pub const MINIX_SUPER_MAGIC: c_uint = 0x0000137f; pub const MSDOS_SUPER_MAGIC: c_uint = 0x00004d44; pub const NCP_SUPER_MAGIC: c_uint = 0x0000564c; pub const NFS_SUPER_MAGIC: c_uint = 0x00006969; pub const NILFS_SUPER_MAGIC: c_uint = 0x3434; pub const OCFS2_SUPER_MAGIC: c_uint = 0x7461636f; pub const OPENPROM_SUPER_MAGIC: c_uint = 0x00009fa1; pub const OVERLAYFS_SUPER_MAGIC: c_uint = 0x794c7630; pub const PROC_SUPER_MAGIC: c_uint = 0x00009fa0; pub const QNX4_SUPER_MAGIC: c_uint = 0x0000002f; pub const QNX6_SUPER_MAGIC: c_uint = 0x68191122; pub const RDTGROUP_SUPER_MAGIC: c_uint = 0x7655821; pub const REISERFS_SUPER_MAGIC: c_uint = 0x52654973; pub const SECURITYFS_MAGIC: c_uint = 0x73636673; pub const SELINUX_MAGIC: c_uint = 0xf97cff8c; pub const SMACK_MAGIC: c_uint = 0x43415d53; pub const SMB_SUPER_MAGIC: c_uint = 0x0000517b; pub const SYSFS_MAGIC: c_uint = 0x62656572; pub const TMPFS_MAGIC: c_uint = 0x01021994; pub const TRACEFS_MAGIC: c_uint = 0x74726163; pub const UDF_SUPER_MAGIC: c_uint = 0x15013346; pub const USBDEVICE_SUPER_MAGIC: c_uint = 0x00009fa2; pub const XENFS_SUPER_MAGIC: c_uint = 0xabba1974; pub const NSFS_MAGIC: c_uint = 0x6e736673; } } cfg_if! { if #[cfg(any(target_env = "gnu", target_os = "android"))] { pub const AT_STATX_SYNC_TYPE: c_int = 0x6000; pub const AT_STATX_SYNC_AS_STAT: c_int = 0x0000; pub const AT_STATX_FORCE_SYNC: c_int = 0x2000; pub const AT_STATX_DONT_SYNC: c_int = 0x4000; pub const STATX_TYPE: c_uint = 0x0001; pub const STATX_MODE: c_uint = 0x0002; pub const STATX_NLINK: c_uint = 0x0004; pub const STATX_UID: c_uint = 0x0008; pub const STATX_GID: c_uint = 0x0010; pub const STATX_ATIME: c_uint = 0x0020; pub const STATX_MTIME: c_uint = 0x0040; pub const STATX_CTIME: c_uint = 0x0080; pub const STATX_INO: c_uint = 0x0100; pub const STATX_SIZE: c_uint = 0x0200; pub const STATX_BLOCKS: c_uint = 0x0400; pub const STATX_BASIC_STATS: c_uint = 0x07ff; pub const STATX_BTIME: c_uint = 0x0800; pub const STATX_ALL: c_uint = 0x0fff; pub const STATX_MNT_ID: c_uint = 0x1000; pub const STATX_DIOALIGN: c_uint = 0x2000; pub const STATX__RESERVED: c_int = 0x80000000; pub const STATX_ATTR_COMPRESSED: c_int = 0x0004; pub const STATX_ATTR_IMMUTABLE: c_int = 0x0010; pub const STATX_ATTR_APPEND: c_int = 0x0020; pub const STATX_ATTR_NODUMP: c_int = 0x0040; pub const STATX_ATTR_ENCRYPTED: c_int = 0x0800; pub const STATX_ATTR_AUTOMOUNT: c_int = 0x1000; pub const STATX_ATTR_MOUNT_ROOT: c_int = 0x2000; pub const STATX_ATTR_VERITY: c_int = 0x100000; pub const STATX_ATTR_DAX: c_int = 0x200000; } } // https://github.com/search?q=repo%3Atorvalds%2Flinux+%22%23define+_IOC_NONE%22&type=code cfg_if! { if #[cfg(any( target_os = "linux", target_os = "android", target_os = "l4re" ))] { const _IOC_NRBITS: u32 = 8; const _IOC_TYPEBITS: u32 = 8; cfg_if! { if #[cfg(any( any(target_arch = "powerpc", target_arch = "powerpc64"), any(target_arch = "sparc", target_arch = "sparc64"), any(target_arch = "mips", target_arch = "mips64"), ))] { // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/powerpc/include/uapi/asm/ioctl.h // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/sparc/include/uapi/asm/ioctl.h // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/arch/mips/include/uapi/asm/ioctl.h const _IOC_SIZEBITS: u32 = 13; const _IOC_DIRBITS: u32 = 3; const _IOC_NONE: u32 = 1; const _IOC_READ: u32 = 2; const _IOC_WRITE: u32 = 4; } else { // https://github.com/torvalds/linux/blob/b311c1b497e51a628aa89e7cb954481e5f9dced2/include/uapi/asm-generic/ioctl.h const _IOC_SIZEBITS: u32 = 14; const _IOC_DIRBITS: u32 = 2; const _IOC_NONE: u32 = 0; const _IOC_WRITE: u32 = 1; const _IOC_READ: u32 = 2; } } const _IOC_NRMASK: u32 = (1 << _IOC_NRBITS) - 1; const _IOC_TYPEMASK: u32 = (1 << _IOC_TYPEBITS) - 1; const _IOC_SIZEMASK: u32 = (1 << _IOC_SIZEBITS) - 1; const _IOC_DIRMASK: u32 = (1 << _IOC_DIRBITS) - 1; const _IOC_NRSHIFT: u32 = 0; const _IOC_TYPESHIFT: u32 = _IOC_NRSHIFT + _IOC_NRBITS; const _IOC_SIZESHIFT: u32 = _IOC_TYPESHIFT + _IOC_TYPEBITS; const _IOC_DIRSHIFT: u32 = _IOC_SIZESHIFT + _IOC_SIZEBITS; // adapted from https://github.com/torvalds/linux/blob/8a696a29c6905594e4abf78eaafcb62165ac61f1/rust/kernel/ioctl.rs /// Build an ioctl number, analogous to the C macro of the same name. const fn _IOC(dir: u32, ty: u32, nr: u32, size: usize) -> u32 { // FIXME(ctest) the `garando_syntax` crate (used by ctest in the CI test suite) // cannot currently parse these `debug_assert!`s // // debug_assert!(dir <= _IOC_DIRMASK); // debug_assert!(ty <= _IOC_TYPEMASK); // debug_assert!(nr <= _IOC_NRMASK); // debug_assert!(size <= (_IOC_SIZEMASK as usize)); (dir << _IOC_DIRSHIFT) | (ty << _IOC_TYPESHIFT) | (nr << _IOC_NRSHIFT) | ((size as u32) << _IOC_SIZESHIFT) } } } const_fn! { {const} fn CMSG_ALIGN(len: usize) -> usize { len + mem::size_of::() - 1 & !(mem::size_of::() - 1) } } f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { cmsg.offset(1) as *mut c_uchar } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(mem::size_of::())) as c_uint } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { CMSG_ALIGN(mem::size_of::()) as c_uint + length } pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub fn SIGRTMAX() -> c_int { unsafe { __libc_current_sigrtmax() } } pub fn SIGRTMIN() -> c_int { unsafe { __libc_current_sigrtmin() } } pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0x7f } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: c_int) -> bool { (status & 0x80) != 0 } pub {const} fn W_EXITCODE(ret: c_int, sig: c_int) -> c_int { (ret << 8) | sig } pub {const} fn W_STOPCODE(sig: c_int) -> c_int { (sig << 8) | 0x7f } pub {const} fn QCMD(cmd: c_int, type_: c_int) -> c_int { (cmd << 8) | (type_ & 0x00ff) } pub {const} fn IPOPT_COPIED(o: u8) -> u8 { o & IPOPT_COPY } pub {const} fn IPOPT_CLASS(o: u8) -> u8 { o & IPOPT_CLASS_MASK } pub {const} fn IPOPT_NUMBER(o: u8) -> u8 { o & IPOPT_NUMBER_MASK } pub {const} fn IPTOS_ECN(x: u8) -> u8 { x & crate::IPTOS_ECN_MASK } #[allow(ellipsis_inclusive_range_patterns)] pub {const} fn KERNEL_VERSION(a: u32, b: u32, c: u32) -> u32 { ((a << 16) + (b << 8)) + if c > 255 { 255 } else { c } } } extern "C" { #[doc(hidden)] pub fn __libc_current_sigrtmax() -> c_int; #[doc(hidden)] pub fn __libc_current_sigrtmin() -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar) -> c_int; pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_settime(clk_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn clock_getcpuclockid(pid: crate::pid_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn pthread_getattr_np(native: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_attr_setstack( attr: *mut crate::pthread_attr_t, stackaddr: *mut c_void, stacksize: size_t, ) -> c_int; pub fn memalign(align: size_t, size: size_t) -> *mut c_void; pub fn setgroups(ngroups: size_t, ptr: *const crate::gid_t) -> c_int; pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "statfs64")] pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "fstatfs64")] pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; #[cfg_attr(gnu_file_offset_bits64, link_name = "posix_fadvise64")] pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; pub fn freelocale(loc: crate::locale_t); pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: c_int) -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: c_int) -> c_int; pub fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn clearenv() -> c_int; pub fn waitid( idtype: idtype_t, id: id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn getresuid( ruid: *mut crate::uid_t, euid: *mut crate::uid_t, suid: *mut crate::uid_t, ) -> c_int; pub fn getresgid( rgid: *mut crate::gid_t, egid: *mut crate::gid_t, sgid: *mut crate::gid_t, ) -> c_int; pub fn acct(filename: *const c_char) -> c_int; pub fn brk(addr: *mut c_void) -> c_int; pub fn sbrk(increment: intptr_t) -> *mut c_void; #[deprecated( since = "0.2.66", note = "causes memory corruption, see rust-lang/libc#1596" )] pub fn vfork() -> crate::pid_t; pub fn setresgid(rgid: crate::gid_t, egid: crate::gid_t, sgid: crate::gid_t) -> c_int; pub fn setresuid(ruid: crate::uid_t, euid: crate::uid_t, suid: crate::uid_t) -> c_int; pub fn wait4( pid: crate::pid_t, status: *mut c_int, options: c_int, rusage: *mut crate::rusage, ) -> crate::pid_t; pub fn login_tty(fd: c_int) -> c_int; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn execvpe( file: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; pub fn fexecve(fd: c_int, argv: *const *const c_char, envp: *const *const c_char) -> c_int; pub fn getifaddrs(ifap: *mut *mut crate::ifaddrs) -> c_int; pub fn freeifaddrs(ifa: *mut crate::ifaddrs); pub fn bind( socket: c_int, address: *const crate::sockaddr, address_len: crate::socklen_t, ) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn sendmsg(fd: c_int, msg: *const crate::msghdr, flags: c_int) -> ssize_t; pub fn recvmsg(fd: c_int, msg: *mut crate::msghdr, flags: c_int) -> ssize_t; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char; pub fn strftime( s: *mut c_char, max: size_t, format: *const c_char, tm: *const crate::tm, ) -> size_t; pub fn strftime_l( s: *mut c_char, max: size_t, format: *const c_char, tm: *const crate::tm, locale: crate::locale_t, ) -> size_t; pub fn strptime(s: *const c_char, format: *const c_char, tm: *mut crate::tm) -> *mut c_char; #[cfg_attr(gnu_file_offset_bits64, link_name = "mkostemp64")] pub fn mkostemp(template: *mut c_char, flags: c_int) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "mkostemps64")] pub fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int; pub fn getdomainname(name: *mut c_char, len: size_t) -> c_int; pub fn setdomainname(name: *const c_char, len: size_t) -> c_int; } // LFS64 extensions // // * musl and Emscripten has 64-bit versions only so aliases the LFS64 symbols to the standard ones // * ulibc doesn't have preadv64/pwritev64 cfg_if! { if #[cfg(not(any(target_env = "musl", target_os = "emscripten")))] { extern "C" { pub fn fstatfs64(fd: c_int, buf: *mut statfs64) -> c_int; pub fn statvfs64(path: *const c_char, buf: *mut statvfs64) -> c_int; pub fn fstatvfs64(fd: c_int, buf: *mut statvfs64) -> c_int; pub fn statfs64(path: *const c_char, buf: *mut statfs64) -> c_int; pub fn creat64(path: *const c_char, mode: mode_t) -> c_int; pub fn fstat64(fildes: c_int, buf: *mut stat64) -> c_int; pub fn fstatat64( dirfd: c_int, pathname: *const c_char, buf: *mut stat64, flags: c_int, ) -> c_int; pub fn ftruncate64(fd: c_int, length: off64_t) -> c_int; pub fn lseek64(fd: c_int, offset: off64_t, whence: c_int) -> off64_t; pub fn lstat64(path: *const c_char, buf: *mut stat64) -> c_int; pub fn mmap64( addr: *mut c_void, len: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off64_t, ) -> *mut c_void; pub fn open64(path: *const c_char, oflag: c_int, ...) -> c_int; pub fn openat64(fd: c_int, path: *const c_char, oflag: c_int, ...) -> c_int; pub fn posix_fadvise64( fd: c_int, offset: off64_t, len: off64_t, advise: c_int, ) -> c_int; pub fn pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: off64_t) -> ssize_t; pub fn pwrite64( fd: c_int, buf: *const c_void, count: size_t, offset: off64_t, ) -> ssize_t; pub fn readdir64(dirp: *mut crate::DIR) -> *mut crate::dirent64; pub fn readdir64_r( dirp: *mut crate::DIR, entry: *mut crate::dirent64, result: *mut *mut crate::dirent64, ) -> c_int; pub fn stat64(path: *const c_char, buf: *mut stat64) -> c_int; pub fn truncate64(path: *const c_char, length: off64_t) -> c_int; } } } cfg_if! { if #[cfg(not(any( target_env = "uclibc", target_env = "musl", target_os = "emscripten" )))] { extern "C" { pub fn preadv64( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, ) -> ssize_t; pub fn pwritev64( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, ) -> ssize_t; } } } cfg_if! { if #[cfg(not(target_env = "uclibc"))] { extern "C" { // uclibc has separate non-const version of this function pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *const termios, winp: *const crate::winsize, ) -> crate::pid_t; // uclibc has separate non-const version of this function pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *const termios, winp: *const crate::winsize, ) -> c_int; } } } // The statx syscall, available on some libcs. cfg_if! { if #[cfg(any(target_env = "gnu", target_os = "android"))] { extern "C" { pub fn statx( dirfd: c_int, pathname: *const c_char, flags: c_int, mask: c_uint, statxbuf: *mut statx, ) -> c_int; } } } cfg_if! { if #[cfg(target_os = "emscripten")] { mod emscripten; pub use self::emscripten::*; } else if #[cfg(target_os = "linux")] { mod linux; pub use self::linux::*; } else if #[cfg(target_os = "l4re")] { mod linux; pub use self::linux::*; } else if #[cfg(target_os = "android")] { mod android; pub use self::android::*; } else { // Unknown target_os } } libc/src/unix/linux_like/android/0000775000175000017500000000000015105742312016652 5ustar bdrungbdrunglibc/src/unix/linux_like/android/mod.rs0000644000175000017500000044405315105742312020007 0ustar bdrungbdrung//! Android-specific definitions for linux-like values use crate::prelude::*; pub type clock_t = c_long; pub type time_t = c_long; pub type suseconds_t = c_long; pub type off_t = c_long; pub type blkcnt_t = c_ulong; pub type blksize_t = c_ulong; pub type nlink_t = u32; pub type useconds_t = u32; pub type pthread_t = c_long; pub type pthread_mutexattr_t = c_long; pub type pthread_rwlockattr_t = c_long; pub type pthread_barrierattr_t = c_int; pub type pthread_condattr_t = c_long; pub type pthread_key_t = c_int; pub type fsfilcnt_t = c_ulong; pub type fsblkcnt_t = c_ulong; pub type nfds_t = c_uint; pub type rlim_t = c_ulong; pub type dev_t = c_ulong; pub type ino_t = c_ulong; pub type ino64_t = u64; pub type __CPU_BITTYPE = c_ulong; pub type idtype_t = c_int; pub type loff_t = c_longlong; pub type __kernel_loff_t = c_longlong; pub type __kernel_pid_t = c_int; pub type __u8 = c_uchar; pub type __u16 = c_ushort; pub type __s16 = c_short; pub type __u32 = c_uint; pub type __s32 = c_int; // linux/elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Off = u32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Off = u64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; pub type eventfd_t = u64; // these structs sit behind a heap allocation on Android pub type posix_spawn_file_actions_t = *mut c_void; pub type posix_spawnattr_t = *mut c_void; s! { pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct __fsid_t { __val: [c_int; 2], } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: size_t, pub msg_control: *mut c_void, pub msg_controllen: size_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: size_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], } pub struct termios2 { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; 19], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } pub struct mallinfo { pub arena: size_t, pub ordblks: size_t, pub smblks: size_t, pub hblks: size_t, pub hblkhd: size_t, pub usmblks: size_t, pub fsmblks: size_t, pub uordblks: size_t, pub fordblks: size_t, pub keepcost: size_t, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: crate::__kernel_loff_t, pub l_len: crate::__kernel_loff_t, pub l_pid: crate::__kernel_pid_t, } pub struct cpu_set_t { #[cfg(target_pointer_width = "64")] __bits: [__CPU_BITTYPE; 16], #[cfg(target_pointer_width = "32")] __bits: [__CPU_BITTYPE; 1], } pub struct sem_t { count: c_uint, #[cfg(target_pointer_width = "64")] __reserved: [c_int; 3], } pub struct exit_status { pub e_termination: c_short, pub e_exit: c_short, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, #[cfg(target_pointer_width = "64")] __f_reserved: [u32; 6], } pub struct signalfd_siginfo { pub ssi_signo: u32, pub ssi_errno: i32, pub ssi_code: i32, pub ssi_pid: u32, pub ssi_uid: u32, pub ssi_fd: i32, pub ssi_tid: u32, pub ssi_band: u32, pub ssi_overrun: u32, pub ssi_trapno: u32, pub ssi_status: i32, pub ssi_int: i32, pub ssi_ptr: c_ulonglong, pub ssi_utime: c_ulonglong, pub ssi_stime: c_ulonglong, pub ssi_addr: c_ulonglong, pub ssi_addr_lsb: u16, _pad2: u16, pub ssi_syscall: i32, pub ssi_call_addr: u64, pub ssi_arch: u32, _pad: [u8; 28], } pub struct itimerspec { pub it_interval: crate::timespec, pub it_value: crate::timespec, } pub struct ucred { pub pid: crate::pid_t, pub uid: crate::uid_t, pub gid: crate::gid_t, } pub struct genlmsghdr { pub cmd: u8, pub version: u8, pub reserved: u16, } pub struct nlmsghdr { pub nlmsg_len: u32, pub nlmsg_type: u16, pub nlmsg_flags: u16, pub nlmsg_seq: u32, pub nlmsg_pid: u32, } pub struct nlmsgerr { pub error: c_int, pub msg: nlmsghdr, } pub struct nl_pktinfo { pub group: u32, } pub struct nl_mmap_req { pub nm_block_size: c_uint, pub nm_block_nr: c_uint, pub nm_frame_size: c_uint, pub nm_frame_nr: c_uint, } pub struct nl_mmap_hdr { pub nm_status: c_uint, pub nm_len: c_uint, pub nm_group: u32, pub nm_pid: u32, pub nm_uid: u32, pub nm_gid: u32, } pub struct nlattr { pub nla_len: u16, pub nla_type: u16, } pub struct in6_pktinfo { pub ipi6_addr: crate::in6_addr, pub ipi6_ifindex: c_int, } pub struct inotify_event { pub wd: c_int, pub mask: u32, pub cookie: u32, pub len: u32, } pub struct sock_extended_err { pub ee_errno: u32, pub ee_origin: u8, pub ee_type: u8, pub ee_code: u8, pub ee_pad: u8, pub ee_info: u32, pub ee_data: u32, } pub struct regex_t { re_magic: c_int, re_nsub: size_t, re_endp: *const c_char, re_guts: *mut c_void, } pub struct regmatch_t { pub rm_so: ssize_t, pub rm_eo: ssize_t, } pub struct sockaddr_vm { pub svm_family: crate::sa_family_t, pub svm_reserved1: c_ushort, pub svm_port: c_uint, pub svm_cid: c_uint, pub svm_zero: [u8; 4], } // linux/elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } // link.h pub struct dl_phdr_info { #[cfg(target_pointer_width = "64")] pub dlpi_addr: Elf64_Addr, #[cfg(target_pointer_width = "32")] pub dlpi_addr: Elf32_Addr, pub dlpi_name: *const c_char, #[cfg(target_pointer_width = "64")] pub dlpi_phdr: *const Elf64_Phdr, #[cfg(target_pointer_width = "32")] pub dlpi_phdr: *const Elf32_Phdr, #[cfg(target_pointer_width = "64")] pub dlpi_phnum: Elf64_Half, #[cfg(target_pointer_width = "32")] pub dlpi_phnum: Elf32_Half, // These fields were added in Android R pub dlpi_adds: c_ulonglong, pub dlpi_subs: c_ulonglong, pub dlpi_tls_modid: size_t, pub dlpi_tls_data: *mut c_void, } // linux/filter.h pub struct sock_filter { pub code: crate::__u16, pub jt: crate::__u8, pub jf: crate::__u8, pub k: crate::__u32, } pub struct sock_fprog { pub len: c_ushort, pub filter: *mut sock_filter, } // linux/seccomp.h pub struct seccomp_data { pub nr: c_int, pub arch: crate::__u32, pub instruction_pointer: crate::__u64, pub args: [crate::__u64; 6], } pub struct seccomp_metadata { pub filter_off: crate::__u64, pub flags: crate::__u64, } pub struct ptrace_peeksiginfo_args { pub off: crate::__u64, pub flags: crate::__u32, pub nr: crate::__s32, } // linux/input.h pub struct input_event { pub time: crate::timeval, pub type_: crate::__u16, pub code: crate::__u16, pub value: crate::__s32, } pub struct input_id { pub bustype: crate::__u16, pub vendor: crate::__u16, pub product: crate::__u16, pub version: crate::__u16, } pub struct input_absinfo { pub value: crate::__s32, pub minimum: crate::__s32, pub maximum: crate::__s32, pub fuzz: crate::__s32, pub flat: crate::__s32, pub resolution: crate::__s32, } pub struct input_keymap_entry { pub flags: crate::__u8, pub len: crate::__u8, pub index: crate::__u16, pub keycode: crate::__u32, pub scancode: [crate::__u8; 32], } pub struct input_mask { pub type_: crate::__u32, pub codes_size: crate::__u32, pub codes_ptr: crate::__u64, } pub struct ff_replay { pub length: crate::__u16, pub delay: crate::__u16, } pub struct ff_trigger { pub button: crate::__u16, pub interval: crate::__u16, } pub struct ff_envelope { pub attack_length: crate::__u16, pub attack_level: crate::__u16, pub fade_length: crate::__u16, pub fade_level: crate::__u16, } pub struct ff_constant_effect { pub level: crate::__s16, pub envelope: ff_envelope, } pub struct ff_ramp_effect { pub start_level: crate::__s16, pub end_level: crate::__s16, pub envelope: ff_envelope, } pub struct ff_condition_effect { pub right_saturation: crate::__u16, pub left_saturation: crate::__u16, pub right_coeff: crate::__s16, pub left_coeff: crate::__s16, pub deadband: crate::__u16, pub center: crate::__s16, } pub struct ff_periodic_effect { pub waveform: crate::__u16, pub period: crate::__u16, pub magnitude: crate::__s16, pub offset: crate::__s16, pub phase: crate::__u16, pub envelope: ff_envelope, pub custom_len: crate::__u32, pub custom_data: *mut crate::__s16, } pub struct ff_rumble_effect { pub strong_magnitude: crate::__u16, pub weak_magnitude: crate::__u16, } pub struct ff_effect { pub type_: crate::__u16, pub id: crate::__s16, pub direction: crate::__u16, pub trigger: ff_trigger, pub replay: ff_replay, // FIXME(1.0): this is actually a union #[cfg(target_pointer_width = "64")] pub u: [u64; 4], #[cfg(target_pointer_width = "32")] pub u: [u32; 7], } // linux/uinput.h pub struct uinput_ff_upload { pub request_id: crate::__u32, pub retval: crate::__s32, pub effect: ff_effect, pub old: ff_effect, } pub struct uinput_ff_erase { pub request_id: crate::__u32, pub retval: crate::__s32, pub effect_id: crate::__u32, } pub struct uinput_abs_setup { pub code: crate::__u16, pub absinfo: input_absinfo, } pub struct option { pub name: *const c_char, pub has_arg: c_int, pub flag: *mut c_int, pub val: c_int, } pub struct __c_anonymous_ifru_map { pub mem_start: c_ulong, pub mem_end: c_ulong, pub base_addr: c_ushort, pub irq: c_uchar, pub dma: c_uchar, pub port: c_uchar, } pub struct in6_ifreq { pub ifr6_addr: crate::in6_addr, pub ifr6_prefixlen: u32, pub ifr6_ifindex: c_int, } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } } s_no_extra_traits! { pub struct sockaddr_nl { pub nl_family: crate::sa_family_t, nl_pad: c_ushort, pub nl_pid: u32, pub nl_groups: u32, } pub struct dirent { pub d_ino: u64, pub d_off: i64, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } pub struct dirent64 { pub d_ino: u64, pub d_off: i64, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, pub _pad: [c_int; 29], _align: [usize; 0], } pub struct lastlog { ll_time: crate::time_t, ll_line: [c_char; UT_LINESIZE], ll_host: [c_char; UT_HOSTSIZE], } pub struct utmp { pub ut_type: c_short, pub ut_pid: crate::pid_t, pub ut_line: [c_char; UT_LINESIZE], pub ut_id: [c_char; 4], pub ut_user: [c_char; UT_NAMESIZE], pub ut_host: [c_char; UT_HOSTSIZE], pub ut_exit: exit_status, pub ut_session: c_long, pub ut_tv: crate::timeval, pub ut_addr_v6: [i32; 4], unused: [c_char; 20], } pub struct sockaddr_alg { pub salg_family: crate::sa_family_t, pub salg_type: [c_uchar; 14], pub salg_feat: u32, pub salg_mask: u32, pub salg_name: [c_uchar; 64], } pub struct uinput_setup { pub id: input_id, pub name: [c_char; UINPUT_MAX_NAME_SIZE], pub ff_effects_max: crate::__u32, } pub struct uinput_user_dev { pub name: [c_char; UINPUT_MAX_NAME_SIZE], pub id: input_id, pub ff_effects_max: crate::__u32, pub absmax: [crate::__s32; ABS_CNT], pub absmin: [crate::__s32; ABS_CNT], pub absfuzz: [crate::__s32; ABS_CNT], pub absflat: [crate::__s32; ABS_CNT], } /// WARNING: The `PartialEq`, `Eq` and `Hash` implementations of this /// type are unsound and will be removed in the future. #[deprecated( note = "this struct has unsafe trait implementations that will be \ removed in the future", since = "0.2.80" )] pub struct af_alg_iv { pub ivlen: u32, pub iv: [c_uchar; 0], } pub struct prop_info { __name: [c_char; 32], __serial: c_uint, __value: [c_char; 92], } pub union __c_anonymous_ifr_ifru { pub ifru_addr: crate::sockaddr, pub ifru_dstaddr: crate::sockaddr, pub ifru_broadaddr: crate::sockaddr, pub ifru_netmask: crate::sockaddr, pub ifru_hwaddr: crate::sockaddr, pub ifru_flags: c_short, pub ifru_ifindex: c_int, pub ifru_metric: c_int, pub ifru_mtu: c_int, pub ifru_map: __c_anonymous_ifru_map, pub ifru_slave: [c_char; crate::IFNAMSIZ], pub ifru_newname: [c_char; crate::IFNAMSIZ], pub ifru_data: *mut c_char, } pub struct ifreq { /// interface name, e.g. "en0" pub ifr_name: [c_char; crate::IFNAMSIZ], pub ifr_ifru: __c_anonymous_ifr_ifru, } pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: *mut c_char, pub ifcu_req: *mut crate::ifreq, } /* Structure used in SIOCGIFCONF request. Used to retrieve interface configuration for machine (useful for programs which must know all networks accessible). */ pub struct ifconf { pub ifc_len: c_int, /* Size of buffer. */ pub ifc_ifcu: __c_anonymous_ifc_ifcu, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_nl { fn eq(&self, other: &sockaddr_nl) -> bool { self.nl_family == other.nl_family && self.nl_pid == other.nl_pid && self.nl_groups == other.nl_groups } } impl Eq for sockaddr_nl {} impl fmt::Debug for sockaddr_nl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_nl") .field("nl_family", &self.nl_family) .field("nl_pid", &self.nl_pid) .field("nl_groups", &self.nl_groups) .finish() } } impl hash::Hash for sockaddr_nl { fn hash(&self, state: &mut H) { self.nl_family.hash(state); self.nl_pid.hash(state); self.nl_groups.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for dirent64 { fn eq(&self, other: &dirent64) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent64 {} impl fmt::Debug for dirent64 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent64") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent64 { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { self.si_signo == other.si_signo && self.si_errno == other.si_errno && self.si_code == other.si_code // Ignore _pad // Ignore _align } } impl Eq for siginfo_t {} impl fmt::Debug for siginfo_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("siginfo_t") .field("si_signo", &self.si_signo) .field("si_errno", &self.si_errno) .field("si_code", &self.si_code) // Ignore _pad // Ignore _align .finish() } } impl hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_errno.hash(state); self.si_code.hash(state); // Ignore _pad // Ignore _align } } impl PartialEq for lastlog { fn eq(&self, other: &lastlog) -> bool { self.ll_time == other.ll_time && self .ll_line .iter() .zip(other.ll_line.iter()) .all(|(a, b)| a == b) && self .ll_host .iter() .zip(other.ll_host.iter()) .all(|(a, b)| a == b) } } impl Eq for lastlog {} impl fmt::Debug for lastlog { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("lastlog") .field("ll_time", &self.ll_time) .field("ll_line", &self.ll_line) // FIXME(debug): .field("ll_host", &self.ll_host) .finish() } } impl hash::Hash for lastlog { fn hash(&self, state: &mut H) { self.ll_time.hash(state); self.ll_line.hash(state); self.ll_host.hash(state); } } impl PartialEq for utmp { fn eq(&self, other: &utmp) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self .ut_line .iter() .zip(other.ut_line.iter()) .all(|(a, b)| a == b) && self.ut_id == other.ut_id && self .ut_user .iter() .zip(other.ut_user.iter()) .all(|(a, b)| a == b) && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_addr_v6 == other.ut_addr_v6 && self.unused == other.unused } } impl Eq for utmp {} impl fmt::Debug for utmp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmp") .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_line", &self.ut_line) .field("ut_id", &self.ut_id) .field("ut_user", &self.ut_user) // FIXME(debug): .field("ut_host", &self.ut_host) .field("ut_exit", &self.ut_exit) .field("ut_session", &self.ut_session) .field("ut_tv", &self.ut_tv) .field("ut_addr_v6", &self.ut_addr_v6) .field("unused", &self.unused) .finish() } } impl hash::Hash for utmp { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_user.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_addr_v6.hash(state); self.unused.hash(state); } } impl PartialEq for sockaddr_alg { fn eq(&self, other: &sockaddr_alg) -> bool { self.salg_family == other.salg_family && self .salg_type .iter() .zip(other.salg_type.iter()) .all(|(a, b)| a == b) && self.salg_feat == other.salg_feat && self.salg_mask == other.salg_mask && self .salg_name .iter() .zip(other.salg_name.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_alg {} impl fmt::Debug for sockaddr_alg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_alg") .field("salg_family", &self.salg_family) .field("salg_type", &self.salg_type) .field("salg_feat", &self.salg_feat) .field("salg_mask", &self.salg_mask) .field("salg_name", &&self.salg_name[..]) .finish() } } impl hash::Hash for sockaddr_alg { fn hash(&self, state: &mut H) { self.salg_family.hash(state); self.salg_type.hash(state); self.salg_feat.hash(state); self.salg_mask.hash(state); self.salg_name.hash(state); } } impl PartialEq for uinput_setup { fn eq(&self, other: &uinput_setup) -> bool { self.id == other.id && self.name[..] == other.name[..] && self.ff_effects_max == other.ff_effects_max } } impl Eq for uinput_setup {} impl fmt::Debug for uinput_setup { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("uinput_setup") .field("id", &self.id) .field("name", &&self.name[..]) .field("ff_effects_max", &self.ff_effects_max) .finish() } } impl hash::Hash for uinput_setup { fn hash(&self, state: &mut H) { self.id.hash(state); self.name.hash(state); self.ff_effects_max.hash(state); } } impl PartialEq for uinput_user_dev { fn eq(&self, other: &uinput_user_dev) -> bool { self.name[..] == other.name[..] && self.id == other.id && self.ff_effects_max == other.ff_effects_max && self.absmax[..] == other.absmax[..] && self.absmin[..] == other.absmin[..] && self.absfuzz[..] == other.absfuzz[..] && self.absflat[..] == other.absflat[..] } } impl Eq for uinput_user_dev {} impl fmt::Debug for uinput_user_dev { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("uinput_setup") .field("name", &&self.name[..]) .field("id", &self.id) .field("ff_effects_max", &self.ff_effects_max) .field("absmax", &&self.absmax[..]) .field("absmin", &&self.absmin[..]) .field("absfuzz", &&self.absfuzz[..]) .field("absflat", &&self.absflat[..]) .finish() } } impl hash::Hash for uinput_user_dev { fn hash(&self, state: &mut H) { self.name.hash(state); self.id.hash(state); self.ff_effects_max.hash(state); self.absmax.hash(state); self.absmin.hash(state); self.absfuzz.hash(state); self.absflat.hash(state); } } impl fmt::Debug for ifreq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } impl fmt::Debug for ifconf { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifconf") .field("ifc_len", &self.ifc_len) .field("ifc_ifcu", &self.ifc_ifcu) .finish() } } #[allow(deprecated)] impl af_alg_iv { fn as_slice(&self) -> &[u8] { unsafe { ::core::slice::from_raw_parts(self.iv.as_ptr(), self.ivlen as usize) } } } #[allow(deprecated)] impl PartialEq for af_alg_iv { fn eq(&self, other: &af_alg_iv) -> bool { *self.as_slice() == *other.as_slice() } } #[allow(deprecated)] impl Eq for af_alg_iv {} #[allow(deprecated)] impl fmt::Debug for af_alg_iv { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("af_alg_iv") .field("ivlen", &self.ivlen) .finish() } } #[allow(deprecated)] impl hash::Hash for af_alg_iv { fn hash(&self, state: &mut H) { self.as_slice().hash(state); } } impl PartialEq for prop_info { fn eq(&self, other: &prop_info) -> bool { self.__name == other.__name && self.__serial == other.__serial && self.__value == other.__value } } impl Eq for prop_info {} impl fmt::Debug for prop_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("prop_info") .field("__name", &self.__name) .field("__serial", &self.__serial) .field("__value", &self.__value) .finish() } } } } pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MS_NOUSER: c_ulong = 0xffffffff80000000; pub const MS_RMT_MASK: c_ulong = 0x02800051; pub const O_TRUNC: c_int = 512; pub const O_CLOEXEC: c_int = 0x80000; pub const O_PATH: c_int = 0o10000000; pub const O_NOATIME: c_int = 0o1000000; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const EPOLL_CLOEXEC: c_int = 0x80000; // sys/eventfd.h pub const EFD_SEMAPHORE: c_int = 0x1; pub const EFD_CLOEXEC: c_int = O_CLOEXEC; pub const EFD_NONBLOCK: c_int = O_NONBLOCK; // sys/timerfd.h pub const TFD_CLOEXEC: c_int = O_CLOEXEC; pub const TFD_NONBLOCK: c_int = O_NONBLOCK; pub const TFD_TIMER_ABSTIME: c_int = 1; pub const TFD_TIMER_CANCEL_ON_SET: c_int = 2; pub const USER_PROCESS: c_short = 7; pub const _POSIX_VDISABLE: crate::cc_t = 0; // linux/falloc.h pub const FALLOC_FL_KEEP_SIZE: c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: c_int = 0x02; pub const FALLOC_FL_NO_HIDE_STALE: c_int = 0x04; pub const FALLOC_FL_COLLAPSE_RANGE: c_int = 0x08; pub const FALLOC_FL_ZERO_RANGE: c_int = 0x10; pub const FALLOC_FL_INSERT_RANGE: c_int = 0x20; pub const FALLOC_FL_UNSHARE_RANGE: c_int = 0x40; pub const BUFSIZ: c_uint = 1024; pub const FILENAME_MAX: c_uint = 4096; pub const FOPEN_MAX: c_uint = 20; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const L_tmpnam: c_uint = 4096; pub const TMP_MAX: c_uint = 308915776; pub const _PC_LINK_MAX: c_int = 1; pub const _PC_MAX_CANON: c_int = 2; pub const _PC_MAX_INPUT: c_int = 3; pub const _PC_NAME_MAX: c_int = 4; pub const _PC_PATH_MAX: c_int = 5; pub const _PC_PIPE_BUF: c_int = 6; pub const _PC_2_SYMLINKS: c_int = 7; pub const _PC_ALLOC_SIZE_MIN: c_int = 8; pub const _PC_REC_INCR_XFER_SIZE: c_int = 9; pub const _PC_REC_MAX_XFER_SIZE: c_int = 10; pub const _PC_REC_MIN_XFER_SIZE: c_int = 11; pub const _PC_REC_XFER_ALIGN: c_int = 12; pub const _PC_SYMLINK_MAX: c_int = 13; pub const _PC_CHOWN_RESTRICTED: c_int = 14; pub const _PC_NO_TRUNC: c_int = 15; pub const _PC_VDISABLE: c_int = 16; pub const _PC_ASYNC_IO: c_int = 17; pub const _PC_PRIO_IO: c_int = 18; pub const _PC_SYNC_IO: c_int = 19; pub const FIONBIO: c_int = 0x5421; pub const _SC_ARG_MAX: c_int = 0x0000; pub const _SC_BC_BASE_MAX: c_int = 0x0001; pub const _SC_BC_DIM_MAX: c_int = 0x0002; pub const _SC_BC_SCALE_MAX: c_int = 0x0003; pub const _SC_BC_STRING_MAX: c_int = 0x0004; pub const _SC_CHILD_MAX: c_int = 0x0005; pub const _SC_CLK_TCK: c_int = 0x0006; pub const _SC_COLL_WEIGHTS_MAX: c_int = 0x0007; pub const _SC_EXPR_NEST_MAX: c_int = 0x0008; pub const _SC_LINE_MAX: c_int = 0x0009; pub const _SC_NGROUPS_MAX: c_int = 0x000a; pub const _SC_OPEN_MAX: c_int = 0x000b; pub const _SC_PASS_MAX: c_int = 0x000c; pub const _SC_2_C_BIND: c_int = 0x000d; pub const _SC_2_C_DEV: c_int = 0x000e; pub const _SC_2_C_VERSION: c_int = 0x000f; pub const _SC_2_CHAR_TERM: c_int = 0x0010; pub const _SC_2_FORT_DEV: c_int = 0x0011; pub const _SC_2_FORT_RUN: c_int = 0x0012; pub const _SC_2_LOCALEDEF: c_int = 0x0013; pub const _SC_2_SW_DEV: c_int = 0x0014; pub const _SC_2_UPE: c_int = 0x0015; pub const _SC_2_VERSION: c_int = 0x0016; pub const _SC_JOB_CONTROL: c_int = 0x0017; pub const _SC_SAVED_IDS: c_int = 0x0018; pub const _SC_VERSION: c_int = 0x0019; pub const _SC_RE_DUP_MAX: c_int = 0x001a; pub const _SC_STREAM_MAX: c_int = 0x001b; pub const _SC_TZNAME_MAX: c_int = 0x001c; pub const _SC_XOPEN_CRYPT: c_int = 0x001d; pub const _SC_XOPEN_ENH_I18N: c_int = 0x001e; pub const _SC_XOPEN_SHM: c_int = 0x001f; pub const _SC_XOPEN_VERSION: c_int = 0x0020; pub const _SC_XOPEN_XCU_VERSION: c_int = 0x0021; pub const _SC_XOPEN_REALTIME: c_int = 0x0022; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 0x0023; pub const _SC_XOPEN_LEGACY: c_int = 0x0024; pub const _SC_ATEXIT_MAX: c_int = 0x0025; pub const _SC_IOV_MAX: c_int = 0x0026; pub const _SC_UIO_MAXIOV: c_int = _SC_IOV_MAX; pub const _SC_PAGESIZE: c_int = 0x0027; pub const _SC_PAGE_SIZE: c_int = 0x0028; pub const _SC_XOPEN_UNIX: c_int = 0x0029; pub const _SC_XBS5_ILP32_OFF32: c_int = 0x002a; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 0x002b; pub const _SC_XBS5_LP64_OFF64: c_int = 0x002c; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 0x002d; pub const _SC_AIO_LISTIO_MAX: c_int = 0x002e; pub const _SC_AIO_MAX: c_int = 0x002f; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 0x0030; pub const _SC_DELAYTIMER_MAX: c_int = 0x0031; pub const _SC_MQ_OPEN_MAX: c_int = 0x0032; pub const _SC_MQ_PRIO_MAX: c_int = 0x0033; pub const _SC_RTSIG_MAX: c_int = 0x0034; pub const _SC_SEM_NSEMS_MAX: c_int = 0x0035; pub const _SC_SEM_VALUE_MAX: c_int = 0x0036; pub const _SC_SIGQUEUE_MAX: c_int = 0x0037; pub const _SC_TIMER_MAX: c_int = 0x0038; pub const _SC_ASYNCHRONOUS_IO: c_int = 0x0039; pub const _SC_FSYNC: c_int = 0x003a; pub const _SC_MAPPED_FILES: c_int = 0x003b; pub const _SC_MEMLOCK: c_int = 0x003c; pub const _SC_MEMLOCK_RANGE: c_int = 0x003d; pub const _SC_MEMORY_PROTECTION: c_int = 0x003e; pub const _SC_MESSAGE_PASSING: c_int = 0x003f; pub const _SC_PRIORITIZED_IO: c_int = 0x0040; pub const _SC_PRIORITY_SCHEDULING: c_int = 0x0041; pub const _SC_REALTIME_SIGNALS: c_int = 0x0042; pub const _SC_SEMAPHORES: c_int = 0x0043; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 0x0044; pub const _SC_SYNCHRONIZED_IO: c_int = 0x0045; pub const _SC_TIMERS: c_int = 0x0046; pub const _SC_GETGR_R_SIZE_MAX: c_int = 0x0047; pub const _SC_GETPW_R_SIZE_MAX: c_int = 0x0048; pub const _SC_LOGIN_NAME_MAX: c_int = 0x0049; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 0x004a; pub const _SC_THREAD_KEYS_MAX: c_int = 0x004b; pub const _SC_THREAD_STACK_MIN: c_int = 0x004c; pub const _SC_THREAD_THREADS_MAX: c_int = 0x004d; pub const _SC_TTY_NAME_MAX: c_int = 0x004e; pub const _SC_THREADS: c_int = 0x004f; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 0x0050; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 0x0051; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 0x0052; pub const _SC_THREAD_PRIO_INHERIT: c_int = 0x0053; pub const _SC_THREAD_PRIO_PROTECT: c_int = 0x0054; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 0x0055; pub const _SC_NPROCESSORS_CONF: c_int = 0x0060; pub const _SC_NPROCESSORS_ONLN: c_int = 0x0061; pub const _SC_PHYS_PAGES: c_int = 0x0062; pub const _SC_AVPHYS_PAGES: c_int = 0x0063; pub const _SC_MONOTONIC_CLOCK: c_int = 0x0064; pub const _SC_2_PBS: c_int = 0x0065; pub const _SC_2_PBS_ACCOUNTING: c_int = 0x0066; pub const _SC_2_PBS_CHECKPOINT: c_int = 0x0067; pub const _SC_2_PBS_LOCATE: c_int = 0x0068; pub const _SC_2_PBS_MESSAGE: c_int = 0x0069; pub const _SC_2_PBS_TRACK: c_int = 0x006a; pub const _SC_ADVISORY_INFO: c_int = 0x006b; pub const _SC_BARRIERS: c_int = 0x006c; pub const _SC_CLOCK_SELECTION: c_int = 0x006d; pub const _SC_CPUTIME: c_int = 0x006e; pub const _SC_HOST_NAME_MAX: c_int = 0x006f; pub const _SC_IPV6: c_int = 0x0070; pub const _SC_RAW_SOCKETS: c_int = 0x0071; pub const _SC_READER_WRITER_LOCKS: c_int = 0x0072; pub const _SC_REGEXP: c_int = 0x0073; pub const _SC_SHELL: c_int = 0x0074; pub const _SC_SPAWN: c_int = 0x0075; pub const _SC_SPIN_LOCKS: c_int = 0x0076; pub const _SC_SPORADIC_SERVER: c_int = 0x0077; pub const _SC_SS_REPL_MAX: c_int = 0x0078; pub const _SC_SYMLOOP_MAX: c_int = 0x0079; pub const _SC_THREAD_CPUTIME: c_int = 0x007a; pub const _SC_THREAD_PROCESS_SHARED: c_int = 0x007b; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 0x007c; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 0x007d; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 0x007e; pub const _SC_TIMEOUTS: c_int = 0x007f; pub const _SC_TRACE: c_int = 0x0080; pub const _SC_TRACE_EVENT_FILTER: c_int = 0x0081; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 0x0082; pub const _SC_TRACE_INHERIT: c_int = 0x0083; pub const _SC_TRACE_LOG: c_int = 0x0084; pub const _SC_TRACE_NAME_MAX: c_int = 0x0085; pub const _SC_TRACE_SYS_MAX: c_int = 0x0086; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 0x0087; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 0x0088; pub const _SC_V7_ILP32_OFF32: c_int = 0x0089; pub const _SC_V7_ILP32_OFFBIG: c_int = 0x008a; pub const _SC_V7_LP64_OFF64: c_int = 0x008b; pub const _SC_V7_LPBIG_OFFBIG: c_int = 0x008c; pub const _SC_XOPEN_STREAMS: c_int = 0x008d; pub const _SC_XOPEN_UUCP: c_int = 0x008e; pub const _SC_LEVEL1_ICACHE_SIZE: c_int = 0x008f; pub const _SC_LEVEL1_ICACHE_ASSOC: c_int = 0x0090; pub const _SC_LEVEL1_ICACHE_LINESIZE: c_int = 0x0091; pub const _SC_LEVEL1_DCACHE_SIZE: c_int = 0x0092; pub const _SC_LEVEL1_DCACHE_ASSOC: c_int = 0x0093; pub const _SC_LEVEL1_DCACHE_LINESIZE: c_int = 0x0094; pub const _SC_LEVEL2_CACHE_SIZE: c_int = 0x0095; pub const _SC_LEVEL2_CACHE_ASSOC: c_int = 0x0096; pub const _SC_LEVEL2_CACHE_LINESIZE: c_int = 0x0097; pub const _SC_LEVEL3_CACHE_SIZE: c_int = 0x0098; pub const _SC_LEVEL3_CACHE_ASSOC: c_int = 0x0099; pub const _SC_LEVEL3_CACHE_LINESIZE: c_int = 0x009a; pub const _SC_LEVEL4_CACHE_SIZE: c_int = 0x009b; pub const _SC_LEVEL4_CACHE_ASSOC: c_int = 0x009c; pub const _SC_LEVEL4_CACHE_LINESIZE: c_int = 0x009d; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const F_SEAL_FUTURE_WRITE: c_int = 0x0010; pub const F_SEAL_EXEC: c_int = 0x0020; pub const IFF_LOWER_UP: c_int = 0x10000; pub const IFF_DORMANT: c_int = 0x20000; pub const IFF_ECHO: c_int = 0x40000; pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_EXPLICIT_SCHED: c_int = 0; pub const PTHREAD_INHERIT_SCHED: c_int = 1; // stdio.h pub const RENAME_NOREPLACE: c_int = 1; pub const RENAME_EXCHANGE: c_int = 2; pub const RENAME_WHITEOUT: c_int = 4; pub const FIOCLEX: c_int = 0x5451; pub const FIONCLEX: c_int = 0x5450; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const RUSAGE_CHILDREN: c_int = -1; pub const LC_PAPER: c_int = 7; pub const LC_NAME: c_int = 8; pub const LC_ADDRESS: c_int = 9; pub const LC_TELEPHONE: c_int = 10; pub const LC_MEASUREMENT: c_int = 11; pub const LC_IDENTIFICATION: c_int = 12; pub const LC_PAPER_MASK: c_int = 1 << LC_PAPER; pub const LC_NAME_MASK: c_int = 1 << LC_NAME; pub const LC_ADDRESS_MASK: c_int = 1 << LC_ADDRESS; pub const LC_TELEPHONE_MASK: c_int = 1 << LC_TELEPHONE; pub const LC_MEASUREMENT_MASK: c_int = 1 << LC_MEASUREMENT; pub const LC_IDENTIFICATION_MASK: c_int = 1 << LC_IDENTIFICATION; pub const LC_ALL_MASK: c_int = crate::LC_CTYPE_MASK | crate::LC_NUMERIC_MASK | crate::LC_TIME_MASK | crate::LC_COLLATE_MASK | crate::LC_MONETARY_MASK | crate::LC_MESSAGES_MASK | LC_PAPER_MASK | LC_NAME_MASK | LC_ADDRESS_MASK | LC_TELEPHONE_MASK | LC_MEASUREMENT_MASK | LC_IDENTIFICATION_MASK; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_SEQPACKET: c_int = 5; pub const SOCK_DCCP: c_int = 6; #[deprecated(since = "0.2.70", note = "AF_PACKET must be used instead")] pub const SOCK_PACKET: c_int = 10; pub const IPPROTO_MAX: c_int = 256; pub const SOL_SOCKET: c_int = 1; pub const SOL_SCTP: c_int = 132; pub const SOL_IPX: c_int = 256; pub const SOL_AX25: c_int = 257; pub const SOL_ATALK: c_int = 258; pub const SOL_NETROM: c_int = 259; pub const SOL_ROSE: c_int = 260; /* DCCP socket options */ pub const DCCP_SOCKOPT_PACKET_SIZE: c_int = 1; pub const DCCP_SOCKOPT_SERVICE: c_int = 2; pub const DCCP_SOCKOPT_CHANGE_L: c_int = 3; pub const DCCP_SOCKOPT_CHANGE_R: c_int = 4; pub const DCCP_SOCKOPT_GET_CUR_MPS: c_int = 5; pub const DCCP_SOCKOPT_SERVER_TIMEWAIT: c_int = 6; pub const DCCP_SOCKOPT_SEND_CSCOV: c_int = 10; pub const DCCP_SOCKOPT_RECV_CSCOV: c_int = 11; pub const DCCP_SOCKOPT_AVAILABLE_CCIDS: c_int = 12; pub const DCCP_SOCKOPT_CCID: c_int = 13; pub const DCCP_SOCKOPT_TX_CCID: c_int = 14; pub const DCCP_SOCKOPT_RX_CCID: c_int = 15; pub const DCCP_SOCKOPT_QPOLICY_ID: c_int = 16; pub const DCCP_SOCKOPT_QPOLICY_TXQLEN: c_int = 17; pub const DCCP_SOCKOPT_CCID_RX_INFO: c_int = 128; pub const DCCP_SOCKOPT_CCID_TX_INFO: c_int = 192; /// maximum number of services provided on the same listening port pub const DCCP_SERVICE_LIST_MAX_LEN: c_int = 32; pub const SO_REUSEADDR: c_int = 2; pub const SO_TYPE: c_int = 3; pub const SO_ERROR: c_int = 4; pub const SO_DONTROUTE: c_int = 5; pub const SO_BROADCAST: c_int = 6; pub const SO_SNDBUF: c_int = 7; pub const SO_RCVBUF: c_int = 8; pub const SO_KEEPALIVE: c_int = 9; pub const SO_OOBINLINE: c_int = 10; pub const SO_PRIORITY: c_int = 12; pub const SO_LINGER: c_int = 13; pub const SO_BSDCOMPAT: c_int = 14; pub const SO_REUSEPORT: c_int = 15; pub const SO_PASSCRED: c_int = 16; pub const SO_PEERCRED: c_int = 17; pub const SO_RCVLOWAT: c_int = 18; pub const SO_SNDLOWAT: c_int = 19; pub const SO_RCVTIMEO: c_int = 20; pub const SO_SNDTIMEO: c_int = 21; pub const SO_BINDTODEVICE: c_int = 25; pub const SO_ATTACH_FILTER: c_int = 26; pub const SO_DETACH_FILTER: c_int = 27; pub const SO_GET_FILTER: c_int = SO_ATTACH_FILTER; pub const SO_TIMESTAMP: c_int = 29; pub const SO_ACCEPTCONN: c_int = 30; pub const SO_PEERSEC: c_int = 31; pub const SO_SNDBUFFORCE: c_int = 32; pub const SO_RCVBUFFORCE: c_int = 33; pub const SO_PASSSEC: c_int = 34; pub const SO_TIMESTAMPNS: c_int = 35; // pub const SO_TIMESTAMPNS_OLD: c_int = 35; pub const SO_MARK: c_int = 36; pub const SO_TIMESTAMPING: c_int = 37; // pub const SO_TIMESTAMPING_OLD: c_int = 37; pub const SO_PROTOCOL: c_int = 38; pub const SO_DOMAIN: c_int = 39; pub const SO_RXQ_OVFL: c_int = 40; pub const SO_PEEK_OFF: c_int = 42; pub const SO_BUSY_POLL: c_int = 46; pub const SCM_TIMESTAMPING_OPT_STATS: c_int = 54; pub const SCM_TIMESTAMPING_PKTINFO: c_int = 58; pub const SO_BINDTOIFINDEX: c_int = 62; pub const SO_TIMESTAMP_NEW: c_int = 63; pub const SO_TIMESTAMPNS_NEW: c_int = 64; pub const SO_TIMESTAMPING_NEW: c_int = 65; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: c_int = SO_TIMESTAMPING; pub const IPTOS_ECN_NOTECT: u8 = 0x00; pub const O_ACCMODE: c_int = 3; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 0x101000; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const O_DSYNC: c_int = 4096; pub const O_RSYNC: c_int = O_SYNC; pub const NI_MAXHOST: size_t = 1025; pub const NI_MAXSERV: size_t = 32; pub const NI_NOFQDN: c_int = 0x00000001; pub const NI_NUMERICHOST: c_int = 0x00000002; pub const NI_NAMEREQD: c_int = 0x00000004; pub const NI_NUMERICSERV: c_int = 0x00000008; pub const NI_DGRAM: c_int = 0x00000010; pub const NCCS: usize = 19; pub const TCSBRKP: c_int = 0x5425; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 0x1; pub const TCSAFLUSH: c_int = 0x2; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0o200000; pub const MAP_HUGETLB: c_int = 0x040000; pub const PTRACE_TRACEME: c_int = 0; pub const PTRACE_PEEKTEXT: c_int = 1; pub const PTRACE_PEEKDATA: c_int = 2; pub const PTRACE_PEEKUSER: c_int = 3; pub const PTRACE_POKETEXT: c_int = 4; pub const PTRACE_POKEDATA: c_int = 5; pub const PTRACE_POKEUSER: c_int = 6; pub const PTRACE_CONT: c_int = 7; pub const PTRACE_KILL: c_int = 8; pub const PTRACE_SINGLESTEP: c_int = 9; pub const PTRACE_GETREGS: c_int = 12; pub const PTRACE_SETREGS: c_int = 13; pub const PTRACE_ATTACH: c_int = 16; pub const PTRACE_DETACH: c_int = 17; pub const PTRACE_SYSCALL: c_int = 24; pub const PTRACE_SETOPTIONS: c_int = 0x4200; pub const PTRACE_GETEVENTMSG: c_int = 0x4201; pub const PTRACE_GETSIGINFO: c_int = 0x4202; pub const PTRACE_SETSIGINFO: c_int = 0x4203; pub const PTRACE_GETREGSET: c_int = 0x4204; pub const PTRACE_SETREGSET: c_int = 0x4205; pub const PTRACE_SECCOMP_GET_METADATA: c_int = 0x420d; pub const PTRACE_EVENT_STOP: c_int = 128; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_RSS: c_int = 5; pub const RLIMIT_NPROC: c_int = 6; pub const RLIMIT_NOFILE: c_int = 7; pub const RLIMIT_MEMLOCK: c_int = 8; pub const RLIMIT_AS: c_int = 9; pub const RLIMIT_LOCKS: c_int = 10; pub const RLIMIT_SIGPENDING: c_int = 11; pub const RLIMIT_MSGQUEUE: c_int = 12; pub const RLIMIT_NICE: c_int = 13; pub const RLIMIT_RTPRIO: c_int = 14; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 16; pub const RLIM_INFINITY: crate::rlim_t = !0; pub const TCGETS: c_int = 0x5401; pub const TCSETS: c_int = 0x5402; pub const TCSETSW: c_int = 0x5403; pub const TCSETSF: c_int = 0x5404; pub const TCGETS2: c_int = 0x802c542a; pub const TCSETS2: c_int = 0x402c542b; pub const TCSETSW2: c_int = 0x402c542c; pub const TCSETSF2: c_int = 0x402c542d; pub const TCGETA: c_int = 0x5405; pub const TCSETA: c_int = 0x5406; pub const TCSETAW: c_int = 0x5407; pub const TCSETAF: c_int = 0x5408; pub const TCSBRK: c_int = 0x5409; pub const TCXONC: c_int = 0x540A; pub const TCFLSH: c_int = 0x540B; pub const TIOCGSOFTCAR: c_int = 0x5419; pub const TIOCSSOFTCAR: c_int = 0x541A; pub const TIOCINQ: c_int = 0x541B; pub const TIOCLINUX: c_int = 0x541C; pub const TIOCGSERIAL: c_int = 0x541E; pub const TIOCEXCL: c_int = 0x540C; pub const TIOCNXCL: c_int = 0x540D; pub const TIOCSCTTY: c_int = 0x540E; pub const TIOCGPGRP: c_int = 0x540F; pub const TIOCSPGRP: c_int = 0x5410; pub const TIOCOUTQ: c_int = 0x5411; pub const TIOCSTI: c_int = 0x5412; pub const TIOCGWINSZ: c_int = 0x5413; pub const TIOCSWINSZ: c_int = 0x5414; pub const TIOCMGET: c_int = 0x5415; pub const TIOCMBIS: c_int = 0x5416; pub const TIOCMBIC: c_int = 0x5417; pub const TIOCMSET: c_int = 0x5418; pub const FIONREAD: c_int = 0x541B; pub const TIOCCONS: c_int = 0x541D; pub const TIOCSBRK: c_int = 0x5427; pub const TIOCCBRK: c_int = 0x5428; cfg_if! { if #[cfg(any( target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", target_arch = "riscv64", target_arch = "s390x" ))] { pub const FICLONE: c_int = 0x40049409; pub const FICLONERANGE: c_int = 0x4020940D; } else if #[cfg(any( target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64" ))] { pub const FICLONE: c_int = 0x80049409; pub const FICLONERANGE: c_int = 0x8020940D; } } pub const ST_RDONLY: c_ulong = 1; pub const ST_NOSUID: c_ulong = 2; pub const ST_NODEV: c_ulong = 4; pub const ST_NOEXEC: c_ulong = 8; pub const ST_SYNCHRONOUS: c_ulong = 16; pub const ST_MANDLOCK: c_ulong = 64; pub const ST_NOATIME: c_ulong = 1024; pub const ST_NODIRATIME: c_ulong = 2048; pub const ST_RELATIME: c_ulong = 4096; pub const RTLD_NOLOAD: c_int = 0x4; pub const RTLD_NODELETE: c_int = 0x1000; pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; pub const AI_PASSIVE: c_int = 0x00000001; pub const AI_CANONNAME: c_int = 0x00000002; pub const AI_NUMERICHOST: c_int = 0x00000004; pub const AI_NUMERICSERV: c_int = 0x00000008; pub const AI_MASK: c_int = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG; pub const AI_ALL: c_int = 0x00000100; pub const AI_V4MAPPED_CFG: c_int = 0x00000200; pub const AI_ADDRCONFIG: c_int = 0x00000400; pub const AI_V4MAPPED: c_int = 0x00000800; pub const AI_DEFAULT: c_int = AI_V4MAPPED_CFG | AI_ADDRCONFIG; // linux/kexec.h pub const KEXEC_ON_CRASH: c_int = 0x00000001; pub const KEXEC_PRESERVE_CONTEXT: c_int = 0x00000002; pub const KEXEC_ARCH_MASK: c_int = 0xffff0000; pub const KEXEC_FILE_UNLOAD: c_int = 0x00000001; pub const KEXEC_FILE_ON_CRASH: c_int = 0x00000002; pub const KEXEC_FILE_NO_INITRAMFS: c_int = 0x00000004; pub const LINUX_REBOOT_MAGIC1: c_int = 0xfee1dead; pub const LINUX_REBOOT_MAGIC2: c_int = 672274793; pub const LINUX_REBOOT_MAGIC2A: c_int = 85072278; pub const LINUX_REBOOT_MAGIC2B: c_int = 369367448; pub const LINUX_REBOOT_MAGIC2C: c_int = 537993216; pub const LINUX_REBOOT_CMD_RESTART: c_int = 0x01234567; pub const LINUX_REBOOT_CMD_HALT: c_int = 0xCDEF0123; pub const LINUX_REBOOT_CMD_CAD_ON: c_int = 0x89ABCDEF; pub const LINUX_REBOOT_CMD_CAD_OFF: c_int = 0x00000000; pub const LINUX_REBOOT_CMD_POWER_OFF: c_int = 0x4321FEDC; pub const LINUX_REBOOT_CMD_RESTART2: c_int = 0xA1B2C3D4; pub const LINUX_REBOOT_CMD_SW_SUSPEND: c_int = 0xD000FCE2; pub const LINUX_REBOOT_CMD_KEXEC: c_int = 0x45584543; pub const REG_BASIC: c_int = 0; pub const REG_EXTENDED: c_int = 1; pub const REG_ICASE: c_int = 2; pub const REG_NOSUB: c_int = 4; pub const REG_NEWLINE: c_int = 8; pub const REG_NOSPEC: c_int = 16; pub const REG_PEND: c_int = 32; pub const REG_DUMP: c_int = 128; pub const REG_NOMATCH: c_int = 1; pub const REG_BADPAT: c_int = 2; pub const REG_ECOLLATE: c_int = 3; pub const REG_ECTYPE: c_int = 4; pub const REG_EESCAPE: c_int = 5; pub const REG_ESUBREG: c_int = 6; pub const REG_EBRACK: c_int = 7; pub const REG_EPAREN: c_int = 8; pub const REG_EBRACE: c_int = 9; pub const REG_BADBR: c_int = 10; pub const REG_ERANGE: c_int = 11; pub const REG_ESPACE: c_int = 12; pub const REG_BADRPT: c_int = 13; pub const REG_EMPTY: c_int = 14; pub const REG_ASSERT: c_int = 15; pub const REG_INVARG: c_int = 16; pub const REG_ATOI: c_int = 255; pub const REG_ITOA: c_int = 256; pub const REG_NOTBOL: c_int = 1; pub const REG_NOTEOL: c_int = 2; pub const REG_STARTEND: c_int = 4; pub const REG_TRACE: c_int = 256; pub const REG_LARGE: c_int = 512; pub const REG_BACKR: c_int = 1024; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const BOTHER: crate::speed_t = 0o010000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const IBSHIFT: crate::tcflag_t = 16; pub const BLKIOMIN: c_int = 0x1278; pub const BLKIOOPT: c_int = 0x1279; pub const BLKSSZGET: c_int = 0x1268; pub const BLKPBSZGET: c_int = 0x127B; cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(any(target_arch = "x86", target_arch = "arm"))] { pub const FS_IOC_GETFLAGS: c_int = 0x80046601; pub const FS_IOC_SETFLAGS: c_int = 0x40046602; pub const FS_IOC_GETVERSION: c_int = 0x80047601; pub const FS_IOC_SETVERSION: c_int = 0x40047602; pub const FS_IOC32_GETFLAGS: c_int = 0x80046601; pub const FS_IOC32_SETFLAGS: c_int = 0x40046602; pub const FS_IOC32_GETVERSION: c_int = 0x80047601; pub const FS_IOC32_SETVERSION: c_int = 0x40047602; } else if #[cfg(any( target_arch = "x86_64", target_arch = "riscv64", target_arch = "aarch64" ))] { pub const FS_IOC_GETFLAGS: c_int = 0x80086601; pub const FS_IOC_SETFLAGS: c_int = 0x40086602; pub const FS_IOC_GETVERSION: c_int = 0x80087601; pub const FS_IOC_SETVERSION: c_int = 0x40087602; pub const FS_IOC32_GETFLAGS: c_int = 0x80046601; pub const FS_IOC32_SETFLAGS: c_int = 0x40046602; pub const FS_IOC32_GETVERSION: c_int = 0x80047601; pub const FS_IOC32_SETVERSION: c_int = 0x40047602; } } pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_MEMORY: c_int = 6; pub const EAI_NODATA: c_int = 7; pub const EAI_NONAME: c_int = 8; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 14; pub const NETLINK_ROUTE: c_int = 0; pub const NETLINK_UNUSED: c_int = 1; pub const NETLINK_USERSOCK: c_int = 2; pub const NETLINK_FIREWALL: c_int = 3; pub const NETLINK_SOCK_DIAG: c_int = 4; pub const NETLINK_NFLOG: c_int = 5; pub const NETLINK_XFRM: c_int = 6; pub const NETLINK_SELINUX: c_int = 7; pub const NETLINK_ISCSI: c_int = 8; pub const NETLINK_AUDIT: c_int = 9; pub const NETLINK_FIB_LOOKUP: c_int = 10; pub const NETLINK_CONNECTOR: c_int = 11; pub const NETLINK_NETFILTER: c_int = 12; pub const NETLINK_IP6_FW: c_int = 13; pub const NETLINK_DNRTMSG: c_int = 14; pub const NETLINK_KOBJECT_UEVENT: c_int = 15; pub const NETLINK_GENERIC: c_int = 16; pub const NETLINK_SCSITRANSPORT: c_int = 18; pub const NETLINK_ECRYPTFS: c_int = 19; pub const NETLINK_RDMA: c_int = 20; pub const NETLINK_CRYPTO: c_int = 21; pub const NETLINK_INET_DIAG: c_int = NETLINK_SOCK_DIAG; pub const MAX_LINKS: c_int = 32; pub const NLM_F_REQUEST: c_int = 1; pub const NLM_F_MULTI: c_int = 2; pub const NLM_F_ACK: c_int = 4; pub const NLM_F_ECHO: c_int = 8; pub const NLM_F_DUMP_INTR: c_int = 16; pub const NLM_F_DUMP_FILTERED: c_int = 32; pub const NLM_F_ROOT: c_int = 0x100; pub const NLM_F_MATCH: c_int = 0x200; pub const NLM_F_ATOMIC: c_int = 0x400; pub const NLM_F_DUMP: c_int = NLM_F_ROOT | NLM_F_MATCH; pub const NLM_F_REPLACE: c_int = 0x100; pub const NLM_F_EXCL: c_int = 0x200; pub const NLM_F_CREATE: c_int = 0x400; pub const NLM_F_APPEND: c_int = 0x800; pub const NLM_F_NONREC: c_int = 0x100; pub const NLM_F_BULK: c_int = 0x200; pub const NLM_F_CAPPED: c_int = 0x100; pub const NLM_F_ACK_TLVS: c_int = 0x200; pub const NLMSG_NOOP: c_int = 0x1; pub const NLMSG_ERROR: c_int = 0x2; pub const NLMSG_DONE: c_int = 0x3; pub const NLMSG_OVERRUN: c_int = 0x4; pub const NLMSG_MIN_TYPE: c_int = 0x10; // linux/netfilter/nfnetlink.h pub const NFNLGRP_NONE: c_int = 0; pub const NFNLGRP_CONNTRACK_NEW: c_int = 1; pub const NFNLGRP_CONNTRACK_UPDATE: c_int = 2; pub const NFNLGRP_CONNTRACK_DESTROY: c_int = 3; pub const NFNLGRP_CONNTRACK_EXP_NEW: c_int = 4; pub const NFNLGRP_CONNTRACK_EXP_UPDATE: c_int = 5; pub const NFNLGRP_CONNTRACK_EXP_DESTROY: c_int = 6; pub const NFNLGRP_NFTABLES: c_int = 7; pub const NFNLGRP_ACCT_QUOTA: c_int = 8; pub const NFNETLINK_V0: c_int = 0; pub const NFNL_SUBSYS_NONE: c_int = 0; pub const NFNL_SUBSYS_CTNETLINK: c_int = 1; pub const NFNL_SUBSYS_CTNETLINK_EXP: c_int = 2; pub const NFNL_SUBSYS_QUEUE: c_int = 3; pub const NFNL_SUBSYS_ULOG: c_int = 4; pub const NFNL_SUBSYS_OSF: c_int = 5; pub const NFNL_SUBSYS_IPSET: c_int = 6; pub const NFNL_SUBSYS_ACCT: c_int = 7; pub const NFNL_SUBSYS_CTNETLINK_TIMEOUT: c_int = 8; pub const NFNL_SUBSYS_CTHELPER: c_int = 9; pub const NFNL_SUBSYS_NFTABLES: c_int = 10; pub const NFNL_SUBSYS_NFT_COMPAT: c_int = 11; pub const NFNL_SUBSYS_COUNT: c_int = 12; pub const NFNL_MSG_BATCH_BEGIN: c_int = NLMSG_MIN_TYPE; pub const NFNL_MSG_BATCH_END: c_int = NLMSG_MIN_TYPE + 1; // linux/netfilter/nfnetlink_log.h pub const NFULNL_MSG_PACKET: c_int = 0; pub const NFULNL_MSG_CONFIG: c_int = 1; pub const NFULA_UNSPEC: c_int = 0; pub const NFULA_PACKET_HDR: c_int = 1; pub const NFULA_MARK: c_int = 2; pub const NFULA_TIMESTAMP: c_int = 3; pub const NFULA_IFINDEX_INDEV: c_int = 4; pub const NFULA_IFINDEX_OUTDEV: c_int = 5; pub const NFULA_IFINDEX_PHYSINDEV: c_int = 6; pub const NFULA_IFINDEX_PHYSOUTDEV: c_int = 7; pub const NFULA_HWADDR: c_int = 8; pub const NFULA_PAYLOAD: c_int = 9; pub const NFULA_PREFIX: c_int = 10; pub const NFULA_UID: c_int = 11; pub const NFULA_SEQ: c_int = 12; pub const NFULA_SEQ_GLOBAL: c_int = 13; pub const NFULA_GID: c_int = 14; pub const NFULA_HWTYPE: c_int = 15; pub const NFULA_HWHEADER: c_int = 16; pub const NFULA_HWLEN: c_int = 17; pub const NFULA_CT: c_int = 18; pub const NFULA_CT_INFO: c_int = 19; pub const NFULNL_CFG_CMD_NONE: c_int = 0; pub const NFULNL_CFG_CMD_BIND: c_int = 1; pub const NFULNL_CFG_CMD_UNBIND: c_int = 2; pub const NFULNL_CFG_CMD_PF_BIND: c_int = 3; pub const NFULNL_CFG_CMD_PF_UNBIND: c_int = 4; pub const NFULA_CFG_UNSPEC: c_int = 0; pub const NFULA_CFG_CMD: c_int = 1; pub const NFULA_CFG_MODE: c_int = 2; pub const NFULA_CFG_NLBUFSIZ: c_int = 3; pub const NFULA_CFG_TIMEOUT: c_int = 4; pub const NFULA_CFG_QTHRESH: c_int = 5; pub const NFULA_CFG_FLAGS: c_int = 6; pub const NFULNL_COPY_NONE: c_int = 0x00; pub const NFULNL_COPY_META: c_int = 0x01; pub const NFULNL_COPY_PACKET: c_int = 0x02; pub const NFULNL_CFG_F_SEQ: c_int = 0x0001; pub const NFULNL_CFG_F_SEQ_GLOBAL: c_int = 0x0002; pub const NFULNL_CFG_F_CONNTRACK: c_int = 0x0004; // linux/netfilter/nfnetlink_log.h pub const NFQNL_MSG_PACKET: c_int = 0; pub const NFQNL_MSG_VERDICT: c_int = 1; pub const NFQNL_MSG_CONFIG: c_int = 2; pub const NFQNL_MSG_VERDICT_BATCH: c_int = 3; pub const NFQA_UNSPEC: c_int = 0; pub const NFQA_PACKET_HDR: c_int = 1; pub const NFQA_VERDICT_HDR: c_int = 2; pub const NFQA_MARK: c_int = 3; pub const NFQA_TIMESTAMP: c_int = 4; pub const NFQA_IFINDEX_INDEV: c_int = 5; pub const NFQA_IFINDEX_OUTDEV: c_int = 6; pub const NFQA_IFINDEX_PHYSINDEV: c_int = 7; pub const NFQA_IFINDEX_PHYSOUTDEV: c_int = 8; pub const NFQA_HWADDR: c_int = 9; pub const NFQA_PAYLOAD: c_int = 10; pub const NFQA_CT: c_int = 11; pub const NFQA_CT_INFO: c_int = 12; pub const NFQA_CAP_LEN: c_int = 13; pub const NFQA_SKB_INFO: c_int = 14; pub const NFQA_EXP: c_int = 15; pub const NFQA_UID: c_int = 16; pub const NFQA_GID: c_int = 17; pub const NFQA_SECCTX: c_int = 18; /* FIXME: These are not yet available in musl sanitized kernel headers and make the tests fail. Enable them once musl has them. See https://github.com/rust-lang/libc/pull/1628 for more details. pub const NFQA_VLAN: c_int = 19; pub const NFQA_L2HDR: c_int = 20; pub const NFQA_VLAN_UNSPEC: c_int = 0; pub const NFQA_VLAN_PROTO: c_int = 1; pub const NFQA_VLAN_TCI: c_int = 2; */ pub const NFQNL_CFG_CMD_NONE: c_int = 0; pub const NFQNL_CFG_CMD_BIND: c_int = 1; pub const NFQNL_CFG_CMD_UNBIND: c_int = 2; pub const NFQNL_CFG_CMD_PF_BIND: c_int = 3; pub const NFQNL_CFG_CMD_PF_UNBIND: c_int = 4; pub const NFQNL_COPY_NONE: c_int = 0; pub const NFQNL_COPY_META: c_int = 1; pub const NFQNL_COPY_PACKET: c_int = 2; pub const NFQA_CFG_UNSPEC: c_int = 0; pub const NFQA_CFG_CMD: c_int = 1; pub const NFQA_CFG_PARAMS: c_int = 2; pub const NFQA_CFG_QUEUE_MAXLEN: c_int = 3; pub const NFQA_CFG_MASK: c_int = 4; pub const NFQA_CFG_FLAGS: c_int = 5; pub const NFQA_CFG_F_FAIL_OPEN: c_int = 0x0001; pub const NFQA_CFG_F_CONNTRACK: c_int = 0x0002; pub const NFQA_CFG_F_GSO: c_int = 0x0004; pub const NFQA_CFG_F_UID_GID: c_int = 0x0008; pub const NFQA_CFG_F_SECCTX: c_int = 0x0010; pub const NFQA_CFG_F_MAX: c_int = 0x0020; pub const NFQA_SKB_CSUMNOTREADY: c_int = 0x0001; pub const NFQA_SKB_GSO: c_int = 0x0002; pub const NFQA_SKB_CSUM_NOTVERIFIED: c_int = 0x0004; pub const GENL_NAMSIZ: c_int = 16; pub const GENL_MIN_ID: c_int = NLMSG_MIN_TYPE; pub const GENL_MAX_ID: c_int = 1023; pub const GENL_ADMIN_PERM: c_int = 0x01; pub const GENL_CMD_CAP_DO: c_int = 0x02; pub const GENL_CMD_CAP_DUMP: c_int = 0x04; pub const GENL_CMD_CAP_HASPOL: c_int = 0x08; pub const GENL_UNS_ADMIN_PERM: c_int = 0x10; pub const GENL_ID_CTRL: c_int = NLMSG_MIN_TYPE; pub const GENL_ID_VFS_DQUOT: c_int = NLMSG_MIN_TYPE + 1; pub const GENL_ID_PMCRAID: c_int = NLMSG_MIN_TYPE + 2; pub const CTRL_CMD_UNSPEC: c_int = 0; pub const CTRL_CMD_NEWFAMILY: c_int = 1; pub const CTRL_CMD_DELFAMILY: c_int = 2; pub const CTRL_CMD_GETFAMILY: c_int = 3; pub const CTRL_CMD_NEWOPS: c_int = 4; pub const CTRL_CMD_DELOPS: c_int = 5; pub const CTRL_CMD_GETOPS: c_int = 6; pub const CTRL_CMD_NEWMCAST_GRP: c_int = 7; pub const CTRL_CMD_DELMCAST_GRP: c_int = 8; pub const CTRL_CMD_GETMCAST_GRP: c_int = 9; pub const CTRL_ATTR_UNSPEC: c_int = 0; pub const CTRL_ATTR_FAMILY_ID: c_int = 1; pub const CTRL_ATTR_FAMILY_NAME: c_int = 2; pub const CTRL_ATTR_VERSION: c_int = 3; pub const CTRL_ATTR_HDRSIZE: c_int = 4; pub const CTRL_ATTR_MAXATTR: c_int = 5; pub const CTRL_ATTR_OPS: c_int = 6; pub const CTRL_ATTR_MCAST_GROUPS: c_int = 7; pub const CTRL_ATTR_OP_UNSPEC: c_int = 0; pub const CTRL_ATTR_OP_ID: c_int = 1; pub const CTRL_ATTR_OP_FLAGS: c_int = 2; pub const CTRL_ATTR_MCAST_GRP_UNSPEC: c_int = 0; pub const CTRL_ATTR_MCAST_GRP_NAME: c_int = 1; pub const CTRL_ATTR_MCAST_GRP_ID: c_int = 2; pub const NETLINK_ADD_MEMBERSHIP: c_int = 1; pub const NETLINK_DROP_MEMBERSHIP: c_int = 2; pub const NETLINK_PKTINFO: c_int = 3; pub const NETLINK_BROADCAST_ERROR: c_int = 4; pub const NETLINK_NO_ENOBUFS: c_int = 5; pub const NETLINK_RX_RING: c_int = 6; pub const NETLINK_TX_RING: c_int = 7; pub const NETLINK_LISTEN_ALL_NSID: c_int = 8; pub const NETLINK_LIST_MEMBERSHIPS: c_int = 9; pub const NETLINK_CAP_ACK: c_int = 10; pub const NETLINK_EXT_ACK: c_int = 11; pub const NETLINK_GET_STRICT_CHK: c_int = 12; pub const GRND_NONBLOCK: c_uint = 0x0001; pub const GRND_RANDOM: c_uint = 0x0002; pub const GRND_INSECURE: c_uint = 0x0004; // pub const SECCOMP_MODE_DISABLED: c_uint = 0; pub const SECCOMP_MODE_STRICT: c_uint = 1; pub const SECCOMP_MODE_FILTER: c_uint = 2; pub const SECCOMP_SET_MODE_STRICT: c_uint = 0; pub const SECCOMP_SET_MODE_FILTER: c_uint = 1; pub const SECCOMP_GET_ACTION_AVAIL: c_uint = 2; pub const SECCOMP_GET_NOTIF_SIZES: c_uint = 3; pub const SECCOMP_FILTER_FLAG_TSYNC: c_ulong = 1 << 0; pub const SECCOMP_FILTER_FLAG_LOG: c_ulong = 1 << 1; pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: c_ulong = 1 << 2; pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: c_ulong = 1 << 3; pub const SECCOMP_FILTER_FLAG_TSYNC_ESRCH: c_ulong = 1 << 4; pub const SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV: c_ulong = 1 << 5; pub const SECCOMP_RET_KILL_PROCESS: c_uint = 0x80000000; pub const SECCOMP_RET_KILL_THREAD: c_uint = 0x00000000; pub const SECCOMP_RET_KILL: c_uint = SECCOMP_RET_KILL_THREAD; pub const SECCOMP_RET_TRAP: c_uint = 0x00030000; pub const SECCOMP_RET_ERRNO: c_uint = 0x00050000; pub const SECCOMP_RET_USER_NOTIF: c_uint = 0x7fc00000; pub const SECCOMP_RET_TRACE: c_uint = 0x7ff00000; pub const SECCOMP_RET_LOG: c_uint = 0x7ffc0000; pub const SECCOMP_RET_ALLOW: c_uint = 0x7fff0000; pub const SECCOMP_RET_ACTION_FULL: c_uint = 0xffff0000; pub const SECCOMP_RET_ACTION: c_uint = 0x7fff0000; pub const SECCOMP_RET_DATA: c_uint = 0x0000ffff; pub const SECCOMP_USER_NOTIF_FLAG_CONTINUE: c_ulong = 1; pub const SECCOMP_ADDFD_FLAG_SETFD: c_ulong = 1; pub const SECCOMP_ADDFD_FLAG_SEND: c_ulong = 2; pub const NLA_F_NESTED: c_int = 1 << 15; pub const NLA_F_NET_BYTEORDER: c_int = 1 << 14; pub const NLA_TYPE_MASK: c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER); pub const NLA_ALIGNTO: c_int = 4; pub const SIGEV_THREAD_ID: c_int = 4; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const TIOCM_LE: c_int = 0x001; pub const TIOCM_DTR: c_int = 0x002; pub const TIOCM_RTS: c_int = 0x004; pub const TIOCM_ST: c_int = 0x008; pub const TIOCM_SR: c_int = 0x010; pub const TIOCM_CTS: c_int = 0x020; pub const TIOCM_CAR: c_int = 0x040; pub const TIOCM_RNG: c_int = 0x080; pub const TIOCM_DSR: c_int = 0x100; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const SFD_CLOEXEC: c_int = O_CLOEXEC; pub const SFD_NONBLOCK: c_int = O_NONBLOCK; pub const SOCK_NONBLOCK: c_int = O_NONBLOCK; pub const SO_ORIGINAL_DST: c_int = 80; pub const IP_RECVFRAGSIZE: c_int = 25; pub const IPV6_FLOWINFO: c_int = 11; pub const IPV6_MULTICAST_ALL: c_int = 29; pub const IPV6_ROUTER_ALERT_ISOLATE: c_int = 30; pub const IPV6_FLOWLABEL_MGR: c_int = 32; pub const IPV6_FLOWINFO_SEND: c_int = 33; pub const IPV6_RECVFRAGSIZE: c_int = 77; pub const IPV6_FREEBIND: c_int = 78; pub const IPV6_FLOWINFO_FLOWLABEL: c_int = 0x000fffff; pub const IPV6_FLOWINFO_PRIORITY: c_int = 0x0ff00000; pub const IUTF8: crate::tcflag_t = 0x00004000; pub const CMSPAR: crate::tcflag_t = 0o10000000000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const MFD_CLOEXEC: c_uint = 0x0001; pub const MFD_ALLOW_SEALING: c_uint = 0x0002; pub const MFD_HUGETLB: c_uint = 0x0004; pub const MFD_NOEXEC_SEAL: c_uint = 0x0008; pub const MFD_EXEC: c_uint = 0x0010; pub const MFD_HUGE_64KB: c_uint = 0x40000000; pub const MFD_HUGE_512KB: c_uint = 0x4c000000; pub const MFD_HUGE_1MB: c_uint = 0x50000000; pub const MFD_HUGE_2MB: c_uint = 0x54000000; pub const MFD_HUGE_8MB: c_uint = 0x5c000000; pub const MFD_HUGE_16MB: c_uint = 0x60000000; pub const MFD_HUGE_32MB: c_uint = 0x64000000; pub const MFD_HUGE_256MB: c_uint = 0x70000000; pub const MFD_HUGE_512MB: c_uint = 0x74000000; pub const MFD_HUGE_1GB: c_uint = 0x78000000; pub const MFD_HUGE_2GB: c_uint = 0x7c000000; pub const MFD_HUGE_16GB: c_uint = 0x88000000; pub const MFD_HUGE_MASK: c_uint = 63; pub const MFD_HUGE_SHIFT: c_uint = 26; // these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has // the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32 // so we can use that type here to avoid having to cast. pub const PT_NULL: u32 = 0; pub const PT_LOAD: u32 = 1; pub const PT_DYNAMIC: u32 = 2; pub const PT_INTERP: u32 = 3; pub const PT_NOTE: u32 = 4; pub const PT_SHLIB: u32 = 5; pub const PT_PHDR: u32 = 6; pub const PT_TLS: u32 = 7; pub const PT_LOOS: u32 = 0x60000000; pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; pub const PT_GNU_STACK: u32 = 0x6474e551; pub const PT_GNU_RELRO: u32 = 0x6474e552; pub const PT_HIOS: u32 = 0x6fffffff; pub const PT_LOPROC: u32 = 0x70000000; pub const PT_HIPROC: u32 = 0x7fffffff; // uapi/linux/mount.h pub const OPEN_TREE_CLONE: c_uint = 0x01; pub const OPEN_TREE_CLOEXEC: c_uint = O_CLOEXEC as c_uint; // linux/netfilter.h pub const NF_DROP: c_int = 0; pub const NF_ACCEPT: c_int = 1; pub const NF_STOLEN: c_int = 2; pub const NF_QUEUE: c_int = 3; pub const NF_REPEAT: c_int = 4; pub const NF_STOP: c_int = 5; pub const NF_MAX_VERDICT: c_int = NF_STOP; pub const NF_VERDICT_MASK: c_int = 0x000000ff; pub const NF_VERDICT_FLAG_QUEUE_BYPASS: c_int = 0x00008000; pub const NF_VERDICT_QMASK: c_int = 0xffff0000; pub const NF_VERDICT_QBITS: c_int = 16; pub const NF_VERDICT_BITS: c_int = 16; pub const NF_INET_PRE_ROUTING: c_int = 0; pub const NF_INET_LOCAL_IN: c_int = 1; pub const NF_INET_FORWARD: c_int = 2; pub const NF_INET_LOCAL_OUT: c_int = 3; pub const NF_INET_POST_ROUTING: c_int = 4; pub const NF_INET_NUMHOOKS: c_int = 5; pub const NF_INET_INGRESS: c_int = NF_INET_NUMHOOKS; pub const NF_NETDEV_INGRESS: c_int = 0; pub const NF_NETDEV_EGRESS: c_int = 1; pub const NF_NETDEV_NUMHOOKS: c_int = 2; pub const NFPROTO_UNSPEC: c_int = 0; pub const NFPROTO_INET: c_int = 1; pub const NFPROTO_IPV4: c_int = 2; pub const NFPROTO_ARP: c_int = 3; pub const NFPROTO_NETDEV: c_int = 5; pub const NFPROTO_BRIDGE: c_int = 7; pub const NFPROTO_IPV6: c_int = 10; pub const NFPROTO_DECNET: c_int = 12; pub const NFPROTO_NUMPROTO: c_int = 13; // linux/netfilter_arp.h pub const NF_ARP: c_int = 0; pub const NF_ARP_IN: c_int = 0; pub const NF_ARP_OUT: c_int = 1; pub const NF_ARP_FORWARD: c_int = 2; pub const NF_ARP_NUMHOOKS: c_int = 3; // linux/netfilter_bridge.h pub const NF_BR_PRE_ROUTING: c_int = 0; pub const NF_BR_LOCAL_IN: c_int = 1; pub const NF_BR_FORWARD: c_int = 2; pub const NF_BR_LOCAL_OUT: c_int = 3; pub const NF_BR_POST_ROUTING: c_int = 4; pub const NF_BR_BROUTING: c_int = 5; pub const NF_BR_NUMHOOKS: c_int = 6; pub const NF_BR_PRI_FIRST: c_int = crate::INT_MIN; pub const NF_BR_PRI_NAT_DST_BRIDGED: c_int = -300; pub const NF_BR_PRI_FILTER_BRIDGED: c_int = -200; pub const NF_BR_PRI_BRNF: c_int = 0; pub const NF_BR_PRI_NAT_DST_OTHER: c_int = 100; pub const NF_BR_PRI_FILTER_OTHER: c_int = 200; pub const NF_BR_PRI_NAT_SRC: c_int = 300; pub const NF_BR_PRI_LAST: c_int = crate::INT_MAX; // linux/netfilter_ipv4.h pub const NF_IP_PRE_ROUTING: c_int = 0; pub const NF_IP_LOCAL_IN: c_int = 1; pub const NF_IP_FORWARD: c_int = 2; pub const NF_IP_LOCAL_OUT: c_int = 3; pub const NF_IP_POST_ROUTING: c_int = 4; pub const NF_IP_NUMHOOKS: c_int = 5; pub const NF_IP_PRI_FIRST: c_int = crate::INT_MIN; pub const NF_IP_PRI_RAW_BEFORE_DEFRAG: c_int = -450; pub const NF_IP_PRI_CONNTRACK_DEFRAG: c_int = -400; pub const NF_IP_PRI_RAW: c_int = -300; pub const NF_IP_PRI_SELINUX_FIRST: c_int = -225; pub const NF_IP_PRI_CONNTRACK: c_int = -200; pub const NF_IP_PRI_MANGLE: c_int = -150; pub const NF_IP_PRI_NAT_DST: c_int = -100; pub const NF_IP_PRI_FILTER: c_int = 0; pub const NF_IP_PRI_SECURITY: c_int = 50; pub const NF_IP_PRI_NAT_SRC: c_int = 100; pub const NF_IP_PRI_SELINUX_LAST: c_int = 225; pub const NF_IP_PRI_CONNTRACK_HELPER: c_int = 300; pub const NF_IP_PRI_CONNTRACK_CONFIRM: c_int = crate::INT_MAX; pub const NF_IP_PRI_LAST: c_int = crate::INT_MAX; // linux/netfilter_ipv6.h pub const NF_IP6_PRE_ROUTING: c_int = 0; pub const NF_IP6_LOCAL_IN: c_int = 1; pub const NF_IP6_FORWARD: c_int = 2; pub const NF_IP6_LOCAL_OUT: c_int = 3; pub const NF_IP6_POST_ROUTING: c_int = 4; pub const NF_IP6_NUMHOOKS: c_int = 5; pub const NF_IP6_PRI_FIRST: c_int = crate::INT_MIN; pub const NF_IP6_PRI_RAW_BEFORE_DEFRAG: c_int = -450; pub const NF_IP6_PRI_CONNTRACK_DEFRAG: c_int = -400; pub const NF_IP6_PRI_RAW: c_int = -300; pub const NF_IP6_PRI_SELINUX_FIRST: c_int = -225; pub const NF_IP6_PRI_CONNTRACK: c_int = -200; pub const NF_IP6_PRI_MANGLE: c_int = -150; pub const NF_IP6_PRI_NAT_DST: c_int = -100; pub const NF_IP6_PRI_FILTER: c_int = 0; pub const NF_IP6_PRI_SECURITY: c_int = 50; pub const NF_IP6_PRI_NAT_SRC: c_int = 100; pub const NF_IP6_PRI_SELINUX_LAST: c_int = 225; pub const NF_IP6_PRI_CONNTRACK_HELPER: c_int = 300; pub const NF_IP6_PRI_LAST: c_int = crate::INT_MAX; // linux/netfilter_ipv6/ip6_tables.h pub const IP6T_SO_ORIGINAL_DST: c_int = 80; // linux/netfilter/nf_tables.h pub const NFT_TABLE_MAXNAMELEN: c_int = 256; pub const NFT_CHAIN_MAXNAMELEN: c_int = 256; pub const NFT_SET_MAXNAMELEN: c_int = 256; pub const NFT_OBJ_MAXNAMELEN: c_int = 256; pub const NFT_USERDATA_MAXLEN: c_int = 256; pub const NFT_REG_VERDICT: c_int = 0; pub const NFT_REG_1: c_int = 1; pub const NFT_REG_2: c_int = 2; pub const NFT_REG_3: c_int = 3; pub const NFT_REG_4: c_int = 4; pub const __NFT_REG_MAX: c_int = 5; pub const NFT_REG32_00: c_int = 8; pub const NFT_REG32_01: c_int = 9; pub const NFT_REG32_02: c_int = 10; pub const NFT_REG32_03: c_int = 11; pub const NFT_REG32_04: c_int = 12; pub const NFT_REG32_05: c_int = 13; pub const NFT_REG32_06: c_int = 14; pub const NFT_REG32_07: c_int = 15; pub const NFT_REG32_08: c_int = 16; pub const NFT_REG32_09: c_int = 17; pub const NFT_REG32_10: c_int = 18; pub const NFT_REG32_11: c_int = 19; pub const NFT_REG32_12: c_int = 20; pub const NFT_REG32_13: c_int = 21; pub const NFT_REG32_14: c_int = 22; pub const NFT_REG32_15: c_int = 23; pub const NFT_REG_SIZE: c_int = 16; pub const NFT_REG32_SIZE: c_int = 4; pub const NFT_CONTINUE: c_int = -1; pub const NFT_BREAK: c_int = -2; pub const NFT_JUMP: c_int = -3; pub const NFT_GOTO: c_int = -4; pub const NFT_RETURN: c_int = -5; pub const NFT_MSG_NEWTABLE: c_int = 0; pub const NFT_MSG_GETTABLE: c_int = 1; pub const NFT_MSG_DELTABLE: c_int = 2; pub const NFT_MSG_NEWCHAIN: c_int = 3; pub const NFT_MSG_GETCHAIN: c_int = 4; pub const NFT_MSG_DELCHAIN: c_int = 5; pub const NFT_MSG_NEWRULE: c_int = 6; pub const NFT_MSG_GETRULE: c_int = 7; pub const NFT_MSG_DELRULE: c_int = 8; pub const NFT_MSG_NEWSET: c_int = 9; pub const NFT_MSG_GETSET: c_int = 10; pub const NFT_MSG_DELSET: c_int = 11; pub const NFT_MSG_NEWSETELEM: c_int = 12; pub const NFT_MSG_GETSETELEM: c_int = 13; pub const NFT_MSG_DELSETELEM: c_int = 14; pub const NFT_MSG_NEWGEN: c_int = 15; pub const NFT_MSG_GETGEN: c_int = 16; pub const NFT_MSG_TRACE: c_int = 17; pub const NFT_MSG_NEWOBJ: c_int = 18; pub const NFT_MSG_GETOBJ: c_int = 19; pub const NFT_MSG_DELOBJ: c_int = 20; pub const NFT_MSG_GETOBJ_RESET: c_int = 21; pub const NFT_MSG_MAX: c_int = 25; pub const NFT_SET_ANONYMOUS: c_int = 0x1; pub const NFT_SET_CONSTANT: c_int = 0x2; pub const NFT_SET_INTERVAL: c_int = 0x4; pub const NFT_SET_MAP: c_int = 0x8; pub const NFT_SET_TIMEOUT: c_int = 0x10; pub const NFT_SET_EVAL: c_int = 0x20; pub const NFT_SET_POL_PERFORMANCE: c_int = 0; pub const NFT_SET_POL_MEMORY: c_int = 1; pub const NFT_SET_ELEM_INTERVAL_END: c_int = 0x1; pub const NFT_DATA_VALUE: c_uint = 0; pub const NFT_DATA_VERDICT: c_uint = 0xffffff00; pub const NFT_DATA_RESERVED_MASK: c_uint = 0xffffff00; pub const NFT_DATA_VALUE_MAXLEN: c_int = 64; pub const NFT_BYTEORDER_NTOH: c_int = 0; pub const NFT_BYTEORDER_HTON: c_int = 1; pub const NFT_CMP_EQ: c_int = 0; pub const NFT_CMP_NEQ: c_int = 1; pub const NFT_CMP_LT: c_int = 2; pub const NFT_CMP_LTE: c_int = 3; pub const NFT_CMP_GT: c_int = 4; pub const NFT_CMP_GTE: c_int = 5; pub const NFT_RANGE_EQ: c_int = 0; pub const NFT_RANGE_NEQ: c_int = 1; pub const NFT_LOOKUP_F_INV: c_int = 1 << 0; pub const NFT_DYNSET_OP_ADD: c_int = 0; pub const NFT_DYNSET_OP_UPDATE: c_int = 1; pub const NFT_DYNSET_F_INV: c_int = 1 << 0; pub const NFT_PAYLOAD_LL_HEADER: c_int = 0; pub const NFT_PAYLOAD_NETWORK_HEADER: c_int = 1; pub const NFT_PAYLOAD_TRANSPORT_HEADER: c_int = 2; pub const NFT_PAYLOAD_CSUM_NONE: c_int = 0; pub const NFT_PAYLOAD_CSUM_INET: c_int = 1; pub const NFT_META_LEN: c_int = 0; pub const NFT_META_PROTOCOL: c_int = 1; pub const NFT_META_PRIORITY: c_int = 2; pub const NFT_META_MARK: c_int = 3; pub const NFT_META_IIF: c_int = 4; pub const NFT_META_OIF: c_int = 5; pub const NFT_META_IIFNAME: c_int = 6; pub const NFT_META_OIFNAME: c_int = 7; pub const NFT_META_IIFTYPE: c_int = 8; pub const NFT_META_OIFTYPE: c_int = 9; pub const NFT_META_SKUID: c_int = 10; pub const NFT_META_SKGID: c_int = 11; pub const NFT_META_NFTRACE: c_int = 12; pub const NFT_META_RTCLASSID: c_int = 13; pub const NFT_META_SECMARK: c_int = 14; pub const NFT_META_NFPROTO: c_int = 15; pub const NFT_META_L4PROTO: c_int = 16; pub const NFT_META_BRI_IIFNAME: c_int = 17; pub const NFT_META_BRI_OIFNAME: c_int = 18; pub const NFT_META_PKTTYPE: c_int = 19; pub const NFT_META_CPU: c_int = 20; pub const NFT_META_IIFGROUP: c_int = 21; pub const NFT_META_OIFGROUP: c_int = 22; pub const NFT_META_CGROUP: c_int = 23; pub const NFT_META_PRANDOM: c_int = 24; pub const NFT_CT_STATE: c_int = 0; pub const NFT_CT_DIRECTION: c_int = 1; pub const NFT_CT_STATUS: c_int = 2; pub const NFT_CT_MARK: c_int = 3; pub const NFT_CT_SECMARK: c_int = 4; pub const NFT_CT_EXPIRATION: c_int = 5; pub const NFT_CT_HELPER: c_int = 6; pub const NFT_CT_L3PROTOCOL: c_int = 7; pub const NFT_CT_SRC: c_int = 8; pub const NFT_CT_DST: c_int = 9; pub const NFT_CT_PROTOCOL: c_int = 10; pub const NFT_CT_PROTO_SRC: c_int = 11; pub const NFT_CT_PROTO_DST: c_int = 12; pub const NFT_CT_LABELS: c_int = 13; pub const NFT_CT_PKTS: c_int = 14; pub const NFT_CT_BYTES: c_int = 15; pub const NFT_CT_AVGPKT: c_int = 16; pub const NFT_CT_ZONE: c_int = 17; pub const NFT_CT_EVENTMASK: c_int = 18; pub const NFT_CT_SRC_IP: c_int = 19; pub const NFT_CT_DST_IP: c_int = 20; pub const NFT_CT_SRC_IP6: c_int = 21; pub const NFT_CT_DST_IP6: c_int = 22; pub const NFT_CT_ID: c_int = 23; pub const NFT_LIMIT_PKTS: c_int = 0; pub const NFT_LIMIT_PKT_BYTES: c_int = 1; pub const NFT_LIMIT_F_INV: c_int = 1 << 0; pub const NFT_QUEUE_FLAG_BYPASS: c_int = 0x01; pub const NFT_QUEUE_FLAG_CPU_FANOUT: c_int = 0x02; pub const NFT_QUEUE_FLAG_MASK: c_int = 0x03; pub const NFT_QUOTA_F_INV: c_int = 1 << 0; pub const NFT_REJECT_ICMP_UNREACH: c_int = 0; pub const NFT_REJECT_TCP_RST: c_int = 1; pub const NFT_REJECT_ICMPX_UNREACH: c_int = 2; pub const NFT_REJECT_ICMPX_NO_ROUTE: c_int = 0; pub const NFT_REJECT_ICMPX_PORT_UNREACH: c_int = 1; pub const NFT_REJECT_ICMPX_HOST_UNREACH: c_int = 2; pub const NFT_REJECT_ICMPX_ADMIN_PROHIBITED: c_int = 3; pub const NFT_NAT_SNAT: c_int = 0; pub const NFT_NAT_DNAT: c_int = 1; pub const NFT_TRACETYPE_UNSPEC: c_int = 0; pub const NFT_TRACETYPE_POLICY: c_int = 1; pub const NFT_TRACETYPE_RETURN: c_int = 2; pub const NFT_TRACETYPE_RULE: c_int = 3; pub const NFT_NG_INCREMENTAL: c_int = 0; pub const NFT_NG_RANDOM: c_int = 1; // linux/input.h pub const FF_MAX: crate::__u16 = 0x7f; pub const FF_CNT: usize = FF_MAX as usize + 1; // linux/input-event-codes.h pub const INPUT_PROP_MAX: crate::__u16 = 0x1f; pub const INPUT_PROP_CNT: usize = INPUT_PROP_MAX as usize + 1; pub const EV_MAX: crate::__u16 = 0x1f; pub const EV_CNT: usize = EV_MAX as usize + 1; pub const SYN_MAX: crate::__u16 = 0xf; pub const SYN_CNT: usize = SYN_MAX as usize + 1; pub const KEY_MAX: crate::__u16 = 0x2ff; pub const KEY_CNT: usize = KEY_MAX as usize + 1; pub const REL_MAX: crate::__u16 = 0x0f; pub const REL_CNT: usize = REL_MAX as usize + 1; pub const ABS_MAX: crate::__u16 = 0x3f; pub const ABS_CNT: usize = ABS_MAX as usize + 1; pub const SW_MAX: crate::__u16 = 0x0f; pub const SW_CNT: usize = SW_MAX as usize + 1; pub const MSC_MAX: crate::__u16 = 0x07; pub const MSC_CNT: usize = MSC_MAX as usize + 1; pub const LED_MAX: crate::__u16 = 0x0f; pub const LED_CNT: usize = LED_MAX as usize + 1; pub const REP_MAX: crate::__u16 = 0x01; pub const REP_CNT: usize = REP_MAX as usize + 1; pub const SND_MAX: crate::__u16 = 0x07; pub const SND_CNT: usize = SND_MAX as usize + 1; // linux/uinput.h pub const UINPUT_VERSION: c_uint = 5; pub const UINPUT_MAX_NAME_SIZE: usize = 80; // bionic/libc/kernel/uapi/linux/if_tun.h pub const IFF_TUN: c_int = 0x0001; pub const IFF_TAP: c_int = 0x0002; pub const IFF_NAPI: c_int = 0x0010; pub const IFF_NAPI_FRAGS: c_int = 0x0020; pub const IFF_NO_CARRIER: c_int = 0x0040; pub const IFF_NO_PI: c_int = 0x1000; pub const IFF_ONE_QUEUE: c_int = 0x2000; pub const IFF_VNET_HDR: c_int = 0x4000; pub const IFF_TUN_EXCL: c_int = 0x8000; pub const IFF_MULTI_QUEUE: c_int = 0x0100; pub const IFF_ATTACH_QUEUE: c_int = 0x0200; pub const IFF_DETACH_QUEUE: c_int = 0x0400; pub const IFF_PERSIST: c_int = 0x0800; pub const IFF_NOFILTER: c_int = 0x1000; pub const TUN_TX_TIMESTAMP: c_int = 1; // Features for GSO (TUNSETOFFLOAD) pub const TUN_F_CSUM: c_uint = 0x01; pub const TUN_F_TSO4: c_uint = 0x02; pub const TUN_F_TSO6: c_uint = 0x04; pub const TUN_F_TSO_ECN: c_uint = 0x08; pub const TUN_F_UFO: c_uint = 0x10; pub const TUN_F_USO4: c_uint = 0x20; pub const TUN_F_USO6: c_uint = 0x40; // Protocol info prepended to the packets (when IFF_NO_PI is not set) pub const TUN_PKT_STRIP: c_int = 0x0001; // Accept all multicast packets pub const TUN_FLT_ALLMULTI: c_int = 0x0001; // Ioctl operation codes const T_TYPE: u32 = b'T' as u32; pub const TUNSETNOCSUM: c_int = _IOW::(T_TYPE, 200); pub const TUNSETDEBUG: c_int = _IOW::(T_TYPE, 201); pub const TUNSETIFF: c_int = _IOW::(T_TYPE, 202); pub const TUNSETPERSIST: c_int = _IOW::(T_TYPE, 203); pub const TUNSETOWNER: c_int = _IOW::(T_TYPE, 204); pub const TUNSETLINK: c_int = _IOW::(T_TYPE, 205); pub const TUNSETGROUP: c_int = _IOW::(T_TYPE, 206); pub const TUNGETFEATURES: c_int = _IOR::(T_TYPE, 207); pub const TUNSETOFFLOAD: c_int = _IOW::(T_TYPE, 208); pub const TUNSETTXFILTER: c_int = _IOW::(T_TYPE, 209); pub const TUNGETIFF: c_int = _IOR::(T_TYPE, 210); pub const TUNGETSNDBUF: c_int = _IOR::(T_TYPE, 211); pub const TUNSETSNDBUF: c_int = _IOW::(T_TYPE, 212); pub const TUNATTACHFILTER: c_int = _IOW::(T_TYPE, 213); pub const TUNDETACHFILTER: c_int = _IOW::(T_TYPE, 214); pub const TUNGETVNETHDRSZ: c_int = _IOR::(T_TYPE, 215); pub const TUNSETVNETHDRSZ: c_int = _IOW::(T_TYPE, 216); pub const TUNSETQUEUE: c_int = _IOW::(T_TYPE, 217); pub const TUNSETIFINDEX: c_int = _IOW::(T_TYPE, 218); pub const TUNGETFILTER: c_int = _IOR::(T_TYPE, 219); pub const TUNSETVNETLE: c_int = _IOW::(T_TYPE, 220); pub const TUNGETVNETLE: c_int = _IOR::(T_TYPE, 221); pub const TUNSETVNETBE: c_int = _IOW::(T_TYPE, 222); pub const TUNGETVNETBE: c_int = _IOR::(T_TYPE, 223); pub const TUNSETSTEERINGEBPF: c_int = _IOR::(T_TYPE, 224); pub const TUNSETFILTEREBPF: c_int = _IOR::(T_TYPE, 225); pub const TUNSETCARRIER: c_int = _IOW::(T_TYPE, 226); pub const TUNGETDEVNETNS: c_int = _IO(T_TYPE, 227); // start android/platform/bionic/libc/kernel/uapi/linux/if_ether.h // from https://android.googlesource.com/platform/bionic/+/HEAD/libc/kernel/uapi/linux/if_ether.h pub const ETH_ALEN: c_int = 6; pub const ETH_HLEN: c_int = 14; pub const ETH_ZLEN: c_int = 60; pub const ETH_DATA_LEN: c_int = 1500; pub const ETH_FRAME_LEN: c_int = 1514; pub const ETH_FCS_LEN: c_int = 4; pub const ETH_MIN_MTU: c_int = 68; pub const ETH_MAX_MTU: c_int = 0xFFFF; pub const ETH_P_LOOP: c_int = 0x0060; pub const ETH_P_PUP: c_int = 0x0200; pub const ETH_P_PUPAT: c_int = 0x0201; pub const ETH_P_TSN: c_int = 0x22F0; pub const ETH_P_IP: c_int = 0x0800; pub const ETH_P_X25: c_int = 0x0805; pub const ETH_P_ARP: c_int = 0x0806; pub const ETH_P_BPQ: c_int = 0x08FF; pub const ETH_P_IEEEPUP: c_int = 0x0a00; pub const ETH_P_IEEEPUPAT: c_int = 0x0a01; pub const ETH_P_BATMAN: c_int = 0x4305; pub const ETH_P_DEC: c_int = 0x6000; pub const ETH_P_DNA_DL: c_int = 0x6001; pub const ETH_P_DNA_RC: c_int = 0x6002; pub const ETH_P_DNA_RT: c_int = 0x6003; pub const ETH_P_LAT: c_int = 0x6004; pub const ETH_P_DIAG: c_int = 0x6005; pub const ETH_P_CUST: c_int = 0x6006; pub const ETH_P_SCA: c_int = 0x6007; pub const ETH_P_TEB: c_int = 0x6558; pub const ETH_P_RARP: c_int = 0x8035; pub const ETH_P_ATALK: c_int = 0x809B; pub const ETH_P_AARP: c_int = 0x80F3; pub const ETH_P_8021Q: c_int = 0x8100; /* see rust-lang/libc#924 pub const ETH_P_ERSPAN: c_int = 0x88BE;*/ pub const ETH_P_IPX: c_int = 0x8137; pub const ETH_P_IPV6: c_int = 0x86DD; pub const ETH_P_PAUSE: c_int = 0x8808; pub const ETH_P_SLOW: c_int = 0x8809; pub const ETH_P_WCCP: c_int = 0x883E; pub const ETH_P_MPLS_UC: c_int = 0x8847; pub const ETH_P_MPLS_MC: c_int = 0x8848; pub const ETH_P_ATMMPOA: c_int = 0x884c; pub const ETH_P_PPP_DISC: c_int = 0x8863; pub const ETH_P_PPP_SES: c_int = 0x8864; pub const ETH_P_LINK_CTL: c_int = 0x886c; pub const ETH_P_ATMFATE: c_int = 0x8884; pub const ETH_P_PAE: c_int = 0x888E; pub const ETH_P_AOE: c_int = 0x88A2; pub const ETH_P_8021AD: c_int = 0x88A8; pub const ETH_P_802_EX1: c_int = 0x88B5; pub const ETH_P_TIPC: c_int = 0x88CA; pub const ETH_P_MACSEC: c_int = 0x88E5; pub const ETH_P_8021AH: c_int = 0x88E7; pub const ETH_P_MVRP: c_int = 0x88F5; pub const ETH_P_1588: c_int = 0x88F7; pub const ETH_P_NCSI: c_int = 0x88F8; pub const ETH_P_PRP: c_int = 0x88FB; pub const ETH_P_FCOE: c_int = 0x8906; /* see rust-lang/libc#924 pub const ETH_P_IBOE: c_int = 0x8915;*/ pub const ETH_P_TDLS: c_int = 0x890D; pub const ETH_P_FIP: c_int = 0x8914; pub const ETH_P_80221: c_int = 0x8917; pub const ETH_P_HSR: c_int = 0x892F; /* see rust-lang/libc#924 pub const ETH_P_NSH: c_int = 0x894F;*/ pub const ETH_P_LOOPBACK: c_int = 0x9000; pub const ETH_P_QINQ1: c_int = 0x9100; pub const ETH_P_QINQ2: c_int = 0x9200; pub const ETH_P_QINQ3: c_int = 0x9300; pub const ETH_P_EDSA: c_int = 0xDADA; /* see rust-lang/libc#924 pub const ETH_P_IFE: c_int = 0xED3E;*/ pub const ETH_P_AF_IUCV: c_int = 0xFBFB; pub const ETH_P_802_3_MIN: c_int = 0x0600; pub const ETH_P_802_3: c_int = 0x0001; pub const ETH_P_AX25: c_int = 0x0002; pub const ETH_P_ALL: c_int = 0x0003; pub const ETH_P_802_2: c_int = 0x0004; pub const ETH_P_SNAP: c_int = 0x0005; pub const ETH_P_DDCMP: c_int = 0x0006; pub const ETH_P_WAN_PPP: c_int = 0x0007; pub const ETH_P_PPP_MP: c_int = 0x0008; pub const ETH_P_LOCALTALK: c_int = 0x0009; pub const ETH_P_CAN: c_int = 0x000C; pub const ETH_P_CANFD: c_int = 0x000D; pub const ETH_P_PPPTALK: c_int = 0x0010; pub const ETH_P_TR_802_2: c_int = 0x0011; pub const ETH_P_MOBITEX: c_int = 0x0015; pub const ETH_P_CONTROL: c_int = 0x0016; pub const ETH_P_IRDA: c_int = 0x0017; pub const ETH_P_ECONET: c_int = 0x0018; pub const ETH_P_HDLC: c_int = 0x0019; pub const ETH_P_ARCNET: c_int = 0x001A; pub const ETH_P_DSA: c_int = 0x001B; pub const ETH_P_TRAILER: c_int = 0x001C; pub const ETH_P_PHONET: c_int = 0x00F5; pub const ETH_P_IEEE802154: c_int = 0x00F6; pub const ETH_P_CAIF: c_int = 0x00F7; pub const ETH_P_XDSA: c_int = 0x00F8; /* see rust-lang/libc#924 pub const ETH_P_MAP: c_int = 0x00F9;*/ // end android/platform/bionic/libc/kernel/uapi/linux/if_ether.h // start android/platform/bionic/libc/kernel/uapi/linux/neighbour.h pub const NDA_UNSPEC: c_ushort = 0; pub const NDA_DST: c_ushort = 1; pub const NDA_LLADDR: c_ushort = 2; pub const NDA_CACHEINFO: c_ushort = 3; pub const NDA_PROBES: c_ushort = 4; pub const NDA_VLAN: c_ushort = 5; pub const NDA_PORT: c_ushort = 6; pub const NDA_VNI: c_ushort = 7; pub const NDA_IFINDEX: c_ushort = 8; pub const NDA_MASTER: c_ushort = 9; pub const NDA_LINK_NETNSID: c_ushort = 10; pub const NDA_SRC_VNI: c_ushort = 11; pub const NDA_PROTOCOL: c_ushort = 12; pub const NDA_NH_ID: c_ushort = 13; pub const NDA_FDB_EXT_ATTRS: c_ushort = 14; pub const NDA_FLAGS_EXT: c_ushort = 15; pub const NDA_NDM_STATE_MASK: c_ushort = 16; pub const NDA_NDM_FLAGS_MASK: c_ushort = 17; pub const NTF_USE: u8 = 0x01; pub const NTF_SELF: u8 = 0x02; pub const NTF_MASTER: u8 = 0x04; pub const NTF_PROXY: u8 = 0x08; pub const NTF_EXT_LEARNED: u8 = 0x10; pub const NTF_OFFLOADED: u8 = 0x20; pub const NTF_STICKY: u8 = 0x40; pub const NTF_ROUTER: u8 = 0x80; pub const NTF_EXT_MANAGED: u8 = 0x01; pub const NTF_EXT_LOCKED: u8 = 0x02; pub const NUD_NONE: u16 = 0x00; pub const NUD_INCOMPLETE: u16 = 0x01; pub const NUD_REACHABLE: u16 = 0x02; pub const NUD_STALE: u16 = 0x04; pub const NUD_DELAY: u16 = 0x08; pub const NUD_PROBE: u16 = 0x10; pub const NUD_FAILED: u16 = 0x20; pub const NUD_NOARP: u16 = 0x40; pub const NUD_PERMANENT: u16 = 0x80; pub const NDTPA_UNSPEC: c_ushort = 0; pub const NDTPA_IFINDEX: c_ushort = 1; pub const NDTPA_REFCNT: c_ushort = 2; pub const NDTPA_REACHABLE_TIME: c_ushort = 3; pub const NDTPA_BASE_REACHABLE_TIME: c_ushort = 4; pub const NDTPA_RETRANS_TIME: c_ushort = 5; pub const NDTPA_GC_STALETIME: c_ushort = 6; pub const NDTPA_DELAY_PROBE_TIME: c_ushort = 7; pub const NDTPA_QUEUE_LEN: c_ushort = 8; pub const NDTPA_APP_PROBES: c_ushort = 9; pub const NDTPA_UCAST_PROBES: c_ushort = 10; pub const NDTPA_MCAST_PROBES: c_ushort = 11; pub const NDTPA_ANYCAST_DELAY: c_ushort = 12; pub const NDTPA_PROXY_DELAY: c_ushort = 13; pub const NDTPA_PROXY_QLEN: c_ushort = 14; pub const NDTPA_LOCKTIME: c_ushort = 15; pub const NDTPA_QUEUE_LENBYTES: c_ushort = 16; pub const NDTPA_MCAST_REPROBES: c_ushort = 17; pub const NDTPA_PAD: c_ushort = 18; pub const NDTPA_INTERVAL_PROBE_TIME_MS: c_ushort = 19; pub const NDTA_UNSPEC: c_ushort = 0; pub const NDTA_NAME: c_ushort = 1; pub const NDTA_THRESH1: c_ushort = 2; pub const NDTA_THRESH2: c_ushort = 3; pub const NDTA_THRESH3: c_ushort = 4; pub const NDTA_CONFIG: c_ushort = 5; pub const NDTA_PARMS: c_ushort = 6; pub const NDTA_STATS: c_ushort = 7; pub const NDTA_GC_INTERVAL: c_ushort = 8; pub const NDTA_PAD: c_ushort = 9; pub const FDB_NOTIFY_BIT: u16 = 0x01; pub const FDB_NOTIFY_INACTIVE_BIT: u16 = 0x02; pub const NFEA_UNSPEC: c_ushort = 0; pub const NFEA_ACTIVITY_NOTIFY: c_ushort = 1; pub const NFEA_DONT_REFRESH: c_ushort = 2; // end android/platform/bionic/libc/kernel/uapi/linux/neighbour.h pub const SIOCADDRT: c_ulong = 0x0000890B; pub const SIOCDELRT: c_ulong = 0x0000890C; pub const SIOCRTMSG: c_ulong = 0x0000890D; pub const SIOCGIFNAME: c_ulong = 0x00008910; pub const SIOCSIFLINK: c_ulong = 0x00008911; pub const SIOCGIFCONF: c_ulong = 0x00008912; pub const SIOCGIFFLAGS: c_ulong = 0x00008913; pub const SIOCSIFFLAGS: c_ulong = 0x00008914; pub const SIOCGIFADDR: c_ulong = 0x00008915; pub const SIOCSIFADDR: c_ulong = 0x00008916; pub const SIOCGIFDSTADDR: c_ulong = 0x00008917; pub const SIOCSIFDSTADDR: c_ulong = 0x00008918; pub const SIOCGIFBRDADDR: c_ulong = 0x00008919; pub const SIOCSIFBRDADDR: c_ulong = 0x0000891A; pub const SIOCGIFNETMASK: c_ulong = 0x0000891B; pub const SIOCSIFNETMASK: c_ulong = 0x0000891C; pub const SIOCGIFMETRIC: c_ulong = 0x0000891D; pub const SIOCSIFMETRIC: c_ulong = 0x0000891E; pub const SIOCGIFMEM: c_ulong = 0x0000891F; pub const SIOCSIFMEM: c_ulong = 0x00008920; pub const SIOCGIFMTU: c_ulong = 0x00008921; pub const SIOCSIFMTU: c_ulong = 0x00008922; pub const SIOCSIFNAME: c_ulong = 0x00008923; pub const SIOCSIFHWADDR: c_ulong = 0x00008924; pub const SIOCGIFENCAP: c_ulong = 0x00008925; pub const SIOCSIFENCAP: c_ulong = 0x00008926; pub const SIOCGIFHWADDR: c_ulong = 0x00008927; pub const SIOCGIFSLAVE: c_ulong = 0x00008929; pub const SIOCSIFSLAVE: c_ulong = 0x00008930; pub const SIOCADDMULTI: c_ulong = 0x00008931; pub const SIOCDELMULTI: c_ulong = 0x00008932; pub const SIOCGIFINDEX: c_ulong = 0x00008933; pub const SIOGIFINDEX: c_ulong = SIOCGIFINDEX; pub const SIOCSIFPFLAGS: c_ulong = 0x00008934; pub const SIOCGIFPFLAGS: c_ulong = 0x00008935; pub const SIOCDIFADDR: c_ulong = 0x00008936; pub const SIOCSIFHWBROADCAST: c_ulong = 0x00008937; pub const SIOCGIFCOUNT: c_ulong = 0x00008938; pub const SIOCGIFBR: c_ulong = 0x00008940; pub const SIOCSIFBR: c_ulong = 0x00008941; pub const SIOCGIFTXQLEN: c_ulong = 0x00008942; pub const SIOCSIFTXQLEN: c_ulong = 0x00008943; pub const SIOCETHTOOL: c_ulong = 0x00008946; pub const SIOCGMIIPHY: c_ulong = 0x00008947; pub const SIOCGMIIREG: c_ulong = 0x00008948; pub const SIOCSMIIREG: c_ulong = 0x00008949; pub const SIOCWANDEV: c_ulong = 0x0000894A; pub const SIOCOUTQNSD: c_ulong = 0x0000894B; pub const SIOCGSKNS: c_ulong = 0x0000894C; pub const SIOCDARP: c_ulong = 0x00008953; pub const SIOCGARP: c_ulong = 0x00008954; pub const SIOCSARP: c_ulong = 0x00008955; pub const SIOCDRARP: c_ulong = 0x00008960; pub const SIOCGRARP: c_ulong = 0x00008961; pub const SIOCSRARP: c_ulong = 0x00008962; pub const SIOCGIFMAP: c_ulong = 0x00008970; pub const SIOCSIFMAP: c_ulong = 0x00008971; pub const SIOCADDDLCI: c_ulong = 0x00008980; pub const SIOCDELDLCI: c_ulong = 0x00008981; pub const SIOCGIFVLAN: c_ulong = 0x00008982; pub const SIOCSIFVLAN: c_ulong = 0x00008983; pub const SIOCBONDENSLAVE: c_ulong = 0x00008990; pub const SIOCBONDRELEASE: c_ulong = 0x00008991; pub const SIOCBONDSETHWADDR: c_ulong = 0x00008992; pub const SIOCBONDSLAVEINFOQUERY: c_ulong = 0x00008993; pub const SIOCBONDINFOQUERY: c_ulong = 0x00008994; pub const SIOCBONDCHANGEACTIVE: c_ulong = 0x00008995; pub const SIOCBRADDBR: c_ulong = 0x000089a0; pub const SIOCBRDELBR: c_ulong = 0x000089a1; pub const SIOCBRADDIF: c_ulong = 0x000089a2; pub const SIOCBRDELIF: c_ulong = 0x000089a3; pub const SIOCSHWTSTAMP: c_ulong = 0x000089b0; pub const SIOCGHWTSTAMP: c_ulong = 0x000089b1; pub const SIOCDEVPRIVATE: c_ulong = 0x000089F0; pub const SIOCPROTOPRIVATE: c_ulong = 0x000089E0; // linux/module.h pub const MODULE_INIT_IGNORE_MODVERSIONS: c_uint = 0x0001; pub const MODULE_INIT_IGNORE_VERMAGIC: c_uint = 0x0002; // linux/net_tstamp.h pub const SOF_TIMESTAMPING_TX_HARDWARE: c_uint = 1 << 0; pub const SOF_TIMESTAMPING_TX_SOFTWARE: c_uint = 1 << 1; pub const SOF_TIMESTAMPING_RX_HARDWARE: c_uint = 1 << 2; pub const SOF_TIMESTAMPING_RX_SOFTWARE: c_uint = 1 << 3; pub const SOF_TIMESTAMPING_SOFTWARE: c_uint = 1 << 4; pub const SOF_TIMESTAMPING_SYS_HARDWARE: c_uint = 1 << 5; pub const SOF_TIMESTAMPING_RAW_HARDWARE: c_uint = 1 << 6; pub const SOF_TIMESTAMPING_OPT_ID: c_uint = 1 << 7; pub const SOF_TIMESTAMPING_TX_SCHED: c_uint = 1 << 8; pub const SOF_TIMESTAMPING_TX_ACK: c_uint = 1 << 9; pub const SOF_TIMESTAMPING_OPT_CMSG: c_uint = 1 << 10; pub const SOF_TIMESTAMPING_OPT_TSONLY: c_uint = 1 << 11; pub const SOF_TIMESTAMPING_OPT_STATS: c_uint = 1 << 12; pub const SOF_TIMESTAMPING_OPT_PKTINFO: c_uint = 1 << 13; pub const SOF_TIMESTAMPING_OPT_TX_SWHW: c_uint = 1 << 14; pub const SOF_TIMESTAMPING_BIND_PHC: c_uint = 1 << 15; pub const SOF_TIMESTAMPING_OPT_ID_TCP: c_uint = 1 << 16; pub const SOF_TIMESTAMPING_OPT_RX_FILTER: c_uint = 1 << 17; #[deprecated( since = "0.2.55", note = "ENOATTR is not available on Android; use ENODATA instead" )] pub const ENOATTR: c_int = crate::ENODATA; // linux/if_alg.h pub const ALG_SET_KEY: c_int = 1; pub const ALG_SET_IV: c_int = 2; pub const ALG_SET_OP: c_int = 3; pub const ALG_SET_AEAD_ASSOCLEN: c_int = 4; pub const ALG_SET_AEAD_AUTHSIZE: c_int = 5; pub const ALG_SET_DRBG_ENTROPY: c_int = 6; pub const ALG_OP_DECRYPT: c_int = 0; pub const ALG_OP_ENCRYPT: c_int = 1; // sys/mman.h pub const MLOCK_ONFAULT: c_int = 0x01; // uapi/linux/vm_sockets.h pub const VMADDR_CID_ANY: c_uint = 0xFFFFFFFF; pub const VMADDR_CID_HYPERVISOR: c_uint = 0; pub const VMADDR_CID_LOCAL: c_uint = 1; pub const VMADDR_CID_HOST: c_uint = 2; pub const VMADDR_PORT_ANY: c_uint = 0xFFFFFFFF; // uapi/linux/inotify.h pub const IN_ACCESS: u32 = 0x0000_0001; pub const IN_MODIFY: u32 = 0x0000_0002; pub const IN_ATTRIB: u32 = 0x0000_0004; pub const IN_CLOSE_WRITE: u32 = 0x0000_0008; pub const IN_CLOSE_NOWRITE: u32 = 0x0000_0010; pub const IN_CLOSE: u32 = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE; pub const IN_OPEN: u32 = 0x0000_0020; pub const IN_MOVED_FROM: u32 = 0x0000_0040; pub const IN_MOVED_TO: u32 = 0x0000_0080; pub const IN_MOVE: u32 = IN_MOVED_FROM | IN_MOVED_TO; pub const IN_CREATE: u32 = 0x0000_0100; pub const IN_DELETE: u32 = 0x0000_0200; pub const IN_DELETE_SELF: u32 = 0x0000_0400; pub const IN_MOVE_SELF: u32 = 0x0000_0800; pub const IN_UNMOUNT: u32 = 0x0000_2000; pub const IN_Q_OVERFLOW: u32 = 0x0000_4000; pub const IN_IGNORED: u32 = 0x0000_8000; pub const IN_ONLYDIR: u32 = 0x0100_0000; pub const IN_DONT_FOLLOW: u32 = 0x0200_0000; pub const IN_EXCL_UNLINK: u32 = 0x0400_0000; pub const IN_MASK_CREATE: u32 = 0x1000_0000; pub const IN_MASK_ADD: u32 = 0x2000_0000; pub const IN_ISDIR: u32 = 0x4000_0000; pub const IN_ONESHOT: u32 = 0x8000_0000; pub const IN_ALL_EVENTS: u32 = IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | IN_MOVE_SELF; pub const IN_CLOEXEC: c_int = O_CLOEXEC; pub const IN_NONBLOCK: c_int = O_NONBLOCK; pub const FUTEX_WAIT: c_int = 0; pub const FUTEX_WAKE: c_int = 1; pub const FUTEX_FD: c_int = 2; pub const FUTEX_REQUEUE: c_int = 3; pub const FUTEX_CMP_REQUEUE: c_int = 4; pub const FUTEX_WAKE_OP: c_int = 5; pub const FUTEX_LOCK_PI: c_int = 6; pub const FUTEX_UNLOCK_PI: c_int = 7; pub const FUTEX_TRYLOCK_PI: c_int = 8; pub const FUTEX_WAIT_BITSET: c_int = 9; pub const FUTEX_WAKE_BITSET: c_int = 10; pub const FUTEX_WAIT_REQUEUE_PI: c_int = 11; pub const FUTEX_CMP_REQUEUE_PI: c_int = 12; pub const FUTEX_LOCK_PI2: c_int = 13; pub const FUTEX_PRIVATE_FLAG: c_int = 128; pub const FUTEX_CLOCK_REALTIME: c_int = 256; pub const FUTEX_CMD_MASK: c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); // linux/errqueue.h pub const SO_EE_ORIGIN_NONE: u8 = 0; pub const SO_EE_ORIGIN_LOCAL: u8 = 1; pub const SO_EE_ORIGIN_ICMP: u8 = 2; pub const SO_EE_ORIGIN_ICMP6: u8 = 3; pub const SO_EE_ORIGIN_TXSTATUS: u8 = 4; pub const SO_EE_ORIGIN_TIMESTAMPING: u8 = SO_EE_ORIGIN_TXSTATUS; // errno.h pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EWOULDBLOCK: c_int = EAGAIN; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; // linux/sched.h pub const SCHED_NORMAL: c_int = 0; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const SCHED_BATCH: c_int = 3; pub const SCHED_IDLE: c_int = 5; pub const SCHED_DEADLINE: c_int = 6; pub const SCHED_RESET_ON_FORK: c_int = 0x40000000; pub const CLONE_PIDFD: c_int = 0x1000; // linux/membarrier.h pub const MEMBARRIER_CMD_QUERY: c_int = 0; pub const MEMBARRIER_CMD_GLOBAL: c_int = 1 << 0; pub const MEMBARRIER_CMD_GLOBAL_EXPEDITED: c_int = 1 << 1; pub const MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED: c_int = 1 << 2; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED: c_int = 1 << 3; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED: c_int = 1 << 4; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE: c_int = 1 << 5; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE: c_int = 1 << 6; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ: c_int = 1 << 7; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ: c_int = 1 << 8; // linux/mempolicy.h pub const MPOL_DEFAULT: c_int = 0; pub const MPOL_PREFERRED: c_int = 1; pub const MPOL_BIND: c_int = 2; pub const MPOL_INTERLEAVE: c_int = 3; pub const MPOL_LOCAL: c_int = 4; pub const MPOL_F_NUMA_BALANCING: c_int = 1 << 13; pub const MPOL_F_RELATIVE_NODES: c_int = 1 << 14; pub const MPOL_F_STATIC_NODES: c_int = 1 << 15; // bits/seek_constants.h pub const SEEK_DATA: c_int = 3; pub const SEEK_HOLE: c_int = 4; // sys/socket.h pub const AF_NFC: c_int = 39; pub const AF_VSOCK: c_int = 40; pub const PF_NFC: c_int = AF_NFC; pub const PF_VSOCK: c_int = AF_VSOCK; pub const SOMAXCONN: c_int = 128; // sys/prctl.h pub const PR_SET_PDEATHSIG: c_int = 1; pub const PR_GET_PDEATHSIG: c_int = 2; pub const PR_GET_SECUREBITS: c_int = 27; pub const PR_SET_SECUREBITS: c_int = 28; // sys/system_properties.h pub const PROP_VALUE_MAX: c_int = 92; pub const PROP_NAME_MAX: c_int = 32; // sys/prctl.h pub const PR_SET_VMA: c_int = 0x53564d41; pub const PR_SET_VMA_ANON_NAME: c_int = 0; pub const PR_SET_NO_NEW_PRIVS: c_int = 38; pub const PR_GET_NO_NEW_PRIVS: c_int = 39; pub const PR_GET_SECCOMP: c_int = 21; pub const PR_SET_SECCOMP: c_int = 22; pub const PR_GET_TIMING: c_int = 13; pub const PR_SET_TIMING: c_int = 14; pub const PR_TIMING_STATISTICAL: c_int = 0; pub const PR_TIMING_TIMESTAMP: c_int = 1; pub const PR_SET_NAME: c_int = 15; pub const PR_GET_NAME: c_int = 16; // linux/if_addr.h pub const IFA_UNSPEC: c_ushort = 0; pub const IFA_ADDRESS: c_ushort = 1; pub const IFA_LOCAL: c_ushort = 2; pub const IFA_LABEL: c_ushort = 3; pub const IFA_BROADCAST: c_ushort = 4; pub const IFA_ANYCAST: c_ushort = 5; pub const IFA_CACHEINFO: c_ushort = 6; pub const IFA_MULTICAST: c_ushort = 7; pub const IFA_F_SECONDARY: u32 = 0x01; pub const IFA_F_TEMPORARY: u32 = 0x01; pub const IFA_F_NODAD: u32 = 0x02; pub const IFA_F_OPTIMISTIC: u32 = 0x04; pub const IFA_F_DADFAILED: u32 = 0x08; pub const IFA_F_HOMEADDRESS: u32 = 0x10; pub const IFA_F_DEPRECATED: u32 = 0x20; pub const IFA_F_TENTATIVE: u32 = 0x40; pub const IFA_F_PERMANENT: u32 = 0x80; // linux/if_link.h pub const IFLA_UNSPEC: c_ushort = 0; pub const IFLA_ADDRESS: c_ushort = 1; pub const IFLA_BROADCAST: c_ushort = 2; pub const IFLA_IFNAME: c_ushort = 3; pub const IFLA_MTU: c_ushort = 4; pub const IFLA_LINK: c_ushort = 5; pub const IFLA_QDISC: c_ushort = 6; pub const IFLA_STATS: c_ushort = 7; pub const IFLA_COST: c_ushort = 8; pub const IFLA_PRIORITY: c_ushort = 9; pub const IFLA_MASTER: c_ushort = 10; pub const IFLA_WIRELESS: c_ushort = 11; pub const IFLA_PROTINFO: c_ushort = 12; pub const IFLA_TXQLEN: c_ushort = 13; pub const IFLA_MAP: c_ushort = 14; pub const IFLA_WEIGHT: c_ushort = 15; pub const IFLA_OPERSTATE: c_ushort = 16; pub const IFLA_LINKMODE: c_ushort = 17; pub const IFLA_LINKINFO: c_ushort = 18; pub const IFLA_NET_NS_PID: c_ushort = 19; pub const IFLA_IFALIAS: c_ushort = 20; pub const IFLA_NUM_VF: c_ushort = 21; pub const IFLA_VFINFO_LIST: c_ushort = 22; pub const IFLA_STATS64: c_ushort = 23; pub const IFLA_VF_PORTS: c_ushort = 24; pub const IFLA_PORT_SELF: c_ushort = 25; pub const IFLA_AF_SPEC: c_ushort = 26; pub const IFLA_GROUP: c_ushort = 27; pub const IFLA_NET_NS_FD: c_ushort = 28; pub const IFLA_EXT_MASK: c_ushort = 29; pub const IFLA_PROMISCUITY: c_ushort = 30; pub const IFLA_NUM_TX_QUEUES: c_ushort = 31; pub const IFLA_NUM_RX_QUEUES: c_ushort = 32; pub const IFLA_CARRIER: c_ushort = 33; pub const IFLA_PHYS_PORT_ID: c_ushort = 34; pub const IFLA_CARRIER_CHANGES: c_ushort = 35; pub const IFLA_PHYS_SWITCH_ID: c_ushort = 36; pub const IFLA_LINK_NETNSID: c_ushort = 37; pub const IFLA_PHYS_PORT_NAME: c_ushort = 38; pub const IFLA_PROTO_DOWN: c_ushort = 39; pub const IFLA_GSO_MAX_SEGS: c_ushort = 40; pub const IFLA_GSO_MAX_SIZE: c_ushort = 41; pub const IFLA_PAD: c_ushort = 42; pub const IFLA_XDP: c_ushort = 43; pub const IFLA_EVENT: c_ushort = 44; pub const IFLA_NEW_NETNSID: c_ushort = 45; pub const IFLA_IF_NETNSID: c_ushort = 46; pub const IFLA_TARGET_NETNSID: c_ushort = IFLA_IF_NETNSID; pub const IFLA_CARRIER_UP_COUNT: c_ushort = 47; pub const IFLA_CARRIER_DOWN_COUNT: c_ushort = 48; pub const IFLA_NEW_IFINDEX: c_ushort = 49; pub const IFLA_MIN_MTU: c_ushort = 50; pub const IFLA_MAX_MTU: c_ushort = 51; pub const IFLA_PROP_LIST: c_ushort = 52; pub const IFLA_ALT_IFNAME: c_ushort = 53; pub const IFLA_PERM_ADDRESS: c_ushort = 54; pub const IFLA_PROTO_DOWN_REASON: c_ushort = 55; pub const IFLA_PARENT_DEV_NAME: c_ushort = 56; pub const IFLA_PARENT_DEV_BUS_NAME: c_ushort = 57; pub const IFLA_GRO_MAX_SIZE: c_ushort = 58; pub const IFLA_TSO_MAX_SIZE: c_ushort = 59; pub const IFLA_TSO_MAX_SEGS: c_ushort = 60; pub const IFLA_ALLMULTI: c_ushort = 61; pub const IFLA_DEVLINK_PORT: c_ushort = 62; pub const IFLA_GSO_IPV4_MAX_SIZE: c_ushort = 63; pub const IFLA_GRO_IPV4_MAX_SIZE: c_ushort = 64; pub const IFLA_INFO_UNSPEC: c_ushort = 0; pub const IFLA_INFO_KIND: c_ushort = 1; pub const IFLA_INFO_DATA: c_ushort = 2; pub const IFLA_INFO_XSTATS: c_ushort = 3; pub const IFLA_INFO_SLAVE_KIND: c_ushort = 4; pub const IFLA_INFO_SLAVE_DATA: c_ushort = 5; // linux/rtnetlink.h pub const TCA_UNSPEC: c_ushort = 0; pub const TCA_KIND: c_ushort = 1; pub const TCA_OPTIONS: c_ushort = 2; pub const TCA_STATS: c_ushort = 3; pub const TCA_XSTATS: c_ushort = 4; pub const TCA_RATE: c_ushort = 5; pub const TCA_FCNT: c_ushort = 6; pub const TCA_STATS2: c_ushort = 7; pub const TCA_STAB: c_ushort = 8; pub const RTM_NEWLINK: u16 = 16; pub const RTM_DELLINK: u16 = 17; pub const RTM_GETLINK: u16 = 18; pub const RTM_SETLINK: u16 = 19; pub const RTM_NEWADDR: u16 = 20; pub const RTM_DELADDR: u16 = 21; pub const RTM_GETADDR: u16 = 22; pub const RTM_NEWROUTE: u16 = 24; pub const RTM_DELROUTE: u16 = 25; pub const RTM_GETROUTE: u16 = 26; pub const RTM_NEWNEIGH: u16 = 28; pub const RTM_DELNEIGH: u16 = 29; pub const RTM_GETNEIGH: u16 = 30; pub const RTM_NEWRULE: u16 = 32; pub const RTM_DELRULE: u16 = 33; pub const RTM_GETRULE: u16 = 34; pub const RTM_NEWQDISC: u16 = 36; pub const RTM_DELQDISC: u16 = 37; pub const RTM_GETQDISC: u16 = 38; pub const RTM_NEWTCLASS: u16 = 40; pub const RTM_DELTCLASS: u16 = 41; pub const RTM_GETTCLASS: u16 = 42; pub const RTM_NEWTFILTER: u16 = 44; pub const RTM_DELTFILTER: u16 = 45; pub const RTM_GETTFILTER: u16 = 46; pub const RTM_NEWACTION: u16 = 48; pub const RTM_DELACTION: u16 = 49; pub const RTM_GETACTION: u16 = 50; pub const RTM_NEWPREFIX: u16 = 52; pub const RTM_GETMULTICAST: u16 = 58; pub const RTM_GETANYCAST: u16 = 62; pub const RTM_NEWNEIGHTBL: u16 = 64; pub const RTM_GETNEIGHTBL: u16 = 66; pub const RTM_SETNEIGHTBL: u16 = 67; pub const RTM_NEWNDUSEROPT: u16 = 68; pub const RTM_NEWADDRLABEL: u16 = 72; pub const RTM_DELADDRLABEL: u16 = 73; pub const RTM_GETADDRLABEL: u16 = 74; pub const RTM_GETDCB: u16 = 78; pub const RTM_SETDCB: u16 = 79; pub const RTM_NEWNETCONF: u16 = 80; pub const RTM_GETNETCONF: u16 = 82; pub const RTM_NEWMDB: u16 = 84; pub const RTM_DELMDB: u16 = 85; pub const RTM_GETMDB: u16 = 86; pub const RTM_NEWNSID: u16 = 88; pub const RTM_DELNSID: u16 = 89; pub const RTM_GETNSID: u16 = 90; pub const RTM_F_NOTIFY: c_uint = 0x100; pub const RTM_F_CLONED: c_uint = 0x200; pub const RTM_F_EQUALIZE: c_uint = 0x400; pub const RTM_F_PREFIX: c_uint = 0x800; pub const RTA_UNSPEC: c_ushort = 0; pub const RTA_DST: c_ushort = 1; pub const RTA_SRC: c_ushort = 2; pub const RTA_IIF: c_ushort = 3; pub const RTA_OIF: c_ushort = 4; pub const RTA_GATEWAY: c_ushort = 5; pub const RTA_PRIORITY: c_ushort = 6; pub const RTA_PREFSRC: c_ushort = 7; pub const RTA_METRICS: c_ushort = 8; pub const RTA_MULTIPATH: c_ushort = 9; pub const RTA_PROTOINFO: c_ushort = 10; // No longer used pub const RTA_FLOW: c_ushort = 11; pub const RTA_CACHEINFO: c_ushort = 12; pub const RTA_SESSION: c_ushort = 13; // No longer used pub const RTA_MP_ALGO: c_ushort = 14; // No longer used pub const RTA_TABLE: c_ushort = 15; pub const RTA_MARK: c_ushort = 16; pub const RTA_MFC_STATS: c_ushort = 17; pub const RTN_UNSPEC: c_uchar = 0; pub const RTN_UNICAST: c_uchar = 1; pub const RTN_LOCAL: c_uchar = 2; pub const RTN_BROADCAST: c_uchar = 3; pub const RTN_ANYCAST: c_uchar = 4; pub const RTN_MULTICAST: c_uchar = 5; pub const RTN_BLACKHOLE: c_uchar = 6; pub const RTN_UNREACHABLE: c_uchar = 7; pub const RTN_PROHIBIT: c_uchar = 8; pub const RTN_THROW: c_uchar = 9; pub const RTN_NAT: c_uchar = 10; pub const RTN_XRESOLVE: c_uchar = 11; pub const RTPROT_UNSPEC: c_uchar = 0; pub const RTPROT_REDIRECT: c_uchar = 1; pub const RTPROT_KERNEL: c_uchar = 2; pub const RTPROT_BOOT: c_uchar = 3; pub const RTPROT_STATIC: c_uchar = 4; pub const RT_SCOPE_UNIVERSE: c_uchar = 0; pub const RT_SCOPE_SITE: c_uchar = 200; pub const RT_SCOPE_LINK: c_uchar = 253; pub const RT_SCOPE_HOST: c_uchar = 254; pub const RT_SCOPE_NOWHERE: c_uchar = 255; pub const RT_TABLE_UNSPEC: c_uchar = 0; pub const RT_TABLE_COMPAT: c_uchar = 252; pub const RT_TABLE_DEFAULT: c_uchar = 253; pub const RT_TABLE_MAIN: c_uchar = 254; pub const RT_TABLE_LOCAL: c_uchar = 255; pub const RTMSG_NEWDEVICE: u32 = 0x11; pub const RTMSG_DELDEVICE: u32 = 0x12; pub const RTMSG_NEWROUTE: u32 = 0x21; pub const RTMSG_DELROUTE: u32 = 0x22; pub const CTL_KERN: c_int = 1; pub const CTL_VM: c_int = 2; pub const CTL_NET: c_int = 3; pub const CTL_FS: c_int = 5; pub const CTL_DEBUG: c_int = 6; pub const CTL_DEV: c_int = 7; pub const CTL_BUS: c_int = 8; pub const CTL_ABI: c_int = 9; pub const CTL_CPU: c_int = 10; pub const CTL_BUS_ISA: c_int = 1; pub const INOTIFY_MAX_USER_INSTANCES: c_int = 1; pub const INOTIFY_MAX_USER_WATCHES: c_int = 2; pub const INOTIFY_MAX_QUEUED_EVENTS: c_int = 3; pub const KERN_OSTYPE: c_int = 1; pub const KERN_OSRELEASE: c_int = 2; pub const KERN_OSREV: c_int = 3; pub const KERN_VERSION: c_int = 4; pub const KERN_SECUREMASK: c_int = 5; pub const KERN_PROF: c_int = 6; pub const KERN_NODENAME: c_int = 7; pub const KERN_DOMAINNAME: c_int = 8; pub const KERN_PANIC: c_int = 15; pub const KERN_REALROOTDEV: c_int = 16; pub const KERN_SPARC_REBOOT: c_int = 21; pub const KERN_CTLALTDEL: c_int = 22; pub const KERN_PRINTK: c_int = 23; pub const KERN_NAMETRANS: c_int = 24; pub const KERN_PPC_HTABRECLAIM: c_int = 25; pub const KERN_PPC_ZEROPAGED: c_int = 26; pub const KERN_PPC_POWERSAVE_NAP: c_int = 27; pub const KERN_MODPROBE: c_int = 28; pub const KERN_SG_BIG_BUFF: c_int = 29; pub const KERN_ACCT: c_int = 30; pub const KERN_PPC_L2CR: c_int = 31; pub const KERN_RTSIGNR: c_int = 32; pub const KERN_RTSIGMAX: c_int = 33; pub const KERN_SHMMAX: c_int = 34; pub const KERN_MSGMAX: c_int = 35; pub const KERN_MSGMNB: c_int = 36; pub const KERN_MSGPOOL: c_int = 37; pub const KERN_SYSRQ: c_int = 38; pub const KERN_MAX_THREADS: c_int = 39; pub const KERN_RANDOM: c_int = 40; pub const KERN_SHMALL: c_int = 41; pub const KERN_MSGMNI: c_int = 42; pub const KERN_SEM: c_int = 43; pub const KERN_SPARC_STOP_A: c_int = 44; pub const KERN_SHMMNI: c_int = 45; pub const KERN_OVERFLOWUID: c_int = 46; pub const KERN_OVERFLOWGID: c_int = 47; pub const KERN_SHMPATH: c_int = 48; pub const KERN_HOTPLUG: c_int = 49; pub const KERN_IEEE_EMULATION_WARNINGS: c_int = 50; pub const KERN_S390_USER_DEBUG_LOGGING: c_int = 51; pub const KERN_CORE_USES_PID: c_int = 52; pub const KERN_TAINTED: c_int = 53; pub const KERN_CADPID: c_int = 54; pub const KERN_PIDMAX: c_int = 55; pub const KERN_CORE_PATTERN: c_int = 56; pub const KERN_PANIC_ON_OOPS: c_int = 57; pub const KERN_HPPA_PWRSW: c_int = 58; pub const KERN_HPPA_UNALIGNED: c_int = 59; pub const KERN_PRINTK_RATELIMIT: c_int = 60; pub const KERN_PRINTK_RATELIMIT_BURST: c_int = 61; pub const KERN_PTY: c_int = 62; pub const KERN_NGROUPS_MAX: c_int = 63; pub const KERN_SPARC_SCONS_PWROFF: c_int = 64; pub const KERN_HZ_TIMER: c_int = 65; pub const KERN_UNKNOWN_NMI_PANIC: c_int = 66; pub const KERN_BOOTLOADER_TYPE: c_int = 67; pub const KERN_RANDOMIZE: c_int = 68; pub const KERN_SETUID_DUMPABLE: c_int = 69; pub const KERN_SPIN_RETRY: c_int = 70; pub const KERN_ACPI_VIDEO_FLAGS: c_int = 71; pub const KERN_IA64_UNALIGNED: c_int = 72; pub const KERN_COMPAT_LOG: c_int = 73; pub const KERN_MAX_LOCK_DEPTH: c_int = 74; pub const VM_OVERCOMMIT_MEMORY: c_int = 5; pub const VM_PAGE_CLUSTER: c_int = 10; pub const VM_DIRTY_BACKGROUND: c_int = 11; pub const VM_DIRTY_RATIO: c_int = 12; pub const VM_DIRTY_WB_CS: c_int = 13; pub const VM_DIRTY_EXPIRE_CS: c_int = 14; pub const VM_NR_PDFLUSH_THREADS: c_int = 15; pub const VM_OVERCOMMIT_RATIO: c_int = 16; pub const VM_PAGEBUF: c_int = 17; pub const VM_HUGETLB_PAGES: c_int = 18; pub const VM_SWAPPINESS: c_int = 19; pub const VM_LOWMEM_RESERVE_RATIO: c_int = 20; pub const VM_MIN_FREE_KBYTES: c_int = 21; pub const VM_MAX_MAP_COUNT: c_int = 22; pub const VM_LAPTOP_MODE: c_int = 23; pub const VM_BLOCK_DUMP: c_int = 24; pub const VM_HUGETLB_GROUP: c_int = 25; pub const VM_VFS_CACHE_PRESSURE: c_int = 26; pub const VM_LEGACY_VA_LAYOUT: c_int = 27; pub const VM_SWAP_TOKEN_TIMEOUT: c_int = 28; pub const VM_DROP_PAGECACHE: c_int = 29; pub const VM_PERCPU_PAGELIST_FRACTION: c_int = 30; pub const VM_ZONE_RECLAIM_MODE: c_int = 31; pub const VM_MIN_UNMAPPED: c_int = 32; pub const VM_PANIC_ON_OOM: c_int = 33; pub const VM_VDSO_ENABLED: c_int = 34; pub const NET_CORE: c_int = 1; pub const NET_ETHER: c_int = 2; pub const NET_802: c_int = 3; pub const NET_UNIX: c_int = 4; pub const NET_IPV4: c_int = 5; pub const NET_IPX: c_int = 6; pub const NET_ATALK: c_int = 7; pub const NET_NETROM: c_int = 8; pub const NET_AX25: c_int = 9; pub const NET_BRIDGE: c_int = 10; pub const NET_ROSE: c_int = 11; pub const NET_IPV6: c_int = 12; pub const NET_X25: c_int = 13; pub const NET_TR: c_int = 14; pub const NET_DECNET: c_int = 15; pub const NET_ECONET: c_int = 16; pub const NET_SCTP: c_int = 17; pub const NET_LLC: c_int = 18; pub const NET_NETFILTER: c_int = 19; pub const NET_DCCP: c_int = 20; pub const HUGETLB_FLAG_ENCODE_SHIFT: c_int = 26; pub const MAP_HUGE_SHIFT: c_int = HUGETLB_FLAG_ENCODE_SHIFT; // include/linux/sched.h pub const PF_VCPU: c_int = 0x00000001; pub const PF_IDLE: c_int = 0x00000002; pub const PF_EXITING: c_int = 0x00000004; pub const PF_POSTCOREDUMP: c_int = 0x00000008; pub const PF_IO_WORKER: c_int = 0x00000010; pub const PF_WQ_WORKER: c_int = 0x00000020; pub const PF_FORKNOEXEC: c_int = 0x00000040; pub const PF_MCE_PROCESS: c_int = 0x00000080; pub const PF_SUPERPRIV: c_int = 0x00000100; pub const PF_DUMPCORE: c_int = 0x00000200; pub const PF_SIGNALED: c_int = 0x00000400; pub const PF_MEMALLOC: c_int = 0x00000800; pub const PF_NPROC_EXCEEDED: c_int = 0x00001000; pub const PF_USED_MATH: c_int = 0x00002000; pub const PF_USER_WORKER: c_int = 0x00004000; pub const PF_NOFREEZE: c_int = 0x00008000; pub const PF_KSWAPD: c_int = 0x00020000; pub const PF_MEMALLOC_NOFS: c_int = 0x00040000; pub const PF_MEMALLOC_NOIO: c_int = 0x00080000; pub const PF_LOCAL_THROTTLE: c_int = 0x00100000; pub const PF_KTHREAD: c_int = 0x00200000; pub const PF_RANDOMIZE: c_int = 0x00400000; pub const PF_NO_SETAFFINITY: c_int = 0x04000000; pub const PF_MCE_EARLY: c_int = 0x08000000; pub const PF_MEMALLOC_PIN: c_int = 0x10000000; pub const PF_SUSPEND_TASK: c_int = 0x80000000; pub const KLOG_CLOSE: c_int = 0; pub const KLOG_OPEN: c_int = 1; pub const KLOG_READ: c_int = 2; pub const KLOG_READ_ALL: c_int = 3; pub const KLOG_READ_CLEAR: c_int = 4; pub const KLOG_CLEAR: c_int = 5; pub const KLOG_CONSOLE_OFF: c_int = 6; pub const KLOG_CONSOLE_ON: c_int = 7; pub const KLOG_CONSOLE_LEVEL: c_int = 8; pub const KLOG_SIZE_UNREAD: c_int = 9; pub const KLOG_SIZE_BUFFER: c_int = 10; // From NDK's linux/auxvec.h pub const AT_NULL: c_ulong = 0; pub const AT_IGNORE: c_ulong = 1; pub const AT_EXECFD: c_ulong = 2; pub const AT_PHDR: c_ulong = 3; pub const AT_PHENT: c_ulong = 4; pub const AT_PHNUM: c_ulong = 5; pub const AT_PAGESZ: c_ulong = 6; pub const AT_BASE: c_ulong = 7; pub const AT_FLAGS: c_ulong = 8; pub const AT_ENTRY: c_ulong = 9; pub const AT_NOTELF: c_ulong = 10; pub const AT_UID: c_ulong = 11; pub const AT_EUID: c_ulong = 12; pub const AT_GID: c_ulong = 13; pub const AT_EGID: c_ulong = 14; pub const AT_PLATFORM: c_ulong = 15; pub const AT_HWCAP: c_ulong = 16; pub const AT_CLKTCK: c_ulong = 17; pub const AT_SECURE: c_ulong = 23; pub const AT_BASE_PLATFORM: c_ulong = 24; pub const AT_RANDOM: c_ulong = 25; pub const AT_HWCAP2: c_ulong = 26; pub const AT_RSEQ_FEATURE_SIZE: c_ulong = 27; pub const AT_RSEQ_ALIGN: c_ulong = 28; pub const AT_EXECFN: c_ulong = 31; pub const AT_MINSIGSTKSZ: c_ulong = 51; // siginfo.h pub const SI_DETHREAD: c_int = -7; pub const TRAP_PERF: c_int = 6; // Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the // following are only available on newer Linux versions than the versions // currently used in CI in some configurations, so we define them here. cfg_if! { if #[cfg(not(target_arch = "s390x"))] { pub const XFS_SUPER_MAGIC: c_long = 0x58465342; } else if #[cfg(target_arch = "s390x")] { pub const XFS_SUPER_MAGIC: c_uint = 0x58465342; } } f! { pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { let next = (cmsg as usize + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if (next.offset(1)) as usize > max { 0 as *mut cmsghdr } else { next as *mut cmsghdr } } pub fn CPU_ALLOC_SIZE(count: c_int) -> size_t { let _dummy: cpu_set_t = mem::zeroed(); let size_in_bits = 8 * mem::size_of_val(&_dummy.__bits[0]); ((count as size_t + size_in_bits - 1) / 8) as size_t } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.__bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.__bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.__bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.__bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.__bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * mem::size_of_val(&cpuset.__bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.__bits[idx] & (1 << offset)) } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> c_int { let mut s: u32 = 0; let size_of_mask = mem::size_of_val(&cpuset.__bits[0]); for i in cpuset.__bits[..(size / size_of_mask)].iter() { s += i.count_ones(); } s as c_int } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> c_int { CPU_COUNT_S(mem::size_of::(), cpuset) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.__bits == set2.__bits } pub fn NLA_ALIGN(len: c_int) -> c_int { return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1); } pub fn SO_EE_OFFENDER(ee: *const crate::sock_extended_err) -> *mut crate::sockaddr { ee.offset(1) as *mut crate::sockaddr } } safe_f! { pub {const} fn makedev(ma: c_uint, mi: c_uint) -> crate::dev_t { let ma = ma as crate::dev_t; let mi = mi as crate::dev_t; ((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12) } pub {const} fn major(dev: crate::dev_t) -> c_int { ((dev >> 8) & 0xfff) as c_int } pub {const} fn minor(dev: crate::dev_t) -> c_int { ((dev & 0xff) | ((dev >> 12) & 0xfff00)) as c_int } } extern "C" { pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut crate::group; pub fn getrlimit64(resource: c_int, rlim: *mut rlimit64) -> c_int; pub fn setrlimit64(resource: c_int, rlim: *const rlimit64) -> c_int; pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; pub fn prlimit( pid: crate::pid_t, resource: c_int, new_limit: *const crate::rlimit, old_limit: *mut crate::rlimit, ) -> c_int; pub fn prlimit64( pid: crate::pid_t, resource: c_int, new_limit: *const crate::rlimit64, old_limit: *mut crate::rlimit64, ) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut crate::timezone) -> c_int; pub fn mlock2(addr: *const c_void, len: size_t, flags: c_int) -> c_int; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: size_t, serv: *mut c_char, servlen: size_t, flags: c_int, ) -> c_int; pub fn preadv(fd: c_int, iov: *const crate::iovec, count: c_int, offset: off_t) -> ssize_t; pub fn pwritev(fd: c_int, iov: *const crate::iovec, count: c_int, offset: off_t) -> ssize_t; pub fn process_vm_readv( pid: crate::pid_t, local_iov: *const crate::iovec, local_iov_count: c_ulong, remote_iov: *const crate::iovec, remote_iov_count: c_ulong, flags: c_ulong, ) -> ssize_t; pub fn process_vm_writev( pid: crate::pid_t, local_iov: *const crate::iovec, local_iov_count: c_ulong, remote_iov: *const crate::iovec, remote_iov_count: c_ulong, flags: c_ulong, ) -> ssize_t; pub fn ptrace(request: c_int, ...) -> c_long; pub fn getpriority(which: c_int, who: crate::id_t) -> c_int; pub fn setpriority(which: c_int, who: crate::id_t, prio: c_int) -> c_int; pub fn __sched_cpualloc(count: size_t) -> *mut crate::cpu_set_t; pub fn __sched_cpufree(set: *mut crate::cpu_set_t); pub fn __sched_cpucount(setsize: size_t, set: *const cpu_set_t) -> c_int; pub fn sched_getcpu() -> c_int; pub fn mallinfo() -> crate::mallinfo; // available from API 23 pub fn malloc_info(options: c_int, stream: *mut crate::FILE) -> c_int; pub fn malloc_usable_size(ptr: *const c_void) -> size_t; pub fn utmpname(name: *const c_char) -> c_int; pub fn setutent(); pub fn getutent() -> *mut utmp; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn fallocate(fd: c_int, mode: c_int, offset: off_t, len: off_t) -> c_int; pub fn fallocate64(fd: c_int, mode: c_int, offset: off64_t, len: off64_t) -> c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn posix_fallocate64(fd: c_int, offset: off64_t, len: off64_t) -> c_int; pub fn getxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn lgetxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn fgetxattr( filedes: c_int, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn setxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn lsetxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn fsetxattr( filedes: c_int, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn listxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; pub fn llistxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; pub fn flistxattr(filedes: c_int, list: *mut c_char, size: size_t) -> ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> c_int; pub fn lremovexattr(path: *const c_char, name: *const c_char) -> c_int; pub fn fremovexattr(filedes: c_int, name: *const c_char) -> c_int; pub fn signalfd(fd: c_int, mask: *const crate::sigset_t, flags: c_int) -> c_int; pub fn timerfd_create(clock: crate::clockid_t, flags: c_int) -> c_int; pub fn timerfd_gettime(fd: c_int, current_value: *mut itimerspec) -> c_int; pub fn timerfd_settime( fd: c_int, flags: c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> c_int; pub fn syscall(num: c_long, ...) -> c_long; pub fn sched_getaffinity( pid: crate::pid_t, cpusetsize: size_t, cpuset: *mut cpu_set_t, ) -> c_int; pub fn sched_setaffinity( pid: crate::pid_t, cpusetsize: size_t, cpuset: *const cpu_set_t, ) -> c_int; pub fn epoll_create(size: c_int) -> c_int; pub fn epoll_create1(flags: c_int) -> c_int; pub fn epoll_wait( epfd: c_int, events: *mut crate::epoll_event, maxevents: c_int, timeout: c_int, ) -> c_int; pub fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut crate::epoll_event) -> c_int; pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut crate::sched_param, ) -> c_int; pub fn unshare(flags: c_int) -> c_int; pub fn umount(target: *const c_char) -> c_int; pub fn sched_get_priority_max(policy: c_int) -> c_int; pub fn tee(fd_in: c_int, fd_out: c_int, len: size_t, flags: c_uint) -> ssize_t; pub fn settimeofday(tv: *const crate::timeval, tz: *const crate::timezone) -> c_int; pub fn splice( fd_in: c_int, off_in: *mut crate::loff_t, fd_out: c_int, off_out: *mut crate::loff_t, len: size_t, flags: c_uint, ) -> ssize_t; pub fn eventfd(init: c_uint, flags: c_int) -> c_int; pub fn eventfd_read(fd: c_int, value: *mut eventfd_t) -> c_int; pub fn eventfd_write(fd: c_int, value: eventfd_t) -> c_int; pub fn sched_rr_get_interval(pid: crate::pid_t, tp: *mut crate::timespec) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const crate::sched_param) -> c_int; pub fn setns(fd: c_int, nstype: c_int) -> c_int; pub fn swapoff(puath: *const c_char) -> c_int; pub fn vmsplice(fd: c_int, iov: *const crate::iovec, nr_segs: size_t, flags: c_uint) -> ssize_t; pub fn mount( src: *const c_char, target: *const c_char, fstype: *const c_char, flags: c_ulong, data: *const c_void, ) -> c_int; pub fn personality(persona: c_uint) -> c_int; pub fn prctl(option: c_int, ...) -> c_int; pub fn sched_getparam(pid: crate::pid_t, param: *mut crate::sched_param) -> c_int; pub fn ppoll( fds: *mut crate::pollfd, nfds: nfds_t, timeout: *const crate::timespec, sigmask: *const sigset_t, ) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_barrierattr_init(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_destroy(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_getpshared( attr: *const crate::pthread_barrierattr_t, shared: *mut c_int, ) -> c_int; pub fn pthread_barrierattr_setpshared( attr: *mut crate::pthread_barrierattr_t, shared: c_int, ) -> c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const crate::pthread_barrierattr_t, count: c_uint, ) -> c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_spin_init(lock: *mut crate::pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn clone( cb: extern "C" fn(*mut c_void) -> c_int, child_stack: *mut c_void, flags: c_int, arg: *mut c_void, ... ) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn pthread_attr_getinheritsched( attr: *const crate::pthread_attr_t, flag: *mut c_int, ) -> c_int; pub fn pthread_attr_setinheritsched(attr: *mut crate::pthread_attr_t, flag: c_int) -> c_int; pub fn sethostname(name: *const c_char, len: size_t) -> c_int; pub fn sched_get_priority_min(policy: c_int) -> c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut c_int, ) -> c_int; pub fn sysinfo(info: *mut crate::sysinfo) -> c_int; pub fn umount2(target: *const c_char, flags: c_int) -> c_int; pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn swapon(path: *const c_char, swapflags: c_int) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn sendfile(out_fd: c_int, in_fd: c_int, offset: *mut off_t, count: size_t) -> ssize_t; pub fn sendfile64(out_fd: c_int, in_fd: c_int, offset: *mut off64_t, count: size_t) -> ssize_t; pub fn setfsgid(gid: crate::gid_t) -> c_int; pub fn setfsuid(uid: crate::uid_t) -> c_int; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn getgrouplist( user: *const c_char, group: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn initgroups(user: *const c_char, group: crate::gid_t) -> c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut c_int, ) -> c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn __errno() -> *mut c_int; pub fn inotify_rm_watch(fd: c_int, wd: u32) -> c_int; pub fn sendmmsg( sockfd: c_int, msgvec: *const crate::mmsghdr, vlen: c_uint, flags: c_int, ) -> c_int; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn inotify_init() -> c_int; pub fn inotify_init1(flags: c_int) -> c_int; pub fn inotify_add_watch(fd: c_int, path: *const c_char, mask: u32) -> c_int; pub fn regcomp(preg: *mut crate::regex_t, pattern: *const c_char, cflags: c_int) -> c_int; pub fn regexec( preg: *const crate::regex_t, input: *const c_char, nmatch: size_t, pmatch: *mut regmatch_t, eflags: c_int, ) -> c_int; pub fn regerror( errcode: c_int, preg: *const crate::regex_t, errbuf: *mut c_char, errbuf_size: size_t, ) -> size_t; pub fn regfree(preg: *mut crate::regex_t); pub fn android_set_abort_message(msg: *const c_char); pub fn gettid() -> crate::pid_t; pub fn getauxval(type_: c_ulong) -> c_ulong; /// Only available in API Version 28+ pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn pthread_setname_np(thread: crate::pthread_t, name: *const c_char) -> c_int; pub fn __system_property_set(__name: *const c_char, __value: *const c_char) -> c_int; pub fn __system_property_get(__name: *const c_char, __value: *mut c_char) -> c_int; pub fn __system_property_find(__name: *const c_char) -> *const prop_info; pub fn __system_property_find_nth(__n: c_uint) -> *const prop_info; pub fn __system_property_foreach( __callback: unsafe extern "C" fn(__pi: *const prop_info, __cookie: *mut c_void), __cookie: *mut c_void, ) -> c_int; // #include /// Only available in API Version 21+ pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn(info: *mut dl_phdr_info, size: usize, data: *mut c_void) -> c_int, >, data: *mut c_void, ) -> c_int; pub fn arc4random() -> u32; pub fn arc4random_uniform(__upper_bound: u32) -> u32; pub fn arc4random_buf(__buf: *mut c_void, __n: size_t); pub fn reallocarray(ptr: *mut c_void, nmemb: size_t, size: size_t) -> *mut c_void; pub fn pthread_getcpuclockid(thread: crate::pthread_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn dirname(path: *const c_char) -> *mut c_char; pub fn basename(path: *const c_char) -> *mut c_char; pub fn getopt_long( argc: c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut c_int, ) -> c_int; pub fn sync(); pub fn syncfs(fd: c_int) -> c_int; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; pub fn fread_unlocked( buf: *mut c_void, size: size_t, nobj: size_t, stream: *mut crate::FILE, ) -> size_t; pub fn fwrite_unlocked( buf: *const c_void, size: size_t, nobj: size_t, stream: *mut crate::FILE, ) -> size_t; pub fn fflush_unlocked(stream: *mut crate::FILE) -> c_int; pub fn fgets_unlocked(buf: *mut c_char, size: c_int, stream: *mut crate::FILE) -> *mut c_char; pub fn klogctl(syslog_type: c_int, bufp: *mut c_char, len: c_int) -> c_int; pub fn memfd_create(name: *const c_char, flags: c_uint) -> c_int; pub fn renameat2( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_uint, ) -> c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); } cfg_if! { if #[cfg(target_pointer_width = "32")] { mod b32; pub use self::b32::*; } else if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { // Unknown target_pointer_width } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { #[repr(C)] struct siginfo_sigfault { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, si_addr: *mut c_void, } (*(self as *const siginfo_t as *const siginfo_sigfault)).si_addr } pub unsafe fn si_value(&self) -> crate::sigval { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, _si_tid: c_int, _si_overrun: c_int, si_sigval: crate::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).si_sigval } } // Internal, for casts to access union fields #[repr(C)] struct sifields_sigchld { si_pid: crate::pid_t, si_uid: crate::uid_t, si_status: c_int, si_utime: c_long, si_stime: c_long, } impl Copy for sifields_sigchld {} impl Clone for sifields_sigchld { fn clone(&self) -> sifields_sigchld { *self } } // Internal, for casts to access union fields #[repr(C)] union sifields { _align_pointer: *mut c_void, sigchld: sifields_sigchld, } // Internal, for casts to access union fields. Note that some variants // of sifields start with a pointer, which makes the alignment of // sifields vary on 32-bit and 64-bit architectures. #[repr(C)] struct siginfo_f { _siginfo_base: [c_int; 3], sifields: sifields, } impl siginfo_t { unsafe fn sifields(&self) -> &sifields { &(*(self as *const siginfo_t as *const siginfo_f)).sifields } pub unsafe fn si_pid(&self) -> crate::pid_t { self.sifields().sigchld.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.sifields().sigchld.si_uid } pub unsafe fn si_status(&self) -> c_int { self.sifields().sigchld.si_status } pub unsafe fn si_utime(&self) -> c_long { self.sifields().sigchld.si_utime } pub unsafe fn si_stime(&self) -> c_long { self.sifields().sigchld.si_stime } } /// Build an ioctl number for an argumentless ioctl. pub const fn _IO(ty: u32, nr: u32) -> c_int { super::_IOC(super::_IOC_NONE, ty, nr, 0) as c_int } /// Build an ioctl number for an read-only ioctl. pub const fn _IOR(ty: u32, nr: u32) -> c_int { super::_IOC(super::_IOC_READ, ty, nr, mem::size_of::()) as c_int } /// Build an ioctl number for an write-only ioctl. pub const fn _IOW(ty: u32, nr: u32) -> c_int { super::_IOC(super::_IOC_WRITE, ty, nr, mem::size_of::()) as c_int } /// Build an ioctl number for a read-write ioctl. pub const fn _IOWR(ty: u32, nr: u32) -> c_int { super::_IOC(super::_IOC_READ | super::_IOC_WRITE, ty, nr, mem::size_of::()) as c_int } libc/src/unix/linux_like/android/b32/0000775000175000017500000000000015105742312017240 5ustar bdrungbdrunglibc/src/unix/linux_like/android/b32/mod.rs0000644000175000017500000001457315105742312020375 0ustar bdrungbdrunguse crate::prelude::*; // The following definitions are correct for arm and i686, // but may be wrong for mips pub type mode_t = u16; pub type off64_t = c_longlong; pub type sigset_t = c_ulong; pub type socklen_t = i32; pub type time64_t = i64; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct rlimit64 { pub rlim_cur: u64, pub rlim_max: u64, } pub struct stat { pub st_dev: c_ulonglong, __pad0: [c_uchar; 4], __st_ino: crate::ino_t, pub st_mode: c_uint, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulonglong, __pad3: [c_uchar; 4], pub st_size: c_longlong, pub st_blksize: crate::blksize_t, pub st_blocks: c_ulonglong, pub st_atime: c_long, pub st_atime_nsec: c_long, pub st_mtime: c_long, pub st_mtime_nsec: c_long, pub st_ctime: c_long, pub st_ctime_nsec: c_long, pub st_ino: c_ulonglong, } pub struct stat64 { pub st_dev: c_ulonglong, __pad0: [c_uchar; 4], __st_ino: crate::ino_t, pub st_mode: c_uint, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulonglong, __pad3: [c_uchar; 4], pub st_size: c_longlong, pub st_blksize: crate::blksize_t, pub st_blocks: c_ulonglong, pub st_atime: c_long, pub st_atime_nsec: c_long, pub st_mtime: c_long, pub st_mtime_nsec: c_long, pub st_ctime: c_long, pub st_ctime_nsec: c_long, pub st_ino: c_ulonglong, } pub struct statfs64 { pub f_type: u32, pub f_bsize: u32, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::__fsid_t, pub f_namelen: u32, pub f_frsize: u32, pub f_flags: u32, pub f_spare: [u32; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: c_ulong, pub f_bfree: c_ulong, pub f_bavail: c_ulong, pub f_files: c_ulong, pub f_ffree: c_ulong, pub f_favail: c_ulong, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, } pub struct pthread_attr_t { pub flags: u32, pub stack_base: *mut c_void, pub stack_size: size_t, pub guard_size: size_t, pub sched_policy: i32, pub sched_priority: i32, } pub struct pthread_mutex_t { value: c_int, } pub struct pthread_cond_t { value: c_int, } pub struct pthread_rwlock_t { lock: pthread_mutex_t, cond: pthread_cond_t, numLocks: c_int, writerThreadId: c_int, pendingReaders: c_int, pendingWriters: c_int, attr: i32, __reserved: [c_char; 12], } pub struct pthread_barrier_t { __private: [i32; 8], } pub struct pthread_spinlock_t { __private: [i32; 2], } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct statfs { pub f_type: u32, pub f_bsize: u32, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::__fsid_t, pub f_namelen: u32, pub f_frsize: u32, pub f_flags: u32, pub f_spare: [u32; 4], } pub struct sysinfo { pub uptime: c_long, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub _f: [c_char; 8], } } s_no_extra_traits! { pub struct sigset64_t { __bits: [c_ulong; 2], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl fmt::Debug for sigset64_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigset64_t") .field("__bits", &self.__bits) .finish() } } } } // These constants must be of the same type of sigaction.sa_flags pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const RTLD_GLOBAL: c_int = 2; pub const RTLD_NOW: c_int = 0; pub const RTLD_DEFAULT: *mut c_void = -1isize as *mut c_void; pub const PTRACE_GETFPREGS: c_int = 14; pub const PTRACE_SETFPREGS: c_int = 15; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { value: 0 }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { value: 0 }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { lock: PTHREAD_MUTEX_INITIALIZER, cond: PTHREAD_COND_INITIALIZER, numLocks: 0, writerThreadId: 0, pendingReaders: 0, pendingWriters: 0, attr: 0, __reserved: [0; 12], }; pub const PTHREAD_STACK_MIN: size_t = 4096 * 2; pub const CPU_SETSIZE: size_t = 32; pub const __CPU_BITS: size_t = 32; pub const UT_LINESIZE: usize = 8; pub const UT_NAMESIZE: usize = 8; pub const UT_HOSTSIZE: usize = 16; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; extern "C" { pub fn timegm64(tm: *const crate::tm) -> crate::time64_t; } cfg_if! { if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/android/b32/arm.rs0000644000175000017500000005034115105742312020366 0ustar bdrungbdrunguse crate::prelude::*; pub type wchar_t = u32; pub type greg_t = i32; pub type mcontext_t = sigcontext; s! { pub struct sigcontext { pub trap_no: c_ulong, pub error_code: c_ulong, pub oldmask: c_ulong, pub arm_r0: c_ulong, pub arm_r1: c_ulong, pub arm_r2: c_ulong, pub arm_r3: c_ulong, pub arm_r4: c_ulong, pub arm_r5: c_ulong, pub arm_r6: c_ulong, pub arm_r7: c_ulong, pub arm_r8: c_ulong, pub arm_r9: c_ulong, pub arm_r10: c_ulong, pub arm_fp: c_ulong, pub arm_ip: c_ulong, pub arm_sp: c_ulong, pub arm_lr: c_ulong, pub arm_pc: c_ulong, pub arm_cpsr: c_ulong, pub fault_address: c_ulong, } } s_no_extra_traits! { pub struct __c_anonymous_uc_sigmask_with_padding { pub uc_sigmask: crate::sigset_t, /* Android has a wrong (smaller) sigset_t on x86. */ __padding_rt_sigset: u32, } pub union __c_anonymous_uc_sigmask { uc_sigmask: __c_anonymous_uc_sigmask_with_padding, uc_sigmask64: crate::sigset64_t, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask__c_anonymous_union: __c_anonymous_uc_sigmask, /* The kernel adds extra padding after uc_sigmask to match * glibc sigset_t on ARM. */ __padding: [c_char; 120], __align: [c_longlong; 0], uc_regspace: [c_ulong; 128], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __c_anonymous_uc_sigmask_with_padding { fn eq(&self, other: &__c_anonymous_uc_sigmask_with_padding) -> bool { self.uc_sigmask == other.uc_sigmask // Ignore padding } } impl Eq for __c_anonymous_uc_sigmask_with_padding {} impl fmt::Debug for __c_anonymous_uc_sigmask_with_padding { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("uc_sigmask_with_padding") .field("uc_sigmask_with_padding", &self.uc_sigmask) // Ignore padding .finish() } } impl hash::Hash for __c_anonymous_uc_sigmask_with_padding { fn hash(&self, state: &mut H) { self.uc_sigmask.hash(state) // Ignore padding } } impl PartialEq for __c_anonymous_uc_sigmask { fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool { unsafe { self.uc_sigmask == other.uc_sigmask } } } impl Eq for __c_anonymous_uc_sigmask {} impl hash::Hash for __c_anonymous_uc_sigmask { fn hash(&self, state: &mut H) { unsafe { self.uc_sigmask.hash(state) } } } impl PartialEq for ucontext_t { fn eq(&self, other: &Self) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask__c_anonymous_union == other.uc_sigmask__c_anonymous_union && &self.uc_regspace[..] == &other.uc_regspace[..] // Ignore padding field } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field( "uc_sigmask__c_anonymous_union", &self.uc_sigmask__c_anonymous_union, ) .field("uc_regspace", &&self.uc_regspace[..]) // Ignore padding field .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask__c_anonymous_union.hash(state); self.uc_regspace[..].hash(state); // Ignore padding field } } } } pub const O_DIRECT: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_LARGEFILE: c_int = 0o400000; pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_ptrace: c_long = 26; pub const SYS_pause: c_long = 29; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_setpgid: c_long = 57; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_symlink: c_long = 83; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_vhangup: c_long = 111; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS_getdents: c_long = 141; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_setresgid: c_long = 170; pub const SYS_getresgid: c_long = 171; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_chown: c_long = 182; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_vfork: c_long = 190; pub const SYS_ugetrlimit: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_lchown32: c_long = 198; pub const SYS_getuid32: c_long = 199; pub const SYS_getgid32: c_long = 200; pub const SYS_geteuid32: c_long = 201; pub const SYS_getegid32: c_long = 202; pub const SYS_setreuid32: c_long = 203; pub const SYS_setregid32: c_long = 204; pub const SYS_getgroups32: c_long = 205; pub const SYS_setgroups32: c_long = 206; pub const SYS_fchown32: c_long = 207; pub const SYS_setresuid32: c_long = 208; pub const SYS_getresuid32: c_long = 209; pub const SYS_setresgid32: c_long = 210; pub const SYS_getresgid32: c_long = 211; pub const SYS_chown32: c_long = 212; pub const SYS_setuid32: c_long = 213; pub const SYS_setgid32: c_long = 214; pub const SYS_setfsuid32: c_long = 215; pub const SYS_setfsgid32: c_long = 216; pub const SYS_getdents64: c_long = 217; pub const SYS_pivot_root: c_long = 218; pub const SYS_mincore: c_long = 219; pub const SYS_madvise: c_long = 220; pub const SYS_fcntl64: c_long = 221; pub const SYS_gettid: c_long = 224; pub const SYS_readahead: c_long = 225; pub const SYS_setxattr: c_long = 226; pub const SYS_lsetxattr: c_long = 227; pub const SYS_fsetxattr: c_long = 228; pub const SYS_getxattr: c_long = 229; pub const SYS_lgetxattr: c_long = 230; pub const SYS_fgetxattr: c_long = 231; pub const SYS_listxattr: c_long = 232; pub const SYS_llistxattr: c_long = 233; pub const SYS_flistxattr: c_long = 234; pub const SYS_removexattr: c_long = 235; pub const SYS_lremovexattr: c_long = 236; pub const SYS_fremovexattr: c_long = 237; pub const SYS_tkill: c_long = 238; pub const SYS_sendfile64: c_long = 239; pub const SYS_futex: c_long = 240; pub const SYS_sched_setaffinity: c_long = 241; pub const SYS_sched_getaffinity: c_long = 242; pub const SYS_io_setup: c_long = 243; pub const SYS_io_destroy: c_long = 244; pub const SYS_io_getevents: c_long = 245; pub const SYS_io_submit: c_long = 246; pub const SYS_io_cancel: c_long = 247; pub const SYS_exit_group: c_long = 248; pub const SYS_lookup_dcookie: c_long = 249; pub const SYS_epoll_create: c_long = 250; pub const SYS_epoll_ctl: c_long = 251; pub const SYS_epoll_wait: c_long = 252; pub const SYS_remap_file_pages: c_long = 253; pub const SYS_set_tid_address: c_long = 256; pub const SYS_timer_create: c_long = 257; pub const SYS_timer_settime: c_long = 258; pub const SYS_timer_gettime: c_long = 259; pub const SYS_timer_getoverrun: c_long = 260; pub const SYS_timer_delete: c_long = 261; pub const SYS_clock_settime: c_long = 262; pub const SYS_clock_gettime: c_long = 263; pub const SYS_clock_getres: c_long = 264; pub const SYS_clock_nanosleep: c_long = 265; pub const SYS_statfs64: c_long = 266; pub const SYS_fstatfs64: c_long = 267; pub const SYS_tgkill: c_long = 268; pub const SYS_utimes: c_long = 269; pub const SYS_arm_fadvise64_64: c_long = 270; pub const SYS_pciconfig_iobase: c_long = 271; pub const SYS_pciconfig_read: c_long = 272; pub const SYS_pciconfig_write: c_long = 273; pub const SYS_mq_open: c_long = 274; pub const SYS_mq_unlink: c_long = 275; pub const SYS_mq_timedsend: c_long = 276; pub const SYS_mq_timedreceive: c_long = 277; pub const SYS_mq_notify: c_long = 278; pub const SYS_mq_getsetattr: c_long = 279; pub const SYS_waitid: c_long = 280; pub const SYS_socket: c_long = 281; pub const SYS_bind: c_long = 282; pub const SYS_connect: c_long = 283; pub const SYS_listen: c_long = 284; pub const SYS_accept: c_long = 285; pub const SYS_getsockname: c_long = 286; pub const SYS_getpeername: c_long = 287; pub const SYS_socketpair: c_long = 288; pub const SYS_send: c_long = 289; pub const SYS_sendto: c_long = 290; pub const SYS_recv: c_long = 291; pub const SYS_recvfrom: c_long = 292; pub const SYS_shutdown: c_long = 293; pub const SYS_setsockopt: c_long = 294; pub const SYS_getsockopt: c_long = 295; pub const SYS_sendmsg: c_long = 296; pub const SYS_recvmsg: c_long = 297; pub const SYS_semop: c_long = 298; pub const SYS_semget: c_long = 299; pub const SYS_semctl: c_long = 300; pub const SYS_msgsnd: c_long = 301; pub const SYS_msgrcv: c_long = 302; pub const SYS_msgget: c_long = 303; pub const SYS_msgctl: c_long = 304; pub const SYS_shmat: c_long = 305; pub const SYS_shmdt: c_long = 306; pub const SYS_shmget: c_long = 307; pub const SYS_shmctl: c_long = 308; pub const SYS_add_key: c_long = 309; pub const SYS_request_key: c_long = 310; pub const SYS_keyctl: c_long = 311; pub const SYS_semtimedop: c_long = 312; pub const SYS_vserver: c_long = 313; pub const SYS_ioprio_set: c_long = 314; pub const SYS_ioprio_get: c_long = 315; pub const SYS_inotify_init: c_long = 316; pub const SYS_inotify_add_watch: c_long = 317; pub const SYS_inotify_rm_watch: c_long = 318; pub const SYS_mbind: c_long = 319; pub const SYS_get_mempolicy: c_long = 320; pub const SYS_set_mempolicy: c_long = 321; pub const SYS_openat: c_long = 322; pub const SYS_mkdirat: c_long = 323; pub const SYS_mknodat: c_long = 324; pub const SYS_fchownat: c_long = 325; pub const SYS_futimesat: c_long = 326; pub const SYS_fstatat64: c_long = 327; pub const SYS_unlinkat: c_long = 328; pub const SYS_renameat: c_long = 329; pub const SYS_linkat: c_long = 330; pub const SYS_symlinkat: c_long = 331; pub const SYS_readlinkat: c_long = 332; pub const SYS_fchmodat: c_long = 333; pub const SYS_faccessat: c_long = 334; pub const SYS_pselect6: c_long = 335; pub const SYS_ppoll: c_long = 336; pub const SYS_unshare: c_long = 337; pub const SYS_set_robust_list: c_long = 338; pub const SYS_get_robust_list: c_long = 339; pub const SYS_splice: c_long = 340; pub const SYS_arm_sync_file_range: c_long = 341; pub const SYS_tee: c_long = 342; pub const SYS_vmsplice: c_long = 343; pub const SYS_move_pages: c_long = 344; pub const SYS_getcpu: c_long = 345; pub const SYS_epoll_pwait: c_long = 346; pub const SYS_kexec_load: c_long = 347; pub const SYS_utimensat: c_long = 348; pub const SYS_signalfd: c_long = 349; pub const SYS_timerfd_create: c_long = 350; pub const SYS_eventfd: c_long = 351; pub const SYS_fallocate: c_long = 352; pub const SYS_timerfd_settime: c_long = 353; pub const SYS_timerfd_gettime: c_long = 354; pub const SYS_signalfd4: c_long = 355; pub const SYS_eventfd2: c_long = 356; pub const SYS_epoll_create1: c_long = 357; pub const SYS_dup3: c_long = 358; pub const SYS_pipe2: c_long = 359; pub const SYS_inotify_init1: c_long = 360; pub const SYS_preadv: c_long = 361; pub const SYS_pwritev: c_long = 362; pub const SYS_rt_tgsigqueueinfo: c_long = 363; pub const SYS_perf_event_open: c_long = 364; pub const SYS_recvmmsg: c_long = 365; pub const SYS_accept4: c_long = 366; pub const SYS_fanotify_init: c_long = 367; pub const SYS_fanotify_mark: c_long = 368; pub const SYS_prlimit64: c_long = 369; pub const SYS_name_to_handle_at: c_long = 370; pub const SYS_open_by_handle_at: c_long = 371; pub const SYS_clock_adjtime: c_long = 372; pub const SYS_syncfs: c_long = 373; pub const SYS_sendmmsg: c_long = 374; pub const SYS_setns: c_long = 375; pub const SYS_process_vm_readv: c_long = 376; pub const SYS_process_vm_writev: c_long = 377; pub const SYS_kcmp: c_long = 378; pub const SYS_finit_module: c_long = 379; pub const SYS_sched_setattr: c_long = 380; pub const SYS_sched_getattr: c_long = 381; pub const SYS_renameat2: c_long = 382; pub const SYS_seccomp: c_long = 383; pub const SYS_getrandom: c_long = 384; pub const SYS_memfd_create: c_long = 385; pub const SYS_bpf: c_long = 386; pub const SYS_execveat: c_long = 387; pub const SYS_userfaultfd: c_long = 388; pub const SYS_membarrier: c_long = 389; pub const SYS_mlock2: c_long = 390; pub const SYS_copy_file_range: c_long = 391; pub const SYS_preadv2: c_long = 392; pub const SYS_pwritev2: c_long = 393; pub const SYS_pkey_mprotect: c_long = 394; pub const SYS_pkey_alloc: c_long = 395; pub const SYS_pkey_free: c_long = 396; pub const SYS_statx: c_long = 397; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_R0: c_int = 0; pub const REG_R1: c_int = 1; pub const REG_R2: c_int = 2; pub const REG_R3: c_int = 3; pub const REG_R4: c_int = 4; pub const REG_R5: c_int = 5; pub const REG_R6: c_int = 6; pub const REG_R7: c_int = 7; pub const REG_R8: c_int = 8; pub const REG_R9: c_int = 9; pub const REG_R10: c_int = 10; pub const REG_R11: c_int = 11; pub const REG_R12: c_int = 12; pub const REG_R13: c_int = 13; pub const REG_R14: c_int = 14; pub const REG_R15: c_int = 15; pub const NGREG: c_int = 18; // From NDK's asm/auxvec.h pub const AT_SYSINFO_EHDR: c_ulong = 33; f! { // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not // exposed by the libc. As work-around, we implement it through `syscall` // directly. This workaround can be removed if the minimum version of // Android is bumped. When the workaround is removed, `accept4` can be // moved back to `linux_like/mod.rs` pub fn accept4( fd: c_int, addr: *mut crate::sockaddr, len: *mut crate::socklen_t, flg: c_int, ) -> c_int { crate::syscall(SYS_accept4, fd, addr, len, flg) as c_int } } libc/src/unix/linux_like/android/b32/x86/0000775000175000017500000000000015105742312017665 5ustar bdrungbdrunglibc/src/unix/linux_like/android/b32/x86/mod.rs0000644000175000017500000005522615105742312021022 0ustar bdrungbdrunguse crate::prelude::*; pub type wchar_t = i32; pub type greg_t = i32; s! { pub struct _libc_fpreg { pub significand: [u16; 4], pub exponent: u16, } pub struct _libc_fpstate { pub cw: c_ulong, pub sw: c_ulong, pub tag: c_ulong, pub ipoff: c_ulong, pub cssel: c_ulong, pub dataoff: c_ulong, pub datasel: c_ulong, pub _st: [_libc_fpreg; 8], pub status: c_ulong, } pub struct mcontext_t { pub gregs: [greg_t; 19], pub fpregs: *mut _libc_fpstate, pub oldmask: c_ulong, pub cr2: c_ulong, } } s_no_extra_traits! { pub struct __c_anonymous_uc_sigmask_with_padding { pub uc_sigmask: crate::sigset_t, /* Android has a wrong (smaller) sigset_t on x86. */ __padding_rt_sigset: u32, } pub union __c_anonymous_uc_sigmask { uc_sigmask: __c_anonymous_uc_sigmask_with_padding, uc_sigmask64: crate::sigset64_t, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask__c_anonymous_union: __c_anonymous_uc_sigmask, __padding_rt_sigset: u32, __fpregs_mem: _libc_fpstate, } #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f64; 2], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __c_anonymous_uc_sigmask_with_padding { fn eq(&self, other: &__c_anonymous_uc_sigmask_with_padding) -> bool { self.uc_sigmask == other.uc_sigmask // Ignore padding } } impl Eq for __c_anonymous_uc_sigmask_with_padding {} impl fmt::Debug for __c_anonymous_uc_sigmask_with_padding { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("uc_sigmask_with_padding") .field("uc_sigmask_with_padding", &self.uc_sigmask) // Ignore padding .finish() } } impl hash::Hash for __c_anonymous_uc_sigmask_with_padding { fn hash(&self, state: &mut H) { self.uc_sigmask.hash(state) // Ignore padding } } impl PartialEq for __c_anonymous_uc_sigmask { fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool { unsafe { self.uc_sigmask == other.uc_sigmask } } } impl Eq for __c_anonymous_uc_sigmask {} impl hash::Hash for __c_anonymous_uc_sigmask { fn hash(&self, state: &mut H) { unsafe { self.uc_sigmask.hash(state) } } } impl PartialEq for ucontext_t { fn eq(&self, other: &Self) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask__c_anonymous_union == other.uc_sigmask__c_anonymous_union // Ignore padding field } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field( "uc_sigmask__c_anonymous_union", &self.uc_sigmask__c_anonymous_union, ) // Ignore padding field .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask__c_anonymous_union.hash(state); // Ignore padding field } } } } pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_LARGEFILE: c_int = 0o0100000; pub const MAP_32BIT: c_int = 0x40; // Syscall table pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_waitpid: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_time: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_break: c_long = 17; pub const SYS_oldstat: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_stime: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_oldfstat: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_stty: c_long = 31; pub const SYS_gtty: c_long = 32; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_ftime: c_long = 35; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_prof: c_long = 44; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_lock: c_long = 53; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_mpx: c_long = 56; pub const SYS_setpgid: c_long = 57; pub const SYS_ulimit: c_long = 58; pub const SYS_oldolduname: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sgetmask: c_long = 68; pub const SYS_ssetmask: c_long = 69; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrlimit: c_long = 76; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_select: c_long = 82; pub const SYS_symlink: c_long = 83; pub const SYS_oldlstat: c_long = 84; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_profil: c_long = 98; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_ioperm: c_long = 101; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_olduname: c_long = 109; pub const SYS_iopl: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_vm86old: c_long = 113; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_modify_ldt: c_long = 123; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; // FIXME(android): SYS__llseek is in the NDK sources but for some reason is // not available in the tests // pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; // FIXME(android): SYS__newselect is in the NDK sources but for some reason is // not available in the tests // pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; // FIXME(android): SYS__llseek is in the NDK sources but for some reason is // not available in the tests // pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; pub const SYS_vm86: c_long = 166; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 167; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_setresgid: c_long = 170; pub const SYS_getresgid: c_long = 171; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_chown: c_long = 182; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_getpmsg: c_long = 188; pub const SYS_putpmsg: c_long = 189; pub const SYS_vfork: c_long = 190; pub const SYS_ugetrlimit: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_lchown32: c_long = 198; pub const SYS_getuid32: c_long = 199; pub const SYS_getgid32: c_long = 200; pub const SYS_geteuid32: c_long = 201; pub const SYS_getegid32: c_long = 202; pub const SYS_setreuid32: c_long = 203; pub const SYS_setregid32: c_long = 204; pub const SYS_getgroups32: c_long = 205; pub const SYS_setgroups32: c_long = 206; pub const SYS_fchown32: c_long = 207; pub const SYS_setresuid32: c_long = 208; pub const SYS_getresuid32: c_long = 209; pub const SYS_setresgid32: c_long = 210; pub const SYS_getresgid32: c_long = 211; pub const SYS_chown32: c_long = 212; pub const SYS_setuid32: c_long = 213; pub const SYS_setgid32: c_long = 214; pub const SYS_setfsuid32: c_long = 215; pub const SYS_setfsgid32: c_long = 216; pub const SYS_pivot_root: c_long = 217; pub const SYS_mincore: c_long = 218; pub const SYS_madvise: c_long = 219; pub const SYS_getdents64: c_long = 220; pub const SYS_fcntl64: c_long = 221; pub const SYS_gettid: c_long = 224; pub const SYS_readahead: c_long = 225; pub const SYS_setxattr: c_long = 226; pub const SYS_lsetxattr: c_long = 227; pub const SYS_fsetxattr: c_long = 228; pub const SYS_getxattr: c_long = 229; pub const SYS_lgetxattr: c_long = 230; pub const SYS_fgetxattr: c_long = 231; pub const SYS_listxattr: c_long = 232; pub const SYS_llistxattr: c_long = 233; pub const SYS_flistxattr: c_long = 234; pub const SYS_removexattr: c_long = 235; pub const SYS_lremovexattr: c_long = 236; pub const SYS_fremovexattr: c_long = 237; pub const SYS_tkill: c_long = 238; pub const SYS_sendfile64: c_long = 239; pub const SYS_futex: c_long = 240; pub const SYS_sched_setaffinity: c_long = 241; pub const SYS_sched_getaffinity: c_long = 242; pub const SYS_set_thread_area: c_long = 243; pub const SYS_get_thread_area: c_long = 244; pub const SYS_io_setup: c_long = 245; pub const SYS_io_destroy: c_long = 246; pub const SYS_io_getevents: c_long = 247; pub const SYS_io_submit: c_long = 248; pub const SYS_io_cancel: c_long = 249; pub const SYS_fadvise64: c_long = 250; pub const SYS_exit_group: c_long = 252; pub const SYS_lookup_dcookie: c_long = 253; pub const SYS_epoll_create: c_long = 254; pub const SYS_epoll_ctl: c_long = 255; pub const SYS_epoll_wait: c_long = 256; pub const SYS_remap_file_pages: c_long = 257; pub const SYS_set_tid_address: c_long = 258; pub const SYS_timer_create: c_long = 259; pub const SYS_timer_settime: c_long = 260; pub const SYS_timer_gettime: c_long = 261; pub const SYS_timer_getoverrun: c_long = 262; pub const SYS_timer_delete: c_long = 263; pub const SYS_clock_settime: c_long = 264; pub const SYS_clock_gettime: c_long = 265; pub const SYS_clock_getres: c_long = 266; pub const SYS_clock_nanosleep: c_long = 267; pub const SYS_statfs64: c_long = 268; pub const SYS_fstatfs64: c_long = 269; pub const SYS_tgkill: c_long = 270; pub const SYS_utimes: c_long = 271; pub const SYS_fadvise64_64: c_long = 272; pub const SYS_vserver: c_long = 273; pub const SYS_mbind: c_long = 274; pub const SYS_get_mempolicy: c_long = 275; pub const SYS_set_mempolicy: c_long = 276; pub const SYS_mq_open: c_long = 277; pub const SYS_mq_unlink: c_long = 278; pub const SYS_mq_timedsend: c_long = 279; pub const SYS_mq_timedreceive: c_long = 280; pub const SYS_mq_notify: c_long = 281; pub const SYS_mq_getsetattr: c_long = 282; pub const SYS_kexec_load: c_long = 283; pub const SYS_waitid: c_long = 284; pub const SYS_add_key: c_long = 286; pub const SYS_request_key: c_long = 287; pub const SYS_keyctl: c_long = 288; pub const SYS_ioprio_set: c_long = 289; pub const SYS_ioprio_get: c_long = 290; pub const SYS_inotify_init: c_long = 291; pub const SYS_inotify_add_watch: c_long = 292; pub const SYS_inotify_rm_watch: c_long = 293; pub const SYS_migrate_pages: c_long = 294; pub const SYS_openat: c_long = 295; pub const SYS_mkdirat: c_long = 296; pub const SYS_mknodat: c_long = 297; pub const SYS_fchownat: c_long = 298; pub const SYS_futimesat: c_long = 299; pub const SYS_fstatat64: c_long = 300; pub const SYS_unlinkat: c_long = 301; pub const SYS_renameat: c_long = 302; pub const SYS_linkat: c_long = 303; pub const SYS_symlinkat: c_long = 304; pub const SYS_readlinkat: c_long = 305; pub const SYS_fchmodat: c_long = 306; pub const SYS_faccessat: c_long = 307; pub const SYS_pselect6: c_long = 308; pub const SYS_ppoll: c_long = 309; pub const SYS_unshare: c_long = 310; pub const SYS_set_robust_list: c_long = 311; pub const SYS_get_robust_list: c_long = 312; pub const SYS_splice: c_long = 313; pub const SYS_sync_file_range: c_long = 314; pub const SYS_tee: c_long = 315; pub const SYS_vmsplice: c_long = 316; pub const SYS_move_pages: c_long = 317; pub const SYS_getcpu: c_long = 318; pub const SYS_epoll_pwait: c_long = 319; pub const SYS_utimensat: c_long = 320; pub const SYS_signalfd: c_long = 321; pub const SYS_timerfd_create: c_long = 322; pub const SYS_eventfd: c_long = 323; pub const SYS_fallocate: c_long = 324; pub const SYS_timerfd_settime: c_long = 325; pub const SYS_timerfd_gettime: c_long = 326; pub const SYS_signalfd4: c_long = 327; pub const SYS_eventfd2: c_long = 328; pub const SYS_epoll_create1: c_long = 329; pub const SYS_dup3: c_long = 330; pub const SYS_pipe2: c_long = 331; pub const SYS_inotify_init1: c_long = 332; pub const SYS_preadv: c_long = 333; pub const SYS_pwritev: c_long = 334; pub const SYS_rt_tgsigqueueinfo: c_long = 335; pub const SYS_perf_event_open: c_long = 336; pub const SYS_recvmmsg: c_long = 337; pub const SYS_fanotify_init: c_long = 338; pub const SYS_fanotify_mark: c_long = 339; pub const SYS_prlimit64: c_long = 340; pub const SYS_name_to_handle_at: c_long = 341; pub const SYS_open_by_handle_at: c_long = 342; pub const SYS_clock_adjtime: c_long = 343; pub const SYS_syncfs: c_long = 344; pub const SYS_sendmmsg: c_long = 345; pub const SYS_setns: c_long = 346; pub const SYS_process_vm_readv: c_long = 347; pub const SYS_process_vm_writev: c_long = 348; pub const SYS_kcmp: c_long = 349; pub const SYS_finit_module: c_long = 350; pub const SYS_sched_setattr: c_long = 351; pub const SYS_sched_getattr: c_long = 352; pub const SYS_renameat2: c_long = 353; pub const SYS_seccomp: c_long = 354; pub const SYS_getrandom: c_long = 355; pub const SYS_memfd_create: c_long = 356; pub const SYS_bpf: c_long = 357; pub const SYS_execveat: c_long = 358; pub const SYS_socket: c_long = 359; pub const SYS_socketpair: c_long = 360; pub const SYS_bind: c_long = 361; pub const SYS_connect: c_long = 362; pub const SYS_listen: c_long = 363; pub const SYS_accept4: c_long = 364; pub const SYS_getsockopt: c_long = 365; pub const SYS_setsockopt: c_long = 366; pub const SYS_getsockname: c_long = 367; pub const SYS_getpeername: c_long = 368; pub const SYS_sendto: c_long = 369; pub const SYS_sendmsg: c_long = 370; pub const SYS_recvfrom: c_long = 371; pub const SYS_recvmsg: c_long = 372; pub const SYS_shutdown: c_long = 373; pub const SYS_userfaultfd: c_long = 374; pub const SYS_membarrier: c_long = 375; pub const SYS_mlock2: c_long = 376; pub const SYS_copy_file_range: c_long = 377; pub const SYS_preadv2: c_long = 378; pub const SYS_pwritev2: c_long = 379; pub const SYS_pkey_mprotect: c_long = 380; pub const SYS_pkey_alloc: c_long = 381; pub const SYS_pkey_free: c_long = 382; pub const SYS_statx: c_long = 383; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; // offsets in user_regs_structs, from sys/reg.h pub const EBX: c_int = 0; pub const ECX: c_int = 1; pub const EDX: c_int = 2; pub const ESI: c_int = 3; pub const EDI: c_int = 4; pub const EBP: c_int = 5; pub const EAX: c_int = 6; pub const DS: c_int = 7; pub const ES: c_int = 8; pub const FS: c_int = 9; pub const GS: c_int = 10; pub const ORIG_EAX: c_int = 11; pub const EIP: c_int = 12; pub const CS: c_int = 13; pub const EFL: c_int = 14; pub const UESP: c_int = 15; pub const SS: c_int = 16; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_GS: c_int = 0; pub const REG_FS: c_int = 1; pub const REG_ES: c_int = 2; pub const REG_DS: c_int = 3; pub const REG_EDI: c_int = 4; pub const REG_ESI: c_int = 5; pub const REG_EBP: c_int = 6; pub const REG_ESP: c_int = 7; pub const REG_EBX: c_int = 8; pub const REG_EDX: c_int = 9; pub const REG_ECX: c_int = 10; pub const REG_EAX: c_int = 11; pub const REG_TRAPNO: c_int = 12; pub const REG_ERR: c_int = 13; pub const REG_EIP: c_int = 14; pub const REG_CS: c_int = 15; pub const REG_EFL: c_int = 16; pub const REG_UESP: c_int = 17; pub const REG_SS: c_int = 18; // From NDK's asm/auxvec.h pub const AT_SYSINFO: c_ulong = 32; pub const AT_SYSINFO_EHDR: c_ulong = 33; pub const AT_VECTOR_SIZE_ARCH: c_ulong = 3; // socketcall values from linux/net.h (only the needed ones, and not public) const SYS_ACCEPT4: c_int = 18; f! { // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not // exposed by the libc. As work-around, we implement it as raw syscall. // Note that for x86, the `accept4` syscall is not available either, // and we must use the `socketcall` syscall instead. // This workaround can be removed if the minimum Android version is bumped. // When the workaround is removed, `accept4` can be moved back // to `linux_like/mod.rs` pub fn accept4( fd: c_int, addr: *mut crate::sockaddr, len: *mut crate::socklen_t, flg: c_int, ) -> c_int { // Arguments are passed as array of `long int` // (which is big enough on x86 for a pointer). let mut args = [fd as c_long, addr as c_long, len as c_long, flg as c_long]; crate::syscall(SYS_socketcall, SYS_ACCEPT4, args[..].as_mut_ptr()) } } libc/src/unix/linux_like/android/b64/0000775000175000017500000000000015105742312017245 5ustar bdrungbdrunglibc/src/unix/linux_like/android/b64/mod.rs0000644000175000017500000002245515105742312020400 0ustar bdrungbdrunguse crate::prelude::*; // The following definitions are correct for aarch64 and x86_64, // but may be wrong for mips64 pub type mode_t = u32; pub type off64_t = i64; pub type socklen_t = u32; s! { pub struct sigset_t { __val: [c_ulong; 1], } pub struct sigaction { pub sa_flags: c_int, pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_restorer: Option, } pub struct rlimit64 { pub rlim_cur: c_ulonglong, pub rlim_max: c_ulonglong, } pub struct pthread_attr_t { pub flags: u32, pub stack_base: *mut c_void, pub stack_size: size_t, pub guard_size: size_t, pub sched_policy: i32, pub sched_priority: i32, __reserved: [c_char; 16], } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct statfs { pub f_type: u64, pub f_bsize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::__fsid_t, pub f_namelen: u64, pub f_frsize: u64, pub f_flags: u64, pub f_spare: [u64; 4], } pub struct sysinfo { pub uptime: c_long, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub _f: [c_char; 0], } pub struct statfs64 { pub f_type: u64, pub f_bsize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::__fsid_t, pub f_namelen: u64, pub f_frsize: u64, pub f_flags: u64, pub f_spare: [u64; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct pthread_barrier_t { __private: [i64; 4], } pub struct pthread_spinlock_t { __private: i64, } } s_no_extra_traits! { pub struct pthread_mutex_t { value: c_int, __reserved: [c_char; 36], } pub struct pthread_cond_t { value: c_int, __reserved: [c_char; 44], } pub struct pthread_rwlock_t { numLocks: c_int, writerThreadId: c_int, pendingReaders: c_int, pendingWriters: c_int, attr: i32, __reserved: [c_char; 36], } pub struct sigset64_t { __bits: [c_ulong; 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { self.value == other.value && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_mutex_t {} impl fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_mutex_t") .field("value", &self.value) // FIXME(debug): .field("__reserved", &self.__reserved) .finish() } } impl hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { self.value.hash(state); self.__reserved.hash(state); } } impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.value == other.value && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_cond_t {} impl fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_cond_t") .field("value", &self.value) // FIXME(debug): .field("__reserved", &self.__reserved) .finish() } } impl hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.value.hash(state); self.__reserved.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { self.numLocks == other.numLocks && self.writerThreadId == other.writerThreadId && self.pendingReaders == other.pendingReaders && self.pendingWriters == other.pendingWriters && self.attr == other.attr && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_rwlock_t {} impl fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_rwlock_t") .field("numLocks", &self.numLocks) .field("writerThreadId", &self.writerThreadId) .field("pendingReaders", &self.pendingReaders) .field("pendingWriters", &self.pendingWriters) .field("attr", &self.attr) // FIXME(debug): .field("__reserved", &self.__reserved) .finish() } } impl hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { self.numLocks.hash(state); self.writerThreadId.hash(state); self.pendingReaders.hash(state); self.pendingWriters.hash(state); self.attr.hash(state); self.__reserved.hash(state); } } impl fmt::Debug for sigset64_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigset64_t") .field("__bits", &self.__bits) .finish() } } } } // These constants must be of the same type of sigaction.sa_flags pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const RTLD_GLOBAL: c_int = 0x00100; pub const RTLD_NOW: c_int = 2; pub const RTLD_DEFAULT: *mut c_void = 0i64 as *mut c_void; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { value: 0, __reserved: [0; 36], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { value: 0, __reserved: [0; 44], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { numLocks: 0, writerThreadId: 0, pendingReaders: 0, pendingWriters: 0, attr: 0, __reserved: [0; 36], }; pub const PTHREAD_STACK_MIN: size_t = 4096 * 4; pub const CPU_SETSIZE: size_t = 1024; pub const __CPU_BITS: size_t = 64; pub const UT_LINESIZE: usize = 32; pub const UT_NAMESIZE: usize = 32; pub const UT_HOSTSIZE: usize = 256; f! { // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not // exposed by the libc. As work-around, we implement it through `syscall` // directly. This workaround can be removed if the minimum version of // Android is bumped. When the workaround is removed, `accept4` can be // moved back to `linux_like/mod.rs` pub fn accept4( fd: c_int, addr: *mut crate::sockaddr, len: *mut crate::socklen_t, flg: c_int, ) -> c_int { crate::syscall(SYS_accept4, fd, addr, len, flg) as c_int } } extern "C" { pub fn __system_property_wait( pi: *const crate::prop_info, __old_serial: u32, __new_serial_ptr: *mut u32, __relative_timeout: *const crate::timespec, ) -> bool; } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/android/b64/x86_64/0000775000175000017500000000000015105742312020203 5ustar bdrungbdrunglibc/src/unix/linux_like/android/b64/x86_64/mod.rs0000644000175000017500000006745115105742312021343 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type wchar_t = i32; pub type greg_t = i64; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: c_ulong, pub st_mode: c_uint, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off64_t, pub st_blksize: c_long, pub st_blocks: c_long, pub st_atime: c_long, pub st_atime_nsec: c_long, pub st_mtime: c_long, pub st_mtime_nsec: c_long, pub st_ctime: c_long, pub st_ctime_nsec: c_long, __unused: [c_long; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: c_ulong, pub st_mode: c_uint, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off64_t, pub st_blksize: c_long, pub st_blocks: c_long, pub st_atime: c_long, pub st_atime_nsec: c_long, pub st_mtime: c_long, pub st_mtime_nsec: c_long, pub st_ctime: c_long, pub st_ctime_nsec: c_long, __unused: [c_long; 3], } pub struct _libc_xmmreg { pub element: [u32; 4], } pub struct user_regs_struct { pub r15: c_ulong, pub r14: c_ulong, pub r13: c_ulong, pub r12: c_ulong, pub rbp: c_ulong, pub rbx: c_ulong, pub r11: c_ulong, pub r10: c_ulong, pub r9: c_ulong, pub r8: c_ulong, pub rax: c_ulong, pub rcx: c_ulong, pub rdx: c_ulong, pub rsi: c_ulong, pub rdi: c_ulong, pub orig_rax: c_ulong, pub rip: c_ulong, pub cs: c_ulong, pub eflags: c_ulong, pub rsp: c_ulong, pub ss: c_ulong, pub fs_base: c_ulong, pub gs_base: c_ulong, pub ds: c_ulong, pub es: c_ulong, pub fs: c_ulong, pub gs: c_ulong, } pub struct user { pub regs: user_regs_struct, pub u_fpvalid: c_int, pub i387: user_fpregs_struct, pub u_tsize: c_ulong, pub u_dsize: c_ulong, pub u_ssize: c_ulong, pub start_code: c_ulong, pub start_stack: c_ulong, pub signal: c_long, __reserved: c_int, #[cfg(target_pointer_width = "32")] __pad1: u32, pub u_ar0: *mut user_regs_struct, #[cfg(target_pointer_width = "32")] __pad2: u32, pub u_fpstate: *mut user_fpregs_struct, pub magic: c_ulong, pub u_comm: [c_char; 32], pub u_debugreg: [c_ulong; 8], pub error_code: c_ulong, pub fault_address: c_ulong, } } s_no_extra_traits! { pub union __c_anonymous_uc_sigmask { uc_sigmask: crate::sigset_t, uc_sigmask64: crate::sigset64_t, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __c_anonymous_uc_sigmask { fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool { unsafe { self.uc_sigmask == other.uc_sigmask } } } impl Eq for __c_anonymous_uc_sigmask {} impl hash::Hash for __c_anonymous_uc_sigmask { fn hash(&self, state: &mut H) { unsafe { self.uc_sigmask.hash(state) } } } } } s_no_extra_traits! { pub struct _libc_fpxreg { pub significand: [u16; 4], pub exponent: u16, __padding: [u16; 3], } pub struct _libc_fpstate { pub cwd: u16, pub swd: u16, pub ftw: u16, pub fop: u16, pub rip: u64, pub rdp: u64, pub mxcsr: u32, pub mxcr_mask: u32, pub _st: [_libc_fpxreg; 8], pub _xmm: [_libc_xmmreg; 16], __private: [u32; 24], } pub struct mcontext_t { pub gregs: [greg_t; 23], pub fpregs: *mut _libc_fpstate, __private: [u64; 8], } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask64: __c_anonymous_uc_sigmask, __fpregs_mem: _libc_fpstate, } pub struct user_fpregs_struct { pub cwd: c_ushort, pub swd: c_ushort, pub ftw: c_ushort, pub fop: c_ushort, pub rip: c_ulong, pub rdp: c_ulong, pub mxcsr: c_uint, pub mxcr_mask: c_uint, pub st_space: [c_uint; 32], pub xmm_space: [c_uint; 64], padding: [c_uint; 24], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for _libc_fpxreg { fn eq(&self, other: &Self) -> bool { self.significand == other.significand && self.exponent == other.exponent // Ignore padding field } } impl Eq for _libc_fpxreg {} impl fmt::Debug for _libc_fpxreg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("_libc_fpxreg") .field("significand", &self.significand) .field("exponent", &self.exponent) // Ignore padding field .finish() } } impl hash::Hash for _libc_fpxreg { fn hash(&self, state: &mut H) { self.significand.hash(state); self.exponent.hash(state); // Ignore padding field } } impl PartialEq for _libc_fpstate { fn eq(&self, other: &Self) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.ftw == other.ftw && self.fop == other.fop && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mxcr_mask == other.mxcr_mask && self._st == other._st && self._xmm == other._xmm // Ignore padding field } } impl Eq for _libc_fpstate {} impl fmt::Debug for _libc_fpstate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("_libc_fpstate") .field("cwd", &self.cwd) .field("swd", &self.swd) .field("ftw", &self.ftw) .field("fop", &self.fop) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mxcr_mask", &self.mxcr_mask) .field("_st", &self._st) .field("_xmm", &self._xmm) // Ignore padding field .finish() } } impl hash::Hash for _libc_fpstate { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.swd.hash(state); self.ftw.hash(state); self.fop.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mxcr_mask.hash(state); self._st.hash(state); self._xmm.hash(state); // Ignore padding field } } impl PartialEq for mcontext_t { fn eq(&self, other: &Self) -> bool { self.gregs == other.gregs && self.fpregs == other.fpregs // Ignore padding field } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("gregs", &self.gregs) .field("fpregs", &self.fpregs) // Ignore padding field .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.gregs.hash(state); self.fpregs.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &Self) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask64 == other.uc_sigmask64 // Ignore padding field } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask64", &self.uc_sigmask64) // Ignore padding field .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask64.hash(state); // Ignore padding field } } impl PartialEq for user_fpregs_struct { fn eq(&self, other: &user_fpregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.ftw == other.ftw && self.fop == other.fop && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mxcr_mask == other.mxcr_mask && self.st_space == other.st_space && self .xmm_space .iter() .zip(other.xmm_space.iter()) .all(|(a, b)| a == b) // Ignore padding field } } impl Eq for user_fpregs_struct {} impl fmt::Debug for user_fpregs_struct { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("user_fpregs_struct") .field("cwd", &self.cwd) .field("swd", &self.swd) .field("ftw", &self.ftw) .field("fop", &self.fop) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mxcr_mask", &self.mxcr_mask) .field("st_space", &self.st_space) // FIXME(debug): .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl hash::Hash for user_fpregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.swd.hash(state); self.ftw.hash(state); self.fop.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mxcr_mask.hash(state); self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } } } pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_LARGEFILE: c_int = 0o0100000; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const MAP_32BIT: c_int = 0x40; // Syscall table pub const SYS_read: c_long = 0; pub const SYS_write: c_long = 1; pub const SYS_open: c_long = 2; pub const SYS_close: c_long = 3; pub const SYS_stat: c_long = 4; pub const SYS_fstat: c_long = 5; pub const SYS_lstat: c_long = 6; pub const SYS_poll: c_long = 7; pub const SYS_lseek: c_long = 8; pub const SYS_mmap: c_long = 9; pub const SYS_mprotect: c_long = 10; pub const SYS_munmap: c_long = 11; pub const SYS_brk: c_long = 12; pub const SYS_rt_sigaction: c_long = 13; pub const SYS_rt_sigprocmask: c_long = 14; pub const SYS_rt_sigreturn: c_long = 15; pub const SYS_ioctl: c_long = 16; pub const SYS_pread64: c_long = 17; pub const SYS_pwrite64: c_long = 18; pub const SYS_readv: c_long = 19; pub const SYS_writev: c_long = 20; pub const SYS_access: c_long = 21; pub const SYS_pipe: c_long = 22; pub const SYS_select: c_long = 23; pub const SYS_sched_yield: c_long = 24; pub const SYS_mremap: c_long = 25; pub const SYS_msync: c_long = 26; pub const SYS_mincore: c_long = 27; pub const SYS_madvise: c_long = 28; pub const SYS_shmget: c_long = 29; pub const SYS_shmat: c_long = 30; pub const SYS_shmctl: c_long = 31; pub const SYS_dup: c_long = 32; pub const SYS_dup2: c_long = 33; pub const SYS_pause: c_long = 34; pub const SYS_nanosleep: c_long = 35; pub const SYS_getitimer: c_long = 36; pub const SYS_alarm: c_long = 37; pub const SYS_setitimer: c_long = 38; pub const SYS_getpid: c_long = 39; pub const SYS_sendfile: c_long = 40; pub const SYS_socket: c_long = 41; pub const SYS_connect: c_long = 42; pub const SYS_accept: c_long = 43; pub const SYS_sendto: c_long = 44; pub const SYS_recvfrom: c_long = 45; pub const SYS_sendmsg: c_long = 46; pub const SYS_recvmsg: c_long = 47; pub const SYS_shutdown: c_long = 48; pub const SYS_bind: c_long = 49; pub const SYS_listen: c_long = 50; pub const SYS_getsockname: c_long = 51; pub const SYS_getpeername: c_long = 52; pub const SYS_socketpair: c_long = 53; pub const SYS_setsockopt: c_long = 54; pub const SYS_getsockopt: c_long = 55; pub const SYS_clone: c_long = 56; pub const SYS_fork: c_long = 57; pub const SYS_vfork: c_long = 58; pub const SYS_execve: c_long = 59; pub const SYS_exit: c_long = 60; pub const SYS_wait4: c_long = 61; pub const SYS_kill: c_long = 62; pub const SYS_uname: c_long = 63; pub const SYS_semget: c_long = 64; pub const SYS_semop: c_long = 65; pub const SYS_semctl: c_long = 66; pub const SYS_shmdt: c_long = 67; pub const SYS_msgget: c_long = 68; pub const SYS_msgsnd: c_long = 69; pub const SYS_msgrcv: c_long = 70; pub const SYS_msgctl: c_long = 71; pub const SYS_fcntl: c_long = 72; pub const SYS_flock: c_long = 73; pub const SYS_fsync: c_long = 74; pub const SYS_fdatasync: c_long = 75; pub const SYS_truncate: c_long = 76; pub const SYS_ftruncate: c_long = 77; pub const SYS_getdents: c_long = 78; pub const SYS_getcwd: c_long = 79; pub const SYS_chdir: c_long = 80; pub const SYS_fchdir: c_long = 81; pub const SYS_rename: c_long = 82; pub const SYS_mkdir: c_long = 83; pub const SYS_rmdir: c_long = 84; pub const SYS_creat: c_long = 85; pub const SYS_link: c_long = 86; pub const SYS_unlink: c_long = 87; pub const SYS_symlink: c_long = 88; pub const SYS_readlink: c_long = 89; pub const SYS_chmod: c_long = 90; pub const SYS_fchmod: c_long = 91; pub const SYS_chown: c_long = 92; pub const SYS_fchown: c_long = 93; pub const SYS_lchown: c_long = 94; pub const SYS_umask: c_long = 95; pub const SYS_gettimeofday: c_long = 96; pub const SYS_getrlimit: c_long = 97; pub const SYS_getrusage: c_long = 98; pub const SYS_sysinfo: c_long = 99; pub const SYS_times: c_long = 100; pub const SYS_ptrace: c_long = 101; pub const SYS_getuid: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_getgid: c_long = 104; pub const SYS_setuid: c_long = 105; pub const SYS_setgid: c_long = 106; pub const SYS_geteuid: c_long = 107; pub const SYS_getegid: c_long = 108; pub const SYS_setpgid: c_long = 109; pub const SYS_getppid: c_long = 110; pub const SYS_getpgrp: c_long = 111; pub const SYS_setsid: c_long = 112; pub const SYS_setreuid: c_long = 113; pub const SYS_setregid: c_long = 114; pub const SYS_getgroups: c_long = 115; pub const SYS_setgroups: c_long = 116; pub const SYS_setresuid: c_long = 117; pub const SYS_getresuid: c_long = 118; pub const SYS_setresgid: c_long = 119; pub const SYS_getresgid: c_long = 120; pub const SYS_getpgid: c_long = 121; pub const SYS_setfsuid: c_long = 122; pub const SYS_setfsgid: c_long = 123; pub const SYS_getsid: c_long = 124; pub const SYS_capget: c_long = 125; pub const SYS_capset: c_long = 126; pub const SYS_rt_sigpending: c_long = 127; pub const SYS_rt_sigtimedwait: c_long = 128; pub const SYS_rt_sigqueueinfo: c_long = 129; pub const SYS_rt_sigsuspend: c_long = 130; pub const SYS_sigaltstack: c_long = 131; pub const SYS_utime: c_long = 132; pub const SYS_mknod: c_long = 133; pub const SYS_uselib: c_long = 134; pub const SYS_personality: c_long = 135; pub const SYS_ustat: c_long = 136; pub const SYS_statfs: c_long = 137; pub const SYS_fstatfs: c_long = 138; pub const SYS_sysfs: c_long = 139; pub const SYS_getpriority: c_long = 140; pub const SYS_setpriority: c_long = 141; pub const SYS_sched_setparam: c_long = 142; pub const SYS_sched_getparam: c_long = 143; pub const SYS_sched_setscheduler: c_long = 144; pub const SYS_sched_getscheduler: c_long = 145; pub const SYS_sched_get_priority_max: c_long = 146; pub const SYS_sched_get_priority_min: c_long = 147; pub const SYS_sched_rr_get_interval: c_long = 148; pub const SYS_mlock: c_long = 149; pub const SYS_munlock: c_long = 150; pub const SYS_mlockall: c_long = 151; pub const SYS_munlockall: c_long = 152; pub const SYS_vhangup: c_long = 153; pub const SYS_modify_ldt: c_long = 154; pub const SYS_pivot_root: c_long = 155; // FIXME(android): SYS__sysctl is in the NDK sources but for some reason is // not available in the tests // pub const SYS__sysctl: c_long = 156; pub const SYS_prctl: c_long = 157; pub const SYS_arch_prctl: c_long = 158; pub const SYS_adjtimex: c_long = 159; pub const SYS_setrlimit: c_long = 160; pub const SYS_chroot: c_long = 161; pub const SYS_sync: c_long = 162; pub const SYS_acct: c_long = 163; pub const SYS_settimeofday: c_long = 164; pub const SYS_mount: c_long = 165; pub const SYS_umount2: c_long = 166; pub const SYS_swapon: c_long = 167; pub const SYS_swapoff: c_long = 168; pub const SYS_reboot: c_long = 169; pub const SYS_sethostname: c_long = 170; pub const SYS_setdomainname: c_long = 171; pub const SYS_iopl: c_long = 172; pub const SYS_ioperm: c_long = 173; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 174; pub const SYS_init_module: c_long = 175; pub const SYS_delete_module: c_long = 176; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 177; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 178; pub const SYS_quotactl: c_long = 179; pub const SYS_nfsservctl: c_long = 180; pub const SYS_getpmsg: c_long = 181; pub const SYS_putpmsg: c_long = 182; pub const SYS_afs_syscall: c_long = 183; pub const SYS_tuxcall: c_long = 184; pub const SYS_security: c_long = 185; pub const SYS_gettid: c_long = 186; pub const SYS_readahead: c_long = 187; pub const SYS_setxattr: c_long = 188; pub const SYS_lsetxattr: c_long = 189; pub const SYS_fsetxattr: c_long = 190; pub const SYS_getxattr: c_long = 191; pub const SYS_lgetxattr: c_long = 192; pub const SYS_fgetxattr: c_long = 193; pub const SYS_listxattr: c_long = 194; pub const SYS_llistxattr: c_long = 195; pub const SYS_flistxattr: c_long = 196; pub const SYS_removexattr: c_long = 197; pub const SYS_lremovexattr: c_long = 198; pub const SYS_fremovexattr: c_long = 199; pub const SYS_tkill: c_long = 200; pub const SYS_time: c_long = 201; pub const SYS_futex: c_long = 202; pub const SYS_sched_setaffinity: c_long = 203; pub const SYS_sched_getaffinity: c_long = 204; pub const SYS_set_thread_area: c_long = 205; pub const SYS_io_setup: c_long = 206; pub const SYS_io_destroy: c_long = 207; pub const SYS_io_getevents: c_long = 208; pub const SYS_io_submit: c_long = 209; pub const SYS_io_cancel: c_long = 210; pub const SYS_get_thread_area: c_long = 211; pub const SYS_lookup_dcookie: c_long = 212; pub const SYS_epoll_create: c_long = 213; pub const SYS_epoll_ctl_old: c_long = 214; pub const SYS_epoll_wait_old: c_long = 215; pub const SYS_remap_file_pages: c_long = 216; pub const SYS_getdents64: c_long = 217; pub const SYS_set_tid_address: c_long = 218; pub const SYS_restart_syscall: c_long = 219; pub const SYS_semtimedop: c_long = 220; pub const SYS_fadvise64: c_long = 221; pub const SYS_timer_create: c_long = 222; pub const SYS_timer_settime: c_long = 223; pub const SYS_timer_gettime: c_long = 224; pub const SYS_timer_getoverrun: c_long = 225; pub const SYS_timer_delete: c_long = 226; pub const SYS_clock_settime: c_long = 227; pub const SYS_clock_gettime: c_long = 228; pub const SYS_clock_getres: c_long = 229; pub const SYS_clock_nanosleep: c_long = 230; pub const SYS_exit_group: c_long = 231; pub const SYS_epoll_wait: c_long = 232; pub const SYS_epoll_ctl: c_long = 233; pub const SYS_tgkill: c_long = 234; pub const SYS_utimes: c_long = 235; pub const SYS_vserver: c_long = 236; pub const SYS_mbind: c_long = 237; pub const SYS_set_mempolicy: c_long = 238; pub const SYS_get_mempolicy: c_long = 239; pub const SYS_mq_open: c_long = 240; pub const SYS_mq_unlink: c_long = 241; pub const SYS_mq_timedsend: c_long = 242; pub const SYS_mq_timedreceive: c_long = 243; pub const SYS_mq_notify: c_long = 244; pub const SYS_mq_getsetattr: c_long = 245; pub const SYS_kexec_load: c_long = 246; pub const SYS_waitid: c_long = 247; pub const SYS_add_key: c_long = 248; pub const SYS_request_key: c_long = 249; pub const SYS_keyctl: c_long = 250; pub const SYS_ioprio_set: c_long = 251; pub const SYS_ioprio_get: c_long = 252; pub const SYS_inotify_init: c_long = 253; pub const SYS_inotify_add_watch: c_long = 254; pub const SYS_inotify_rm_watch: c_long = 255; pub const SYS_migrate_pages: c_long = 256; pub const SYS_openat: c_long = 257; pub const SYS_mkdirat: c_long = 258; pub const SYS_mknodat: c_long = 259; pub const SYS_fchownat: c_long = 260; pub const SYS_futimesat: c_long = 261; pub const SYS_newfstatat: c_long = 262; pub const SYS_unlinkat: c_long = 263; pub const SYS_renameat: c_long = 264; pub const SYS_linkat: c_long = 265; pub const SYS_symlinkat: c_long = 266; pub const SYS_readlinkat: c_long = 267; pub const SYS_fchmodat: c_long = 268; pub const SYS_faccessat: c_long = 269; pub const SYS_pselect6: c_long = 270; pub const SYS_ppoll: c_long = 271; pub const SYS_unshare: c_long = 272; pub const SYS_set_robust_list: c_long = 273; pub const SYS_get_robust_list: c_long = 274; pub const SYS_splice: c_long = 275; pub const SYS_tee: c_long = 276; pub const SYS_sync_file_range: c_long = 277; pub const SYS_vmsplice: c_long = 278; pub const SYS_move_pages: c_long = 279; pub const SYS_utimensat: c_long = 280; pub const SYS_epoll_pwait: c_long = 281; pub const SYS_signalfd: c_long = 282; pub const SYS_timerfd_create: c_long = 283; pub const SYS_eventfd: c_long = 284; pub const SYS_fallocate: c_long = 285; pub const SYS_timerfd_settime: c_long = 286; pub const SYS_timerfd_gettime: c_long = 287; pub const SYS_accept4: c_long = 288; pub const SYS_signalfd4: c_long = 289; pub const SYS_eventfd2: c_long = 290; pub const SYS_epoll_create1: c_long = 291; pub const SYS_dup3: c_long = 292; pub const SYS_pipe2: c_long = 293; pub const SYS_inotify_init1: c_long = 294; pub const SYS_preadv: c_long = 295; pub const SYS_pwritev: c_long = 296; pub const SYS_rt_tgsigqueueinfo: c_long = 297; pub const SYS_perf_event_open: c_long = 298; pub const SYS_recvmmsg: c_long = 299; pub const SYS_fanotify_init: c_long = 300; pub const SYS_fanotify_mark: c_long = 301; pub const SYS_prlimit64: c_long = 302; pub const SYS_name_to_handle_at: c_long = 303; pub const SYS_open_by_handle_at: c_long = 304; pub const SYS_clock_adjtime: c_long = 305; pub const SYS_syncfs: c_long = 306; pub const SYS_sendmmsg: c_long = 307; pub const SYS_setns: c_long = 308; pub const SYS_getcpu: c_long = 309; pub const SYS_process_vm_readv: c_long = 310; pub const SYS_process_vm_writev: c_long = 311; pub const SYS_kcmp: c_long = 312; pub const SYS_finit_module: c_long = 313; pub const SYS_sched_setattr: c_long = 314; pub const SYS_sched_getattr: c_long = 315; pub const SYS_renameat2: c_long = 316; pub const SYS_seccomp: c_long = 317; pub const SYS_getrandom: c_long = 318; pub const SYS_memfd_create: c_long = 319; pub const SYS_kexec_file_load: c_long = 320; pub const SYS_bpf: c_long = 321; pub const SYS_execveat: c_long = 322; pub const SYS_userfaultfd: c_long = 323; pub const SYS_membarrier: c_long = 324; pub const SYS_mlock2: c_long = 325; pub const SYS_copy_file_range: c_long = 326; pub const SYS_preadv2: c_long = 327; pub const SYS_pwritev2: c_long = 328; pub const SYS_pkey_mprotect: c_long = 329; pub const SYS_pkey_alloc: c_long = 330; pub const SYS_pkey_free: c_long = 331; pub const SYS_statx: c_long = 332; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; // offsets in user_regs_structs, from sys/reg.h pub const R15: c_int = 0; pub const R14: c_int = 1; pub const R13: c_int = 2; pub const R12: c_int = 3; pub const RBP: c_int = 4; pub const RBX: c_int = 5; pub const R11: c_int = 6; pub const R10: c_int = 7; pub const R9: c_int = 8; pub const R8: c_int = 9; pub const RAX: c_int = 10; pub const RCX: c_int = 11; pub const RDX: c_int = 12; pub const RSI: c_int = 13; pub const RDI: c_int = 14; pub const ORIG_RAX: c_int = 15; pub const RIP: c_int = 16; pub const CS: c_int = 17; pub const EFLAGS: c_int = 18; pub const RSP: c_int = 19; pub const SS: c_int = 20; pub const FS_BASE: c_int = 21; pub const GS_BASE: c_int = 22; pub const DS: c_int = 23; pub const ES: c_int = 24; pub const FS: c_int = 25; pub const GS: c_int = 26; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_R8: c_int = 0; pub const REG_R9: c_int = 1; pub const REG_R10: c_int = 2; pub const REG_R11: c_int = 3; pub const REG_R12: c_int = 4; pub const REG_R13: c_int = 5; pub const REG_R14: c_int = 6; pub const REG_R15: c_int = 7; pub const REG_RDI: c_int = 8; pub const REG_RSI: c_int = 9; pub const REG_RBP: c_int = 10; pub const REG_RBX: c_int = 11; pub const REG_RDX: c_int = 12; pub const REG_RAX: c_int = 13; pub const REG_RCX: c_int = 14; pub const REG_RSP: c_int = 15; pub const REG_RIP: c_int = 16; pub const REG_EFL: c_int = 17; pub const REG_CSGSFS: c_int = 18; pub const REG_ERR: c_int = 19; pub const REG_TRAPNO: c_int = 20; pub const REG_OLDMASK: c_int = 21; pub const REG_CR2: c_int = 22; // From NDK's asm/auxvec.h pub const AT_SYSINFO_EHDR: c_ulong = 33; pub const AT_VECTOR_SIZE_ARCH: c_ulong = 3; libc/src/unix/linux_like/android/b64/aarch64/0000775000175000017500000000000015105742312020475 5ustar bdrungbdrunglibc/src/unix/linux_like/android/b64/aarch64/mod.rs0000644000175000017500000004154415105742312021630 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type wchar_t = u32; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: c_uint, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: c_ulong, pub st_size: off64_t, pub st_blksize: c_int, __pad2: c_int, pub st_blocks: c_long, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused4: c_uint, __unused5: c_uint, } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: c_uint, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: c_ulong, pub st_size: off64_t, pub st_blksize: c_int, __pad2: c_int, pub st_blocks: c_long, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused4: c_uint, __unused5: c_uint, } pub struct user_regs_struct { pub regs: [u64; 31], pub sp: u64, pub pc: u64, pub pstate: u64, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub fault_address: c_ulonglong, pub regs: [c_ulonglong; 31], pub sp: c_ulonglong, pub pc: c_ulonglong, pub pstate: c_ulonglong, __reserved: [u64; 512], } pub struct user_fpsimd_struct { pub vregs: [crate::__uint128_t; 32], pub fpsr: u32, pub fpcr: u32, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f32; 8], } } pub const O_DIRECT: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_LARGEFILE: c_int = 0o400000; pub const SIGSTKSZ: size_t = 16384; pub const MINSIGSTKSZ: size_t = 5120; // From NDK's asm/hwcap.h pub const HWCAP_FP: c_ulong = 1 << 0; pub const HWCAP_ASIMD: c_ulong = 1 << 1; pub const HWCAP_EVTSTRM: c_ulong = 1 << 2; pub const HWCAP_AES: c_ulong = 1 << 3; pub const HWCAP_PMULL: c_ulong = 1 << 4; pub const HWCAP_SHA1: c_ulong = 1 << 5; pub const HWCAP_SHA2: c_ulong = 1 << 6; pub const HWCAP_CRC32: c_ulong = 1 << 7; pub const HWCAP_ATOMICS: c_ulong = 1 << 8; pub const HWCAP_FPHP: c_ulong = 1 << 9; pub const HWCAP_ASIMDHP: c_ulong = 1 << 10; pub const HWCAP_CPUID: c_ulong = 1 << 11; pub const HWCAP_ASIMDRDM: c_ulong = 1 << 12; pub const HWCAP_JSCVT: c_ulong = 1 << 13; pub const HWCAP_FCMA: c_ulong = 1 << 14; pub const HWCAP_LRCPC: c_ulong = 1 << 15; pub const HWCAP_DCPOP: c_ulong = 1 << 16; pub const HWCAP_SHA3: c_ulong = 1 << 17; pub const HWCAP_SM3: c_ulong = 1 << 18; pub const HWCAP_SM4: c_ulong = 1 << 19; pub const HWCAP_ASIMDDP: c_ulong = 1 << 20; pub const HWCAP_SHA512: c_ulong = 1 << 21; pub const HWCAP_SVE: c_ulong = 1 << 22; pub const HWCAP_ASIMDFHM: c_ulong = 1 << 23; pub const HWCAP_DIT: c_ulong = 1 << 24; pub const HWCAP_USCAT: c_ulong = 1 << 25; pub const HWCAP_ILRCPC: c_ulong = 1 << 26; pub const HWCAP_FLAGM: c_ulong = 1 << 27; pub const HWCAP_SSBS: c_ulong = 1 << 28; pub const HWCAP_SB: c_ulong = 1 << 29; pub const HWCAP_PACA: c_ulong = 1 << 30; pub const HWCAP_PACG: c_ulong = 1 << 31; pub const HWCAP2_DCPODP: c_ulong = 1 << 0; pub const HWCAP2_SVE2: c_ulong = 1 << 1; pub const HWCAP2_SVEAES: c_ulong = 1 << 2; pub const HWCAP2_SVEPMULL: c_ulong = 1 << 3; pub const HWCAP2_SVEBITPERM: c_ulong = 1 << 4; pub const HWCAP2_SVESHA3: c_ulong = 1 << 5; pub const HWCAP2_SVESM4: c_ulong = 1 << 6; pub const HWCAP2_FLAGM2: c_ulong = 1 << 7; pub const HWCAP2_FRINT: c_ulong = 1 << 8; pub const HWCAP2_SVEI8MM: c_ulong = 1 << 9; pub const HWCAP2_SVEF32MM: c_ulong = 1 << 10; pub const HWCAP2_SVEF64MM: c_ulong = 1 << 11; pub const HWCAP2_SVEBF16: c_ulong = 1 << 12; pub const HWCAP2_I8MM: c_ulong = 1 << 13; pub const HWCAP2_BF16: c_ulong = 1 << 14; pub const HWCAP2_DGH: c_ulong = 1 << 15; pub const HWCAP2_RNG: c_ulong = 1 << 16; pub const HWCAP2_BTI: c_ulong = 1 << 17; pub const HWCAP2_MTE: c_ulong = 1 << 18; pub const HWCAP2_ECV: c_ulong = 1 << 19; pub const HWCAP2_AFP: c_ulong = 1 << 20; pub const HWCAP2_RPRES: c_ulong = 1 << 21; pub const HWCAP2_MTE3: c_ulong = 1 << 22; pub const HWCAP2_SME: c_ulong = 1 << 23; pub const HWCAP2_SME_I16I64: c_ulong = 1 << 24; pub const HWCAP2_SME_F64F64: c_ulong = 1 << 25; pub const HWCAP2_SME_I8I32: c_ulong = 1 << 26; pub const HWCAP2_SME_F16F32: c_ulong = 1 << 27; pub const HWCAP2_SME_B16F32: c_ulong = 1 << 28; pub const HWCAP2_SME_F32F32: c_ulong = 1 << 29; pub const HWCAP2_SME_FA64: c_ulong = 1 << 30; pub const HWCAP2_WFXT: c_ulong = 1 << 31; pub const HWCAP2_EBF16: c_ulong = 1 << 32; pub const HWCAP2_SVE_EBF16: c_ulong = 1 << 33; pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_io_getevents: c_long = 4; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_getcwd: c_long = 17; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_dup: c_long = 23; pub const SYS_dup3: c_long = 24; pub const SYS_fcntl: c_long = 25; pub const SYS_inotify_init1: c_long = 26; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_ioctl: c_long = 29; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_flock: c_long = 32; pub const SYS_mknodat: c_long = 33; pub const SYS_mkdirat: c_long = 34; pub const SYS_unlinkat: c_long = 35; pub const SYS_symlinkat: c_long = 36; pub const SYS_linkat: c_long = 37; pub const SYS_renameat: c_long = 38; pub const SYS_umount2: c_long = 39; pub const SYS_mount: c_long = 40; pub const SYS_pivot_root: c_long = 41; pub const SYS_nfsservctl: c_long = 42; pub const SYS_fallocate: c_long = 47; pub const SYS_faccessat: c_long = 48; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_chroot: c_long = 51; pub const SYS_fchmod: c_long = 52; pub const SYS_fchmodat: c_long = 53; pub const SYS_fchownat: c_long = 54; pub const SYS_fchown: c_long = 55; pub const SYS_openat: c_long = 56; pub const SYS_close: c_long = 57; pub const SYS_vhangup: c_long = 58; pub const SYS_pipe2: c_long = 59; pub const SYS_quotactl: c_long = 60; pub const SYS_getdents64: c_long = 61; pub const SYS_lseek: c_long = 62; pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_signalfd4: c_long = 74; pub const SYS_vmsplice: c_long = 75; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_readlinkat: c_long = 78; pub const SYS_sync: c_long = 81; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_sync_file_range: c_long = 84; pub const SYS_timerfd_create: c_long = 85; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_utimensat: c_long = 88; pub const SYS_acct: c_long = 89; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_personality: c_long = 92; pub const SYS_exit: c_long = 93; pub const SYS_exit_group: c_long = 94; pub const SYS_waitid: c_long = 95; pub const SYS_set_tid_address: c_long = 96; pub const SYS_unshare: c_long = 97; pub const SYS_futex: c_long = 98; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_kexec_load: c_long = 104; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_syslog: c_long = 116; pub const SYS_ptrace: c_long = 117; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_sched_yield: c_long = 124; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_restart_syscall: c_long = 128; pub const SYS_kill: c_long = 129; pub const SYS_tkill: c_long = 130; pub const SYS_tgkill: c_long = 131; pub const SYS_sigaltstack: c_long = 132; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_setpriority: c_long = 140; pub const SYS_getpriority: c_long = 141; pub const SYS_reboot: c_long = 142; pub const SYS_setregid: c_long = 143; pub const SYS_setgid: c_long = 144; pub const SYS_setreuid: c_long = 145; pub const SYS_setuid: c_long = 146; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_times: c_long = 153; pub const SYS_setpgid: c_long = 154; pub const SYS_getpgid: c_long = 155; pub const SYS_getsid: c_long = 156; pub const SYS_setsid: c_long = 157; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_uname: c_long = 160; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_getrlimit: c_long = 163; pub const SYS_setrlimit: c_long = 164; pub const SYS_getrusage: c_long = 165; pub const SYS_umask: c_long = 166; pub const SYS_prctl: c_long = 167; pub const SYS_getcpu: c_long = 168; pub const SYS_gettimeofday: c_long = 169; pub const SYS_settimeofday: c_long = 170; pub const SYS_adjtimex: c_long = 171; pub const SYS_getpid: c_long = 172; pub const SYS_getppid: c_long = 173; pub const SYS_getuid: c_long = 174; pub const SYS_geteuid: c_long = 175; pub const SYS_getgid: c_long = 176; pub const SYS_getegid: c_long = 177; pub const SYS_gettid: c_long = 178; pub const SYS_sysinfo: c_long = 179; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_msgget: c_long = 186; pub const SYS_msgctl: c_long = 187; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgsnd: c_long = 189; pub const SYS_semget: c_long = 190; pub const SYS_semctl: c_long = 191; pub const SYS_semtimedop: c_long = 192; pub const SYS_semop: c_long = 193; pub const SYS_shmget: c_long = 194; pub const SYS_shmctl: c_long = 195; pub const SYS_shmat: c_long = 196; pub const SYS_shmdt: c_long = 197; pub const SYS_socket: c_long = 198; pub const SYS_socketpair: c_long = 199; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_accept: c_long = 202; pub const SYS_connect: c_long = 203; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_shutdown: c_long = 210; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_readahead: c_long = 213; pub const SYS_brk: c_long = 214; pub const SYS_munmap: c_long = 215; pub const SYS_mremap: c_long = 216; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_mmap: c_long = 222; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_mprotect: c_long = 226; pub const SYS_msync: c_long = 227; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_mbind: c_long = 235; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_migrate_pages: c_long = 238; pub const SYS_move_pages: c_long = 239; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_accept4: c_long = 242; pub const SYS_recvmmsg: c_long = 243; pub const SYS_arch_specific_syscall: c_long = 244; pub const SYS_wait4: c_long = 260; pub const SYS_prlimit64: c_long = 261; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_setns: c_long = 268; pub const SYS_sendmmsg: c_long = 269; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_syscalls: c_long = 451; pub const PROT_BTI: c_int = 0x10; pub const PROT_MTE: c_int = 0x20; // From NDK's asm/auxvec.h pub const AT_SYSINFO_EHDR: c_ulong = 33; pub const AT_VECTOR_SIZE_ARCH: c_ulong = 2; libc/src/unix/linux_like/android/b64/riscv64/0000775000175000017500000000000015105742312020545 5ustar bdrungbdrunglibc/src/unix/linux_like/android/b64/riscv64/mod.rs0000644000175000017500000003356115105742312021700 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type wchar_t = u32; pub type greg_t = i64; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: c_uint, pub st_nlink: c_uint, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: c_ulong, pub st_size: off64_t, pub st_blksize: c_int, __pad2: c_int, pub st_blocks: c_long, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused4: c_uint, __unused5: c_uint, } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: c_uint, pub st_nlink: c_uint, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: c_ulong, pub st_size: off64_t, pub st_blksize: c_int, __pad2: c_int, pub st_blocks: c_long, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused4: c_uint, __unused5: c_uint, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f32; 8], } } pub const O_DIRECT: c_int = 0x40000; pub const O_DIRECTORY: c_int = 0x200000; pub const O_NOFOLLOW: c_int = 0x400000; pub const O_LARGEFILE: c_int = 0x100000; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; // From NDK's asm/hwcap.h pub const COMPAT_HWCAP_ISA_I: c_ulong = 1 << (b'I' - b'A'); pub const COMPAT_HWCAP_ISA_M: c_ulong = 1 << (b'M' - b'A'); pub const COMPAT_HWCAP_ISA_A: c_ulong = 1 << (b'A' - b'A'); pub const COMPAT_HWCAP_ISA_F: c_ulong = 1 << (b'F' - b'A'); pub const COMPAT_HWCAP_ISA_D: c_ulong = 1 << (b'D' - b'A'); pub const COMPAT_HWCAP_ISA_C: c_ulong = 1 << (b'C' - b'A'); pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_io_getevents: c_long = 4; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_getcwd: c_long = 17; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_dup: c_long = 23; pub const SYS_dup3: c_long = 24; pub const SYS_inotify_init1: c_long = 26; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_ioctl: c_long = 29; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_flock: c_long = 32; pub const SYS_mknodat: c_long = 33; pub const SYS_mkdirat: c_long = 34; pub const SYS_unlinkat: c_long = 35; pub const SYS_symlinkat: c_long = 36; pub const SYS_linkat: c_long = 37; pub const SYS_renameat: c_long = 38; pub const SYS_umount2: c_long = 39; pub const SYS_mount: c_long = 40; pub const SYS_pivot_root: c_long = 41; pub const SYS_nfsservctl: c_long = 42; pub const SYS_fallocate: c_long = 47; pub const SYS_faccessat: c_long = 48; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_chroot: c_long = 51; pub const SYS_fchmod: c_long = 52; pub const SYS_fchmodat: c_long = 53; pub const SYS_fchownat: c_long = 54; pub const SYS_fchown: c_long = 55; pub const SYS_openat: c_long = 56; pub const SYS_close: c_long = 57; pub const SYS_vhangup: c_long = 58; pub const SYS_pipe2: c_long = 59; pub const SYS_quotactl: c_long = 60; pub const SYS_getdents64: c_long = 61; pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_signalfd4: c_long = 74; pub const SYS_vmsplice: c_long = 75; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_readlinkat: c_long = 78; pub const SYS_sync: c_long = 81; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_sync_file_range: c_long = 84; pub const SYS_timerfd_create: c_long = 85; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_utimensat: c_long = 88; pub const SYS_acct: c_long = 89; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_personality: c_long = 92; pub const SYS_exit: c_long = 93; pub const SYS_exit_group: c_long = 94; pub const SYS_waitid: c_long = 95; pub const SYS_set_tid_address: c_long = 96; pub const SYS_unshare: c_long = 97; pub const SYS_futex: c_long = 98; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_kexec_load: c_long = 104; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_syslog: c_long = 116; pub const SYS_ptrace: c_long = 117; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_sched_yield: c_long = 124; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_restart_syscall: c_long = 128; pub const SYS_kill: c_long = 129; pub const SYS_tkill: c_long = 130; pub const SYS_tgkill: c_long = 131; pub const SYS_sigaltstack: c_long = 132; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_setpriority: c_long = 140; pub const SYS_getpriority: c_long = 141; pub const SYS_reboot: c_long = 142; pub const SYS_setregid: c_long = 143; pub const SYS_setgid: c_long = 144; pub const SYS_setreuid: c_long = 145; pub const SYS_setuid: c_long = 146; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_times: c_long = 153; pub const SYS_setpgid: c_long = 154; pub const SYS_getpgid: c_long = 155; pub const SYS_getsid: c_long = 156; pub const SYS_setsid: c_long = 157; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_uname: c_long = 160; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_getrlimit: c_long = 163; pub const SYS_setrlimit: c_long = 164; pub const SYS_getrusage: c_long = 165; pub const SYS_umask: c_long = 166; pub const SYS_prctl: c_long = 167; pub const SYS_getcpu: c_long = 168; pub const SYS_gettimeofday: c_long = 169; pub const SYS_settimeofday: c_long = 170; pub const SYS_adjtimex: c_long = 171; pub const SYS_getpid: c_long = 172; pub const SYS_getppid: c_long = 173; pub const SYS_getuid: c_long = 174; pub const SYS_geteuid: c_long = 175; pub const SYS_getgid: c_long = 176; pub const SYS_getegid: c_long = 177; pub const SYS_gettid: c_long = 178; pub const SYS_sysinfo: c_long = 179; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_msgget: c_long = 186; pub const SYS_msgctl: c_long = 187; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgsnd: c_long = 189; pub const SYS_semget: c_long = 190; pub const SYS_semctl: c_long = 191; pub const SYS_semtimedop: c_long = 192; pub const SYS_semop: c_long = 193; pub const SYS_shmget: c_long = 194; pub const SYS_shmctl: c_long = 195; pub const SYS_shmat: c_long = 196; pub const SYS_shmdt: c_long = 197; pub const SYS_socket: c_long = 198; pub const SYS_socketpair: c_long = 199; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_accept: c_long = 202; pub const SYS_connect: c_long = 203; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_shutdown: c_long = 210; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_readahead: c_long = 213; pub const SYS_brk: c_long = 214; pub const SYS_munmap: c_long = 215; pub const SYS_mremap: c_long = 216; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_mprotect: c_long = 226; pub const SYS_msync: c_long = 227; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_mbind: c_long = 235; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_migrate_pages: c_long = 238; pub const SYS_move_pages: c_long = 239; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_accept4: c_long = 242; pub const SYS_recvmmsg: c_long = 243; pub const SYS_arch_specific_syscall: c_long = 244; pub const SYS_wait4: c_long = 260; pub const SYS_prlimit64: c_long = 261; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_setns: c_long = 268; pub const SYS_sendmmsg: c_long = 269; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; // From NDK's asm/auxvec.h pub const AT_SYSINFO_EHDR: c_ulong = 33; pub const AT_L1I_CACHESIZE: c_ulong = 40; pub const AT_L1I_CACHEGEOMETRY: c_ulong = 41; pub const AT_L1D_CACHESIZE: c_ulong = 42; pub const AT_L1D_CACHEGEOMETRY: c_ulong = 43; pub const AT_L2_CACHESIZE: c_ulong = 44; pub const AT_L2_CACHEGEOMETRY: c_ulong = 45; pub const AT_L3_CACHESIZE: c_ulong = 46; pub const AT_L3_CACHEGEOMETRY: c_ulong = 47; pub const AT_VECTOR_SIZE_ARCH: c_ulong = 9; libc/src/unix/linux_like/linux/0000775000175000017500000000000015105742312016371 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/mod.rs0000644000175000017500000071771615105742312017537 0ustar bdrungbdrung//! Linux-specific definitions for linux-like values use core::mem::size_of; use crate::prelude::*; pub type useconds_t = u32; pub type dev_t = u64; pub type socklen_t = u32; pub type mode_t = u32; pub type ino64_t = u64; pub type off64_t = i64; pub type blkcnt64_t = i64; pub type rlim64_t = u64; pub type mqd_t = c_int; pub type nfds_t = c_ulong; pub type nl_item = c_int; pub type idtype_t = c_uint; pub type loff_t = c_longlong; pub type pthread_key_t = c_uint; pub type pthread_once_t = c_int; pub type pthread_spinlock_t = c_int; pub type __kernel_fsid_t = __c_anonymous__kernel_fsid_t; pub type __kernel_clockid_t = c_int; pub type __u8 = c_uchar; pub type __u16 = c_ushort; pub type __s16 = c_short; pub type __u32 = c_uint; pub type __s32 = c_int; pub type Elf32_Half = u16; pub type Elf32_Word = u32; pub type Elf32_Off = u32; pub type Elf32_Addr = u32; pub type Elf32_Xword = u64; pub type Elf32_Sword = i32; pub type Elf64_Half = u16; pub type Elf64_Word = u32; pub type Elf64_Off = u64; pub type Elf64_Addr = u64; pub type Elf64_Xword = u64; pub type Elf64_Sxword = i64; pub type Elf64_Sword = i32; pub type Elf32_Section = u16; pub type Elf64_Section = u16; pub type Elf32_Relr = Elf32_Word; pub type Elf64_Relr = Elf32_Xword; pub type Elf32_Rel = __c_anonymous_elf32_rel; pub type Elf64_Rel = __c_anonymous_elf64_rel; cfg_if! { if #[cfg(not(target_arch = "sparc64"))] { pub type Elf32_Rela = __c_anonymous_elf32_rela; pub type Elf64_Rela = __c_anonymous_elf64_rela; } } // linux/can.h pub type canid_t = u32; // linux/can/j1939.h pub type can_err_mask_t = u32; pub type pgn_t = u32; pub type priority_t = u8; pub type name_t = u64; pub type iconv_t = *mut c_void; // linux/sctp.h pub type sctp_assoc_t = __s32; pub type eventfd_t = u64; cfg_if! { if #[cfg(not(target_env = "gnu"))] { missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos64_t {} // FIXME(linux): fill this out with a struct } } } e! { #[repr(u32)] pub enum tpacket_versions { TPACKET_V1, TPACKET_V2, TPACKET_V3, } } s! { pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct spwd { pub sp_namp: *mut c_char, pub sp_pwdp: *mut c_char, pub sp_lstchg: c_long, pub sp_min: c_long, pub sp_max: c_long, pub sp_warn: c_long, pub sp_inact: c_long, pub sp_expire: c_long, pub sp_flag: c_ulong, } pub struct dqblk { pub dqb_bhardlimit: u64, pub dqb_bsoftlimit: u64, pub dqb_curspace: u64, pub dqb_ihardlimit: u64, pub dqb_isoftlimit: u64, pub dqb_curinodes: u64, pub dqb_btime: u64, pub dqb_itime: u64, pub dqb_valid: u32, } pub struct signalfd_siginfo { pub ssi_signo: u32, pub ssi_errno: i32, pub ssi_code: i32, pub ssi_pid: u32, pub ssi_uid: u32, pub ssi_fd: i32, pub ssi_tid: u32, pub ssi_band: u32, pub ssi_overrun: u32, pub ssi_trapno: u32, pub ssi_status: i32, pub ssi_int: i32, pub ssi_ptr: u64, pub ssi_utime: u64, pub ssi_stime: u64, pub ssi_addr: u64, pub ssi_addr_lsb: u16, _pad2: u16, pub ssi_syscall: i32, pub ssi_call_addr: u64, pub ssi_arch: u32, _pad: [u8; 28], } pub struct itimerspec { pub it_interval: crate::timespec, pub it_value: crate::timespec, } pub struct fsid_t { __val: [c_int; 2], } pub struct fanout_args { #[cfg(target_endian = "little")] pub id: __u16, pub type_flags: __u16, #[cfg(target_endian = "big")] pub id: __u16, pub max_num_members: __u32, } pub struct packet_mreq { pub mr_ifindex: c_int, pub mr_type: c_ushort, pub mr_alen: c_ushort, pub mr_address: [c_uchar; 8], } #[deprecated(since = "0.2.70", note = "sockaddr_ll type must be used instead")] pub struct sockaddr_pkt { pub spkt_family: c_ushort, pub spkt_device: [c_uchar; 14], pub spkt_protocol: c_ushort, } pub struct tpacket_auxdata { pub tp_status: __u32, pub tp_len: __u32, pub tp_snaplen: __u32, pub tp_mac: __u16, pub tp_net: __u16, pub tp_vlan_tci: __u16, pub tp_vlan_tpid: __u16, } pub struct tpacket_hdr { pub tp_status: c_ulong, pub tp_len: c_uint, pub tp_snaplen: c_uint, pub tp_mac: c_ushort, pub tp_net: c_ushort, pub tp_sec: c_uint, pub tp_usec: c_uint, } pub struct tpacket_hdr_variant1 { pub tp_rxhash: __u32, pub tp_vlan_tci: __u32, pub tp_vlan_tpid: __u16, pub tp_padding: __u16, } pub struct tpacket2_hdr { pub tp_status: __u32, pub tp_len: __u32, pub tp_snaplen: __u32, pub tp_mac: __u16, pub tp_net: __u16, pub tp_sec: __u32, pub tp_nsec: __u32, pub tp_vlan_tci: __u16, pub tp_vlan_tpid: __u16, pub tp_padding: [__u8; 4], } pub struct tpacket_req { pub tp_block_size: c_uint, pub tp_block_nr: c_uint, pub tp_frame_size: c_uint, pub tp_frame_nr: c_uint, } pub struct tpacket_req3 { pub tp_block_size: c_uint, pub tp_block_nr: c_uint, pub tp_frame_size: c_uint, pub tp_frame_nr: c_uint, pub tp_retire_blk_tov: c_uint, pub tp_sizeof_priv: c_uint, pub tp_feature_req_word: c_uint, } #[repr(align(8))] pub struct tpacket_rollover_stats { pub tp_all: crate::__u64, pub tp_huge: crate::__u64, pub tp_failed: crate::__u64, } pub struct tpacket_stats { pub tp_packets: c_uint, pub tp_drops: c_uint, } pub struct tpacket_stats_v3 { pub tp_packets: c_uint, pub tp_drops: c_uint, pub tp_freeze_q_cnt: c_uint, } pub struct tpacket3_hdr { pub tp_next_offset: __u32, pub tp_sec: __u32, pub tp_nsec: __u32, pub tp_snaplen: __u32, pub tp_len: __u32, pub tp_status: __u32, pub tp_mac: __u16, pub tp_net: __u16, pub hv1: crate::tpacket_hdr_variant1, pub tp_padding: [__u8; 8], } pub struct tpacket_bd_ts { pub ts_sec: c_uint, pub ts_usec: c_uint, } #[repr(align(8))] pub struct tpacket_hdr_v1 { pub block_status: __u32, pub num_pkts: __u32, pub offset_to_first_pkt: __u32, pub blk_len: __u32, pub seq_num: crate::__u64, pub ts_first_pkt: crate::tpacket_bd_ts, pub ts_last_pkt: crate::tpacket_bd_ts, } pub struct cpu_set_t { #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] bits: [u32; 32], #[cfg(not(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] bits: [u64; 16], } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } // System V IPC pub struct msginfo { pub msgpool: c_int, pub msgmap: c_int, pub msgmax: c_int, pub msgmnb: c_int, pub msgmni: c_int, pub msgssz: c_int, pub msgtql: c_int, pub msgseg: c_ushort, } pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } pub struct input_event { // FIXME(1.0): Change to the commented variant, see https://github.com/rust-lang/libc/pull/4148#discussion_r1857511742 #[cfg(any(target_pointer_width = "64", not(linux_time_bits64)))] pub time: crate::timeval, // #[cfg(any(target_pointer_width = "64", not(linux_time_bits64)))] // pub input_event_sec: time_t, // #[cfg(any(target_pointer_width = "64", not(linux_time_bits64)))] // pub input_event_usec: suseconds_t, // #[cfg(target_arch = "sparc64")] // _pad1: c_int, #[cfg(all(target_pointer_width = "32", linux_time_bits64))] pub input_event_sec: c_ulong, #[cfg(all(target_pointer_width = "32", linux_time_bits64))] pub input_event_usec: c_ulong, pub type_: __u16, pub code: __u16, pub value: __s32, } pub struct input_id { pub bustype: __u16, pub vendor: __u16, pub product: __u16, pub version: __u16, } pub struct input_absinfo { pub value: __s32, pub minimum: __s32, pub maximum: __s32, pub fuzz: __s32, pub flat: __s32, pub resolution: __s32, } pub struct input_keymap_entry { pub flags: __u8, pub len: __u8, pub index: __u16, pub keycode: __u32, pub scancode: [__u8; 32], } pub struct input_mask { pub type_: __u32, pub codes_size: __u32, pub codes_ptr: crate::__u64, } pub struct ff_replay { pub length: __u16, pub delay: __u16, } pub struct ff_trigger { pub button: __u16, pub interval: __u16, } pub struct ff_envelope { pub attack_length: __u16, pub attack_level: __u16, pub fade_length: __u16, pub fade_level: __u16, } pub struct ff_constant_effect { pub level: __s16, pub envelope: ff_envelope, } pub struct ff_ramp_effect { pub start_level: __s16, pub end_level: __s16, pub envelope: ff_envelope, } pub struct ff_condition_effect { pub right_saturation: __u16, pub left_saturation: __u16, pub right_coeff: __s16, pub left_coeff: __s16, pub deadband: __u16, pub center: __s16, } pub struct ff_periodic_effect { pub waveform: __u16, pub period: __u16, pub magnitude: __s16, pub offset: __s16, pub phase: __u16, pub envelope: ff_envelope, pub custom_len: __u32, pub custom_data: *mut __s16, } pub struct ff_rumble_effect { pub strong_magnitude: __u16, pub weak_magnitude: __u16, } pub struct ff_effect { pub type_: __u16, pub id: __s16, pub direction: __u16, pub trigger: ff_trigger, pub replay: ff_replay, // FIXME(1.0): this is actually a union #[cfg(target_pointer_width = "64")] pub u: [u64; 4], #[cfg(target_pointer_width = "32")] pub u: [u32; 7], } pub struct uinput_ff_upload { pub request_id: __u32, pub retval: __s32, pub effect: ff_effect, pub old: ff_effect, } pub struct uinput_ff_erase { pub request_id: __u32, pub retval: __s32, pub effect_id: __u32, } pub struct uinput_abs_setup { pub code: __u16, pub absinfo: input_absinfo, } pub struct dl_phdr_info { #[cfg(target_pointer_width = "64")] pub dlpi_addr: Elf64_Addr, #[cfg(target_pointer_width = "32")] pub dlpi_addr: Elf32_Addr, pub dlpi_name: *const c_char, #[cfg(target_pointer_width = "64")] pub dlpi_phdr: *const Elf64_Phdr, #[cfg(target_pointer_width = "32")] pub dlpi_phdr: *const Elf32_Phdr, #[cfg(target_pointer_width = "64")] pub dlpi_phnum: Elf64_Half, #[cfg(target_pointer_width = "32")] pub dlpi_phnum: Elf32_Half, // As of uClibc 1.0.36, the following fields are // gated behind a "#if 0" block which always evaluates // to false. So I'm just removing these, and if uClibc changes // the #if block in the future to include the following fields, these // will probably need including here. tsidea, skrap // QNX (NTO) platform does not define these fields #[cfg(not(any(target_env = "uclibc", target_os = "nto")))] pub dlpi_adds: c_ulonglong, #[cfg(not(any(target_env = "uclibc", target_os = "nto")))] pub dlpi_subs: c_ulonglong, #[cfg(not(any(target_env = "uclibc", target_os = "nto")))] pub dlpi_tls_modid: size_t, #[cfg(not(any(target_env = "uclibc", target_os = "nto")))] pub dlpi_tls_data: *mut c_void, } pub struct Elf32_Ehdr { pub e_ident: [c_uchar; 16], pub e_type: Elf32_Half, pub e_machine: Elf32_Half, pub e_version: Elf32_Word, pub e_entry: Elf32_Addr, pub e_phoff: Elf32_Off, pub e_shoff: Elf32_Off, pub e_flags: Elf32_Word, pub e_ehsize: Elf32_Half, pub e_phentsize: Elf32_Half, pub e_phnum: Elf32_Half, pub e_shentsize: Elf32_Half, pub e_shnum: Elf32_Half, pub e_shstrndx: Elf32_Half, } pub struct Elf64_Ehdr { pub e_ident: [c_uchar; 16], pub e_type: Elf64_Half, pub e_machine: Elf64_Half, pub e_version: Elf64_Word, pub e_entry: Elf64_Addr, pub e_phoff: Elf64_Off, pub e_shoff: Elf64_Off, pub e_flags: Elf64_Word, pub e_ehsize: Elf64_Half, pub e_phentsize: Elf64_Half, pub e_phnum: Elf64_Half, pub e_shentsize: Elf64_Half, pub e_shnum: Elf64_Half, pub e_shstrndx: Elf64_Half, } pub struct Elf32_Sym { pub st_name: Elf32_Word, pub st_value: Elf32_Addr, pub st_size: Elf32_Word, pub st_info: c_uchar, pub st_other: c_uchar, pub st_shndx: Elf32_Section, } pub struct Elf64_Sym { pub st_name: Elf64_Word, pub st_info: c_uchar, pub st_other: c_uchar, pub st_shndx: Elf64_Section, pub st_value: Elf64_Addr, pub st_size: Elf64_Xword, } pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } pub struct Elf32_Shdr { pub sh_name: Elf32_Word, pub sh_type: Elf32_Word, pub sh_flags: Elf32_Word, pub sh_addr: Elf32_Addr, pub sh_offset: Elf32_Off, pub sh_size: Elf32_Word, pub sh_link: Elf32_Word, pub sh_info: Elf32_Word, pub sh_addralign: Elf32_Word, pub sh_entsize: Elf32_Word, } pub struct Elf64_Shdr { pub sh_name: Elf64_Word, pub sh_type: Elf64_Word, pub sh_flags: Elf64_Xword, pub sh_addr: Elf64_Addr, pub sh_offset: Elf64_Off, pub sh_size: Elf64_Xword, pub sh_link: Elf64_Word, pub sh_info: Elf64_Word, pub sh_addralign: Elf64_Xword, pub sh_entsize: Elf64_Xword, } pub struct __c_anonymous_elf32_rel { pub r_offset: Elf32_Addr, pub r_info: Elf32_Word, } pub struct __c_anonymous_elf64_rel { pub r_offset: Elf64_Addr, pub r_info: Elf64_Xword, } pub struct __c_anonymous__kernel_fsid_t { pub val: [c_int; 2], } pub struct ucred { pub pid: crate::pid_t, pub uid: crate::uid_t, pub gid: crate::gid_t, } pub struct mntent { pub mnt_fsname: *mut c_char, pub mnt_dir: *mut c_char, pub mnt_type: *mut c_char, pub mnt_opts: *mut c_char, pub mnt_freq: c_int, pub mnt_passno: c_int, } pub struct posix_spawn_file_actions_t { __allocated: c_int, __used: c_int, __actions: *mut c_int, __pad: [c_int; 16], } pub struct posix_spawnattr_t { __flags: c_short, __pgrp: crate::pid_t, __sd: crate::sigset_t, __ss: crate::sigset_t, #[cfg(any(target_env = "musl", target_env = "ohos"))] __prio: c_int, #[cfg(not(any(target_env = "musl", target_env = "ohos")))] __sp: crate::sched_param, __policy: c_int, __pad: [c_int; 16], } pub struct genlmsghdr { pub cmd: u8, pub version: u8, pub reserved: u16, } pub struct in6_pktinfo { pub ipi6_addr: crate::in6_addr, pub ipi6_ifindex: c_uint, } pub struct arpd_request { pub req: c_ushort, pub ip: u32, pub dev: c_ulong, pub stamp: c_ulong, pub updated: c_ulong, pub ha: [c_uchar; crate::MAX_ADDR_LEN], } pub struct inotify_event { pub wd: c_int, pub mask: u32, pub cookie: u32, pub len: u32, } pub struct fanotify_response { pub fd: c_int, pub response: __u32, } pub struct fanotify_event_info_header { pub info_type: __u8, pub pad: __u8, pub len: __u16, } pub struct fanotify_event_info_fid { pub hdr: fanotify_event_info_header, pub fsid: crate::__kernel_fsid_t, pub handle: [c_uchar; 0], } pub struct sockaddr_vm { pub svm_family: crate::sa_family_t, pub svm_reserved1: c_ushort, pub svm_port: c_uint, pub svm_cid: c_uint, pub svm_zero: [u8; 4], } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct sock_extended_err { pub ee_errno: u32, pub ee_origin: u8, pub ee_type: u8, pub ee_code: u8, pub ee_pad: u8, pub ee_info: u32, pub ee_data: u32, } // linux/can.h pub struct __c_anonymous_sockaddr_can_tp { pub rx_id: canid_t, pub tx_id: canid_t, } pub struct __c_anonymous_sockaddr_can_j1939 { pub name: u64, pub pgn: u32, pub addr: u8, } pub struct can_filter { pub can_id: canid_t, pub can_mask: canid_t, } // linux/can/j1939.h pub struct j1939_filter { pub name: name_t, pub name_mask: name_t, pub pgn: pgn_t, pub pgn_mask: pgn_t, pub addr: u8, pub addr_mask: u8, } // linux/filter.h pub struct sock_filter { pub code: __u16, pub jt: __u8, pub jf: __u8, pub k: __u32, } pub struct sock_fprog { pub len: c_ushort, pub filter: *mut sock_filter, } // linux/seccomp.h pub struct seccomp_data { pub nr: c_int, pub arch: __u32, pub instruction_pointer: crate::__u64, pub args: [crate::__u64; 6], } pub struct seccomp_notif_sizes { pub seccomp_notif: __u16, pub seccomp_notif_resp: __u16, pub seccomp_data: __u16, } pub struct seccomp_notif { pub id: crate::__u64, pub pid: __u32, pub flags: __u32, pub data: seccomp_data, } pub struct seccomp_notif_resp { pub id: crate::__u64, pub val: crate::__s64, pub error: __s32, pub flags: __u32, } pub struct seccomp_notif_addfd { pub id: crate::__u64, pub flags: __u32, pub srcfd: __u32, pub newfd: __u32, pub newfd_flags: __u32, } pub struct nlmsghdr { pub nlmsg_len: u32, pub nlmsg_type: u16, pub nlmsg_flags: u16, pub nlmsg_seq: u32, pub nlmsg_pid: u32, } pub struct nlmsgerr { pub error: c_int, pub msg: nlmsghdr, } pub struct nlattr { pub nla_len: u16, pub nla_type: u16, } pub struct file_clone_range { pub src_fd: crate::__s64, pub src_offset: crate::__u64, pub src_length: crate::__u64, pub dest_offset: crate::__u64, } pub struct __c_anonymous_ifru_map { pub mem_start: c_ulong, pub mem_end: c_ulong, pub base_addr: c_ushort, pub irq: c_uchar, pub dma: c_uchar, pub port: c_uchar, } pub struct in6_ifreq { pub ifr6_addr: crate::in6_addr, pub ifr6_prefixlen: u32, pub ifr6_ifindex: c_int, } pub struct option { pub name: *const c_char, pub has_arg: c_int, pub flag: *mut c_int, pub val: c_int, } // linux/openat2.h #[non_exhaustive] pub struct open_how { pub flags: crate::__u64, pub mode: crate::__u64, pub resolve: crate::__u64, } // linux/ptp_clock.h pub struct ptp_clock_time { pub sec: crate::__s64, pub nsec: __u32, pub reserved: __u32, } pub struct ptp_extts_request { pub index: c_uint, pub flags: c_uint, pub rsv: [c_uint; 2], } pub struct ptp_sys_offset_extended { pub n_samples: c_uint, pub clockid: __kernel_clockid_t, pub rsv: [c_uint; 2], pub ts: [[ptp_clock_time; 3]; PTP_MAX_SAMPLES as usize], } pub struct ptp_sys_offset_precise { pub device: ptp_clock_time, pub sys_realtime: ptp_clock_time, pub sys_monoraw: ptp_clock_time, pub rsv: [c_uint; 4], } pub struct ptp_extts_event { pub t: ptp_clock_time, index: c_uint, flags: c_uint, rsv: [c_uint; 2], } // linux/sctp.h pub struct sctp_initmsg { pub sinit_num_ostreams: __u16, pub sinit_max_instreams: __u16, pub sinit_max_attempts: __u16, pub sinit_max_init_timeo: __u16, } pub struct sctp_sndrcvinfo { pub sinfo_stream: __u16, pub sinfo_ssn: __u16, pub sinfo_flags: __u16, pub sinfo_ppid: __u32, pub sinfo_context: __u32, pub sinfo_timetolive: __u32, pub sinfo_tsn: __u32, pub sinfo_cumtsn: __u32, pub sinfo_assoc_id: crate::sctp_assoc_t, } pub struct sctp_sndinfo { pub snd_sid: __u16, pub snd_flags: __u16, pub snd_ppid: __u32, pub snd_context: __u32, pub snd_assoc_id: crate::sctp_assoc_t, } pub struct sctp_rcvinfo { pub rcv_sid: __u16, pub rcv_ssn: __u16, pub rcv_flags: __u16, pub rcv_ppid: __u32, pub rcv_tsn: __u32, pub rcv_cumtsn: __u32, pub rcv_context: __u32, pub rcv_assoc_id: crate::sctp_assoc_t, } pub struct sctp_nxtinfo { pub nxt_sid: __u16, pub nxt_flags: __u16, pub nxt_ppid: __u32, pub nxt_length: __u32, pub nxt_assoc_id: crate::sctp_assoc_t, } pub struct sctp_prinfo { pub pr_policy: __u16, pub pr_value: __u32, } pub struct sctp_authinfo { pub auth_keynumber: __u16, } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } // linux/tls.h pub struct tls_crypto_info { pub version: __u16, pub cipher_type: __u16, } pub struct tls12_crypto_info_aes_gcm_128 { pub info: tls_crypto_info, pub iv: [c_uchar; TLS_CIPHER_AES_GCM_128_IV_SIZE], pub key: [c_uchar; TLS_CIPHER_AES_GCM_128_KEY_SIZE], pub salt: [c_uchar; TLS_CIPHER_AES_GCM_128_SALT_SIZE], pub rec_seq: [c_uchar; TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE], } pub struct tls12_crypto_info_aes_gcm_256 { pub info: tls_crypto_info, pub iv: [c_uchar; TLS_CIPHER_AES_GCM_256_IV_SIZE], pub key: [c_uchar; TLS_CIPHER_AES_GCM_256_KEY_SIZE], pub salt: [c_uchar; TLS_CIPHER_AES_GCM_256_SALT_SIZE], pub rec_seq: [c_uchar; TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE], } pub struct tls12_crypto_info_aes_ccm_128 { pub info: tls_crypto_info, pub iv: [c_uchar; TLS_CIPHER_AES_CCM_128_IV_SIZE], pub key: [c_uchar; TLS_CIPHER_AES_CCM_128_KEY_SIZE], pub salt: [c_uchar; TLS_CIPHER_AES_CCM_128_SALT_SIZE], pub rec_seq: [c_uchar; TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE], } pub struct tls12_crypto_info_chacha20_poly1305 { pub info: tls_crypto_info, pub iv: [c_uchar; TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE], pub key: [c_uchar; TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE], pub salt: [c_uchar; TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE], pub rec_seq: [c_uchar; TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE], } pub struct tls12_crypto_info_sm4_gcm { pub info: tls_crypto_info, pub iv: [c_uchar; TLS_CIPHER_SM4_GCM_IV_SIZE], pub key: [c_uchar; TLS_CIPHER_SM4_GCM_KEY_SIZE], pub salt: [c_uchar; TLS_CIPHER_SM4_GCM_SALT_SIZE], pub rec_seq: [c_uchar; TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE], } pub struct tls12_crypto_info_sm4_ccm { pub info: tls_crypto_info, pub iv: [c_uchar; TLS_CIPHER_SM4_CCM_IV_SIZE], pub key: [c_uchar; TLS_CIPHER_SM4_CCM_KEY_SIZE], pub salt: [c_uchar; TLS_CIPHER_SM4_CCM_SALT_SIZE], pub rec_seq: [c_uchar; TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE], } pub struct tls12_crypto_info_aria_gcm_128 { pub info: tls_crypto_info, pub iv: [c_uchar; TLS_CIPHER_ARIA_GCM_128_IV_SIZE], pub key: [c_uchar; TLS_CIPHER_ARIA_GCM_128_KEY_SIZE], pub salt: [c_uchar; TLS_CIPHER_ARIA_GCM_128_SALT_SIZE], pub rec_seq: [c_uchar; TLS_CIPHER_ARIA_GCM_128_REC_SEQ_SIZE], } pub struct tls12_crypto_info_aria_gcm_256 { pub info: tls_crypto_info, pub iv: [c_uchar; TLS_CIPHER_ARIA_GCM_256_IV_SIZE], pub key: [c_uchar; TLS_CIPHER_ARIA_GCM_256_KEY_SIZE], pub salt: [c_uchar; TLS_CIPHER_ARIA_GCM_256_SALT_SIZE], pub rec_seq: [c_uchar; TLS_CIPHER_ARIA_GCM_256_REC_SEQ_SIZE], } // linux/wireless.h pub struct iw_param { pub value: __s32, pub fixed: __u8, pub disabled: __u8, pub flags: __u16, } pub struct iw_point { pub pointer: *mut c_void, pub length: __u16, pub flags: __u16, } pub struct iw_freq { pub m: __s32, pub e: __s16, pub i: __u8, pub flags: __u8, } pub struct iw_quality { pub qual: __u8, pub level: __u8, pub noise: __u8, pub updated: __u8, } pub struct iw_discarded { pub nwid: __u32, pub code: __u32, pub fragment: __u32, pub retries: __u32, pubmisc: __u32, } pub struct iw_missed { pub beacon: __u32, } pub struct iw_scan_req { pub scan_type: __u8, pub essid_len: __u8, pub num_channels: __u8, pub flags: __u8, pub bssid: crate::sockaddr, pub essid: [__u8; IW_ESSID_MAX_SIZE], pub min_channel_time: __u32, pub max_channel_time: __u32, pub channel_list: [iw_freq; IW_MAX_FREQUENCIES], } pub struct iw_encode_ext { pub ext_flags: __u32, pub tx_seq: [__u8; IW_ENCODE_SEQ_MAX_SIZE], pub rx_seq: [__u8; IW_ENCODE_SEQ_MAX_SIZE], pub addr: crate::sockaddr, pub alg: __u16, pub key_len: __u16, pub key: [__u8; 0], } pub struct iw_pmksa { pub cmd: __u32, pub bssid: crate::sockaddr, pub pmkid: [__u8; IW_PMKID_LEN], } pub struct iw_pmkid_cand { pub flags: __u32, pub index: __u32, pub bssid: crate::sockaddr, } pub struct iw_statistics { pub status: __u16, pub qual: iw_quality, pub discard: iw_discarded, pub miss: iw_missed, } pub struct iw_range { pub throughput: __u32, pub min_nwid: __u32, pub max_nwid: __u32, pub old_num_channels: __u16, pub old_num_frequency: __u8, pub scan_capa: __u8, pub event_capa: [__u32; 6], pub sensitivity: __s32, pub max_qual: iw_quality, pub avg_qual: iw_quality, pub num_bitrates: __u8, pub bitrate: [__s32; IW_MAX_BITRATES], pub min_rts: __s32, pub max_rts: __s32, pub min_frag: __s32, pub max_frag: __s32, pub min_pmp: __s32, pub max_pmp: __s32, pub min_pmt: __s32, pub max_pmt: __s32, pub pmp_flags: __u16, pub pmt_flags: __u16, pub pm_capa: __u16, pub encoding_size: [__u16; IW_MAX_ENCODING_SIZES], pub num_encoding_sizes: __u8, pub max_encoding_tokens: __u8, pub encoding_login_index: __u8, pub txpower_capa: __u16, pub num_txpower: __u8, pub txpower: [__s32; IW_MAX_TXPOWER], pub we_version_compiled: __u8, pub we_version_source: __u8, pub retry_capa: __u16, pub retry_flags: __u16, pub r_time_flags: __u16, pub min_retry: __s32, pub max_retry: __s32, pub min_r_time: __s32, pub max_r_time: __s32, pub num_channels: __u16, pub num_frequency: __u8, pub freq: [iw_freq; IW_MAX_FREQUENCIES], pub enc_capa: __u32, } pub struct iw_priv_args { pub cmd: __u32, pub set_args: __u16, pub get_args: __u16, pub name: [c_char; crate::IFNAMSIZ], } // #include pub struct epoll_params { pub busy_poll_usecs: u32, pub busy_poll_budget: u16, pub prefer_busy_poll: u8, pub __pad: u8, // Must be zero } #[cfg_attr( any( target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64", target_arch = "aarch64", target_arch = "riscv64", target_arch = "riscv32", target_arch = "loongarch64" ), repr(align(4)) )] #[cfg_attr( not(any( target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64", target_arch = "aarch64", target_arch = "riscv64", target_arch = "riscv32", target_arch = "loongarch64" )), repr(align(8)) )] pub struct pthread_mutexattr_t { #[doc(hidden)] size: [u8; crate::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[cfg_attr( any(target_env = "musl", target_env = "ohos", target_pointer_width = "32"), repr(align(4)) )] #[cfg_attr( all( not(target_env = "musl"), not(target_env = "ohos"), target_pointer_width = "64" ), repr(align(8)) )] pub struct pthread_rwlockattr_t { #[doc(hidden)] size: [u8; crate::__SIZEOF_PTHREAD_RWLOCKATTR_T], } #[repr(align(4))] pub struct pthread_condattr_t { #[doc(hidden)] size: [u8; crate::__SIZEOF_PTHREAD_CONDATTR_T], } #[repr(align(4))] pub struct pthread_barrierattr_t { #[doc(hidden)] size: [u8; crate::__SIZEOF_PTHREAD_BARRIERATTR_T], } #[repr(align(8))] pub struct fanotify_event_metadata { pub event_len: __u32, pub vers: __u8, pub reserved: __u8, pub metadata_len: __u16, pub mask: __u64, pub fd: c_int, pub pid: c_int, } // linux/ptp_clock.h pub struct ptp_sys_offset { pub n_samples: c_uint, pub rsv: [c_uint; 3], // FIXME(garando): replace length with `2 * PTP_MAX_SAMPLES + 1` when supported pub ts: [ptp_clock_time; 51], } pub struct ptp_pin_desc { pub name: [c_char; 64], pub index: c_uint, pub func: c_uint, pub chan: c_uint, pub rsv: [c_uint; 5], } pub struct ptp_clock_caps { pub max_adj: c_int, pub n_alarm: c_int, pub n_ext_ts: c_int, pub n_per_out: c_int, pub pps: c_int, pub n_pins: c_int, pub cross_timestamping: c_int, pub adjust_phase: c_int, pub max_phase_adj: c_int, pub rsv: [c_int; 11], } // linux/if_xdp.h pub struct sockaddr_xdp { pub sxdp_family: crate::__u16, pub sxdp_flags: crate::__u16, pub sxdp_ifindex: crate::__u32, pub sxdp_queue_id: crate::__u32, pub sxdp_shared_umem_fd: crate::__u32, } pub struct xdp_ring_offset { pub producer: crate::__u64, pub consumer: crate::__u64, pub desc: crate::__u64, pub flags: crate::__u64, } pub struct xdp_mmap_offsets { pub rx: xdp_ring_offset, pub tx: xdp_ring_offset, pub fr: xdp_ring_offset, pub cr: xdp_ring_offset, } pub struct xdp_ring_offset_v1 { pub producer: crate::__u64, pub consumer: crate::__u64, pub desc: crate::__u64, } pub struct xdp_mmap_offsets_v1 { pub rx: xdp_ring_offset_v1, pub tx: xdp_ring_offset_v1, pub fr: xdp_ring_offset_v1, pub cr: xdp_ring_offset_v1, } pub struct xdp_umem_reg { pub addr: crate::__u64, pub len: crate::__u64, pub chunk_size: crate::__u32, pub headroom: crate::__u32, pub flags: crate::__u32, pub tx_metadata_len: crate::__u32, } pub struct xdp_umem_reg_v1 { pub addr: crate::__u64, pub len: crate::__u64, pub chunk_size: crate::__u32, pub headroom: crate::__u32, } pub struct xdp_statistics { pub rx_dropped: crate::__u64, pub rx_invalid_descs: crate::__u64, pub tx_invalid_descs: crate::__u64, pub rx_ring_full: crate::__u64, pub rx_fill_ring_empty_descs: crate::__u64, pub tx_ring_empty_descs: crate::__u64, } pub struct xdp_statistics_v1 { pub rx_dropped: crate::__u64, pub rx_invalid_descs: crate::__u64, pub tx_invalid_descs: crate::__u64, } pub struct xdp_options { pub flags: crate::__u32, } pub struct xdp_desc { pub addr: crate::__u64, pub len: crate::__u32, pub options: crate::__u32, } pub struct xsk_tx_metadata_completion { pub tx_timestamp: crate::__u64, } pub struct xsk_tx_metadata_request { pub csum_start: __u16, pub csum_offset: __u16, } // linux/mount.h pub struct mount_attr { pub attr_set: crate::__u64, pub attr_clr: crate::__u64, pub propagation: crate::__u64, pub userns_fd: crate::__u64, } // linux/uio.h pub struct dmabuf_cmsg { pub frag_offset: crate::__u64, pub frag_size: crate::__u32, pub frag_token: crate::__u32, pub dmabuf_id: crate::__u32, pub flags: crate::__u32, } pub struct dmabuf_token { pub token_start: crate::__u32, pub token_count: crate::__u32, } } cfg_if! { if #[cfg(not(target_arch = "sparc64"))] { s! { pub struct iw_thrspy { pub addr: crate::sockaddr, pub qual: iw_quality, pub low: iw_quality, pub high: iw_quality, } pub struct iw_mlme { pub cmd: __u16, pub reason_code: __u16, pub addr: crate::sockaddr, } pub struct iw_michaelmicfailure { pub flags: __u32, pub src_addr: crate::sockaddr, pub tsc: [__u8; IW_ENCODE_SEQ_MAX_SIZE], } pub struct __c_anonymous_elf32_rela { pub r_offset: Elf32_Addr, pub r_info: Elf32_Word, pub r_addend: Elf32_Sword, } pub struct __c_anonymous_elf64_rela { pub r_offset: Elf64_Addr, pub r_info: Elf64_Xword, pub r_addend: Elf64_Sxword, } } } } s_no_extra_traits! { pub struct sockaddr_nl { pub nl_family: crate::sa_family_t, nl_pad: c_ushort, pub nl_pid: u32, pub nl_groups: u32, } pub struct dirent { pub d_ino: crate::ino_t, pub d_off: off_t, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } pub struct sockaddr_alg { pub salg_family: crate::sa_family_t, pub salg_type: [c_uchar; 14], pub salg_feat: u32, pub salg_mask: u32, pub salg_name: [c_uchar; 64], } pub struct uinput_setup { pub id: input_id, pub name: [c_char; UINPUT_MAX_NAME_SIZE], pub ff_effects_max: __u32, } pub struct uinput_user_dev { pub name: [c_char; UINPUT_MAX_NAME_SIZE], pub id: input_id, pub ff_effects_max: __u32, pub absmax: [__s32; ABS_CNT], pub absmin: [__s32; ABS_CNT], pub absfuzz: [__s32; ABS_CNT], pub absflat: [__s32; ABS_CNT], } /// WARNING: The `PartialEq`, `Eq` and `Hash` implementations of this /// type are unsound and will be removed in the future. #[deprecated( note = "this struct has unsafe trait implementations that will be \ removed in the future", since = "0.2.80" )] pub struct af_alg_iv { pub ivlen: u32, pub iv: [c_uchar; 0], } // x32 compatibility // See https://sourceware.org/bugzilla/show_bug.cgi?id=21279 pub struct mq_attr { #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_flags: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_maxmsg: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_msgsize: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_curmsgs: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pad: [i64; 4], #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_flags: c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_maxmsg: c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_msgsize: c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_curmsgs: c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pad: [c_long; 4], } pub union __c_anonymous_ifr_ifru { pub ifru_addr: crate::sockaddr, pub ifru_dstaddr: crate::sockaddr, pub ifru_broadaddr: crate::sockaddr, pub ifru_netmask: crate::sockaddr, pub ifru_hwaddr: crate::sockaddr, pub ifru_flags: c_short, pub ifru_ifindex: c_int, pub ifru_metric: c_int, pub ifru_mtu: c_int, pub ifru_map: __c_anonymous_ifru_map, pub ifru_slave: [c_char; crate::IFNAMSIZ], pub ifru_newname: [c_char; crate::IFNAMSIZ], pub ifru_data: *mut c_char, } pub struct ifreq { /// interface name, e.g. "en0" pub ifr_name: [c_char; crate::IFNAMSIZ], pub ifr_ifru: __c_anonymous_ifr_ifru, } pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: *mut c_char, pub ifcu_req: *mut crate::ifreq, } /// Structure used in SIOCGIFCONF request. Used to retrieve interface configuration for /// machine (useful for programs which must know all networks accessible). pub struct ifconf { /// Size of buffer pub ifc_len: c_int, pub ifc_ifcu: __c_anonymous_ifc_ifcu, } pub struct hwtstamp_config { pub flags: c_int, pub tx_type: c_int, pub rx_filter: c_int, } pub struct dirent64 { pub d_ino: crate::ino64_t, pub d_off: off64_t, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } pub struct sched_attr { pub size: __u32, pub sched_policy: __u32, pub sched_flags: crate::__u64, pub sched_nice: __s32, pub sched_priority: __u32, pub sched_runtime: crate::__u64, pub sched_deadline: crate::__u64, pub sched_period: crate::__u64, } #[allow(missing_debug_implementations)] pub union tpacket_req_u { pub req: crate::tpacket_req, pub req3: crate::tpacket_req3, } #[allow(missing_debug_implementations)] pub union tpacket_bd_header_u { pub bh1: crate::tpacket_hdr_v1, } #[allow(missing_debug_implementations)] pub struct tpacket_block_desc { pub version: __u32, pub offset_to_priv: __u32, pub hdr: crate::tpacket_bd_header_u, } #[cfg_attr( all( any(target_env = "musl", target_env = "ohos"), target_pointer_width = "32" ), repr(align(4)) )] #[cfg_attr( all( any(target_env = "musl", target_env = "ohos"), target_pointer_width = "64" ), repr(align(8)) )] #[cfg_attr( all( not(any(target_env = "musl", target_env = "ohos")), target_arch = "x86" ), repr(align(4)) )] #[cfg_attr( all( not(any(target_env = "musl", target_env = "ohos")), not(target_arch = "x86") ), repr(align(8)) )] pub struct pthread_cond_t { #[doc(hidden)] size: [u8; crate::__SIZEOF_PTHREAD_COND_T], } #[cfg_attr( all( target_pointer_width = "32", any( target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86" ) ), repr(align(4)) )] #[cfg_attr( any( target_pointer_width = "64", not(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86" )) ), repr(align(8)) )] pub struct pthread_mutex_t { #[doc(hidden)] size: [u8; crate::__SIZEOF_PTHREAD_MUTEX_T], } #[cfg_attr( all( target_pointer_width = "32", any( target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86" ) ), repr(align(4)) )] #[cfg_attr( any( target_pointer_width = "64", not(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86" )) ), repr(align(8)) )] pub struct pthread_rwlock_t { size: [u8; crate::__SIZEOF_PTHREAD_RWLOCK_T], } #[cfg_attr( all( target_pointer_width = "32", any( target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86" ) ), repr(align(4)) )] #[cfg_attr( any( target_pointer_width = "64", not(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86" )) ), repr(align(8)) )] pub struct pthread_barrier_t { size: [u8; crate::__SIZEOF_PTHREAD_BARRIER_T], } // linux/net_tstamp.h #[allow(missing_debug_implementations)] pub struct sock_txtime { pub clockid: crate::clockid_t, pub flags: __u32, } // linux/can.h #[repr(align(8))] #[allow(missing_debug_implementations)] pub struct can_frame { pub can_id: canid_t, // FIXME(1.0): this field was renamed to `len` in Linux 5.11 pub can_dlc: u8, __pad: u8, __res0: u8, pub len8_dlc: u8, pub data: [u8; CAN_MAX_DLEN], } #[repr(align(8))] #[allow(missing_debug_implementations)] pub struct canfd_frame { pub can_id: canid_t, pub len: u8, pub flags: u8, __res0: u8, __res1: u8, pub data: [u8; CANFD_MAX_DLEN], } #[repr(align(8))] #[allow(missing_debug_implementations)] pub struct canxl_frame { pub prio: canid_t, pub flags: u8, pub sdt: u8, pub len: u16, pub af: u32, pub data: [u8; CANXL_MAX_DLEN], } #[allow(missing_debug_implementations)] pub union __c_anonymous_sockaddr_can_can_addr { pub tp: __c_anonymous_sockaddr_can_tp, pub j1939: __c_anonymous_sockaddr_can_j1939, } #[allow(missing_debug_implementations)] pub struct sockaddr_can { pub can_family: crate::sa_family_t, pub can_ifindex: c_int, pub can_addr: __c_anonymous_sockaddr_can_can_addr, } // linux/wireless.h pub union iwreq_data { pub name: [c_char; crate::IFNAMSIZ], pub essid: iw_point, pub nwid: iw_param, pub freq: iw_freq, pub sens: iw_param, pub bitrate: iw_param, pub txpower: iw_param, pub rts: iw_param, pub frag: iw_param, pub mode: __u32, pub retry: iw_param, pub encoding: iw_point, pub power: iw_param, pub qual: iw_quality, pub ap_addr: crate::sockaddr, pub addr: crate::sockaddr, pub param: iw_param, pub data: iw_point, } pub struct iw_event { pub len: __u16, pub cmd: __u16, pub u: iwreq_data, } pub union __c_anonymous_iwreq { pub ifrn_name: [c_char; crate::IFNAMSIZ], } pub struct iwreq { pub ifr_ifrn: __c_anonymous_iwreq, pub u: iwreq_data, } // linux/ptp_clock.h pub union __c_anonymous_ptp_perout_request_1 { pub start: ptp_clock_time, pub phase: ptp_clock_time, } pub union __c_anonymous_ptp_perout_request_2 { pub on: ptp_clock_time, pub rsv: [c_uint; 4], } #[allow(missing_debug_implementations)] pub struct ptp_perout_request { pub anonymous_1: __c_anonymous_ptp_perout_request_1, pub period: ptp_clock_time, pub index: c_uint, pub flags: c_uint, pub anonymous_2: __c_anonymous_ptp_perout_request_2, } // linux/if_xdp.h #[allow(missing_debug_implementations)] pub struct xsk_tx_metadata { pub flags: crate::__u64, pub xsk_tx_metadata_union: __c_anonymous_xsk_tx_metadata_union, } pub union __c_anonymous_xsk_tx_metadata_union { pub request: xsk_tx_metadata_request, pub completion: xsk_tx_metadata_completion, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_nl { fn eq(&self, other: &sockaddr_nl) -> bool { self.nl_family == other.nl_family && self.nl_pid == other.nl_pid && self.nl_groups == other.nl_groups } } impl Eq for sockaddr_nl {} impl fmt::Debug for sockaddr_nl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_nl") .field("nl_family", &self.nl_family) .field("nl_pid", &self.nl_pid) .field("nl_groups", &self.nl_groups) .finish() } } impl hash::Hash for sockaddr_nl { fn hash(&self, state: &mut H) { self.nl_family.hash(state); self.nl_pid.hash(state); self.nl_groups.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for dirent64 { fn eq(&self, other: &dirent64) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent64 {} impl fmt::Debug for dirent64 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent64") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent64 { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a, b)| a == b) } } impl Eq for pthread_cond_t {} impl fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_cond_t") // FIXME(debug): .field("size", &self.size) .finish() } } impl hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a, b)| a == b) } } impl Eq for pthread_mutex_t {} impl fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_mutex_t") // FIXME(debug): .field("size", &self.size) .finish() } } impl hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a, b)| a == b) } } impl Eq for pthread_rwlock_t {} impl fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_rwlock_t") // FIXME(debug): .field("size", &self.size) .finish() } } impl hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_barrier_t { fn eq(&self, other: &pthread_barrier_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a, b)| a == b) } } impl Eq for pthread_barrier_t {} impl fmt::Debug for pthread_barrier_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_barrier_t") .field("size", &self.size) .finish() } } impl hash::Hash for pthread_barrier_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for sockaddr_alg { fn eq(&self, other: &sockaddr_alg) -> bool { self.salg_family == other.salg_family && self .salg_type .iter() .zip(other.salg_type.iter()) .all(|(a, b)| a == b) && self.salg_feat == other.salg_feat && self.salg_mask == other.salg_mask && self .salg_name .iter() .zip(other.salg_name.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_alg {} impl fmt::Debug for sockaddr_alg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_alg") .field("salg_family", &self.salg_family) .field("salg_type", &self.salg_type) .field("salg_feat", &self.salg_feat) .field("salg_mask", &self.salg_mask) .field("salg_name", &&self.salg_name[..]) .finish() } } impl hash::Hash for sockaddr_alg { fn hash(&self, state: &mut H) { self.salg_family.hash(state); self.salg_type.hash(state); self.salg_feat.hash(state); self.salg_mask.hash(state); self.salg_name.hash(state); } } impl PartialEq for uinput_setup { fn eq(&self, other: &uinput_setup) -> bool { self.id == other.id && self.name[..] == other.name[..] && self.ff_effects_max == other.ff_effects_max } } impl Eq for uinput_setup {} impl fmt::Debug for uinput_setup { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("uinput_setup") .field("id", &self.id) .field("name", &&self.name[..]) .field("ff_effects_max", &self.ff_effects_max) .finish() } } impl hash::Hash for uinput_setup { fn hash(&self, state: &mut H) { self.id.hash(state); self.name.hash(state); self.ff_effects_max.hash(state); } } impl PartialEq for uinput_user_dev { fn eq(&self, other: &uinput_user_dev) -> bool { self.name[..] == other.name[..] && self.id == other.id && self.ff_effects_max == other.ff_effects_max && self.absmax[..] == other.absmax[..] && self.absmin[..] == other.absmin[..] && self.absfuzz[..] == other.absfuzz[..] && self.absflat[..] == other.absflat[..] } } impl Eq for uinput_user_dev {} impl fmt::Debug for uinput_user_dev { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("uinput_setup") .field("name", &&self.name[..]) .field("id", &self.id) .field("ff_effects_max", &self.ff_effects_max) .field("absmax", &&self.absmax[..]) .field("absmin", &&self.absmin[..]) .field("absfuzz", &&self.absfuzz[..]) .field("absflat", &&self.absflat[..]) .finish() } } impl hash::Hash for uinput_user_dev { fn hash(&self, state: &mut H) { self.name.hash(state); self.id.hash(state); self.ff_effects_max.hash(state); self.absmax.hash(state); self.absmin.hash(state); self.absfuzz.hash(state); self.absflat.hash(state); } } #[allow(deprecated)] impl af_alg_iv { fn as_slice(&self) -> &[u8] { unsafe { ::core::slice::from_raw_parts(self.iv.as_ptr(), self.ivlen as usize) } } } #[allow(deprecated)] impl PartialEq for af_alg_iv { fn eq(&self, other: &af_alg_iv) -> bool { *self.as_slice() == *other.as_slice() } } #[allow(deprecated)] impl Eq for af_alg_iv {} #[allow(deprecated)] impl fmt::Debug for af_alg_iv { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("af_alg_iv") .field("ivlen", &self.ivlen) .finish() } } #[allow(deprecated)] impl hash::Hash for af_alg_iv { fn hash(&self, state: &mut H) { self.as_slice().hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_flags == other.mq_flags && self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_curmsgs == other.mq_curmsgs } } impl Eq for mq_attr {} impl fmt::Debug for mq_attr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mq_attr") .field("mq_flags", &self.mq_flags) .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_curmsgs", &self.mq_curmsgs) .finish() } } impl hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_flags.hash(state); self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_curmsgs.hash(state); } } impl fmt::Debug for ifreq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } impl fmt::Debug for ifconf { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifconf") .field("ifc_len", &self.ifc_len) .field("ifc_ifcu", &self.ifc_ifcu) .finish() } } impl fmt::Debug for hwtstamp_config { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("hwtstamp_config") .field("flags", &self.flags) .field("tx_type", &self.tx_type) .field("rx_filter", &self.rx_filter) .finish() } } impl PartialEq for hwtstamp_config { fn eq(&self, other: &hwtstamp_config) -> bool { self.flags == other.flags && self.tx_type == other.tx_type && self.rx_filter == other.rx_filter } } impl Eq for hwtstamp_config {} impl hash::Hash for hwtstamp_config { fn hash(&self, state: &mut H) { self.flags.hash(state); self.tx_type.hash(state); self.rx_filter.hash(state); } } impl fmt::Debug for sched_attr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sched_attr") .field("size", &self.size) .field("sched_policy", &self.sched_policy) .field("sched_flags", &self.sched_flags) .field("sched_nice", &self.sched_nice) .field("sched_priority", &self.sched_priority) .field("sched_runtime", &self.sched_runtime) .field("sched_deadline", &self.sched_deadline) .field("sched_period", &self.sched_period) .finish() } } impl PartialEq for sched_attr { fn eq(&self, other: &sched_attr) -> bool { self.size == other.size && self.sched_policy == other.sched_policy && self.sched_flags == other.sched_flags && self.sched_nice == other.sched_nice && self.sched_priority == other.sched_priority && self.sched_runtime == other.sched_runtime && self.sched_deadline == other.sched_deadline && self.sched_period == other.sched_period } } impl Eq for sched_attr {} impl hash::Hash for sched_attr { fn hash(&self, state: &mut H) { self.size.hash(state); self.sched_policy.hash(state); self.sched_flags.hash(state); self.sched_nice.hash(state); self.sched_priority.hash(state); self.sched_runtime.hash(state); self.sched_deadline.hash(state); self.sched_period.hash(state); } } impl fmt::Debug for iw_event { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("iw_event") .field("len", &self.len) .field("cmd", &self.cmd) .field("u", &self.u) .finish() } } impl fmt::Debug for iwreq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("iwreq") .field("ifr_ifrn", &self.ifr_ifrn) .field("u", &self.u) .finish() } } } } cfg_if! { if #[cfg(any( target_env = "gnu", target_env = "musl", target_env = "ohos" ))] { pub const ABDAY_1: crate::nl_item = 0x20000; pub const ABDAY_2: crate::nl_item = 0x20001; pub const ABDAY_3: crate::nl_item = 0x20002; pub const ABDAY_4: crate::nl_item = 0x20003; pub const ABDAY_5: crate::nl_item = 0x20004; pub const ABDAY_6: crate::nl_item = 0x20005; pub const ABDAY_7: crate::nl_item = 0x20006; pub const DAY_1: crate::nl_item = 0x20007; pub const DAY_2: crate::nl_item = 0x20008; pub const DAY_3: crate::nl_item = 0x20009; pub const DAY_4: crate::nl_item = 0x2000A; pub const DAY_5: crate::nl_item = 0x2000B; pub const DAY_6: crate::nl_item = 0x2000C; pub const DAY_7: crate::nl_item = 0x2000D; pub const ABMON_1: crate::nl_item = 0x2000E; pub const ABMON_2: crate::nl_item = 0x2000F; pub const ABMON_3: crate::nl_item = 0x20010; pub const ABMON_4: crate::nl_item = 0x20011; pub const ABMON_5: crate::nl_item = 0x20012; pub const ABMON_6: crate::nl_item = 0x20013; pub const ABMON_7: crate::nl_item = 0x20014; pub const ABMON_8: crate::nl_item = 0x20015; pub const ABMON_9: crate::nl_item = 0x20016; pub const ABMON_10: crate::nl_item = 0x20017; pub const ABMON_11: crate::nl_item = 0x20018; pub const ABMON_12: crate::nl_item = 0x20019; pub const MON_1: crate::nl_item = 0x2001A; pub const MON_2: crate::nl_item = 0x2001B; pub const MON_3: crate::nl_item = 0x2001C; pub const MON_4: crate::nl_item = 0x2001D; pub const MON_5: crate::nl_item = 0x2001E; pub const MON_6: crate::nl_item = 0x2001F; pub const MON_7: crate::nl_item = 0x20020; pub const MON_8: crate::nl_item = 0x20021; pub const MON_9: crate::nl_item = 0x20022; pub const MON_10: crate::nl_item = 0x20023; pub const MON_11: crate::nl_item = 0x20024; pub const MON_12: crate::nl_item = 0x20025; pub const AM_STR: crate::nl_item = 0x20026; pub const PM_STR: crate::nl_item = 0x20027; pub const D_T_FMT: crate::nl_item = 0x20028; pub const D_FMT: crate::nl_item = 0x20029; pub const T_FMT: crate::nl_item = 0x2002A; pub const T_FMT_AMPM: crate::nl_item = 0x2002B; pub const ERA: crate::nl_item = 0x2002C; pub const ERA_D_FMT: crate::nl_item = 0x2002E; pub const ALT_DIGITS: crate::nl_item = 0x2002F; pub const ERA_D_T_FMT: crate::nl_item = 0x20030; pub const ERA_T_FMT: crate::nl_item = 0x20031; pub const CODESET: crate::nl_item = 14; pub const CRNCYSTR: crate::nl_item = 0x4000F; pub const RADIXCHAR: crate::nl_item = 0x10000; pub const THOUSEP: crate::nl_item = 0x10001; pub const YESEXPR: crate::nl_item = 0x50000; pub const NOEXPR: crate::nl_item = 0x50001; pub const YESSTR: crate::nl_item = 0x50002; pub const NOSTR: crate::nl_item = 0x50003; } } pub const RUSAGE_CHILDREN: c_int = -1; pub const L_tmpnam: c_uint = 20; pub const _PC_LINK_MAX: c_int = 0; pub const _PC_MAX_CANON: c_int = 1; pub const _PC_MAX_INPUT: c_int = 2; pub const _PC_NAME_MAX: c_int = 3; pub const _PC_PATH_MAX: c_int = 4; pub const _PC_PIPE_BUF: c_int = 5; pub const _PC_CHOWN_RESTRICTED: c_int = 6; pub const _PC_NO_TRUNC: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_SYNC_IO: c_int = 9; pub const _PC_ASYNC_IO: c_int = 10; pub const _PC_PRIO_IO: c_int = 11; pub const _PC_SOCK_MAXBUF: c_int = 12; pub const _PC_FILESIZEBITS: c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: c_int = 16; pub const _PC_REC_XFER_ALIGN: c_int = 17; pub const _PC_ALLOC_SIZE_MIN: c_int = 18; pub const _PC_SYMLINK_MAX: c_int = 19; pub const _PC_2_SYMLINKS: c_int = 20; pub const MS_NOUSER: c_ulong = 0xffffffff80000000; pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_STREAM_MAX: c_int = 5; pub const _SC_TZNAME_MAX: c_int = 6; pub const _SC_JOB_CONTROL: c_int = 7; pub const _SC_SAVED_IDS: c_int = 8; pub const _SC_REALTIME_SIGNALS: c_int = 9; pub const _SC_PRIORITY_SCHEDULING: c_int = 10; pub const _SC_TIMERS: c_int = 11; pub const _SC_ASYNCHRONOUS_IO: c_int = 12; pub const _SC_PRIORITIZED_IO: c_int = 13; pub const _SC_SYNCHRONIZED_IO: c_int = 14; pub const _SC_FSYNC: c_int = 15; pub const _SC_MAPPED_FILES: c_int = 16; pub const _SC_MEMLOCK: c_int = 17; pub const _SC_MEMLOCK_RANGE: c_int = 18; pub const _SC_MEMORY_PROTECTION: c_int = 19; pub const _SC_MESSAGE_PASSING: c_int = 20; pub const _SC_SEMAPHORES: c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 22; pub const _SC_AIO_LISTIO_MAX: c_int = 23; pub const _SC_AIO_MAX: c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 25; pub const _SC_DELAYTIMER_MAX: c_int = 26; pub const _SC_MQ_OPEN_MAX: c_int = 27; pub const _SC_MQ_PRIO_MAX: c_int = 28; pub const _SC_VERSION: c_int = 29; pub const _SC_PAGESIZE: c_int = 30; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_RTSIG_MAX: c_int = 31; pub const _SC_SEM_NSEMS_MAX: c_int = 32; pub const _SC_SEM_VALUE_MAX: c_int = 33; pub const _SC_SIGQUEUE_MAX: c_int = 34; pub const _SC_TIMER_MAX: c_int = 35; pub const _SC_BC_BASE_MAX: c_int = 36; pub const _SC_BC_DIM_MAX: c_int = 37; pub const _SC_BC_SCALE_MAX: c_int = 38; pub const _SC_BC_STRING_MAX: c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: c_int = 40; pub const _SC_EXPR_NEST_MAX: c_int = 42; pub const _SC_LINE_MAX: c_int = 43; pub const _SC_RE_DUP_MAX: c_int = 44; pub const _SC_2_VERSION: c_int = 46; pub const _SC_2_C_BIND: c_int = 47; pub const _SC_2_C_DEV: c_int = 48; pub const _SC_2_FORT_DEV: c_int = 49; pub const _SC_2_FORT_RUN: c_int = 50; pub const _SC_2_SW_DEV: c_int = 51; pub const _SC_2_LOCALEDEF: c_int = 52; pub const _SC_UIO_MAXIOV: c_int = 60; pub const _SC_IOV_MAX: c_int = 60; pub const _SC_THREADS: c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: c_int = 70; pub const _SC_LOGIN_NAME_MAX: c_int = 71; pub const _SC_TTY_NAME_MAX: c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73; pub const _SC_THREAD_KEYS_MAX: c_int = 74; pub const _SC_THREAD_STACK_MIN: c_int = 75; pub const _SC_THREAD_THREADS_MAX: c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: c_int = 82; pub const _SC_NPROCESSORS_CONF: c_int = 83; pub const _SC_NPROCESSORS_ONLN: c_int = 84; pub const _SC_PHYS_PAGES: c_int = 85; pub const _SC_AVPHYS_PAGES: c_int = 86; pub const _SC_ATEXIT_MAX: c_int = 87; pub const _SC_PASS_MAX: c_int = 88; pub const _SC_XOPEN_VERSION: c_int = 89; pub const _SC_XOPEN_XCU_VERSION: c_int = 90; pub const _SC_XOPEN_UNIX: c_int = 91; pub const _SC_XOPEN_CRYPT: c_int = 92; pub const _SC_XOPEN_ENH_I18N: c_int = 93; pub const _SC_XOPEN_SHM: c_int = 94; pub const _SC_2_CHAR_TERM: c_int = 95; pub const _SC_2_UPE: c_int = 97; pub const _SC_XOPEN_XPG2: c_int = 98; pub const _SC_XOPEN_XPG3: c_int = 99; pub const _SC_XOPEN_XPG4: c_int = 100; pub const _SC_NZERO: c_int = 109; pub const _SC_XBS5_ILP32_OFF32: c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 126; pub const _SC_XBS5_LP64_OFF64: c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 128; pub const _SC_XOPEN_LEGACY: c_int = 129; pub const _SC_XOPEN_REALTIME: c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131; pub const _SC_ADVISORY_INFO: c_int = 132; pub const _SC_BARRIERS: c_int = 133; pub const _SC_CLOCK_SELECTION: c_int = 137; pub const _SC_CPUTIME: c_int = 138; pub const _SC_THREAD_CPUTIME: c_int = 139; pub const _SC_MONOTONIC_CLOCK: c_int = 149; pub const _SC_READER_WRITER_LOCKS: c_int = 153; pub const _SC_SPIN_LOCKS: c_int = 154; pub const _SC_REGEXP: c_int = 155; pub const _SC_SHELL: c_int = 157; pub const _SC_SPAWN: c_int = 159; pub const _SC_SPORADIC_SERVER: c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 161; pub const _SC_TIMEOUTS: c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 165; pub const _SC_2_PBS: c_int = 168; pub const _SC_2_PBS_ACCOUNTING: c_int = 169; pub const _SC_2_PBS_LOCATE: c_int = 170; pub const _SC_2_PBS_MESSAGE: c_int = 171; pub const _SC_2_PBS_TRACK: c_int = 172; pub const _SC_SYMLOOP_MAX: c_int = 173; pub const _SC_STREAMS: c_int = 174; pub const _SC_2_PBS_CHECKPOINT: c_int = 175; pub const _SC_V6_ILP32_OFF32: c_int = 176; pub const _SC_V6_ILP32_OFFBIG: c_int = 177; pub const _SC_V6_LP64_OFF64: c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: c_int = 179; pub const _SC_HOST_NAME_MAX: c_int = 180; pub const _SC_TRACE: c_int = 181; pub const _SC_TRACE_EVENT_FILTER: c_int = 182; pub const _SC_TRACE_INHERIT: c_int = 183; pub const _SC_TRACE_LOG: c_int = 184; pub const _SC_IPV6: c_int = 235; pub const _SC_RAW_SOCKETS: c_int = 236; pub const _SC_V7_ILP32_OFF32: c_int = 237; pub const _SC_V7_ILP32_OFFBIG: c_int = 238; pub const _SC_V7_LP64_OFF64: c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: c_int = 240; pub const _SC_SS_REPL_MAX: c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 242; pub const _SC_TRACE_NAME_MAX: c_int = 243; pub const _SC_TRACE_SYS_MAX: c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 245; pub const _SC_XOPEN_STREAMS: c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 248; pub const _CS_PATH: c_int = 0; pub const _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS: c_int = 1; pub const _CS_POSIX_V5_WIDTH_RESTRICTED_ENVS: c_int = 4; pub const _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS: c_int = 5; pub const _CS_POSIX_V6_ILP32_OFF32_CFLAGS: c_int = 1116; pub const _CS_POSIX_V6_ILP32_OFF32_LDFLAGS: c_int = 1117; pub const _CS_POSIX_V6_ILP32_OFF32_LIBS: c_int = 1118; pub const _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS: c_int = 1119; pub const _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS: c_int = 1120; pub const _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS: c_int = 1121; pub const _CS_POSIX_V6_ILP32_OFFBIG_LIBS: c_int = 1122; pub const _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS: c_int = 1123; pub const _CS_POSIX_V6_LP64_OFF64_CFLAGS: c_int = 1124; pub const _CS_POSIX_V6_LP64_OFF64_LDFLAGS: c_int = 1125; pub const _CS_POSIX_V6_LP64_OFF64_LIBS: c_int = 1126; pub const _CS_POSIX_V6_LP64_OFF64_LINTFLAGS: c_int = 1127; pub const _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS: c_int = 1128; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS: c_int = 1129; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LIBS: c_int = 1130; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS: c_int = 1131; pub const _CS_POSIX_V7_ILP32_OFF32_CFLAGS: c_int = 1132; pub const _CS_POSIX_V7_ILP32_OFF32_LDFLAGS: c_int = 1133; pub const _CS_POSIX_V7_ILP32_OFF32_LIBS: c_int = 1134; pub const _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS: c_int = 1135; pub const _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS: c_int = 1136; pub const _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS: c_int = 1137; pub const _CS_POSIX_V7_ILP32_OFFBIG_LIBS: c_int = 1138; pub const _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS: c_int = 1139; pub const _CS_POSIX_V7_LP64_OFF64_CFLAGS: c_int = 1140; pub const _CS_POSIX_V7_LP64_OFF64_LDFLAGS: c_int = 1141; pub const _CS_POSIX_V7_LP64_OFF64_LIBS: c_int = 1142; pub const _CS_POSIX_V7_LP64_OFF64_LINTFLAGS: c_int = 1143; pub const _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS: c_int = 1144; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS: c_int = 1145; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LIBS: c_int = 1146; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS: c_int = 1147; pub const RLIM_SAVED_MAX: crate::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: crate::rlim_t = RLIM_INFINITY; // elf.h - Fields in the e_ident array. pub const EI_NIDENT: usize = 16; pub const EI_MAG0: usize = 0; pub const ELFMAG0: u8 = 0x7f; pub const EI_MAG1: usize = 1; pub const ELFMAG1: u8 = b'E'; pub const EI_MAG2: usize = 2; pub const ELFMAG2: u8 = b'L'; pub const EI_MAG3: usize = 3; pub const ELFMAG3: u8 = b'F'; pub const SELFMAG: usize = 4; pub const EI_CLASS: usize = 4; pub const ELFCLASSNONE: u8 = 0; pub const ELFCLASS32: u8 = 1; pub const ELFCLASS64: u8 = 2; pub const ELFCLASSNUM: usize = 3; pub const EI_DATA: usize = 5; pub const ELFDATANONE: u8 = 0; pub const ELFDATA2LSB: u8 = 1; pub const ELFDATA2MSB: u8 = 2; pub const ELFDATANUM: usize = 3; pub const EI_VERSION: usize = 6; pub const EI_OSABI: usize = 7; pub const ELFOSABI_NONE: u8 = 0; pub const ELFOSABI_SYSV: u8 = 0; pub const ELFOSABI_HPUX: u8 = 1; pub const ELFOSABI_NETBSD: u8 = 2; pub const ELFOSABI_GNU: u8 = 3; pub const ELFOSABI_LINUX: u8 = ELFOSABI_GNU; pub const ELFOSABI_SOLARIS: u8 = 6; pub const ELFOSABI_AIX: u8 = 7; pub const ELFOSABI_IRIX: u8 = 8; pub const ELFOSABI_FREEBSD: u8 = 9; pub const ELFOSABI_TRU64: u8 = 10; pub const ELFOSABI_MODESTO: u8 = 11; pub const ELFOSABI_OPENBSD: u8 = 12; pub const ELFOSABI_ARM: u8 = 97; pub const ELFOSABI_STANDALONE: u8 = 255; pub const EI_ABIVERSION: usize = 8; pub const EI_PAD: usize = 9; // elf.h - Legal values for e_type (object file type). pub const ET_NONE: u16 = 0; pub const ET_REL: u16 = 1; pub const ET_EXEC: u16 = 2; pub const ET_DYN: u16 = 3; pub const ET_CORE: u16 = 4; pub const ET_NUM: u16 = 5; pub const ET_LOOS: u16 = 0xfe00; pub const ET_HIOS: u16 = 0xfeff; pub const ET_LOPROC: u16 = 0xff00; pub const ET_HIPROC: u16 = 0xffff; // elf.h - Legal values for e_machine (architecture). pub const EM_NONE: u16 = 0; pub const EM_M32: u16 = 1; pub const EM_SPARC: u16 = 2; pub const EM_386: u16 = 3; pub const EM_68K: u16 = 4; pub const EM_88K: u16 = 5; pub const EM_860: u16 = 7; pub const EM_MIPS: u16 = 8; pub const EM_S370: u16 = 9; pub const EM_MIPS_RS3_LE: u16 = 10; pub const EM_PARISC: u16 = 15; pub const EM_VPP500: u16 = 17; pub const EM_SPARC32PLUS: u16 = 18; pub const EM_960: u16 = 19; pub const EM_PPC: u16 = 20; pub const EM_PPC64: u16 = 21; pub const EM_S390: u16 = 22; pub const EM_V800: u16 = 36; pub const EM_FR20: u16 = 37; pub const EM_RH32: u16 = 38; pub const EM_RCE: u16 = 39; pub const EM_ARM: u16 = 40; pub const EM_FAKE_ALPHA: u16 = 41; pub const EM_SH: u16 = 42; pub const EM_SPARCV9: u16 = 43; pub const EM_TRICORE: u16 = 44; pub const EM_ARC: u16 = 45; pub const EM_H8_300: u16 = 46; pub const EM_H8_300H: u16 = 47; pub const EM_H8S: u16 = 48; pub const EM_H8_500: u16 = 49; pub const EM_IA_64: u16 = 50; pub const EM_MIPS_X: u16 = 51; pub const EM_COLDFIRE: u16 = 52; pub const EM_68HC12: u16 = 53; pub const EM_MMA: u16 = 54; pub const EM_PCP: u16 = 55; pub const EM_NCPU: u16 = 56; pub const EM_NDR1: u16 = 57; pub const EM_STARCORE: u16 = 58; pub const EM_ME16: u16 = 59; pub const EM_ST100: u16 = 60; pub const EM_TINYJ: u16 = 61; pub const EM_X86_64: u16 = 62; pub const EM_PDSP: u16 = 63; pub const EM_FX66: u16 = 66; pub const EM_ST9PLUS: u16 = 67; pub const EM_ST7: u16 = 68; pub const EM_68HC16: u16 = 69; pub const EM_68HC11: u16 = 70; pub const EM_68HC08: u16 = 71; pub const EM_68HC05: u16 = 72; pub const EM_SVX: u16 = 73; pub const EM_ST19: u16 = 74; pub const EM_VAX: u16 = 75; pub const EM_CRIS: u16 = 76; pub const EM_JAVELIN: u16 = 77; pub const EM_FIREPATH: u16 = 78; pub const EM_ZSP: u16 = 79; pub const EM_MMIX: u16 = 80; pub const EM_HUANY: u16 = 81; pub const EM_PRISM: u16 = 82; pub const EM_AVR: u16 = 83; pub const EM_FR30: u16 = 84; pub const EM_D10V: u16 = 85; pub const EM_D30V: u16 = 86; pub const EM_V850: u16 = 87; pub const EM_M32R: u16 = 88; pub const EM_MN10300: u16 = 89; pub const EM_MN10200: u16 = 90; pub const EM_PJ: u16 = 91; pub const EM_OPENRISC: u16 = 92; pub const EM_ARC_A5: u16 = 93; pub const EM_XTENSA: u16 = 94; pub const EM_AARCH64: u16 = 183; pub const EM_TILEPRO: u16 = 188; pub const EM_TILEGX: u16 = 191; pub const EM_ALPHA: u16 = 0x9026; // elf.h - Legal values for e_version (version). pub const EV_NONE: u32 = 0; pub const EV_CURRENT: u32 = 1; pub const EV_NUM: u32 = 2; // elf.h - Legal values for p_type (segment type). pub const PT_NULL: u32 = 0; pub const PT_LOAD: u32 = 1; pub const PT_DYNAMIC: u32 = 2; pub const PT_INTERP: u32 = 3; pub const PT_NOTE: u32 = 4; pub const PT_SHLIB: u32 = 5; pub const PT_PHDR: u32 = 6; pub const PT_TLS: u32 = 7; pub const PT_NUM: u32 = 8; pub const PT_LOOS: u32 = 0x60000000; pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; pub const PT_GNU_STACK: u32 = 0x6474e551; pub const PT_GNU_RELRO: u32 = 0x6474e552; pub const PT_LOSUNW: u32 = 0x6ffffffa; pub const PT_SUNWBSS: u32 = 0x6ffffffa; pub const PT_SUNWSTACK: u32 = 0x6ffffffb; pub const PT_HISUNW: u32 = 0x6fffffff; pub const PT_HIOS: u32 = 0x6fffffff; pub const PT_LOPROC: u32 = 0x70000000; pub const PT_HIPROC: u32 = 0x7fffffff; // Legal values for p_flags (segment flags). pub const PF_X: u32 = 1 << 0; pub const PF_W: u32 = 1 << 1; pub const PF_R: u32 = 1 << 2; pub const PF_MASKOS: u32 = 0x0ff00000; pub const PF_MASKPROC: u32 = 0xf0000000; // elf.h - Legal values for a_type (entry type). pub const AT_NULL: c_ulong = 0; pub const AT_IGNORE: c_ulong = 1; pub const AT_EXECFD: c_ulong = 2; pub const AT_PHDR: c_ulong = 3; pub const AT_PHENT: c_ulong = 4; pub const AT_PHNUM: c_ulong = 5; pub const AT_PAGESZ: c_ulong = 6; pub const AT_BASE: c_ulong = 7; pub const AT_FLAGS: c_ulong = 8; pub const AT_ENTRY: c_ulong = 9; pub const AT_NOTELF: c_ulong = 10; pub const AT_UID: c_ulong = 11; pub const AT_EUID: c_ulong = 12; pub const AT_GID: c_ulong = 13; pub const AT_EGID: c_ulong = 14; pub const AT_PLATFORM: c_ulong = 15; pub const AT_HWCAP: c_ulong = 16; pub const AT_CLKTCK: c_ulong = 17; pub const AT_SECURE: c_ulong = 23; pub const AT_BASE_PLATFORM: c_ulong = 24; pub const AT_RANDOM: c_ulong = 25; pub const AT_HWCAP2: c_ulong = 26; pub const AT_EXECFN: c_ulong = 31; // defined in arch//include/uapi/asm/auxvec.h but has the same value // wherever it is defined. pub const AT_SYSINFO_EHDR: c_ulong = 33; pub const AT_MINSIGSTKSZ: c_ulong = 51; pub const GLOB_ERR: c_int = 1 << 0; pub const GLOB_MARK: c_int = 1 << 1; pub const GLOB_NOSORT: c_int = 1 << 2; pub const GLOB_DOOFFS: c_int = 1 << 3; pub const GLOB_NOCHECK: c_int = 1 << 4; pub const GLOB_APPEND: c_int = 1 << 5; pub const GLOB_NOESCAPE: c_int = 1 << 6; pub const GLOB_NOSPACE: c_int = 1; pub const GLOB_ABORTED: c_int = 2; pub const GLOB_NOMATCH: c_int = 3; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 1; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const POSIX_SPAWN_USEVFORK: c_int = 64; pub const POSIX_SPAWN_SETSID: c_int = 128; pub const S_IEXEC: mode_t = 0o0100; pub const S_IWRITE: mode_t = 0o0200; pub const S_IREAD: mode_t = 0o0400; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const F_SEAL_FUTURE_WRITE: c_int = 0x0010; pub const F_SEAL_EXEC: c_int = 0x0020; pub const IFF_LOWER_UP: c_int = 0x10000; pub const IFF_DORMANT: c_int = 0x20000; pub const IFF_ECHO: c_int = 0x40000; // linux/if_addr.h pub const IFA_UNSPEC: c_ushort = 0; pub const IFA_ADDRESS: c_ushort = 1; pub const IFA_LOCAL: c_ushort = 2; pub const IFA_LABEL: c_ushort = 3; pub const IFA_BROADCAST: c_ushort = 4; pub const IFA_ANYCAST: c_ushort = 5; pub const IFA_CACHEINFO: c_ushort = 6; pub const IFA_MULTICAST: c_ushort = 7; pub const IFA_FLAGS: c_ushort = 8; pub const IFA_F_SECONDARY: u32 = 0x01; pub const IFA_F_TEMPORARY: u32 = 0x01; pub const IFA_F_NODAD: u32 = 0x02; pub const IFA_F_OPTIMISTIC: u32 = 0x04; pub const IFA_F_DADFAILED: u32 = 0x08; pub const IFA_F_HOMEADDRESS: u32 = 0x10; pub const IFA_F_DEPRECATED: u32 = 0x20; pub const IFA_F_TENTATIVE: u32 = 0x40; pub const IFA_F_PERMANENT: u32 = 0x80; pub const IFA_F_MANAGETEMPADDR: u32 = 0x100; pub const IFA_F_NOPREFIXROUTE: u32 = 0x200; pub const IFA_F_MCAUTOJOIN: u32 = 0x400; pub const IFA_F_STABLE_PRIVACY: u32 = 0x800; // linux/if_link.h pub const IFLA_UNSPEC: c_ushort = 0; pub const IFLA_ADDRESS: c_ushort = 1; pub const IFLA_BROADCAST: c_ushort = 2; pub const IFLA_IFNAME: c_ushort = 3; pub const IFLA_MTU: c_ushort = 4; pub const IFLA_LINK: c_ushort = 5; pub const IFLA_QDISC: c_ushort = 6; pub const IFLA_STATS: c_ushort = 7; pub const IFLA_COST: c_ushort = 8; pub const IFLA_PRIORITY: c_ushort = 9; pub const IFLA_MASTER: c_ushort = 10; pub const IFLA_WIRELESS: c_ushort = 11; pub const IFLA_PROTINFO: c_ushort = 12; pub const IFLA_TXQLEN: c_ushort = 13; pub const IFLA_MAP: c_ushort = 14; pub const IFLA_WEIGHT: c_ushort = 15; pub const IFLA_OPERSTATE: c_ushort = 16; pub const IFLA_LINKMODE: c_ushort = 17; pub const IFLA_LINKINFO: c_ushort = 18; pub const IFLA_NET_NS_PID: c_ushort = 19; pub const IFLA_IFALIAS: c_ushort = 20; pub const IFLA_NUM_VF: c_ushort = 21; pub const IFLA_VFINFO_LIST: c_ushort = 22; pub const IFLA_STATS64: c_ushort = 23; pub const IFLA_VF_PORTS: c_ushort = 24; pub const IFLA_PORT_SELF: c_ushort = 25; pub const IFLA_AF_SPEC: c_ushort = 26; pub const IFLA_GROUP: c_ushort = 27; pub const IFLA_NET_NS_FD: c_ushort = 28; pub const IFLA_EXT_MASK: c_ushort = 29; pub const IFLA_PROMISCUITY: c_ushort = 30; pub const IFLA_NUM_TX_QUEUES: c_ushort = 31; pub const IFLA_NUM_RX_QUEUES: c_ushort = 32; pub const IFLA_CARRIER: c_ushort = 33; pub const IFLA_PHYS_PORT_ID: c_ushort = 34; pub const IFLA_CARRIER_CHANGES: c_ushort = 35; pub const IFLA_PHYS_SWITCH_ID: c_ushort = 36; pub const IFLA_LINK_NETNSID: c_ushort = 37; pub const IFLA_PHYS_PORT_NAME: c_ushort = 38; pub const IFLA_PROTO_DOWN: c_ushort = 39; pub const IFLA_GSO_MAX_SEGS: c_ushort = 40; pub const IFLA_GSO_MAX_SIZE: c_ushort = 41; pub const IFLA_PAD: c_ushort = 42; pub const IFLA_XDP: c_ushort = 43; pub const IFLA_EVENT: c_ushort = 44; pub const IFLA_NEW_NETNSID: c_ushort = 45; pub const IFLA_IF_NETNSID: c_ushort = 46; pub const IFLA_TARGET_NETNSID: c_ushort = IFLA_IF_NETNSID; pub const IFLA_CARRIER_UP_COUNT: c_ushort = 47; pub const IFLA_CARRIER_DOWN_COUNT: c_ushort = 48; pub const IFLA_NEW_IFINDEX: c_ushort = 49; pub const IFLA_MIN_MTU: c_ushort = 50; pub const IFLA_MAX_MTU: c_ushort = 51; pub const IFLA_PROP_LIST: c_ushort = 52; pub const IFLA_ALT_IFNAME: c_ushort = 53; pub const IFLA_PERM_ADDRESS: c_ushort = 54; pub const IFLA_PROTO_DOWN_REASON: c_ushort = 55; pub const IFLA_PARENT_DEV_NAME: c_ushort = 56; pub const IFLA_PARENT_DEV_BUS_NAME: c_ushort = 57; pub const IFLA_GRO_MAX_SIZE: c_ushort = 58; pub const IFLA_TSO_MAX_SIZE: c_ushort = 59; pub const IFLA_TSO_MAX_SEGS: c_ushort = 60; pub const IFLA_ALLMULTI: c_ushort = 61; pub const IFLA_INFO_UNSPEC: c_ushort = 0; pub const IFLA_INFO_KIND: c_ushort = 1; pub const IFLA_INFO_DATA: c_ushort = 2; pub const IFLA_INFO_XSTATS: c_ushort = 3; pub const IFLA_INFO_SLAVE_KIND: c_ushort = 4; pub const IFLA_INFO_SLAVE_DATA: c_ushort = 5; // linux/if_tun.h /* TUNSETIFF ifr flags */ pub const IFF_TUN: c_int = 0x0001; pub const IFF_TAP: c_int = 0x0002; pub const IFF_NAPI: c_int = 0x0010; pub const IFF_NAPI_FRAGS: c_int = 0x0020; // Used in TUNSETIFF to bring up tun/tap without carrier pub const IFF_NO_CARRIER: c_int = 0x0040; pub const IFF_NO_PI: c_int = 0x1000; // Read queue size pub const TUN_READQ_SIZE: c_short = 500; // TUN device type flags: deprecated. Use IFF_TUN/IFF_TAP instead. pub const TUN_TUN_DEV: c_short = crate::IFF_TUN as c_short; pub const TUN_TAP_DEV: c_short = crate::IFF_TAP as c_short; pub const TUN_TYPE_MASK: c_short = 0x000f; // This flag has no real effect pub const IFF_ONE_QUEUE: c_int = 0x2000; pub const IFF_VNET_HDR: c_int = 0x4000; pub const IFF_TUN_EXCL: c_int = 0x8000; pub const IFF_MULTI_QUEUE: c_int = 0x0100; pub const IFF_ATTACH_QUEUE: c_int = 0x0200; pub const IFF_DETACH_QUEUE: c_int = 0x0400; // read-only flag pub const IFF_PERSIST: c_int = 0x0800; pub const IFF_NOFILTER: c_int = 0x1000; // Socket options pub const TUN_TX_TIMESTAMP: c_int = 1; // Features for GSO (TUNSETOFFLOAD) pub const TUN_F_CSUM: c_uint = 0x01; pub const TUN_F_TSO4: c_uint = 0x02; pub const TUN_F_TSO6: c_uint = 0x04; pub const TUN_F_TSO_ECN: c_uint = 0x08; pub const TUN_F_UFO: c_uint = 0x10; pub const TUN_F_USO4: c_uint = 0x20; pub const TUN_F_USO6: c_uint = 0x40; // Protocol info prepended to the packets (when IFF_NO_PI is not set) pub const TUN_PKT_STRIP: c_int = 0x0001; // Accept all multicast packets pub const TUN_FLT_ALLMULTI: c_int = 0x0001; // Since Linux 3.1 pub const SEEK_DATA: c_int = 3; pub const SEEK_HOLE: c_int = 4; pub const ST_RDONLY: c_ulong = 1; pub const ST_NOSUID: c_ulong = 2; pub const ST_NODEV: c_ulong = 4; pub const ST_NOEXEC: c_ulong = 8; pub const ST_SYNCHRONOUS: c_ulong = 16; pub const ST_MANDLOCK: c_ulong = 64; pub const ST_WRITE: c_ulong = 128; pub const ST_APPEND: c_ulong = 256; pub const ST_IMMUTABLE: c_ulong = 512; pub const ST_NOATIME: c_ulong = 1024; pub const ST_NODIRATIME: c_ulong = 2048; pub const RTLD_NEXT: *mut c_void = -1i64 as *mut c_void; pub const RTLD_DEFAULT: *mut c_void = 0i64 as *mut c_void; pub const RTLD_NODELETE: c_int = 0x1000; pub const RTLD_NOW: c_int = 0x2; pub const AT_EACCESS: c_int = 0x200; // linux/mempolicy.h pub const MPOL_DEFAULT: c_int = 0; pub const MPOL_PREFERRED: c_int = 1; pub const MPOL_BIND: c_int = 2; pub const MPOL_INTERLEAVE: c_int = 3; pub const MPOL_LOCAL: c_int = 4; pub const MPOL_F_NUMA_BALANCING: c_int = 1 << 13; pub const MPOL_F_RELATIVE_NODES: c_int = 1 << 14; pub const MPOL_F_STATIC_NODES: c_int = 1 << 15; // linux/membarrier.h pub const MEMBARRIER_CMD_QUERY: c_int = 0; pub const MEMBARRIER_CMD_GLOBAL: c_int = 1 << 0; pub const MEMBARRIER_CMD_GLOBAL_EXPEDITED: c_int = 1 << 1; pub const MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED: c_int = 1 << 2; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED: c_int = 1 << 3; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED: c_int = 1 << 4; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE: c_int = 1 << 5; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE: c_int = 1 << 6; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ: c_int = 1 << 7; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ: c_int = 1 << 8; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { size: [0; __SIZEOF_PTHREAD_RWLOCK_T], }; pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1; pub const PTHREAD_ONCE_INIT: pthread_once_t = 0; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_MUTEX_STALLED: c_int = 0; pub const PTHREAD_MUTEX_ROBUST: c_int = 1; pub const PTHREAD_PRIO_NONE: c_int = 0; pub const PTHREAD_PRIO_INHERIT: c_int = 1; pub const PTHREAD_PRIO_PROTECT: c_int = 2; pub const PTHREAD_PROCESS_PRIVATE: c_int = 0; pub const PTHREAD_PROCESS_SHARED: c_int = 1; pub const PTHREAD_INHERIT_SCHED: c_int = 0; pub const PTHREAD_EXPLICIT_SCHED: c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const RENAME_NOREPLACE: c_uint = 1; pub const RENAME_EXCHANGE: c_uint = 2; pub const RENAME_WHITEOUT: c_uint = 4; // netinet/in.h // NOTE: These are in addition to the constants defined in src/unix/mod.rs #[deprecated( since = "0.2.80", note = "This value was increased in the newer kernel \ and we'll change this following upstream in the future release. \ See #1896 for more info." )] pub const IPPROTO_MAX: c_int = 256; // System V IPC pub const IPC_PRIVATE: crate::key_t = 0; pub const IPC_CREAT: c_int = 0o1000; pub const IPC_EXCL: c_int = 0o2000; pub const IPC_NOWAIT: c_int = 0o4000; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 1; pub const IPC_STAT: c_int = 2; pub const IPC_INFO: c_int = 3; pub const MSG_STAT: c_int = 11; pub const MSG_INFO: c_int = 12; pub const MSG_NOTIFICATION: c_int = 0x8000; pub const MSG_NOERROR: c_int = 0o10000; pub const MSG_EXCEPT: c_int = 0o20000; pub const MSG_ZEROCOPY: c_int = 0x4000000; pub const SEM_UNDO: c_int = 0x1000; pub const GETPID: c_int = 11; pub const GETVAL: c_int = 12; pub const GETALL: c_int = 13; pub const GETNCNT: c_int = 14; pub const GETZCNT: c_int = 15; pub const SETVAL: c_int = 16; pub const SETALL: c_int = 17; pub const SEM_STAT: c_int = 18; pub const SEM_INFO: c_int = 19; pub const SEM_STAT_ANY: c_int = 20; pub const SHM_R: c_int = 0o400; pub const SHM_W: c_int = 0o200; pub const SHM_RDONLY: c_int = 0o10000; pub const SHM_RND: c_int = 0o20000; pub const SHM_REMAP: c_int = 0o40000; pub const SHM_LOCK: c_int = 11; pub const SHM_UNLOCK: c_int = 12; pub const SHM_HUGETLB: c_int = 0o4000; #[cfg(not(all(target_env = "uclibc", target_arch = "mips")))] pub const SHM_NORESERVE: c_int = 0o10000; pub const QFMT_VFS_OLD: c_int = 1; pub const QFMT_VFS_V0: c_int = 2; pub const QFMT_VFS_V1: c_int = 4; pub const EFD_SEMAPHORE: c_int = 0x1; pub const LOG_NFACILITIES: c_int = 24; pub const SEM_FAILED: *mut crate::sem_t = 0 as *mut sem_t; pub const RB_AUTOBOOT: c_int = 0x01234567u32 as i32; pub const RB_HALT_SYSTEM: c_int = 0xcdef0123u32 as i32; pub const RB_ENABLE_CAD: c_int = 0x89abcdefu32 as i32; pub const RB_DISABLE_CAD: c_int = 0x00000000u32 as i32; pub const RB_POWER_OFF: c_int = 0x4321fedcu32 as i32; pub const RB_SW_SUSPEND: c_int = 0xd000fce2u32 as i32; pub const RB_KEXEC: c_int = 0x45584543u32 as i32; pub const AI_PASSIVE: c_int = 0x0001; pub const AI_CANONNAME: c_int = 0x0002; pub const AI_NUMERICHOST: c_int = 0x0004; pub const AI_V4MAPPED: c_int = 0x0008; pub const AI_ALL: c_int = 0x0010; pub const AI_ADDRCONFIG: c_int = 0x0020; pub const AI_NUMERICSERV: c_int = 0x0400; pub const EAI_BADFLAGS: c_int = -1; pub const EAI_NONAME: c_int = -2; pub const EAI_AGAIN: c_int = -3; pub const EAI_FAIL: c_int = -4; pub const EAI_NODATA: c_int = -5; pub const EAI_FAMILY: c_int = -6; pub const EAI_SOCKTYPE: c_int = -7; pub const EAI_SERVICE: c_int = -8; pub const EAI_MEMORY: c_int = -10; pub const EAI_SYSTEM: c_int = -11; pub const EAI_OVERFLOW: c_int = -12; pub const NI_NUMERICHOST: c_int = 1; pub const NI_NUMERICSERV: c_int = 2; pub const NI_NOFQDN: c_int = 4; pub const NI_NAMEREQD: c_int = 8; pub const NI_DGRAM: c_int = 16; pub const NI_IDN: c_int = 32; pub const SYNC_FILE_RANGE_WAIT_BEFORE: c_uint = 1; pub const SYNC_FILE_RANGE_WRITE: c_uint = 2; pub const SYNC_FILE_RANGE_WAIT_AFTER: c_uint = 4; cfg_if! { if #[cfg(not(target_env = "uclibc"))] { pub const AIO_CANCELED: c_int = 0; pub const AIO_NOTCANCELED: c_int = 1; pub const AIO_ALLDONE: c_int = 2; pub const LIO_READ: c_int = 0; pub const LIO_WRITE: c_int = 1; pub const LIO_NOP: c_int = 2; pub const LIO_WAIT: c_int = 0; pub const LIO_NOWAIT: c_int = 1; pub const RUSAGE_THREAD: c_int = 1; pub const MSG_COPY: c_int = 0o40000; pub const SHM_EXEC: c_int = 0o100000; pub const IPV6_MULTICAST_ALL: c_int = 29; pub const IPV6_ROUTER_ALERT_ISOLATE: c_int = 30; pub const PACKET_MR_UNICAST: c_int = 3; pub const PTRACE_EVENT_STOP: c_int = 128; pub const UDP_SEGMENT: c_int = 103; pub const UDP_GRO: c_int = 104; } } pub const MREMAP_MAYMOVE: c_int = 1; pub const MREMAP_FIXED: c_int = 2; pub const MREMAP_DONTUNMAP: c_int = 4; pub const PR_SET_PDEATHSIG: c_int = 1; pub const PR_GET_PDEATHSIG: c_int = 2; pub const PR_GET_DUMPABLE: c_int = 3; pub const PR_SET_DUMPABLE: c_int = 4; pub const PR_GET_UNALIGN: c_int = 5; pub const PR_SET_UNALIGN: c_int = 6; pub const PR_UNALIGN_NOPRINT: c_int = 1; pub const PR_UNALIGN_SIGBUS: c_int = 2; pub const PR_GET_KEEPCAPS: c_int = 7; pub const PR_SET_KEEPCAPS: c_int = 8; pub const PR_GET_FPEMU: c_int = 9; pub const PR_SET_FPEMU: c_int = 10; pub const PR_FPEMU_NOPRINT: c_int = 1; pub const PR_FPEMU_SIGFPE: c_int = 2; pub const PR_GET_FPEXC: c_int = 11; pub const PR_SET_FPEXC: c_int = 12; pub const PR_FP_EXC_SW_ENABLE: c_int = 0x80; pub const PR_FP_EXC_DIV: c_int = 0x010000; pub const PR_FP_EXC_OVF: c_int = 0x020000; pub const PR_FP_EXC_UND: c_int = 0x040000; pub const PR_FP_EXC_RES: c_int = 0x080000; pub const PR_FP_EXC_INV: c_int = 0x100000; pub const PR_FP_EXC_DISABLED: c_int = 0; pub const PR_FP_EXC_NONRECOV: c_int = 1; pub const PR_FP_EXC_ASYNC: c_int = 2; pub const PR_FP_EXC_PRECISE: c_int = 3; pub const PR_GET_TIMING: c_int = 13; pub const PR_SET_TIMING: c_int = 14; pub const PR_TIMING_STATISTICAL: c_int = 0; pub const PR_TIMING_TIMESTAMP: c_int = 1; pub const PR_SET_NAME: c_int = 15; pub const PR_GET_NAME: c_int = 16; pub const PR_GET_ENDIAN: c_int = 19; pub const PR_SET_ENDIAN: c_int = 20; pub const PR_ENDIAN_BIG: c_int = 0; pub const PR_ENDIAN_LITTLE: c_int = 1; pub const PR_ENDIAN_PPC_LITTLE: c_int = 2; pub const PR_GET_SECCOMP: c_int = 21; pub const PR_SET_SECCOMP: c_int = 22; pub const PR_CAPBSET_READ: c_int = 23; pub const PR_CAPBSET_DROP: c_int = 24; pub const PR_GET_TSC: c_int = 25; pub const PR_SET_TSC: c_int = 26; pub const PR_TSC_ENABLE: c_int = 1; pub const PR_TSC_SIGSEGV: c_int = 2; pub const PR_GET_SECUREBITS: c_int = 27; pub const PR_SET_SECUREBITS: c_int = 28; pub const PR_SET_TIMERSLACK: c_int = 29; pub const PR_GET_TIMERSLACK: c_int = 30; pub const PR_TASK_PERF_EVENTS_DISABLE: c_int = 31; pub const PR_TASK_PERF_EVENTS_ENABLE: c_int = 32; pub const PR_MCE_KILL: c_int = 33; pub const PR_MCE_KILL_CLEAR: c_int = 0; pub const PR_MCE_KILL_SET: c_int = 1; pub const PR_MCE_KILL_LATE: c_int = 0; pub const PR_MCE_KILL_EARLY: c_int = 1; pub const PR_MCE_KILL_DEFAULT: c_int = 2; pub const PR_MCE_KILL_GET: c_int = 34; pub const PR_SET_MM: c_int = 35; pub const PR_SET_MM_START_CODE: c_int = 1; pub const PR_SET_MM_END_CODE: c_int = 2; pub const PR_SET_MM_START_DATA: c_int = 3; pub const PR_SET_MM_END_DATA: c_int = 4; pub const PR_SET_MM_START_STACK: c_int = 5; pub const PR_SET_MM_START_BRK: c_int = 6; pub const PR_SET_MM_BRK: c_int = 7; pub const PR_SET_MM_ARG_START: c_int = 8; pub const PR_SET_MM_ARG_END: c_int = 9; pub const PR_SET_MM_ENV_START: c_int = 10; pub const PR_SET_MM_ENV_END: c_int = 11; pub const PR_SET_MM_AUXV: c_int = 12; pub const PR_SET_MM_EXE_FILE: c_int = 13; pub const PR_SET_MM_MAP: c_int = 14; pub const PR_SET_MM_MAP_SIZE: c_int = 15; pub const PR_SET_PTRACER: c_int = 0x59616d61; pub const PR_SET_PTRACER_ANY: c_ulong = 0xffffffffffffffff; pub const PR_SET_CHILD_SUBREAPER: c_int = 36; pub const PR_GET_CHILD_SUBREAPER: c_int = 37; pub const PR_SET_NO_NEW_PRIVS: c_int = 38; pub const PR_GET_NO_NEW_PRIVS: c_int = 39; pub const PR_GET_TID_ADDRESS: c_int = 40; pub const PR_SET_THP_DISABLE: c_int = 41; pub const PR_GET_THP_DISABLE: c_int = 42; pub const PR_MPX_ENABLE_MANAGEMENT: c_int = 43; pub const PR_MPX_DISABLE_MANAGEMENT: c_int = 44; pub const PR_SET_FP_MODE: c_int = 45; pub const PR_GET_FP_MODE: c_int = 46; pub const PR_FP_MODE_FR: c_int = 1 << 0; pub const PR_FP_MODE_FRE: c_int = 1 << 1; pub const PR_CAP_AMBIENT: c_int = 47; pub const PR_CAP_AMBIENT_IS_SET: c_int = 1; pub const PR_CAP_AMBIENT_RAISE: c_int = 2; pub const PR_CAP_AMBIENT_LOWER: c_int = 3; pub const PR_CAP_AMBIENT_CLEAR_ALL: c_int = 4; pub const PR_SET_VMA: c_int = 0x53564d41; pub const PR_SET_VMA_ANON_NAME: c_int = 0; pub const PR_SCHED_CORE: c_int = 62; pub const PR_SCHED_CORE_GET: c_int = 0; pub const PR_SCHED_CORE_CREATE: c_int = 1; pub const PR_SCHED_CORE_SHARE_TO: c_int = 2; pub const PR_SCHED_CORE_SHARE_FROM: c_int = 3; pub const PR_SCHED_CORE_MAX: c_int = 4; pub const PR_SCHED_CORE_SCOPE_THREAD: c_int = 0; pub const PR_SCHED_CORE_SCOPE_THREAD_GROUP: c_int = 1; pub const PR_SCHED_CORE_SCOPE_PROCESS_GROUP: c_int = 2; pub const GRND_NONBLOCK: c_uint = 0x0001; pub const GRND_RANDOM: c_uint = 0x0002; pub const GRND_INSECURE: c_uint = 0x0004; // pub const SECCOMP_MODE_DISABLED: c_uint = 0; pub const SECCOMP_MODE_STRICT: c_uint = 1; pub const SECCOMP_MODE_FILTER: c_uint = 2; pub const SECCOMP_SET_MODE_STRICT: c_uint = 0; pub const SECCOMP_SET_MODE_FILTER: c_uint = 1; pub const SECCOMP_GET_ACTION_AVAIL: c_uint = 2; pub const SECCOMP_GET_NOTIF_SIZES: c_uint = 3; pub const SECCOMP_FILTER_FLAG_TSYNC: c_ulong = 1 << 0; pub const SECCOMP_FILTER_FLAG_LOG: c_ulong = 1 << 1; pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: c_ulong = 1 << 2; pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: c_ulong = 1 << 3; pub const SECCOMP_FILTER_FLAG_TSYNC_ESRCH: c_ulong = 1 << 4; pub const SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV: c_ulong = 1 << 5; pub const SECCOMP_RET_KILL_PROCESS: c_uint = 0x80000000; pub const SECCOMP_RET_KILL_THREAD: c_uint = 0x00000000; pub const SECCOMP_RET_KILL: c_uint = SECCOMP_RET_KILL_THREAD; pub const SECCOMP_RET_TRAP: c_uint = 0x00030000; pub const SECCOMP_RET_ERRNO: c_uint = 0x00050000; pub const SECCOMP_RET_USER_NOTIF: c_uint = 0x7fc00000; pub const SECCOMP_RET_TRACE: c_uint = 0x7ff00000; pub const SECCOMP_RET_LOG: c_uint = 0x7ffc0000; pub const SECCOMP_RET_ALLOW: c_uint = 0x7fff0000; pub const SECCOMP_RET_ACTION_FULL: c_uint = 0xffff0000; pub const SECCOMP_RET_ACTION: c_uint = 0x7fff0000; pub const SECCOMP_RET_DATA: c_uint = 0x0000ffff; pub const SECCOMP_USER_NOTIF_FLAG_CONTINUE: c_ulong = 1; pub const SECCOMP_ADDFD_FLAG_SETFD: c_ulong = 1; pub const SECCOMP_ADDFD_FLAG_SEND: c_ulong = 2; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; pub const ITIMER_PROF: c_int = 2; pub const TFD_CLOEXEC: c_int = O_CLOEXEC; pub const TFD_NONBLOCK: c_int = O_NONBLOCK; pub const TFD_TIMER_ABSTIME: c_int = 1; pub const TFD_TIMER_CANCEL_ON_SET: c_int = 2; pub const _POSIX_VDISABLE: crate::cc_t = 0; pub const FALLOC_FL_KEEP_SIZE: c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: c_int = 0x02; pub const FALLOC_FL_COLLAPSE_RANGE: c_int = 0x08; pub const FALLOC_FL_ZERO_RANGE: c_int = 0x10; pub const FALLOC_FL_INSERT_RANGE: c_int = 0x20; pub const FALLOC_FL_UNSHARE_RANGE: c_int = 0x40; #[deprecated( since = "0.2.55", note = "ENOATTR is not available on Linux; use ENODATA instead" )] pub const ENOATTR: c_int = crate::ENODATA; pub const SO_ORIGINAL_DST: c_int = 80; pub const IP_RECVFRAGSIZE: c_int = 25; pub const IPV6_FLOWINFO: c_int = 11; pub const IPV6_FLOWLABEL_MGR: c_int = 32; pub const IPV6_FLOWINFO_SEND: c_int = 33; pub const IPV6_RECVFRAGSIZE: c_int = 77; pub const IPV6_FREEBIND: c_int = 78; pub const IPV6_FLOWINFO_FLOWLABEL: c_int = 0x000fffff; pub const IPV6_FLOWINFO_PRIORITY: c_int = 0x0ff00000; pub const IPV6_RTHDR_LOOSE: c_int = 0; pub const IPV6_RTHDR_STRICT: c_int = 1; // SO_MEMINFO offsets pub const SK_MEMINFO_RMEM_ALLOC: c_int = 0; pub const SK_MEMINFO_RCVBUF: c_int = 1; pub const SK_MEMINFO_WMEM_ALLOC: c_int = 2; pub const SK_MEMINFO_SNDBUF: c_int = 3; pub const SK_MEMINFO_FWD_ALLOC: c_int = 4; pub const SK_MEMINFO_WMEM_QUEUED: c_int = 5; pub const SK_MEMINFO_OPTMEM: c_int = 6; pub const SK_MEMINFO_BACKLOG: c_int = 7; pub const SK_MEMINFO_DROPS: c_int = 8; pub const IUTF8: crate::tcflag_t = 0x00004000; #[cfg(not(all(target_env = "uclibc", target_arch = "mips")))] pub const CMSPAR: crate::tcflag_t = 0o10000000000; pub const MFD_CLOEXEC: c_uint = 0x0001; pub const MFD_ALLOW_SEALING: c_uint = 0x0002; pub const MFD_HUGETLB: c_uint = 0x0004; pub const MFD_NOEXEC_SEAL: c_uint = 0x0008; pub const MFD_EXEC: c_uint = 0x0010; pub const MFD_HUGE_64KB: c_uint = 0x40000000; pub const MFD_HUGE_512KB: c_uint = 0x4c000000; pub const MFD_HUGE_1MB: c_uint = 0x50000000; pub const MFD_HUGE_2MB: c_uint = 0x54000000; pub const MFD_HUGE_8MB: c_uint = 0x5c000000; pub const MFD_HUGE_16MB: c_uint = 0x60000000; pub const MFD_HUGE_32MB: c_uint = 0x64000000; pub const MFD_HUGE_256MB: c_uint = 0x70000000; pub const MFD_HUGE_512MB: c_uint = 0x74000000; pub const MFD_HUGE_1GB: c_uint = 0x78000000; pub const MFD_HUGE_2GB: c_uint = 0x7c000000; pub const MFD_HUGE_16GB: c_uint = 0x88000000; pub const MFD_HUGE_MASK: c_uint = 63; pub const MFD_HUGE_SHIFT: c_uint = 26; // linux/close_range.h pub const CLOSE_RANGE_UNSHARE: c_uint = 1 << 1; pub const CLOSE_RANGE_CLOEXEC: c_uint = 1 << 2; // linux/filter.h pub const SKF_AD_OFF: c_int = -0x1000; pub const SKF_AD_PROTOCOL: c_int = 0; pub const SKF_AD_PKTTYPE: c_int = 4; pub const SKF_AD_IFINDEX: c_int = 8; pub const SKF_AD_NLATTR: c_int = 12; pub const SKF_AD_NLATTR_NEST: c_int = 16; pub const SKF_AD_MARK: c_int = 20; pub const SKF_AD_QUEUE: c_int = 24; pub const SKF_AD_HATYPE: c_int = 28; pub const SKF_AD_RXHASH: c_int = 32; pub const SKF_AD_CPU: c_int = 36; pub const SKF_AD_ALU_XOR_X: c_int = 40; pub const SKF_AD_VLAN_TAG: c_int = 44; pub const SKF_AD_VLAN_TAG_PRESENT: c_int = 48; pub const SKF_AD_PAY_OFFSET: c_int = 52; pub const SKF_AD_RANDOM: c_int = 56; pub const SKF_AD_VLAN_TPID: c_int = 60; pub const SKF_AD_MAX: c_int = 64; pub const SKF_NET_OFF: c_int = -0x100000; pub const SKF_LL_OFF: c_int = -0x200000; pub const BPF_NET_OFF: c_int = SKF_NET_OFF; pub const BPF_LL_OFF: c_int = SKF_LL_OFF; pub const BPF_MEMWORDS: c_int = 16; pub const BPF_MAXINSNS: c_int = 4096; // linux/bpf_common.h pub const BPF_LD: __u32 = 0x00; pub const BPF_LDX: __u32 = 0x01; pub const BPF_ST: __u32 = 0x02; pub const BPF_STX: __u32 = 0x03; pub const BPF_ALU: __u32 = 0x04; pub const BPF_JMP: __u32 = 0x05; pub const BPF_RET: __u32 = 0x06; pub const BPF_MISC: __u32 = 0x07; pub const BPF_W: __u32 = 0x00; pub const BPF_H: __u32 = 0x08; pub const BPF_B: __u32 = 0x10; pub const BPF_IMM: __u32 = 0x00; pub const BPF_ABS: __u32 = 0x20; pub const BPF_IND: __u32 = 0x40; pub const BPF_MEM: __u32 = 0x60; pub const BPF_LEN: __u32 = 0x80; pub const BPF_MSH: __u32 = 0xa0; pub const BPF_ADD: __u32 = 0x00; pub const BPF_SUB: __u32 = 0x10; pub const BPF_MUL: __u32 = 0x20; pub const BPF_DIV: __u32 = 0x30; pub const BPF_OR: __u32 = 0x40; pub const BPF_AND: __u32 = 0x50; pub const BPF_LSH: __u32 = 0x60; pub const BPF_RSH: __u32 = 0x70; pub const BPF_NEG: __u32 = 0x80; pub const BPF_MOD: __u32 = 0x90; pub const BPF_XOR: __u32 = 0xa0; pub const BPF_JA: __u32 = 0x00; pub const BPF_JEQ: __u32 = 0x10; pub const BPF_JGT: __u32 = 0x20; pub const BPF_JGE: __u32 = 0x30; pub const BPF_JSET: __u32 = 0x40; pub const BPF_K: __u32 = 0x00; pub const BPF_X: __u32 = 0x08; // linux/filter.h pub const BPF_A: __u32 = 0x10; pub const BPF_TAX: __u32 = 0x00; pub const BPF_TXA: __u32 = 0x80; // linux/openat2.h pub const RESOLVE_NO_XDEV: crate::__u64 = 0x01; pub const RESOLVE_NO_MAGICLINKS: crate::__u64 = 0x02; pub const RESOLVE_NO_SYMLINKS: crate::__u64 = 0x04; pub const RESOLVE_BENEATH: crate::__u64 = 0x08; pub const RESOLVE_IN_ROOT: crate::__u64 = 0x10; pub const RESOLVE_CACHED: crate::__u64 = 0x20; // linux/if_ether.h pub const ETH_ALEN: c_int = 6; pub const ETH_HLEN: c_int = 14; pub const ETH_ZLEN: c_int = 60; pub const ETH_DATA_LEN: c_int = 1500; pub const ETH_FRAME_LEN: c_int = 1514; pub const ETH_FCS_LEN: c_int = 4; // These are the defined Ethernet Protocol ID's. pub const ETH_P_LOOP: c_int = 0x0060; pub const ETH_P_PUP: c_int = 0x0200; pub const ETH_P_PUPAT: c_int = 0x0201; pub const ETH_P_IP: c_int = 0x0800; pub const ETH_P_X25: c_int = 0x0805; pub const ETH_P_ARP: c_int = 0x0806; pub const ETH_P_BPQ: c_int = 0x08FF; pub const ETH_P_IEEEPUP: c_int = 0x0a00; pub const ETH_P_IEEEPUPAT: c_int = 0x0a01; pub const ETH_P_BATMAN: c_int = 0x4305; pub const ETH_P_DEC: c_int = 0x6000; pub const ETH_P_DNA_DL: c_int = 0x6001; pub const ETH_P_DNA_RC: c_int = 0x6002; pub const ETH_P_DNA_RT: c_int = 0x6003; pub const ETH_P_LAT: c_int = 0x6004; pub const ETH_P_DIAG: c_int = 0x6005; pub const ETH_P_CUST: c_int = 0x6006; pub const ETH_P_SCA: c_int = 0x6007; pub const ETH_P_TEB: c_int = 0x6558; pub const ETH_P_RARP: c_int = 0x8035; pub const ETH_P_ATALK: c_int = 0x809B; pub const ETH_P_AARP: c_int = 0x80F3; pub const ETH_P_8021Q: c_int = 0x8100; pub const ETH_P_IPX: c_int = 0x8137; pub const ETH_P_IPV6: c_int = 0x86DD; pub const ETH_P_PAUSE: c_int = 0x8808; pub const ETH_P_SLOW: c_int = 0x8809; pub const ETH_P_WCCP: c_int = 0x883E; pub const ETH_P_MPLS_UC: c_int = 0x8847; pub const ETH_P_MPLS_MC: c_int = 0x8848; pub const ETH_P_ATMMPOA: c_int = 0x884c; pub const ETH_P_PPP_DISC: c_int = 0x8863; pub const ETH_P_PPP_SES: c_int = 0x8864; pub const ETH_P_LINK_CTL: c_int = 0x886c; pub const ETH_P_ATMFATE: c_int = 0x8884; pub const ETH_P_PAE: c_int = 0x888E; pub const ETH_P_AOE: c_int = 0x88A2; pub const ETH_P_8021AD: c_int = 0x88A8; pub const ETH_P_802_EX1: c_int = 0x88B5; pub const ETH_P_TIPC: c_int = 0x88CA; pub const ETH_P_MACSEC: c_int = 0x88E5; pub const ETH_P_8021AH: c_int = 0x88E7; pub const ETH_P_MVRP: c_int = 0x88F5; pub const ETH_P_1588: c_int = 0x88F7; pub const ETH_P_PRP: c_int = 0x88FB; pub const ETH_P_FCOE: c_int = 0x8906; pub const ETH_P_TDLS: c_int = 0x890D; pub const ETH_P_FIP: c_int = 0x8914; pub const ETH_P_80221: c_int = 0x8917; pub const ETH_P_LOOPBACK: c_int = 0x9000; pub const ETH_P_QINQ1: c_int = 0x9100; pub const ETH_P_QINQ2: c_int = 0x9200; pub const ETH_P_QINQ3: c_int = 0x9300; pub const ETH_P_EDSA: c_int = 0xDADA; pub const ETH_P_AF_IUCV: c_int = 0xFBFB; pub const ETH_P_802_3_MIN: c_int = 0x0600; // Non DIX types. Won't clash for 1500 types. pub const ETH_P_802_3: c_int = 0x0001; pub const ETH_P_AX25: c_int = 0x0002; pub const ETH_P_ALL: c_int = 0x0003; pub const ETH_P_802_2: c_int = 0x0004; pub const ETH_P_SNAP: c_int = 0x0005; pub const ETH_P_DDCMP: c_int = 0x0006; pub const ETH_P_WAN_PPP: c_int = 0x0007; pub const ETH_P_PPP_MP: c_int = 0x0008; pub const ETH_P_LOCALTALK: c_int = 0x0009; pub const ETH_P_CANFD: c_int = 0x000D; pub const ETH_P_PPPTALK: c_int = 0x0010; pub const ETH_P_TR_802_2: c_int = 0x0011; pub const ETH_P_MOBITEX: c_int = 0x0015; pub const ETH_P_CONTROL: c_int = 0x0016; pub const ETH_P_IRDA: c_int = 0x0017; pub const ETH_P_ECONET: c_int = 0x0018; pub const ETH_P_HDLC: c_int = 0x0019; pub const ETH_P_ARCNET: c_int = 0x001A; pub const ETH_P_DSA: c_int = 0x001B; pub const ETH_P_TRAILER: c_int = 0x001C; pub const ETH_P_PHONET: c_int = 0x00F5; pub const ETH_P_IEEE802154: c_int = 0x00F6; pub const ETH_P_CAIF: c_int = 0x00F7; // DIFF(main): changed to `c_short` in f62eb023ab pub const POSIX_SPAWN_RESETIDS: c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: c_int = 0x02; pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x04; pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x08; pub const POSIX_SPAWN_SETSCHEDPARAM: c_int = 0x10; pub const POSIX_SPAWN_SETSCHEDULER: c_int = 0x20; pub const NLMSG_NOOP: c_int = 0x1; pub const NLMSG_ERROR: c_int = 0x2; pub const NLMSG_DONE: c_int = 0x3; pub const NLMSG_OVERRUN: c_int = 0x4; pub const NLMSG_MIN_TYPE: c_int = 0x10; // linux/netfilter/nfnetlink.h pub const NFNLGRP_NONE: c_int = 0; pub const NFNLGRP_CONNTRACK_NEW: c_int = 1; pub const NFNLGRP_CONNTRACK_UPDATE: c_int = 2; pub const NFNLGRP_CONNTRACK_DESTROY: c_int = 3; pub const NFNLGRP_CONNTRACK_EXP_NEW: c_int = 4; pub const NFNLGRP_CONNTRACK_EXP_UPDATE: c_int = 5; pub const NFNLGRP_CONNTRACK_EXP_DESTROY: c_int = 6; pub const NFNLGRP_NFTABLES: c_int = 7; pub const NFNLGRP_ACCT_QUOTA: c_int = 8; pub const NFNLGRP_NFTRACE: c_int = 9; pub const NFNETLINK_V0: c_int = 0; pub const NFNL_SUBSYS_NONE: c_int = 0; pub const NFNL_SUBSYS_CTNETLINK: c_int = 1; pub const NFNL_SUBSYS_CTNETLINK_EXP: c_int = 2; pub const NFNL_SUBSYS_QUEUE: c_int = 3; pub const NFNL_SUBSYS_ULOG: c_int = 4; pub const NFNL_SUBSYS_OSF: c_int = 5; pub const NFNL_SUBSYS_IPSET: c_int = 6; pub const NFNL_SUBSYS_ACCT: c_int = 7; pub const NFNL_SUBSYS_CTNETLINK_TIMEOUT: c_int = 8; pub const NFNL_SUBSYS_CTHELPER: c_int = 9; pub const NFNL_SUBSYS_NFTABLES: c_int = 10; pub const NFNL_SUBSYS_NFT_COMPAT: c_int = 11; pub const NFNL_SUBSYS_HOOK: c_int = 12; pub const NFNL_SUBSYS_COUNT: c_int = 13; pub const NFNL_MSG_BATCH_BEGIN: c_int = NLMSG_MIN_TYPE; pub const NFNL_MSG_BATCH_END: c_int = NLMSG_MIN_TYPE + 1; pub const NFNL_BATCH_UNSPEC: c_int = 0; pub const NFNL_BATCH_GENID: c_int = 1; // linux/netfilter/nfnetlink_log.h pub const NFULNL_MSG_PACKET: c_int = 0; pub const NFULNL_MSG_CONFIG: c_int = 1; pub const NFULA_VLAN_UNSPEC: c_int = 0; pub const NFULA_VLAN_PROTO: c_int = 1; pub const NFULA_VLAN_TCI: c_int = 2; pub const NFULA_UNSPEC: c_int = 0; pub const NFULA_PACKET_HDR: c_int = 1; pub const NFULA_MARK: c_int = 2; pub const NFULA_TIMESTAMP: c_int = 3; pub const NFULA_IFINDEX_INDEV: c_int = 4; pub const NFULA_IFINDEX_OUTDEV: c_int = 5; pub const NFULA_IFINDEX_PHYSINDEV: c_int = 6; pub const NFULA_IFINDEX_PHYSOUTDEV: c_int = 7; pub const NFULA_HWADDR: c_int = 8; pub const NFULA_PAYLOAD: c_int = 9; pub const NFULA_PREFIX: c_int = 10; pub const NFULA_UID: c_int = 11; pub const NFULA_SEQ: c_int = 12; pub const NFULA_SEQ_GLOBAL: c_int = 13; pub const NFULA_GID: c_int = 14; pub const NFULA_HWTYPE: c_int = 15; pub const NFULA_HWHEADER: c_int = 16; pub const NFULA_HWLEN: c_int = 17; pub const NFULA_CT: c_int = 18; pub const NFULA_CT_INFO: c_int = 19; pub const NFULA_VLAN: c_int = 20; pub const NFULA_L2HDR: c_int = 21; pub const NFULNL_CFG_CMD_NONE: c_int = 0; pub const NFULNL_CFG_CMD_BIND: c_int = 1; pub const NFULNL_CFG_CMD_UNBIND: c_int = 2; pub const NFULNL_CFG_CMD_PF_BIND: c_int = 3; pub const NFULNL_CFG_CMD_PF_UNBIND: c_int = 4; pub const NFULA_CFG_UNSPEC: c_int = 0; pub const NFULA_CFG_CMD: c_int = 1; pub const NFULA_CFG_MODE: c_int = 2; pub const NFULA_CFG_NLBUFSIZ: c_int = 3; pub const NFULA_CFG_TIMEOUT: c_int = 4; pub const NFULA_CFG_QTHRESH: c_int = 5; pub const NFULA_CFG_FLAGS: c_int = 6; pub const NFULNL_COPY_NONE: c_int = 0x00; pub const NFULNL_COPY_META: c_int = 0x01; pub const NFULNL_COPY_PACKET: c_int = 0x02; pub const NFULNL_CFG_F_SEQ: c_int = 0x0001; pub const NFULNL_CFG_F_SEQ_GLOBAL: c_int = 0x0002; pub const NFULNL_CFG_F_CONNTRACK: c_int = 0x0004; // linux/netfilter/nfnetlink_queue.h pub const NFQNL_MSG_PACKET: c_int = 0; pub const NFQNL_MSG_VERDICT: c_int = 1; pub const NFQNL_MSG_CONFIG: c_int = 2; pub const NFQNL_MSG_VERDICT_BATCH: c_int = 3; pub const NFQA_UNSPEC: c_int = 0; pub const NFQA_PACKET_HDR: c_int = 1; pub const NFQA_VERDICT_HDR: c_int = 2; pub const NFQA_MARK: c_int = 3; pub const NFQA_TIMESTAMP: c_int = 4; pub const NFQA_IFINDEX_INDEV: c_int = 5; pub const NFQA_IFINDEX_OUTDEV: c_int = 6; pub const NFQA_IFINDEX_PHYSINDEV: c_int = 7; pub const NFQA_IFINDEX_PHYSOUTDEV: c_int = 8; pub const NFQA_HWADDR: c_int = 9; pub const NFQA_PAYLOAD: c_int = 10; pub const NFQA_CT: c_int = 11; pub const NFQA_CT_INFO: c_int = 12; pub const NFQA_CAP_LEN: c_int = 13; pub const NFQA_SKB_INFO: c_int = 14; pub const NFQA_EXP: c_int = 15; pub const NFQA_UID: c_int = 16; pub const NFQA_GID: c_int = 17; pub const NFQA_SECCTX: c_int = 18; pub const NFQA_VLAN: c_int = 19; pub const NFQA_L2HDR: c_int = 20; pub const NFQA_PRIORITY: c_int = 21; pub const NFQA_VLAN_UNSPEC: c_int = 0; pub const NFQA_VLAN_PROTO: c_int = 1; pub const NFQA_VLAN_TCI: c_int = 2; pub const NFQNL_CFG_CMD_NONE: c_int = 0; pub const NFQNL_CFG_CMD_BIND: c_int = 1; pub const NFQNL_CFG_CMD_UNBIND: c_int = 2; pub const NFQNL_CFG_CMD_PF_BIND: c_int = 3; pub const NFQNL_CFG_CMD_PF_UNBIND: c_int = 4; pub const NFQNL_COPY_NONE: c_int = 0; pub const NFQNL_COPY_META: c_int = 1; pub const NFQNL_COPY_PACKET: c_int = 2; pub const NFQA_CFG_UNSPEC: c_int = 0; pub const NFQA_CFG_CMD: c_int = 1; pub const NFQA_CFG_PARAMS: c_int = 2; pub const NFQA_CFG_QUEUE_MAXLEN: c_int = 3; pub const NFQA_CFG_MASK: c_int = 4; pub const NFQA_CFG_FLAGS: c_int = 5; pub const NFQA_CFG_F_FAIL_OPEN: c_int = 0x0001; pub const NFQA_CFG_F_CONNTRACK: c_int = 0x0002; pub const NFQA_CFG_F_GSO: c_int = 0x0004; pub const NFQA_CFG_F_UID_GID: c_int = 0x0008; pub const NFQA_CFG_F_SECCTX: c_int = 0x0010; pub const NFQA_CFG_F_MAX: c_int = 0x0020; pub const NFQA_SKB_CSUMNOTREADY: c_int = 0x0001; pub const NFQA_SKB_GSO: c_int = 0x0002; pub const NFQA_SKB_CSUM_NOTVERIFIED: c_int = 0x0004; // linux/genetlink.h pub const GENL_NAMSIZ: c_int = 16; pub const GENL_MIN_ID: c_int = NLMSG_MIN_TYPE; pub const GENL_MAX_ID: c_int = 1023; pub const GENL_ADMIN_PERM: c_int = 0x01; pub const GENL_CMD_CAP_DO: c_int = 0x02; pub const GENL_CMD_CAP_DUMP: c_int = 0x04; pub const GENL_CMD_CAP_HASPOL: c_int = 0x08; pub const GENL_ID_CTRL: c_int = NLMSG_MIN_TYPE; pub const CTRL_CMD_UNSPEC: c_int = 0; pub const CTRL_CMD_NEWFAMILY: c_int = 1; pub const CTRL_CMD_DELFAMILY: c_int = 2; pub const CTRL_CMD_GETFAMILY: c_int = 3; pub const CTRL_CMD_NEWOPS: c_int = 4; pub const CTRL_CMD_DELOPS: c_int = 5; pub const CTRL_CMD_GETOPS: c_int = 6; pub const CTRL_CMD_NEWMCAST_GRP: c_int = 7; pub const CTRL_CMD_DELMCAST_GRP: c_int = 8; pub const CTRL_CMD_GETMCAST_GRP: c_int = 9; pub const CTRL_ATTR_UNSPEC: c_int = 0; pub const CTRL_ATTR_FAMILY_ID: c_int = 1; pub const CTRL_ATTR_FAMILY_NAME: c_int = 2; pub const CTRL_ATTR_VERSION: c_int = 3; pub const CTRL_ATTR_HDRSIZE: c_int = 4; pub const CTRL_ATTR_MAXATTR: c_int = 5; pub const CTRL_ATTR_OPS: c_int = 6; pub const CTRL_ATTR_MCAST_GROUPS: c_int = 7; pub const CTRL_ATTR_OP_UNSPEC: c_int = 0; pub const CTRL_ATTR_OP_ID: c_int = 1; pub const CTRL_ATTR_OP_FLAGS: c_int = 2; pub const CTRL_ATTR_MCAST_GRP_UNSPEC: c_int = 0; pub const CTRL_ATTR_MCAST_GRP_NAME: c_int = 1; pub const CTRL_ATTR_MCAST_GRP_ID: c_int = 2; // linux/if_packet.h pub const PACKET_HOST: c_uchar = 0; pub const PACKET_BROADCAST: c_uchar = 1; pub const PACKET_MULTICAST: c_uchar = 2; pub const PACKET_OTHERHOST: c_uchar = 3; pub const PACKET_OUTGOING: c_uchar = 4; pub const PACKET_LOOPBACK: c_uchar = 5; pub const PACKET_USER: c_uchar = 6; pub const PACKET_KERNEL: c_uchar = 7; pub const PACKET_ADD_MEMBERSHIP: c_int = 1; pub const PACKET_DROP_MEMBERSHIP: c_int = 2; pub const PACKET_RX_RING: c_int = 5; pub const PACKET_STATISTICS: c_int = 6; pub const PACKET_AUXDATA: c_int = 8; pub const PACKET_VERSION: c_int = 10; pub const PACKET_RESERVE: c_int = 12; pub const PACKET_TX_RING: c_int = 13; pub const PACKET_LOSS: c_int = 14; pub const PACKET_TIMESTAMP: c_int = 17; pub const PACKET_FANOUT: c_int = 18; pub const PACKET_QDISC_BYPASS: c_int = 20; pub const PACKET_FANOUT_HASH: c_uint = 0; pub const PACKET_FANOUT_LB: c_uint = 1; pub const PACKET_FANOUT_CPU: c_uint = 2; pub const PACKET_FANOUT_ROLLOVER: c_uint = 3; pub const PACKET_FANOUT_RND: c_uint = 4; pub const PACKET_FANOUT_QM: c_uint = 5; pub const PACKET_FANOUT_CBPF: c_uint = 6; pub const PACKET_FANOUT_EBPF: c_uint = 7; pub const PACKET_FANOUT_FLAG_ROLLOVER: c_uint = 0x1000; pub const PACKET_FANOUT_FLAG_UNIQUEID: c_uint = 0x2000; pub const PACKET_FANOUT_FLAG_DEFRAG: c_uint = 0x8000; pub const PACKET_MR_MULTICAST: c_int = 0; pub const PACKET_MR_PROMISC: c_int = 1; pub const PACKET_MR_ALLMULTI: c_int = 2; pub const TP_STATUS_KERNEL: __u32 = 0; pub const TP_STATUS_USER: __u32 = 1 << 0; pub const TP_STATUS_COPY: __u32 = 1 << 1; pub const TP_STATUS_LOSING: __u32 = 1 << 2; pub const TP_STATUS_CSUMNOTREADY: __u32 = 1 << 3; pub const TP_STATUS_VLAN_VALID: __u32 = 1 << 4; pub const TP_STATUS_BLK_TMO: __u32 = 1 << 5; pub const TP_STATUS_VLAN_TPID_VALID: __u32 = 1 << 6; pub const TP_STATUS_CSUM_VALID: __u32 = 1 << 7; pub const TP_STATUS_AVAILABLE: __u32 = 0; pub const TP_STATUS_SEND_REQUEST: __u32 = 1 << 0; pub const TP_STATUS_SENDING: __u32 = 1 << 1; pub const TP_STATUS_WRONG_FORMAT: __u32 = 1 << 2; pub const TP_STATUS_TS_SOFTWARE: __u32 = 1 << 29; pub const TP_STATUS_TS_SYS_HARDWARE: __u32 = 1 << 30; pub const TP_STATUS_TS_RAW_HARDWARE: __u32 = 1 << 31; pub const TP_FT_REQ_FILL_RXHASH: __u32 = 1; pub const TPACKET_ALIGNMENT: usize = 16; pub const TPACKET_HDRLEN: usize = ((size_of::() + TPACKET_ALIGNMENT - 1) & !(TPACKET_ALIGNMENT - 1)) + size_of::(); pub const TPACKET2_HDRLEN: usize = ((size_of::() + TPACKET_ALIGNMENT - 1) & !(TPACKET_ALIGNMENT - 1)) + size_of::(); pub const TPACKET3_HDRLEN: usize = ((size_of::() + TPACKET_ALIGNMENT - 1) & !(TPACKET_ALIGNMENT - 1)) + size_of::(); // linux/netfilter.h pub const NF_DROP: c_int = 0; pub const NF_ACCEPT: c_int = 1; pub const NF_STOLEN: c_int = 2; pub const NF_QUEUE: c_int = 3; pub const NF_REPEAT: c_int = 4; pub const NF_STOP: c_int = 5; pub const NF_MAX_VERDICT: c_int = NF_STOP; pub const NF_VERDICT_MASK: c_int = 0x000000ff; pub const NF_VERDICT_FLAG_QUEUE_BYPASS: c_int = 0x00008000; pub const NF_VERDICT_QMASK: c_int = 0xffff0000; pub const NF_VERDICT_QBITS: c_int = 16; pub const NF_VERDICT_BITS: c_int = 16; pub const NF_INET_PRE_ROUTING: c_int = 0; pub const NF_INET_LOCAL_IN: c_int = 1; pub const NF_INET_FORWARD: c_int = 2; pub const NF_INET_LOCAL_OUT: c_int = 3; pub const NF_INET_POST_ROUTING: c_int = 4; pub const NF_INET_NUMHOOKS: c_int = 5; pub const NF_INET_INGRESS: c_int = NF_INET_NUMHOOKS; pub const NF_NETDEV_INGRESS: c_int = 0; pub const NF_NETDEV_EGRESS: c_int = 1; pub const NF_NETDEV_NUMHOOKS: c_int = 2; // Some NFPROTO are not compatible with musl and are defined in submodules. pub const NFPROTO_UNSPEC: c_int = 0; pub const NFPROTO_INET: c_int = 1; pub const NFPROTO_IPV4: c_int = 2; pub const NFPROTO_ARP: c_int = 3; pub const NFPROTO_NETDEV: c_int = 5; pub const NFPROTO_BRIDGE: c_int = 7; pub const NFPROTO_IPV6: c_int = 10; pub const NFPROTO_DECNET: c_int = 12; pub const NFPROTO_NUMPROTO: c_int = 13; // linux/netfilter_arp.h pub const NF_ARP: c_int = 0; pub const NF_ARP_IN: c_int = 0; pub const NF_ARP_OUT: c_int = 1; pub const NF_ARP_FORWARD: c_int = 2; pub const NF_ARP_NUMHOOKS: c_int = 3; // linux/netfilter_bridge.h pub const NF_BR_PRE_ROUTING: c_int = 0; pub const NF_BR_LOCAL_IN: c_int = 1; pub const NF_BR_FORWARD: c_int = 2; pub const NF_BR_LOCAL_OUT: c_int = 3; pub const NF_BR_POST_ROUTING: c_int = 4; pub const NF_BR_BROUTING: c_int = 5; pub const NF_BR_NUMHOOKS: c_int = 6; pub const NF_BR_PRI_FIRST: c_int = crate::INT_MIN; pub const NF_BR_PRI_NAT_DST_BRIDGED: c_int = -300; pub const NF_BR_PRI_FILTER_BRIDGED: c_int = -200; pub const NF_BR_PRI_BRNF: c_int = 0; pub const NF_BR_PRI_NAT_DST_OTHER: c_int = 100; pub const NF_BR_PRI_FILTER_OTHER: c_int = 200; pub const NF_BR_PRI_NAT_SRC: c_int = 300; pub const NF_BR_PRI_LAST: c_int = crate::INT_MAX; // linux/netfilter_ipv4.h pub const NF_IP_PRE_ROUTING: c_int = 0; pub const NF_IP_LOCAL_IN: c_int = 1; pub const NF_IP_FORWARD: c_int = 2; pub const NF_IP_LOCAL_OUT: c_int = 3; pub const NF_IP_POST_ROUTING: c_int = 4; pub const NF_IP_NUMHOOKS: c_int = 5; pub const NF_IP_PRI_FIRST: c_int = crate::INT_MIN; pub const NF_IP_PRI_RAW_BEFORE_DEFRAG: c_int = -450; pub const NF_IP_PRI_CONNTRACK_DEFRAG: c_int = -400; pub const NF_IP_PRI_RAW: c_int = -300; pub const NF_IP_PRI_SELINUX_FIRST: c_int = -225; pub const NF_IP_PRI_CONNTRACK: c_int = -200; pub const NF_IP_PRI_MANGLE: c_int = -150; pub const NF_IP_PRI_NAT_DST: c_int = -100; pub const NF_IP_PRI_FILTER: c_int = 0; pub const NF_IP_PRI_SECURITY: c_int = 50; pub const NF_IP_PRI_NAT_SRC: c_int = 100; pub const NF_IP_PRI_SELINUX_LAST: c_int = 225; pub const NF_IP_PRI_CONNTRACK_HELPER: c_int = 300; pub const NF_IP_PRI_CONNTRACK_CONFIRM: c_int = crate::INT_MAX; pub const NF_IP_PRI_LAST: c_int = crate::INT_MAX; // linux/netfilter_ipv6.h pub const NF_IP6_PRE_ROUTING: c_int = 0; pub const NF_IP6_LOCAL_IN: c_int = 1; pub const NF_IP6_FORWARD: c_int = 2; pub const NF_IP6_LOCAL_OUT: c_int = 3; pub const NF_IP6_POST_ROUTING: c_int = 4; pub const NF_IP6_NUMHOOKS: c_int = 5; pub const NF_IP6_PRI_FIRST: c_int = crate::INT_MIN; pub const NF_IP6_PRI_RAW_BEFORE_DEFRAG: c_int = -450; pub const NF_IP6_PRI_CONNTRACK_DEFRAG: c_int = -400; pub const NF_IP6_PRI_RAW: c_int = -300; pub const NF_IP6_PRI_SELINUX_FIRST: c_int = -225; pub const NF_IP6_PRI_CONNTRACK: c_int = -200; pub const NF_IP6_PRI_MANGLE: c_int = -150; pub const NF_IP6_PRI_NAT_DST: c_int = -100; pub const NF_IP6_PRI_FILTER: c_int = 0; pub const NF_IP6_PRI_SECURITY: c_int = 50; pub const NF_IP6_PRI_NAT_SRC: c_int = 100; pub const NF_IP6_PRI_SELINUX_LAST: c_int = 225; pub const NF_IP6_PRI_CONNTRACK_HELPER: c_int = 300; pub const NF_IP6_PRI_LAST: c_int = crate::INT_MAX; // linux/netfilter_ipv6/ip6_tables.h pub const IP6T_SO_ORIGINAL_DST: c_int = 80; pub const SIOCADDRT: c_ulong = 0x0000890B; pub const SIOCDELRT: c_ulong = 0x0000890C; pub const SIOCGIFNAME: c_ulong = 0x00008910; pub const SIOCSIFLINK: c_ulong = 0x00008911; pub const SIOCGIFCONF: c_ulong = 0x00008912; pub const SIOCGIFFLAGS: c_ulong = 0x00008913; pub const SIOCSIFFLAGS: c_ulong = 0x00008914; pub const SIOCGIFADDR: c_ulong = 0x00008915; pub const SIOCSIFADDR: c_ulong = 0x00008916; pub const SIOCGIFDSTADDR: c_ulong = 0x00008917; pub const SIOCSIFDSTADDR: c_ulong = 0x00008918; pub const SIOCGIFBRDADDR: c_ulong = 0x00008919; pub const SIOCSIFBRDADDR: c_ulong = 0x0000891A; pub const SIOCGIFNETMASK: c_ulong = 0x0000891B; pub const SIOCSIFNETMASK: c_ulong = 0x0000891C; pub const SIOCGIFMETRIC: c_ulong = 0x0000891D; pub const SIOCSIFMETRIC: c_ulong = 0x0000891E; pub const SIOCGIFMEM: c_ulong = 0x0000891F; pub const SIOCSIFMEM: c_ulong = 0x00008920; pub const SIOCGIFMTU: c_ulong = 0x00008921; pub const SIOCSIFMTU: c_ulong = 0x00008922; pub const SIOCSIFNAME: c_ulong = 0x00008923; pub const SIOCSIFHWADDR: c_ulong = 0x00008924; pub const SIOCGIFENCAP: c_ulong = 0x00008925; pub const SIOCSIFENCAP: c_ulong = 0x00008926; pub const SIOCGIFHWADDR: c_ulong = 0x00008927; pub const SIOCGIFSLAVE: c_ulong = 0x00008929; pub const SIOCSIFSLAVE: c_ulong = 0x00008930; pub const SIOCADDMULTI: c_ulong = 0x00008931; pub const SIOCDELMULTI: c_ulong = 0x00008932; pub const SIOCGIFINDEX: c_ulong = 0x00008933; pub const SIOGIFINDEX: c_ulong = SIOCGIFINDEX; pub const SIOCSIFPFLAGS: c_ulong = 0x00008934; pub const SIOCGIFPFLAGS: c_ulong = 0x00008935; pub const SIOCDIFADDR: c_ulong = 0x00008936; pub const SIOCSIFHWBROADCAST: c_ulong = 0x00008937; pub const SIOCGIFCOUNT: c_ulong = 0x00008938; pub const SIOCGIFBR: c_ulong = 0x00008940; pub const SIOCSIFBR: c_ulong = 0x00008941; pub const SIOCGIFTXQLEN: c_ulong = 0x00008942; pub const SIOCSIFTXQLEN: c_ulong = 0x00008943; pub const SIOCETHTOOL: c_ulong = 0x00008946; pub const SIOCGMIIPHY: c_ulong = 0x00008947; pub const SIOCGMIIREG: c_ulong = 0x00008948; pub const SIOCSMIIREG: c_ulong = 0x00008949; pub const SIOCWANDEV: c_ulong = 0x0000894A; pub const SIOCOUTQNSD: c_ulong = 0x0000894B; pub const SIOCGSKNS: c_ulong = 0x0000894C; pub const SIOCDARP: c_ulong = 0x00008953; pub const SIOCGARP: c_ulong = 0x00008954; pub const SIOCSARP: c_ulong = 0x00008955; pub const SIOCDRARP: c_ulong = 0x00008960; pub const SIOCGRARP: c_ulong = 0x00008961; pub const SIOCSRARP: c_ulong = 0x00008962; pub const SIOCGIFMAP: c_ulong = 0x00008970; pub const SIOCSIFMAP: c_ulong = 0x00008971; pub const SIOCSHWTSTAMP: c_ulong = 0x000089b0; pub const SIOCGHWTSTAMP: c_ulong = 0x000089b1; // wireless.h pub const WIRELESS_EXT: c_ulong = 0x16; pub const SIOCSIWCOMMIT: c_ulong = 0x8B00; pub const SIOCGIWNAME: c_ulong = 0x8B01; pub const SIOCSIWNWID: c_ulong = 0x8B02; pub const SIOCGIWNWID: c_ulong = 0x8B03; pub const SIOCSIWFREQ: c_ulong = 0x8B04; pub const SIOCGIWFREQ: c_ulong = 0x8B05; pub const SIOCSIWMODE: c_ulong = 0x8B06; pub const SIOCGIWMODE: c_ulong = 0x8B07; pub const SIOCSIWSENS: c_ulong = 0x8B08; pub const SIOCGIWSENS: c_ulong = 0x8B09; pub const SIOCSIWRANGE: c_ulong = 0x8B0A; pub const SIOCGIWRANGE: c_ulong = 0x8B0B; pub const SIOCSIWPRIV: c_ulong = 0x8B0C; pub const SIOCGIWPRIV: c_ulong = 0x8B0D; pub const SIOCSIWSTATS: c_ulong = 0x8B0E; pub const SIOCGIWSTATS: c_ulong = 0x8B0F; pub const SIOCSIWSPY: c_ulong = 0x8B10; pub const SIOCGIWSPY: c_ulong = 0x8B11; pub const SIOCSIWTHRSPY: c_ulong = 0x8B12; pub const SIOCGIWTHRSPY: c_ulong = 0x8B13; pub const SIOCSIWAP: c_ulong = 0x8B14; pub const SIOCGIWAP: c_ulong = 0x8B15; pub const SIOCGIWAPLIST: c_ulong = 0x8B17; pub const SIOCSIWSCAN: c_ulong = 0x8B18; pub const SIOCGIWSCAN: c_ulong = 0x8B19; pub const SIOCSIWESSID: c_ulong = 0x8B1A; pub const SIOCGIWESSID: c_ulong = 0x8B1B; pub const SIOCSIWNICKN: c_ulong = 0x8B1C; pub const SIOCGIWNICKN: c_ulong = 0x8B1D; pub const SIOCSIWRATE: c_ulong = 0x8B20; pub const SIOCGIWRATE: c_ulong = 0x8B21; pub const SIOCSIWRTS: c_ulong = 0x8B22; pub const SIOCGIWRTS: c_ulong = 0x8B23; pub const SIOCSIWFRAG: c_ulong = 0x8B24; pub const SIOCGIWFRAG: c_ulong = 0x8B25; pub const SIOCSIWTXPOW: c_ulong = 0x8B26; pub const SIOCGIWTXPOW: c_ulong = 0x8B27; pub const SIOCSIWRETRY: c_ulong = 0x8B28; pub const SIOCGIWRETRY: c_ulong = 0x8B29; pub const SIOCSIWENCODE: c_ulong = 0x8B2A; pub const SIOCGIWENCODE: c_ulong = 0x8B2B; pub const SIOCSIWPOWER: c_ulong = 0x8B2C; pub const SIOCGIWPOWER: c_ulong = 0x8B2D; pub const SIOCSIWGENIE: c_ulong = 0x8B30; pub const SIOCGIWGENIE: c_ulong = 0x8B31; pub const SIOCSIWMLME: c_ulong = 0x8B16; pub const SIOCSIWAUTH: c_ulong = 0x8B32; pub const SIOCGIWAUTH: c_ulong = 0x8B33; pub const SIOCSIWENCODEEXT: c_ulong = 0x8B34; pub const SIOCGIWENCODEEXT: c_ulong = 0x8B35; pub const SIOCSIWPMKSA: c_ulong = 0x8B36; pub const SIOCIWFIRSTPRIV: c_ulong = 0x8BE0; pub const SIOCIWLASTPRIV: c_ulong = 0x8BFF; pub const SIOCIWFIRST: c_ulong = 0x8B00; pub const SIOCIWLAST: c_ulong = SIOCIWLASTPRIV; pub const IWEVTXDROP: c_ulong = 0x8C00; pub const IWEVQUAL: c_ulong = 0x8C01; pub const IWEVCUSTOM: c_ulong = 0x8C02; pub const IWEVREGISTERED: c_ulong = 0x8C03; pub const IWEVEXPIRED: c_ulong = 0x8C04; pub const IWEVGENIE: c_ulong = 0x8C05; pub const IWEVMICHAELMICFAILURE: c_ulong = 0x8C06; pub const IWEVASSOCREQIE: c_ulong = 0x8C07; pub const IWEVASSOCRESPIE: c_ulong = 0x8C08; pub const IWEVPMKIDCAND: c_ulong = 0x8C09; pub const IWEVFIRST: c_ulong = 0x8C00; pub const IW_PRIV_TYPE_MASK: c_ulong = 0x7000; pub const IW_PRIV_TYPE_NONE: c_ulong = 0x0000; pub const IW_PRIV_TYPE_BYTE: c_ulong = 0x1000; pub const IW_PRIV_TYPE_CHAR: c_ulong = 0x2000; pub const IW_PRIV_TYPE_INT: c_ulong = 0x4000; pub const IW_PRIV_TYPE_FLOAT: c_ulong = 0x5000; pub const IW_PRIV_TYPE_ADDR: c_ulong = 0x6000; pub const IW_PRIV_SIZE_FIXED: c_ulong = 0x0800; pub const IW_PRIV_SIZE_MASK: c_ulong = 0x07FF; pub const IW_MAX_FREQUENCIES: usize = 32; pub const IW_MAX_BITRATES: usize = 32; pub const IW_MAX_TXPOWER: usize = 8; pub const IW_MAX_SPY: usize = 8; pub const IW_MAX_AP: usize = 64; pub const IW_ESSID_MAX_SIZE: usize = 32; pub const IW_MODE_AUTO: usize = 0; pub const IW_MODE_ADHOC: usize = 1; pub const IW_MODE_INFRA: usize = 2; pub const IW_MODE_MASTER: usize = 3; pub const IW_MODE_REPEAT: usize = 4; pub const IW_MODE_SECOND: usize = 5; pub const IW_MODE_MONITOR: usize = 6; pub const IW_MODE_MESH: usize = 7; pub const IW_QUAL_QUAL_UPDATED: c_ulong = 0x01; pub const IW_QUAL_LEVEL_UPDATED: c_ulong = 0x02; pub const IW_QUAL_NOISE_UPDATED: c_ulong = 0x04; pub const IW_QUAL_ALL_UPDATED: c_ulong = 0x07; pub const IW_QUAL_DBM: c_ulong = 0x08; pub const IW_QUAL_QUAL_INVALID: c_ulong = 0x10; pub const IW_QUAL_LEVEL_INVALID: c_ulong = 0x20; pub const IW_QUAL_NOISE_INVALID: c_ulong = 0x40; pub const IW_QUAL_RCPI: c_ulong = 0x80; pub const IW_QUAL_ALL_INVALID: c_ulong = 0x70; pub const IW_FREQ_AUTO: c_ulong = 0x00; pub const IW_FREQ_FIXED: c_ulong = 0x01; pub const IW_MAX_ENCODING_SIZES: usize = 8; pub const IW_ENCODING_TOKEN_MAX: usize = 64; pub const IW_ENCODE_INDEX: c_ulong = 0x00FF; pub const IW_ENCODE_FLAGS: c_ulong = 0xFF00; pub const IW_ENCODE_MODE: c_ulong = 0xF000; pub const IW_ENCODE_DISABLED: c_ulong = 0x8000; pub const IW_ENCODE_ENABLED: c_ulong = 0x0000; pub const IW_ENCODE_RESTRICTED: c_ulong = 0x4000; pub const IW_ENCODE_OPEN: c_ulong = 0x2000; pub const IW_ENCODE_NOKEY: c_ulong = 0x0800; pub const IW_ENCODE_TEMP: c_ulong = 0x0400; pub const IW_POWER_ON: c_ulong = 0x0000; pub const IW_POWER_TYPE: c_ulong = 0xF000; pub const IW_POWER_PERIOD: c_ulong = 0x1000; pub const IW_POWER_TIMEOUT: c_ulong = 0x2000; pub const IW_POWER_MODE: c_ulong = 0x0F00; pub const IW_POWER_UNICAST_R: c_ulong = 0x0100; pub const IW_POWER_MULTICAST_R: c_ulong = 0x0200; pub const IW_POWER_ALL_R: c_ulong = 0x0300; pub const IW_POWER_FORCE_S: c_ulong = 0x0400; pub const IW_POWER_REPEATER: c_ulong = 0x0800; pub const IW_POWER_MODIFIER: c_ulong = 0x000F; pub const IW_POWER_MIN: c_ulong = 0x0001; pub const IW_POWER_MAX: c_ulong = 0x0002; pub const IW_POWER_RELATIVE: c_ulong = 0x0004; pub const IW_TXPOW_TYPE: c_ulong = 0x00FF; pub const IW_TXPOW_DBM: c_ulong = 0x0000; pub const IW_TXPOW_MWATT: c_ulong = 0x0001; pub const IW_TXPOW_RELATIVE: c_ulong = 0x0002; pub const IW_TXPOW_RANGE: c_ulong = 0x1000; pub const IW_RETRY_ON: c_ulong = 0x0000; pub const IW_RETRY_TYPE: c_ulong = 0xF000; pub const IW_RETRY_LIMIT: c_ulong = 0x1000; pub const IW_RETRY_LIFETIME: c_ulong = 0x2000; pub const IW_RETRY_MODIFIER: c_ulong = 0x00FF; pub const IW_RETRY_MIN: c_ulong = 0x0001; pub const IW_RETRY_MAX: c_ulong = 0x0002; pub const IW_RETRY_RELATIVE: c_ulong = 0x0004; pub const IW_RETRY_SHORT: c_ulong = 0x0010; pub const IW_RETRY_LONG: c_ulong = 0x0020; pub const IW_SCAN_DEFAULT: c_ulong = 0x0000; pub const IW_SCAN_ALL_ESSID: c_ulong = 0x0001; pub const IW_SCAN_THIS_ESSID: c_ulong = 0x0002; pub const IW_SCAN_ALL_FREQ: c_ulong = 0x0004; pub const IW_SCAN_THIS_FREQ: c_ulong = 0x0008; pub const IW_SCAN_ALL_MODE: c_ulong = 0x0010; pub const IW_SCAN_THIS_MODE: c_ulong = 0x0020; pub const IW_SCAN_ALL_RATE: c_ulong = 0x0040; pub const IW_SCAN_THIS_RATE: c_ulong = 0x0080; pub const IW_SCAN_TYPE_ACTIVE: usize = 0; pub const IW_SCAN_TYPE_PASSIVE: usize = 1; pub const IW_SCAN_MAX_DATA: usize = 4096; pub const IW_SCAN_CAPA_NONE: c_ulong = 0x00; pub const IW_SCAN_CAPA_ESSID: c_ulong = 0x01; pub const IW_SCAN_CAPA_BSSID: c_ulong = 0x02; pub const IW_SCAN_CAPA_CHANNEL: c_ulong = 0x04; pub const IW_SCAN_CAPA_MODE: c_ulong = 0x08; pub const IW_SCAN_CAPA_RATE: c_ulong = 0x10; pub const IW_SCAN_CAPA_TYPE: c_ulong = 0x20; pub const IW_SCAN_CAPA_TIME: c_ulong = 0x40; pub const IW_CUSTOM_MAX: c_ulong = 256; pub const IW_GENERIC_IE_MAX: c_ulong = 1024; pub const IW_MLME_DEAUTH: c_ulong = 0; pub const IW_MLME_DISASSOC: c_ulong = 1; pub const IW_MLME_AUTH: c_ulong = 2; pub const IW_MLME_ASSOC: c_ulong = 3; pub const IW_AUTH_INDEX: c_ulong = 0x0FFF; pub const IW_AUTH_FLAGS: c_ulong = 0xF000; pub const IW_AUTH_WPA_VERSION: usize = 0; pub const IW_AUTH_CIPHER_PAIRWISE: usize = 1; pub const IW_AUTH_CIPHER_GROUP: usize = 2; pub const IW_AUTH_KEY_MGMT: usize = 3; pub const IW_AUTH_TKIP_COUNTERMEASURES: usize = 4; pub const IW_AUTH_DROP_UNENCRYPTED: usize = 5; pub const IW_AUTH_80211_AUTH_ALG: usize = 6; pub const IW_AUTH_WPA_ENABLED: usize = 7; pub const IW_AUTH_RX_UNENCRYPTED_EAPOL: usize = 8; pub const IW_AUTH_ROAMING_CONTROL: usize = 9; pub const IW_AUTH_PRIVACY_INVOKED: usize = 10; pub const IW_AUTH_CIPHER_GROUP_MGMT: usize = 11; pub const IW_AUTH_MFP: usize = 12; pub const IW_AUTH_WPA_VERSION_DISABLED: c_ulong = 0x00000001; pub const IW_AUTH_WPA_VERSION_WPA: c_ulong = 0x00000002; pub const IW_AUTH_WPA_VERSION_WPA2: c_ulong = 0x00000004; pub const IW_AUTH_CIPHER_NONE: c_ulong = 0x00000001; pub const IW_AUTH_CIPHER_WEP40: c_ulong = 0x00000002; pub const IW_AUTH_CIPHER_TKIP: c_ulong = 0x00000004; pub const IW_AUTH_CIPHER_CCMP: c_ulong = 0x00000008; pub const IW_AUTH_CIPHER_WEP104: c_ulong = 0x00000010; pub const IW_AUTH_CIPHER_AES_CMAC: c_ulong = 0x00000020; pub const IW_AUTH_KEY_MGMT_802_1X: usize = 1; pub const IW_AUTH_KEY_MGMT_PSK: usize = 2; pub const IW_AUTH_ALG_OPEN_SYSTEM: c_ulong = 0x00000001; pub const IW_AUTH_ALG_SHARED_KEY: c_ulong = 0x00000002; pub const IW_AUTH_ALG_LEAP: c_ulong = 0x00000004; pub const IW_AUTH_ROAMING_ENABLE: usize = 0; pub const IW_AUTH_ROAMING_DISABLE: usize = 1; pub const IW_AUTH_MFP_DISABLED: usize = 0; pub const IW_AUTH_MFP_OPTIONAL: usize = 1; pub const IW_AUTH_MFP_REQUIRED: usize = 2; pub const IW_ENCODE_SEQ_MAX_SIZE: usize = 8; pub const IW_ENCODE_ALG_NONE: usize = 0; pub const IW_ENCODE_ALG_WEP: usize = 1; pub const IW_ENCODE_ALG_TKIP: usize = 2; pub const IW_ENCODE_ALG_CCMP: usize = 3; pub const IW_ENCODE_ALG_PMK: usize = 4; pub const IW_ENCODE_ALG_AES_CMAC: usize = 5; pub const IW_ENCODE_EXT_TX_SEQ_VALID: c_ulong = 0x00000001; pub const IW_ENCODE_EXT_RX_SEQ_VALID: c_ulong = 0x00000002; pub const IW_ENCODE_EXT_GROUP_KEY: c_ulong = 0x00000004; pub const IW_ENCODE_EXT_SET_TX_KEY: c_ulong = 0x00000008; pub const IW_MICFAILURE_KEY_ID: c_ulong = 0x00000003; pub const IW_MICFAILURE_GROUP: c_ulong = 0x00000004; pub const IW_MICFAILURE_PAIRWISE: c_ulong = 0x00000008; pub const IW_MICFAILURE_STAKEY: c_ulong = 0x00000010; pub const IW_MICFAILURE_COUNT: c_ulong = 0x00000060; pub const IW_ENC_CAPA_WPA: c_ulong = 0x00000001; pub const IW_ENC_CAPA_WPA2: c_ulong = 0x00000002; pub const IW_ENC_CAPA_CIPHER_TKIP: c_ulong = 0x00000004; pub const IW_ENC_CAPA_CIPHER_CCMP: c_ulong = 0x00000008; pub const IW_ENC_CAPA_4WAY_HANDSHAKE: c_ulong = 0x00000010; pub const IW_EVENT_CAPA_K_0: c_ulong = 0x4000050; // IW_EVENT_CAPA_MASK(0x8B04) | IW_EVENT_CAPA_MASK(0x8B06) | IW_EVENT_CAPA_MASK(0x8B1A); pub const IW_EVENT_CAPA_K_1: c_ulong = 0x400; // W_EVENT_CAPA_MASK(0x8B2A); pub const IW_PMKSA_ADD: usize = 1; pub const IW_PMKSA_REMOVE: usize = 2; pub const IW_PMKSA_FLUSH: usize = 3; pub const IW_PMKID_LEN: usize = 16; pub const IW_PMKID_CAND_PREAUTH: c_ulong = 0x00000001; pub const IW_EV_LCP_PK_LEN: usize = 4; pub const IW_EV_CHAR_PK_LEN: usize = 20; // IW_EV_LCP_PK_LEN + crate::IFNAMSIZ; pub const IW_EV_UINT_PK_LEN: usize = 8; // IW_EV_LCP_PK_LEN + size_of::(); pub const IW_EV_FREQ_PK_LEN: usize = 12; // IW_EV_LCP_PK_LEN + size_of::(); pub const IW_EV_PARAM_PK_LEN: usize = 12; // IW_EV_LCP_PK_LEN + size_of::(); pub const IW_EV_ADDR_PK_LEN: usize = 20; // IW_EV_LCP_PK_LEN + size_of::(); pub const IW_EV_QUAL_PK_LEN: usize = 8; // IW_EV_LCP_PK_LEN + size_of::(); pub const IW_EV_POINT_PK_LEN: usize = 8; // IW_EV_LCP_PK_LEN + 4; pub const IPTOS_TOS_MASK: u8 = 0x1E; pub const IPTOS_PREC_MASK: u8 = 0xE0; pub const IPTOS_ECN_NOT_ECT: u8 = 0x00; pub const RTF_UP: c_ushort = 0x0001; pub const RTF_GATEWAY: c_ushort = 0x0002; pub const RTF_HOST: c_ushort = 0x0004; pub const RTF_REINSTATE: c_ushort = 0x0008; pub const RTF_DYNAMIC: c_ushort = 0x0010; pub const RTF_MODIFIED: c_ushort = 0x0020; pub const RTF_MTU: c_ushort = 0x0040; pub const RTF_MSS: c_ushort = RTF_MTU; pub const RTF_WINDOW: c_ushort = 0x0080; pub const RTF_IRTT: c_ushort = 0x0100; pub const RTF_REJECT: c_ushort = 0x0200; pub const RTF_STATIC: c_ushort = 0x0400; pub const RTF_XRESOLVE: c_ushort = 0x0800; pub const RTF_NOFORWARD: c_ushort = 0x1000; pub const RTF_THROW: c_ushort = 0x2000; pub const RTF_NOPMTUDISC: c_ushort = 0x4000; pub const RTF_DEFAULT: u32 = 0x00010000; pub const RTF_ALLONLINK: u32 = 0x00020000; pub const RTF_ADDRCONF: u32 = 0x00040000; pub const RTF_LINKRT: u32 = 0x00100000; pub const RTF_NONEXTHOP: u32 = 0x00200000; pub const RTF_CACHE: u32 = 0x01000000; pub const RTF_FLOW: u32 = 0x02000000; pub const RTF_POLICY: u32 = 0x04000000; pub const RTCF_VALVE: u32 = 0x00200000; pub const RTCF_MASQ: u32 = 0x00400000; pub const RTCF_NAT: u32 = 0x00800000; pub const RTCF_DOREDIRECT: u32 = 0x01000000; pub const RTCF_LOG: u32 = 0x02000000; pub const RTCF_DIRECTSRC: u32 = 0x04000000; pub const RTF_LOCAL: u32 = 0x80000000; pub const RTF_INTERFACE: u32 = 0x40000000; pub const RTF_MULTICAST: u32 = 0x20000000; pub const RTF_BROADCAST: u32 = 0x10000000; pub const RTF_NAT: u32 = 0x08000000; pub const RTF_ADDRCLASSMASK: u32 = 0xF8000000; pub const RT_CLASS_UNSPEC: u8 = 0; pub const RT_CLASS_DEFAULT: u8 = 253; pub const RT_CLASS_MAIN: u8 = 254; pub const RT_CLASS_LOCAL: u8 = 255; pub const RT_CLASS_MAX: u8 = 255; // linux/neighbor.h pub const NUD_NONE: u16 = 0x00; pub const NUD_INCOMPLETE: u16 = 0x01; pub const NUD_REACHABLE: u16 = 0x02; pub const NUD_STALE: u16 = 0x04; pub const NUD_DELAY: u16 = 0x08; pub const NUD_PROBE: u16 = 0x10; pub const NUD_FAILED: u16 = 0x20; pub const NUD_NOARP: u16 = 0x40; pub const NUD_PERMANENT: u16 = 0x80; pub const NTF_USE: u8 = 0x01; pub const NTF_SELF: u8 = 0x02; pub const NTF_MASTER: u8 = 0x04; pub const NTF_PROXY: u8 = 0x08; pub const NTF_ROUTER: u8 = 0x80; pub const NDA_UNSPEC: c_ushort = 0; pub const NDA_DST: c_ushort = 1; pub const NDA_LLADDR: c_ushort = 2; pub const NDA_CACHEINFO: c_ushort = 3; pub const NDA_PROBES: c_ushort = 4; pub const NDA_VLAN: c_ushort = 5; pub const NDA_PORT: c_ushort = 6; pub const NDA_VNI: c_ushort = 7; pub const NDA_IFINDEX: c_ushort = 8; // linux/netlink.h pub const NLA_ALIGNTO: c_int = 4; pub const NETLINK_ROUTE: c_int = 0; pub const NETLINK_UNUSED: c_int = 1; pub const NETLINK_USERSOCK: c_int = 2; pub const NETLINK_FIREWALL: c_int = 3; pub const NETLINK_SOCK_DIAG: c_int = 4; pub const NETLINK_NFLOG: c_int = 5; pub const NETLINK_XFRM: c_int = 6; pub const NETLINK_SELINUX: c_int = 7; pub const NETLINK_ISCSI: c_int = 8; pub const NETLINK_AUDIT: c_int = 9; pub const NETLINK_FIB_LOOKUP: c_int = 10; pub const NETLINK_CONNECTOR: c_int = 11; pub const NETLINK_NETFILTER: c_int = 12; pub const NETLINK_IP6_FW: c_int = 13; pub const NETLINK_DNRTMSG: c_int = 14; pub const NETLINK_KOBJECT_UEVENT: c_int = 15; pub const NETLINK_GENERIC: c_int = 16; pub const NETLINK_SCSITRANSPORT: c_int = 18; pub const NETLINK_ECRYPTFS: c_int = 19; pub const NETLINK_RDMA: c_int = 20; pub const NETLINK_CRYPTO: c_int = 21; pub const NETLINK_INET_DIAG: c_int = NETLINK_SOCK_DIAG; pub const NLM_F_REQUEST: c_int = 1; pub const NLM_F_MULTI: c_int = 2; pub const NLM_F_ACK: c_int = 4; pub const NLM_F_ECHO: c_int = 8; pub const NLM_F_DUMP_INTR: c_int = 16; pub const NLM_F_DUMP_FILTERED: c_int = 32; pub const NLM_F_ROOT: c_int = 0x100; pub const NLM_F_MATCH: c_int = 0x200; pub const NLM_F_ATOMIC: c_int = 0x400; pub const NLM_F_DUMP: c_int = NLM_F_ROOT | NLM_F_MATCH; pub const NLM_F_REPLACE: c_int = 0x100; pub const NLM_F_EXCL: c_int = 0x200; pub const NLM_F_CREATE: c_int = 0x400; pub const NLM_F_APPEND: c_int = 0x800; pub const NLM_F_NONREC: c_int = 0x100; pub const NLM_F_BULK: c_int = 0x200; pub const NLM_F_CAPPED: c_int = 0x100; pub const NLM_F_ACK_TLVS: c_int = 0x200; pub const NETLINK_ADD_MEMBERSHIP: c_int = 1; pub const NETLINK_DROP_MEMBERSHIP: c_int = 2; pub const NETLINK_PKTINFO: c_int = 3; pub const NETLINK_BROADCAST_ERROR: c_int = 4; pub const NETLINK_NO_ENOBUFS: c_int = 5; pub const NETLINK_RX_RING: c_int = 6; pub const NETLINK_TX_RING: c_int = 7; pub const NETLINK_LISTEN_ALL_NSID: c_int = 8; pub const NETLINK_LIST_MEMBERSHIPS: c_int = 9; pub const NETLINK_CAP_ACK: c_int = 10; pub const NETLINK_EXT_ACK: c_int = 11; pub const NETLINK_GET_STRICT_CHK: c_int = 12; pub const NLA_F_NESTED: c_int = 1 << 15; pub const NLA_F_NET_BYTEORDER: c_int = 1 << 14; pub const NLA_TYPE_MASK: c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER); // linux/rtnetlink.h pub const TCA_UNSPEC: c_ushort = 0; pub const TCA_KIND: c_ushort = 1; pub const TCA_OPTIONS: c_ushort = 2; pub const TCA_STATS: c_ushort = 3; pub const TCA_XSTATS: c_ushort = 4; pub const TCA_RATE: c_ushort = 5; pub const TCA_FCNT: c_ushort = 6; pub const TCA_STATS2: c_ushort = 7; pub const TCA_STAB: c_ushort = 8; pub const RTM_NEWLINK: u16 = 16; pub const RTM_DELLINK: u16 = 17; pub const RTM_GETLINK: u16 = 18; pub const RTM_SETLINK: u16 = 19; pub const RTM_NEWADDR: u16 = 20; pub const RTM_DELADDR: u16 = 21; pub const RTM_GETADDR: u16 = 22; pub const RTM_NEWROUTE: u16 = 24; pub const RTM_DELROUTE: u16 = 25; pub const RTM_GETROUTE: u16 = 26; pub const RTM_NEWNEIGH: u16 = 28; pub const RTM_DELNEIGH: u16 = 29; pub const RTM_GETNEIGH: u16 = 30; pub const RTM_NEWRULE: u16 = 32; pub const RTM_DELRULE: u16 = 33; pub const RTM_GETRULE: u16 = 34; pub const RTM_NEWQDISC: u16 = 36; pub const RTM_DELQDISC: u16 = 37; pub const RTM_GETQDISC: u16 = 38; pub const RTM_NEWTCLASS: u16 = 40; pub const RTM_DELTCLASS: u16 = 41; pub const RTM_GETTCLASS: u16 = 42; pub const RTM_NEWTFILTER: u16 = 44; pub const RTM_DELTFILTER: u16 = 45; pub const RTM_GETTFILTER: u16 = 46; pub const RTM_NEWACTION: u16 = 48; pub const RTM_DELACTION: u16 = 49; pub const RTM_GETACTION: u16 = 50; pub const RTM_NEWPREFIX: u16 = 52; pub const RTM_GETMULTICAST: u16 = 58; pub const RTM_GETANYCAST: u16 = 62; pub const RTM_NEWNEIGHTBL: u16 = 64; pub const RTM_GETNEIGHTBL: u16 = 66; pub const RTM_SETNEIGHTBL: u16 = 67; pub const RTM_NEWNDUSEROPT: u16 = 68; pub const RTM_NEWADDRLABEL: u16 = 72; pub const RTM_DELADDRLABEL: u16 = 73; pub const RTM_GETADDRLABEL: u16 = 74; pub const RTM_GETDCB: u16 = 78; pub const RTM_SETDCB: u16 = 79; pub const RTM_NEWNETCONF: u16 = 80; pub const RTM_GETNETCONF: u16 = 82; pub const RTM_NEWMDB: u16 = 84; pub const RTM_DELMDB: u16 = 85; pub const RTM_GETMDB: u16 = 86; pub const RTM_NEWNSID: u16 = 88; pub const RTM_DELNSID: u16 = 89; pub const RTM_GETNSID: u16 = 90; pub const RTM_F_NOTIFY: c_uint = 0x100; pub const RTM_F_CLONED: c_uint = 0x200; pub const RTM_F_EQUALIZE: c_uint = 0x400; pub const RTM_F_PREFIX: c_uint = 0x800; pub const RTA_UNSPEC: c_ushort = 0; pub const RTA_DST: c_ushort = 1; pub const RTA_SRC: c_ushort = 2; pub const RTA_IIF: c_ushort = 3; pub const RTA_OIF: c_ushort = 4; pub const RTA_GATEWAY: c_ushort = 5; pub const RTA_PRIORITY: c_ushort = 6; pub const RTA_PREFSRC: c_ushort = 7; pub const RTA_METRICS: c_ushort = 8; pub const RTA_MULTIPATH: c_ushort = 9; pub const RTA_PROTOINFO: c_ushort = 10; // No longer used pub const RTA_FLOW: c_ushort = 11; pub const RTA_CACHEINFO: c_ushort = 12; pub const RTA_SESSION: c_ushort = 13; // No longer used pub const RTA_MP_ALGO: c_ushort = 14; // No longer used pub const RTA_TABLE: c_ushort = 15; pub const RTA_MARK: c_ushort = 16; pub const RTA_MFC_STATS: c_ushort = 17; pub const RTN_UNSPEC: c_uchar = 0; pub const RTN_UNICAST: c_uchar = 1; pub const RTN_LOCAL: c_uchar = 2; pub const RTN_BROADCAST: c_uchar = 3; pub const RTN_ANYCAST: c_uchar = 4; pub const RTN_MULTICAST: c_uchar = 5; pub const RTN_BLACKHOLE: c_uchar = 6; pub const RTN_UNREACHABLE: c_uchar = 7; pub const RTN_PROHIBIT: c_uchar = 8; pub const RTN_THROW: c_uchar = 9; pub const RTN_NAT: c_uchar = 10; pub const RTN_XRESOLVE: c_uchar = 11; pub const RTPROT_UNSPEC: c_uchar = 0; pub const RTPROT_REDIRECT: c_uchar = 1; pub const RTPROT_KERNEL: c_uchar = 2; pub const RTPROT_BOOT: c_uchar = 3; pub const RTPROT_STATIC: c_uchar = 4; pub const RT_SCOPE_UNIVERSE: c_uchar = 0; pub const RT_SCOPE_SITE: c_uchar = 200; pub const RT_SCOPE_LINK: c_uchar = 253; pub const RT_SCOPE_HOST: c_uchar = 254; pub const RT_SCOPE_NOWHERE: c_uchar = 255; pub const RT_TABLE_UNSPEC: c_uchar = 0; pub const RT_TABLE_COMPAT: c_uchar = 252; pub const RT_TABLE_DEFAULT: c_uchar = 253; pub const RT_TABLE_MAIN: c_uchar = 254; pub const RT_TABLE_LOCAL: c_uchar = 255; pub const RTMSG_OVERRUN: u32 = crate::NLMSG_OVERRUN as u32; pub const RTMSG_NEWDEVICE: u32 = 0x11; pub const RTMSG_DELDEVICE: u32 = 0x12; pub const RTMSG_NEWROUTE: u32 = 0x21; pub const RTMSG_DELROUTE: u32 = 0x22; pub const RTMSG_NEWRULE: u32 = 0x31; pub const RTMSG_DELRULE: u32 = 0x32; pub const RTMSG_CONTROL: u32 = 0x40; pub const RTMSG_AR_FAILED: u32 = 0x51; pub const MAX_ADDR_LEN: usize = 7; pub const ARPD_UPDATE: c_ushort = 0x01; pub const ARPD_LOOKUP: c_ushort = 0x02; pub const ARPD_FLUSH: c_ushort = 0x03; pub const ATF_MAGIC: c_int = 0x80; pub const RTEXT_FILTER_VF: c_int = 1 << 0; pub const RTEXT_FILTER_BRVLAN: c_int = 1 << 1; pub const RTEXT_FILTER_BRVLAN_COMPRESSED: c_int = 1 << 2; pub const RTEXT_FILTER_SKIP_STATS: c_int = 1 << 3; pub const RTEXT_FILTER_MRP: c_int = 1 << 4; pub const RTEXT_FILTER_CFM_CONFIG: c_int = 1 << 5; pub const RTEXT_FILTER_CFM_STATUS: c_int = 1 << 6; // userspace compat definitions for RTNLGRP_* pub const RTMGRP_LINK: c_int = 0x00001; pub const RTMGRP_NOTIFY: c_int = 0x00002; pub const RTMGRP_NEIGH: c_int = 0x00004; pub const RTMGRP_TC: c_int = 0x00008; pub const RTMGRP_IPV4_IFADDR: c_int = 0x00010; pub const RTMGRP_IPV4_MROUTE: c_int = 0x00020; pub const RTMGRP_IPV4_ROUTE: c_int = 0x00040; pub const RTMGRP_IPV4_RULE: c_int = 0x00080; pub const RTMGRP_IPV6_IFADDR: c_int = 0x00100; pub const RTMGRP_IPV6_MROUTE: c_int = 0x00200; pub const RTMGRP_IPV6_ROUTE: c_int = 0x00400; pub const RTMGRP_IPV6_IFINFO: c_int = 0x00800; pub const RTMGRP_DECnet_IFADDR: c_int = 0x01000; pub const RTMGRP_DECnet_ROUTE: c_int = 0x04000; pub const RTMGRP_IPV6_PREFIX: c_int = 0x20000; // enum rtnetlink_groups pub const RTNLGRP_NONE: c_uint = 0x00; pub const RTNLGRP_LINK: c_uint = 0x01; pub const RTNLGRP_NOTIFY: c_uint = 0x02; pub const RTNLGRP_NEIGH: c_uint = 0x03; pub const RTNLGRP_TC: c_uint = 0x04; pub const RTNLGRP_IPV4_IFADDR: c_uint = 0x05; pub const RTNLGRP_IPV4_MROUTE: c_uint = 0x06; pub const RTNLGRP_IPV4_ROUTE: c_uint = 0x07; pub const RTNLGRP_IPV4_RULE: c_uint = 0x08; pub const RTNLGRP_IPV6_IFADDR: c_uint = 0x09; pub const RTNLGRP_IPV6_MROUTE: c_uint = 0x0a; pub const RTNLGRP_IPV6_ROUTE: c_uint = 0x0b; pub const RTNLGRP_IPV6_IFINFO: c_uint = 0x0c; pub const RTNLGRP_DECnet_IFADDR: c_uint = 0x0d; pub const RTNLGRP_NOP2: c_uint = 0x0e; pub const RTNLGRP_DECnet_ROUTE: c_uint = 0x0f; pub const RTNLGRP_DECnet_RULE: c_uint = 0x10; pub const RTNLGRP_NOP4: c_uint = 0x11; pub const RTNLGRP_IPV6_PREFIX: c_uint = 0x12; pub const RTNLGRP_IPV6_RULE: c_uint = 0x13; pub const RTNLGRP_ND_USEROPT: c_uint = 0x14; pub const RTNLGRP_PHONET_IFADDR: c_uint = 0x15; pub const RTNLGRP_PHONET_ROUTE: c_uint = 0x16; pub const RTNLGRP_DCB: c_uint = 0x17; pub const RTNLGRP_IPV4_NETCONF: c_uint = 0x18; pub const RTNLGRP_IPV6_NETCONF: c_uint = 0x19; pub const RTNLGRP_MDB: c_uint = 0x1a; pub const RTNLGRP_MPLS_ROUTE: c_uint = 0x1b; pub const RTNLGRP_NSID: c_uint = 0x1c; pub const RTNLGRP_MPLS_NETCONF: c_uint = 0x1d; pub const RTNLGRP_IPV4_MROUTE_R: c_uint = 0x1e; pub const RTNLGRP_IPV6_MROUTE_R: c_uint = 0x1f; pub const RTNLGRP_NEXTHOP: c_uint = 0x20; pub const RTNLGRP_BRVLAN: c_uint = 0x21; pub const RTNLGRP_MCTP_IFADDR: c_uint = 0x22; pub const RTNLGRP_TUNNEL: c_uint = 0x23; pub const RTNLGRP_STATS: c_uint = 0x24; // linux/module.h pub const MODULE_INIT_IGNORE_MODVERSIONS: c_uint = 0x0001; pub const MODULE_INIT_IGNORE_VERMAGIC: c_uint = 0x0002; // linux/net_tstamp.h pub const SOF_TIMESTAMPING_TX_HARDWARE: c_uint = 1 << 0; pub const SOF_TIMESTAMPING_TX_SOFTWARE: c_uint = 1 << 1; pub const SOF_TIMESTAMPING_RX_HARDWARE: c_uint = 1 << 2; pub const SOF_TIMESTAMPING_RX_SOFTWARE: c_uint = 1 << 3; pub const SOF_TIMESTAMPING_SOFTWARE: c_uint = 1 << 4; pub const SOF_TIMESTAMPING_SYS_HARDWARE: c_uint = 1 << 5; pub const SOF_TIMESTAMPING_RAW_HARDWARE: c_uint = 1 << 6; pub const SOF_TIMESTAMPING_OPT_ID: c_uint = 1 << 7; pub const SOF_TIMESTAMPING_TX_SCHED: c_uint = 1 << 8; pub const SOF_TIMESTAMPING_TX_ACK: c_uint = 1 << 9; pub const SOF_TIMESTAMPING_OPT_CMSG: c_uint = 1 << 10; pub const SOF_TIMESTAMPING_OPT_TSONLY: c_uint = 1 << 11; pub const SOF_TIMESTAMPING_OPT_STATS: c_uint = 1 << 12; pub const SOF_TIMESTAMPING_OPT_PKTINFO: c_uint = 1 << 13; pub const SOF_TIMESTAMPING_OPT_TX_SWHW: c_uint = 1 << 14; pub const SOF_TIMESTAMPING_BIND_PHC: c_uint = 1 << 15; pub const SOF_TIMESTAMPING_OPT_ID_TCP: c_uint = 1 << 16; pub const SOF_TIMESTAMPING_OPT_RX_FILTER: c_uint = 1 << 17; pub const SOF_TXTIME_DEADLINE_MODE: u32 = 1 << 0; pub const SOF_TXTIME_REPORT_ERRORS: u32 = 1 << 1; pub const HWTSTAMP_TX_OFF: c_uint = 0; pub const HWTSTAMP_TX_ON: c_uint = 1; pub const HWTSTAMP_TX_ONESTEP_SYNC: c_uint = 2; pub const HWTSTAMP_TX_ONESTEP_P2P: c_uint = 3; pub const HWTSTAMP_FILTER_NONE: c_uint = 0; pub const HWTSTAMP_FILTER_ALL: c_uint = 1; pub const HWTSTAMP_FILTER_SOME: c_uint = 2; pub const HWTSTAMP_FILTER_PTP_V1_L4_EVENT: c_uint = 3; pub const HWTSTAMP_FILTER_PTP_V1_L4_SYNC: c_uint = 4; pub const HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: c_uint = 5; pub const HWTSTAMP_FILTER_PTP_V2_L4_EVENT: c_uint = 6; pub const HWTSTAMP_FILTER_PTP_V2_L4_SYNC: c_uint = 7; pub const HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: c_uint = 8; pub const HWTSTAMP_FILTER_PTP_V2_L2_EVENT: c_uint = 9; pub const HWTSTAMP_FILTER_PTP_V2_L2_SYNC: c_uint = 10; pub const HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: c_uint = 11; pub const HWTSTAMP_FILTER_PTP_V2_EVENT: c_uint = 12; pub const HWTSTAMP_FILTER_PTP_V2_SYNC: c_uint = 13; pub const HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: c_uint = 14; pub const HWTSTAMP_FILTER_NTP_ALL: c_uint = 15; // linux/ptp_clock.h pub const PTP_MAX_SAMPLES: c_uint = 25; // Maximum allowed offset measurement samples. const PTP_CLK_MAGIC: u32 = b'=' as u32; pub const PTP_CLOCK_GETCAPS: c_uint = _IOR::(PTP_CLK_MAGIC, 1); pub const PTP_EXTTS_REQUEST: c_uint = _IOW::(PTP_CLK_MAGIC, 2); pub const PTP_PEROUT_REQUEST: c_uint = _IOW::(PTP_CLK_MAGIC, 3); pub const PTP_ENABLE_PPS: c_uint = _IOW::(PTP_CLK_MAGIC, 4); pub const PTP_SYS_OFFSET: c_uint = _IOW::(PTP_CLK_MAGIC, 5); pub const PTP_PIN_GETFUNC: c_uint = _IOWR::(PTP_CLK_MAGIC, 6); pub const PTP_PIN_SETFUNC: c_uint = _IOW::(PTP_CLK_MAGIC, 7); pub const PTP_SYS_OFFSET_PRECISE: c_uint = _IOWR::(PTP_CLK_MAGIC, 8); pub const PTP_SYS_OFFSET_EXTENDED: c_uint = _IOWR::(PTP_CLK_MAGIC, 9); pub const PTP_CLOCK_GETCAPS2: c_uint = _IOR::(PTP_CLK_MAGIC, 10); pub const PTP_EXTTS_REQUEST2: c_uint = _IOW::(PTP_CLK_MAGIC, 11); pub const PTP_PEROUT_REQUEST2: c_uint = _IOW::(PTP_CLK_MAGIC, 12); pub const PTP_ENABLE_PPS2: c_uint = _IOW::(PTP_CLK_MAGIC, 13); pub const PTP_SYS_OFFSET2: c_uint = _IOW::(PTP_CLK_MAGIC, 14); pub const PTP_PIN_GETFUNC2: c_uint = _IOWR::(PTP_CLK_MAGIC, 15); pub const PTP_PIN_SETFUNC2: c_uint = _IOW::(PTP_CLK_MAGIC, 16); pub const PTP_SYS_OFFSET_PRECISE2: c_uint = _IOWR::(PTP_CLK_MAGIC, 17); pub const PTP_SYS_OFFSET_EXTENDED2: c_uint = _IOWR::(PTP_CLK_MAGIC, 18); // enum ptp_pin_function pub const PTP_PF_NONE: c_uint = 0; pub const PTP_PF_EXTTS: c_uint = 1; pub const PTP_PF_PEROUT: c_uint = 2; pub const PTP_PF_PHYSYNC: c_uint = 3; // linux/tls.h pub const TLS_TX: c_int = 1; pub const TLS_RX: c_int = 2; pub const TLS_TX_ZEROCOPY_RO: c_int = 3; pub const TLS_RX_EXPECT_NO_PAD: c_int = 4; pub const TLS_1_2_VERSION_MAJOR: __u8 = 0x3; pub const TLS_1_2_VERSION_MINOR: __u8 = 0x3; pub const TLS_1_2_VERSION: __u16 = ((TLS_1_2_VERSION_MAJOR as __u16) << 8) | (TLS_1_2_VERSION_MINOR as __u16); pub const TLS_1_3_VERSION_MAJOR: __u8 = 0x3; pub const TLS_1_3_VERSION_MINOR: __u8 = 0x4; pub const TLS_1_3_VERSION: __u16 = ((TLS_1_3_VERSION_MAJOR as __u16) << 8) | (TLS_1_3_VERSION_MINOR as __u16); pub const TLS_CIPHER_AES_GCM_128: __u16 = 51; pub const TLS_CIPHER_AES_GCM_128_IV_SIZE: usize = 8; pub const TLS_CIPHER_AES_GCM_128_KEY_SIZE: usize = 16; pub const TLS_CIPHER_AES_GCM_128_SALT_SIZE: usize = 4; pub const TLS_CIPHER_AES_GCM_128_TAG_SIZE: usize = 16; pub const TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_AES_GCM_256: __u16 = 52; pub const TLS_CIPHER_AES_GCM_256_IV_SIZE: usize = 8; pub const TLS_CIPHER_AES_GCM_256_KEY_SIZE: usize = 32; pub const TLS_CIPHER_AES_GCM_256_SALT_SIZE: usize = 4; pub const TLS_CIPHER_AES_GCM_256_TAG_SIZE: usize = 16; pub const TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_AES_CCM_128: __u16 = 53; pub const TLS_CIPHER_AES_CCM_128_IV_SIZE: usize = 8; pub const TLS_CIPHER_AES_CCM_128_KEY_SIZE: usize = 16; pub const TLS_CIPHER_AES_CCM_128_SALT_SIZE: usize = 4; pub const TLS_CIPHER_AES_CCM_128_TAG_SIZE: usize = 16; pub const TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_CHACHA20_POLY1305: __u16 = 54; pub const TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE: usize = 12; pub const TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE: usize = 32; pub const TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE: usize = 0; pub const TLS_CIPHER_CHACHA20_POLY1305_TAG_SIZE: usize = 16; pub const TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_SM4_GCM: __u16 = 55; pub const TLS_CIPHER_SM4_GCM_IV_SIZE: usize = 8; pub const TLS_CIPHER_SM4_GCM_KEY_SIZE: usize = 16; pub const TLS_CIPHER_SM4_GCM_SALT_SIZE: usize = 4; pub const TLS_CIPHER_SM4_GCM_TAG_SIZE: usize = 16; pub const TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_SM4_CCM: __u16 = 56; pub const TLS_CIPHER_SM4_CCM_IV_SIZE: usize = 8; pub const TLS_CIPHER_SM4_CCM_KEY_SIZE: usize = 16; pub const TLS_CIPHER_SM4_CCM_SALT_SIZE: usize = 4; pub const TLS_CIPHER_SM4_CCM_TAG_SIZE: usize = 16; pub const TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_ARIA_GCM_128: __u16 = 57; pub const TLS_CIPHER_ARIA_GCM_128_IV_SIZE: usize = 8; pub const TLS_CIPHER_ARIA_GCM_128_KEY_SIZE: usize = 16; pub const TLS_CIPHER_ARIA_GCM_128_SALT_SIZE: usize = 4; pub const TLS_CIPHER_ARIA_GCM_128_TAG_SIZE: usize = 16; pub const TLS_CIPHER_ARIA_GCM_128_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_ARIA_GCM_256: __u16 = 58; pub const TLS_CIPHER_ARIA_GCM_256_IV_SIZE: usize = 8; pub const TLS_CIPHER_ARIA_GCM_256_KEY_SIZE: usize = 32; pub const TLS_CIPHER_ARIA_GCM_256_SALT_SIZE: usize = 4; pub const TLS_CIPHER_ARIA_GCM_256_TAG_SIZE: usize = 16; pub const TLS_CIPHER_ARIA_GCM_256_REC_SEQ_SIZE: usize = 8; pub const TLS_SET_RECORD_TYPE: c_int = 1; pub const TLS_GET_RECORD_TYPE: c_int = 2; pub const SOL_TLS: c_int = 282; // enum pub const TLS_INFO_UNSPEC: c_int = 0x00; pub const TLS_INFO_VERSION: c_int = 0x01; pub const TLS_INFO_CIPHER: c_int = 0x02; pub const TLS_INFO_TXCONF: c_int = 0x03; pub const TLS_INFO_RXCONF: c_int = 0x04; pub const TLS_INFO_ZC_RO_TX: c_int = 0x05; pub const TLS_INFO_RX_NO_PAD: c_int = 0x06; pub const TLS_CONF_BASE: c_int = 1; pub const TLS_CONF_SW: c_int = 2; pub const TLS_CONF_HW: c_int = 3; pub const TLS_CONF_HW_RECORD: c_int = 4; // linux/if_alg.h pub const ALG_SET_KEY: c_int = 1; pub const ALG_SET_IV: c_int = 2; pub const ALG_SET_OP: c_int = 3; pub const ALG_SET_AEAD_ASSOCLEN: c_int = 4; pub const ALG_SET_AEAD_AUTHSIZE: c_int = 5; pub const ALG_SET_DRBG_ENTROPY: c_int = 6; pub const ALG_SET_KEY_BY_KEY_SERIAL: c_int = 7; pub const ALG_OP_DECRYPT: c_int = 0; pub const ALG_OP_ENCRYPT: c_int = 1; // include/uapi/linux/if.h pub const IF_OPER_UNKNOWN: c_int = 0; pub const IF_OPER_NOTPRESENT: c_int = 1; pub const IF_OPER_DOWN: c_int = 2; pub const IF_OPER_LOWERLAYERDOWN: c_int = 3; pub const IF_OPER_TESTING: c_int = 4; pub const IF_OPER_DORMANT: c_int = 5; pub const IF_OPER_UP: c_int = 6; pub const IF_LINK_MODE_DEFAULT: c_int = 0; pub const IF_LINK_MODE_DORMANT: c_int = 1; pub const IF_LINK_MODE_TESTING: c_int = 2; // include/uapi/linux/udp.h pub const UDP_CORK: c_int = 1; pub const UDP_ENCAP: c_int = 100; pub const UDP_NO_CHECK6_TX: c_int = 101; pub const UDP_NO_CHECK6_RX: c_int = 102; // include/uapi/linux/mman.h pub const MAP_SHARED_VALIDATE: c_int = 0x3; pub const MAP_DROPPABLE: c_int = 0x8; // include/uapi/asm-generic/mman-common.h pub const MAP_FIXED_NOREPLACE: c_int = 0x100000; pub const MLOCK_ONFAULT: c_uint = 0x01; // uapi/linux/vm_sockets.h pub const VMADDR_CID_ANY: c_uint = 0xFFFFFFFF; pub const VMADDR_CID_HYPERVISOR: c_uint = 0; #[deprecated( since = "0.2.74", note = "VMADDR_CID_RESERVED is removed since Linux v5.6 and \ replaced with VMADDR_CID_LOCAL" )] pub const VMADDR_CID_RESERVED: c_uint = 1; pub const VMADDR_CID_LOCAL: c_uint = 1; pub const VMADDR_CID_HOST: c_uint = 2; pub const VMADDR_PORT_ANY: c_uint = 0xFFFFFFFF; // uapi/linux/inotify.h pub const IN_ACCESS: u32 = 0x0000_0001; pub const IN_MODIFY: u32 = 0x0000_0002; pub const IN_ATTRIB: u32 = 0x0000_0004; pub const IN_CLOSE_WRITE: u32 = 0x0000_0008; pub const IN_CLOSE_NOWRITE: u32 = 0x0000_0010; pub const IN_CLOSE: u32 = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE; pub const IN_OPEN: u32 = 0x0000_0020; pub const IN_MOVED_FROM: u32 = 0x0000_0040; pub const IN_MOVED_TO: u32 = 0x0000_0080; pub const IN_MOVE: u32 = IN_MOVED_FROM | IN_MOVED_TO; pub const IN_CREATE: u32 = 0x0000_0100; pub const IN_DELETE: u32 = 0x0000_0200; pub const IN_DELETE_SELF: u32 = 0x0000_0400; pub const IN_MOVE_SELF: u32 = 0x0000_0800; pub const IN_UNMOUNT: u32 = 0x0000_2000; pub const IN_Q_OVERFLOW: u32 = 0x0000_4000; pub const IN_IGNORED: u32 = 0x0000_8000; pub const IN_ONLYDIR: u32 = 0x0100_0000; pub const IN_DONT_FOLLOW: u32 = 0x0200_0000; pub const IN_EXCL_UNLINK: u32 = 0x0400_0000; // linux/keyctl.h pub const KEY_SPEC_THREAD_KEYRING: i32 = -1; pub const KEY_SPEC_PROCESS_KEYRING: i32 = -2; pub const KEY_SPEC_SESSION_KEYRING: i32 = -3; pub const KEY_SPEC_USER_KEYRING: i32 = -4; pub const KEY_SPEC_USER_SESSION_KEYRING: i32 = -5; pub const KEY_SPEC_GROUP_KEYRING: i32 = -6; pub const KEY_SPEC_REQKEY_AUTH_KEY: i32 = -7; pub const KEY_SPEC_REQUESTOR_KEYRING: i32 = -8; pub const KEY_REQKEY_DEFL_NO_CHANGE: i32 = -1; pub const KEY_REQKEY_DEFL_DEFAULT: i32 = 0; pub const KEY_REQKEY_DEFL_THREAD_KEYRING: i32 = 1; pub const KEY_REQKEY_DEFL_PROCESS_KEYRING: i32 = 2; pub const KEY_REQKEY_DEFL_SESSION_KEYRING: i32 = 3; pub const KEY_REQKEY_DEFL_USER_KEYRING: i32 = 4; pub const KEY_REQKEY_DEFL_USER_SESSION_KEYRING: i32 = 5; pub const KEY_REQKEY_DEFL_GROUP_KEYRING: i32 = 6; pub const KEY_REQKEY_DEFL_REQUESTOR_KEYRING: i32 = 7; pub const KEYCTL_GET_KEYRING_ID: u32 = 0; pub const KEYCTL_JOIN_SESSION_KEYRING: u32 = 1; pub const KEYCTL_UPDATE: u32 = 2; pub const KEYCTL_REVOKE: u32 = 3; pub const KEYCTL_CHOWN: u32 = 4; pub const KEYCTL_SETPERM: u32 = 5; pub const KEYCTL_DESCRIBE: u32 = 6; pub const KEYCTL_CLEAR: u32 = 7; pub const KEYCTL_LINK: u32 = 8; pub const KEYCTL_UNLINK: u32 = 9; pub const KEYCTL_SEARCH: u32 = 10; pub const KEYCTL_READ: u32 = 11; pub const KEYCTL_INSTANTIATE: u32 = 12; pub const KEYCTL_NEGATE: u32 = 13; pub const KEYCTL_SET_REQKEY_KEYRING: u32 = 14; pub const KEYCTL_SET_TIMEOUT: u32 = 15; pub const KEYCTL_ASSUME_AUTHORITY: u32 = 16; pub const KEYCTL_GET_SECURITY: u32 = 17; pub const KEYCTL_SESSION_TO_PARENT: u32 = 18; pub const KEYCTL_REJECT: u32 = 19; pub const KEYCTL_INSTANTIATE_IOV: u32 = 20; pub const KEYCTL_INVALIDATE: u32 = 21; pub const KEYCTL_GET_PERSISTENT: u32 = 22; pub const IN_MASK_CREATE: u32 = 0x1000_0000; pub const IN_MASK_ADD: u32 = 0x2000_0000; pub const IN_ISDIR: u32 = 0x4000_0000; pub const IN_ONESHOT: u32 = 0x8000_0000; pub const IN_ALL_EVENTS: u32 = IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | IN_MOVE_SELF; pub const IN_CLOEXEC: c_int = O_CLOEXEC; pub const IN_NONBLOCK: c_int = O_NONBLOCK; // uapi/linux/mount.h pub const OPEN_TREE_CLONE: c_uint = 0x01; pub const OPEN_TREE_CLOEXEC: c_uint = O_CLOEXEC as c_uint; // uapi/linux/netfilter/nf_tables.h pub const NFT_TABLE_MAXNAMELEN: c_int = 256; pub const NFT_CHAIN_MAXNAMELEN: c_int = 256; pub const NFT_SET_MAXNAMELEN: c_int = 256; pub const NFT_OBJ_MAXNAMELEN: c_int = 256; pub const NFT_USERDATA_MAXLEN: c_int = 256; pub const NFT_REG_VERDICT: c_int = 0; pub const NFT_REG_1: c_int = 1; pub const NFT_REG_2: c_int = 2; pub const NFT_REG_3: c_int = 3; pub const NFT_REG_4: c_int = 4; pub const __NFT_REG_MAX: c_int = 5; pub const NFT_REG32_00: c_int = 8; pub const NFT_REG32_01: c_int = 9; pub const NFT_REG32_02: c_int = 10; pub const NFT_REG32_03: c_int = 11; pub const NFT_REG32_04: c_int = 12; pub const NFT_REG32_05: c_int = 13; pub const NFT_REG32_06: c_int = 14; pub const NFT_REG32_07: c_int = 15; pub const NFT_REG32_08: c_int = 16; pub const NFT_REG32_09: c_int = 17; pub const NFT_REG32_10: c_int = 18; pub const NFT_REG32_11: c_int = 19; pub const NFT_REG32_12: c_int = 20; pub const NFT_REG32_13: c_int = 21; pub const NFT_REG32_14: c_int = 22; pub const NFT_REG32_15: c_int = 23; pub const NFT_REG_SIZE: c_int = 16; pub const NFT_REG32_SIZE: c_int = 4; pub const NFT_CONTINUE: c_int = -1; pub const NFT_BREAK: c_int = -2; pub const NFT_JUMP: c_int = -3; pub const NFT_GOTO: c_int = -4; pub const NFT_RETURN: c_int = -5; pub const NFT_MSG_NEWTABLE: c_int = 0; pub const NFT_MSG_GETTABLE: c_int = 1; pub const NFT_MSG_DELTABLE: c_int = 2; pub const NFT_MSG_NEWCHAIN: c_int = 3; pub const NFT_MSG_GETCHAIN: c_int = 4; pub const NFT_MSG_DELCHAIN: c_int = 5; pub const NFT_MSG_NEWRULE: c_int = 6; pub const NFT_MSG_GETRULE: c_int = 7; pub const NFT_MSG_DELRULE: c_int = 8; pub const NFT_MSG_NEWSET: c_int = 9; pub const NFT_MSG_GETSET: c_int = 10; pub const NFT_MSG_DELSET: c_int = 11; pub const NFT_MSG_NEWSETELEM: c_int = 12; pub const NFT_MSG_GETSETELEM: c_int = 13; pub const NFT_MSG_DELSETELEM: c_int = 14; pub const NFT_MSG_NEWGEN: c_int = 15; pub const NFT_MSG_GETGEN: c_int = 16; pub const NFT_MSG_TRACE: c_int = 17; cfg_if! { if #[cfg(not(target_arch = "sparc64"))] { pub const NFT_MSG_NEWOBJ: c_int = 18; pub const NFT_MSG_GETOBJ: c_int = 19; pub const NFT_MSG_DELOBJ: c_int = 20; pub const NFT_MSG_GETOBJ_RESET: c_int = 21; } } pub const NFT_MSG_MAX: c_int = 25; pub const NFT_SET_ANONYMOUS: c_int = 0x1; pub const NFT_SET_CONSTANT: c_int = 0x2; pub const NFT_SET_INTERVAL: c_int = 0x4; pub const NFT_SET_MAP: c_int = 0x8; pub const NFT_SET_TIMEOUT: c_int = 0x10; pub const NFT_SET_EVAL: c_int = 0x20; pub const NFT_SET_POL_PERFORMANCE: c_int = 0; pub const NFT_SET_POL_MEMORY: c_int = 1; pub const NFT_SET_ELEM_INTERVAL_END: c_int = 0x1; pub const NFT_DATA_VALUE: c_uint = 0; pub const NFT_DATA_VERDICT: c_uint = 0xffffff00; pub const NFT_DATA_RESERVED_MASK: c_uint = 0xffffff00; pub const NFT_DATA_VALUE_MAXLEN: c_int = 64; pub const NFT_BYTEORDER_NTOH: c_int = 0; pub const NFT_BYTEORDER_HTON: c_int = 1; pub const NFT_CMP_EQ: c_int = 0; pub const NFT_CMP_NEQ: c_int = 1; pub const NFT_CMP_LT: c_int = 2; pub const NFT_CMP_LTE: c_int = 3; pub const NFT_CMP_GT: c_int = 4; pub const NFT_CMP_GTE: c_int = 5; pub const NFT_RANGE_EQ: c_int = 0; pub const NFT_RANGE_NEQ: c_int = 1; pub const NFT_LOOKUP_F_INV: c_int = 1 << 0; pub const NFT_DYNSET_OP_ADD: c_int = 0; pub const NFT_DYNSET_OP_UPDATE: c_int = 1; pub const NFT_DYNSET_F_INV: c_int = 1 << 0; pub const NFT_PAYLOAD_LL_HEADER: c_int = 0; pub const NFT_PAYLOAD_NETWORK_HEADER: c_int = 1; pub const NFT_PAYLOAD_TRANSPORT_HEADER: c_int = 2; pub const NFT_PAYLOAD_CSUM_NONE: c_int = 0; pub const NFT_PAYLOAD_CSUM_INET: c_int = 1; pub const NFT_META_LEN: c_int = 0; pub const NFT_META_PROTOCOL: c_int = 1; pub const NFT_META_PRIORITY: c_int = 2; pub const NFT_META_MARK: c_int = 3; pub const NFT_META_IIF: c_int = 4; pub const NFT_META_OIF: c_int = 5; pub const NFT_META_IIFNAME: c_int = 6; pub const NFT_META_OIFNAME: c_int = 7; pub const NFT_META_IIFTYPE: c_int = 8; pub const NFT_META_OIFTYPE: c_int = 9; pub const NFT_META_SKUID: c_int = 10; pub const NFT_META_SKGID: c_int = 11; pub const NFT_META_NFTRACE: c_int = 12; pub const NFT_META_RTCLASSID: c_int = 13; pub const NFT_META_SECMARK: c_int = 14; pub const NFT_META_NFPROTO: c_int = 15; pub const NFT_META_L4PROTO: c_int = 16; pub const NFT_META_BRI_IIFNAME: c_int = 17; pub const NFT_META_BRI_OIFNAME: c_int = 18; pub const NFT_META_PKTTYPE: c_int = 19; pub const NFT_META_CPU: c_int = 20; pub const NFT_META_IIFGROUP: c_int = 21; pub const NFT_META_OIFGROUP: c_int = 22; pub const NFT_META_CGROUP: c_int = 23; pub const NFT_META_PRANDOM: c_int = 24; pub const NFT_CT_STATE: c_int = 0; pub const NFT_CT_DIRECTION: c_int = 1; pub const NFT_CT_STATUS: c_int = 2; pub const NFT_CT_MARK: c_int = 3; pub const NFT_CT_SECMARK: c_int = 4; pub const NFT_CT_EXPIRATION: c_int = 5; pub const NFT_CT_HELPER: c_int = 6; pub const NFT_CT_L3PROTOCOL: c_int = 7; pub const NFT_CT_SRC: c_int = 8; pub const NFT_CT_DST: c_int = 9; pub const NFT_CT_PROTOCOL: c_int = 10; pub const NFT_CT_PROTO_SRC: c_int = 11; pub const NFT_CT_PROTO_DST: c_int = 12; pub const NFT_CT_LABELS: c_int = 13; pub const NFT_CT_PKTS: c_int = 14; pub const NFT_CT_BYTES: c_int = 15; pub const NFT_CT_AVGPKT: c_int = 16; pub const NFT_CT_ZONE: c_int = 17; pub const NFT_CT_EVENTMASK: c_int = 18; pub const NFT_CT_SRC_IP: c_int = 19; pub const NFT_CT_DST_IP: c_int = 20; pub const NFT_CT_SRC_IP6: c_int = 21; pub const NFT_CT_DST_IP6: c_int = 22; pub const NFT_LIMIT_PKTS: c_int = 0; pub const NFT_LIMIT_PKT_BYTES: c_int = 1; pub const NFT_LIMIT_F_INV: c_int = 1 << 0; pub const NFT_QUEUE_FLAG_BYPASS: c_int = 0x01; pub const NFT_QUEUE_FLAG_CPU_FANOUT: c_int = 0x02; pub const NFT_QUEUE_FLAG_MASK: c_int = 0x03; pub const NFT_QUOTA_F_INV: c_int = 1 << 0; pub const NFT_REJECT_ICMP_UNREACH: c_int = 0; pub const NFT_REJECT_TCP_RST: c_int = 1; pub const NFT_REJECT_ICMPX_UNREACH: c_int = 2; pub const NFT_REJECT_ICMPX_NO_ROUTE: c_int = 0; pub const NFT_REJECT_ICMPX_PORT_UNREACH: c_int = 1; pub const NFT_REJECT_ICMPX_HOST_UNREACH: c_int = 2; pub const NFT_REJECT_ICMPX_ADMIN_PROHIBITED: c_int = 3; pub const NFT_NAT_SNAT: c_int = 0; pub const NFT_NAT_DNAT: c_int = 1; pub const NFT_TRACETYPE_UNSPEC: c_int = 0; pub const NFT_TRACETYPE_POLICY: c_int = 1; pub const NFT_TRACETYPE_RETURN: c_int = 2; pub const NFT_TRACETYPE_RULE: c_int = 3; pub const NFT_NG_INCREMENTAL: c_int = 0; pub const NFT_NG_RANDOM: c_int = 1; // linux/input.h pub const FF_MAX: __u16 = 0x7f; pub const FF_CNT: usize = FF_MAX as usize + 1; // linux/input-event-codes.h pub const INPUT_PROP_POINTER: __u16 = 0x00; pub const INPUT_PROP_DIRECT: __u16 = 0x01; pub const INPUT_PROP_BUTTONPAD: __u16 = 0x02; pub const INPUT_PROP_SEMI_MT: __u16 = 0x03; pub const INPUT_PROP_TOPBUTTONPAD: __u16 = 0x04; pub const INPUT_PROP_POINTING_STICK: __u16 = 0x05; pub const INPUT_PROP_ACCELEROMETER: __u16 = 0x06; pub const INPUT_PROP_MAX: __u16 = 0x1f; pub const INPUT_PROP_CNT: usize = INPUT_PROP_MAX as usize + 1; pub const EV_MAX: __u16 = 0x1f; pub const EV_CNT: usize = EV_MAX as usize + 1; pub const SYN_MAX: __u16 = 0xf; pub const SYN_CNT: usize = SYN_MAX as usize + 1; pub const KEY_MAX: __u16 = 0x2ff; pub const KEY_CNT: usize = KEY_MAX as usize + 1; pub const REL_MAX: __u16 = 0x0f; pub const REL_CNT: usize = REL_MAX as usize + 1; pub const ABS_MAX: __u16 = 0x3f; pub const ABS_CNT: usize = ABS_MAX as usize + 1; pub const SW_MAX: __u16 = 0x10; pub const SW_CNT: usize = SW_MAX as usize + 1; pub const MSC_MAX: __u16 = 0x07; pub const MSC_CNT: usize = MSC_MAX as usize + 1; pub const LED_MAX: __u16 = 0x0f; pub const LED_CNT: usize = LED_MAX as usize + 1; pub const REP_MAX: __u16 = 0x01; pub const REP_CNT: usize = REP_MAX as usize + 1; pub const SND_MAX: __u16 = 0x07; pub const SND_CNT: usize = SND_MAX as usize + 1; // linux/uinput.h pub const UINPUT_VERSION: c_uint = 5; pub const UINPUT_MAX_NAME_SIZE: usize = 80; // uapi/linux/fanotify.h pub const FAN_ACCESS: u64 = 0x0000_0001; pub const FAN_MODIFY: u64 = 0x0000_0002; pub const FAN_ATTRIB: u64 = 0x0000_0004; pub const FAN_CLOSE_WRITE: u64 = 0x0000_0008; pub const FAN_CLOSE_NOWRITE: u64 = 0x0000_0010; pub const FAN_OPEN: u64 = 0x0000_0020; pub const FAN_MOVED_FROM: u64 = 0x0000_0040; pub const FAN_MOVED_TO: u64 = 0x0000_0080; pub const FAN_CREATE: u64 = 0x0000_0100; pub const FAN_DELETE: u64 = 0x0000_0200; pub const FAN_DELETE_SELF: u64 = 0x0000_0400; pub const FAN_MOVE_SELF: u64 = 0x0000_0800; pub const FAN_OPEN_EXEC: u64 = 0x0000_1000; pub const FAN_Q_OVERFLOW: u64 = 0x0000_4000; pub const FAN_FS_ERROR: u64 = 0x0000_8000; pub const FAN_OPEN_PERM: u64 = 0x0001_0000; pub const FAN_ACCESS_PERM: u64 = 0x0002_0000; pub const FAN_OPEN_EXEC_PERM: u64 = 0x0004_0000; pub const FAN_EVENT_ON_CHILD: u64 = 0x0800_0000; pub const FAN_RENAME: u64 = 0x1000_0000; pub const FAN_ONDIR: u64 = 0x4000_0000; pub const FAN_CLOSE: u64 = FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE; pub const FAN_MOVE: u64 = FAN_MOVED_FROM | FAN_MOVED_TO; pub const FAN_CLOEXEC: c_uint = 0x0000_0001; pub const FAN_NONBLOCK: c_uint = 0x0000_0002; pub const FAN_CLASS_NOTIF: c_uint = 0x0000_0000; pub const FAN_CLASS_CONTENT: c_uint = 0x0000_0004; pub const FAN_CLASS_PRE_CONTENT: c_uint = 0x0000_0008; pub const FAN_UNLIMITED_QUEUE: c_uint = 0x0000_0010; pub const FAN_UNLIMITED_MARKS: c_uint = 0x0000_0020; pub const FAN_ENABLE_AUDIT: c_uint = 0x0000_0040; pub const FAN_REPORT_PIDFD: c_uint = 0x0000_0080; pub const FAN_REPORT_TID: c_uint = 0x0000_0100; pub const FAN_REPORT_FID: c_uint = 0x0000_0200; pub const FAN_REPORT_DIR_FID: c_uint = 0x0000_0400; pub const FAN_REPORT_NAME: c_uint = 0x0000_0800; pub const FAN_REPORT_TARGET_FID: c_uint = 0x0000_1000; pub const FAN_REPORT_DFID_NAME: c_uint = FAN_REPORT_DIR_FID | FAN_REPORT_NAME; pub const FAN_REPORT_DFID_NAME_TARGET: c_uint = FAN_REPORT_DFID_NAME | FAN_REPORT_FID | FAN_REPORT_TARGET_FID; pub const FAN_MARK_ADD: c_uint = 0x0000_0001; pub const FAN_MARK_REMOVE: c_uint = 0x0000_0002; pub const FAN_MARK_DONT_FOLLOW: c_uint = 0x0000_0004; pub const FAN_MARK_ONLYDIR: c_uint = 0x0000_0008; pub const FAN_MARK_IGNORED_MASK: c_uint = 0x0000_0020; pub const FAN_MARK_IGNORED_SURV_MODIFY: c_uint = 0x0000_0040; pub const FAN_MARK_FLUSH: c_uint = 0x0000_0080; pub const FAN_MARK_EVICTABLE: c_uint = 0x0000_0200; pub const FAN_MARK_IGNORE: c_uint = 0x0000_0400; pub const FAN_MARK_INODE: c_uint = 0x0000_0000; pub const FAN_MARK_MOUNT: c_uint = 0x0000_0010; pub const FAN_MARK_FILESYSTEM: c_uint = 0x0000_0100; pub const FAN_MARK_IGNORE_SURV: c_uint = FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY; pub const FANOTIFY_METADATA_VERSION: u8 = 3; pub const FAN_EVENT_INFO_TYPE_FID: u8 = 1; pub const FAN_EVENT_INFO_TYPE_DFID_NAME: u8 = 2; pub const FAN_EVENT_INFO_TYPE_DFID: u8 = 3; pub const FAN_EVENT_INFO_TYPE_PIDFD: u8 = 4; pub const FAN_EVENT_INFO_TYPE_ERROR: u8 = 5; pub const FAN_EVENT_INFO_TYPE_OLD_DFID_NAME: u8 = 10; pub const FAN_EVENT_INFO_TYPE_NEW_DFID_NAME: u8 = 12; pub const FAN_RESPONSE_INFO_NONE: u8 = 0; pub const FAN_RESPONSE_INFO_AUDIT_RULE: u8 = 1; pub const FAN_ALLOW: u32 = 0x01; pub const FAN_DENY: u32 = 0x02; pub const FAN_AUDIT: u32 = 0x10; pub const FAN_INFO: u32 = 0x20; pub const FAN_NOFD: c_int = -1; pub const FAN_NOPIDFD: c_int = FAN_NOFD; pub const FAN_EPIDFD: c_int = -2; // linux/futex.h pub const FUTEX_WAIT: c_int = 0; pub const FUTEX_WAKE: c_int = 1; pub const FUTEX_FD: c_int = 2; pub const FUTEX_REQUEUE: c_int = 3; pub const FUTEX_CMP_REQUEUE: c_int = 4; pub const FUTEX_WAKE_OP: c_int = 5; pub const FUTEX_LOCK_PI: c_int = 6; pub const FUTEX_UNLOCK_PI: c_int = 7; pub const FUTEX_TRYLOCK_PI: c_int = 8; pub const FUTEX_WAIT_BITSET: c_int = 9; pub const FUTEX_WAKE_BITSET: c_int = 10; pub const FUTEX_WAIT_REQUEUE_PI: c_int = 11; pub const FUTEX_CMP_REQUEUE_PI: c_int = 12; pub const FUTEX_LOCK_PI2: c_int = 13; pub const FUTEX_PRIVATE_FLAG: c_int = 128; pub const FUTEX_CLOCK_REALTIME: c_int = 256; pub const FUTEX_CMD_MASK: c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); pub const FUTEX_WAITERS: u32 = 0x80000000; pub const FUTEX_OWNER_DIED: u32 = 0x40000000; pub const FUTEX_TID_MASK: u32 = 0x3fffffff; pub const FUTEX_BITSET_MATCH_ANY: c_int = 0xffffffff; pub const FUTEX_OP_SET: c_int = 0; pub const FUTEX_OP_ADD: c_int = 1; pub const FUTEX_OP_OR: c_int = 2; pub const FUTEX_OP_ANDN: c_int = 3; pub const FUTEX_OP_XOR: c_int = 4; pub const FUTEX_OP_OPARG_SHIFT: c_int = 8; pub const FUTEX_OP_CMP_EQ: c_int = 0; pub const FUTEX_OP_CMP_NE: c_int = 1; pub const FUTEX_OP_CMP_LT: c_int = 2; pub const FUTEX_OP_CMP_LE: c_int = 3; pub const FUTEX_OP_CMP_GT: c_int = 4; pub const FUTEX_OP_CMP_GE: c_int = 5; pub fn FUTEX_OP(op: c_int, oparg: c_int, cmp: c_int, cmparg: c_int) -> c_int { ((op & 0xf) << 28) | ((cmp & 0xf) << 24) | ((oparg & 0xfff) << 12) | (cmparg & 0xfff) } // linux/kexec.h pub const KEXEC_ON_CRASH: c_int = 0x00000001; pub const KEXEC_PRESERVE_CONTEXT: c_int = 0x00000002; pub const KEXEC_ARCH_MASK: c_int = 0xffff0000; pub const KEXEC_FILE_UNLOAD: c_int = 0x00000001; pub const KEXEC_FILE_ON_CRASH: c_int = 0x00000002; pub const KEXEC_FILE_NO_INITRAMFS: c_int = 0x00000004; // linux/reboot.h pub const LINUX_REBOOT_MAGIC1: c_int = 0xfee1dead; pub const LINUX_REBOOT_MAGIC2: c_int = 672274793; pub const LINUX_REBOOT_MAGIC2A: c_int = 85072278; pub const LINUX_REBOOT_MAGIC2B: c_int = 369367448; pub const LINUX_REBOOT_MAGIC2C: c_int = 537993216; pub const LINUX_REBOOT_CMD_RESTART: c_int = 0x01234567; pub const LINUX_REBOOT_CMD_HALT: c_int = 0xCDEF0123; pub const LINUX_REBOOT_CMD_CAD_ON: c_int = 0x89ABCDEF; pub const LINUX_REBOOT_CMD_CAD_OFF: c_int = 0x00000000; pub const LINUX_REBOOT_CMD_POWER_OFF: c_int = 0x4321FEDC; pub const LINUX_REBOOT_CMD_RESTART2: c_int = 0xA1B2C3D4; pub const LINUX_REBOOT_CMD_SW_SUSPEND: c_int = 0xD000FCE2; pub const LINUX_REBOOT_CMD_KEXEC: c_int = 0x45584543; pub const REG_EXTENDED: c_int = 1; pub const REG_ICASE: c_int = 2; pub const REG_NEWLINE: c_int = 4; pub const REG_NOSUB: c_int = 8; pub const REG_NOTBOL: c_int = 1; pub const REG_NOTEOL: c_int = 2; pub const REG_ENOSYS: c_int = -1; pub const REG_NOMATCH: c_int = 1; pub const REG_BADPAT: c_int = 2; pub const REG_ECOLLATE: c_int = 3; pub const REG_ECTYPE: c_int = 4; pub const REG_EESCAPE: c_int = 5; pub const REG_ESUBREG: c_int = 6; pub const REG_EBRACK: c_int = 7; pub const REG_EPAREN: c_int = 8; pub const REG_EBRACE: c_int = 9; pub const REG_BADBR: c_int = 10; pub const REG_ERANGE: c_int = 11; pub const REG_ESPACE: c_int = 12; pub const REG_BADRPT: c_int = 13; // linux/errqueue.h pub const SO_EE_ORIGIN_NONE: u8 = 0; pub const SO_EE_ORIGIN_LOCAL: u8 = 1; pub const SO_EE_ORIGIN_ICMP: u8 = 2; pub const SO_EE_ORIGIN_ICMP6: u8 = 3; pub const SO_EE_ORIGIN_TXSTATUS: u8 = 4; pub const SO_EE_ORIGIN_TIMESTAMPING: u8 = SO_EE_ORIGIN_TXSTATUS; // errno.h pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EWOULDBLOCK: c_int = EAGAIN; // linux/can.h pub const CAN_EFF_FLAG: canid_t = 0x80000000; pub const CAN_RTR_FLAG: canid_t = 0x40000000; pub const CAN_ERR_FLAG: canid_t = 0x20000000; pub const CAN_SFF_MASK: canid_t = 0x000007FF; pub const CAN_EFF_MASK: canid_t = 0x1FFFFFFF; pub const CAN_ERR_MASK: canid_t = 0x1FFFFFFF; pub const CANXL_PRIO_MASK: crate::canid_t = CAN_SFF_MASK; pub const CAN_SFF_ID_BITS: c_int = 11; pub const CAN_EFF_ID_BITS: c_int = 29; pub const CANXL_PRIO_BITS: c_int = CAN_SFF_ID_BITS; pub const CAN_MAX_DLC: c_int = 8; pub const CAN_MAX_DLEN: usize = 8; pub const CANFD_MAX_DLC: c_int = 15; pub const CANFD_MAX_DLEN: usize = 64; pub const CANFD_BRS: c_int = 0x01; pub const CANFD_ESI: c_int = 0x02; pub const CANFD_FDF: c_int = 0x04; pub const CANXL_MIN_DLC: c_int = 0; pub const CANXL_MAX_DLC: c_int = 2047; pub const CANXL_MAX_DLC_MASK: c_int = 0x07FF; pub const CANXL_MIN_DLEN: usize = 1; pub const CANXL_MAX_DLEN: usize = 2048; pub const CANXL_XLF: c_int = 0x80; pub const CANXL_SEC: c_int = 0x01; pub const CAN_MTU: usize = size_of::(); pub const CANFD_MTU: usize = size_of::(); pub const CANXL_MTU: usize = size_of::(); // FIXME(offset_of): use `core::mem::offset_of!` once that is available // https://github.com/rust-lang/rfcs/pull/3308 // pub const CANXL_HDR_SIZE: usize = core::mem::offset_of!(canxl_frame, data); pub const CANXL_HDR_SIZE: usize = 12; pub const CANXL_MIN_MTU: usize = CANXL_HDR_SIZE + 64; pub const CANXL_MAX_MTU: usize = CANXL_MTU; pub const CAN_RAW: c_int = 1; pub const CAN_BCM: c_int = 2; pub const CAN_TP16: c_int = 3; pub const CAN_TP20: c_int = 4; pub const CAN_MCNET: c_int = 5; pub const CAN_ISOTP: c_int = 6; pub const CAN_J1939: c_int = 7; pub const CAN_NPROTO: c_int = 8; pub const SOL_CAN_BASE: c_int = 100; pub const CAN_INV_FILTER: canid_t = 0x20000000; pub const CAN_RAW_FILTER_MAX: c_int = 512; // linux/can/raw.h pub const SOL_CAN_RAW: c_int = SOL_CAN_BASE + CAN_RAW; pub const CAN_RAW_FILTER: c_int = 1; pub const CAN_RAW_ERR_FILTER: c_int = 2; pub const CAN_RAW_LOOPBACK: c_int = 3; pub const CAN_RAW_RECV_OWN_MSGS: c_int = 4; pub const CAN_RAW_FD_FRAMES: c_int = 5; pub const CAN_RAW_JOIN_FILTERS: c_int = 6; pub const CAN_RAW_XL_FRAMES: c_int = 7; // linux/can/j1939.h pub const SOL_CAN_J1939: c_int = SOL_CAN_BASE + CAN_J1939; pub const J1939_MAX_UNICAST_ADDR: c_uchar = 0xfd; pub const J1939_IDLE_ADDR: c_uchar = 0xfe; pub const J1939_NO_ADDR: c_uchar = 0xff; pub const J1939_NO_NAME: c_ulong = 0; pub const J1939_PGN_REQUEST: c_uint = 0x0ea00; pub const J1939_PGN_ADDRESS_CLAIMED: c_uint = 0x0ee00; pub const J1939_PGN_ADDRESS_COMMANDED: c_uint = 0x0fed8; pub const J1939_PGN_PDU1_MAX: c_uint = 0x3ff00; pub const J1939_PGN_MAX: c_uint = 0x3ffff; pub const J1939_NO_PGN: c_uint = 0x40000; pub const SO_J1939_FILTER: c_int = 1; pub const SO_J1939_PROMISC: c_int = 2; pub const SO_J1939_SEND_PRIO: c_int = 3; pub const SO_J1939_ERRQUEUE: c_int = 4; pub const SCM_J1939_DEST_ADDR: c_int = 1; pub const SCM_J1939_DEST_NAME: c_int = 2; pub const SCM_J1939_PRIO: c_int = 3; pub const SCM_J1939_ERRQUEUE: c_int = 4; pub const J1939_NLA_PAD: c_int = 0; pub const J1939_NLA_BYTES_ACKED: c_int = 1; pub const J1939_NLA_TOTAL_SIZE: c_int = 2; pub const J1939_NLA_PGN: c_int = 3; pub const J1939_NLA_SRC_NAME: c_int = 4; pub const J1939_NLA_DEST_NAME: c_int = 5; pub const J1939_NLA_SRC_ADDR: c_int = 6; pub const J1939_NLA_DEST_ADDR: c_int = 7; pub const J1939_EE_INFO_NONE: c_int = 0; pub const J1939_EE_INFO_TX_ABORT: c_int = 1; pub const J1939_EE_INFO_RX_RTS: c_int = 2; pub const J1939_EE_INFO_RX_DPO: c_int = 3; pub const J1939_EE_INFO_RX_ABORT: c_int = 4; pub const J1939_FILTER_MAX: c_int = 512; // linux/sctp.h pub const SCTP_FUTURE_ASSOC: c_int = 0; pub const SCTP_CURRENT_ASSOC: c_int = 1; pub const SCTP_ALL_ASSOC: c_int = 2; pub const SCTP_RTOINFO: c_int = 0; pub const SCTP_ASSOCINFO: c_int = 1; pub const SCTP_INITMSG: c_int = 2; pub const SCTP_NODELAY: c_int = 3; pub const SCTP_AUTOCLOSE: c_int = 4; pub const SCTP_SET_PEER_PRIMARY_ADDR: c_int = 5; pub const SCTP_PRIMARY_ADDR: c_int = 6; pub const SCTP_ADAPTATION_LAYER: c_int = 7; pub const SCTP_DISABLE_FRAGMENTS: c_int = 8; pub const SCTP_PEER_ADDR_PARAMS: c_int = 9; pub const SCTP_DEFAULT_SEND_PARAM: c_int = 10; pub const SCTP_EVENTS: c_int = 11; pub const SCTP_I_WANT_MAPPED_V4_ADDR: c_int = 12; pub const SCTP_MAXSEG: c_int = 13; pub const SCTP_STATUS: c_int = 14; pub const SCTP_GET_PEER_ADDR_INFO: c_int = 15; pub const SCTP_DELAYED_ACK_TIME: c_int = 16; pub const SCTP_DELAYED_ACK: c_int = SCTP_DELAYED_ACK_TIME; pub const SCTP_DELAYED_SACK: c_int = SCTP_DELAYED_ACK_TIME; pub const SCTP_CONTEXT: c_int = 17; pub const SCTP_FRAGMENT_INTERLEAVE: c_int = 18; pub const SCTP_PARTIAL_DELIVERY_POINT: c_int = 19; pub const SCTP_MAX_BURST: c_int = 20; pub const SCTP_AUTH_CHUNK: c_int = 21; pub const SCTP_HMAC_IDENT: c_int = 22; pub const SCTP_AUTH_KEY: c_int = 23; pub const SCTP_AUTH_ACTIVE_KEY: c_int = 24; pub const SCTP_AUTH_DELETE_KEY: c_int = 25; pub const SCTP_PEER_AUTH_CHUNKS: c_int = 26; pub const SCTP_LOCAL_AUTH_CHUNKS: c_int = 27; pub const SCTP_GET_ASSOC_NUMBER: c_int = 28; pub const SCTP_GET_ASSOC_ID_LIST: c_int = 29; pub const SCTP_AUTO_ASCONF: c_int = 30; pub const SCTP_PEER_ADDR_THLDS: c_int = 31; pub const SCTP_RECVRCVINFO: c_int = 32; pub const SCTP_RECVNXTINFO: c_int = 33; pub const SCTP_DEFAULT_SNDINFO: c_int = 34; pub const SCTP_AUTH_DEACTIVATE_KEY: c_int = 35; pub const SCTP_REUSE_PORT: c_int = 36; pub const SCTP_PEER_ADDR_THLDS_V2: c_int = 37; pub const SCTP_PR_SCTP_NONE: c_int = 0x0000; pub const SCTP_PR_SCTP_TTL: c_int = 0x0010; pub const SCTP_PR_SCTP_RTX: c_int = 0x0020; pub const SCTP_PR_SCTP_PRIO: c_int = 0x0030; pub const SCTP_PR_SCTP_MAX: c_int = SCTP_PR_SCTP_PRIO; pub const SCTP_PR_SCTP_MASK: c_int = 0x0030; pub const SCTP_ENABLE_RESET_STREAM_REQ: c_int = 0x01; pub const SCTP_ENABLE_RESET_ASSOC_REQ: c_int = 0x02; pub const SCTP_ENABLE_CHANGE_ASSOC_REQ: c_int = 0x04; pub const SCTP_ENABLE_STRRESET_MASK: c_int = 0x07; pub const SCTP_STREAM_RESET_INCOMING: c_int = 0x01; pub const SCTP_STREAM_RESET_OUTGOING: c_int = 0x02; pub const SCTP_INIT: c_int = 0; pub const SCTP_SNDRCV: c_int = 1; pub const SCTP_SNDINFO: c_int = 2; pub const SCTP_RCVINFO: c_int = 3; pub const SCTP_NXTINFO: c_int = 4; pub const SCTP_PRINFO: c_int = 5; pub const SCTP_AUTHINFO: c_int = 6; pub const SCTP_DSTADDRV4: c_int = 7; pub const SCTP_DSTADDRV6: c_int = 8; pub const SCTP_UNORDERED: c_int = 1 << 0; pub const SCTP_ADDR_OVER: c_int = 1 << 1; pub const SCTP_ABORT: c_int = 1 << 2; pub const SCTP_SACK_IMMEDIATELY: c_int = 1 << 3; pub const SCTP_SENDALL: c_int = 1 << 6; pub const SCTP_PR_SCTP_ALL: c_int = 1 << 7; pub const SCTP_NOTIFICATION: c_int = MSG_NOTIFICATION; pub const SCTP_EOF: c_int = crate::MSG_FIN; /* DCCP socket options */ pub const DCCP_SOCKOPT_PACKET_SIZE: c_int = 1; pub const DCCP_SOCKOPT_SERVICE: c_int = 2; pub const DCCP_SOCKOPT_CHANGE_L: c_int = 3; pub const DCCP_SOCKOPT_CHANGE_R: c_int = 4; pub const DCCP_SOCKOPT_GET_CUR_MPS: c_int = 5; pub const DCCP_SOCKOPT_SERVER_TIMEWAIT: c_int = 6; pub const DCCP_SOCKOPT_SEND_CSCOV: c_int = 10; pub const DCCP_SOCKOPT_RECV_CSCOV: c_int = 11; pub const DCCP_SOCKOPT_AVAILABLE_CCIDS: c_int = 12; pub const DCCP_SOCKOPT_CCID: c_int = 13; pub const DCCP_SOCKOPT_TX_CCID: c_int = 14; pub const DCCP_SOCKOPT_RX_CCID: c_int = 15; pub const DCCP_SOCKOPT_QPOLICY_ID: c_int = 16; pub const DCCP_SOCKOPT_QPOLICY_TXQLEN: c_int = 17; pub const DCCP_SOCKOPT_CCID_RX_INFO: c_int = 128; pub const DCCP_SOCKOPT_CCID_TX_INFO: c_int = 192; /// maximum number of services provided on the same listening port pub const DCCP_SERVICE_LIST_MAX_LEN: c_int = 32; pub const CTL_KERN: c_int = 1; pub const CTL_VM: c_int = 2; pub const CTL_NET: c_int = 3; pub const CTL_FS: c_int = 5; pub const CTL_DEBUG: c_int = 6; pub const CTL_DEV: c_int = 7; pub const CTL_BUS: c_int = 8; pub const CTL_ABI: c_int = 9; pub const CTL_CPU: c_int = 10; pub const CTL_BUS_ISA: c_int = 1; pub const INOTIFY_MAX_USER_INSTANCES: c_int = 1; pub const INOTIFY_MAX_USER_WATCHES: c_int = 2; pub const INOTIFY_MAX_QUEUED_EVENTS: c_int = 3; pub const KERN_OSTYPE: c_int = 1; pub const KERN_OSRELEASE: c_int = 2; pub const KERN_OSREV: c_int = 3; pub const KERN_VERSION: c_int = 4; pub const KERN_SECUREMASK: c_int = 5; pub const KERN_PROF: c_int = 6; pub const KERN_NODENAME: c_int = 7; pub const KERN_DOMAINNAME: c_int = 8; pub const KERN_PANIC: c_int = 15; pub const KERN_REALROOTDEV: c_int = 16; pub const KERN_SPARC_REBOOT: c_int = 21; pub const KERN_CTLALTDEL: c_int = 22; pub const KERN_PRINTK: c_int = 23; pub const KERN_NAMETRANS: c_int = 24; pub const KERN_PPC_HTABRECLAIM: c_int = 25; pub const KERN_PPC_ZEROPAGED: c_int = 26; pub const KERN_PPC_POWERSAVE_NAP: c_int = 27; pub const KERN_MODPROBE: c_int = 28; pub const KERN_SG_BIG_BUFF: c_int = 29; pub const KERN_ACCT: c_int = 30; pub const KERN_PPC_L2CR: c_int = 31; pub const KERN_RTSIGNR: c_int = 32; pub const KERN_RTSIGMAX: c_int = 33; pub const KERN_SHMMAX: c_int = 34; pub const KERN_MSGMAX: c_int = 35; pub const KERN_MSGMNB: c_int = 36; pub const KERN_MSGPOOL: c_int = 37; pub const KERN_SYSRQ: c_int = 38; pub const KERN_MAX_THREADS: c_int = 39; pub const KERN_RANDOM: c_int = 40; pub const KERN_SHMALL: c_int = 41; pub const KERN_MSGMNI: c_int = 42; pub const KERN_SEM: c_int = 43; pub const KERN_SPARC_STOP_A: c_int = 44; pub const KERN_SHMMNI: c_int = 45; pub const KERN_OVERFLOWUID: c_int = 46; pub const KERN_OVERFLOWGID: c_int = 47; pub const KERN_SHMPATH: c_int = 48; pub const KERN_HOTPLUG: c_int = 49; pub const KERN_IEEE_EMULATION_WARNINGS: c_int = 50; pub const KERN_S390_USER_DEBUG_LOGGING: c_int = 51; pub const KERN_CORE_USES_PID: c_int = 52; pub const KERN_TAINTED: c_int = 53; pub const KERN_CADPID: c_int = 54; pub const KERN_PIDMAX: c_int = 55; pub const KERN_CORE_PATTERN: c_int = 56; pub const KERN_PANIC_ON_OOPS: c_int = 57; pub const KERN_HPPA_PWRSW: c_int = 58; pub const KERN_HPPA_UNALIGNED: c_int = 59; pub const KERN_PRINTK_RATELIMIT: c_int = 60; pub const KERN_PRINTK_RATELIMIT_BURST: c_int = 61; pub const KERN_PTY: c_int = 62; pub const KERN_NGROUPS_MAX: c_int = 63; pub const KERN_SPARC_SCONS_PWROFF: c_int = 64; pub const KERN_HZ_TIMER: c_int = 65; pub const KERN_UNKNOWN_NMI_PANIC: c_int = 66; pub const KERN_BOOTLOADER_TYPE: c_int = 67; pub const KERN_RANDOMIZE: c_int = 68; pub const KERN_SETUID_DUMPABLE: c_int = 69; pub const KERN_SPIN_RETRY: c_int = 70; pub const KERN_ACPI_VIDEO_FLAGS: c_int = 71; pub const KERN_IA64_UNALIGNED: c_int = 72; pub const KERN_COMPAT_LOG: c_int = 73; pub const KERN_MAX_LOCK_DEPTH: c_int = 74; pub const KERN_NMI_WATCHDOG: c_int = 75; pub const KERN_PANIC_ON_NMI: c_int = 76; pub const VM_OVERCOMMIT_MEMORY: c_int = 5; pub const VM_PAGE_CLUSTER: c_int = 10; pub const VM_DIRTY_BACKGROUND: c_int = 11; pub const VM_DIRTY_RATIO: c_int = 12; pub const VM_DIRTY_WB_CS: c_int = 13; pub const VM_DIRTY_EXPIRE_CS: c_int = 14; pub const VM_NR_PDFLUSH_THREADS: c_int = 15; pub const VM_OVERCOMMIT_RATIO: c_int = 16; pub const VM_PAGEBUF: c_int = 17; pub const VM_HUGETLB_PAGES: c_int = 18; pub const VM_SWAPPINESS: c_int = 19; pub const VM_LOWMEM_RESERVE_RATIO: c_int = 20; pub const VM_MIN_FREE_KBYTES: c_int = 21; pub const VM_MAX_MAP_COUNT: c_int = 22; pub const VM_LAPTOP_MODE: c_int = 23; pub const VM_BLOCK_DUMP: c_int = 24; pub const VM_HUGETLB_GROUP: c_int = 25; pub const VM_VFS_CACHE_PRESSURE: c_int = 26; pub const VM_LEGACY_VA_LAYOUT: c_int = 27; pub const VM_SWAP_TOKEN_TIMEOUT: c_int = 28; pub const VM_DROP_PAGECACHE: c_int = 29; pub const VM_PERCPU_PAGELIST_FRACTION: c_int = 30; pub const VM_ZONE_RECLAIM_MODE: c_int = 31; pub const VM_MIN_UNMAPPED: c_int = 32; pub const VM_PANIC_ON_OOM: c_int = 33; pub const VM_VDSO_ENABLED: c_int = 34; pub const VM_MIN_SLAB: c_int = 35; pub const NET_CORE: c_int = 1; pub const NET_ETHER: c_int = 2; pub const NET_802: c_int = 3; pub const NET_UNIX: c_int = 4; pub const NET_IPV4: c_int = 5; pub const NET_IPX: c_int = 6; pub const NET_ATALK: c_int = 7; pub const NET_NETROM: c_int = 8; pub const NET_AX25: c_int = 9; pub const NET_BRIDGE: c_int = 10; pub const NET_ROSE: c_int = 11; pub const NET_IPV6: c_int = 12; pub const NET_X25: c_int = 13; pub const NET_TR: c_int = 14; pub const NET_DECNET: c_int = 15; pub const NET_ECONET: c_int = 16; pub const NET_SCTP: c_int = 17; pub const NET_LLC: c_int = 18; pub const NET_NETFILTER: c_int = 19; pub const NET_DCCP: c_int = 20; pub const NET_IRDA: c_int = 412; // include/linux/sched.h /// I'm a virtual CPU. pub const PF_VCPU: c_int = 0x00000001; /// I am an IDLE thread. pub const PF_IDLE: c_int = 0x00000002; /// Getting shut down. pub const PF_EXITING: c_int = 0x00000004; /// Coredumps should ignore this task. pub const PF_POSTCOREDUMP: c_int = 0x00000008; /// Task is an IO worker. pub const PF_IO_WORKER: c_int = 0x00000010; /// I'm a workqueue worker. pub const PF_WQ_WORKER: c_int = 0x00000020; /// Forked but didn't exec. pub const PF_FORKNOEXEC: c_int = 0x00000040; /// Process policy on mce errors. pub const PF_MCE_PROCESS: c_int = 0x00000080; /// Used super-user privileges. pub const PF_SUPERPRIV: c_int = 0x00000100; /// Dumped core. pub const PF_DUMPCORE: c_int = 0x00000200; /// Killed by a signal. pub const PF_SIGNALED: c_int = 0x00000400; /// Allocating memory to free memory. /// /// See `memalloc_noreclaim_save()`. pub const PF_MEMALLOC: c_int = 0x00000800; /// `set_user()` noticed that `RLIMIT_NPROC` was exceeded. pub const PF_NPROC_EXCEEDED: c_int = 0x00001000; /// If unset the fpu must be initialized before use. pub const PF_USED_MATH: c_int = 0x00002000; /// Kernel thread cloned from userspace thread. pub const PF_USER_WORKER: c_int = 0x00004000; /// This thread should not be frozen. pub const PF_NOFREEZE: c_int = 0x00008000; /// I am `kswapd`. pub const PF_KSWAPD: c_int = 0x00020000; /// All allocations inherit `GFP_NOFS`. /// /// See `memalloc_nfs_save()`. pub const PF_MEMALLOC_NOFS: c_int = 0x00040000; /// All allocations inherit `GFP_NOIO`. /// /// See `memalloc_noio_save()`. pub const PF_MEMALLOC_NOIO: c_int = 0x00080000; /// Throttle writes only against the bdi I write to, I am cleaning /// dirty pages from some other bdi. pub const PF_LOCAL_THROTTLE: c_int = 0x00100000; /// I am a kernel thread. pub const PF_KTHREAD: c_int = 0x00200000; /// Randomize virtual address space. pub const PF_RANDOMIZE: c_int = 0x00400000; /// Userland is not allowed to meddle with `cpus_mask`. pub const PF_NO_SETAFFINITY: c_int = 0x04000000; /// Early kill for mce process policy. pub const PF_MCE_EARLY: c_int = 0x08000000; /// Allocations constrained to zones which allow long term pinning. /// /// See `memalloc_pin_save()`. pub const PF_MEMALLOC_PIN: c_int = 0x10000000; /// Plug has ts that needs updating. pub const PF_BLOCK_TS: c_int = 0x20000000; /// This thread called `freeze_processes()` and should not be frozen. pub const PF_SUSPEND_TASK: c_int = PF_SUSPEND_TASK_UINT as _; // The used value is the highest possible bit fitting on 32 bits, so directly // defining it as a signed integer causes the compiler to report an overflow. // Use instead a private intermediary that assuringly has the correct type and // cast it where necessary to the wanted final type, which preserves the // desired information as-is in terms of integer representation. const PF_SUSPEND_TASK_UINT: c_uint = 0x80000000; pub const CSIGNAL: c_int = 0x000000ff; pub const SCHED_NORMAL: c_int = 0; pub const SCHED_OTHER: c_int = 0; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const SCHED_BATCH: c_int = 3; pub const SCHED_IDLE: c_int = 5; pub const SCHED_DEADLINE: c_int = 6; pub const SCHED_RESET_ON_FORK: c_int = 0x40000000; pub const CLONE_PIDFD: c_int = 0x1000; pub const SCHED_FLAG_RESET_ON_FORK: c_int = 0x01; pub const SCHED_FLAG_RECLAIM: c_int = 0x02; pub const SCHED_FLAG_DL_OVERRUN: c_int = 0x04; pub const SCHED_FLAG_KEEP_POLICY: c_int = 0x08; pub const SCHED_FLAG_KEEP_PARAMS: c_int = 0x10; pub const SCHED_FLAG_UTIL_CLAMP_MIN: c_int = 0x20; pub const SCHED_FLAG_UTIL_CLAMP_MAX: c_int = 0x40; // linux/if_xdp.h pub const XDP_SHARED_UMEM: crate::__u16 = 1 << 0; pub const XDP_COPY: crate::__u16 = 1 << 1; pub const XDP_ZEROCOPY: crate::__u16 = 1 << 2; pub const XDP_USE_NEED_WAKEUP: crate::__u16 = 1 << 3; pub const XDP_USE_SG: crate::__u16 = 1 << 4; pub const XDP_UMEM_UNALIGNED_CHUNK_FLAG: crate::__u32 = 1 << 0; pub const XDP_RING_NEED_WAKEUP: crate::__u32 = 1 << 0; pub const XDP_MMAP_OFFSETS: c_int = 1; pub const XDP_RX_RING: c_int = 2; pub const XDP_TX_RING: c_int = 3; pub const XDP_UMEM_REG: c_int = 4; pub const XDP_UMEM_FILL_RING: c_int = 5; pub const XDP_UMEM_COMPLETION_RING: c_int = 6; pub const XDP_STATISTICS: c_int = 7; pub const XDP_OPTIONS: c_int = 8; pub const XDP_OPTIONS_ZEROCOPY: crate::__u32 = 1 << 0; pub const XDP_PGOFF_RX_RING: crate::off_t = 0; pub const XDP_PGOFF_TX_RING: crate::off_t = 0x80000000; pub const XDP_UMEM_PGOFF_FILL_RING: crate::c_ulonglong = 0x100000000; pub const XDP_UMEM_PGOFF_COMPLETION_RING: crate::c_ulonglong = 0x180000000; pub const XSK_UNALIGNED_BUF_OFFSET_SHIFT: crate::c_int = 48; pub const XSK_UNALIGNED_BUF_ADDR_MASK: crate::c_ulonglong = (1 << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1; pub const XDP_PKT_CONTD: crate::__u32 = 1 << 0; pub const XDP_UMEM_TX_SW_CSUM: crate::__u32 = 1 << 1; pub const XDP_UMEM_TX_METADATA_LEN: crate::__u32 = 1 << 2; pub const XDP_TXMD_FLAGS_TIMESTAMP: crate::__u32 = 1 << 0; pub const XDP_TXMD_FLAGS_CHECKSUM: crate::__u32 = 1 << 1; pub const XDP_TX_METADATA: crate::__u32 = 1 << 1; pub const SOL_XDP: c_int = 283; // linux/mount.h pub const MOUNT_ATTR_RDONLY: crate::__u64 = 0x00000001; pub const MOUNT_ATTR_NOSUID: crate::__u64 = 0x00000002; pub const MOUNT_ATTR_NODEV: crate::__u64 = 0x00000004; pub const MOUNT_ATTR_NOEXEC: crate::__u64 = 0x00000008; pub const MOUNT_ATTR__ATIME: crate::__u64 = 0x00000070; pub const MOUNT_ATTR_RELATIME: crate::__u64 = 0x00000000; pub const MOUNT_ATTR_NOATIME: crate::__u64 = 0x00000010; pub const MOUNT_ATTR_STRICTATIME: crate::__u64 = 0x00000020; pub const MOUNT_ATTR_NODIRATIME: crate::__u64 = 0x00000080; pub const MOUNT_ATTR_IDMAP: crate::__u64 = 0x00100000; pub const MOUNT_ATTR_NOSYMFOLLOW: crate::__u64 = 0x00200000; pub const MOUNT_ATTR_SIZE_VER0: c_int = 32; // elf.h pub const NT_PRSTATUS: c_int = 1; pub const NT_PRFPREG: c_int = 2; pub const NT_FPREGSET: c_int = 2; pub const NT_PRPSINFO: c_int = 3; pub const NT_PRXREG: c_int = 4; pub const NT_TASKSTRUCT: c_int = 4; pub const NT_PLATFORM: c_int = 5; pub const NT_AUXV: c_int = 6; pub const NT_GWINDOWS: c_int = 7; pub const NT_ASRS: c_int = 8; pub const NT_PSTATUS: c_int = 10; pub const NT_PSINFO: c_int = 13; pub const NT_PRCRED: c_int = 14; pub const NT_UTSNAME: c_int = 15; pub const NT_LWPSTATUS: c_int = 16; pub const NT_LWPSINFO: c_int = 17; pub const NT_PRFPXREG: c_int = 20; pub const SCHED_FLAG_KEEP_ALL: c_int = SCHED_FLAG_KEEP_POLICY | SCHED_FLAG_KEEP_PARAMS; pub const SCHED_FLAG_UTIL_CLAMP: c_int = SCHED_FLAG_UTIL_CLAMP_MIN | SCHED_FLAG_UTIL_CLAMP_MAX; pub const SCHED_FLAG_ALL: c_int = SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM | SCHED_FLAG_DL_OVERRUN | SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP; // ioctl_eventpoll: added in Linux 6.9 pub const EPIOCSPARAMS: Ioctl = 0x40088a01; pub const EPIOCGPARAMS: Ioctl = 0x80088a02; // siginfo.h pub const SI_DETHREAD: c_int = -7; pub const TRAP_PERF: c_int = 6; /// Build an ioctl number for an argumentless ioctl. pub const fn _IO(ty: u32, nr: u32) -> u32 { super::_IOC(super::_IOC_NONE, ty, nr, 0) } /// Build an ioctl number for an read-only ioctl. pub const fn _IOR(ty: u32, nr: u32) -> u32 { super::_IOC(super::_IOC_READ, ty, nr, size_of::()) } /// Build an ioctl number for an write-only ioctl. pub const fn _IOW(ty: u32, nr: u32) -> u32 { super::_IOC(super::_IOC_WRITE, ty, nr, size_of::()) } /// Build an ioctl number for a read-write ioctl. pub const fn _IOWR(ty: u32, nr: u32) -> u32 { super::_IOC(super::_IOC_READ | super::_IOC_WRITE, ty, nr, size_of::()) } f! { pub fn NLA_ALIGN(len: c_int) -> c_int { return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1); } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as usize) < size_of::() { return 0 as *mut cmsghdr; }; let next = (cmsg as usize + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if (next.wrapping_offset(1)) as usize > max || next as usize + super::CMSG_ALIGN((*next).cmsg_len as usize) > max { 0 as *mut cmsghdr } else { next as *mut cmsghdr } } pub fn CPU_ALLOC_SIZE(count: c_int) -> size_t { let _dummy: cpu_set_t = mem::zeroed(); let size_in_bits = 8 * mem::size_of_val(&_dummy.bits[0]); ((count as size_t + size_in_bits - 1) / 8) as size_t } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> c_int { let mut s: u32 = 0; let size_of_mask = mem::size_of_val(&cpuset.bits[0]); for i in cpuset.bits[..(size / size_of_mask)].iter() { s += i.count_ones(); } s as c_int } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> c_int { CPU_COUNT_S(size_of::(), cpuset) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } pub fn SCTP_PR_INDEX(policy: c_int) -> c_int { policy >> 4 - 1 } pub fn SCTP_PR_POLICY(policy: c_int) -> c_int { policy & SCTP_PR_SCTP_MASK } pub fn SCTP_PR_SET_POLICY(flags: &mut c_int, policy: c_int) -> () { *flags &= !SCTP_PR_SCTP_MASK; *flags |= policy; () } pub fn IPTOS_TOS(tos: u8) -> u8 { tos & IPTOS_TOS_MASK } pub fn IPTOS_PREC(tos: u8) -> u8 { tos & IPTOS_PREC_MASK } pub fn RT_TOS(tos: u8) -> u8 { tos & crate::IPTOS_TOS_MASK } pub fn RT_ADDRCLASS(flags: u32) -> u32 { flags >> 23 } pub fn RT_LOCALADDR(flags: u32) -> bool { (flags & RTF_ADDRCLASSMASK) == (RTF_LOCAL | RTF_INTERFACE) } pub fn SO_EE_OFFENDER(ee: *const crate::sock_extended_err) -> *mut crate::sockaddr { ee.offset(1) as *mut crate::sockaddr } pub fn TPACKET_ALIGN(x: usize) -> usize { (x + TPACKET_ALIGNMENT - 1) & !(TPACKET_ALIGNMENT - 1) } pub fn BPF_CLASS(code: __u32) -> __u32 { code & 0x07 } pub fn BPF_SIZE(code: __u32) -> __u32 { code & 0x18 } pub fn BPF_MODE(code: __u32) -> __u32 { code & 0xe0 } pub fn BPF_OP(code: __u32) -> __u32 { code & 0xf0 } pub fn BPF_SRC(code: __u32) -> __u32 { code & 0x08 } pub fn BPF_RVAL(code: __u32) -> __u32 { code & 0x18 } pub fn BPF_MISCOP(code: __u32) -> __u32 { code & 0xf8 } pub fn BPF_STMT(code: __u16, k: __u32) -> sock_filter { sock_filter { code: code, jt: 0, jf: 0, k: k, } } pub fn BPF_JUMP(code: __u16, k: __u32, jt: __u8, jf: __u8) -> sock_filter { sock_filter { code: code, jt: jt, jf: jf, k: k, } } pub fn ELF32_R_SYM(val: Elf32_Word) -> Elf32_Word { val >> 8 } pub fn ELF32_R_TYPE(val: Elf32_Word) -> Elf32_Word { val & 0xff } pub fn ELF32_R_INFO(sym: Elf32_Word, t: Elf32_Word) -> Elf32_Word { sym << 8 + t & 0xff } pub fn ELF64_R_SYM(val: Elf64_Xword) -> Elf64_Xword { val >> 32 } pub fn ELF64_R_TYPE(val: Elf64_Xword) -> Elf64_Xword { val & 0xffffffff } pub fn ELF64_R_INFO(sym: Elf64_Xword, t: Elf64_Xword) -> Elf64_Xword { sym << 32 + t } } safe_f! { pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= (major & 0x00000fff) << 8; dev |= (major & 0xfffff000) << 32; dev |= (minor & 0x000000ff) << 0; dev |= (minor & 0xffffff00) << 12; dev } pub {const} fn major(dev: crate::dev_t) -> c_uint { let mut major = 0; major |= (dev & 0x00000000000fff00) >> 8; major |= (dev & 0xfffff00000000000) >> 32; major as c_uint } pub {const} fn minor(dev: crate::dev_t) -> c_uint { let mut minor = 0; minor |= (dev & 0x00000000000000ff) >> 0; minor |= (dev & 0x00000ffffff00000) >> 12; minor as c_uint } pub {const} fn SCTP_PR_TTL_ENABLED(policy: c_int) -> bool { policy == SCTP_PR_SCTP_TTL } pub {const} fn SCTP_PR_RTX_ENABLED(policy: c_int) -> bool { policy == SCTP_PR_SCTP_RTX } pub {const} fn SCTP_PR_PRIO_ENABLED(policy: c_int) -> bool { policy == SCTP_PR_SCTP_PRIO } } cfg_if! { if #[cfg(all( any(target_env = "gnu", target_env = "musl", target_env = "ohos"), any(target_arch = "x86_64", target_arch = "x86") ))] { extern "C" { pub fn iopl(level: c_int) -> c_int; pub fn ioperm(from: c_ulong, num: c_ulong, turn_on: c_int) -> c_int; } } } cfg_if! { if #[cfg(all(not(target_env = "uclibc"), not(target_env = "ohos")))] { extern "C" { #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_read64")] pub fn aio_read(aiocbp: *mut aiocb) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_write64")] pub fn aio_write(aiocbp: *mut aiocb) -> c_int; pub fn aio_fsync(op: c_int, aiocbp: *mut aiocb) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_error64")] pub fn aio_error(aiocbp: *const aiocb) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_return64")] pub fn aio_return(aiocbp: *mut aiocb) -> ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: c_int, timeout: *const crate::timespec, ) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "aio_cancel64")] pub fn aio_cancel(fd: c_int, aiocbp: *mut aiocb) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "lio_listio64")] pub fn lio_listio( mode: c_int, aiocb_list: *const *mut aiocb, nitems: c_int, sevp: *mut crate::sigevent, ) -> c_int; } } } cfg_if! { if #[cfg(not(target_env = "uclibc"))] { extern "C" { #[cfg_attr(gnu_file_offset_bits64, link_name = "pwritev64")] pub fn pwritev( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t, ) -> ssize_t; #[cfg_attr(gnu_file_offset_bits64, link_name = "preadv64")] pub fn preadv( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t, ) -> ssize_t; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int; pub fn process_vm_readv( pid: crate::pid_t, local_iov: *const crate::iovec, liovcnt: c_ulong, remote_iov: *const crate::iovec, riovcnt: c_ulong, flags: c_ulong, ) -> isize; pub fn process_vm_writev( pid: crate::pid_t, local_iov: *const crate::iovec, liovcnt: c_ulong, remote_iov: *const crate::iovec, riovcnt: c_ulong, flags: c_ulong, ) -> isize; pub fn futimes(fd: c_int, times: *const crate::timeval) -> c_int; } } } // These functions are not available on OpenHarmony cfg_if! { if #[cfg(not(target_env = "ohos"))] { extern "C" { // Only `getspnam_r` is implemented for musl, out of all of the reenterant // functions from `shadow.h`. // https://git.musl-libc.org/cgit/musl/tree/include/shadow.h pub fn getspnam_r( name: *const c_char, spbuf: *mut spwd, buf: *mut c_char, buflen: size_t, spbufp: *mut *mut spwd, ) -> c_int; pub fn mq_open(name: *const c_char, oflag: c_int, ...) -> crate::mqd_t; pub fn mq_close(mqd: crate::mqd_t) -> c_int; pub fn mq_unlink(name: *const c_char) -> c_int; pub fn mq_receive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, ) -> ssize_t; pub fn mq_timedreceive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, abs_timeout: *const crate::timespec, ) -> ssize_t; pub fn mq_send( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, ) -> c_int; pub fn mq_timedsend( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, abs_timeout: *const crate::timespec, ) -> c_int; pub fn mq_getattr(mqd: crate::mqd_t, attr: *mut crate::mq_attr) -> c_int; pub fn mq_setattr( mqd: crate::mqd_t, newattr: *const crate::mq_attr, oldattr: *mut crate::mq_attr, ) -> c_int; pub fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> c_int; pub fn pthread_cancel(thread: crate::pthread_t) -> c_int; pub fn pthread_mutexattr_getrobust( attr: *const pthread_mutexattr_t, robustness: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_setrobust( attr: *mut pthread_mutexattr_t, robustness: c_int, ) -> c_int; } } } extern "C" { #[cfg_attr( not(any(target_env = "musl", target_env = "ohos")), link_name = "__xpg_strerror_r" )] pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn drand48() -> c_double; pub fn erand48(xseed: *mut c_ushort) -> c_double; pub fn lrand48() -> c_long; pub fn nrand48(xseed: *mut c_ushort) -> c_long; pub fn mrand48() -> c_long; pub fn jrand48(xseed: *mut c_ushort) -> c_long; pub fn srand48(seed: c_long); pub fn seed48(xseed: *mut c_ushort) -> *mut c_ushort; pub fn lcong48(p: *mut c_ushort); pub fn lutimes(file: *const c_char, times: *const crate::timeval) -> c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut crate::group; pub fn setspent(); pub fn endspent(); pub fn getspent() -> *mut spwd; pub fn getspnam(name: *const c_char) -> *mut spwd; pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; // System V IPC pub fn shmget(key: crate::key_t, size: size_t, shmflg: c_int) -> c_int; pub fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void; pub fn shmdt(shmaddr: *const c_void) -> c_int; pub fn shmctl(shmid: c_int, cmd: c_int, buf: *mut crate::shmid_ds) -> c_int; pub fn ftok(pathname: *const c_char, proj_id: c_int) -> crate::key_t; pub fn semget(key: crate::key_t, nsems: c_int, semflag: c_int) -> c_int; pub fn semop(semid: c_int, sops: *mut crate::sembuf, nsops: size_t) -> c_int; pub fn semctl(semid: c_int, semnum: c_int, cmd: c_int, ...) -> c_int; pub fn msgctl(msqid: c_int, cmd: c_int, buf: *mut msqid_ds) -> c_int; pub fn msgget(key: crate::key_t, msgflg: c_int) -> c_int; pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtyp: c_long, msgflg: c_int, ) -> ssize_t; pub fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: size_t, msgflg: c_int) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn __errno_location() -> *mut c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "fallocate64")] pub fn fallocate(fd: c_int, mode: c_int, offset: off_t, len: off_t) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "posix_fallocate64")] pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn readahead(fd: c_int, offset: off64_t, count: size_t) -> ssize_t; pub fn getxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn lgetxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn fgetxattr( filedes: c_int, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn setxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn lsetxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn fsetxattr( filedes: c_int, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn listxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; pub fn llistxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; pub fn flistxattr(filedes: c_int, list: *mut c_char, size: size_t) -> ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> c_int; pub fn lremovexattr(path: *const c_char, name: *const c_char) -> c_int; pub fn fremovexattr(filedes: c_int, name: *const c_char) -> c_int; pub fn signalfd(fd: c_int, mask: *const crate::sigset_t, flags: c_int) -> c_int; pub fn timerfd_create(clockid: crate::clockid_t, flags: c_int) -> c_int; pub fn timerfd_gettime(fd: c_int, curr_value: *mut itimerspec) -> c_int; pub fn timerfd_settime( fd: c_int, flags: c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> c_int; pub fn quotactl(cmd: c_int, special: *const c_char, id: c_int, data: *mut c_char) -> c_int; pub fn epoll_pwait( epfd: c_int, events: *mut crate::epoll_event, maxevents: c_int, timeout: c_int, sigmask: *const crate::sigset_t, ) -> c_int; pub fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn nl_langinfo_l(item: crate::nl_item, locale: crate::locale_t) -> *mut c_char; pub fn accept4( fd: c_int, addr: *mut crate::sockaddr, len: *mut crate::socklen_t, flg: c_int, ) -> c_int; pub fn pthread_getaffinity_np( thread: crate::pthread_t, cpusetsize: size_t, cpuset: *mut crate::cpu_set_t, ) -> c_int; pub fn pthread_setaffinity_np( thread: crate::pthread_t, cpusetsize: size_t, cpuset: *const crate::cpu_set_t, ) -> c_int; pub fn pthread_setschedprio(native: crate::pthread_t, priority: c_int) -> c_int; pub fn reboot(how_to: c_int) -> c_int; pub fn setfsgid(gid: crate::gid_t) -> c_int; pub fn setfsuid(uid: crate::uid_t) -> c_int; // Not available now on Android pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn sync_file_range(fd: c_int, offset: off64_t, nbytes: off64_t, flags: c_uint) -> c_int; pub fn mremap( addr: *mut c_void, len: size_t, new_len: size_t, flags: c_int, ... ) -> *mut c_void; #[cfg_attr(gnu_file_offset_bits64, link_name = "glob64")] pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "globfree64")] pub fn globfree(pglob: *mut crate::glob_t); pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn remap_file_pages( addr: *mut c_void, size: size_t, prot: c_int, pgoff: size_t, flags: c_int, ) -> c_int; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; #[cfg_attr(gnu_file_offset_bits64, link_name = "mkstemps64")] pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn vhangup() -> c_int; pub fn sync(); pub fn syncfs(fd: c_int) -> c_int; pub fn syscall(num: c_long, ...) -> c_long; pub fn sched_getaffinity( pid: crate::pid_t, cpusetsize: size_t, cpuset: *mut cpu_set_t, ) -> c_int; pub fn sched_setaffinity( pid: crate::pid_t, cpusetsize: size_t, cpuset: *const cpu_set_t, ) -> c_int; pub fn epoll_create(size: c_int) -> c_int; pub fn epoll_create1(flags: c_int) -> c_int; pub fn epoll_wait( epfd: c_int, events: *mut crate::epoll_event, maxevents: c_int, timeout: c_int, ) -> c_int; pub fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut crate::epoll_event) -> c_int; pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut crate::sched_param, ) -> c_int; pub fn unshare(flags: c_int) -> c_int; pub fn umount(target: *const c_char) -> c_int; pub fn sched_get_priority_max(policy: c_int) -> c_int; pub fn tee(fd_in: c_int, fd_out: c_int, len: size_t, flags: c_uint) -> ssize_t; pub fn settimeofday(tv: *const crate::timeval, tz: *const crate::timezone) -> c_int; pub fn splice( fd_in: c_int, off_in: *mut crate::loff_t, fd_out: c_int, off_out: *mut crate::loff_t, len: size_t, flags: c_uint, ) -> ssize_t; pub fn eventfd(init: c_uint, flags: c_int) -> c_int; pub fn eventfd_read(fd: c_int, value: *mut eventfd_t) -> c_int; pub fn eventfd_write(fd: c_int, value: eventfd_t) -> c_int; pub fn sched_rr_get_interval(pid: crate::pid_t, tp: *mut crate::timespec) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const crate::sched_param) -> c_int; pub fn setns(fd: c_int, nstype: c_int) -> c_int; pub fn swapoff(path: *const c_char) -> c_int; pub fn vmsplice(fd: c_int, iov: *const crate::iovec, nr_segs: size_t, flags: c_uint) -> ssize_t; pub fn mount( src: *const c_char, target: *const c_char, fstype: *const c_char, flags: c_ulong, data: *const c_void, ) -> c_int; pub fn personality(persona: c_ulong) -> c_int; pub fn prctl(option: c_int, ...) -> c_int; pub fn sched_getparam(pid: crate::pid_t, param: *mut crate::sched_param) -> c_int; pub fn ppoll( fds: *mut crate::pollfd, nfds: nfds_t, timeout: *const crate::timespec, sigmask: *const sigset_t, ) -> c_int; pub fn pthread_mutexattr_getprotocol( attr: *const pthread_mutexattr_t, protocol: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_barrierattr_init(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_destroy(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_getpshared( attr: *const crate::pthread_barrierattr_t, shared: *mut c_int, ) -> c_int; pub fn pthread_barrierattr_setpshared( attr: *mut crate::pthread_barrierattr_t, shared: c_int, ) -> c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const crate::pthread_barrierattr_t, count: c_uint, ) -> c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_spin_init(lock: *mut crate::pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn clone( cb: extern "C" fn(*mut c_void) -> c_int, child_stack: *mut c_void, flags: c_int, arg: *mut c_void, ... ) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn pthread_attr_getinheritsched( attr: *const crate::pthread_attr_t, inheritsched: *mut c_int, ) -> c_int; pub fn pthread_attr_setinheritsched( attr: *mut crate::pthread_attr_t, inheritsched: c_int, ) -> c_int; pub fn pthread_attr_getschedpolicy( attr: *const crate::pthread_attr_t, policy: *mut c_int, ) -> c_int; pub fn pthread_attr_setschedpolicy(attr: *mut crate::pthread_attr_t, policy: c_int) -> c_int; pub fn pthread_attr_getschedparam( attr: *const crate::pthread_attr_t, param: *mut crate::sched_param, ) -> c_int; pub fn pthread_attr_setschedparam( attr: *mut crate::pthread_attr_t, param: *const crate::sched_param, ) -> c_int; pub fn sethostname(name: *const c_char, len: size_t) -> c_int; pub fn sched_get_priority_min(policy: c_int) -> c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut c_int, ) -> c_int; pub fn sysinfo(info: *mut crate::sysinfo) -> c_int; pub fn umount2(target: *const c_char, flags: c_int) -> c_int; pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn swapon(path: *const c_char, swapflags: c_int) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "sendfile64")] pub fn sendfile(out_fd: c_int, in_fd: c_int, offset: *mut off_t, count: size_t) -> ssize_t; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn getdtablesize() -> c_int; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn initgroups(user: *const c_char, group: crate::gid_t) -> c_int; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn getgrouplist( user: *const c_char, group: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut c_int, ) -> c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn( info: *mut crate::dl_phdr_info, size: size_t, data: *mut c_void, ) -> c_int, >, data: *mut c_void, ) -> c_int; pub fn setmntent(filename: *const c_char, ty: *const c_char) -> *mut crate::FILE; pub fn getmntent(stream: *mut crate::FILE) -> *mut crate::mntent; pub fn addmntent(stream: *mut crate::FILE, mnt: *const crate::mntent) -> c_int; pub fn endmntent(streamp: *mut crate::FILE) -> c_int; pub fn hasmntopt(mnt: *const crate::mntent, opt: *const c_char) -> *mut c_char; pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: crate::pid_t) -> c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut c_int, ) -> c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: c_int) -> c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut crate::sched_param, ) -> c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const crate::sched_param, ) -> c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int, ) -> c_int; pub fn fread_unlocked( buf: *mut c_void, size: size_t, nobj: size_t, stream: *mut crate::FILE, ) -> size_t; pub fn inotify_rm_watch(fd: c_int, wd: c_int) -> c_int; pub fn inotify_init() -> c_int; pub fn inotify_init1(flags: c_int) -> c_int; pub fn inotify_add_watch(fd: c_int, path: *const c_char, mask: u32) -> c_int; pub fn fanotify_init(flags: c_uint, event_f_flags: c_uint) -> c_int; pub fn regcomp(preg: *mut crate::regex_t, pattern: *const c_char, cflags: c_int) -> c_int; pub fn regexec( preg: *const crate::regex_t, input: *const c_char, nmatch: size_t, pmatch: *mut regmatch_t, eflags: c_int, ) -> c_int; pub fn regerror( errcode: c_int, preg: *const crate::regex_t, errbuf: *mut c_char, errbuf_size: size_t, ) -> size_t; pub fn regfree(preg: *mut crate::regex_t); pub fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut c_char, inbytesleft: *mut size_t, outbuf: *mut *mut c_char, outbytesleft: *mut size_t, ) -> size_t; pub fn iconv_close(cd: iconv_t) -> c_int; pub fn gettid() -> crate::pid_t; pub fn timer_create( clockid: crate::clockid_t, sevp: *mut crate::sigevent, timerid: *mut crate::timer_t, ) -> c_int; pub fn timer_delete(timerid: crate::timer_t) -> c_int; pub fn timer_getoverrun(timerid: crate::timer_t) -> c_int; pub fn timer_gettime(timerid: crate::timer_t, curr_value: *mut crate::itimerspec) -> c_int; pub fn timer_settime( timerid: crate::timer_t, flags: c_int, new_value: *const crate::itimerspec, old_value: *mut crate::itimerspec, ) -> c_int; pub fn gethostid() -> c_long; pub fn pthread_getcpuclockid(thread: crate::pthread_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; pub fn sched_getcpu() -> c_int; pub fn pthread_getname_np(thread: crate::pthread_t, name: *mut c_char, len: size_t) -> c_int; pub fn pthread_setname_np(thread: crate::pthread_t, name: *const c_char) -> c_int; pub fn getopt_long( argc: c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut c_int, ) -> c_int; pub fn pthread_once(control: *mut pthread_once_t, routine: extern "C" fn()) -> c_int; pub fn copy_file_range( fd_in: c_int, off_in: *mut off64_t, fd_out: c_int, off_out: *mut off64_t, len: size_t, flags: c_uint, ) -> ssize_t; pub fn klogctl(syslog_type: c_int, bufp: *mut c_char, len: c_int) -> c_int; pub fn ioctl(fd: c_int, request: Ioctl, ...) -> c_int; } // LFS64 extensions // // * musl has 64-bit versions only so aliases the LFS64 symbols to the standard ones cfg_if! { if #[cfg(not(target_env = "musl"))] { extern "C" { pub fn fallocate64(fd: c_int, mode: c_int, offset: off64_t, len: off64_t) -> c_int; pub fn fgetpos64(stream: *mut crate::FILE, ptr: *mut fpos64_t) -> c_int; pub fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn freopen64( filename: *const c_char, mode: *const c_char, file: *mut crate::FILE, ) -> *mut crate::FILE; pub fn fseeko64(stream: *mut crate::FILE, offset: off64_t, whence: c_int) -> c_int; pub fn fsetpos64(stream: *mut crate::FILE, ptr: *const fpos64_t) -> c_int; pub fn ftello64(stream: *mut crate::FILE) -> off64_t; pub fn posix_fallocate64(fd: c_int, offset: off64_t, len: off64_t) -> c_int; pub fn sendfile64( out_fd: c_int, in_fd: c_int, offset: *mut off64_t, count: size_t, ) -> ssize_t; pub fn tmpfile64() -> *mut crate::FILE; } } } cfg_if! { if #[cfg(target_env = "uclibc")] { mod uclibc; pub use self::uclibc::*; } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { mod musl; pub use self::musl::*; } else if #[cfg(target_env = "gnu")] { mod gnu; pub use self::gnu::*; } } mod arch; pub use self::arch::*; libc/src/unix/linux_like/linux/uclibc/0000775000175000017500000000000015105742312017632 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/uclibc/mod.rs0000644000175000017500000003764115105742312020770 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type shmatt_t = c_ulong; pub type msgqnum_t = c_ulong; pub type msglen_t = c_ulong; pub type regoff_t = c_int; pub type rlim_t = c_ulong; pub type __rlimit_resource_t = c_ulong; pub type __priority_which_t = c_uint; cfg_if! { if #[cfg(doc)] { // Used in `linux::arch` to define ioctl constants. pub(crate) type Ioctl = c_ulong; } else { #[doc(hidden)] pub type Ioctl = c_ulong; } } s! { pub struct statvfs { // Different than GNU! pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, #[cfg(target_endian = "little")] pub f_fsid: c_ulong, #[cfg(target_pointer_width = "32")] __f_unused: c_int, #[cfg(target_endian = "big")] pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct regex_t { __buffer: *mut c_void, __allocated: size_t, __used: size_t, __syntax: c_ulong, __fastmap: *mut c_char, __translate: *mut c_char, __re_nsub: size_t, __bitfield: u8, } pub struct rtentry { pub rt_pad1: c_ulong, pub rt_dst: crate::sockaddr, pub rt_gateway: crate::sockaddr, pub rt_genmask: crate::sockaddr, pub rt_flags: c_ushort, pub rt_pad2: c_short, pub rt_pad3: c_ulong, pub rt_tos: c_uchar, pub rt_class: c_uchar, #[cfg(target_pointer_width = "64")] pub rt_pad4: [c_short; 3usize], #[cfg(not(target_pointer_width = "64"))] pub rt_pad4: c_short, pub rt_metric: c_short, pub rt_dev: *mut c_char, pub rt_mtu: c_ulong, pub rt_window: c_ulong, pub rt_irtt: c_ushort, } pub struct __exit_status { pub e_termination: c_short, pub e_exit: c_short, } pub struct ptrace_peeksiginfo_args { pub off: crate::__u64, pub flags: crate::__u32, pub nr: crate::__s32, } #[cfg_attr( any( target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64" ), repr(align(4)) )] #[cfg_attr( not(any( target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64" )), repr(align(8)) )] pub struct pthread_mutexattr_t { size: [u8; crate::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[repr(align(4))] pub struct pthread_condattr_t { size: [u8; crate::__SIZEOF_PTHREAD_CONDATTR_T], } pub struct tcp_info { pub tcpi_state: u8, pub tcpi_ca_state: u8, pub tcpi_retransmits: u8, pub tcpi_probes: u8, pub tcpi_backoff: u8, pub tcpi_options: u8, /// This contains the bitfields `tcpi_snd_wscale` and `tcpi_rcv_wscale`. /// Each is 4 bits. pub tcpi_snd_rcv_wscale: u8, pub tcpi_rto: u32, pub tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub tcpi_unacked: u32, pub tcpi_sacked: u32, pub tcpi_lost: u32, pub tcpi_retrans: u32, pub tcpi_fackets: u32, pub tcpi_last_data_sent: u32, pub tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub tcpi_last_ack_recv: u32, pub tcpi_pmtu: u32, pub tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub tcpi_advmss: u32, pub tcpi_reordering: u32, pub tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_total_retrans: u32, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { #[repr(C)] struct siginfo_sigfault { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, si_addr: *mut c_void, } (*(self as *const siginfo_t as *const siginfo_sigfault)).si_addr } pub unsafe fn si_value(&self) -> crate::sigval { #[repr(C)] struct siginfo_si_value { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, _si_timerid: c_int, _si_overrun: c_int, si_value: crate::sigval, } (*(self as *const siginfo_t as *const siginfo_si_value)).si_value } } // Internal, for casts to access union fields #[repr(C)] struct sifields_sigchld { si_pid: crate::pid_t, si_uid: crate::uid_t, si_status: c_int, si_utime: c_long, si_stime: c_long, } impl Copy for sifields_sigchld {} impl Clone for sifields_sigchld { fn clone(&self) -> sifields_sigchld { *self } } // Internal, for casts to access union fields #[repr(C)] union sifields { _align_pointer: *mut c_void, sigchld: sifields_sigchld, } // Internal, for casts to access union fields. Note that some variants // of sifields start with a pointer, which makes the alignment of // sifields vary on 32-bit and 64-bit architectures. #[repr(C)] struct siginfo_f { _siginfo_base: [c_int; 3], sifields: sifields, } impl siginfo_t { unsafe fn sifields(&self) -> &sifields { &(*(self as *const siginfo_t as *const siginfo_f)).sifields } pub unsafe fn si_pid(&self) -> crate::pid_t { self.sifields().sigchld.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.sifields().sigchld.si_uid } pub unsafe fn si_status(&self) -> c_int { self.sifields().sigchld.si_status } pub unsafe fn si_utime(&self) -> c_long { self.sifields().sigchld.si_utime } pub unsafe fn si_stime(&self) -> c_long { self.sifields().sigchld.si_stime } } pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const SIGEV_THREAD_ID: c_int = 4; pub const AF_VSOCK: c_int = 40; // Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the // following are only available on newer Linux versions than the versions // currently used in CI in some configurations, so we define them here. pub const BINDERFS_SUPER_MAGIC: c_long = 0x6c6f6f70; pub const XFS_SUPER_MAGIC: c_long = 0x58465342; pub const PTRACE_TRACEME: c_int = 0; pub const PTRACE_PEEKTEXT: c_int = 1; pub const PTRACE_PEEKDATA: c_int = 2; pub const PTRACE_PEEKUSER: c_int = 3; pub const PTRACE_POKETEXT: c_int = 4; pub const PTRACE_POKEDATA: c_int = 5; pub const PTRACE_POKEUSER: c_int = 6; pub const PTRACE_CONT: c_int = 7; pub const PTRACE_KILL: c_int = 8; pub const PTRACE_SINGLESTEP: c_int = 9; pub const PTRACE_GETREGS: c_int = 12; pub const PTRACE_SETREGS: c_int = 13; pub const PTRACE_GETFPREGS: c_int = 14; pub const PTRACE_SETFPREGS: c_int = 15; pub const PTRACE_ATTACH: c_int = 16; pub const PTRACE_DETACH: c_int = 17; pub const PTRACE_GETFPXREGS: c_int = 18; pub const PTRACE_SETFPXREGS: c_int = 19; pub const PTRACE_SYSCALL: c_int = 24; pub const PTRACE_SETOPTIONS: c_int = 0x4200; pub const PTRACE_GETEVENTMSG: c_int = 0x4201; pub const PTRACE_GETSIGINFO: c_int = 0x4202; pub const PTRACE_SETSIGINFO: c_int = 0x4203; pub const PTRACE_GETREGSET: c_int = 0x4204; pub const PTRACE_SETREGSET: c_int = 0x4205; pub const PTRACE_SEIZE: c_int = 0x4206; pub const PTRACE_INTERRUPT: c_int = 0x4207; pub const PTRACE_LISTEN: c_int = 0x4208; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; // These are different than GNU! pub const LC_CTYPE: c_int = 0; pub const LC_NUMERIC: c_int = 1; pub const LC_TIME: c_int = 3; pub const LC_COLLATE: c_int = 4; pub const LC_MONETARY: c_int = 2; pub const LC_MESSAGES: c_int = 5; pub const LC_ALL: c_int = 6; // end different section // MS_ flags for mount(2) pub const MS_RMT_MASK: c_ulong = crate::MS_RDONLY | crate::MS_SYNCHRONOUS | crate::MS_MANDLOCK | crate::MS_I_VERSION; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const IPV6_JOIN_GROUP: c_int = 20; pub const IPV6_LEAVE_GROUP: c_int = 21; // These are different from GNU pub const ABDAY_1: crate::nl_item = 0x300; pub const ABDAY_2: crate::nl_item = 0x301; pub const ABDAY_3: crate::nl_item = 0x302; pub const ABDAY_4: crate::nl_item = 0x303; pub const ABDAY_5: crate::nl_item = 0x304; pub const ABDAY_6: crate::nl_item = 0x305; pub const ABDAY_7: crate::nl_item = 0x306; pub const DAY_1: crate::nl_item = 0x307; pub const DAY_2: crate::nl_item = 0x308; pub const DAY_3: crate::nl_item = 0x309; pub const DAY_4: crate::nl_item = 0x30A; pub const DAY_5: crate::nl_item = 0x30B; pub const DAY_6: crate::nl_item = 0x30C; pub const DAY_7: crate::nl_item = 0x30D; pub const ABMON_1: crate::nl_item = 0x30E; pub const ABMON_2: crate::nl_item = 0x30F; pub const ABMON_3: crate::nl_item = 0x310; pub const ABMON_4: crate::nl_item = 0x311; pub const ABMON_5: crate::nl_item = 0x312; pub const ABMON_6: crate::nl_item = 0x313; pub const ABMON_7: crate::nl_item = 0x314; pub const ABMON_8: crate::nl_item = 0x315; pub const ABMON_9: crate::nl_item = 0x316; pub const ABMON_10: crate::nl_item = 0x317; pub const ABMON_11: crate::nl_item = 0x318; pub const ABMON_12: crate::nl_item = 0x319; pub const MON_1: crate::nl_item = 0x31A; pub const MON_2: crate::nl_item = 0x31B; pub const MON_3: crate::nl_item = 0x31C; pub const MON_4: crate::nl_item = 0x31D; pub const MON_5: crate::nl_item = 0x31E; pub const MON_6: crate::nl_item = 0x31F; pub const MON_7: crate::nl_item = 0x320; pub const MON_8: crate::nl_item = 0x321; pub const MON_9: crate::nl_item = 0x322; pub const MON_10: crate::nl_item = 0x323; pub const MON_11: crate::nl_item = 0x324; pub const MON_12: crate::nl_item = 0x325; pub const AM_STR: crate::nl_item = 0x326; pub const PM_STR: crate::nl_item = 0x327; pub const D_T_FMT: crate::nl_item = 0x328; pub const D_FMT: crate::nl_item = 0x329; pub const T_FMT: crate::nl_item = 0x32A; pub const T_FMT_AMPM: crate::nl_item = 0x32B; pub const ERA: crate::nl_item = 0x32C; pub const ERA_D_FMT: crate::nl_item = 0x32E; pub const ALT_DIGITS: crate::nl_item = 0x32F; pub const ERA_D_T_FMT: crate::nl_item = 0x330; pub const ERA_T_FMT: crate::nl_item = 0x331; pub const CODESET: crate::nl_item = 10; pub const CRNCYSTR: crate::nl_item = 0x215; pub const RADIXCHAR: crate::nl_item = 0x100; pub const THOUSEP: crate::nl_item = 0x101; pub const NOEXPR: crate::nl_item = 0x501; pub const YESSTR: crate::nl_item = 0x502; pub const NOSTR: crate::nl_item = 0x503; // Different than Gnu. pub const FILENAME_MAX: c_uint = 4095; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; pub const SOMAXCONN: c_int = 128; pub const ST_RELATIME: c_ulong = 4096; pub const AF_NFC: c_int = PF_NFC; pub const BUFSIZ: c_int = 4096; pub const EDEADLOCK: c_int = EDEADLK; pub const EXTA: c_uint = B19200; pub const EXTB: c_uint = B38400; pub const EXTPROC: crate::tcflag_t = 0o200000; pub const FOPEN_MAX: c_int = 16; pub const F_GETOWN: c_int = 9; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const F_RDLCK: c_int = 0; pub const F_SETOWN: c_int = 8; pub const F_UNLCK: c_int = 2; pub const F_WRLCK: c_int = 1; pub const IPV6_MULTICAST_ALL: c_int = 29; pub const IPV6_ROUTER_ALERT_ISOLATE: c_int = 30; pub const MAP_HUGE_SHIFT: c_int = 26; pub const MAP_HUGE_MASK: c_int = 0x3f; pub const MAP_HUGE_64KB: c_int = 16 << MAP_HUGE_SHIFT; pub const MAP_HUGE_512KB: c_int = 19 << MAP_HUGE_SHIFT; pub const MAP_HUGE_1MB: c_int = 20 << MAP_HUGE_SHIFT; pub const MAP_HUGE_2MB: c_int = 21 << MAP_HUGE_SHIFT; pub const MAP_HUGE_8MB: c_int = 23 << MAP_HUGE_SHIFT; pub const MAP_HUGE_16MB: c_int = 24 << MAP_HUGE_SHIFT; pub const MAP_HUGE_32MB: c_int = 25 << MAP_HUGE_SHIFT; pub const MAP_HUGE_256MB: c_int = 28 << MAP_HUGE_SHIFT; pub const MAP_HUGE_512MB: c_int = 29 << MAP_HUGE_SHIFT; pub const MAP_HUGE_1GB: c_int = 30 << MAP_HUGE_SHIFT; pub const MAP_HUGE_2GB: c_int = 31 << MAP_HUGE_SHIFT; pub const MAP_HUGE_16GB: c_int = 34 << MAP_HUGE_SHIFT; pub const MINSIGSTKSZ: c_int = 2048; pub const MSG_COPY: c_int = 0o40000; pub const NI_MAXHOST: crate::socklen_t = 1025; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const PACKET_MR_UNICAST: c_int = 3; pub const PF_NFC: c_int = 39; pub const PF_VSOCK: c_int = 40; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const PTRACE_EVENT_STOP: c_int = 128; pub const PTRACE_GETSIGMASK: c_uint = 0x420a; pub const PTRACE_PEEKSIGINFO: c_int = 0x4209; pub const PTRACE_SETSIGMASK: c_uint = 0x420b; pub const RTLD_NOLOAD: c_int = 0x00004; pub const RUSAGE_THREAD: c_int = 1; pub const SHM_EXEC: c_int = 0o100000; pub const SIGPOLL: c_int = SIGIO; pub const SOCK_DCCP: c_int = 6; #[deprecated(since = "0.2.70", note = "AF_PACKET must be used instead")] pub const SOCK_PACKET: c_int = 10; pub const TCP_COOKIE_TRANSACTIONS: c_int = 15; pub const UDP_GRO: c_int = 104; pub const UDP_SEGMENT: c_int = 103; pub const YESEXPR: c_int = ((5) << 8) | (0); extern "C" { pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut crate::timezone) -> c_int; pub fn pthread_rwlockattr_getkind_np( attr: *const crate::pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setkind_np( attr: *mut crate::pthread_rwlockattr_t, val: c_int, ) -> c_int; pub fn ptrace(request: c_uint, ...) -> c_long; pub fn sendmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_int, ) -> c_int; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_int, timeout: *mut crate::timespec, ) -> c_int; pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> c_int; pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> crate::pid_t; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t) -> ssize_t; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t) -> ssize_t; pub fn sethostid(hostid: c_long) -> c_int; pub fn fanotify_mark( fd: c_int, flags: c_uint, mask: u64, dirfd: c_int, path: *const c_char, ) -> c_int; pub fn getrlimit64(resource: crate::__rlimit_resource_t, rlim: *mut crate::rlimit64) -> c_int; pub fn setrlimit64(resource: crate::__rlimit_resource_t, rlim: *const crate::rlimit64) -> c_int; pub fn getrlimit(resource: crate::__rlimit_resource_t, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: crate::__rlimit_resource_t, rlim: *const crate::rlimit) -> c_int; pub fn getpriority(which: crate::__priority_which_t, who: crate::id_t) -> c_int; pub fn setpriority(which: crate::__priority_which_t, who: crate::id_t, prio: c_int) -> c_int; pub fn getauxval(type_: c_ulong) -> c_ulong; } cfg_if! { if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { mod mips; pub use self::mips::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else { pub use unsupported_target; } } libc/src/unix/linux_like/linux/uclibc/x86_64/0000775000175000017500000000000015105742312020570 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs0000644000175000017500000002452415105742312021722 0ustar bdrungbdrung//! Definitions for uclibc on 64bit systems use crate::off64_t; use crate::prelude::*; pub type blkcnt_t = i64; pub type blksize_t = i64; pub type clock_t = i64; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type fsword_t = c_long; pub type ino_t = c_ulong; pub type nlink_t = c_uint; pub type off_t = c_long; // [uClibc docs] Note stat64 has the same shape as stat for x86-64. pub type stat64 = stat; pub type suseconds_t = c_long; pub type time_t = c_int; pub type wchar_t = c_int; pub type fsblkcnt64_t = u64; pub type fsfilcnt64_t = u64; pub type __u64 = c_ulong; pub type __s64 = c_long; s! { pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, // read / write __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } #[cfg(not(target_os = "l4re"))] pub struct pthread_attr_t { __detachstate: c_int, __schedpolicy: c_int, __schedparam: __sched_param, __inheritsched: c_int, __scope: c_int, __guardsize: size_t, __stackaddr_set: c_int, __stackaddr: *mut c_void, // better don't use it __stacksize: size_t, } pub struct __sched_param { __sched_priority: c_int, } pub struct siginfo_t { si_signo: c_int, // signal number si_errno: c_int, // if not zero: error value of signal, see errno.h si_code: c_int, // signal code pub _pad: [c_int; 28], // unported union _align: [usize; 0], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, // segment size in bytes pub shm_atime: crate::time_t, // time of last shmat() pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused1: c_ulong, __unused2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __ignored1: c_ulong, __ignored2: c_ulong, } pub struct sockaddr { pub sa_family: crate::sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in { pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_in6 { pub sin6_family: crate::sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } /* ------------------------------------------------------------ * definitions below are *unverified* and might **break** the software */ // pub struct in_addr { // pub s_addr: in_addr_t, // } // // pub struct in6_addr { // pub s6_addr: [u8; 16], // } pub struct stat { pub st_dev: c_ulong, pub st_ino: crate::ino_t, // According to uclibc/libc/sysdeps/linux/x86_64/bits/stat.h, order of // nlink and mode are swapped on 64 bit systems. pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulong, // dev_t pub st_size: off_t, // file size pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_ulong, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_ulong, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_ulong, st_pad4: [c_long; 3], } pub struct sigaction { pub sa_handler: crate::sighandler_t, pub sa_flags: c_ulong, pub sa_restorer: Option, pub sa_mask: crate::sigset_t, } pub struct stack_t { // FIXME(ulibc) pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct statfs { // FIXME(ulibc) pub f_type: fsword_t, pub f_bsize: fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: fsword_t, pub f_frsize: fsword_t, f_spare: [fsword_t; 5], } pub struct statfs64 { pub f_type: c_int, pub f_bsize: c_int, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_int, pub f_frsize: c_int, pub f_flags: c_int, pub f_spare: [c_int; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct msghdr { // FIXME(ulibc) pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: size_t, pub msg_control: *mut c_void, pub msg_controllen: size_t, pub msg_flags: c_int, } pub struct termios { // FIXME(ulibc) pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], } pub struct sigset_t { // FIXME(ulibc) __val: [c_ulong; 16], } pub struct sysinfo { // FIXME(ulibc) pub uptime: c_long, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub _f: [c_char; 0], } pub struct glob_t { // FIXME(ulibc) pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct cpu_set_t { // FIXME(ulibc) #[cfg(target_pointer_width = "32")] bits: [u32; 32], #[cfg(target_pointer_width = "64")] bits: [u64; 16], } pub struct fsid_t { // FIXME(ulibc) __val: [c_int; 2], } // FIXME(1.0): this is actually a union pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [c_char; 16], #[cfg(target_pointer_width = "64")] __size: [c_char; 32], __align: [c_long; 0], } pub struct cmsghdr { pub cmsg_len: size_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct dirent { pub d_ino: crate::ino64_t, pub d_off: off64_t, pub d_reclen: u16, pub d_type: u8, pub d_name: [c_char; 256], } } // constants pub const ENAMETOOLONG: c_int = 36; // File name too long pub const ENOTEMPTY: c_int = 39; // Directory not empty pub const ELOOP: c_int = 40; // Too many symbolic links encountered pub const EADDRINUSE: c_int = 98; // Address already in use pub const EADDRNOTAVAIL: c_int = 99; // Cannot assign requested address pub const ENETDOWN: c_int = 100; // Network is down pub const ENETUNREACH: c_int = 101; // Network is unreachable pub const ECONNABORTED: c_int = 103; // Software caused connection abort pub const ECONNREFUSED: c_int = 111; // Connection refused pub const ECONNRESET: c_int = 104; // Connection reset by peer pub const EDEADLK: c_int = 35; // Resource deadlock would occur pub const ENOSYS: c_int = 38; // Function not implemented pub const ENOTCONN: c_int = 107; // Transport endpoint is not connected pub const ETIMEDOUT: c_int = 110; // connection timed out pub const ESTALE: c_int = 116; // Stale file handle pub const EHOSTUNREACH: c_int = 113; // No route to host pub const EDQUOT: c_int = 122; // Quota exceeded pub const EOPNOTSUPP: c_int = 0x5f; pub const ENODATA: c_int = 0x3d; pub const O_APPEND: c_int = 0o2000; pub const O_ACCMODE: c_int = 0o003; pub const O_CLOEXEC: c_int = 0x80000; pub const O_CREAT: c_int = 0100; pub const O_DIRECTORY: c_int = 0o200000; pub const O_EXCL: c_int = 0o200; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_NONBLOCK: c_int = 0o4000; pub const O_TRUNC: c_int = 0o1000; pub const NCCS: usize = 32; pub const SIG_SETMASK: c_int = 2; // Set the set of blocked signals pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const SOCK_DGRAM: c_int = 2; // connectionless, unreliable datagrams pub const SOCK_STREAM: c_int = 1; // …/common/bits/socket_type.h pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const PIDFD_NONBLOCK: c_int = 0o4000; cfg_if! { if #[cfg(target_os = "l4re")] { mod l4re; pub use self::l4re::*; } else { mod other; pub use other::*; } } libc/src/unix/linux_like/linux/uclibc/x86_64/l4re.rs0000644000175000017500000000345715105742312022013 0ustar bdrungbdrunguse crate::prelude::*; /// L4Re specifics /// This module contains definitions required by various L4Re libc backends. /// Some of them are formally not part of the libc, but are a dependency of the /// libc and hence we should provide them here. pub type l4_umword_t = c_ulong; // Unsigned machine word. pub type pthread_t = *mut c_void; s! { /// CPU sets. pub struct l4_sched_cpu_set_t { // from the L4Re docs /// Combination of granularity and offset. /// /// The granularity defines how many CPUs each bit in map describes. /// The offset is the number of the first CPU described by the first /// bit in the bitmap. /// offset must be a multiple of 2^graularity. /// /// | MSB | LSB | /// | ---------------- | ------------------- | /// | 8bit granularity | 24bit offset .. | gran_offset: l4_umword_t, /// Bitmap of CPUs. map: l4_umword_t, } } #[allow(missing_debug_implementations)] pub struct pthread_attr_t { pub __detachstate: c_int, pub __schedpolicy: c_int, pub __schedparam: super::__sched_param, pub __inheritsched: c_int, pub __scope: c_int, pub __guardsize: size_t, pub __stackaddr_set: c_int, pub __stackaddr: *mut c_void, // better don't use it pub __stacksize: size_t, // L4Re specifics pub affinity: l4_sched_cpu_set_t, pub create_flags: c_uint, } // L4Re requires a min stack size of 64k; that isn't defined in uClibc, but // somewhere in the core libraries. uClibc wants 16k, but that's not enough. pub const PTHREAD_STACK_MIN: usize = 65536; // Misc other constants required for building. pub const SIGIO: c_int = 29; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; libc/src/unix/linux_like/linux/uclibc/x86_64/other.rs0000644000175000017500000000030215105742312022250 0ustar bdrungbdrunguse crate::prelude::*; // Thestyle checker discourages the use of #[cfg], so this has to go into a // separate module pub type pthread_t = c_ulong; pub const PTHREAD_STACK_MIN: usize = 16384; libc/src/unix/linux_like/linux/uclibc/arm/0000775000175000017500000000000015105742312020411 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/uclibc/arm/mod.rs0000644000175000017500000007664415105742312021555 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type wchar_t = c_uint; pub type time_t = c_long; pub type clock_t = c_long; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type ino_t = c_ulong; pub type off_t = c_long; pub type pthread_t = c_ulong; pub type suseconds_t = c_long; pub type nlink_t = c_uint; pub type blksize_t = c_long; pub type blkcnt_t = c_long; pub type fsblkcnt64_t = u64; pub type fsfilcnt64_t = u64; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct cmsghdr { pub cmsg_len: size_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct pthread_attr_t { __size: [c_long; 9], } pub struct stat { pub st_dev: c_ulonglong, __pad1: c_ushort, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulonglong, __pad2: c_ushort, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused4: c_ulong, __unused5: c_ulong, } pub struct stat64 { pub st_dev: c_ulonglong, pub __pad1: c_uint, pub __st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulonglong, pub __pad2: c_uint, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino64_t, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct sysinfo { pub uptime: c_long, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub _f: [c_char; 8], } pub struct statfs { pub f_type: c_int, pub f_bsize: c_int, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_int, pub f_frsize: c_int, pub f_flags: c_int, pub f_spare: [c_int; 4], } pub struct statfs64 { pub f_type: c_int, pub f_bsize: c_int, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_int, pub f_frsize: c_int, pub f_flags: c_int, pub f_spare: [c_int; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct sigset_t { __val: [c_ulong; 2], } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_flags: c_ulong, pub sa_restorer: Option, pub sa_mask: sigset_t, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, pub _pad: [c_int; 29], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __unused1: c_ulong, pub msg_rtime: crate::time_t, __unused2: c_ulong, pub msg_ctime: crate::time_t, __unused3: c_ulong, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, __unused1: c_ulong, pub shm_dtime: crate::time_t, __unused2: c_ulong, pub shm_ctime: crate::time_t, __unused3: c_ulong, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } // FIXME(1.0) this is actually a union #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [c_char; 16], #[cfg(target_pointer_width = "64")] __size: [c_char; 32], } } pub const O_CLOEXEC: c_int = 0o2000000; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 36; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_COND_COMPAT_T: usize = 12; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const NCCS: usize = 32; // I wasn't able to find those constants // in uclibc build environment for armv7 pub const MAP_HUGETLB: c_int = 0x040000; // from linux/other/mod.rs // autogenerated constants with hand tuned types pub const B0: crate::speed_t = 0; pub const B1000000: crate::speed_t = 0x1008; pub const B110: crate::speed_t = 0x3; pub const B115200: crate::speed_t = 0x1002; pub const B1152000: crate::speed_t = 0x1009; pub const B1200: crate::speed_t = 0x9; pub const B134: crate::speed_t = 0x4; pub const B150: crate::speed_t = 0x5; pub const B1500000: crate::speed_t = 0x100a; pub const B1800: crate::speed_t = 0xa; pub const B19200: crate::speed_t = 0xe; pub const B200: crate::speed_t = 0x6; pub const B2000000: crate::speed_t = 0x100b; pub const B230400: crate::speed_t = 0x1003; pub const B2400: crate::speed_t = 0xb; pub const B2500000: crate::speed_t = 0x100c; pub const B300: crate::speed_t = 0x7; pub const B3000000: crate::speed_t = 0x100d; pub const B3500000: crate::speed_t = 0x100e; pub const B38400: crate::speed_t = 0xf; pub const B4000000: crate::speed_t = 0x100f; pub const B460800: crate::speed_t = 0x1004; pub const B4800: crate::speed_t = 0xc; pub const B50: crate::speed_t = 0x1; pub const B500000: crate::speed_t = 0x1005; pub const B57600: crate::speed_t = 0x1001; pub const B576000: crate::speed_t = 0x1006; pub const B600: crate::speed_t = 0x8; pub const B75: crate::speed_t = 0x2; pub const B921600: crate::speed_t = 0x1007; pub const B9600: crate::speed_t = 0xd; pub const BS1: c_int = 0x2000; pub const BSDLY: c_int = 0x2000; pub const CBAUD: crate::tcflag_t = 0x100f; pub const CBAUDEX: crate::tcflag_t = 0x1000; pub const CIBAUD: crate::tcflag_t = 0x100f0000; pub const CLOCAL: crate::tcflag_t = 0x800; pub const CPU_SETSIZE: c_int = 0x400; pub const CR1: c_int = 0x200; pub const CR2: c_int = 0x400; pub const CR3: c_int = 0x600; pub const CRDLY: c_int = 0x600; pub const CREAD: crate::tcflag_t = 0x80; pub const CS6: crate::tcflag_t = 0x10; pub const CS7: crate::tcflag_t = 0x20; pub const CS8: crate::tcflag_t = 0x30; pub const CSIZE: crate::tcflag_t = 0x30; pub const CSTOPB: crate::tcflag_t = 0x40; pub const EADDRINUSE: c_int = 0x62; pub const EADDRNOTAVAIL: c_int = 0x63; pub const EADV: c_int = 0x44; pub const EAFNOSUPPORT: c_int = 0x61; pub const EALREADY: c_int = 0x72; pub const EBADE: c_int = 0x34; pub const EBADFD: c_int = 0x4d; pub const EBADMSG: c_int = 0x4a; pub const EBADR: c_int = 0x35; pub const EBADRQC: c_int = 0x38; pub const EBADSLT: c_int = 0x39; pub const EBFONT: c_int = 0x3b; pub const ECANCELED: c_int = 0x7d; pub const ECHOCTL: crate::tcflag_t = 0x200; pub const ECHOE: crate::tcflag_t = 0x10; pub const ECHOK: crate::tcflag_t = 0x20; pub const ECHOKE: crate::tcflag_t = 0x800; pub const ECHONL: crate::tcflag_t = 0x40; pub const ECHOPRT: crate::tcflag_t = 0x400; pub const ECHRNG: c_int = 0x2c; pub const ECOMM: c_int = 0x46; pub const ECONNABORTED: c_int = 0x67; pub const ECONNREFUSED: c_int = 0x6f; pub const ECONNRESET: c_int = 0x68; pub const EDEADLK: c_int = 0x23; pub const EDESTADDRREQ: c_int = 0x59; pub const EDOTDOT: c_int = 0x49; pub const EDQUOT: c_int = 0x7a; pub const EFD_CLOEXEC: c_int = 0x80000; pub const EFD_NONBLOCK: c_int = 0x800; pub const EHOSTDOWN: c_int = 0x70; pub const EHOSTUNREACH: c_int = 0x71; pub const EHWPOISON: c_int = 0x85; pub const EIDRM: c_int = 0x2b; pub const EILSEQ: c_int = 0x54; pub const EINPROGRESS: c_int = 0x73; pub const EISCONN: c_int = 0x6a; pub const EISNAM: c_int = 0x78; pub const EKEYEXPIRED: c_int = 0x7f; pub const EKEYREJECTED: c_int = 0x81; pub const EKEYREVOKED: c_int = 0x80; pub const EL2HLT: c_int = 0x33; pub const EL2NSYNC: c_int = 0x2d; pub const EL3HLT: c_int = 0x2e; pub const EL3RST: c_int = 0x2f; pub const ELIBACC: c_int = 0x4f; pub const ELIBBAD: c_int = 0x50; pub const ELIBEXEC: c_int = 0x53; pub const ELIBMAX: c_int = 0x52; pub const ELIBSCN: c_int = 0x51; pub const ELNRNG: c_int = 0x30; pub const ELOOP: c_int = 0x28; pub const EMEDIUMTYPE: c_int = 0x7c; pub const EMSGSIZE: c_int = 0x5a; pub const EMULTIHOP: c_int = 0x48; pub const ENAMETOOLONG: c_int = 0x24; pub const ENAVAIL: c_int = 0x77; pub const ENETDOWN: c_int = 0x64; pub const ENETRESET: c_int = 0x66; pub const ENETUNREACH: c_int = 0x65; pub const ENOANO: c_int = 0x37; pub const ENOBUFS: c_int = 0x69; pub const ENOCSI: c_int = 0x32; pub const ENODATA: c_int = 0x3d; pub const ENOKEY: c_int = 0x7e; pub const ENOLCK: c_int = 0x25; pub const ENOLINK: c_int = 0x43; pub const ENOMEDIUM: c_int = 0x7b; pub const ENOMSG: c_int = 0x2a; pub const ENONET: c_int = 0x40; pub const ENOPKG: c_int = 0x41; pub const ENOPROTOOPT: c_int = 0x5c; pub const ENOSR: c_int = 0x3f; pub const ENOSTR: c_int = 0x3c; pub const ENOSYS: c_int = 0x26; pub const ENOTCONN: c_int = 0x6b; pub const ENOTEMPTY: c_int = 0x27; pub const ENOTNAM: c_int = 0x76; pub const ENOTRECOVERABLE: c_int = 0x83; pub const ENOTSOCK: c_int = 0x58; pub const ENOTUNIQ: c_int = 0x4c; pub const EOPNOTSUPP: c_int = 0x5f; pub const EOVERFLOW: c_int = 0x4b; pub const EOWNERDEAD: c_int = 0x82; pub const EPFNOSUPPORT: c_int = 0x60; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EPROTO: c_int = 0x47; pub const EPROTONOSUPPORT: c_int = 0x5d; pub const EPROTOTYPE: c_int = 0x5b; pub const EREMCHG: c_int = 0x4e; pub const EREMOTE: c_int = 0x42; pub const EREMOTEIO: c_int = 0x79; pub const ERESTART: c_int = 0x55; pub const ERFKILL: c_int = 0x84; pub const ESHUTDOWN: c_int = 0x6c; pub const ESOCKTNOSUPPORT: c_int = 0x5e; pub const ESRMNT: c_int = 0x45; pub const ESTALE: c_int = 0x74; pub const ESTRPIPE: c_int = 0x56; pub const ETIME: c_int = 0x3e; pub const ETIMEDOUT: c_int = 0x6e; pub const ETOOMANYREFS: c_int = 0x6d; pub const EUCLEAN: c_int = 0x75; pub const EUNATCH: c_int = 0x31; pub const EUSERS: c_int = 0x57; pub const EXFULL: c_int = 0x36; pub const FF1: c_int = 0x8000; pub const FFDLY: c_int = 0x8000; pub const FLUSHO: crate::tcflag_t = 0x1000; pub const F_GETLK: c_int = 0x5; pub const F_SETLK: c_int = 0x6; pub const F_SETLKW: c_int = 0x7; pub const HUPCL: crate::tcflag_t = 0x400; pub const ICANON: crate::tcflag_t = 0x2; pub const IEXTEN: crate::tcflag_t = 0x8000; pub const ISIG: crate::tcflag_t = 0x1; pub const IXOFF: crate::tcflag_t = 0x1000; pub const IXON: crate::tcflag_t = 0x400; pub const MAP_ANON: c_int = 0x20; pub const MAP_ANONYMOUS: c_int = 0x20; pub const MAP_DENYWRITE: c_int = 0x800; pub const MAP_EXECUTABLE: c_int = 0x1000; pub const MAP_GROWSDOWN: c_int = 0x100; pub const MAP_LOCKED: c_int = 0x2000; pub const MAP_NONBLOCK: c_int = 0x10000; pub const MAP_NORESERVE: c_int = 0x4000; pub const MAP_POPULATE: c_int = 0x8000; pub const MAP_STACK: c_int = 0x20000; pub const NLDLY: crate::tcflag_t = 0x100; pub const NOFLSH: crate::tcflag_t = 0x80; pub const OLCUC: crate::tcflag_t = 0x2; pub const ONLCR: crate::tcflag_t = 0x4; pub const O_ACCMODE: c_int = 0x3; pub const O_APPEND: c_int = 0x400; pub const O_ASYNC: c_int = 0o20000; pub const O_CREAT: c_int = 0x40; pub const O_DIRECT: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_DSYNC: c_int = O_SYNC; pub const O_EXCL: c_int = 0x80; pub const O_FSYNC: c_int = O_SYNC; pub const O_LARGEFILE: c_int = 0o400000; pub const O_NDELAY: c_int = O_NONBLOCK; pub const O_NOATIME: c_int = 0o1000000; pub const O_NOCTTY: c_int = 0x100; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_NONBLOCK: c_int = 0x800; pub const O_PATH: c_int = 0o10000000; pub const O_RSYNC: c_int = O_SYNC; pub const O_SYNC: c_int = 0o10000; pub const O_TRUNC: c_int = 0x200; pub const PARENB: crate::tcflag_t = 0x100; pub const PARODD: crate::tcflag_t = 0x200; pub const PENDIN: crate::tcflag_t = 0x4000; pub const POLLWRBAND: c_short = 0x200; pub const POLLWRNORM: c_short = 0x100; pub const PTHREAD_STACK_MIN: size_t = 16384; pub const RTLD_GLOBAL: c_int = 0x00100; pub const PIDFD_NONBLOCK: c_int = 0x800; // These are typed unsigned to match sigaction pub const SA_NOCLDSTOP: c_ulong = 0x1; pub const SA_NOCLDWAIT: c_ulong = 0x2; pub const SA_SIGINFO: c_ulong = 0x4; pub const SA_NODEFER: c_ulong = 0x40000000; pub const SA_ONSTACK: c_ulong = 0x8000000; pub const SA_RESETHAND: c_ulong = 0x80000000; pub const SA_RESTART: c_ulong = 0x10000000; pub const SFD_CLOEXEC: c_int = 0x80000; pub const SFD_NONBLOCK: c_int = 0x800; pub const SIGBUS: c_int = 0x7; pub const SIGCHLD: c_int = 0x11; pub const SIGCONT: c_int = 0x12; pub const SIGIO: c_int = 0x1d; pub const SIGPROF: c_int = 0x1b; pub const SIGPWR: c_int = 0x1e; pub const SIGSTKFLT: c_int = 0x10; pub const SIGSTKSZ: size_t = 8192; pub const SIGSTOP: c_int = 0x13; pub const SIGSYS: c_int = 0x1f; pub const SIGTSTP: c_int = 0x14; pub const SIGTTIN: c_int = 0x15; pub const SIGTTOU: c_int = 0x16; pub const SIGURG: c_int = 0x17; pub const SIGUSR1: c_int = 0xa; pub const SIGUSR2: c_int = 0xc; pub const SIGVTALRM: c_int = 0x1a; pub const SIGWINCH: c_int = 0x1c; pub const SIGXCPU: c_int = 0x18; pub const SIGXFSZ: c_int = 0x19; pub const SIG_BLOCK: c_int = 0; pub const SIG_SETMASK: c_int = 0x2; pub const SIG_UNBLOCK: c_int = 0x1; pub const SOCK_DGRAM: c_int = 0x2; pub const SOCK_NONBLOCK: c_int = 0o0004000; pub const SOCK_SEQPACKET: c_int = 0x5; pub const SOCK_STREAM: c_int = 0x1; pub const TAB1: c_int = 0x800; pub const TAB2: c_int = 0x1000; pub const TAB3: c_int = 0x1800; pub const TABDLY: c_int = 0x1800; pub const TCSADRAIN: c_int = 0x1; pub const TCSAFLUSH: c_int = 0x2; pub const TCSANOW: c_int = 0; pub const TOSTOP: crate::tcflag_t = 0x100; pub const VDISCARD: usize = 0xd; pub const VEOF: usize = 0x4; pub const VEOL: usize = 0xb; pub const VEOL2: usize = 0x10; pub const VMIN: usize = 0x6; pub const VREPRINT: usize = 0xc; pub const VSTART: usize = 0x8; pub const VSTOP: usize = 0x9; pub const VSUSP: usize = 0xa; pub const VSWTC: usize = 0x7; pub const VT1: c_int = 0x4000; pub const VTDLY: c_int = 0x4000; pub const VTIME: usize = 0x5; pub const VWERASE: usize = 0xe; pub const XTABS: crate::tcflag_t = 0x1800; pub const MADV_SOFT_OFFLINE: c_int = 101; // Syscall table is copied from src/unix/notbsd/linux/musl/b32/arm.rs pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_ptrace: c_long = 26; pub const SYS_pause: c_long = 29; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_setpgid: c_long = 57; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_symlink: c_long = 83; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_vhangup: c_long = 111; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_setresgid: c_long = 170; pub const SYS_getresgid: c_long = 171; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_chown: c_long = 182; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_vfork: c_long = 190; pub const SYS_ugetrlimit: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_lchown32: c_long = 198; pub const SYS_getuid32: c_long = 199; pub const SYS_getgid32: c_long = 200; pub const SYS_geteuid32: c_long = 201; pub const SYS_getegid32: c_long = 202; pub const SYS_setreuid32: c_long = 203; pub const SYS_setregid32: c_long = 204; pub const SYS_getgroups32: c_long = 205; pub const SYS_setgroups32: c_long = 206; pub const SYS_fchown32: c_long = 207; pub const SYS_setresuid32: c_long = 208; pub const SYS_getresuid32: c_long = 209; pub const SYS_setresgid32: c_long = 210; pub const SYS_getresgid32: c_long = 211; pub const SYS_chown32: c_long = 212; pub const SYS_setuid32: c_long = 213; pub const SYS_setgid32: c_long = 214; pub const SYS_setfsuid32: c_long = 215; pub const SYS_setfsgid32: c_long = 216; pub const SYS_getdents64: c_long = 217; pub const SYS_pivot_root: c_long = 218; pub const SYS_mincore: c_long = 219; pub const SYS_madvise: c_long = 220; pub const SYS_fcntl64: c_long = 221; pub const SYS_gettid: c_long = 224; pub const SYS_readahead: c_long = 225; pub const SYS_setxattr: c_long = 226; pub const SYS_lsetxattr: c_long = 227; pub const SYS_fsetxattr: c_long = 228; pub const SYS_getxattr: c_long = 229; pub const SYS_lgetxattr: c_long = 230; pub const SYS_fgetxattr: c_long = 231; pub const SYS_listxattr: c_long = 232; pub const SYS_llistxattr: c_long = 233; pub const SYS_flistxattr: c_long = 234; pub const SYS_removexattr: c_long = 235; pub const SYS_lremovexattr: c_long = 236; pub const SYS_fremovexattr: c_long = 237; pub const SYS_tkill: c_long = 238; pub const SYS_sendfile64: c_long = 239; pub const SYS_futex: c_long = 240; pub const SYS_sched_setaffinity: c_long = 241; pub const SYS_sched_getaffinity: c_long = 242; pub const SYS_io_setup: c_long = 243; pub const SYS_io_destroy: c_long = 244; pub const SYS_io_getevents: c_long = 245; pub const SYS_io_submit: c_long = 246; pub const SYS_io_cancel: c_long = 247; pub const SYS_exit_group: c_long = 248; pub const SYS_lookup_dcookie: c_long = 249; pub const SYS_epoll_create: c_long = 250; pub const SYS_epoll_ctl: c_long = 251; pub const SYS_epoll_wait: c_long = 252; pub const SYS_remap_file_pages: c_long = 253; pub const SYS_set_tid_address: c_long = 256; pub const SYS_timer_create: c_long = 257; pub const SYS_timer_settime: c_long = 258; pub const SYS_timer_gettime: c_long = 259; pub const SYS_timer_getoverrun: c_long = 260; pub const SYS_timer_delete: c_long = 261; pub const SYS_clock_settime: c_long = 262; pub const SYS_clock_gettime: c_long = 263; pub const SYS_clock_getres: c_long = 264; pub const SYS_clock_nanosleep: c_long = 265; pub const SYS_statfs64: c_long = 266; pub const SYS_fstatfs64: c_long = 267; pub const SYS_tgkill: c_long = 268; pub const SYS_utimes: c_long = 269; pub const SYS_pciconfig_iobase: c_long = 271; pub const SYS_pciconfig_read: c_long = 272; pub const SYS_pciconfig_write: c_long = 273; pub const SYS_mq_open: c_long = 274; pub const SYS_mq_unlink: c_long = 275; pub const SYS_mq_timedsend: c_long = 276; pub const SYS_mq_timedreceive: c_long = 277; pub const SYS_mq_notify: c_long = 278; pub const SYS_mq_getsetattr: c_long = 279; pub const SYS_waitid: c_long = 280; pub const SYS_socket: c_long = 281; pub const SYS_bind: c_long = 282; pub const SYS_connect: c_long = 283; pub const SYS_listen: c_long = 284; pub const SYS_accept: c_long = 285; pub const SYS_getsockname: c_long = 286; pub const SYS_getpeername: c_long = 287; pub const SYS_socketpair: c_long = 288; pub const SYS_send: c_long = 289; pub const SYS_sendto: c_long = 290; pub const SYS_recv: c_long = 291; pub const SYS_recvfrom: c_long = 292; pub const SYS_shutdown: c_long = 293; pub const SYS_setsockopt: c_long = 294; pub const SYS_getsockopt: c_long = 295; pub const SYS_sendmsg: c_long = 296; pub const SYS_recvmsg: c_long = 297; pub const SYS_semop: c_long = 298; pub const SYS_semget: c_long = 299; pub const SYS_semctl: c_long = 300; pub const SYS_msgsnd: c_long = 301; pub const SYS_msgrcv: c_long = 302; pub const SYS_msgget: c_long = 303; pub const SYS_msgctl: c_long = 304; pub const SYS_shmat: c_long = 305; pub const SYS_shmdt: c_long = 306; pub const SYS_shmget: c_long = 307; pub const SYS_shmctl: c_long = 308; pub const SYS_add_key: c_long = 309; pub const SYS_request_key: c_long = 310; pub const SYS_keyctl: c_long = 311; pub const SYS_semtimedop: c_long = 312; pub const SYS_vserver: c_long = 313; pub const SYS_ioprio_set: c_long = 314; pub const SYS_ioprio_get: c_long = 315; pub const SYS_inotify_init: c_long = 316; pub const SYS_inotify_add_watch: c_long = 317; pub const SYS_inotify_rm_watch: c_long = 318; pub const SYS_mbind: c_long = 319; pub const SYS_get_mempolicy: c_long = 320; pub const SYS_set_mempolicy: c_long = 321; pub const SYS_openat: c_long = 322; pub const SYS_mkdirat: c_long = 323; pub const SYS_mknodat: c_long = 324; pub const SYS_fchownat: c_long = 325; pub const SYS_futimesat: c_long = 326; pub const SYS_fstatat64: c_long = 327; pub const SYS_unlinkat: c_long = 328; pub const SYS_renameat: c_long = 329; pub const SYS_linkat: c_long = 330; pub const SYS_symlinkat: c_long = 331; pub const SYS_readlinkat: c_long = 332; pub const SYS_fchmodat: c_long = 333; pub const SYS_faccessat: c_long = 334; pub const SYS_pselect6: c_long = 335; pub const SYS_ppoll: c_long = 336; pub const SYS_unshare: c_long = 337; pub const SYS_set_robust_list: c_long = 338; pub const SYS_get_robust_list: c_long = 339; pub const SYS_splice: c_long = 340; pub const SYS_tee: c_long = 342; pub const SYS_vmsplice: c_long = 343; pub const SYS_move_pages: c_long = 344; pub const SYS_getcpu: c_long = 345; pub const SYS_epoll_pwait: c_long = 346; pub const SYS_kexec_load: c_long = 347; pub const SYS_utimensat: c_long = 348; pub const SYS_signalfd: c_long = 349; pub const SYS_timerfd_create: c_long = 350; pub const SYS_eventfd: c_long = 351; pub const SYS_fallocate: c_long = 352; pub const SYS_timerfd_settime: c_long = 353; pub const SYS_timerfd_gettime: c_long = 354; pub const SYS_signalfd4: c_long = 355; pub const SYS_eventfd2: c_long = 356; pub const SYS_epoll_create1: c_long = 357; pub const SYS_dup3: c_long = 358; pub const SYS_pipe2: c_long = 359; pub const SYS_inotify_init1: c_long = 360; pub const SYS_preadv: c_long = 361; pub const SYS_pwritev: c_long = 362; pub const SYS_rt_tgsigqueueinfo: c_long = 363; pub const SYS_perf_event_open: c_long = 364; pub const SYS_recvmmsg: c_long = 365; pub const SYS_accept4: c_long = 366; pub const SYS_fanotify_init: c_long = 367; pub const SYS_fanotify_mark: c_long = 368; pub const SYS_prlimit64: c_long = 369; pub const SYS_name_to_handle_at: c_long = 370; pub const SYS_open_by_handle_at: c_long = 371; pub const SYS_clock_adjtime: c_long = 372; pub const SYS_syncfs: c_long = 373; pub const SYS_sendmmsg: c_long = 374; pub const SYS_setns: c_long = 375; pub const SYS_process_vm_readv: c_long = 376; pub const SYS_process_vm_writev: c_long = 377; pub const SYS_kcmp: c_long = 378; pub const SYS_finit_module: c_long = 379; pub const SYS_sched_setattr: c_long = 380; pub const SYS_sched_getattr: c_long = 381; pub const SYS_renameat2: c_long = 382; pub const SYS_seccomp: c_long = 383; pub const SYS_getrandom: c_long = 384; pub const SYS_memfd_create: c_long = 385; pub const SYS_bpf: c_long = 386; pub const SYS_execveat: c_long = 387; pub const SYS_userfaultfd: c_long = 388; pub const SYS_membarrier: c_long = 389; pub const SYS_mlock2: c_long = 390; pub const SYS_copy_file_range: c_long = 391; pub const SYS_preadv2: c_long = 392; pub const SYS_pwritev2: c_long = 393; pub const SYS_pkey_mprotect: c_long = 394; pub const SYS_pkey_alloc: c_long = 395; pub const SYS_pkey_free: c_long = 396; // FIXME(linux): should be a `c_long` too, but a bug slipped in. pub const SYS_statx: c_int = 397; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; libc/src/unix/linux_like/linux/uclibc/mips/0000775000175000017500000000000015105742312020602 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/uclibc/mips/mod.rs0000644000175000017500000002412515105742312021731 0ustar bdrungbdrunguse crate::prelude::*; pub type pthread_t = c_ulong; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_CLOEXEC: c_int = 0x80000; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_uint = 0x40000000; pub const SA_RESETHAND: c_uint = 0x80000000; pub const SA_RESTART: c_uint = 0x10000000; pub const SA_NOCLDSTOP: c_uint = 0x00000001; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const TMP_MAX: c_uint = 238328; pub const _SC_2_C_VERSION: c_int = 96; pub const O_ACCMODE: c_int = 3; pub const O_DIRECT: c_int = 0x8000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_NOATIME: c_int = 0x40000; pub const O_PATH: c_int = 0o010000000; pub const O_APPEND: c_int = 8; pub const O_CREAT: c_int = 256; pub const O_EXCL: c_int = 1024; pub const O_NOCTTY: c_int = 2048; pub const O_NONBLOCK: c_int = 128; pub const O_SYNC: c_int = 0x10; pub const O_RSYNC: c_int = 0x10; pub const O_DSYNC: c_int = 0x10; pub const O_FSYNC: c_int = 0x10; pub const O_ASYNC: c_int = 0x1000; pub const O_LARGEFILE: c_int = 0x2000; pub const O_NDELAY: c_int = 0x80; pub const SOCK_NONBLOCK: c_int = 128; pub const PIDFD_NONBLOCK: c_int = 128; pub const EDEADLK: c_int = 45; pub const ENAMETOOLONG: c_int = 78; pub const ENOLCK: c_int = 46; pub const ENOSYS: c_int = 89; pub const ENOTEMPTY: c_int = 93; pub const ELOOP: c_int = 90; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EBADE: c_int = 50; pub const EBADR: c_int = 51; pub const EXFULL: c_int = 52; pub const FFDLY: c_int = 0o0100000; pub const ENOANO: c_int = 53; pub const EBADRQC: c_int = 54; pub const EBADSLT: c_int = 55; pub const EMULTIHOP: c_int = 74; pub const EOVERFLOW: c_int = 79; pub const ENOTUNIQ: c_int = 80; pub const EBADFD: c_int = 81; pub const EBADMSG: c_int = 77; pub const EREMCHG: c_int = 82; pub const ELIBACC: c_int = 83; pub const ELIBBAD: c_int = 84; pub const ELIBSCN: c_int = 85; pub const ELIBMAX: c_int = 86; pub const ELIBEXEC: c_int = 87; pub const EILSEQ: c_int = 88; pub const ERESTART: c_int = 91; pub const ESTRPIPE: c_int = 92; pub const EUSERS: c_int = 94; pub const ENOTSOCK: c_int = 95; pub const EDESTADDRREQ: c_int = 96; pub const EMSGSIZE: c_int = 97; pub const EPROTOTYPE: c_int = 98; pub const ENOPROTOOPT: c_int = 99; pub const EPROTONOSUPPORT: c_int = 120; pub const ESOCKTNOSUPPORT: c_int = 121; pub const EOPNOTSUPP: c_int = 122; pub const EPFNOSUPPORT: c_int = 123; pub const EAFNOSUPPORT: c_int = 124; pub const EADDRINUSE: c_int = 125; pub const EADDRNOTAVAIL: c_int = 126; pub const ENETDOWN: c_int = 127; pub const ENETUNREACH: c_int = 128; pub const ENETRESET: c_int = 129; pub const ECONNABORTED: c_int = 130; pub const ECONNRESET: c_int = 131; pub const ENOBUFS: c_int = 132; pub const EISCONN: c_int = 133; pub const ENOTCONN: c_int = 134; pub const ESHUTDOWN: c_int = 143; pub const ETOOMANYREFS: c_int = 144; pub const ETIMEDOUT: c_int = 145; pub const ECONNREFUSED: c_int = 146; pub const EHOSTDOWN: c_int = 147; pub const EHOSTUNREACH: c_int = 148; pub const EALREADY: c_int = 149; pub const EINPROGRESS: c_int = 150; pub const ESTALE: c_int = 151; pub const EUCLEAN: c_int = 135; pub const ENOTNAM: c_int = 137; pub const ENAVAIL: c_int = 138; pub const EISNAM: c_int = 139; pub const EREMOTEIO: c_int = 140; pub const EDQUOT: c_int = 1133; pub const ENOMEDIUM: c_int = 159; pub const EMEDIUMTYPE: c_int = 160; pub const ECANCELED: c_int = 158; pub const ENOKEY: c_int = 161; pub const EKEYEXPIRED: c_int = 162; pub const EKEYREVOKED: c_int = 163; pub const EKEYREJECTED: c_int = 164; pub const EOWNERDEAD: c_int = 165; pub const ENOTRECOVERABLE: c_int = 166; pub const ERFKILL: c_int = 167; pub const MAP_NORESERVE: c_int = 0x400; pub const MAP_ANON: c_int = 0x800; pub const MAP_ANONYMOUS: c_int = 0x800; pub const MAP_GROWSDOWN: c_int = 0x1000; pub const MAP_DENYWRITE: c_int = 0x2000; pub const MAP_EXECUTABLE: c_int = 0x4000; pub const MAP_LOCKED: c_int = 0x8000; pub const MAP_POPULATE: c_int = 0x10000; pub const MAP_NONBLOCK: c_int = 0x20000; pub const MAP_STACK: c_int = 0x40000; pub const NLDLY: crate::tcflag_t = 0o0000400; pub const SOCK_STREAM: c_int = 2; pub const SOCK_DGRAM: c_int = 1; pub const SOCK_SEQPACKET: c_int = 5; pub const SA_ONSTACK: c_uint = 0x08000000; pub const SA_SIGINFO: c_uint = 0x00000008; pub const SA_NOCLDWAIT: c_int = 0x00010000; pub const SIGCHLD: c_int = 18; pub const SIGBUS: c_int = 10; pub const SIGTTIN: c_int = 26; pub const SIGTTOU: c_int = 27; pub const SIGXCPU: c_int = 30; pub const SIGXFSZ: c_int = 31; pub const SIGVTALRM: c_int = 28; pub const SIGPROF: c_int = 29; pub const SIGWINCH: c_int = 20; pub const SIGUSR1: c_int = 16; pub const SIGUSR2: c_int = 17; pub const SIGCONT: c_int = 25; pub const SIGSTOP: c_int = 23; pub const SIGTSTP: c_int = 24; pub const SIGURG: c_int = 21; pub const SIGIO: c_int = 22; pub const SIGSYS: c_int = 12; pub const SIGPWR: c_int = 19; pub const SIG_SETMASK: c_int = 3; pub const SIG_BLOCK: c_int = 0x1; pub const SIG_UNBLOCK: c_int = 0x2; pub const POLLWRNORM: c_short = 0x004; pub const POLLWRBAND: c_short = 0x100; pub const PTHREAD_STACK_MIN: size_t = 16384; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: crate::tcflag_t = 0x00000100; pub const TOSTOP: crate::tcflag_t = 0x00008000; pub const FLUSHO: crate::tcflag_t = 0x00002000; pub const TCSANOW: c_int = 0x540e; pub const TCSADRAIN: c_int = 0x540f; pub const TCSAFLUSH: c_int = 0x5410; pub const CPU_SETSIZE: c_int = 0x400; pub const EFD_NONBLOCK: c_int = 0x80; pub const F_GETLK: c_int = 14; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const SFD_NONBLOCK: c_int = 0x80; pub const RTLD_GLOBAL: c_int = 0x4; pub const SIGSTKSZ: size_t = 8192; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const CBAUDEX: crate::tcflag_t = 0o0010000; pub const CIBAUD: crate::tcflag_t = 0o002003600000; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const TABDLY: crate::tcflag_t = 0o0014000; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const BSDLY: crate::tcflag_t = 0o0020000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const XTABS: crate::tcflag_t = 0o0014000; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSWTC: usize = 7; pub const VTDLY: c_int = 0o0040000; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const OLCUC: crate::tcflag_t = 0o0000002; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CRDLY: c_int = 0o0003000; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const MAP_HUGETLB: c_int = 0x80000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; cfg_if! { if #[cfg(target_arch = "mips")] { mod mips32; pub use self::mips32::*; } else if #[cfg(target_arch = "mips64")] { mod mips64; pub use self::mips64::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/uclibc/mips/mips64/0000775000175000017500000000000015105742312021724 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs0000644000175000017500000001301215105742312023044 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type blkcnt_t = i64; pub type blksize_t = i64; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type ino_t = u64; pub type nlink_t = u64; pub type off_t = i64; pub type suseconds_t = i64; pub type time_t = i64; pub type wchar_t = i32; s! { pub struct stat { pub st_dev: c_ulong, st_pad1: [c_long; 2], pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulong, st_pad2: [c_ulong; 1], pub st_size: off_t, st_pad3: c_long, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, st_pad4: c_long, pub st_blocks: crate::blkcnt_t, st_pad5: [c_long; 7], } pub struct stat64 { pub st_dev: c_ulong, st_pad1: [c_long; 2], pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulong, st_pad2: [c_long; 2], pub st_size: off64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, st_pad3: c_long, pub st_blocks: crate::blkcnt64_t, st_pad5: [c_long; 7], } pub struct pthread_attr_t { __size: [c_ulong; 7], } pub struct sigaction { pub sa_flags: c_int, pub sa_sigaction: crate::sighandler_t, pub sa_mask: sigset_t, _restorer: *mut c_void, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct sigset_t { __size: [c_ulong; 16], } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, _pad: c_int, _pad2: [c_long; 14], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_uint, pub __seq: c_ushort, __pad1: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct statfs { pub f_type: c_long, pub f_bsize: c_long, pub f_frsize: c_long, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_files: crate::fsblkcnt_t, pub f_ffree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, f_spare: [c_long; 6], } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: size_t, pub msg_control: *mut c_void, pub msg_controllen: size_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: size_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], } pub struct sysinfo { pub uptime: c_long, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub _f: [c_char; 0], } // FIXME(1.0): this is actually a union #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { __size: [c_char; 32], } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const SYS_gettid: c_long = 5178; // Valid for n64 libc/src/unix/linux_like/linux/uclibc/mips/mips32/0000775000175000017500000000000015105742312021717 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs0000644000175000017500000006362215105742312023053 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type clock_t = i32; pub type time_t = i32; pub type suseconds_t = i32; pub type wchar_t = i32; pub type off_t = i32; pub type ino_t = u32; pub type blkcnt_t = i32; pub type blksize_t = i32; pub type nlink_t = u32; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; pub type fsblkcnt64_t = u64; pub type fsfilcnt64_t = u64; s! { pub struct stat { pub st_dev: crate::dev_t, st_pad1: [c_long; 2], pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_pad2: [c_long; 1], pub st_size: off_t, st_pad3: c_long, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, st_pad5: [c_long; 14], } pub struct stat64 { pub st_dev: crate::dev_t, st_pad1: [c_long; 2], pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, st_pad2: [c_long; 2], pub st_size: off64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, st_pad3: c_long, pub st_blocks: crate::blkcnt64_t, st_pad5: [c_long; 14], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_favail: crate::fsfilcnt64_t, pub f_fsid: c_ulong, pub __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, pub __f_spare: [c_int; 6], } pub struct pthread_attr_t { __size: [u32; 9], } pub struct sigaction { pub sa_flags: c_uint, pub sa_sigaction: crate::sighandler_t, pub sa_mask: sigset_t, _restorer: *mut c_void, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct sigset_t { __val: [c_ulong; 4], } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, pub _pad: [c_int; 29], } pub struct glob64_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_uint, pub __seq: c_ushort, __pad1: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, #[cfg(target_endian = "big")] __glibc_reserved1: c_ulong, pub msg_stime: crate::time_t, #[cfg(target_endian = "little")] __glibc_reserved1: c_ulong, #[cfg(target_endian = "big")] __glibc_reserved2: c_ulong, pub msg_rtime: crate::time_t, #[cfg(target_endian = "little")] __glibc_reserved2: c_ulong, #[cfg(target_endian = "big")] __glibc_reserved3: c_ulong, pub msg_ctime: crate::time_t, #[cfg(target_endian = "little")] __glibc_reserved3: c_ulong, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct statfs { pub f_type: c_long, pub f_bsize: c_long, pub f_frsize: c_long, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_files: crate::fsblkcnt_t, pub f_ffree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, f_spare: [c_long; 6], } pub struct statfs64 { pub f_type: c_long, pub f_bsize: c_long, pub f_frsize: c_long, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_files: crate::fsblkcnt64_t, pub f_ffree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, pub f_flags: c_long, pub f_spare: [c_long; 5], } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: size_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: size_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_sysid: c_long, pub l_pid: crate::pid_t, pad: [c_long; 4], } pub struct sysinfo { pub uptime: c_long, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub _f: [c_char; 8], } // FIXME(1.0): this is actually a union #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [c_char; 16], #[cfg(target_pointer_width = "64")] __size: [c_char; 32], } } pub const __SIZEOF_PTHREAD_ATTR_T: usize = 36; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const SYS_syscall: c_long = 4000 + 0; pub const SYS_exit: c_long = 4000 + 1; pub const SYS_fork: c_long = 4000 + 2; pub const SYS_read: c_long = 4000 + 3; pub const SYS_write: c_long = 4000 + 4; pub const SYS_open: c_long = 4000 + 5; pub const SYS_close: c_long = 4000 + 6; pub const SYS_waitpid: c_long = 4000 + 7; pub const SYS_creat: c_long = 4000 + 8; pub const SYS_link: c_long = 4000 + 9; pub const SYS_unlink: c_long = 4000 + 10; pub const SYS_execve: c_long = 4000 + 11; pub const SYS_chdir: c_long = 4000 + 12; pub const SYS_time: c_long = 4000 + 13; pub const SYS_mknod: c_long = 4000 + 14; pub const SYS_chmod: c_long = 4000 + 15; pub const SYS_lchown: c_long = 4000 + 16; pub const SYS_break: c_long = 4000 + 17; pub const SYS_lseek: c_long = 4000 + 19; pub const SYS_getpid: c_long = 4000 + 20; pub const SYS_mount: c_long = 4000 + 21; pub const SYS_umount: c_long = 4000 + 22; pub const SYS_setuid: c_long = 4000 + 23; pub const SYS_getuid: c_long = 4000 + 24; pub const SYS_stime: c_long = 4000 + 25; pub const SYS_ptrace: c_long = 4000 + 26; pub const SYS_alarm: c_long = 4000 + 27; pub const SYS_pause: c_long = 4000 + 29; pub const SYS_utime: c_long = 4000 + 30; pub const SYS_stty: c_long = 4000 + 31; pub const SYS_gtty: c_long = 4000 + 32; pub const SYS_access: c_long = 4000 + 33; pub const SYS_nice: c_long = 4000 + 34; pub const SYS_ftime: c_long = 4000 + 35; pub const SYS_sync: c_long = 4000 + 36; pub const SYS_kill: c_long = 4000 + 37; pub const SYS_rename: c_long = 4000 + 38; pub const SYS_mkdir: c_long = 4000 + 39; pub const SYS_rmdir: c_long = 4000 + 40; pub const SYS_dup: c_long = 4000 + 41; pub const SYS_pipe: c_long = 4000 + 42; pub const SYS_times: c_long = 4000 + 43; pub const SYS_prof: c_long = 4000 + 44; pub const SYS_brk: c_long = 4000 + 45; pub const SYS_setgid: c_long = 4000 + 46; pub const SYS_getgid: c_long = 4000 + 47; pub const SYS_signal: c_long = 4000 + 48; pub const SYS_geteuid: c_long = 4000 + 49; pub const SYS_getegid: c_long = 4000 + 50; pub const SYS_acct: c_long = 4000 + 51; pub const SYS_umount2: c_long = 4000 + 52; pub const SYS_lock: c_long = 4000 + 53; pub const SYS_ioctl: c_long = 4000 + 54; pub const SYS_fcntl: c_long = 4000 + 55; pub const SYS_mpx: c_long = 4000 + 56; pub const SYS_setpgid: c_long = 4000 + 57; pub const SYS_ulimit: c_long = 4000 + 58; pub const SYS_umask: c_long = 4000 + 60; pub const SYS_chroot: c_long = 4000 + 61; pub const SYS_ustat: c_long = 4000 + 62; pub const SYS_dup2: c_long = 4000 + 63; pub const SYS_getppid: c_long = 4000 + 64; pub const SYS_getpgrp: c_long = 4000 + 65; pub const SYS_setsid: c_long = 4000 + 66; pub const SYS_sigaction: c_long = 4000 + 67; pub const SYS_sgetmask: c_long = 4000 + 68; pub const SYS_ssetmask: c_long = 4000 + 69; pub const SYS_setreuid: c_long = 4000 + 70; pub const SYS_setregid: c_long = 4000 + 71; pub const SYS_sigsuspend: c_long = 4000 + 72; pub const SYS_sigpending: c_long = 4000 + 73; pub const SYS_sethostname: c_long = 4000 + 74; pub const SYS_setrlimit: c_long = 4000 + 75; pub const SYS_getrlimit: c_long = 4000 + 76; pub const SYS_getrusage: c_long = 4000 + 77; pub const SYS_gettimeofday: c_long = 4000 + 78; pub const SYS_settimeofday: c_long = 4000 + 79; pub const SYS_getgroups: c_long = 4000 + 80; pub const SYS_setgroups: c_long = 4000 + 81; pub const SYS_symlink: c_long = 4000 + 83; pub const SYS_readlink: c_long = 4000 + 85; pub const SYS_uselib: c_long = 4000 + 86; pub const SYS_swapon: c_long = 4000 + 87; pub const SYS_reboot: c_long = 4000 + 88; pub const SYS_readdir: c_long = 4000 + 89; pub const SYS_mmap: c_long = 4000 + 90; pub const SYS_munmap: c_long = 4000 + 91; pub const SYS_truncate: c_long = 4000 + 92; pub const SYS_ftruncate: c_long = 4000 + 93; pub const SYS_fchmod: c_long = 4000 + 94; pub const SYS_fchown: c_long = 4000 + 95; pub const SYS_getpriority: c_long = 4000 + 96; pub const SYS_setpriority: c_long = 4000 + 97; pub const SYS_profil: c_long = 4000 + 98; pub const SYS_statfs: c_long = 4000 + 99; pub const SYS_fstatfs: c_long = 4000 + 100; pub const SYS_ioperm: c_long = 4000 + 101; pub const SYS_socketcall: c_long = 4000 + 102; pub const SYS_syslog: c_long = 4000 + 103; pub const SYS_setitimer: c_long = 4000 + 104; pub const SYS_getitimer: c_long = 4000 + 105; pub const SYS_stat: c_long = 4000 + 106; pub const SYS_lstat: c_long = 4000 + 107; pub const SYS_fstat: c_long = 4000 + 108; pub const SYS_iopl: c_long = 4000 + 110; pub const SYS_vhangup: c_long = 4000 + 111; pub const SYS_idle: c_long = 4000 + 112; pub const SYS_vm86: c_long = 4000 + 113; pub const SYS_wait4: c_long = 4000 + 114; pub const SYS_swapoff: c_long = 4000 + 115; pub const SYS_sysinfo: c_long = 4000 + 116; pub const SYS_ipc: c_long = 4000 + 117; pub const SYS_fsync: c_long = 4000 + 118; pub const SYS_sigreturn: c_long = 4000 + 119; pub const SYS_clone: c_long = 4000 + 120; pub const SYS_setdomainname: c_long = 4000 + 121; pub const SYS_uname: c_long = 4000 + 122; pub const SYS_modify_ldt: c_long = 4000 + 123; pub const SYS_adjtimex: c_long = 4000 + 124; pub const SYS_mprotect: c_long = 4000 + 125; pub const SYS_sigprocmask: c_long = 4000 + 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 4000 + 127; pub const SYS_init_module: c_long = 4000 + 128; pub const SYS_delete_module: c_long = 4000 + 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 4000 + 130; pub const SYS_quotactl: c_long = 4000 + 131; pub const SYS_getpgid: c_long = 4000 + 132; pub const SYS_fchdir: c_long = 4000 + 133; pub const SYS_bdflush: c_long = 4000 + 134; pub const SYS_sysfs: c_long = 4000 + 135; pub const SYS_personality: c_long = 4000 + 136; pub const SYS_afs_syscall: c_long = 4000 + 137; pub const SYS_setfsuid: c_long = 4000 + 138; pub const SYS_setfsgid: c_long = 4000 + 139; pub const SYS__llseek: c_long = 4000 + 140; pub const SYS_getdents: c_long = 4000 + 141; pub const SYS__newselect: c_long = 4000 + 142; pub const SYS_flock: c_long = 4000 + 143; pub const SYS_msync: c_long = 4000 + 144; pub const SYS_readv: c_long = 4000 + 145; pub const SYS_writev: c_long = 4000 + 146; pub const SYS_cacheflush: c_long = 4000 + 147; pub const SYS_cachectl: c_long = 4000 + 148; pub const SYS_sysmips: c_long = 4000 + 149; pub const SYS_getsid: c_long = 4000 + 151; pub const SYS_fdatasync: c_long = 4000 + 152; pub const SYS__sysctl: c_long = 4000 + 153; pub const SYS_mlock: c_long = 4000 + 154; pub const SYS_munlock: c_long = 4000 + 155; pub const SYS_mlockall: c_long = 4000 + 156; pub const SYS_munlockall: c_long = 4000 + 157; pub const SYS_sched_setparam: c_long = 4000 + 158; pub const SYS_sched_getparam: c_long = 4000 + 159; pub const SYS_sched_setscheduler: c_long = 4000 + 160; pub const SYS_sched_getscheduler: c_long = 4000 + 161; pub const SYS_sched_yield: c_long = 4000 + 162; pub const SYS_sched_get_priority_max: c_long = 4000 + 163; pub const SYS_sched_get_priority_min: c_long = 4000 + 164; pub const SYS_sched_rr_get_interval: c_long = 4000 + 165; pub const SYS_nanosleep: c_long = 4000 + 166; pub const SYS_mremap: c_long = 4000 + 167; pub const SYS_accept: c_long = 4000 + 168; pub const SYS_bind: c_long = 4000 + 169; pub const SYS_connect: c_long = 4000 + 170; pub const SYS_getpeername: c_long = 4000 + 171; pub const SYS_getsockname: c_long = 4000 + 172; pub const SYS_getsockopt: c_long = 4000 + 173; pub const SYS_listen: c_long = 4000 + 174; pub const SYS_recv: c_long = 4000 + 175; pub const SYS_recvfrom: c_long = 4000 + 176; pub const SYS_recvmsg: c_long = 4000 + 177; pub const SYS_send: c_long = 4000 + 178; pub const SYS_sendmsg: c_long = 4000 + 179; pub const SYS_sendto: c_long = 4000 + 180; pub const SYS_setsockopt: c_long = 4000 + 181; pub const SYS_shutdown: c_long = 4000 + 182; pub const SYS_socket: c_long = 4000 + 183; pub const SYS_socketpair: c_long = 4000 + 184; pub const SYS_setresuid: c_long = 4000 + 185; pub const SYS_getresuid: c_long = 4000 + 186; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 4000 + 187; pub const SYS_poll: c_long = 4000 + 188; pub const SYS_nfsservctl: c_long = 4000 + 189; pub const SYS_setresgid: c_long = 4000 + 190; pub const SYS_getresgid: c_long = 4000 + 191; pub const SYS_prctl: c_long = 4000 + 192; pub const SYS_rt_sigreturn: c_long = 4000 + 193; pub const SYS_rt_sigaction: c_long = 4000 + 194; pub const SYS_rt_sigprocmask: c_long = 4000 + 195; pub const SYS_rt_sigpending: c_long = 4000 + 196; pub const SYS_rt_sigtimedwait: c_long = 4000 + 197; pub const SYS_rt_sigqueueinfo: c_long = 4000 + 198; pub const SYS_rt_sigsuspend: c_long = 4000 + 199; pub const SYS_pread64: c_long = 4000 + 200; pub const SYS_pwrite64: c_long = 4000 + 201; pub const SYS_chown: c_long = 4000 + 202; pub const SYS_getcwd: c_long = 4000 + 203; pub const SYS_capget: c_long = 4000 + 204; pub const SYS_capset: c_long = 4000 + 205; pub const SYS_sigaltstack: c_long = 4000 + 206; pub const SYS_sendfile: c_long = 4000 + 207; pub const SYS_getpmsg: c_long = 4000 + 208; pub const SYS_putpmsg: c_long = 4000 + 209; pub const SYS_mmap2: c_long = 4000 + 210; pub const SYS_truncate64: c_long = 4000 + 211; pub const SYS_ftruncate64: c_long = 4000 + 212; pub const SYS_stat64: c_long = 4000 + 213; pub const SYS_lstat64: c_long = 4000 + 214; pub const SYS_fstat64: c_long = 4000 + 215; pub const SYS_pivot_root: c_long = 4000 + 216; pub const SYS_mincore: c_long = 4000 + 217; pub const SYS_madvise: c_long = 4000 + 218; pub const SYS_getdents64: c_long = 4000 + 219; pub const SYS_fcntl64: c_long = 4000 + 220; pub const SYS_gettid: c_long = 4000 + 222; pub const SYS_readahead: c_long = 4000 + 223; pub const SYS_setxattr: c_long = 4000 + 224; pub const SYS_lsetxattr: c_long = 4000 + 225; pub const SYS_fsetxattr: c_long = 4000 + 226; pub const SYS_getxattr: c_long = 4000 + 227; pub const SYS_lgetxattr: c_long = 4000 + 228; pub const SYS_fgetxattr: c_long = 4000 + 229; pub const SYS_listxattr: c_long = 4000 + 230; pub const SYS_llistxattr: c_long = 4000 + 231; pub const SYS_flistxattr: c_long = 4000 + 232; pub const SYS_removexattr: c_long = 4000 + 233; pub const SYS_lremovexattr: c_long = 4000 + 234; pub const SYS_fremovexattr: c_long = 4000 + 235; pub const SYS_tkill: c_long = 4000 + 236; pub const SYS_sendfile64: c_long = 4000 + 237; pub const SYS_futex: c_long = 4000 + 238; pub const SYS_sched_setaffinity: c_long = 4000 + 239; pub const SYS_sched_getaffinity: c_long = 4000 + 240; pub const SYS_io_setup: c_long = 4000 + 241; pub const SYS_io_destroy: c_long = 4000 + 242; pub const SYS_io_getevents: c_long = 4000 + 243; pub const SYS_io_submit: c_long = 4000 + 244; pub const SYS_io_cancel: c_long = 4000 + 245; pub const SYS_exit_group: c_long = 4000 + 246; pub const SYS_lookup_dcookie: c_long = 4000 + 247; pub const SYS_epoll_create: c_long = 4000 + 248; pub const SYS_epoll_ctl: c_long = 4000 + 249; pub const SYS_epoll_wait: c_long = 4000 + 250; pub const SYS_remap_file_pages: c_long = 4000 + 251; pub const SYS_set_tid_address: c_long = 4000 + 252; pub const SYS_restart_syscall: c_long = 4000 + 253; pub const SYS_fadvise64: c_long = 4000 + 254; pub const SYS_statfs64: c_long = 4000 + 255; pub const SYS_fstatfs64: c_long = 4000 + 256; pub const SYS_timer_create: c_long = 4000 + 257; pub const SYS_timer_settime: c_long = 4000 + 258; pub const SYS_timer_gettime: c_long = 4000 + 259; pub const SYS_timer_getoverrun: c_long = 4000 + 260; pub const SYS_timer_delete: c_long = 4000 + 261; pub const SYS_clock_settime: c_long = 4000 + 262; pub const SYS_clock_gettime: c_long = 4000 + 263; pub const SYS_clock_getres: c_long = 4000 + 264; pub const SYS_clock_nanosleep: c_long = 4000 + 265; pub const SYS_tgkill: c_long = 4000 + 266; pub const SYS_utimes: c_long = 4000 + 267; pub const SYS_mbind: c_long = 4000 + 268; pub const SYS_get_mempolicy: c_long = 4000 + 269; pub const SYS_set_mempolicy: c_long = 4000 + 270; pub const SYS_mq_open: c_long = 4000 + 271; pub const SYS_mq_unlink: c_long = 4000 + 272; pub const SYS_mq_timedsend: c_long = 4000 + 273; pub const SYS_mq_timedreceive: c_long = 4000 + 274; pub const SYS_mq_notify: c_long = 4000 + 275; pub const SYS_mq_getsetattr: c_long = 4000 + 276; pub const SYS_vserver: c_long = 4000 + 277; pub const SYS_waitid: c_long = 4000 + 278; /* pub const SYS_sys_setaltroot: c_long = 4000 + 279; */ pub const SYS_add_key: c_long = 4000 + 280; pub const SYS_request_key: c_long = 4000 + 281; pub const SYS_keyctl: c_long = 4000 + 282; pub const SYS_set_thread_area: c_long = 4000 + 283; pub const SYS_inotify_init: c_long = 4000 + 284; pub const SYS_inotify_add_watch: c_long = 4000 + 285; pub const SYS_inotify_rm_watch: c_long = 4000 + 286; pub const SYS_migrate_pages: c_long = 4000 + 287; pub const SYS_openat: c_long = 4000 + 288; pub const SYS_mkdirat: c_long = 4000 + 289; pub const SYS_mknodat: c_long = 4000 + 290; pub const SYS_fchownat: c_long = 4000 + 291; pub const SYS_futimesat: c_long = 4000 + 292; pub const SYS_fstatat64: c_long = 4000 + 293; pub const SYS_unlinkat: c_long = 4000 + 294; pub const SYS_renameat: c_long = 4000 + 295; pub const SYS_linkat: c_long = 4000 + 296; pub const SYS_symlinkat: c_long = 4000 + 297; pub const SYS_readlinkat: c_long = 4000 + 298; pub const SYS_fchmodat: c_long = 4000 + 299; pub const SYS_faccessat: c_long = 4000 + 300; pub const SYS_pselect6: c_long = 4000 + 301; pub const SYS_ppoll: c_long = 4000 + 302; pub const SYS_unshare: c_long = 4000 + 303; pub const SYS_splice: c_long = 4000 + 304; pub const SYS_sync_file_range: c_long = 4000 + 305; pub const SYS_tee: c_long = 4000 + 306; pub const SYS_vmsplice: c_long = 4000 + 307; pub const SYS_move_pages: c_long = 4000 + 308; pub const SYS_set_robust_list: c_long = 4000 + 309; pub const SYS_get_robust_list: c_long = 4000 + 310; pub const SYS_kexec_load: c_long = 4000 + 311; pub const SYS_getcpu: c_long = 4000 + 312; pub const SYS_epoll_pwait: c_long = 4000 + 313; pub const SYS_ioprio_set: c_long = 4000 + 314; pub const SYS_ioprio_get: c_long = 4000 + 315; pub const SYS_utimensat: c_long = 4000 + 316; pub const SYS_signalfd: c_long = 4000 + 317; pub const SYS_timerfd: c_long = 4000 + 318; pub const SYS_eventfd: c_long = 4000 + 319; pub const SYS_fallocate: c_long = 4000 + 320; pub const SYS_timerfd_create: c_long = 4000 + 321; pub const SYS_timerfd_gettime: c_long = 4000 + 322; pub const SYS_timerfd_settime: c_long = 4000 + 323; pub const SYS_signalfd4: c_long = 4000 + 324; pub const SYS_eventfd2: c_long = 4000 + 325; pub const SYS_epoll_create1: c_long = 4000 + 326; pub const SYS_dup3: c_long = 4000 + 327; pub const SYS_pipe2: c_long = 4000 + 328; pub const SYS_inotify_init1: c_long = 4000 + 329; pub const SYS_preadv: c_long = 4000 + 330; pub const SYS_pwritev: c_long = 4000 + 331; pub const SYS_rt_tgsigqueueinfo: c_long = 4000 + 332; pub const SYS_perf_event_open: c_long = 4000 + 333; pub const SYS_accept4: c_long = 4000 + 334; pub const SYS_recvmmsg: c_long = 4000 + 335; pub const SYS_fanotify_init: c_long = 4000 + 336; pub const SYS_fanotify_mark: c_long = 4000 + 337; pub const SYS_prlimit64: c_long = 4000 + 338; pub const SYS_name_to_handle_at: c_long = 4000 + 339; pub const SYS_open_by_handle_at: c_long = 4000 + 340; pub const SYS_clock_adjtime: c_long = 4000 + 341; pub const SYS_syncfs: c_long = 4000 + 342; pub const SYS_sendmmsg: c_long = 4000 + 343; pub const SYS_setns: c_long = 4000 + 344; pub const SYS_process_vm_readv: c_long = 4000 + 345; pub const SYS_process_vm_writev: c_long = 4000 + 346; pub const SYS_kcmp: c_long = 4000 + 347; pub const SYS_finit_module: c_long = 4000 + 348; pub const SYS_sched_setattr: c_long = 4000 + 349; pub const SYS_sched_getattr: c_long = 4000 + 350; pub const SYS_renameat2: c_long = 4000 + 351; pub const SYS_seccomp: c_long = 4000 + 352; pub const SYS_getrandom: c_long = 4000 + 353; pub const SYS_memfd_create: c_long = 4000 + 354; pub const SYS_bpf: c_long = 4000 + 355; pub const SYS_execveat: c_long = 4000 + 356; pub const SYS_userfaultfd: c_long = 4000 + 357; pub const SYS_membarrier: c_long = 4000 + 358; pub const SYS_mlock2: c_long = 4000 + 359; pub const SYS_copy_file_range: c_long = 4000 + 360; pub const SYS_preadv2: c_long = 4000 + 361; pub const SYS_pwritev2: c_long = 4000 + 362; pub const SYS_pkey_mprotect: c_long = 4000 + 363; pub const SYS_pkey_alloc: c_long = 4000 + 364; pub const SYS_pkey_free: c_long = 4000 + 365; pub const SYS_statx: c_long = 4000 + 366; pub const SYS_pidfd_send_signal: c_long = 4000 + 424; pub const SYS_io_uring_setup: c_long = 4000 + 425; pub const SYS_io_uring_enter: c_long = 4000 + 426; pub const SYS_io_uring_register: c_long = 4000 + 427; pub const SYS_open_tree: c_long = 4000 + 428; pub const SYS_move_mount: c_long = 4000 + 429; pub const SYS_fsopen: c_long = 4000 + 430; pub const SYS_fsconfig: c_long = 4000 + 431; pub const SYS_fsmount: c_long = 4000 + 432; pub const SYS_fspick: c_long = 4000 + 433; pub const SYS_pidfd_open: c_long = 4000 + 434; pub const SYS_clone3: c_long = 4000 + 435; pub const SYS_close_range: c_long = 4000 + 436; pub const SYS_openat2: c_long = 4000 + 437; pub const SYS_pidfd_getfd: c_long = 4000 + 438; pub const SYS_faccessat2: c_long = 4000 + 439; pub const SYS_process_madvise: c_long = 4000 + 440; pub const SYS_epoll_pwait2: c_long = 4000 + 441; pub const SYS_mount_setattr: c_long = 4000 + 442; pub const SYS_quotactl_fd: c_long = 4000 + 443; pub const SYS_landlock_create_ruleset: c_long = 4000 + 444; pub const SYS_landlock_add_rule: c_long = 4000 + 445; pub const SYS_landlock_restrict_self: c_long = 4000 + 446; pub const SYS_memfd_secret: c_long = 4000 + 447; pub const SYS_process_mrelease: c_long = 4000 + 448; pub const SYS_futex_waitv: c_long = 4000 + 449; pub const SYS_set_mempolicy_home_node: c_long = 4000 + 450; #[link(name = "util")] extern "C" { pub fn sysctl( name: *mut c_int, namelen: c_int, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; pub fn glob64( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut glob64_t, ) -> c_int; pub fn globfree64(pglob: *mut glob64_t); pub fn pthread_attr_getaffinity_np( attr: *const crate::pthread_attr_t, cpusetsize: size_t, cpuset: *mut crate::cpu_set_t, ) -> c_int; pub fn pthread_attr_setaffinity_np( attr: *mut crate::pthread_attr_t, cpusetsize: size_t, cpuset: *const crate::cpu_set_t, ) -> c_int; } libc/src/unix/linux_like/linux/musl/0000775000175000017500000000000015105742312017351 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/mod.rs0000644000175000017500000010323415105742312020477 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type pthread_t = *mut c_void; pub type clock_t = c_long; #[cfg_attr( not(feature = "rustc-dep-of-std"), deprecated( since = "0.2.80", note = "This type is changed to 64-bit in musl 1.2.0, \ we'll follow that change in the future release. \ See #1848 for more info." ) )] pub type time_t = c_long; pub type suseconds_t = c_long; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i64; pub type shmatt_t = c_ulong; pub type msgqnum_t = c_ulong; pub type msglen_t = c_ulong; pub type fsblkcnt_t = c_ulonglong; pub type fsblkcnt64_t = c_ulonglong; pub type fsfilcnt_t = c_ulonglong; pub type fsfilcnt64_t = c_ulonglong; pub type rlim_t = c_ulonglong; cfg_if! { if #[cfg(doc)] { // Used in `linux::arch` to define ioctl constants. pub(crate) type Ioctl = c_int; } else { #[doc(hidden)] pub type Ioctl = c_int; } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { #[repr(C)] struct siginfo_sigfault { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, si_addr: *mut c_void, } (*(self as *const siginfo_t as *const siginfo_sigfault)).si_addr } pub unsafe fn si_value(&self) -> crate::sigval { #[repr(C)] struct siginfo_si_value { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, _si_timerid: c_int, _si_overrun: c_int, si_value: crate::sigval, } (*(self as *const siginfo_t as *const siginfo_si_value)).si_value } } // Internal, for casts to access union fields #[repr(C)] struct sifields_sigchld { si_pid: crate::pid_t, si_uid: crate::uid_t, si_status: c_int, si_utime: c_long, si_stime: c_long, } impl Copy for sifields_sigchld {} impl Clone for sifields_sigchld { fn clone(&self) -> sifields_sigchld { *self } } // Internal, for casts to access union fields #[repr(C)] union sifields { _align_pointer: *mut c_void, sigchld: sifields_sigchld, } // Internal, for casts to access union fields. Note that some variants // of sifields start with a pointer, which makes the alignment of // sifields vary on 32-bit and 64-bit architectures. #[repr(C)] struct siginfo_f { _siginfo_base: [c_int; 3], sifields: sifields, } impl siginfo_t { unsafe fn sifields(&self) -> &sifields { &(*(self as *const siginfo_t as *const siginfo_f)).sifields } pub unsafe fn si_pid(&self) -> crate::pid_t { self.sifields().sigchld.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.sifields().sigchld.si_uid } pub unsafe fn si_status(&self) -> c_int { self.sifields().sigchld.si_status } pub unsafe fn si_utime(&self) -> c_long { self.sifields().sigchld.si_utime } pub unsafe fn si_stime(&self) -> c_long { self.sifields().sigchld.si_stime } } s! { pub struct aiocb { pub aio_fildes: c_int, pub aio_lio_opcode: c_int, pub aio_reqprio: c_int, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_sigevent: crate::sigevent, __td: *mut c_void, __lock: [c_int; 2], __err: c_int, __ret: ssize_t, pub aio_offset: off_t, __next: *mut c_void, __prev: *mut c_void, #[cfg(target_pointer_width = "32")] __dummy4: [c_char; 24], #[cfg(target_pointer_width = "64")] __dummy4: [c_char; 16], } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } // `mips*` targets swap the `s_errno` and `s_code` fields otherwise this struct is // target-agnostic (see https://www.openwall.com/lists/musl/2016/01/27/1/2) // // FIXME(union): C implementation uses unions pub struct siginfo_t { pub si_signo: c_int, #[cfg(not(target_arch = "mips"))] pub si_errno: c_int, pub si_code: c_int, #[cfg(target_arch = "mips")] pub si_errno: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on https://github.com/rust-lang/libc/pull/1316 \ if you're using this field" )] pub _pad: [c_int; 29], _align: [usize; 0], } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, #[cfg(target_endian = "little")] pub f_fsid: c_ulong, #[cfg(target_pointer_width = "32")] __pad: c_int, #[cfg(target_endian = "big")] pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_reserved: [c_int; 6], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_favail: crate::fsfilcnt64_t, #[cfg(target_endian = "little")] pub f_fsid: c_ulong, #[cfg(target_pointer_width = "32")] __pad: c_int, #[cfg(target_endian = "big")] pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_reserved: [c_int; 6], } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], pub __c_ispeed: crate::speed_t, pub __c_ospeed: crate::speed_t, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct regex_t { __re_nsub: size_t, __opaque: *mut c_void, __padding: [*mut c_void; 4usize], __nsub2: size_t, __padding2: c_char, } pub struct rtentry { pub rt_pad1: c_ulong, pub rt_dst: crate::sockaddr, pub rt_gateway: crate::sockaddr, pub rt_genmask: crate::sockaddr, pub rt_flags: c_ushort, pub rt_pad2: c_short, pub rt_pad3: c_ulong, pub rt_tos: c_uchar, pub rt_class: c_uchar, #[cfg(target_pointer_width = "64")] pub rt_pad4: [c_short; 3usize], #[cfg(not(target_pointer_width = "64"))] pub rt_pad4: [c_short; 1usize], pub rt_metric: c_short, pub rt_dev: *mut c_char, pub rt_mtu: c_ulong, pub rt_window: c_ulong, pub rt_irtt: c_ushort, } pub struct __exit_status { pub e_termination: c_short, pub e_exit: c_short, } pub struct Elf64_Chdr { pub ch_type: crate::Elf64_Word, pub ch_reserved: crate::Elf64_Word, pub ch_size: crate::Elf64_Xword, pub ch_addralign: crate::Elf64_Xword, } pub struct Elf32_Chdr { pub ch_type: crate::Elf32_Word, pub ch_size: crate::Elf32_Word, pub ch_addralign: crate::Elf32_Word, } pub struct timex { pub modes: c_uint, pub offset: c_long, pub freq: c_long, pub maxerror: c_long, pub esterror: c_long, pub status: c_int, pub constant: c_long, pub precision: c_long, pub tolerance: c_long, pub time: crate::timeval, pub tick: c_long, pub ppsfreq: c_long, pub jitter: c_long, pub shift: c_int, pub stabil: c_long, pub jitcnt: c_long, pub calcnt: c_long, pub errcnt: c_long, pub stbcnt: c_long, pub tai: c_int, pub __padding: [c_int; 11], } pub struct ntptimeval { pub time: crate::timeval, pub maxerror: c_long, pub esterror: c_long, } // netinet/tcp.h pub struct tcp_info { pub tcpi_state: u8, pub tcpi_ca_state: u8, pub tcpi_retransmits: u8, pub tcpi_probes: u8, pub tcpi_backoff: u8, pub tcpi_options: u8, /* * FIXME(musl): enable on all targets once musl headers are more up to date */ /// This contains the bitfields `tcpi_snd_wscale` and `tcpi_rcv_wscale`. /// Each is 4 bits. #[cfg(target_arch = "loongarch64")] pub tcpi_snd_rcv_wscale: u8, /// This contains the bitfields `tcpi_delivery_rate_app_limited` (1 bit) and /// `tcpi_fastopen_client_fail` (2 bits). #[cfg(target_arch = "loongarch64")] pub tcpi_delivery_fastopen_bitfields: u8, pub tcpi_rto: u32, pub tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub tcpi_unacked: u32, pub tcpi_sacked: u32, pub tcpi_lost: u32, pub tcpi_retrans: u32, pub tcpi_fackets: u32, pub tcpi_last_data_sent: u32, pub tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub tcpi_last_ack_recv: u32, pub tcpi_pmtu: u32, pub tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub tcpi_advmss: u32, pub tcpi_reordering: u32, pub tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_total_retrans: u32, pub tcpi_pacing_rate: u64, pub tcpi_max_pacing_rate: u64, pub tcpi_bytes_acked: u64, pub tcpi_bytes_received: u64, pub tcpi_segs_out: u32, pub tcpi_segs_in: u32, pub tcpi_notsent_bytes: u32, pub tcpi_min_rtt: u32, pub tcpi_data_segs_in: u32, pub tcpi_data_segs_out: u32, pub tcpi_delivery_rate: u64, pub tcpi_busy_time: u64, pub tcpi_rwnd_limited: u64, pub tcpi_sndbuf_limited: u64, pub tcpi_delivered: u32, pub tcpi_delivered_ce: u32, pub tcpi_bytes_sent: u64, pub tcpi_bytes_retrans: u64, pub tcpi_dsack_dups: u32, pub tcpi_reord_seen: u32, // FIXME(musl): enable on all targets once CI musl is updated #[cfg(target_arch = "loongarch64")] pub tcpi_rcv_ooopack: u32, #[cfg(target_arch = "loongarch64")] pub tcpi_snd_wnd: u32, } // MIPS implementation is special (see mips arch folders) #[cfg(not(target_arch = "mips"))] pub struct statfs { pub f_type: c_ulong, pub f_bsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_ulong, pub f_frsize: c_ulong, pub f_flags: c_ulong, pub f_spare: [c_ulong; 4], } // MIPS implementation is special (see mips arch folders) #[cfg(not(target_arch = "mips"))] pub struct statfs64 { pub f_type: c_ulong, pub f_bsize: c_ulong, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_ulong, pub f_frsize: c_ulong, pub f_flags: c_ulong, pub f_spare: [c_ulong; 4], } } s_no_extra_traits! { pub struct sysinfo { pub uptime: c_ulong, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub __reserved: [c_char; 256], } // FIXME(musl): musl added paddings and adjusted // layout in 1.2.0 but our CI is still 1.1.24. // So, I'm leaving some fields as cfg for now. // ref. https://github.com/bminor/musl/commit/ // 1e7f0fcd7ff2096904fd93a2ee6d12a2392be392 // // OpenHarmony uses the musl 1.2 layout. pub struct utmpx { pub ut_type: c_short, __ut_pad1: c_short, pub ut_pid: crate::pid_t, pub ut_line: [c_char; 32], pub ut_id: [c_char; 4], pub ut_user: [c_char; 32], pub ut_host: [c_char; 256], pub ut_exit: __exit_status, #[cfg(target_env = "musl")] #[cfg(not(target_arch = "loongarch64"))] pub ut_session: c_long, #[cfg(target_env = "musl")] #[cfg(target_arch = "loongarch64")] pub ut_session: c_int, #[cfg(target_env = "musl")] #[cfg(target_arch = "loongarch64")] __ut_pad2: c_int, #[cfg(target_env = "ohos")] #[cfg(target_endian = "little")] pub ut_session: c_int, #[cfg(target_env = "ohos")] #[cfg(target_endian = "little")] __ut_pad2: c_int, #[cfg(target_env = "ohos")] #[cfg(not(target_endian = "little"))] __ut_pad2: c_int, #[cfg(target_env = "ohos")] #[cfg(not(target_endian = "little"))] pub ut_session: c_int, pub ut_tv: crate::timeval, pub ut_addr_v6: [c_uint; 4], __unused: [c_char; 20], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sysinfo { fn eq(&self, other: &sysinfo) -> bool { self.uptime == other.uptime && self.loads == other.loads && self.totalram == other.totalram && self.freeram == other.freeram && self.sharedram == other.sharedram && self.bufferram == other.bufferram && self.totalswap == other.totalswap && self.freeswap == other.freeswap && self.procs == other.procs && self.pad == other.pad && self.totalhigh == other.totalhigh && self.freehigh == other.freehigh && self.mem_unit == other.mem_unit && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a, b)| a == b) } } impl Eq for sysinfo {} impl fmt::Debug for sysinfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sysinfo") .field("uptime", &self.uptime) .field("loads", &self.loads) .field("totalram", &self.totalram) .field("freeram", &self.freeram) .field("sharedram", &self.sharedram) .field("bufferram", &self.bufferram) .field("totalswap", &self.totalswap) .field("freeswap", &self.freeswap) .field("procs", &self.procs) .field("pad", &self.pad) .field("totalhigh", &self.totalhigh) .field("freehigh", &self.freehigh) .field("mem_unit", &self.mem_unit) // FIXME(debug): .field("__reserved", &self.__reserved) .finish() } } impl hash::Hash for sysinfo { fn hash(&self, state: &mut H) { self.uptime.hash(state); self.loads.hash(state); self.totalram.hash(state); self.freeram.hash(state); self.sharedram.hash(state); self.bufferram.hash(state); self.totalswap.hash(state); self.freeswap.hash(state); self.procs.hash(state); self.pad.hash(state); self.totalhigh.hash(state); self.freehigh.hash(state); self.mem_unit.hash(state); self.__reserved.hash(state); } } impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type //&& self.__ut_pad1 == other.__ut_pad1 && self.ut_pid == other.ut_pid && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_user == other.ut_user && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session //&& self.__ut_pad2 == other.__ut_pad2 && self.ut_tv == other.ut_tv && self.ut_addr_v6 == other.ut_addr_v6 && self.__unused == other.__unused } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) //.field("__ut_pad1", &self.__ut_pad1) .field("ut_pid", &self.ut_pid) .field("ut_line", &self.ut_line) .field("ut_id", &self.ut_id) .field("ut_user", &self.ut_user) //FIXME(debug): .field("ut_host", &self.ut_host) .field("ut_exit", &self.ut_exit) .field("ut_session", &self.ut_session) //.field("__ut_pad2", &self.__ut_pad2) .field("ut_tv", &self.ut_tv) .field("ut_addr_v6", &self.ut_addr_v6) .field("__unused", &self.__unused) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); //self.__ut_pad1.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_user.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); //self.__ut_pad2.hash(state); self.ut_tv.hash(state); self.ut_addr_v6.hash(state); self.__unused.hash(state); } } } } // include/sys/mman.h /* * Huge page size encoding when MAP_HUGETLB is specified, and a huge page * size other than the default is desired. See hugetlb_encode.h. * All known huge page size encodings are provided here. It is the * responsibility of the application to know which sizes are supported on * the running system. See mmap(2) man page for details. */ pub const MAP_HUGE_SHIFT: c_int = 26; pub const MAP_HUGE_MASK: c_int = 0x3f; pub const MAP_HUGE_64KB: c_int = 16 << MAP_HUGE_SHIFT; pub const MAP_HUGE_512KB: c_int = 19 << MAP_HUGE_SHIFT; pub const MAP_HUGE_1MB: c_int = 20 << MAP_HUGE_SHIFT; pub const MAP_HUGE_2MB: c_int = 21 << MAP_HUGE_SHIFT; pub const MAP_HUGE_8MB: c_int = 23 << MAP_HUGE_SHIFT; pub const MAP_HUGE_16MB: c_int = 24 << MAP_HUGE_SHIFT; pub const MAP_HUGE_32MB: c_int = 25 << MAP_HUGE_SHIFT; pub const MAP_HUGE_256MB: c_int = 28 << MAP_HUGE_SHIFT; pub const MAP_HUGE_512MB: c_int = 29 << MAP_HUGE_SHIFT; pub const MAP_HUGE_1GB: c_int = 30 << MAP_HUGE_SHIFT; pub const MAP_HUGE_2GB: c_int = 31 << MAP_HUGE_SHIFT; pub const MAP_HUGE_16GB: c_int = 34 << MAP_HUGE_SHIFT; pub const MS_RMT_MASK: c_ulong = 0x02800051; // include/utmpx.h pub const EMPTY: c_short = 0; pub const RUN_LVL: c_short = 1; pub const BOOT_TIME: c_short = 2; pub const NEW_TIME: c_short = 3; pub const OLD_TIME: c_short = 4; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const USER_PROCESS: c_short = 7; pub const DEAD_PROCESS: c_short = 8; pub const ACCOUNTING: c_short = 9; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_NOATIME: c_int = 0o1000000; pub const O_CLOEXEC: c_int = 0x80000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const BUFSIZ: c_uint = 1024; pub const TMP_MAX: c_uint = 10000; pub const FOPEN_MAX: c_uint = 1000; pub const FILENAME_MAX: c_uint = 4096; pub const O_PATH: c_int = 0o10000000; pub const O_EXEC: c_int = 0o10000000; pub const O_SEARCH: c_int = 0o10000000; pub const O_ACCMODE: c_int = 0o10000003; pub const O_NDELAY: c_int = O_NONBLOCK; pub const NI_MAXHOST: crate::socklen_t = 255; pub const PTHREAD_STACK_MIN: size_t = 2048; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const SOCK_SEQPACKET: c_int = 5; pub const SOCK_DCCP: c_int = 6; pub const SOCK_NONBLOCK: c_int = O_NONBLOCK; #[deprecated(since = "0.2.70", note = "AF_PACKET must be used instead")] pub const SOCK_PACKET: c_int = 10; pub const SOMAXCONN: c_int = 128; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = crate::SIGSYS; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; #[cfg(not(target_arch = "loongarch64"))] pub const CPU_SETSIZE: c_int = 128; #[cfg(target_arch = "loongarch64")] pub const CPU_SETSIZE: c_int = 1024; pub const PTRACE_TRACEME: c_int = 0; pub const PTRACE_PEEKTEXT: c_int = 1; pub const PTRACE_PEEKDATA: c_int = 2; pub const PTRACE_PEEKUSER: c_int = 3; pub const PTRACE_POKETEXT: c_int = 4; pub const PTRACE_POKEDATA: c_int = 5; pub const PTRACE_POKEUSER: c_int = 6; pub const PTRACE_CONT: c_int = 7; pub const PTRACE_KILL: c_int = 8; pub const PTRACE_SINGLESTEP: c_int = 9; pub const PTRACE_GETREGS: c_int = 12; pub const PTRACE_SETREGS: c_int = 13; pub const PTRACE_GETFPREGS: c_int = 14; pub const PTRACE_SETFPREGS: c_int = 15; pub const PTRACE_ATTACH: c_int = 16; pub const PTRACE_DETACH: c_int = 17; pub const PTRACE_GETFPXREGS: c_int = 18; pub const PTRACE_SETFPXREGS: c_int = 19; pub const PTRACE_SYSCALL: c_int = 24; pub const PTRACE_SETOPTIONS: c_int = 0x4200; pub const PTRACE_GETEVENTMSG: c_int = 0x4201; pub const PTRACE_GETSIGINFO: c_int = 0x4202; pub const PTRACE_SETSIGINFO: c_int = 0x4203; pub const PTRACE_GETREGSET: c_int = 0x4204; pub const PTRACE_SETREGSET: c_int = 0x4205; pub const PTRACE_SEIZE: c_int = 0x4206; pub const PTRACE_INTERRUPT: c_int = 0x4207; pub const PTRACE_LISTEN: c_int = 0x4208; pub const PTRACE_PEEKSIGINFO: c_int = 0x4209; pub const PTRACE_GETSIGMASK: c_uint = 0x420a; pub const PTRACE_SETSIGMASK: c_uint = 0x420b; pub const RWF_HIPRI: c_int = 0x00000001; pub const RWF_DSYNC: c_int = 0x00000002; pub const RWF_SYNC: c_int = 0x00000004; pub const RWF_NOWAIT: c_int = 0x00000008; pub const RWF_APPEND: c_int = 0x00000010; pub const AF_IB: c_int = 27; pub const AF_MPLS: c_int = 28; pub const AF_NFC: c_int = 39; pub const AF_VSOCK: c_int = 40; pub const AF_XDP: c_int = 44; pub const PF_IB: c_int = AF_IB; pub const PF_MPLS: c_int = AF_MPLS; pub const PF_NFC: c_int = AF_NFC; pub const PF_VSOCK: c_int = AF_VSOCK; pub const PF_XDP: c_int = AF_XDP; pub const EFD_NONBLOCK: c_int = crate::O_NONBLOCK; pub const SFD_NONBLOCK: c_int = crate::O_NONBLOCK; pub const PIDFD_NONBLOCK: c_uint = O_NONBLOCK as c_uint; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const CLOCK_SGI_CYCLE: crate::clockid_t = 10; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const REG_OK: c_int = 0; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; pub const ADJ_OFFSET: c_uint = 0x0001; pub const ADJ_FREQUENCY: c_uint = 0x0002; pub const ADJ_MAXERROR: c_uint = 0x0004; pub const ADJ_ESTERROR: c_uint = 0x0008; pub const ADJ_STATUS: c_uint = 0x0010; pub const ADJ_TIMECONST: c_uint = 0x0020; pub const ADJ_TAI: c_uint = 0x0080; pub const ADJ_SETOFFSET: c_uint = 0x0100; pub const ADJ_MICRO: c_uint = 0x1000; pub const ADJ_NANO: c_uint = 0x2000; pub const ADJ_TICK: c_uint = 0x4000; pub const ADJ_OFFSET_SINGLESHOT: c_uint = 0x8001; pub const ADJ_OFFSET_SS_READ: c_uint = 0xa001; pub const MOD_OFFSET: c_uint = ADJ_OFFSET; pub const MOD_FREQUENCY: c_uint = ADJ_FREQUENCY; pub const MOD_MAXERROR: c_uint = ADJ_MAXERROR; pub const MOD_ESTERROR: c_uint = ADJ_ESTERROR; pub const MOD_STATUS: c_uint = ADJ_STATUS; pub const MOD_TIMECONST: c_uint = ADJ_TIMECONST; pub const MOD_CLKB: c_uint = ADJ_TICK; pub const MOD_CLKA: c_uint = ADJ_OFFSET_SINGLESHOT; pub const MOD_TAI: c_uint = ADJ_TAI; pub const MOD_MICRO: c_uint = ADJ_MICRO; pub const MOD_NANO: c_uint = ADJ_NANO; pub const STA_PLL: c_int = 0x0001; pub const STA_PPSFREQ: c_int = 0x0002; pub const STA_PPSTIME: c_int = 0x0004; pub const STA_FLL: c_int = 0x0008; pub const STA_INS: c_int = 0x0010; pub const STA_DEL: c_int = 0x0020; pub const STA_UNSYNC: c_int = 0x0040; pub const STA_FREQHOLD: c_int = 0x0080; pub const STA_PPSSIGNAL: c_int = 0x0100; pub const STA_PPSJITTER: c_int = 0x0200; pub const STA_PPSWANDER: c_int = 0x0400; pub const STA_PPSERROR: c_int = 0x0800; pub const STA_CLOCKERR: c_int = 0x1000; pub const STA_NANO: c_int = 0x2000; pub const STA_MODE: c_int = 0x4000; pub const STA_CLK: c_int = 0x8000; pub const STA_RONLY: c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const TIME_OK: c_int = 0; pub const TIME_INS: c_int = 1; pub const TIME_DEL: c_int = 2; pub const TIME_OOP: c_int = 3; pub const TIME_WAIT: c_int = 4; pub const TIME_ERROR: c_int = 5; pub const TIME_BAD: c_int = TIME_ERROR; pub const MAXTC: c_long = 6; pub const _CS_V6_ENV: c_int = 1148; pub const _CS_V7_ENV: c_int = 1149; pub const CLONE_NEWTIME: c_int = 0x80; pub const UT_HOSTSIZE: usize = 256; pub const UT_LINESIZE: usize = 32; pub const UT_NAMESIZE: usize = 32; cfg_if! { if #[cfg(target_arch = "s390x")] { pub const POSIX_FADV_DONTNEED: c_int = 6; pub const POSIX_FADV_NOREUSE: c_int = 7; } else { pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; } } extern "C" { pub fn sendmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_uint, ) -> c_int; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_uint, timeout: *mut crate::timespec, ) -> c_int; pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; pub fn prlimit( pid: crate::pid_t, resource: c_int, new_limit: *const crate::rlimit, old_limit: *mut crate::rlimit, ) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn ptrace(request: c_int, ...) -> c_long; pub fn getpriority(which: c_int, who: crate::id_t) -> c_int; pub fn setpriority(which: c_int, who: crate::id_t, prio: c_int) -> c_int; // Musl targets need the `mask` argument of `fanotify_mark` be specified // `c_ulonglong` instead of `u64` or there will be a type mismatch between // `long long unsigned int` and the expected `uint64_t`. pub fn fanotify_mark( fd: c_int, flags: c_uint, mask: c_ulonglong, dirfd: c_int, path: *const c_char, ) -> c_int; pub fn preadv2( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t, flags: c_int, ) -> ssize_t; pub fn pwritev2( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t, flags: c_int, ) -> ssize_t; pub fn getauxval(type_: c_ulong) -> c_ulong; // Added in `musl` 1.1.20 pub fn explicit_bzero(s: *mut c_void, len: size_t); // Added in `musl` 1.2.2 pub fn reallocarray(ptr: *mut c_void, nmemb: size_t, size: size_t) -> *mut c_void; pub fn adjtimex(buf: *mut crate::timex) -> c_int; pub fn clock_adjtime(clk_id: crate::clockid_t, buf: *mut crate::timex) -> c_int; pub fn ctermid(s: *mut c_char) -> *mut c_char; pub fn memfd_create(name: *const c_char, flags: c_uint) -> c_int; pub fn mlock2(addr: *const c_void, len: size_t, flags: c_uint) -> c_int; pub fn malloc_usable_size(ptr: *mut c_void) -> size_t; pub fn euidaccess(pathname: *const c_char, mode: c_int) -> c_int; pub fn eaccess(pathname: *const c_char, mode: c_int) -> c_int; pub fn asctime_r(tm: *const crate::tm, buf: *mut c_char) -> *mut c_char; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn basename(path: *mut c_char) -> *mut c_char; // Addded in `musl` 1.1.20 pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; // Added in `musl` 1.1.24 pub fn posix_spawn_file_actions_addchdir_np( actions: *mut crate::posix_spawn_file_actions_t, path: *const c_char, ) -> c_int; // Added in `musl` 1.1.24 pub fn posix_spawn_file_actions_addfchdir_np( actions: *mut crate::posix_spawn_file_actions_t, fd: c_int, ) -> c_int; #[deprecated( since = "0.2.172", note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html" )] pub fn getutxent() -> *mut utmpx; #[deprecated( since = "0.2.172", note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html" )] pub fn getutxid(ut: *const utmpx) -> *mut utmpx; #[deprecated( since = "0.2.172", note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html" )] pub fn getutxline(ut: *const utmpx) -> *mut utmpx; #[deprecated( since = "0.2.172", note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html" )] pub fn pututxline(ut: *const utmpx) -> *mut utmpx; #[deprecated( since = "0.2.172", note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html" )] pub fn setutxent(); #[deprecated( since = "0.2.172", note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html" )] pub fn endutxent(); #[deprecated( since = "0.2.172", note = "musl provides `utmp` as stubs and an alternative should be preferred; see https://wiki.musl-libc.org/faq.html" )] pub fn utmpxname(file: *const c_char) -> c_int; } // Alias to 64 to mimic glibc's LFS64 support mod lfs64; pub use self::lfs64::*; cfg_if! { if #[cfg(any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", target_arch = "powerpc64", target_arch = "s390x", target_arch = "riscv64", target_arch = "loongarch64", // musl-linux ABI for wasm32 follows b64 convention target_arch = "wasm32", ))] { mod b64; pub use self::b64::*; } else if #[cfg(any( target_arch = "x86", target_arch = "mips", target_arch = "powerpc", target_arch = "hexagon", target_arch = "riscv32", target_arch = "arm" ))] { mod b32; pub use self::b32::*; } else { } } libc/src/unix/linux_like/linux/musl/b32/0000775000175000017500000000000015105742312017737 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b32/mod.rs0000644000175000017500000000310115105742312021055 0ustar bdrungbdrunguse crate::prelude::*; pub type nlink_t = u32; pub type blksize_t = c_long; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; pub type regoff_t = c_int; s! { pub struct pthread_attr_t { __size: [u32; 9], } pub struct sigset_t { __val: [c_ulong; 32], } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct sem_t { __val: [c_int; 4], } } pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; cfg_if! { if #[cfg(any(target_arch = "x86"))] { mod x86; pub use self::x86::*; } else if #[cfg(any(target_arch = "mips"))] { mod mips; pub use self::mips::*; } else if #[cfg(any(target_arch = "arm"))] { mod arm; pub use self::arm::*; } else if #[cfg(any(target_arch = "powerpc"))] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(any(target_arch = "hexagon"))] { mod hexagon; pub use self::hexagon::*; } else if #[cfg(any(target_arch = "riscv32"))] { mod riscv32; pub use self::riscv32::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/musl/b32/powerpc.rs0000644000175000017500000006443515105742312021776 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = i32; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __st_rdev_padding: c_short, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 2], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __st_rdev_padding: c_short, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 2], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __pad1: c_int, __pad2: c_longlong, __pad3: c_longlong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, __unused1: c_int, pub shm_atime: crate::time_t, __unused2: c_int, pub shm_dtime: crate::time_t, __unused3: c_int, pub shm_ctime: crate::time_t, __unused4: c_int, pub shm_segsz: size_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: c_ulong, __pad1: c_ulong, __pad2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, __unused1: c_int, pub msg_stime: crate::time_t, __unused2: c_int, pub msg_rtime: crate::time_t, __unused3: c_int, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } } pub const MADV_SOFT_OFFLINE: c_int = 101; pub const SIGSTKSZ: size_t = 10240; pub const MINSIGSTKSZ: size_t = 4096; pub const O_DIRECT: c_int = 0x20000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_ASYNC: c_int = 0x2000; pub const O_LARGEFILE: c_int = 0x10000; pub const MCL_CURRENT: c_int = 0x2000; pub const MCL_FUTURE: c_int = 0x4000; pub const MCL_ONFAULT: c_int = 0x8000; pub const CBAUD: crate::tcflag_t = 0o0000377; pub const TAB1: c_int = 0x00000400; pub const TAB2: c_int = 0x00000800; pub const TAB3: c_int = 0x00000C00; pub const CR1: c_int = 0x00001000; pub const CR2: c_int = 0x00002000; pub const CR3: c_int = 0x00003000; pub const FF1: c_int = 0x00004000; pub const BS1: c_int = 0x00008000; pub const VT1: c_int = 0x00010000; pub const VWERASE: usize = 10; pub const VREPRINT: usize = 11; pub const VSUSP: usize = 12; pub const VSTART: usize = 13; pub const VSTOP: usize = 14; pub const VDISCARD: usize = 16; pub const VTIME: usize = 7; pub const IXON: crate::tcflag_t = 0x00000200; pub const IXOFF: crate::tcflag_t = 0x00000400; pub const ONLCR: crate::tcflag_t = 0x00000002; pub const CSIZE: crate::tcflag_t = 0x00000300; pub const CS6: crate::tcflag_t = 0x00000100; pub const CS7: crate::tcflag_t = 0x00000200; pub const CS8: crate::tcflag_t = 0x00000300; pub const CSTOPB: crate::tcflag_t = 0x00000400; pub const CREAD: crate::tcflag_t = 0x00000800; pub const PARENB: crate::tcflag_t = 0x00001000; pub const PARODD: crate::tcflag_t = 0x00002000; pub const HUPCL: crate::tcflag_t = 0x00004000; pub const CLOCAL: crate::tcflag_t = 0x00008000; pub const ECHOKE: crate::tcflag_t = 0x00000001; pub const ECHOE: crate::tcflag_t = 0x00000002; pub const ECHOK: crate::tcflag_t = 0x00000004; pub const ECHONL: crate::tcflag_t = 0x00000010; pub const ECHOPRT: crate::tcflag_t = 0x00000020; pub const ECHOCTL: crate::tcflag_t = 0x00000040; pub const ISIG: crate::tcflag_t = 0x00000080; pub const ICANON: crate::tcflag_t = 0x00000100; pub const PENDIN: crate::tcflag_t = 0x20000000; pub const NOFLSH: crate::tcflag_t = 0x80000000; pub const CIBAUD: crate::tcflag_t = 0o00077600000; pub const CBAUDEX: crate::tcflag_t = 0o000020; pub const VSWTC: usize = 9; pub const OLCUC: crate::tcflag_t = 0o000004; pub const NLDLY: crate::tcflag_t = 0o001400; pub const CRDLY: crate::tcflag_t = 0o030000; pub const TABDLY: crate::tcflag_t = 0o006000; pub const BSDLY: crate::tcflag_t = 0o100000; pub const FFDLY: crate::tcflag_t = 0o040000; pub const VTDLY: crate::tcflag_t = 0o200000; pub const XTABS: crate::tcflag_t = 0o006000; pub const B57600: crate::speed_t = 0o000020; pub const B115200: crate::speed_t = 0o000021; pub const B230400: crate::speed_t = 0o000022; pub const B460800: crate::speed_t = 0o000023; pub const B500000: crate::speed_t = 0o000024; pub const B576000: crate::speed_t = 0o000025; pub const B921600: crate::speed_t = 0o000026; pub const B1000000: crate::speed_t = 0o000027; pub const B1152000: crate::speed_t = 0o000030; pub const B1500000: crate::speed_t = 0o000031; pub const B2000000: crate::speed_t = 0o000032; pub const B2500000: crate::speed_t = 0o000033; pub const B3000000: crate::speed_t = 0o000034; pub const B3500000: crate::speed_t = 0o000035; pub const B4000000: crate::speed_t = 0o000036; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x00080; pub const MAP_NORESERVE: c_int = 0x00040; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const PTRACE_SYSEMU: c_int = 0x1d; pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 0x1e; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EDEADLOCK: c_int = 58; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const EXTPROC: crate::tcflag_t = 0x10000000; pub const F_GETLK: c_int = 12; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 13; pub const F_SETLKW: c_int = 14; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; pub const VMIN: usize = 5; pub const IEXTEN: crate::tcflag_t = 0x00000400; pub const TOSTOP: crate::tcflag_t = 0x00400000; pub const FLUSHO: crate::tcflag_t = 0x00800000; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; // Syscall table pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_waitpid: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_time: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_break: c_long = 17; pub const SYS_oldstat: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_stime: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_oldfstat: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_stty: c_long = 31; pub const SYS_gtty: c_long = 32; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_ftime: c_long = 35; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_prof: c_long = 44; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_lock: c_long = 53; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_mpx: c_long = 56; pub const SYS_setpgid: c_long = 57; pub const SYS_ulimit: c_long = 58; pub const SYS_oldolduname: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sgetmask: c_long = 68; pub const SYS_ssetmask: c_long = 69; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrlimit: c_long = 76; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_select: c_long = 82; pub const SYS_symlink: c_long = 83; pub const SYS_oldlstat: c_long = 84; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_profil: c_long = 98; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_ioperm: c_long = 101; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_olduname: c_long = 109; pub const SYS_iopl: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_vm86: c_long = 113; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_modify_ldt: c_long = 123; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 166; pub const SYS_poll: c_long = 167; pub const SYS_nfsservctl: c_long = 168; pub const SYS_setresgid: c_long = 169; pub const SYS_getresgid: c_long = 170; pub const SYS_prctl: c_long = 171; pub const SYS_rt_sigreturn: c_long = 172; pub const SYS_rt_sigaction: c_long = 173; pub const SYS_rt_sigprocmask: c_long = 174; pub const SYS_rt_sigpending: c_long = 175; pub const SYS_rt_sigtimedwait: c_long = 176; pub const SYS_rt_sigqueueinfo: c_long = 177; pub const SYS_rt_sigsuspend: c_long = 178; pub const SYS_pread64: c_long = 179; pub const SYS_pwrite64: c_long = 180; pub const SYS_chown: c_long = 181; pub const SYS_getcwd: c_long = 182; pub const SYS_capget: c_long = 183; pub const SYS_capset: c_long = 184; pub const SYS_sigaltstack: c_long = 185; pub const SYS_sendfile: c_long = 186; pub const SYS_getpmsg: c_long = 187; pub const SYS_putpmsg: c_long = 188; pub const SYS_vfork: c_long = 189; pub const SYS_ugetrlimit: c_long = 190; pub const SYS_readahead: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_pciconfig_read: c_long = 198; pub const SYS_pciconfig_write: c_long = 199; pub const SYS_pciconfig_iobase: c_long = 200; pub const SYS_multiplexer: c_long = 201; pub const SYS_getdents64: c_long = 202; pub const SYS_pivot_root: c_long = 203; pub const SYS_fcntl64: c_long = 204; pub const SYS_madvise: c_long = 205; pub const SYS_mincore: c_long = 206; pub const SYS_gettid: c_long = 207; pub const SYS_tkill: c_long = 208; pub const SYS_setxattr: c_long = 209; pub const SYS_lsetxattr: c_long = 210; pub const SYS_fsetxattr: c_long = 211; pub const SYS_getxattr: c_long = 212; pub const SYS_lgetxattr: c_long = 213; pub const SYS_fgetxattr: c_long = 214; pub const SYS_listxattr: c_long = 215; pub const SYS_llistxattr: c_long = 216; pub const SYS_flistxattr: c_long = 217; pub const SYS_removexattr: c_long = 218; pub const SYS_lremovexattr: c_long = 219; pub const SYS_fremovexattr: c_long = 220; pub const SYS_futex: c_long = 221; pub const SYS_sched_setaffinity: c_long = 222; pub const SYS_sched_getaffinity: c_long = 223; pub const SYS_tuxcall: c_long = 225; pub const SYS_sendfile64: c_long = 226; pub const SYS_io_setup: c_long = 227; pub const SYS_io_destroy: c_long = 228; pub const SYS_io_getevents: c_long = 229; pub const SYS_io_submit: c_long = 230; pub const SYS_io_cancel: c_long = 231; pub const SYS_set_tid_address: c_long = 232; pub const SYS_fadvise64: c_long = 233; pub const SYS_exit_group: c_long = 234; pub const SYS_lookup_dcookie: c_long = 235; pub const SYS_epoll_create: c_long = 236; pub const SYS_epoll_ctl: c_long = 237; pub const SYS_epoll_wait: c_long = 238; pub const SYS_remap_file_pages: c_long = 239; pub const SYS_timer_create: c_long = 240; pub const SYS_timer_settime: c_long = 241; pub const SYS_timer_gettime: c_long = 242; pub const SYS_timer_getoverrun: c_long = 243; pub const SYS_timer_delete: c_long = 244; pub const SYS_clock_settime: c_long = 245; pub const SYS_clock_gettime: c_long = 246; pub const SYS_clock_getres: c_long = 247; pub const SYS_clock_nanosleep: c_long = 248; pub const SYS_swapcontext: c_long = 249; pub const SYS_tgkill: c_long = 250; pub const SYS_utimes: c_long = 251; pub const SYS_statfs64: c_long = 252; pub const SYS_fstatfs64: c_long = 253; pub const SYS_fadvise64_64: c_long = 254; pub const SYS_rtas: c_long = 255; pub const SYS_sys_debug_setcontext: c_long = 256; pub const SYS_migrate_pages: c_long = 258; pub const SYS_mbind: c_long = 259; pub const SYS_get_mempolicy: c_long = 260; pub const SYS_set_mempolicy: c_long = 261; pub const SYS_mq_open: c_long = 262; pub const SYS_mq_unlink: c_long = 263; pub const SYS_mq_timedsend: c_long = 264; pub const SYS_mq_timedreceive: c_long = 265; pub const SYS_mq_notify: c_long = 266; pub const SYS_mq_getsetattr: c_long = 267; pub const SYS_kexec_load: c_long = 268; pub const SYS_add_key: c_long = 269; pub const SYS_request_key: c_long = 270; pub const SYS_keyctl: c_long = 271; pub const SYS_waitid: c_long = 272; pub const SYS_ioprio_set: c_long = 273; pub const SYS_ioprio_get: c_long = 274; pub const SYS_inotify_init: c_long = 275; pub const SYS_inotify_add_watch: c_long = 276; pub const SYS_inotify_rm_watch: c_long = 277; pub const SYS_spu_run: c_long = 278; pub const SYS_spu_create: c_long = 279; pub const SYS_pselect6: c_long = 280; pub const SYS_ppoll: c_long = 281; pub const SYS_unshare: c_long = 282; pub const SYS_splice: c_long = 283; pub const SYS_tee: c_long = 284; pub const SYS_vmsplice: c_long = 285; pub const SYS_openat: c_long = 286; pub const SYS_mkdirat: c_long = 287; pub const SYS_mknodat: c_long = 288; pub const SYS_fchownat: c_long = 289; pub const SYS_futimesat: c_long = 290; pub const SYS_fstatat64: c_long = 291; pub const SYS_unlinkat: c_long = 292; pub const SYS_renameat: c_long = 293; pub const SYS_linkat: c_long = 294; pub const SYS_symlinkat: c_long = 295; pub const SYS_readlinkat: c_long = 296; pub const SYS_fchmodat: c_long = 297; pub const SYS_faccessat: c_long = 298; pub const SYS_get_robust_list: c_long = 299; pub const SYS_set_robust_list: c_long = 300; pub const SYS_move_pages: c_long = 301; pub const SYS_getcpu: c_long = 302; pub const SYS_epoll_pwait: c_long = 303; pub const SYS_utimensat: c_long = 304; pub const SYS_signalfd: c_long = 305; pub const SYS_timerfd_create: c_long = 306; pub const SYS_eventfd: c_long = 307; pub const SYS_sync_file_range2: c_long = 308; pub const SYS_fallocate: c_long = 309; pub const SYS_subpage_prot: c_long = 310; pub const SYS_timerfd_settime: c_long = 311; pub const SYS_timerfd_gettime: c_long = 312; pub const SYS_signalfd4: c_long = 313; pub const SYS_eventfd2: c_long = 314; pub const SYS_epoll_create1: c_long = 315; pub const SYS_dup3: c_long = 316; pub const SYS_pipe2: c_long = 317; pub const SYS_inotify_init1: c_long = 318; pub const SYS_perf_event_open: c_long = 319; pub const SYS_preadv: c_long = 320; pub const SYS_pwritev: c_long = 321; pub const SYS_rt_tgsigqueueinfo: c_long = 322; pub const SYS_fanotify_init: c_long = 323; pub const SYS_fanotify_mark: c_long = 324; pub const SYS_prlimit64: c_long = 325; pub const SYS_socket: c_long = 326; pub const SYS_bind: c_long = 327; pub const SYS_connect: c_long = 328; pub const SYS_listen: c_long = 329; pub const SYS_accept: c_long = 330; pub const SYS_getsockname: c_long = 331; pub const SYS_getpeername: c_long = 332; pub const SYS_socketpair: c_long = 333; pub const SYS_send: c_long = 334; pub const SYS_sendto: c_long = 335; pub const SYS_recv: c_long = 336; pub const SYS_recvfrom: c_long = 337; pub const SYS_shutdown: c_long = 338; pub const SYS_setsockopt: c_long = 339; pub const SYS_getsockopt: c_long = 340; pub const SYS_sendmsg: c_long = 341; pub const SYS_recvmsg: c_long = 342; pub const SYS_recvmmsg: c_long = 343; pub const SYS_accept4: c_long = 344; pub const SYS_name_to_handle_at: c_long = 345; pub const SYS_open_by_handle_at: c_long = 346; pub const SYS_clock_adjtime: c_long = 347; pub const SYS_syncfs: c_long = 348; pub const SYS_sendmmsg: c_long = 349; pub const SYS_setns: c_long = 350; pub const SYS_process_vm_readv: c_long = 351; pub const SYS_process_vm_writev: c_long = 352; pub const SYS_finit_module: c_long = 353; pub const SYS_kcmp: c_long = 354; pub const SYS_sched_setattr: c_long = 355; pub const SYS_sched_getattr: c_long = 356; pub const SYS_renameat2: c_long = 357; pub const SYS_seccomp: c_long = 358; pub const SYS_getrandom: c_long = 359; pub const SYS_memfd_create: c_long = 360; pub const SYS_bpf: c_long = 361; pub const SYS_execveat: c_long = 362; pub const SYS_switch_endian: c_long = 363; pub const SYS_userfaultfd: c_long = 364; pub const SYS_membarrier: c_long = 365; pub const SYS_mlock2: c_long = 378; pub const SYS_copy_file_range: c_long = 379; pub const SYS_preadv2: c_long = 380; pub const SYS_pwritev2: c_long = 381; pub const SYS_kexec_file_load: c_long = 382; pub const SYS_statx: c_long = 383; pub const SYS_pkey_alloc: c_long = 384; pub const SYS_pkey_free: c_long = 385; pub const SYS_pkey_mprotect: c_long = 386; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_mseal: c_long = 462; libc/src/unix/linux_like/linux/musl/b32/arm/0000775000175000017500000000000015105742312020516 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b32/arm/mod.rs0000644000175000017500000006715615105742312021660 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = u32; s! { pub struct stat { pub st_dev: crate::dev_t, __st_dev_padding: c_int, __st_ino_truncated: c_long, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __st_rdev_padding: c_int, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino_t, } pub struct stat64 { pub st_dev: crate::dev_t, __st_dev_padding: c_int, __st_ino_truncated: c_long, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __st_rdev_padding: c_int, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino_t, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __unused1: c_long, __unused2: c_long, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, __unused1: c_int, pub shm_dtime: crate::time_t, __unused2: c_int, pub shm_ctime: crate::time_t, __unused3: c_int, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: c_ulong, __pad1: c_ulong, __pad2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __unused1: c_int, pub msg_rtime: crate::time_t, __unused2: c_int, pub msg_ctime: crate::time_t, __unused3: c_int, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } pub struct mcontext_t { pub trap_no: c_ulong, pub error_code: c_ulong, pub oldmask: c_ulong, pub arm_r0: c_ulong, pub arm_r1: c_ulong, pub arm_r2: c_ulong, pub arm_r3: c_ulong, pub arm_r4: c_ulong, pub arm_r5: c_ulong, pub arm_r6: c_ulong, pub arm_r7: c_ulong, pub arm_r8: c_ulong, pub arm_r9: c_ulong, pub arm_r10: c_ulong, pub arm_fp: c_ulong, pub arm_ip: c_ulong, pub arm_sp: c_ulong, pub arm_lr: c_ulong, pub arm_pc: c_ulong, pub arm_cpsr: c_ulong, pub fault_address: c_ulong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: crate::sigset_t, pub uc_regspace: [c_ulonglong; 64], } #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: (i64, i64), } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_link) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); } } } } pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const O_DIRECT: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_ASYNC: c_int = 0x2000; pub const O_LARGEFILE: c_int = 0o400000; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_SYNC: c_int = 0x080000; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EDEADLOCK: c_int = EDEADLK; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const MAP_HUGETLB: c_int = 0x040000; pub const F_GETLK: c_int = 12; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 13; pub const F_SETLKW: c_int = 14; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; // Syscall table pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_ptrace: c_long = 26; pub const SYS_pause: c_long = 29; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_setpgid: c_long = 57; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_symlink: c_long = 83; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_vhangup: c_long = 111; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_setresgid: c_long = 170; pub const SYS_getresgid: c_long = 171; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_chown: c_long = 182; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_vfork: c_long = 190; pub const SYS_ugetrlimit: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_lchown32: c_long = 198; pub const SYS_getuid32: c_long = 199; pub const SYS_getgid32: c_long = 200; pub const SYS_geteuid32: c_long = 201; pub const SYS_getegid32: c_long = 202; pub const SYS_setreuid32: c_long = 203; pub const SYS_setregid32: c_long = 204; pub const SYS_getgroups32: c_long = 205; pub const SYS_setgroups32: c_long = 206; pub const SYS_fchown32: c_long = 207; pub const SYS_setresuid32: c_long = 208; pub const SYS_getresuid32: c_long = 209; pub const SYS_setresgid32: c_long = 210; pub const SYS_getresgid32: c_long = 211; pub const SYS_chown32: c_long = 212; pub const SYS_setuid32: c_long = 213; pub const SYS_setgid32: c_long = 214; pub const SYS_setfsuid32: c_long = 215; pub const SYS_setfsgid32: c_long = 216; pub const SYS_getdents64: c_long = 217; pub const SYS_pivot_root: c_long = 218; pub const SYS_mincore: c_long = 219; pub const SYS_madvise: c_long = 220; pub const SYS_fcntl64: c_long = 221; pub const SYS_gettid: c_long = 224; pub const SYS_readahead: c_long = 225; pub const SYS_setxattr: c_long = 226; pub const SYS_lsetxattr: c_long = 227; pub const SYS_fsetxattr: c_long = 228; pub const SYS_getxattr: c_long = 229; pub const SYS_lgetxattr: c_long = 230; pub const SYS_fgetxattr: c_long = 231; pub const SYS_listxattr: c_long = 232; pub const SYS_llistxattr: c_long = 233; pub const SYS_flistxattr: c_long = 234; pub const SYS_removexattr: c_long = 235; pub const SYS_lremovexattr: c_long = 236; pub const SYS_fremovexattr: c_long = 237; pub const SYS_tkill: c_long = 238; pub const SYS_sendfile64: c_long = 239; pub const SYS_futex: c_long = 240; pub const SYS_sched_setaffinity: c_long = 241; pub const SYS_sched_getaffinity: c_long = 242; pub const SYS_io_setup: c_long = 243; pub const SYS_io_destroy: c_long = 244; pub const SYS_io_getevents: c_long = 245; pub const SYS_io_submit: c_long = 246; pub const SYS_io_cancel: c_long = 247; pub const SYS_exit_group: c_long = 248; pub const SYS_lookup_dcookie: c_long = 249; pub const SYS_epoll_create: c_long = 250; pub const SYS_epoll_ctl: c_long = 251; pub const SYS_epoll_wait: c_long = 252; pub const SYS_remap_file_pages: c_long = 253; pub const SYS_set_tid_address: c_long = 256; pub const SYS_timer_create: c_long = 257; pub const SYS_timer_settime: c_long = 258; pub const SYS_timer_gettime: c_long = 259; pub const SYS_timer_getoverrun: c_long = 260; pub const SYS_timer_delete: c_long = 261; pub const SYS_clock_settime: c_long = 262; pub const SYS_clock_gettime: c_long = 263; pub const SYS_clock_getres: c_long = 264; pub const SYS_clock_nanosleep: c_long = 265; pub const SYS_statfs64: c_long = 266; pub const SYS_fstatfs64: c_long = 267; pub const SYS_tgkill: c_long = 268; pub const SYS_utimes: c_long = 269; pub const SYS_pciconfig_iobase: c_long = 271; pub const SYS_pciconfig_read: c_long = 272; pub const SYS_pciconfig_write: c_long = 273; pub const SYS_mq_open: c_long = 274; pub const SYS_mq_unlink: c_long = 275; pub const SYS_mq_timedsend: c_long = 276; pub const SYS_mq_timedreceive: c_long = 277; pub const SYS_mq_notify: c_long = 278; pub const SYS_mq_getsetattr: c_long = 279; pub const SYS_waitid: c_long = 280; pub const SYS_socket: c_long = 281; pub const SYS_bind: c_long = 282; pub const SYS_connect: c_long = 283; pub const SYS_listen: c_long = 284; pub const SYS_accept: c_long = 285; pub const SYS_getsockname: c_long = 286; pub const SYS_getpeername: c_long = 287; pub const SYS_socketpair: c_long = 288; pub const SYS_send: c_long = 289; pub const SYS_sendto: c_long = 290; pub const SYS_recv: c_long = 291; pub const SYS_recvfrom: c_long = 292; pub const SYS_shutdown: c_long = 293; pub const SYS_setsockopt: c_long = 294; pub const SYS_getsockopt: c_long = 295; pub const SYS_sendmsg: c_long = 296; pub const SYS_recvmsg: c_long = 297; pub const SYS_semop: c_long = 298; pub const SYS_semget: c_long = 299; pub const SYS_semctl: c_long = 300; pub const SYS_msgsnd: c_long = 301; pub const SYS_msgrcv: c_long = 302; pub const SYS_msgget: c_long = 303; pub const SYS_msgctl: c_long = 304; pub const SYS_shmat: c_long = 305; pub const SYS_shmdt: c_long = 306; pub const SYS_shmget: c_long = 307; pub const SYS_shmctl: c_long = 308; pub const SYS_add_key: c_long = 309; pub const SYS_request_key: c_long = 310; pub const SYS_keyctl: c_long = 311; pub const SYS_semtimedop: c_long = 312; pub const SYS_vserver: c_long = 313; pub const SYS_ioprio_set: c_long = 314; pub const SYS_ioprio_get: c_long = 315; pub const SYS_inotify_init: c_long = 316; pub const SYS_inotify_add_watch: c_long = 317; pub const SYS_inotify_rm_watch: c_long = 318; pub const SYS_mbind: c_long = 319; pub const SYS_get_mempolicy: c_long = 320; pub const SYS_set_mempolicy: c_long = 321; pub const SYS_openat: c_long = 322; pub const SYS_mkdirat: c_long = 323; pub const SYS_mknodat: c_long = 324; pub const SYS_fchownat: c_long = 325; pub const SYS_futimesat: c_long = 326; pub const SYS_fstatat64: c_long = 327; pub const SYS_unlinkat: c_long = 328; pub const SYS_renameat: c_long = 329; pub const SYS_linkat: c_long = 330; pub const SYS_symlinkat: c_long = 331; pub const SYS_readlinkat: c_long = 332; pub const SYS_fchmodat: c_long = 333; pub const SYS_faccessat: c_long = 334; pub const SYS_pselect6: c_long = 335; pub const SYS_ppoll: c_long = 336; pub const SYS_unshare: c_long = 337; pub const SYS_set_robust_list: c_long = 338; pub const SYS_get_robust_list: c_long = 339; pub const SYS_splice: c_long = 340; pub const SYS_tee: c_long = 342; pub const SYS_vmsplice: c_long = 343; pub const SYS_move_pages: c_long = 344; pub const SYS_getcpu: c_long = 345; pub const SYS_epoll_pwait: c_long = 346; pub const SYS_kexec_load: c_long = 347; pub const SYS_utimensat: c_long = 348; pub const SYS_signalfd: c_long = 349; pub const SYS_timerfd_create: c_long = 350; pub const SYS_eventfd: c_long = 351; pub const SYS_fallocate: c_long = 352; pub const SYS_timerfd_settime: c_long = 353; pub const SYS_timerfd_gettime: c_long = 354; pub const SYS_signalfd4: c_long = 355; pub const SYS_eventfd2: c_long = 356; pub const SYS_epoll_create1: c_long = 357; pub const SYS_dup3: c_long = 358; pub const SYS_pipe2: c_long = 359; pub const SYS_inotify_init1: c_long = 360; pub const SYS_preadv: c_long = 361; pub const SYS_pwritev: c_long = 362; pub const SYS_rt_tgsigqueueinfo: c_long = 363; pub const SYS_perf_event_open: c_long = 364; pub const SYS_recvmmsg: c_long = 365; pub const SYS_accept4: c_long = 366; pub const SYS_fanotify_init: c_long = 367; pub const SYS_fanotify_mark: c_long = 368; pub const SYS_prlimit64: c_long = 369; pub const SYS_name_to_handle_at: c_long = 370; pub const SYS_open_by_handle_at: c_long = 371; pub const SYS_clock_adjtime: c_long = 372; pub const SYS_syncfs: c_long = 373; pub const SYS_sendmmsg: c_long = 374; pub const SYS_setns: c_long = 375; pub const SYS_process_vm_readv: c_long = 376; pub const SYS_process_vm_writev: c_long = 377; pub const SYS_kcmp: c_long = 378; pub const SYS_finit_module: c_long = 379; pub const SYS_sched_setattr: c_long = 380; pub const SYS_sched_getattr: c_long = 381; pub const SYS_renameat2: c_long = 382; pub const SYS_seccomp: c_long = 383; pub const SYS_getrandom: c_long = 384; pub const SYS_memfd_create: c_long = 385; pub const SYS_bpf: c_long = 386; pub const SYS_execveat: c_long = 387; pub const SYS_userfaultfd: c_long = 388; pub const SYS_membarrier: c_long = 389; pub const SYS_mlock2: c_long = 390; pub const SYS_copy_file_range: c_long = 391; pub const SYS_preadv2: c_long = 392; pub const SYS_pwritev2: c_long = 393; pub const SYS_pkey_mprotect: c_long = 394; pub const SYS_pkey_alloc: c_long = 395; pub const SYS_pkey_free: c_long = 396; pub const SYS_statx: c_long = 397; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_mseal: c_long = 462; libc/src/unix/linux_like/linux/musl/b32/mips/0000775000175000017500000000000015105742312020707 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b32/mips/mod.rs0000644000175000017500000007244215105742312022043 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = c_int; s! { pub struct stat { pub st_dev: crate::dev_t, __st_padding1: [c_long; 2], pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __st_padding2: [c_long; 2], pub st_size: off_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, __st_padding3: c_long, pub st_blocks: crate::blkcnt_t, __st_padding4: [c_long; 14], } pub struct stat64 { pub st_dev: crate::dev_t, __st_padding1: [c_long; 2], pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __st_padding2: [c_long; 2], pub st_size: off_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, __st_padding3: c_long, pub st_blocks: crate::blkcnt64_t, __st_padding4: [c_long; 14], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __unused1: c_long, __unused2: c_long, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: c_ulong, __pad1: c_ulong, __pad2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, #[cfg(target_endian = "big")] __unused1: c_int, pub msg_stime: crate::time_t, #[cfg(target_endian = "little")] __unused1: c_int, #[cfg(target_endian = "big")] __unused2: c_int, pub msg_rtime: crate::time_t, #[cfg(target_endian = "little")] __unused2: c_int, #[cfg(target_endian = "big")] __unused3: c_int, pub msg_ctime: crate::time_t, #[cfg(target_endian = "little")] __unused3: c_int, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } pub struct statfs { pub f_type: c_ulong, pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_ulong, pub f_flags: c_ulong, pub f_spare: [c_ulong; 5], } pub struct statfs64 { pub f_type: c_ulong, pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_ulong, pub f_flags: c_ulong, pub f_spare: [c_ulong; 5], } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f32; 4], } } pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const O_DIRECT: c_int = 0o100000; pub const O_DIRECTORY: c_int = 0o200000; pub const O_NOFOLLOW: c_int = 0o400000; pub const O_ASYNC: c_int = 0o10000; pub const O_LARGEFILE: c_int = 0x2000; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const O_APPEND: c_int = 0o010; pub const O_CREAT: c_int = 0o400; pub const O_EXCL: c_int = 0o2000; pub const O_NOCTTY: c_int = 0o4000; pub const O_NONBLOCK: c_int = 0o200; pub const O_SYNC: c_int = 0o40020; pub const O_RSYNC: c_int = 0o40020; pub const O_DSYNC: c_int = 0o020; pub const MAP_ANON: c_int = 0x800; pub const MAP_GROWSDOWN: c_int = 0x1000; pub const MAP_DENYWRITE: c_int = 0x2000; pub const MAP_EXECUTABLE: c_int = 0x4000; pub const MAP_LOCKED: c_int = 0x8000; pub const MAP_NORESERVE: c_int = 0x0400; pub const MAP_POPULATE: c_int = 0x10000; pub const MAP_NONBLOCK: c_int = 0x20000; pub const MAP_STACK: c_int = 0x40000; pub const MAP_HUGETLB: c_int = 0x80000; pub const EDEADLK: c_int = 45; pub const ENAMETOOLONG: c_int = 78; pub const ENOLCK: c_int = 46; pub const ENOSYS: c_int = 89; pub const ENOTEMPTY: c_int = 93; pub const ELOOP: c_int = 90; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EBADE: c_int = 50; pub const EBADR: c_int = 51; pub const EXFULL: c_int = 52; pub const ENOANO: c_int = 53; pub const EBADRQC: c_int = 54; pub const EBADSLT: c_int = 55; pub const EDEADLOCK: c_int = 56; pub const EMULTIHOP: c_int = 74; pub const EOVERFLOW: c_int = 79; pub const ENOTUNIQ: c_int = 80; pub const EBADFD: c_int = 81; pub const EBADMSG: c_int = 77; pub const EREMCHG: c_int = 82; pub const ELIBACC: c_int = 83; pub const ELIBBAD: c_int = 84; pub const ELIBSCN: c_int = 85; pub const ELIBMAX: c_int = 86; pub const ELIBEXEC: c_int = 87; pub const EILSEQ: c_int = 88; pub const ERESTART: c_int = 91; pub const ESTRPIPE: c_int = 92; pub const EUSERS: c_int = 94; pub const ENOTSOCK: c_int = 95; pub const EDESTADDRREQ: c_int = 96; pub const EMSGSIZE: c_int = 97; pub const EPROTOTYPE: c_int = 98; pub const ENOPROTOOPT: c_int = 99; pub const EPROTONOSUPPORT: c_int = 120; pub const ESOCKTNOSUPPORT: c_int = 121; pub const EOPNOTSUPP: c_int = 122; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 123; pub const EAFNOSUPPORT: c_int = 124; pub const EADDRINUSE: c_int = 125; pub const EADDRNOTAVAIL: c_int = 126; pub const ENETDOWN: c_int = 127; pub const ENETUNREACH: c_int = 128; pub const ENETRESET: c_int = 129; pub const ECONNABORTED: c_int = 130; pub const ECONNRESET: c_int = 131; pub const ENOBUFS: c_int = 132; pub const EISCONN: c_int = 133; pub const ENOTCONN: c_int = 134; pub const ESHUTDOWN: c_int = 143; pub const ETOOMANYREFS: c_int = 144; pub const ETIMEDOUT: c_int = 145; pub const ECONNREFUSED: c_int = 146; pub const EHOSTDOWN: c_int = 147; pub const EHOSTUNREACH: c_int = 148; pub const EALREADY: c_int = 149; pub const EINPROGRESS: c_int = 150; pub const ESTALE: c_int = 151; pub const EUCLEAN: c_int = 135; pub const ENOTNAM: c_int = 137; pub const ENAVAIL: c_int = 138; pub const EISNAM: c_int = 139; pub const EREMOTEIO: c_int = 140; pub const EDQUOT: c_int = 1133; pub const ENOMEDIUM: c_int = 159; pub const EMEDIUMTYPE: c_int = 160; pub const ECANCELED: c_int = 158; pub const ENOKEY: c_int = 161; pub const EKEYEXPIRED: c_int = 162; pub const EKEYREVOKED: c_int = 163; pub const EKEYREJECTED: c_int = 164; pub const EOWNERDEAD: c_int = 165; pub const ENOTRECOVERABLE: c_int = 166; pub const EHWPOISON: c_int = 168; pub const ERFKILL: c_int = 167; pub const SOCK_STREAM: c_int = 2; pub const SOCK_DGRAM: c_int = 1; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 8; pub const SA_NOCLDWAIT: c_int = 0x10000; pub const SIGCHLD: c_int = 18; pub const SIGBUS: c_int = 10; pub const SIGTTIN: c_int = 26; pub const SIGTTOU: c_int = 27; pub const SIGXCPU: c_int = 30; pub const SIGXFSZ: c_int = 31; pub const SIGVTALRM: c_int = 28; pub const SIGPROF: c_int = 29; pub const SIGWINCH: c_int = 20; pub const SIGUSR1: c_int = 16; pub const SIGUSR2: c_int = 17; pub const SIGCONT: c_int = 25; pub const SIGSTOP: c_int = 23; pub const SIGTSTP: c_int = 24; pub const SIGURG: c_int = 21; pub const SIGIO: c_int = 22; pub const SIGSYS: c_int = 12; pub const SIGSTKFLT: c_int = 7; pub const SIGPOLL: c_int = crate::SIGIO; pub const SIGPWR: c_int = 19; pub const SIG_SETMASK: c_int = 3; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const EXTPROC: crate::tcflag_t = 0o200000; pub const F_GETLK: c_int = 33; pub const F_GETOWN: c_int = 23; pub const F_SETLK: c_int = 34; pub const F_SETLKW: c_int = 35; pub const F_SETOWN: c_int = 24; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: crate::tcflag_t = 0o000400; pub const TOSTOP: crate::tcflag_t = 0o100000; pub const FLUSHO: crate::tcflag_t = 0o020000; pub const POLLWRNORM: c_short = 0x4; pub const POLLWRBAND: c_short = 0x100; pub const SYS_syscall: c_long = 4000 + 0; pub const SYS_exit: c_long = 4000 + 1; pub const SYS_fork: c_long = 4000 + 2; pub const SYS_read: c_long = 4000 + 3; pub const SYS_write: c_long = 4000 + 4; pub const SYS_open: c_long = 4000 + 5; pub const SYS_close: c_long = 4000 + 6; pub const SYS_waitpid: c_long = 4000 + 7; pub const SYS_creat: c_long = 4000 + 8; pub const SYS_link: c_long = 4000 + 9; pub const SYS_unlink: c_long = 4000 + 10; pub const SYS_execve: c_long = 4000 + 11; pub const SYS_chdir: c_long = 4000 + 12; pub const SYS_time: c_long = 4000 + 13; pub const SYS_mknod: c_long = 4000 + 14; pub const SYS_chmod: c_long = 4000 + 15; pub const SYS_lchown: c_long = 4000 + 16; pub const SYS_break: c_long = 4000 + 17; pub const SYS_lseek: c_long = 4000 + 19; pub const SYS_getpid: c_long = 4000 + 20; pub const SYS_mount: c_long = 4000 + 21; pub const SYS_umount: c_long = 4000 + 22; pub const SYS_setuid: c_long = 4000 + 23; pub const SYS_getuid: c_long = 4000 + 24; pub const SYS_stime: c_long = 4000 + 25; pub const SYS_ptrace: c_long = 4000 + 26; pub const SYS_alarm: c_long = 4000 + 27; pub const SYS_pause: c_long = 4000 + 29; pub const SYS_utime: c_long = 4000 + 30; pub const SYS_stty: c_long = 4000 + 31; pub const SYS_gtty: c_long = 4000 + 32; pub const SYS_access: c_long = 4000 + 33; pub const SYS_nice: c_long = 4000 + 34; pub const SYS_ftime: c_long = 4000 + 35; pub const SYS_sync: c_long = 4000 + 36; pub const SYS_kill: c_long = 4000 + 37; pub const SYS_rename: c_long = 4000 + 38; pub const SYS_mkdir: c_long = 4000 + 39; pub const SYS_rmdir: c_long = 4000 + 40; pub const SYS_dup: c_long = 4000 + 41; pub const SYS_pipe: c_long = 4000 + 42; pub const SYS_times: c_long = 4000 + 43; pub const SYS_prof: c_long = 4000 + 44; pub const SYS_brk: c_long = 4000 + 45; pub const SYS_setgid: c_long = 4000 + 46; pub const SYS_getgid: c_long = 4000 + 47; pub const SYS_signal: c_long = 4000 + 48; pub const SYS_geteuid: c_long = 4000 + 49; pub const SYS_getegid: c_long = 4000 + 50; pub const SYS_acct: c_long = 4000 + 51; pub const SYS_umount2: c_long = 4000 + 52; pub const SYS_lock: c_long = 4000 + 53; pub const SYS_ioctl: c_long = 4000 + 54; pub const SYS_fcntl: c_long = 4000 + 55; pub const SYS_mpx: c_long = 4000 + 56; pub const SYS_setpgid: c_long = 4000 + 57; pub const SYS_ulimit: c_long = 4000 + 58; pub const SYS_umask: c_long = 4000 + 60; pub const SYS_chroot: c_long = 4000 + 61; pub const SYS_ustat: c_long = 4000 + 62; pub const SYS_dup2: c_long = 4000 + 63; pub const SYS_getppid: c_long = 4000 + 64; pub const SYS_getpgrp: c_long = 4000 + 65; pub const SYS_setsid: c_long = 4000 + 66; pub const SYS_sigaction: c_long = 4000 + 67; pub const SYS_sgetmask: c_long = 4000 + 68; pub const SYS_ssetmask: c_long = 4000 + 69; pub const SYS_setreuid: c_long = 4000 + 70; pub const SYS_setregid: c_long = 4000 + 71; pub const SYS_sigsuspend: c_long = 4000 + 72; pub const SYS_sigpending: c_long = 4000 + 73; pub const SYS_sethostname: c_long = 4000 + 74; pub const SYS_setrlimit: c_long = 4000 + 75; pub const SYS_getrlimit: c_long = 4000 + 76; pub const SYS_getrusage: c_long = 4000 + 77; pub const SYS_gettimeofday: c_long = 4000 + 78; pub const SYS_settimeofday: c_long = 4000 + 79; pub const SYS_getgroups: c_long = 4000 + 80; pub const SYS_setgroups: c_long = 4000 + 81; pub const SYS_symlink: c_long = 4000 + 83; pub const SYS_readlink: c_long = 4000 + 85; pub const SYS_uselib: c_long = 4000 + 86; pub const SYS_swapon: c_long = 4000 + 87; pub const SYS_reboot: c_long = 4000 + 88; pub const SYS_readdir: c_long = 4000 + 89; pub const SYS_mmap: c_long = 4000 + 90; pub const SYS_munmap: c_long = 4000 + 91; pub const SYS_truncate: c_long = 4000 + 92; pub const SYS_ftruncate: c_long = 4000 + 93; pub const SYS_fchmod: c_long = 4000 + 94; pub const SYS_fchown: c_long = 4000 + 95; pub const SYS_getpriority: c_long = 4000 + 96; pub const SYS_setpriority: c_long = 4000 + 97; pub const SYS_profil: c_long = 4000 + 98; pub const SYS_statfs: c_long = 4000 + 99; pub const SYS_fstatfs: c_long = 4000 + 100; pub const SYS_ioperm: c_long = 4000 + 101; pub const SYS_socketcall: c_long = 4000 + 102; pub const SYS_syslog: c_long = 4000 + 103; pub const SYS_setitimer: c_long = 4000 + 104; pub const SYS_getitimer: c_long = 4000 + 105; pub const SYS_stat: c_long = 4000 + 106; pub const SYS_lstat: c_long = 4000 + 107; pub const SYS_fstat: c_long = 4000 + 108; pub const SYS_iopl: c_long = 4000 + 110; pub const SYS_vhangup: c_long = 4000 + 111; pub const SYS_idle: c_long = 4000 + 112; pub const SYS_vm86: c_long = 4000 + 113; pub const SYS_wait4: c_long = 4000 + 114; pub const SYS_swapoff: c_long = 4000 + 115; pub const SYS_sysinfo: c_long = 4000 + 116; pub const SYS_ipc: c_long = 4000 + 117; pub const SYS_fsync: c_long = 4000 + 118; pub const SYS_sigreturn: c_long = 4000 + 119; pub const SYS_clone: c_long = 4000 + 120; pub const SYS_setdomainname: c_long = 4000 + 121; pub const SYS_uname: c_long = 4000 + 122; pub const SYS_modify_ldt: c_long = 4000 + 123; pub const SYS_adjtimex: c_long = 4000 + 124; pub const SYS_mprotect: c_long = 4000 + 125; pub const SYS_sigprocmask: c_long = 4000 + 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 4000 + 127; pub const SYS_init_module: c_long = 4000 + 128; pub const SYS_delete_module: c_long = 4000 + 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 4000 + 130; pub const SYS_quotactl: c_long = 4000 + 131; pub const SYS_getpgid: c_long = 4000 + 132; pub const SYS_fchdir: c_long = 4000 + 133; pub const SYS_bdflush: c_long = 4000 + 134; pub const SYS_sysfs: c_long = 4000 + 135; pub const SYS_personality: c_long = 4000 + 136; pub const SYS_afs_syscall: c_long = 4000 + 137; pub const SYS_setfsuid: c_long = 4000 + 138; pub const SYS_setfsgid: c_long = 4000 + 139; pub const SYS__llseek: c_long = 4000 + 140; pub const SYS_getdents: c_long = 4000 + 141; pub const SYS_flock: c_long = 4000 + 143; pub const SYS_msync: c_long = 4000 + 144; pub const SYS_readv: c_long = 4000 + 145; pub const SYS_writev: c_long = 4000 + 146; pub const SYS_cacheflush: c_long = 4000 + 147; pub const SYS_cachectl: c_long = 4000 + 148; pub const SYS_sysmips: c_long = 4000 + 149; pub const SYS_getsid: c_long = 4000 + 151; pub const SYS_fdatasync: c_long = 4000 + 152; pub const SYS__sysctl: c_long = 4000 + 153; pub const SYS_mlock: c_long = 4000 + 154; pub const SYS_munlock: c_long = 4000 + 155; pub const SYS_mlockall: c_long = 4000 + 156; pub const SYS_munlockall: c_long = 4000 + 157; pub const SYS_sched_setparam: c_long = 4000 + 158; pub const SYS_sched_getparam: c_long = 4000 + 159; pub const SYS_sched_setscheduler: c_long = 4000 + 160; pub const SYS_sched_getscheduler: c_long = 4000 + 161; pub const SYS_sched_yield: c_long = 4000 + 162; pub const SYS_sched_get_priority_max: c_long = 4000 + 163; pub const SYS_sched_get_priority_min: c_long = 4000 + 164; pub const SYS_sched_rr_get_interval: c_long = 4000 + 165; pub const SYS_nanosleep: c_long = 4000 + 166; pub const SYS_mremap: c_long = 4000 + 167; pub const SYS_accept: c_long = 4000 + 168; pub const SYS_bind: c_long = 4000 + 169; pub const SYS_connect: c_long = 4000 + 170; pub const SYS_getpeername: c_long = 4000 + 171; pub const SYS_getsockname: c_long = 4000 + 172; pub const SYS_getsockopt: c_long = 4000 + 173; pub const SYS_listen: c_long = 4000 + 174; pub const SYS_recv: c_long = 4000 + 175; pub const SYS_recvfrom: c_long = 4000 + 176; pub const SYS_recvmsg: c_long = 4000 + 177; pub const SYS_send: c_long = 4000 + 178; pub const SYS_sendmsg: c_long = 4000 + 179; pub const SYS_sendto: c_long = 4000 + 180; pub const SYS_setsockopt: c_long = 4000 + 181; pub const SYS_shutdown: c_long = 4000 + 182; pub const SYS_socket: c_long = 4000 + 183; pub const SYS_socketpair: c_long = 4000 + 184; pub const SYS_setresuid: c_long = 4000 + 185; pub const SYS_getresuid: c_long = 4000 + 186; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 4000 + 187; pub const SYS_poll: c_long = 4000 + 188; pub const SYS_nfsservctl: c_long = 4000 + 189; pub const SYS_setresgid: c_long = 4000 + 190; pub const SYS_getresgid: c_long = 4000 + 191; pub const SYS_prctl: c_long = 4000 + 192; pub const SYS_rt_sigreturn: c_long = 4000 + 193; pub const SYS_rt_sigaction: c_long = 4000 + 194; pub const SYS_rt_sigprocmask: c_long = 4000 + 195; pub const SYS_rt_sigpending: c_long = 4000 + 196; pub const SYS_rt_sigtimedwait: c_long = 4000 + 197; pub const SYS_rt_sigqueueinfo: c_long = 4000 + 198; pub const SYS_rt_sigsuspend: c_long = 4000 + 199; pub const SYS_chown: c_long = 4000 + 202; pub const SYS_getcwd: c_long = 4000 + 203; pub const SYS_capget: c_long = 4000 + 204; pub const SYS_capset: c_long = 4000 + 205; pub const SYS_sigaltstack: c_long = 4000 + 206; pub const SYS_sendfile: c_long = 4000 + 207; pub const SYS_getpmsg: c_long = 4000 + 208; pub const SYS_putpmsg: c_long = 4000 + 209; pub const SYS_mmap2: c_long = 4000 + 210; pub const SYS_truncate64: c_long = 4000 + 211; pub const SYS_ftruncate64: c_long = 4000 + 212; pub const SYS_stat64: c_long = 4000 + 213; pub const SYS_lstat64: c_long = 4000 + 214; pub const SYS_fstat64: c_long = 4000 + 215; pub const SYS_pivot_root: c_long = 4000 + 216; pub const SYS_mincore: c_long = 4000 + 217; pub const SYS_madvise: c_long = 4000 + 218; pub const SYS_getdents64: c_long = 4000 + 219; pub const SYS_fcntl64: c_long = 4000 + 220; pub const SYS_gettid: c_long = 4000 + 222; pub const SYS_readahead: c_long = 4000 + 223; pub const SYS_setxattr: c_long = 4000 + 224; pub const SYS_lsetxattr: c_long = 4000 + 225; pub const SYS_fsetxattr: c_long = 4000 + 226; pub const SYS_getxattr: c_long = 4000 + 227; pub const SYS_lgetxattr: c_long = 4000 + 228; pub const SYS_fgetxattr: c_long = 4000 + 229; pub const SYS_listxattr: c_long = 4000 + 230; pub const SYS_llistxattr: c_long = 4000 + 231; pub const SYS_flistxattr: c_long = 4000 + 232; pub const SYS_removexattr: c_long = 4000 + 233; pub const SYS_lremovexattr: c_long = 4000 + 234; pub const SYS_fremovexattr: c_long = 4000 + 235; pub const SYS_tkill: c_long = 4000 + 236; pub const SYS_sendfile64: c_long = 4000 + 237; pub const SYS_futex: c_long = 4000 + 238; pub const SYS_sched_setaffinity: c_long = 4000 + 239; pub const SYS_sched_getaffinity: c_long = 4000 + 240; pub const SYS_io_setup: c_long = 4000 + 241; pub const SYS_io_destroy: c_long = 4000 + 242; pub const SYS_io_getevents: c_long = 4000 + 243; pub const SYS_io_submit: c_long = 4000 + 244; pub const SYS_io_cancel: c_long = 4000 + 245; pub const SYS_exit_group: c_long = 4000 + 246; pub const SYS_lookup_dcookie: c_long = 4000 + 247; pub const SYS_epoll_create: c_long = 4000 + 248; pub const SYS_epoll_ctl: c_long = 4000 + 249; pub const SYS_epoll_wait: c_long = 4000 + 250; pub const SYS_remap_file_pages: c_long = 4000 + 251; pub const SYS_set_tid_address: c_long = 4000 + 252; pub const SYS_restart_syscall: c_long = 4000 + 253; pub const SYS_statfs64: c_long = 4000 + 255; pub const SYS_fstatfs64: c_long = 4000 + 256; pub const SYS_timer_create: c_long = 4000 + 257; pub const SYS_timer_settime: c_long = 4000 + 258; pub const SYS_timer_gettime: c_long = 4000 + 259; pub const SYS_timer_getoverrun: c_long = 4000 + 260; pub const SYS_timer_delete: c_long = 4000 + 261; pub const SYS_clock_settime: c_long = 4000 + 262; pub const SYS_clock_gettime: c_long = 4000 + 263; pub const SYS_clock_getres: c_long = 4000 + 264; pub const SYS_clock_nanosleep: c_long = 4000 + 265; pub const SYS_tgkill: c_long = 4000 + 266; pub const SYS_utimes: c_long = 4000 + 267; pub const SYS_mbind: c_long = 4000 + 268; pub const SYS_get_mempolicy: c_long = 4000 + 269; pub const SYS_set_mempolicy: c_long = 4000 + 270; pub const SYS_mq_open: c_long = 4000 + 271; pub const SYS_mq_unlink: c_long = 4000 + 272; pub const SYS_mq_timedsend: c_long = 4000 + 273; pub const SYS_mq_timedreceive: c_long = 4000 + 274; pub const SYS_mq_notify: c_long = 4000 + 275; pub const SYS_mq_getsetattr: c_long = 4000 + 276; pub const SYS_vserver: c_long = 4000 + 277; pub const SYS_waitid: c_long = 4000 + 278; /* pub const SYS_sys_setaltroot: c_long = 4000 + 279; */ pub const SYS_add_key: c_long = 4000 + 280; pub const SYS_request_key: c_long = 4000 + 281; pub const SYS_keyctl: c_long = 4000 + 282; pub const SYS_set_thread_area: c_long = 4000 + 283; pub const SYS_inotify_init: c_long = 4000 + 284; pub const SYS_inotify_add_watch: c_long = 4000 + 285; pub const SYS_inotify_rm_watch: c_long = 4000 + 286; pub const SYS_migrate_pages: c_long = 4000 + 287; pub const SYS_openat: c_long = 4000 + 288; pub const SYS_mkdirat: c_long = 4000 + 289; pub const SYS_mknodat: c_long = 4000 + 290; pub const SYS_fchownat: c_long = 4000 + 291; pub const SYS_futimesat: c_long = 4000 + 292; pub const SYS_unlinkat: c_long = 4000 + 294; pub const SYS_renameat: c_long = 4000 + 295; pub const SYS_linkat: c_long = 4000 + 296; pub const SYS_symlinkat: c_long = 4000 + 297; pub const SYS_readlinkat: c_long = 4000 + 298; pub const SYS_fchmodat: c_long = 4000 + 299; pub const SYS_faccessat: c_long = 4000 + 300; pub const SYS_pselect6: c_long = 4000 + 301; pub const SYS_ppoll: c_long = 4000 + 302; pub const SYS_unshare: c_long = 4000 + 303; pub const SYS_splice: c_long = 4000 + 304; pub const SYS_sync_file_range: c_long = 4000 + 305; pub const SYS_tee: c_long = 4000 + 306; pub const SYS_vmsplice: c_long = 4000 + 307; pub const SYS_move_pages: c_long = 4000 + 308; pub const SYS_set_robust_list: c_long = 4000 + 309; pub const SYS_get_robust_list: c_long = 4000 + 310; pub const SYS_kexec_load: c_long = 4000 + 311; pub const SYS_getcpu: c_long = 4000 + 312; pub const SYS_epoll_pwait: c_long = 4000 + 313; pub const SYS_ioprio_set: c_long = 4000 + 314; pub const SYS_ioprio_get: c_long = 4000 + 315; pub const SYS_utimensat: c_long = 4000 + 316; pub const SYS_signalfd: c_long = 4000 + 317; pub const SYS_timerfd: c_long = 4000 + 318; pub const SYS_eventfd: c_long = 4000 + 319; pub const SYS_fallocate: c_long = 4000 + 320; pub const SYS_timerfd_create: c_long = 4000 + 321; pub const SYS_timerfd_gettime: c_long = 4000 + 322; pub const SYS_timerfd_settime: c_long = 4000 + 323; pub const SYS_signalfd4: c_long = 4000 + 324; pub const SYS_eventfd2: c_long = 4000 + 325; pub const SYS_epoll_create1: c_long = 4000 + 326; pub const SYS_dup3: c_long = 4000 + 327; pub const SYS_pipe2: c_long = 4000 + 328; pub const SYS_inotify_init1: c_long = 4000 + 329; pub const SYS_preadv: c_long = 4000 + 330; pub const SYS_pwritev: c_long = 4000 + 331; pub const SYS_rt_tgsigqueueinfo: c_long = 4000 + 332; pub const SYS_perf_event_open: c_long = 4000 + 333; pub const SYS_accept4: c_long = 4000 + 334; pub const SYS_recvmmsg: c_long = 4000 + 335; pub const SYS_fanotify_init: c_long = 4000 + 336; pub const SYS_fanotify_mark: c_long = 4000 + 337; pub const SYS_prlimit64: c_long = 4000 + 338; pub const SYS_name_to_handle_at: c_long = 4000 + 339; pub const SYS_open_by_handle_at: c_long = 4000 + 340; pub const SYS_clock_adjtime: c_long = 4000 + 341; pub const SYS_syncfs: c_long = 4000 + 342; pub const SYS_sendmmsg: c_long = 4000 + 343; pub const SYS_setns: c_long = 4000 + 344; pub const SYS_process_vm_readv: c_long = 4000 + 345; pub const SYS_process_vm_writev: c_long = 4000 + 346; pub const SYS_kcmp: c_long = 4000 + 347; pub const SYS_finit_module: c_long = 4000 + 348; pub const SYS_sched_setattr: c_long = 4000 + 349; pub const SYS_sched_getattr: c_long = 4000 + 350; pub const SYS_renameat2: c_long = 4000 + 351; pub const SYS_seccomp: c_long = 4000 + 352; pub const SYS_getrandom: c_long = 4000 + 353; pub const SYS_memfd_create: c_long = 4000 + 354; pub const SYS_bpf: c_long = 4000 + 355; pub const SYS_execveat: c_long = 4000 + 356; pub const SYS_userfaultfd: c_long = 4000 + 357; pub const SYS_membarrier: c_long = 4000 + 358; pub const SYS_mlock2: c_long = 4000 + 359; pub const SYS_copy_file_range: c_long = 4000 + 360; pub const SYS_preadv2: c_long = 4000 + 361; pub const SYS_pwritev2: c_long = 4000 + 362; pub const SYS_pkey_mprotect: c_long = 4000 + 363; pub const SYS_pkey_alloc: c_long = 4000 + 364; pub const SYS_pkey_free: c_long = 4000 + 365; pub const SYS_statx: c_long = 4000 + 366; pub const SYS_pidfd_send_signal: c_long = 4000 + 424; pub const SYS_io_uring_setup: c_long = 4000 + 425; pub const SYS_io_uring_enter: c_long = 4000 + 426; pub const SYS_io_uring_register: c_long = 4000 + 427; pub const SYS_open_tree: c_long = 4000 + 428; pub const SYS_move_mount: c_long = 4000 + 429; pub const SYS_fsopen: c_long = 4000 + 430; pub const SYS_fsconfig: c_long = 4000 + 431; pub const SYS_fsmount: c_long = 4000 + 432; pub const SYS_fspick: c_long = 4000 + 433; pub const SYS_pidfd_open: c_long = 4000 + 434; pub const SYS_clone3: c_long = 4000 + 435; pub const SYS_close_range: c_long = 4000 + 436; pub const SYS_openat2: c_long = 4000 + 437; pub const SYS_pidfd_getfd: c_long = 4000 + 438; pub const SYS_faccessat2: c_long = 4000 + 439; pub const SYS_process_madvise: c_long = 4000 + 440; pub const SYS_epoll_pwait2: c_long = 4000 + 441; pub const SYS_mount_setattr: c_long = 4000 + 442; pub const SYS_quotactl_fd: c_long = 4000 + 443; pub const SYS_landlock_create_ruleset: c_long = 4000 + 444; pub const SYS_landlock_add_rule: c_long = 4000 + 445; pub const SYS_landlock_restrict_self: c_long = 4000 + 446; pub const SYS_memfd_secret: c_long = 4000 + 447; pub const SYS_process_mrelease: c_long = 4000 + 448; pub const SYS_futex_waitv: c_long = 4000 + 449; pub const SYS_set_mempolicy_home_node: c_long = 4000 + 450; libc/src/unix/linux_like/linux/musl/b32/hexagon.rs0000644000175000017500000005171315105742312021743 0ustar bdrungbdrunguse crate::prelude::*; pub type wchar_t = u32; pub type stat64 = crate::stat; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: c_ulonglong, pub st_mode: c_uint, pub st_nlink: c_uint, pub st_uid: c_uint, pub st_gid: c_uint, pub st_rdev: c_ulonglong, __st_rdev_padding: c_ulong, pub st_size: c_longlong, pub st_blksize: crate::blksize_t, __st_blksize_padding: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_ushort, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, __unused1: c_int, pub shm_dtime: crate::time_t, __unused2: c_int, pub shm_ctime: crate::time_t, __unused3: c_int, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: c_ulong, __pad1: c_ulong, __pad2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __unused1: c_int, pub msg_rtime: crate::time_t, __unused2: c_int, pub msg_ctime: crate::time_t, __unused3: c_int, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } } pub const AF_FILE: c_int = 1; pub const AF_KCM: c_int = 41; pub const AF_MAX: c_int = 43; pub const AF_QIPCRTR: c_int = 42; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const EAFNOSUPPORT: c_int = 97; pub const EALREADY: c_int = 114; pub const EBADE: c_int = 52; pub const EBADMSG: c_int = 74; pub const EBADR: c_int = 53; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const ECANCELED: c_int = 125; pub const ECHRNG: c_int = 44; pub const ECONNABORTED: c_int = 103; pub const ECONNREFUSED: c_int = 111; pub const ECONNRESET: c_int = 104; pub const EDEADLK: c_int = 35; pub const EDEADLOCK: c_int = 35; pub const EDESTADDRREQ: c_int = 89; pub const EDQUOT: c_int = 122; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EHWPOISON: c_int = 133; pub const EIDRM: c_int = 43; pub const EILSEQ: c_int = 84; pub const EINPROGRESS: c_int = 115; pub const EISCONN: c_int = 106; pub const EISNAM: c_int = 120; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREJECTED: c_int = 129; pub const EKEYREVOKED: c_int = 128; pub const EL2HLT: c_int = 51; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBEXEC: c_int = 83; pub const ELIBMAX: c_int = 82; pub const ELIBSCN: c_int = 81; pub const ELNRNG: c_int = 48; pub const ELOOP: c_int = 40; pub const EMEDIUMTYPE: c_int = 124; pub const EMSGSIZE: c_int = 90; pub const EMULTIHOP: c_int = 72; pub const ENAMETOOLONG: c_int = 36; pub const ENAVAIL: c_int = 119; pub const ENETDOWN: c_int = 100; pub const ENETRESET: c_int = 102; pub const ENETUNREACH: c_int = 101; pub const ENOANO: c_int = 55; pub const ENOBUFS: c_int = 105; pub const ENOCSI: c_int = 50; pub const ENOKEY: c_int = 126; pub const ENOLCK: c_int = 37; pub const ENOMEDIUM: c_int = 123; pub const ENOMSG: c_int = 42; pub const ENOPROTOOPT: c_int = 92; pub const ENOSYS: c_int = 38; pub const ENOTCONN: c_int = 107; pub const ENOTEMPTY: c_int = 39; pub const ENOTNAM: c_int = 118; pub const ENOTRECOVERABLE: c_int = 131; pub const ENOTSOCK: c_int = 88; pub const ENOTSUP: c_int = 95; pub const ENOTUNIQ: c_int = 76; pub const EOPNOTSUPP: c_int = 95; pub const EOVERFLOW: c_int = 75; pub const EOWNERDEAD: c_int = 130; pub const EPFNOSUPPORT: c_int = 96; pub const EREMCHG: c_int = 78; pub const ERESTART: c_int = 85; pub const ERFKILL: c_int = 132; pub const ESHUTDOWN: c_int = 108; pub const ESOCKTNOSUPPORT: c_int = 94; pub const ESTALE: c_int = 116; pub const ESTRPIPE: c_int = 86; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const EUCLEAN: c_int = 117; pub const EUNATCH: c_int = 49; pub const EUSERS: c_int = 87; pub const EXFULL: c_int = 54; pub const EXTPROC: c_int = 65536; pub const F_EXLCK: c_int = 4; pub const F_GETLK: c_int = 12; pub const F_GETOWN: c_int = 9; pub const F_GETOWNER_UIDS: c_int = 17; pub const F_GETOWN_EX: c_int = 16; pub const F_GETSIG: c_int = 11; pub const F_LINUX_SPECIFIC_BASE: c_int = 1024; pub const FLUSHO: c_int = 4096; pub const F_OWNER_PGRP: c_int = 2; pub const F_OWNER_PID: c_int = 1; pub const F_OWNER_TID: c_int = 0; pub const F_SETLK: c_int = 13; pub const F_SETLKW: c_int = 14; pub const F_SETOWN: c_int = 8; pub const F_SETOWN_EX: c_int = 15; pub const F_SETSIG: c_int = 10; pub const F_SHLCK: c_int = 8; pub const IEXTEN: c_int = 32768; pub const MAP_ANON: c_int = 32; pub const MAP_DENYWRITE: c_int = 2048; pub const MAP_EXECUTABLE: c_int = 4096; pub const MAP_GROWSDOWN: c_int = 256; pub const MAP_HUGETLB: c_int = 262144; pub const MAP_LOCKED: c_int = 8192; pub const MAP_NONBLOCK: c_int = 65536; pub const MAP_NORESERVE: c_int = 16384; pub const MAP_POPULATE: c_int = 32768; pub const MAP_STACK: c_int = 131072; pub const MAP_UNINITIALIZED: c_int = 0; pub const O_APPEND: c_int = 1024; pub const O_ASYNC: c_int = 8192; pub const O_CREAT: c_int = 64; pub const O_DIRECT: c_int = 16384; pub const O_DIRECTORY: c_int = 65536; pub const O_DSYNC: c_int = 4096; pub const O_EXCL: c_int = 128; pub const O_LARGEFILE: c_int = 32768; pub const O_NOCTTY: c_int = 256; pub const O_NOFOLLOW: c_int = 131072; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const PF_FILE: c_int = 1; pub const PF_KCM: c_int = 41; pub const PF_MAX: c_int = 43; pub const PF_QIPCRTR: c_int = 42; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGBUS: c_int = 7; pub const SIGCHLD: c_int = 17; pub const SIGCONT: c_int = 18; pub const SIGIO: c_int = 29; pub const SIGPOLL: c_int = 29; pub const SIGPROF: c_int = 27; pub const SIGPWR: c_int = 30; pub const SIGSTKFLT: c_int = 16; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const SIGSTOP: c_int = 19; pub const SIGSYS: c_int = 31; pub const SIGTSTP: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGURG: c_int = 23; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGVTALRM: c_int = 26; pub const SIGWINCH: c_int = 28; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIG_SETMASK: c_int = 2; // FIXME(musl) check these pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_STREAM: c_int = 1; pub const SOL_CAIF: c_int = 278; pub const SOL_IUCV: c_int = 277; pub const SOL_KCM: c_int = 281; pub const SOL_NFC: c_int = 280; pub const SOL_PNPIPE: c_int = 275; pub const SOL_PPPOL2TP: c_int = 273; pub const SOL_RDS: c_int = 276; pub const SOL_RXRPC: c_int = 272; pub const SYS3264_fadvise64: c_int = 223; pub const SYS3264_fcntl: c_int = 25; pub const SYS3264_fstatat: c_int = 79; pub const SYS3264_fstat: c_int = 80; pub const SYS3264_fstatfs: c_int = 44; pub const SYS3264_ftruncate: c_int = 46; pub const SYS3264_lseek: c_int = 62; pub const SYS3264_lstat: c_int = 1039; pub const SYS3264_mmap: c_int = 222; pub const SYS3264_sendfile: c_int = 71; pub const SYS3264_stat: c_int = 1038; pub const SYS3264_statfs: c_int = 43; pub const SYS3264_truncate: c_int = 45; pub const SYS_accept4: c_int = 242; pub const SYS_accept: c_int = 202; pub const SYS_access: c_int = 1033; pub const SYS_acct: c_int = 89; pub const SYS_add_key: c_int = 217; pub const SYS_adjtimex: c_int = 171; pub const SYS_alarm: c_int = 1059; pub const SYS_arch_specific_syscall: c_int = 244; pub const SYS_bdflush: c_int = 1075; pub const SYS_bind: c_int = 200; pub const SYS_bpf: c_int = 280; pub const SYS_brk: c_int = 214; pub const SYS_capget: c_int = 90; pub const SYS_capset: c_int = 91; pub const SYS_chdir: c_int = 49; pub const SYS_chmod: c_int = 1028; pub const SYS_chown: c_int = 1029; pub const SYS_chroot: c_int = 51; pub const SYS_clock_adjtime: c_int = 266; pub const SYS_clock_getres: c_int = 114; pub const SYS_clock_gettime: c_int = 113; pub const SYS_clock_nanosleep: c_int = 115; pub const SYS_clock_settime: c_int = 112; pub const SYS_clone: c_int = 220; pub const SYS_close: c_int = 57; pub const SYS_connect: c_int = 203; pub const SYS_copy_file_range: c_int = -1; // FIXME(hexagon) pub const SYS_creat: c_int = 1064; pub const SYS_delete_module: c_int = 106; pub const SYS_dup2: c_int = 1041; pub const SYS_dup3: c_int = 24; pub const SYS_dup: c_int = 23; pub const SYS_epoll_create1: c_int = 20; pub const SYS_epoll_create: c_int = 1042; pub const SYS_epoll_ctl: c_int = 21; pub const SYS_epoll_pwait: c_int = 22; pub const SYS_epoll_wait: c_int = 1069; pub const SYS_eventfd2: c_int = 19; pub const SYS_eventfd: c_int = 1044; pub const SYS_execveat: c_int = 281; pub const SYS_execve: c_int = 221; pub const SYS_exit: c_int = 93; pub const SYS_exit_group: c_int = 94; pub const SYS_faccessat: c_int = 48; pub const SYS_fadvise64_64: c_int = 223; pub const SYS_fallocate: c_int = 47; pub const SYS_fanotify_init: c_int = 262; pub const SYS_fanotify_mark: c_int = 263; pub const SYS_fchdir: c_int = 50; pub const SYS_fchmodat: c_int = 53; pub const SYS_fchmod: c_int = 52; pub const SYS_fchownat: c_int = 54; pub const SYS_fchown: c_int = 55; pub const SYS_fcntl64: c_int = 25; pub const SYS_fcntl: c_int = 25; pub const SYS_fdatasync: c_int = 83; pub const SYS_fgetxattr: c_int = 10; pub const SYS_finit_module: c_int = 273; pub const SYS_flistxattr: c_int = 13; pub const SYS_flock: c_int = 32; pub const SYS_fork: c_int = 1079; pub const SYS_fremovexattr: c_int = 16; pub const SYS_fsetxattr: c_int = 7; pub const SYS_fstat64: c_int = 80; pub const SYS_fstatat64: c_int = 79; pub const SYS_fstatfs64: c_int = 44; pub const SYS_fstatfs: c_int = 44; pub const SYS_fsync: c_int = 82; pub const SYS_ftruncate64: c_int = 46; pub const SYS_ftruncate: c_int = 46; pub const SYS_futex: c_int = 98; pub const SYS_futimesat: c_int = 1066; pub const SYS_getcpu: c_int = 168; pub const SYS_getcwd: c_int = 17; pub const SYS_getdents64: c_int = 61; pub const SYS_getdents: c_int = 1065; pub const SYS_getegid: c_int = 177; pub const SYS_geteuid: c_int = 175; pub const SYS_getgid: c_int = 176; pub const SYS_getgroups: c_int = 158; pub const SYS_getitimer: c_int = 102; pub const SYS_get_mempolicy: c_int = 236; pub const SYS_getpeername: c_int = 205; pub const SYS_getpgid: c_int = 155; pub const SYS_getpgrp: c_int = 1060; pub const SYS_getpid: c_int = 172; pub const SYS_getppid: c_int = 173; pub const SYS_getpriority: c_int = 141; pub const SYS_getrandom: c_int = 278; pub const SYS_getresgid: c_int = 150; pub const SYS_getresuid: c_int = 148; pub const SYS_getrlimit: c_int = 163; pub const SYS_get_robust_list: c_int = 100; pub const SYS_getrusage: c_int = 165; pub const SYS_getsid: c_int = 156; pub const SYS_getsockname: c_int = 204; pub const SYS_getsockopt: c_int = 209; pub const SYS_gettid: c_int = 178; pub const SYS_gettimeofday: c_int = 169; pub const SYS_getuid: c_int = 174; pub const SYS_getxattr: c_int = 8; pub const SYS_init_module: c_int = 105; pub const SYS_inotify_add_watch: c_int = 27; pub const SYS_inotify_init1: c_int = 26; pub const SYS_inotify_init: c_int = 1043; pub const SYS_inotify_rm_watch: c_int = 28; pub const SYS_io_cancel: c_int = 3; pub const SYS_ioctl: c_int = 29; pub const SYS_io_destroy: c_int = 1; pub const SYS_io_getevents: c_int = 4; pub const SYS_ioprio_get: c_int = 31; pub const SYS_ioprio_set: c_int = 30; pub const SYS_io_setup: c_int = 0; pub const SYS_io_submit: c_int = 2; pub const SYS_kcmp: c_int = 272; pub const SYS_kexec_load: c_int = 104; pub const SYS_keyctl: c_int = 219; pub const SYS_kill: c_int = 129; pub const SYS_lchown: c_int = 1032; pub const SYS_lgetxattr: c_int = 9; pub const SYS_linkat: c_int = 37; pub const SYS_link: c_int = 1025; pub const SYS_listen: c_int = 201; pub const SYS_listxattr: c_int = 11; pub const SYS_llistxattr: c_int = 12; pub const SYS__llseek: c_int = 62; pub const SYS_lookup_dcookie: c_int = 18; pub const SYS_lremovexattr: c_int = 15; pub const SYS_lseek: c_int = 62; pub const SYS_lsetxattr: c_int = 6; pub const SYS_lstat64: c_int = 1039; pub const SYS_lstat: c_int = 1039; pub const SYS_madvise: c_int = 233; pub const SYS_mbind: c_int = 235; pub const SYS_memfd_create: c_int = 279; pub const SYS_migrate_pages: c_int = 238; pub const SYS_mincore: c_int = 232; pub const SYS_mkdirat: c_int = 34; pub const SYS_mkdir: c_int = 1030; pub const SYS_mknodat: c_int = 33; pub const SYS_mknod: c_int = 1027; pub const SYS_mlockall: c_int = 230; pub const SYS_mlock: c_int = 228; pub const SYS_mmap2: c_int = 222; pub const SYS_mount: c_int = 40; pub const SYS_move_pages: c_int = 239; pub const SYS_mprotect: c_int = 226; pub const SYS_mq_getsetattr: c_int = 185; pub const SYS_mq_notify: c_int = 184; pub const SYS_mq_open: c_int = 180; pub const SYS_mq_timedreceive: c_int = 183; pub const SYS_mq_timedsend: c_int = 182; pub const SYS_mq_unlink: c_int = 181; pub const SYS_mremap: c_int = 216; pub const SYS_msgctl: c_int = 187; pub const SYS_msgget: c_int = 186; pub const SYS_msgrcv: c_int = 188; pub const SYS_msgsnd: c_int = 189; pub const SYS_msync: c_int = 227; pub const SYS_munlockall: c_int = 231; pub const SYS_munlock: c_int = 229; pub const SYS_munmap: c_int = 215; pub const SYS_name_to_handle_at: c_int = 264; pub const SYS_nanosleep: c_int = 101; pub const SYS_newfstatat: c_int = 79; pub const SYS_nfsservctl: c_int = 42; pub const SYS_oldwait4: c_int = 1072; pub const SYS_openat: c_int = 56; pub const SYS_open_by_handle_at: c_int = 265; pub const SYS_open: c_int = 1024; pub const SYS_pause: c_int = 1061; pub const SYS_perf_event_open: c_int = 241; pub const SYS_personality: c_int = 92; pub const SYS_pipe2: c_int = 59; pub const SYS_pipe: c_int = 1040; pub const SYS_pivot_root: c_int = 41; pub const SYS_poll: c_int = 1068; pub const SYS_ppoll: c_int = 73; pub const SYS_prctl: c_int = 167; pub const SYS_pread64: c_int = 67; pub const SYS_preadv: c_int = 69; pub const SYS_prlimit64: c_int = 261; pub const SYS_process_vm_readv: c_int = 270; pub const SYS_process_vm_writev: c_int = 271; pub const SYS_pselect6: c_int = 72; pub const SYS_ptrace: c_int = 117; pub const SYS_pwrite64: c_int = 68; pub const SYS_pwritev: c_int = 70; pub const SYS_quotactl: c_int = 60; pub const SYS_readahead: c_int = 213; pub const SYS_read: c_int = 63; pub const SYS_readlinkat: c_int = 78; pub const SYS_readlink: c_int = 1035; pub const SYS_readv: c_int = 65; pub const SYS_reboot: c_int = 142; pub const SYS_recv: c_int = 1073; pub const SYS_recvfrom: c_int = 207; pub const SYS_recvmmsg: c_int = 243; pub const SYS_recvmsg: c_int = 212; pub const SYS_remap_file_pages: c_int = 234; pub const SYS_removexattr: c_int = 14; pub const SYS_renameat2: c_int = 276; pub const SYS_renameat: c_int = 38; pub const SYS_rename: c_int = 1034; pub const SYS_request_key: c_int = 218; pub const SYS_restart_syscall: c_int = 128; pub const SYS_rmdir: c_int = 1031; pub const SYS_rt_sigaction: c_int = 134; pub const SYS_rt_sigpending: c_int = 136; pub const SYS_rt_sigprocmask: c_int = 135; pub const SYS_rt_sigqueueinfo: c_int = 138; pub const SYS_rt_sigreturn: c_int = 139; pub const SYS_rt_sigsuspend: c_int = 133; pub const SYS_rt_sigtimedwait: c_int = 137; pub const SYS_rt_tgsigqueueinfo: c_int = 240; pub const SYS_sched_getaffinity: c_int = 123; pub const SYS_sched_getattr: c_int = 275; pub const SYS_sched_getparam: c_int = 121; pub const SYS_sched_get_priority_max: c_int = 125; pub const SYS_sched_get_priority_min: c_int = 126; pub const SYS_sched_getscheduler: c_int = 120; pub const SYS_sched_rr_get_interval: c_int = 127; pub const SYS_sched_setaffinity: c_int = 122; pub const SYS_sched_setattr: c_int = 274; pub const SYS_sched_setparam: c_int = 118; pub const SYS_sched_setscheduler: c_int = 119; pub const SYS_sched_yield: c_int = 124; pub const SYS_seccomp: c_int = 277; pub const SYS_select: c_int = 1067; pub const SYS_semctl: c_int = 191; pub const SYS_semget: c_int = 190; pub const SYS_semop: c_int = 193; pub const SYS_semtimedop: c_int = 192; pub const SYS_send: c_int = 1074; pub const SYS_sendfile64: c_int = 71; pub const SYS_sendfile: c_int = 71; pub const SYS_sendmmsg: c_int = 269; pub const SYS_sendmsg: c_int = 211; pub const SYS_sendto: c_int = 206; pub const SYS_setdomainname: c_int = 162; pub const SYS_setfsgid: c_int = 152; pub const SYS_setfsuid: c_int = 151; pub const SYS_setgid: c_int = 144; pub const SYS_setgroups: c_int = 159; pub const SYS_sethostname: c_int = 161; pub const SYS_setitimer: c_int = 103; pub const SYS_set_mempolicy: c_int = 237; pub const SYS_setns: c_int = 268; pub const SYS_setpgid: c_int = 154; pub const SYS_setpriority: c_int = 140; pub const SYS_setregid: c_int = 143; pub const SYS_setresgid: c_int = 149; pub const SYS_setresuid: c_int = 147; pub const SYS_setreuid: c_int = 145; pub const SYS_setrlimit: c_int = 164; pub const SYS_set_robust_list: c_int = 99; pub const SYS_setsid: c_int = 157; pub const SYS_setsockopt: c_int = 208; pub const SYS_set_tid_address: c_int = 96; pub const SYS_settimeofday: c_int = 170; pub const SYS_setuid: c_int = 146; pub const SYS_setxattr: c_int = 5; pub const SYS_shmat: c_int = 196; pub const SYS_shmctl: c_int = 195; pub const SYS_shmdt: c_int = 197; pub const SYS_shmget: c_int = 194; pub const SYS_shutdown: c_int = 210; pub const SYS_sigaltstack: c_int = 132; pub const SYS_signalfd4: c_int = 74; pub const SYS_signalfd: c_int = 1045; pub const SYS_socket: c_int = 198; pub const SYS_socketpair: c_int = 199; pub const SYS_splice: c_int = 76; pub const SYS_stat64: c_int = 1038; pub const SYS_stat: c_int = 1038; pub const SYS_statfs64: c_int = 43; pub const SYS_swapoff: c_int = 225; pub const SYS_swapon: c_int = 224; pub const SYS_symlinkat: c_int = 36; pub const SYS_symlink: c_int = 1036; pub const SYS_sync: c_int = 81; pub const SYS_sync_file_range2: c_int = 84; pub const SYS_sync_file_range: c_int = 84; pub const SYS_syncfs: c_int = 267; pub const SYS_syscalls: c_int = 1080; pub const SYS__sysctl: c_int = 1078; pub const SYS_sysinfo: c_int = 179; pub const SYS_syslog: c_int = 116; pub const SYS_tee: c_int = 77; pub const SYS_tgkill: c_int = 131; pub const SYS_time: c_int = 1062; pub const SYS_timer_create: c_int = 107; pub const SYS_timer_delete: c_int = 111; pub const SYS_timerfd_create: c_int = 85; pub const SYS_timerfd_gettime: c_int = 87; pub const SYS_timerfd_settime: c_int = 86; pub const SYS_timer_getoverrun: c_int = 109; pub const SYS_timer_gettime: c_int = 108; pub const SYS_timer_settime: c_int = 110; pub const SYS_times: c_int = 153; pub const SYS_tkill: c_int = 130; pub const SYS_truncate64: c_int = 45; pub const SYS_truncate: c_int = 45; pub const SYS_umask: c_int = 166; pub const SYS_umount2: c_int = 39; pub const SYS_umount: c_int = 1076; pub const SYS_uname: c_int = 160; pub const SYS_unlinkat: c_int = 35; pub const SYS_unlink: c_int = 1026; pub const SYS_unshare: c_int = 97; pub const SYS_uselib: c_int = 1077; pub const SYS_ustat: c_int = 1070; pub const SYS_utime: c_int = 1063; pub const SYS_utimensat: c_int = 88; pub const SYS_utimes: c_int = 1037; pub const SYS_vfork: c_int = 1071; pub const SYS_vhangup: c_int = 58; pub const SYS_vmsplice: c_int = 75; pub const SYS_wait4: c_int = 260; pub const SYS_waitid: c_int = 95; pub const SYS_write: c_int = 64; pub const SYS_writev: c_int = 66; pub const SYS_statx: c_int = 291; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const TIOCM_LOOP: c_int = 32768; pub const TIOCM_OUT1: c_int = 8192; pub const TIOCM_OUT2: c_int = 16384; pub const TIOCSER_TEMT: c_int = 1; pub const TOSTOP: c_int = 256; pub const VEOF: c_int = 4; pub const VEOL2: c_int = 16; pub const VEOL: c_int = 11; pub const VMIN: c_int = 6; libc/src/unix/linux_like/linux/musl/b32/riscv32/0000775000175000017500000000000015105742312021232 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs0000644000175000017500000005443415105742312022367 0ustar bdrungbdrung//! RISC-V-specific definitions for 32-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = c_int; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2usize], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused5: c_ulong, __unused6: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __unused1: c_int, pub msg_rtime: crate::time_t, __unused2: c_int, pub msg_ctime: crate::time_t, __unused3: c_int, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: (i64, f64), } } //pub const RLIM_INFINITY: crate::rlim_t = !0; pub const VEOF: usize = 4; //pub const RLIMIT_RSS: crate::__rlimit_resource_t = 5; //pub const RLIMIT_AS: crate::__rlimit_resource_t = 9; //pub const RLIMIT_MEMLOCK: crate::__rlimit_resource_t = 8; //pub const RLIMIT_NOFILE: crate::__rlimit_resource_t = 7; //pub const RLIMIT_NPROC: crate::__rlimit_resource_t = 6; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const MAP_GROWSDOWN: c_int = 256; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 4; pub const SA_NOCLDWAIT: c_int = 2; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0; pub const SIG_UNBLOCK: c_int = 1; pub const POLLWRNORM: c_short = 256; pub const POLLWRBAND: c_short = 512; pub const O_ASYNC: c_int = 8192; pub const F_SETOWN: c_int = 8; pub const F_GETOWN: c_int = 9; pub const F_GETLK: c_int = 12; pub const F_SETLK: c_int = 13; pub const F_SETLKW: c_int = 14; pub const O_DIRECT: c_int = 16384; pub const O_DIRECTORY: c_int = 65536; pub const O_LARGEFILE: c_int = 0o0100000; pub const O_NOFOLLOW: c_int = 131072; pub const MAP_HUGETLB: c_int = 262144; pub const MAP_LOCKED: c_int = 8192; pub const MAP_NORESERVE: c_int = 16384; pub const MAP_ANON: c_int = 32; pub const MAP_DENYWRITE: c_int = 2048; pub const MAP_EXECUTABLE: c_int = 4096; pub const MAP_POPULATE: c_int = 32768; pub const MAP_NONBLOCK: c_int = 65536; pub const MAP_STACK: c_int = 131072; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const MCL_CURRENT: c_int = 1; pub const MCL_FUTURE: c_int = 2; pub const MCL_ONFAULT: c_int = 4; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 4111; pub const TAB1: crate::tcflag_t = 2048; pub const TAB2: crate::tcflag_t = 4096; pub const TAB3: crate::tcflag_t = 6144; pub const CR1: crate::tcflag_t = 512; pub const CR2: crate::tcflag_t = 1024; pub const CR3: crate::tcflag_t = 1536; pub const FF1: crate::tcflag_t = 32768; pub const BS1: crate::tcflag_t = 8192; pub const VT1: crate::tcflag_t = 16384; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 1024; pub const IXOFF: crate::tcflag_t = 4096; pub const ONLCR: crate::tcflag_t = 4; pub const CSIZE: crate::tcflag_t = 48; pub const CS6: crate::tcflag_t = 16; pub const CS7: crate::tcflag_t = 32; pub const CS8: crate::tcflag_t = 48; pub const CSTOPB: crate::tcflag_t = 64; pub const CREAD: crate::tcflag_t = 128; pub const PARENB: crate::tcflag_t = 256; pub const PARODD: crate::tcflag_t = 512; pub const HUPCL: crate::tcflag_t = 1024; pub const CLOCAL: crate::tcflag_t = 2048; pub const ECHOKE: crate::tcflag_t = 2048; pub const ECHOE: crate::tcflag_t = 16; pub const ECHOK: crate::tcflag_t = 32; pub const ECHONL: crate::tcflag_t = 64; pub const ECHOPRT: crate::tcflag_t = 1024; pub const ECHOCTL: crate::tcflag_t = 512; pub const ISIG: crate::tcflag_t = 1; pub const ICANON: crate::tcflag_t = 2; pub const PENDIN: crate::tcflag_t = 16384; pub const NOFLSH: crate::tcflag_t = 128; pub const CIBAUD: crate::tcflag_t = 269418496; pub const CBAUDEX: crate::tcflag_t = 4096; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 2; pub const NLDLY: crate::tcflag_t = 256; pub const CRDLY: crate::tcflag_t = 1536; pub const TABDLY: crate::tcflag_t = 6144; pub const BSDLY: crate::tcflag_t = 8192; pub const FFDLY: crate::tcflag_t = 32768; pub const VTDLY: crate::tcflag_t = 16384; pub const XTABS: crate::tcflag_t = 6144; pub const B57600: crate::speed_t = 4097; pub const B115200: crate::speed_t = 4098; pub const B230400: crate::speed_t = 4099; pub const B460800: crate::speed_t = 4100; pub const B500000: crate::speed_t = 4101; pub const B576000: crate::speed_t = 4102; pub const B921600: crate::speed_t = 4103; pub const B1000000: crate::speed_t = 4104; pub const B1152000: crate::speed_t = 4105; pub const B1500000: crate::speed_t = 4106; pub const B2000000: crate::speed_t = 4107; pub const B2500000: crate::speed_t = 4108; pub const B3000000: crate::speed_t = 4109; pub const B3500000: crate::speed_t = 4110; pub const B4000000: crate::speed_t = 4111; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 32768; pub const TOSTOP: crate::tcflag_t = 256; pub const FLUSHO: crate::tcflag_t = 4096; pub const EXTPROC: crate::tcflag_t = 65536; pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_close: c_long = 57; // RISC-V don't have SYS_fstat, use statx instead. pub const SYS_lseek: c_long = 62; pub const SYS_mmap: c_long = 222; pub const SYS_mprotect: c_long = 226; pub const SYS_munmap: c_long = 215; pub const SYS_brk: c_long = 214; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_ioctl: c_long = 29; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_sched_yield: c_long = 124; pub const SYS_mremap: c_long = 216; pub const SYS_msync: c_long = 227; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_shmget: c_long = 194; pub const SYS_shmat: c_long = 196; pub const SYS_shmctl: c_long = 195; pub const SYS_dup: c_long = 23; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_getpid: c_long = 172; pub const SYS_sendfile: c_long = 71; pub const SYS_socket: c_long = 198; pub const SYS_connect: c_long = 203; pub const SYS_accept: c_long = 202; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_shutdown: c_long = 210; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_socketpair: c_long = 199; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_exit: c_long = 93; // RISC-V don't have wait4, use waitid instead. pub const SYS_kill: c_long = 129; pub const SYS_uname: c_long = 160; pub const SYS_semget: c_long = 190; pub const SYS_semop: c_long = 193; pub const SYS_semctl: c_long = 191; pub const SYS_shmdt: c_long = 197; pub const SYS_msgget: c_long = 186; pub const SYS_msgsnd: c_long = 189; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgctl: c_long = 187; pub const SYS_fcntl: c_long = 25; pub const SYS_flock: c_long = 32; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_getcwd: c_long = 17; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_fchmod: c_long = 52; pub const SYS_fchown: c_long = 55; pub const SYS_umask: c_long = 166; // RISC-V don't have gettimeofday, use clock_gettime64 instead. // RISC-V don't have getrlimit, use prlimit64 instead. pub const SYS_getrusage: c_long = 165; pub const SYS_sysinfo: c_long = 179; pub const SYS_times: c_long = 153; pub const SYS_ptrace: c_long = 117; pub const SYS_getuid: c_long = 174; pub const SYS_syslog: c_long = 116; pub const SYS_getgid: c_long = 176; pub const SYS_setuid: c_long = 146; pub const SYS_setgid: c_long = 144; pub const SYS_geteuid: c_long = 175; pub const SYS_getegid: c_long = 177; pub const SYS_setpgid: c_long = 154; pub const SYS_getppid: c_long = 173; pub const SYS_setsid: c_long = 157; pub const SYS_setreuid: c_long = 145; pub const SYS_setregid: c_long = 143; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_getpgid: c_long = 155; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_getsid: c_long = 156; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait_time64: c_long = 421; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_sigaltstack: c_long = 132; pub const SYS_personality: c_long = 92; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_getpriority: c_long = 141; pub const SYS_setpriority: c_long = 140; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval_time64: c_long = 423; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_vhangup: c_long = 58; pub const SYS_pivot_root: c_long = 41; pub const SYS_prctl: c_long = 167; // RISC-V don't have setrlimit, use prlimit64 instead. pub const SYS_chroot: c_long = 51; pub const SYS_sync: c_long = 81; pub const SYS_acct: c_long = 89; // RISC-V don't have settimeofday, use clock_settime64 instead. pub const SYS_mount: c_long = 40; pub const SYS_umount2: c_long = 39; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_reboot: c_long = 142; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_quotactl: c_long = 60; pub const SYS_nfsservctl: c_long = 42; pub const SYS_gettid: c_long = 178; pub const SYS_readahead: c_long = 213; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_tkill: c_long = 130; pub const SYS_futex_time64: c_long = 422; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_pgetevents_time64: c_long = 416; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_getdents64: c_long = 61; pub const SYS_set_tid_address: c_long = 96; pub const SYS_restart_syscall: c_long = 128; pub const SYS_semtimedop_time64: c_long = 420; pub const SYS_fadvise64: c_long = 223; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_settime64: c_long = 409; pub const SYS_timer_gettime64: c_long = 408; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime64: c_long = 404; pub const SYS_clock_gettime64: c_long = 403; pub const SYS_clock_getres_time64: c_long = 406; pub const SYS_clock_nanosleep_time64: c_long = 407; pub const SYS_exit_group: c_long = 94; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_tgkill: c_long = 131; pub const SYS_mbind: c_long = 235; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend_time64: c_long = 418; pub const SYS_mq_timedreceive_time64: c_long = 419; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_kexec_load: c_long = 104; pub const SYS_waitid: c_long = 95; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_migrate_pages: c_long = 238; pub const SYS_openat: c_long = 56; pub const SYS_mkdirat: c_long = 34; pub const SYS_mknodat: c_long = 33; pub const SYS_fchownat: c_long = 54; // RISC-V don't have newfstatat, use statx instead. pub const SYS_unlinkat: c_long = 35; pub const SYS_linkat: c_long = 37; pub const SYS_symlinkat: c_long = 36; pub const SYS_readlinkat: c_long = 78; pub const SYS_fchmodat: c_long = 53; pub const SYS_faccessat: c_long = 48; pub const SYS_pselect6_time64: c_long = 413; pub const SYS_ppoll_time64: c_long = 414; pub const SYS_unshare: c_long = 97; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_sync_file_range: c_long = 84; pub const SYS_vmsplice: c_long = 75; pub const SYS_move_pages: c_long = 239; pub const SYS_utimensat_time64: c_long = 412; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_timerfd_create: c_long = 85; pub const SYS_fallocate: c_long = 47; pub const SYS_timerfd_settime64: c_long = 411; pub const SYS_timerfd_gettime64: c_long = 410; pub const SYS_accept4: c_long = 242; pub const SYS_signalfd4: c_long = 74; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_dup3: c_long = 24; pub const SYS_pipe2: c_long = 59; pub const SYS_inotify_init1: c_long = 26; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_recvmmsg_time64: c_long = 417; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_prlimit64: c_long = 261; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime64: c_long = 405; pub const SYS_syncfs: c_long = 267; pub const SYS_sendmmsg: c_long = 269; pub const SYS_setns: c_long = 268; pub const SYS_getcpu: c_long = 168; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; libc/src/unix/linux_like/linux/musl/b32/x86/0000775000175000017500000000000015105742312020364 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b32/x86/mod.rs0000644000175000017500000007734415105742312021526 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = i32; s! { pub struct stat { pub st_dev: crate::dev_t, __st_dev_padding: c_int, __st_ino_truncated: c_long, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __st_rdev_padding: c_int, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino_t, } pub struct stat64 { pub st_dev: crate::dev_t, __st_dev_padding: c_int, __st_ino_truncated: c_long, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __st_rdev_padding: c_int, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino_t, } pub struct mcontext_t { __private: [u32; 22], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __unused1: c_long, __unused2: c_long, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, __unused1: c_int, pub shm_dtime: crate::time_t, __unused2: c_int, pub shm_ctime: crate::time_t, __unused3: c_int, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: c_ulong, __pad1: c_ulong, __pad2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __unused1: c_int, pub msg_rtime: crate::time_t, __unused2: c_int, pub msg_ctime: crate::time_t, __unused3: c_int, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } } s_no_extra_traits! { pub struct user_fpxregs_struct { pub cwd: c_ushort, pub swd: c_ushort, pub twd: c_ushort, pub fop: c_ushort, pub fip: c_long, pub fcs: c_long, pub foo: c_long, pub fos: c_long, pub mxcsr: c_long, __reserved: c_long, pub st_space: [c_long; 32], pub xmm_space: [c_long; 32], padding: [c_long; 56], } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: crate::sigset_t, __private: [u8; 112], } #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f64; 3], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for user_fpxregs_struct { fn eq(&self, other: &user_fpxregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.twd == other.twd && self.fop == other.fop && self.fip == other.fip && self.fcs == other.fcs && self.foo == other.foo && self.fos == other.fos && self.mxcsr == other.mxcsr // Ignore __reserved field && self.st_space == other.st_space && self.xmm_space == other.xmm_space // Ignore padding field } } impl Eq for user_fpxregs_struct {} impl fmt::Debug for user_fpxregs_struct { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("user_fpxregs_struct") .field("cwd", &self.cwd) .field("swd", &self.swd) .field("twd", &self.twd) .field("fop", &self.fop) .field("fip", &self.fip) .field("fcs", &self.fcs) .field("foo", &self.foo) .field("fos", &self.fos) .field("mxcsr", &self.mxcsr) // Ignore __reserved field .field("st_space", &self.st_space) .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl hash::Hash for user_fpxregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.swd.hash(state); self.twd.hash(state); self.fop.hash(state); self.fip.hash(state); self.fcs.hash(state); self.foo.hash(state); self.fos.hash(state); self.mxcsr.hash(state); // Ignore __reserved field self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask && self .__private .iter() .zip(other.__private.iter()) .all(|(a, b)| a == b) } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // Ignore __private field .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); self.__private.hash(state); } } } } pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_ASYNC: c_int = 0x2000; pub const O_LARGEFILE: c_int = 0o0100000; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_SYNC: c_int = 0x080000; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EDEADLOCK: c_int = EDEADLK; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_32BIT: c_int = 0x0040; pub const F_GETLK: c_int = 12; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 13; pub const F_SETLKW: c_int = 14; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const PTRACE_SYSEMU: c_int = 31; pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 32; // Syscall table pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_waitpid: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_time: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_break: c_long = 17; pub const SYS_oldstat: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_stime: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_oldfstat: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_stty: c_long = 31; pub const SYS_gtty: c_long = 32; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_ftime: c_long = 35; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_prof: c_long = 44; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_lock: c_long = 53; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_mpx: c_long = 56; pub const SYS_setpgid: c_long = 57; pub const SYS_ulimit: c_long = 58; pub const SYS_oldolduname: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sgetmask: c_long = 68; pub const SYS_ssetmask: c_long = 69; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrlimit: c_long = 76; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_select: c_long = 82; pub const SYS_symlink: c_long = 83; pub const SYS_oldlstat: c_long = 84; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_profil: c_long = 98; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_ioperm: c_long = 101; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_olduname: c_long = 109; pub const SYS_iopl: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_vm86old: c_long = 113; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_modify_ldt: c_long = 123; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; pub const SYS_vm86: c_long = 166; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 167; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_setresgid: c_long = 170; pub const SYS_getresgid: c_long = 171; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_chown: c_long = 182; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_getpmsg: c_long = 188; pub const SYS_putpmsg: c_long = 189; pub const SYS_vfork: c_long = 190; pub const SYS_ugetrlimit: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_lchown32: c_long = 198; pub const SYS_getuid32: c_long = 199; pub const SYS_getgid32: c_long = 200; pub const SYS_geteuid32: c_long = 201; pub const SYS_getegid32: c_long = 202; pub const SYS_setreuid32: c_long = 203; pub const SYS_setregid32: c_long = 204; pub const SYS_getgroups32: c_long = 205; pub const SYS_setgroups32: c_long = 206; pub const SYS_fchown32: c_long = 207; pub const SYS_setresuid32: c_long = 208; pub const SYS_getresuid32: c_long = 209; pub const SYS_setresgid32: c_long = 210; pub const SYS_getresgid32: c_long = 211; pub const SYS_chown32: c_long = 212; pub const SYS_setuid32: c_long = 213; pub const SYS_setgid32: c_long = 214; pub const SYS_setfsuid32: c_long = 215; pub const SYS_setfsgid32: c_long = 216; pub const SYS_pivot_root: c_long = 217; pub const SYS_mincore: c_long = 218; pub const SYS_madvise: c_long = 219; pub const SYS_getdents64: c_long = 220; pub const SYS_fcntl64: c_long = 221; pub const SYS_gettid: c_long = 224; pub const SYS_readahead: c_long = 225; pub const SYS_setxattr: c_long = 226; pub const SYS_lsetxattr: c_long = 227; pub const SYS_fsetxattr: c_long = 228; pub const SYS_getxattr: c_long = 229; pub const SYS_lgetxattr: c_long = 230; pub const SYS_fgetxattr: c_long = 231; pub const SYS_listxattr: c_long = 232; pub const SYS_llistxattr: c_long = 233; pub const SYS_flistxattr: c_long = 234; pub const SYS_removexattr: c_long = 235; pub const SYS_lremovexattr: c_long = 236; pub const SYS_fremovexattr: c_long = 237; pub const SYS_tkill: c_long = 238; pub const SYS_sendfile64: c_long = 239; pub const SYS_futex: c_long = 240; pub const SYS_sched_setaffinity: c_long = 241; pub const SYS_sched_getaffinity: c_long = 242; pub const SYS_set_thread_area: c_long = 243; pub const SYS_get_thread_area: c_long = 244; pub const SYS_io_setup: c_long = 245; pub const SYS_io_destroy: c_long = 246; pub const SYS_io_getevents: c_long = 247; pub const SYS_io_submit: c_long = 248; pub const SYS_io_cancel: c_long = 249; pub const SYS_fadvise64: c_long = 250; pub const SYS_exit_group: c_long = 252; pub const SYS_lookup_dcookie: c_long = 253; pub const SYS_epoll_create: c_long = 254; pub const SYS_epoll_ctl: c_long = 255; pub const SYS_epoll_wait: c_long = 256; pub const SYS_remap_file_pages: c_long = 257; pub const SYS_set_tid_address: c_long = 258; pub const SYS_timer_create: c_long = 259; pub const SYS_timer_settime: c_long = 260; pub const SYS_timer_gettime: c_long = 261; pub const SYS_timer_getoverrun: c_long = 262; pub const SYS_timer_delete: c_long = 263; pub const SYS_clock_settime: c_long = 264; pub const SYS_clock_gettime: c_long = 265; pub const SYS_clock_getres: c_long = 266; pub const SYS_clock_nanosleep: c_long = 267; pub const SYS_statfs64: c_long = 268; pub const SYS_fstatfs64: c_long = 269; pub const SYS_tgkill: c_long = 270; pub const SYS_utimes: c_long = 271; pub const SYS_fadvise64_64: c_long = 272; pub const SYS_vserver: c_long = 273; pub const SYS_mbind: c_long = 274; pub const SYS_get_mempolicy: c_long = 275; pub const SYS_set_mempolicy: c_long = 276; pub const SYS_mq_open: c_long = 277; pub const SYS_mq_unlink: c_long = 278; pub const SYS_mq_timedsend: c_long = 279; pub const SYS_mq_timedreceive: c_long = 280; pub const SYS_mq_notify: c_long = 281; pub const SYS_mq_getsetattr: c_long = 282; pub const SYS_kexec_load: c_long = 283; pub const SYS_waitid: c_long = 284; pub const SYS_add_key: c_long = 286; pub const SYS_request_key: c_long = 287; pub const SYS_keyctl: c_long = 288; pub const SYS_ioprio_set: c_long = 289; pub const SYS_ioprio_get: c_long = 290; pub const SYS_inotify_init: c_long = 291; pub const SYS_inotify_add_watch: c_long = 292; pub const SYS_inotify_rm_watch: c_long = 293; pub const SYS_migrate_pages: c_long = 294; pub const SYS_openat: c_long = 295; pub const SYS_mkdirat: c_long = 296; pub const SYS_mknodat: c_long = 297; pub const SYS_fchownat: c_long = 298; pub const SYS_futimesat: c_long = 299; pub const SYS_fstatat64: c_long = 300; pub const SYS_unlinkat: c_long = 301; pub const SYS_renameat: c_long = 302; pub const SYS_linkat: c_long = 303; pub const SYS_symlinkat: c_long = 304; pub const SYS_readlinkat: c_long = 305; pub const SYS_fchmodat: c_long = 306; pub const SYS_faccessat: c_long = 307; pub const SYS_pselect6: c_long = 308; pub const SYS_ppoll: c_long = 309; pub const SYS_unshare: c_long = 310; pub const SYS_set_robust_list: c_long = 311; pub const SYS_get_robust_list: c_long = 312; pub const SYS_splice: c_long = 313; pub const SYS_sync_file_range: c_long = 314; pub const SYS_tee: c_long = 315; pub const SYS_vmsplice: c_long = 316; pub const SYS_move_pages: c_long = 317; pub const SYS_getcpu: c_long = 318; pub const SYS_epoll_pwait: c_long = 319; pub const SYS_utimensat: c_long = 320; pub const SYS_signalfd: c_long = 321; pub const SYS_timerfd_create: c_long = 322; pub const SYS_eventfd: c_long = 323; pub const SYS_fallocate: c_long = 324; pub const SYS_timerfd_settime: c_long = 325; pub const SYS_timerfd_gettime: c_long = 326; pub const SYS_signalfd4: c_long = 327; pub const SYS_eventfd2: c_long = 328; pub const SYS_epoll_create1: c_long = 329; pub const SYS_dup3: c_long = 330; pub const SYS_pipe2: c_long = 331; pub const SYS_inotify_init1: c_long = 332; pub const SYS_preadv: c_long = 333; pub const SYS_pwritev: c_long = 334; pub const SYS_rt_tgsigqueueinfo: c_long = 335; pub const SYS_perf_event_open: c_long = 336; pub const SYS_recvmmsg: c_long = 337; pub const SYS_fanotify_init: c_long = 338; pub const SYS_fanotify_mark: c_long = 339; pub const SYS_prlimit64: c_long = 340; pub const SYS_name_to_handle_at: c_long = 341; pub const SYS_open_by_handle_at: c_long = 342; pub const SYS_clock_adjtime: c_long = 343; pub const SYS_syncfs: c_long = 344; pub const SYS_sendmmsg: c_long = 345; pub const SYS_setns: c_long = 346; pub const SYS_process_vm_readv: c_long = 347; pub const SYS_process_vm_writev: c_long = 348; pub const SYS_kcmp: c_long = 349; pub const SYS_finit_module: c_long = 350; pub const SYS_sched_setattr: c_long = 351; pub const SYS_sched_getattr: c_long = 352; pub const SYS_renameat2: c_long = 353; pub const SYS_seccomp: c_long = 354; pub const SYS_getrandom: c_long = 355; pub const SYS_memfd_create: c_long = 356; pub const SYS_bpf: c_long = 357; pub const SYS_execveat: c_long = 358; pub const SYS_socket: c_long = 359; pub const SYS_socketpair: c_long = 360; pub const SYS_bind: c_long = 361; pub const SYS_connect: c_long = 362; pub const SYS_listen: c_long = 363; pub const SYS_accept4: c_long = 364; pub const SYS_getsockopt: c_long = 365; pub const SYS_setsockopt: c_long = 366; pub const SYS_getsockname: c_long = 367; pub const SYS_getpeername: c_long = 368; pub const SYS_sendto: c_long = 369; pub const SYS_sendmsg: c_long = 370; pub const SYS_recvfrom: c_long = 371; pub const SYS_recvmsg: c_long = 372; pub const SYS_shutdown: c_long = 373; pub const SYS_userfaultfd: c_long = 374; pub const SYS_membarrier: c_long = 375; pub const SYS_mlock2: c_long = 376; pub const SYS_copy_file_range: c_long = 377; pub const SYS_preadv2: c_long = 378; pub const SYS_pwritev2: c_long = 379; pub const SYS_pkey_mprotect: c_long = 380; pub const SYS_pkey_alloc: c_long = 381; pub const SYS_pkey_free: c_long = 382; pub const SYS_statx: c_long = 383; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_fchmodat2: c_long = 452; // offsets in user_regs_structs, from sys/reg.h pub const EBX: c_int = 0; pub const ECX: c_int = 1; pub const EDX: c_int = 2; pub const ESI: c_int = 3; pub const EDI: c_int = 4; pub const EBP: c_int = 5; pub const EAX: c_int = 6; pub const DS: c_int = 7; pub const ES: c_int = 8; pub const FS: c_int = 9; pub const GS: c_int = 10; pub const ORIG_EAX: c_int = 11; pub const EIP: c_int = 12; pub const CS: c_int = 13; pub const EFL: c_int = 14; pub const UESP: c_int = 15; pub const SS: c_int = 16; libc/src/unix/linux_like/linux/musl/lfs64.rs0000644000175000017500000001341415105742312020656 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; #[inline] pub unsafe extern "C" fn creat64(path: *const c_char, mode: crate::mode_t) -> c_int { crate::creat(path, mode) } #[inline] pub unsafe extern "C" fn fallocate64( fd: c_int, mode: c_int, offset: off64_t, len: off64_t, ) -> c_int { crate::fallocate(fd, mode, offset, len) } #[inline] pub unsafe extern "C" fn fgetpos64(stream: *mut crate::FILE, pos: *mut crate::fpos64_t) -> c_int { crate::fgetpos(stream, pos as *mut _) } #[inline] pub unsafe extern "C" fn fopen64(pathname: *const c_char, mode: *const c_char) -> *mut crate::FILE { crate::fopen(pathname, mode) } #[inline] pub unsafe extern "C" fn freopen64( pathname: *const c_char, mode: *const c_char, stream: *mut crate::FILE, ) -> *mut crate::FILE { crate::freopen(pathname, mode, stream) } #[inline] pub unsafe extern "C" fn fseeko64( stream: *mut crate::FILE, offset: off64_t, whence: c_int, ) -> c_int { crate::fseeko(stream, offset, whence) } #[inline] pub unsafe extern "C" fn fsetpos64(stream: *mut crate::FILE, pos: *const crate::fpos64_t) -> c_int { crate::fsetpos(stream, pos as *mut _) } #[inline] pub unsafe extern "C" fn fstat64(fildes: c_int, buf: *mut crate::stat64) -> c_int { crate::fstat(fildes, buf as *mut _) } #[inline] pub unsafe extern "C" fn fstatat64( fd: c_int, path: *const c_char, buf: *mut crate::stat64, flag: c_int, ) -> c_int { crate::fstatat(fd, path, buf as *mut _, flag) } #[inline] pub unsafe extern "C" fn fstatfs64(fd: c_int, buf: *mut crate::statfs64) -> c_int { crate::fstatfs(fd, buf as *mut _) } #[inline] pub unsafe extern "C" fn fstatvfs64(fd: c_int, buf: *mut crate::statvfs64) -> c_int { crate::fstatvfs(fd, buf as *mut _) } #[inline] pub unsafe extern "C" fn ftello64(stream: *mut crate::FILE) -> off64_t { crate::ftello(stream) } #[inline] pub unsafe extern "C" fn ftruncate64(fd: c_int, length: off64_t) -> c_int { crate::ftruncate(fd, length) } #[inline] pub unsafe extern "C" fn getrlimit64(resource: c_int, rlim: *mut crate::rlimit64) -> c_int { crate::getrlimit(resource, rlim as *mut _) } #[inline] pub unsafe extern "C" fn lseek64(fd: c_int, offset: off64_t, whence: c_int) -> off64_t { crate::lseek(fd, offset, whence) } #[inline] pub unsafe extern "C" fn lstat64(path: *const c_char, buf: *mut crate::stat64) -> c_int { crate::lstat(path, buf as *mut _) } #[inline] pub unsafe extern "C" fn mmap64( addr: *mut c_void, length: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off64_t, ) -> *mut c_void { crate::mmap(addr, length, prot, flags, fd, offset) } // These functions are variadic in the C ABI since the `mode` argument is "optional". Variadic // `extern "C"` functions are unstable in Rust so we cannot write a shim function for these // entrypoints. See https://github.com/rust-lang/rust/issues/44930. // // These aliases are mostly fine though, neither function takes a LFS64-namespaced type as an // argument, nor do their names clash with any declared types. pub use crate::{open as open64, openat as openat64}; #[inline] pub unsafe extern "C" fn posix_fadvise64( fd: c_int, offset: off64_t, len: off64_t, advice: c_int, ) -> c_int { crate::posix_fadvise(fd, offset, len, advice) } #[inline] pub unsafe extern "C" fn posix_fallocate64(fd: c_int, offset: off64_t, len: off64_t) -> c_int { crate::posix_fallocate(fd, offset, len) } #[inline] pub unsafe extern "C" fn pread64( fd: c_int, buf: *mut c_void, count: size_t, offset: off64_t, ) -> ssize_t { crate::pread(fd, buf, count, offset) } #[inline] pub unsafe extern "C" fn preadv64( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, ) -> ssize_t { crate::preadv(fd, iov, iovcnt, offset) } #[inline] pub unsafe extern "C" fn prlimit64( pid: crate::pid_t, resource: c_int, new_limit: *const crate::rlimit64, old_limit: *mut crate::rlimit64, ) -> c_int { crate::prlimit(pid, resource, new_limit as *mut _, old_limit as *mut _) } #[inline] pub unsafe extern "C" fn pwrite64( fd: c_int, buf: *const c_void, count: size_t, offset: off64_t, ) -> ssize_t { crate::pwrite(fd, buf, count, offset) } #[inline] pub unsafe extern "C" fn pwritev64( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, ) -> ssize_t { crate::pwritev(fd, iov, iovcnt, offset) } #[inline] pub unsafe extern "C" fn readdir64(dirp: *mut crate::DIR) -> *mut crate::dirent64 { crate::readdir(dirp) as *mut _ } #[inline] pub unsafe extern "C" fn readdir64_r( dirp: *mut crate::DIR, entry: *mut crate::dirent64, result: *mut *mut crate::dirent64, ) -> c_int { crate::readdir_r(dirp, entry as *mut _, result as *mut _) } #[inline] pub unsafe extern "C" fn sendfile64( out_fd: c_int, in_fd: c_int, offset: *mut off64_t, count: size_t, ) -> ssize_t { crate::sendfile(out_fd, in_fd, offset, count) } #[inline] pub unsafe extern "C" fn setrlimit64(resource: c_int, rlim: *const crate::rlimit64) -> c_int { crate::setrlimit(resource, rlim as *mut _) } #[inline] pub unsafe extern "C" fn stat64(pathname: *const c_char, statbuf: *mut crate::stat64) -> c_int { crate::stat(pathname, statbuf as *mut _) } #[inline] pub unsafe extern "C" fn statfs64(pathname: *const c_char, buf: *mut crate::statfs64) -> c_int { crate::statfs(pathname, buf as *mut _) } #[inline] pub unsafe extern "C" fn statvfs64(path: *const c_char, buf: *mut crate::statvfs64) -> c_int { crate::statvfs(path, buf as *mut _) } #[inline] pub unsafe extern "C" fn tmpfile64() -> *mut crate::FILE { crate::tmpfile() } #[inline] pub unsafe extern "C" fn truncate64(path: *const c_char, length: off64_t) -> c_int { crate::truncate(path, length) } libc/src/unix/linux_like/linux/musl/b64/0000775000175000017500000000000015105742312017744 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b64/mod.rs0000644000175000017500000000573315105742312021077 0ustar bdrungbdrunguse crate::prelude::*; pub type regoff_t = c_long; s! { pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct pthread_attr_t { __size: [u64; 7], } pub struct sigset_t { __val: [c_ulong; 16], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: c_ulong, __pad1: c_ulong, __pad2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, #[cfg(target_endian = "big")] __pad1: c_int, pub msg_iovlen: c_int, #[cfg(target_endian = "little")] __pad1: c_int, pub msg_control: *mut c_void, #[cfg(target_endian = "big")] __pad2: c_int, pub msg_controllen: crate::socklen_t, #[cfg(target_endian = "little")] __pad2: c_int, pub msg_flags: c_int, } pub struct cmsghdr { #[cfg(target_endian = "big")] pub __pad1: c_int, pub cmsg_len: crate::socklen_t, #[cfg(target_endian = "little")] pub __pad1: c_int, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct sem_t { __val: [c_int; 8], } } pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "mips64")] { mod mips64; pub use self::mips64::*; } else if #[cfg(any(target_arch = "powerpc64"))] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(any(target_arch = "s390x"))] { mod s390x; pub use self::s390x::*; } else if #[cfg(any(target_arch = "x86_64"))] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(any(target_arch = "riscv64"))] { mod riscv64; pub use self::riscv64::*; } else if #[cfg(any(target_arch = "loongarch64"))] { mod loongarch64; pub use self::loongarch64::*; } else if #[cfg(any(target_arch = "wasm32"))] { mod wasm32; pub use self::wasm32::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/musl/b64/x86_64/0000775000175000017500000000000015105742312020702 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs0000644000175000017500000007775415105742312022051 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = c_long; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; pub type greg_t = i64; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __reserved: [c_long; 3], } pub struct user_regs_struct { pub r15: c_ulong, pub r14: c_ulong, pub r13: c_ulong, pub r12: c_ulong, pub rbp: c_ulong, pub rbx: c_ulong, pub r11: c_ulong, pub r10: c_ulong, pub r9: c_ulong, pub r8: c_ulong, pub rax: c_ulong, pub rcx: c_ulong, pub rdx: c_ulong, pub rsi: c_ulong, pub rdi: c_ulong, pub orig_rax: c_ulong, pub rip: c_ulong, pub cs: c_ulong, pub eflags: c_ulong, pub rsp: c_ulong, pub ss: c_ulong, pub fs_base: c_ulong, pub gs_base: c_ulong, pub ds: c_ulong, pub es: c_ulong, pub fs: c_ulong, pub gs: c_ulong, } pub struct user { pub regs: user_regs_struct, pub u_fpvalid: c_int, pub i387: user_fpregs_struct, pub u_tsize: c_ulong, pub u_dsize: c_ulong, pub u_ssize: c_ulong, pub start_code: c_ulong, pub start_stack: c_ulong, pub signal: c_long, __reserved: c_int, #[cfg(target_pointer_width = "32")] __pad1: u32, pub u_ar0: *mut user_regs_struct, #[cfg(target_pointer_width = "32")] __pad2: u32, pub u_fpstate: *mut user_fpregs_struct, pub magic: c_ulong, pub u_comm: [c_char; 32], pub u_debugreg: [c_ulong; 8], } // GitHub repo: ifduyue/musl/ // commit: b4b1e10364c8737a632be61582e05a8d3acf5690 // file: arch/x86_64/bits/signal.h#L80-L84 pub struct mcontext_t { pub gregs: [greg_t; 23], __private: [u64; 9], } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __unused1: c_long, __unused2: c_long, } #[repr(align(8))] pub struct clone_args { pub flags: c_ulonglong, pub pidfd: c_ulonglong, pub child_tid: c_ulonglong, pub parent_tid: c_ulonglong, pub exit_signal: c_ulonglong, pub stack: c_ulonglong, pub stack_size: c_ulonglong, pub tls: c_ulonglong, pub set_tid: c_ulonglong, pub set_tid_size: c_ulonglong, pub cgroup: c_ulonglong, } } s_no_extra_traits! { pub struct user_fpregs_struct { pub cwd: c_ushort, pub swd: c_ushort, pub ftw: c_ushort, pub fop: c_ushort, pub rip: c_ulong, pub rdp: c_ulong, pub mxcsr: c_uint, pub mxcr_mask: c_uint, pub st_space: [c_uint; 32], pub xmm_space: [c_uint; 64], padding: [c_uint; 24], } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: crate::sigset_t, __private: [u8; 512], } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for user_fpregs_struct { fn eq(&self, other: &user_fpregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.ftw == other.ftw && self.fop == other.fop && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mxcr_mask == other.mxcr_mask && self.st_space == other.st_space && self .xmm_space .iter() .zip(other.xmm_space.iter()) .all(|(a, b)| a == b) // Ignore padding field } } impl Eq for user_fpregs_struct {} impl fmt::Debug for user_fpregs_struct { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("user_fpregs_struct") .field("cwd", &self.cwd) .field("ftw", &self.ftw) .field("fop", &self.fop) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mxcr_mask", &self.mxcr_mask) .field("st_space", &self.st_space) // FIXME(debug): .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl hash::Hash for user_fpregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.ftw.hash(state); self.fop.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mxcr_mask.hash(state); self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask && self .__private .iter() .zip(other.__private.iter()) .all(|(a, b)| a == b) } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // Ignore __private field .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); self.__private.hash(state); } } } } // Syscall table pub const SYS_read: c_long = 0; pub const SYS_write: c_long = 1; pub const SYS_open: c_long = 2; pub const SYS_close: c_long = 3; pub const SYS_stat: c_long = 4; pub const SYS_fstat: c_long = 5; pub const SYS_lstat: c_long = 6; pub const SYS_poll: c_long = 7; pub const SYS_lseek: c_long = 8; pub const SYS_mmap: c_long = 9; pub const SYS_mprotect: c_long = 10; pub const SYS_munmap: c_long = 11; pub const SYS_brk: c_long = 12; pub const SYS_rt_sigaction: c_long = 13; pub const SYS_rt_sigprocmask: c_long = 14; pub const SYS_rt_sigreturn: c_long = 15; pub const SYS_ioctl: c_long = 16; pub const SYS_pread64: c_long = 17; pub const SYS_pwrite64: c_long = 18; pub const SYS_readv: c_long = 19; pub const SYS_writev: c_long = 20; pub const SYS_access: c_long = 21; pub const SYS_pipe: c_long = 22; pub const SYS_select: c_long = 23; pub const SYS_sched_yield: c_long = 24; pub const SYS_mremap: c_long = 25; pub const SYS_msync: c_long = 26; pub const SYS_mincore: c_long = 27; pub const SYS_madvise: c_long = 28; pub const SYS_shmget: c_long = 29; pub const SYS_shmat: c_long = 30; pub const SYS_shmctl: c_long = 31; pub const SYS_dup: c_long = 32; pub const SYS_dup2: c_long = 33; pub const SYS_pause: c_long = 34; pub const SYS_nanosleep: c_long = 35; pub const SYS_getitimer: c_long = 36; pub const SYS_alarm: c_long = 37; pub const SYS_setitimer: c_long = 38; pub const SYS_getpid: c_long = 39; pub const SYS_sendfile: c_long = 40; pub const SYS_socket: c_long = 41; pub const SYS_connect: c_long = 42; pub const SYS_accept: c_long = 43; pub const SYS_sendto: c_long = 44; pub const SYS_recvfrom: c_long = 45; pub const SYS_sendmsg: c_long = 46; pub const SYS_recvmsg: c_long = 47; pub const SYS_shutdown: c_long = 48; pub const SYS_bind: c_long = 49; pub const SYS_listen: c_long = 50; pub const SYS_getsockname: c_long = 51; pub const SYS_getpeername: c_long = 52; pub const SYS_socketpair: c_long = 53; pub const SYS_setsockopt: c_long = 54; pub const SYS_getsockopt: c_long = 55; pub const SYS_clone: c_long = 56; pub const SYS_fork: c_long = 57; pub const SYS_vfork: c_long = 58; pub const SYS_execve: c_long = 59; pub const SYS_exit: c_long = 60; pub const SYS_wait4: c_long = 61; pub const SYS_kill: c_long = 62; pub const SYS_uname: c_long = 63; pub const SYS_semget: c_long = 64; pub const SYS_semop: c_long = 65; pub const SYS_semctl: c_long = 66; pub const SYS_shmdt: c_long = 67; pub const SYS_msgget: c_long = 68; pub const SYS_msgsnd: c_long = 69; pub const SYS_msgrcv: c_long = 70; pub const SYS_msgctl: c_long = 71; pub const SYS_fcntl: c_long = 72; pub const SYS_flock: c_long = 73; pub const SYS_fsync: c_long = 74; pub const SYS_fdatasync: c_long = 75; pub const SYS_truncate: c_long = 76; pub const SYS_ftruncate: c_long = 77; pub const SYS_getdents: c_long = 78; pub const SYS_getcwd: c_long = 79; pub const SYS_chdir: c_long = 80; pub const SYS_fchdir: c_long = 81; pub const SYS_rename: c_long = 82; pub const SYS_mkdir: c_long = 83; pub const SYS_rmdir: c_long = 84; pub const SYS_creat: c_long = 85; pub const SYS_link: c_long = 86; pub const SYS_unlink: c_long = 87; pub const SYS_symlink: c_long = 88; pub const SYS_readlink: c_long = 89; pub const SYS_chmod: c_long = 90; pub const SYS_fchmod: c_long = 91; pub const SYS_chown: c_long = 92; pub const SYS_fchown: c_long = 93; pub const SYS_lchown: c_long = 94; pub const SYS_umask: c_long = 95; pub const SYS_gettimeofday: c_long = 96; pub const SYS_getrlimit: c_long = 97; pub const SYS_getrusage: c_long = 98; pub const SYS_sysinfo: c_long = 99; pub const SYS_times: c_long = 100; pub const SYS_ptrace: c_long = 101; pub const SYS_getuid: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_getgid: c_long = 104; pub const SYS_setuid: c_long = 105; pub const SYS_setgid: c_long = 106; pub const SYS_geteuid: c_long = 107; pub const SYS_getegid: c_long = 108; pub const SYS_setpgid: c_long = 109; pub const SYS_getppid: c_long = 110; pub const SYS_getpgrp: c_long = 111; pub const SYS_setsid: c_long = 112; pub const SYS_setreuid: c_long = 113; pub const SYS_setregid: c_long = 114; pub const SYS_getgroups: c_long = 115; pub const SYS_setgroups: c_long = 116; pub const SYS_setresuid: c_long = 117; pub const SYS_getresuid: c_long = 118; pub const SYS_setresgid: c_long = 119; pub const SYS_getresgid: c_long = 120; pub const SYS_getpgid: c_long = 121; pub const SYS_setfsuid: c_long = 122; pub const SYS_setfsgid: c_long = 123; pub const SYS_getsid: c_long = 124; pub const SYS_capget: c_long = 125; pub const SYS_capset: c_long = 126; pub const SYS_rt_sigpending: c_long = 127; pub const SYS_rt_sigtimedwait: c_long = 128; pub const SYS_rt_sigqueueinfo: c_long = 129; pub const SYS_rt_sigsuspend: c_long = 130; pub const SYS_sigaltstack: c_long = 131; pub const SYS_utime: c_long = 132; pub const SYS_mknod: c_long = 133; pub const SYS_uselib: c_long = 134; pub const SYS_personality: c_long = 135; pub const SYS_ustat: c_long = 136; pub const SYS_statfs: c_long = 137; pub const SYS_fstatfs: c_long = 138; pub const SYS_sysfs: c_long = 139; pub const SYS_getpriority: c_long = 140; pub const SYS_setpriority: c_long = 141; pub const SYS_sched_setparam: c_long = 142; pub const SYS_sched_getparam: c_long = 143; pub const SYS_sched_setscheduler: c_long = 144; pub const SYS_sched_getscheduler: c_long = 145; pub const SYS_sched_get_priority_max: c_long = 146; pub const SYS_sched_get_priority_min: c_long = 147; pub const SYS_sched_rr_get_interval: c_long = 148; pub const SYS_mlock: c_long = 149; pub const SYS_munlock: c_long = 150; pub const SYS_mlockall: c_long = 151; pub const SYS_munlockall: c_long = 152; pub const SYS_vhangup: c_long = 153; pub const SYS_modify_ldt: c_long = 154; pub const SYS_pivot_root: c_long = 155; pub const SYS__sysctl: c_long = 156; pub const SYS_prctl: c_long = 157; pub const SYS_arch_prctl: c_long = 158; pub const SYS_adjtimex: c_long = 159; pub const SYS_setrlimit: c_long = 160; pub const SYS_chroot: c_long = 161; pub const SYS_sync: c_long = 162; pub const SYS_acct: c_long = 163; pub const SYS_settimeofday: c_long = 164; pub const SYS_mount: c_long = 165; pub const SYS_umount2: c_long = 166; pub const SYS_swapon: c_long = 167; pub const SYS_swapoff: c_long = 168; pub const SYS_reboot: c_long = 169; pub const SYS_sethostname: c_long = 170; pub const SYS_setdomainname: c_long = 171; pub const SYS_iopl: c_long = 172; pub const SYS_ioperm: c_long = 173; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 174; pub const SYS_init_module: c_long = 175; pub const SYS_delete_module: c_long = 176; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 177; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 178; pub const SYS_quotactl: c_long = 179; pub const SYS_nfsservctl: c_long = 180; pub const SYS_getpmsg: c_long = 181; pub const SYS_putpmsg: c_long = 182; pub const SYS_afs_syscall: c_long = 183; pub const SYS_tuxcall: c_long = 184; pub const SYS_security: c_long = 185; pub const SYS_gettid: c_long = 186; pub const SYS_readahead: c_long = 187; pub const SYS_setxattr: c_long = 188; pub const SYS_lsetxattr: c_long = 189; pub const SYS_fsetxattr: c_long = 190; pub const SYS_getxattr: c_long = 191; pub const SYS_lgetxattr: c_long = 192; pub const SYS_fgetxattr: c_long = 193; pub const SYS_listxattr: c_long = 194; pub const SYS_llistxattr: c_long = 195; pub const SYS_flistxattr: c_long = 196; pub const SYS_removexattr: c_long = 197; pub const SYS_lremovexattr: c_long = 198; pub const SYS_fremovexattr: c_long = 199; pub const SYS_tkill: c_long = 200; pub const SYS_time: c_long = 201; pub const SYS_futex: c_long = 202; pub const SYS_sched_setaffinity: c_long = 203; pub const SYS_sched_getaffinity: c_long = 204; pub const SYS_set_thread_area: c_long = 205; pub const SYS_io_setup: c_long = 206; pub const SYS_io_destroy: c_long = 207; pub const SYS_io_getevents: c_long = 208; pub const SYS_io_submit: c_long = 209; pub const SYS_io_cancel: c_long = 210; pub const SYS_get_thread_area: c_long = 211; pub const SYS_lookup_dcookie: c_long = 212; pub const SYS_epoll_create: c_long = 213; pub const SYS_epoll_ctl_old: c_long = 214; pub const SYS_epoll_wait_old: c_long = 215; pub const SYS_remap_file_pages: c_long = 216; pub const SYS_getdents64: c_long = 217; pub const SYS_set_tid_address: c_long = 218; pub const SYS_restart_syscall: c_long = 219; pub const SYS_semtimedop: c_long = 220; pub const SYS_fadvise64: c_long = 221; pub const SYS_timer_create: c_long = 222; pub const SYS_timer_settime: c_long = 223; pub const SYS_timer_gettime: c_long = 224; pub const SYS_timer_getoverrun: c_long = 225; pub const SYS_timer_delete: c_long = 226; pub const SYS_clock_settime: c_long = 227; pub const SYS_clock_gettime: c_long = 228; pub const SYS_clock_getres: c_long = 229; pub const SYS_clock_nanosleep: c_long = 230; pub const SYS_exit_group: c_long = 231; pub const SYS_epoll_wait: c_long = 232; pub const SYS_epoll_ctl: c_long = 233; pub const SYS_tgkill: c_long = 234; pub const SYS_utimes: c_long = 235; pub const SYS_vserver: c_long = 236; pub const SYS_mbind: c_long = 237; pub const SYS_set_mempolicy: c_long = 238; pub const SYS_get_mempolicy: c_long = 239; pub const SYS_mq_open: c_long = 240; pub const SYS_mq_unlink: c_long = 241; pub const SYS_mq_timedsend: c_long = 242; pub const SYS_mq_timedreceive: c_long = 243; pub const SYS_mq_notify: c_long = 244; pub const SYS_mq_getsetattr: c_long = 245; pub const SYS_kexec_load: c_long = 246; pub const SYS_waitid: c_long = 247; pub const SYS_add_key: c_long = 248; pub const SYS_request_key: c_long = 249; pub const SYS_keyctl: c_long = 250; pub const SYS_ioprio_set: c_long = 251; pub const SYS_ioprio_get: c_long = 252; pub const SYS_inotify_init: c_long = 253; pub const SYS_inotify_add_watch: c_long = 254; pub const SYS_inotify_rm_watch: c_long = 255; pub const SYS_migrate_pages: c_long = 256; pub const SYS_openat: c_long = 257; pub const SYS_mkdirat: c_long = 258; pub const SYS_mknodat: c_long = 259; pub const SYS_fchownat: c_long = 260; pub const SYS_futimesat: c_long = 261; pub const SYS_newfstatat: c_long = 262; pub const SYS_unlinkat: c_long = 263; pub const SYS_renameat: c_long = 264; pub const SYS_linkat: c_long = 265; pub const SYS_symlinkat: c_long = 266; pub const SYS_readlinkat: c_long = 267; pub const SYS_fchmodat: c_long = 268; pub const SYS_faccessat: c_long = 269; pub const SYS_pselect6: c_long = 270; pub const SYS_ppoll: c_long = 271; pub const SYS_unshare: c_long = 272; pub const SYS_set_robust_list: c_long = 273; pub const SYS_get_robust_list: c_long = 274; pub const SYS_splice: c_long = 275; pub const SYS_tee: c_long = 276; pub const SYS_sync_file_range: c_long = 277; pub const SYS_vmsplice: c_long = 278; pub const SYS_move_pages: c_long = 279; pub const SYS_utimensat: c_long = 280; pub const SYS_epoll_pwait: c_long = 281; pub const SYS_signalfd: c_long = 282; pub const SYS_timerfd_create: c_long = 283; pub const SYS_eventfd: c_long = 284; pub const SYS_fallocate: c_long = 285; pub const SYS_timerfd_settime: c_long = 286; pub const SYS_timerfd_gettime: c_long = 287; pub const SYS_accept4: c_long = 288; pub const SYS_signalfd4: c_long = 289; pub const SYS_eventfd2: c_long = 290; pub const SYS_epoll_create1: c_long = 291; pub const SYS_dup3: c_long = 292; pub const SYS_pipe2: c_long = 293; pub const SYS_inotify_init1: c_long = 294; pub const SYS_preadv: c_long = 295; pub const SYS_pwritev: c_long = 296; pub const SYS_rt_tgsigqueueinfo: c_long = 297; pub const SYS_perf_event_open: c_long = 298; pub const SYS_recvmmsg: c_long = 299; pub const SYS_fanotify_init: c_long = 300; pub const SYS_fanotify_mark: c_long = 301; pub const SYS_prlimit64: c_long = 302; pub const SYS_name_to_handle_at: c_long = 303; pub const SYS_open_by_handle_at: c_long = 304; pub const SYS_clock_adjtime: c_long = 305; pub const SYS_syncfs: c_long = 306; pub const SYS_sendmmsg: c_long = 307; pub const SYS_setns: c_long = 308; pub const SYS_getcpu: c_long = 309; pub const SYS_process_vm_readv: c_long = 310; pub const SYS_process_vm_writev: c_long = 311; pub const SYS_kcmp: c_long = 312; pub const SYS_finit_module: c_long = 313; pub const SYS_sched_setattr: c_long = 314; pub const SYS_sched_getattr: c_long = 315; pub const SYS_renameat2: c_long = 316; pub const SYS_seccomp: c_long = 317; pub const SYS_getrandom: c_long = 318; pub const SYS_memfd_create: c_long = 319; pub const SYS_kexec_file_load: c_long = 320; pub const SYS_bpf: c_long = 321; pub const SYS_execveat: c_long = 322; pub const SYS_userfaultfd: c_long = 323; pub const SYS_membarrier: c_long = 324; pub const SYS_mlock2: c_long = 325; pub const SYS_copy_file_range: c_long = 326; pub const SYS_preadv2: c_long = 327; pub const SYS_pwritev2: c_long = 328; pub const SYS_pkey_mprotect: c_long = 329; pub const SYS_pkey_alloc: c_long = 330; pub const SYS_pkey_free: c_long = 331; pub const SYS_statx: c_long = 332; pub const SYS_io_pgetevents: c_long = 333; pub const SYS_rseq: c_long = 334; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_fchmodat2: c_long = 452; pub const SYS_mseal: c_long = 462; // offsets in user_regs_structs, from sys/reg.h pub const R15: c_int = 0; pub const R14: c_int = 1; pub const R13: c_int = 2; pub const R12: c_int = 3; pub const RBP: c_int = 4; pub const RBX: c_int = 5; pub const R11: c_int = 6; pub const R10: c_int = 7; pub const R9: c_int = 8; pub const R8: c_int = 9; pub const RAX: c_int = 10; pub const RCX: c_int = 11; pub const RDX: c_int = 12; pub const RSI: c_int = 13; pub const RDI: c_int = 14; pub const ORIG_RAX: c_int = 15; pub const RIP: c_int = 16; pub const CS: c_int = 17; pub const EFLAGS: c_int = 18; pub const RSP: c_int = 19; pub const SS: c_int = 20; pub const FS_BASE: c_int = 21; pub const GS_BASE: c_int = 22; pub const DS: c_int = 23; pub const ES: c_int = 24; pub const FS: c_int = 25; pub const GS: c_int = 26; // offsets in mcontext_t.gregs from bits/signal.h // GitHub repo: ifduyue/musl/ // commit: b4b1e10364c8737a632be61582e05a8d3acf5690 // file: arch/x86_64/bits/signal.h#L9-L56 pub const REG_R8: c_int = 0; pub const REG_R9: c_int = 1; pub const REG_R10: c_int = 2; pub const REG_R11: c_int = 3; pub const REG_R12: c_int = 4; pub const REG_R13: c_int = 5; pub const REG_R14: c_int = 6; pub const REG_R15: c_int = 7; pub const REG_RDI: c_int = 8; pub const REG_RSI: c_int = 9; pub const REG_RBP: c_int = 10; pub const REG_RBX: c_int = 11; pub const REG_RDX: c_int = 12; pub const REG_RAX: c_int = 13; pub const REG_RCX: c_int = 14; pub const REG_RSP: c_int = 15; pub const REG_RIP: c_int = 16; pub const REG_EFL: c_int = 17; pub const REG_CSGSFS: c_int = 18; pub const REG_ERR: c_int = 19; pub const REG_TRAPNO: c_int = 20; pub const REG_OLDMASK: c_int = 21; pub const REG_CR2: c_int = 22; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_32BIT: c_int = 0x0040; pub const O_APPEND: c_int = 1024; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_LARGEFILE: c_int = 0; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_ASYNC: c_int = 0x2000; pub const PTRACE_SYSEMU: c_int = 31; pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 32; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const EDEADLK: c_int = 35; pub const EDEADLOCK: c_int = EDEADLK; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; libc/src/unix/linux_like/linux/musl/b64/aarch64/0000775000175000017500000000000015105742312021174 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs0000644000175000017500000006010415105742312022320 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; pub type wchar_t = u32; pub type nlink_t = u32; pub type blksize_t = c_int; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad0: c_ulong, pub st_size: off_t, pub st_blksize: crate::blksize_t, __pad1: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_uint; 2], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad0: c_ulong, pub st_size: off_t, pub st_blksize: crate::blksize_t, __pad1: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_uint; 2], } pub struct user_regs_struct { pub regs: [c_ulonglong; 31], pub sp: c_ulonglong, pub pc: c_ulonglong, pub pstate: c_ulonglong, } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub fault_address: c_ulong, pub regs: [c_ulong; 31], pub sp: c_ulong, pub pc: c_ulong, pub pstate: c_ulong, __reserved: [u64; 512], } #[repr(align(8))] pub struct clone_args { pub flags: c_ulonglong, pub pidfd: c_ulonglong, pub child_tid: c_ulonglong, pub parent_tid: c_ulonglong, pub exit_signal: c_ulonglong, pub stack: c_ulonglong, pub stack_size: c_ulonglong, pub tls: c_ulonglong, pub set_tid: c_ulonglong, pub set_tid_size: c_ulonglong, pub cgroup: c_ulonglong, } pub struct user_fpsimd_struct { pub vregs: [crate::__uint128_t; 32], pub fpsr: u32, pub fpcr: u32, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f32; 8], } } pub const O_APPEND: c_int = 1024; pub const O_DIRECT: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_LARGEFILE: c_int = 0x20000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_ASYNC: c_int = 0x2000; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; // bits/hwcap.h pub const HWCAP_FP: c_ulong = 1 << 0; pub const HWCAP_ASIMD: c_ulong = 1 << 1; pub const HWCAP_EVTSTRM: c_ulong = 1 << 2; pub const HWCAP_AES: c_ulong = 1 << 3; pub const HWCAP_PMULL: c_ulong = 1 << 4; pub const HWCAP_SHA1: c_ulong = 1 << 5; pub const HWCAP_SHA2: c_ulong = 1 << 6; pub const HWCAP_CRC32: c_ulong = 1 << 7; pub const HWCAP_ATOMICS: c_ulong = 1 << 8; pub const HWCAP_FPHP: c_ulong = 1 << 9; pub const HWCAP_ASIMDHP: c_ulong = 1 << 10; pub const HWCAP_CPUID: c_ulong = 1 << 11; pub const HWCAP_ASIMDRDM: c_ulong = 1 << 12; pub const HWCAP_JSCVT: c_ulong = 1 << 13; pub const HWCAP_FCMA: c_ulong = 1 << 14; pub const HWCAP_LRCPC: c_ulong = 1 << 15; pub const HWCAP_DCPOP: c_ulong = 1 << 16; pub const HWCAP_SHA3: c_ulong = 1 << 17; pub const HWCAP_SM3: c_ulong = 1 << 18; pub const HWCAP_SM4: c_ulong = 1 << 19; pub const HWCAP_ASIMDDP: c_ulong = 1 << 20; pub const HWCAP_SHA512: c_ulong = 1 << 21; pub const HWCAP_SVE: c_ulong = 1 << 22; pub const HWCAP_ASIMDFHM: c_ulong = 1 << 23; pub const HWCAP_DIT: c_ulong = 1 << 24; pub const HWCAP_USCAT: c_ulong = 1 << 25; pub const HWCAP_ILRCPC: c_ulong = 1 << 26; pub const HWCAP_FLAGM: c_ulong = 1 << 27; pub const HWCAP_SSBS: c_ulong = 1 << 28; pub const HWCAP_SB: c_ulong = 1 << 29; pub const HWCAP_PACA: c_ulong = 1 << 30; pub const HWCAP_PACG: c_ulong = 1 << 31; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const MINSIGSTKSZ: size_t = 6144; pub const SIGSTKSZ: size_t = 12288; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_io_getevents: c_long = 4; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_getcwd: c_long = 17; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_dup: c_long = 23; pub const SYS_dup3: c_long = 24; pub const SYS_fcntl: c_long = 25; pub const SYS_inotify_init1: c_long = 26; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_ioctl: c_long = 29; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_flock: c_long = 32; pub const SYS_mknodat: c_long = 33; pub const SYS_mkdirat: c_long = 34; pub const SYS_unlinkat: c_long = 35; pub const SYS_symlinkat: c_long = 36; pub const SYS_linkat: c_long = 37; pub const SYS_renameat: c_long = 38; pub const SYS_umount2: c_long = 39; pub const SYS_mount: c_long = 40; pub const SYS_pivot_root: c_long = 41; pub const SYS_nfsservctl: c_long = 42; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_fallocate: c_long = 47; pub const SYS_faccessat: c_long = 48; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_chroot: c_long = 51; pub const SYS_fchmod: c_long = 52; pub const SYS_fchmodat: c_long = 53; pub const SYS_fchownat: c_long = 54; pub const SYS_fchown: c_long = 55; pub const SYS_openat: c_long = 56; pub const SYS_close: c_long = 57; pub const SYS_vhangup: c_long = 58; pub const SYS_pipe2: c_long = 59; pub const SYS_quotactl: c_long = 60; pub const SYS_getdents64: c_long = 61; pub const SYS_lseek: c_long = 62; pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_signalfd4: c_long = 74; pub const SYS_vmsplice: c_long = 75; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_readlinkat: c_long = 78; pub const SYS_newfstatat: c_long = 79; pub const SYS_fstat: c_long = 80; pub const SYS_sync: c_long = 81; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_sync_file_range: c_long = 84; pub const SYS_timerfd_create: c_long = 85; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_utimensat: c_long = 88; pub const SYS_acct: c_long = 89; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_personality: c_long = 92; pub const SYS_exit: c_long = 93; pub const SYS_exit_group: c_long = 94; pub const SYS_waitid: c_long = 95; pub const SYS_set_tid_address: c_long = 96; pub const SYS_unshare: c_long = 97; pub const SYS_futex: c_long = 98; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_kexec_load: c_long = 104; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_syslog: c_long = 116; pub const SYS_ptrace: c_long = 117; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_sched_yield: c_long = 124; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_restart_syscall: c_long = 128; pub const SYS_kill: c_long = 129; pub const SYS_tkill: c_long = 130; pub const SYS_tgkill: c_long = 131; pub const SYS_sigaltstack: c_long = 132; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_setpriority: c_long = 140; pub const SYS_getpriority: c_long = 141; pub const SYS_reboot: c_long = 142; pub const SYS_setregid: c_long = 143; pub const SYS_setgid: c_long = 144; pub const SYS_setreuid: c_long = 145; pub const SYS_setuid: c_long = 146; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_times: c_long = 153; pub const SYS_setpgid: c_long = 154; pub const SYS_getpgid: c_long = 155; pub const SYS_getsid: c_long = 156; pub const SYS_setsid: c_long = 157; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_uname: c_long = 160; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_getrlimit: c_long = 163; pub const SYS_setrlimit: c_long = 164; pub const SYS_getrusage: c_long = 165; pub const SYS_umask: c_long = 166; pub const SYS_prctl: c_long = 167; pub const SYS_getcpu: c_long = 168; pub const SYS_gettimeofday: c_long = 169; pub const SYS_settimeofday: c_long = 170; pub const SYS_adjtimex: c_long = 171; pub const SYS_getpid: c_long = 172; pub const SYS_getppid: c_long = 173; pub const SYS_getuid: c_long = 174; pub const SYS_geteuid: c_long = 175; pub const SYS_getgid: c_long = 176; pub const SYS_getegid: c_long = 177; pub const SYS_gettid: c_long = 178; pub const SYS_sysinfo: c_long = 179; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_msgget: c_long = 186; pub const SYS_msgctl: c_long = 187; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgsnd: c_long = 189; pub const SYS_semget: c_long = 190; pub const SYS_semctl: c_long = 191; pub const SYS_semtimedop: c_long = 192; pub const SYS_semop: c_long = 193; pub const SYS_shmget: c_long = 194; pub const SYS_shmctl: c_long = 195; pub const SYS_shmat: c_long = 196; pub const SYS_shmdt: c_long = 197; pub const SYS_socket: c_long = 198; pub const SYS_socketpair: c_long = 199; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_accept: c_long = 202; pub const SYS_connect: c_long = 203; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_shutdown: c_long = 210; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_readahead: c_long = 213; pub const SYS_brk: c_long = 214; pub const SYS_munmap: c_long = 215; pub const SYS_mremap: c_long = 216; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_mmap: c_long = 222; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_mprotect: c_long = 226; pub const SYS_msync: c_long = 227; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_mbind: c_long = 235; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_migrate_pages: c_long = 238; pub const SYS_move_pages: c_long = 239; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_accept4: c_long = 242; pub const SYS_recvmmsg: c_long = 243; pub const SYS_wait4: c_long = 260; pub const SYS_prlimit64: c_long = 261; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_setns: c_long = 268; pub const SYS_sendmmsg: c_long = 269; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_io_pgetevents: c_long = 292; pub const SYS_rseq: c_long = 293; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_mseal: c_long = 462; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const EDEADLK: c_int = 35; pub const EDEADLOCK: c_int = EDEADLK; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; libc/src/unix/linux_like/linux/musl/b64/wasm32/0000775000175000017500000000000015105742312021060 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b64/wasm32/mod.rs0000644000175000017500000005776315105742312022225 0ustar bdrungbdrung//! Wasm32 definitions conforming to the WALI ABI. //! The WALI ABI closely mirrors `x86_64` Linux and is thus implemented within the `b64` module as opposed to `b32` use crate::off_t; use crate::prelude::*; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = c_long; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __reserved: [c_long; 3], } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __unused1: c_long, __unused2: c_long, } } // Syscall table pub const SYS_read: c_long = 0; pub const SYS_write: c_long = 1; pub const SYS_open: c_long = 2; pub const SYS_close: c_long = 3; pub const SYS_stat: c_long = 4; pub const SYS_fstat: c_long = 5; pub const SYS_lstat: c_long = 6; pub const SYS_poll: c_long = 7; pub const SYS_lseek: c_long = 8; pub const SYS_mmap: c_long = 9; pub const SYS_mprotect: c_long = 10; pub const SYS_munmap: c_long = 11; pub const SYS_brk: c_long = 12; pub const SYS_rt_sigaction: c_long = 13; pub const SYS_rt_sigprocmask: c_long = 14; pub const SYS_rt_sigreturn: c_long = 15; pub const SYS_ioctl: c_long = 16; pub const SYS_pread64: c_long = 17; pub const SYS_pwrite64: c_long = 18; pub const SYS_readv: c_long = 19; pub const SYS_writev: c_long = 20; pub const SYS_access: c_long = 21; pub const SYS_pipe: c_long = 22; pub const SYS_select: c_long = 23; pub const SYS_sched_yield: c_long = 24; pub const SYS_mremap: c_long = 25; pub const SYS_msync: c_long = 26; pub const SYS_mincore: c_long = 27; pub const SYS_madvise: c_long = 28; pub const SYS_shmget: c_long = 29; pub const SYS_shmat: c_long = 30; pub const SYS_shmctl: c_long = 31; pub const SYS_dup: c_long = 32; pub const SYS_dup2: c_long = 33; pub const SYS_pause: c_long = 34; pub const SYS_nanosleep: c_long = 35; pub const SYS_getitimer: c_long = 36; pub const SYS_alarm: c_long = 37; pub const SYS_setitimer: c_long = 38; pub const SYS_getpid: c_long = 39; pub const SYS_sendfile: c_long = 40; pub const SYS_socket: c_long = 41; pub const SYS_connect: c_long = 42; pub const SYS_accept: c_long = 43; pub const SYS_sendto: c_long = 44; pub const SYS_recvfrom: c_long = 45; pub const SYS_sendmsg: c_long = 46; pub const SYS_recvmsg: c_long = 47; pub const SYS_shutdown: c_long = 48; pub const SYS_bind: c_long = 49; pub const SYS_listen: c_long = 50; pub const SYS_getsockname: c_long = 51; pub const SYS_getpeername: c_long = 52; pub const SYS_socketpair: c_long = 53; pub const SYS_setsockopt: c_long = 54; pub const SYS_getsockopt: c_long = 55; pub const SYS_clone: c_long = 56; pub const SYS_fork: c_long = 57; pub const SYS_vfork: c_long = 58; pub const SYS_execve: c_long = 59; pub const SYS_exit: c_long = 60; pub const SYS_wait4: c_long = 61; pub const SYS_kill: c_long = 62; pub const SYS_uname: c_long = 63; pub const SYS_semget: c_long = 64; pub const SYS_semop: c_long = 65; pub const SYS_semctl: c_long = 66; pub const SYS_shmdt: c_long = 67; pub const SYS_msgget: c_long = 68; pub const SYS_msgsnd: c_long = 69; pub const SYS_msgrcv: c_long = 70; pub const SYS_msgctl: c_long = 71; pub const SYS_fcntl: c_long = 72; pub const SYS_flock: c_long = 73; pub const SYS_fsync: c_long = 74; pub const SYS_fdatasync: c_long = 75; pub const SYS_truncate: c_long = 76; pub const SYS_ftruncate: c_long = 77; pub const SYS_getdents: c_long = 78; pub const SYS_getcwd: c_long = 79; pub const SYS_chdir: c_long = 80; pub const SYS_fchdir: c_long = 81; pub const SYS_rename: c_long = 82; pub const SYS_mkdir: c_long = 83; pub const SYS_rmdir: c_long = 84; pub const SYS_creat: c_long = 85; pub const SYS_link: c_long = 86; pub const SYS_unlink: c_long = 87; pub const SYS_symlink: c_long = 88; pub const SYS_readlink: c_long = 89; pub const SYS_chmod: c_long = 90; pub const SYS_fchmod: c_long = 91; pub const SYS_chown: c_long = 92; pub const SYS_fchown: c_long = 93; pub const SYS_lchown: c_long = 94; pub const SYS_umask: c_long = 95; pub const SYS_gettimeofday: c_long = 96; pub const SYS_getrlimit: c_long = 97; pub const SYS_getrusage: c_long = 98; pub const SYS_sysinfo: c_long = 99; pub const SYS_times: c_long = 100; pub const SYS_ptrace: c_long = 101; pub const SYS_getuid: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_getgid: c_long = 104; pub const SYS_setuid: c_long = 105; pub const SYS_setgid: c_long = 106; pub const SYS_geteuid: c_long = 107; pub const SYS_getegid: c_long = 108; pub const SYS_setpgid: c_long = 109; pub const SYS_getppid: c_long = 110; pub const SYS_getpgrp: c_long = 111; pub const SYS_setsid: c_long = 112; pub const SYS_setreuid: c_long = 113; pub const SYS_setregid: c_long = 114; pub const SYS_getgroups: c_long = 115; pub const SYS_setgroups: c_long = 116; pub const SYS_setresuid: c_long = 117; pub const SYS_getresuid: c_long = 118; pub const SYS_setresgid: c_long = 119; pub const SYS_getresgid: c_long = 120; pub const SYS_getpgid: c_long = 121; pub const SYS_setfsuid: c_long = 122; pub const SYS_setfsgid: c_long = 123; pub const SYS_getsid: c_long = 124; pub const SYS_capget: c_long = 125; pub const SYS_capset: c_long = 126; pub const SYS_rt_sigpending: c_long = 127; pub const SYS_rt_sigtimedwait: c_long = 128; pub const SYS_rt_sigqueueinfo: c_long = 129; pub const SYS_rt_sigsuspend: c_long = 130; pub const SYS_sigaltstack: c_long = 131; pub const SYS_utime: c_long = 132; pub const SYS_mknod: c_long = 133; pub const SYS_uselib: c_long = 134; pub const SYS_personality: c_long = 135; pub const SYS_ustat: c_long = 136; pub const SYS_statfs: c_long = 137; pub const SYS_fstatfs: c_long = 138; pub const SYS_sysfs: c_long = 139; pub const SYS_getpriority: c_long = 140; pub const SYS_setpriority: c_long = 141; pub const SYS_sched_setparam: c_long = 142; pub const SYS_sched_getparam: c_long = 143; pub const SYS_sched_setscheduler: c_long = 144; pub const SYS_sched_getscheduler: c_long = 145; pub const SYS_sched_get_priority_max: c_long = 146; pub const SYS_sched_get_priority_min: c_long = 147; pub const SYS_sched_rr_get_interval: c_long = 148; pub const SYS_mlock: c_long = 149; pub const SYS_munlock: c_long = 150; pub const SYS_mlockall: c_long = 151; pub const SYS_munlockall: c_long = 152; pub const SYS_vhangup: c_long = 153; pub const SYS_modify_ldt: c_long = 154; pub const SYS_pivot_root: c_long = 155; pub const SYS__sysctl: c_long = 156; pub const SYS_prctl: c_long = 157; pub const SYS_arch_prctl: c_long = 158; pub const SYS_adjtimex: c_long = 159; pub const SYS_setrlimit: c_long = 160; pub const SYS_chroot: c_long = 161; pub const SYS_sync: c_long = 162; pub const SYS_acct: c_long = 163; pub const SYS_settimeofday: c_long = 164; pub const SYS_mount: c_long = 165; pub const SYS_umount2: c_long = 166; pub const SYS_swapon: c_long = 167; pub const SYS_swapoff: c_long = 168; pub const SYS_reboot: c_long = 169; pub const SYS_sethostname: c_long = 170; pub const SYS_setdomainname: c_long = 171; pub const SYS_iopl: c_long = 172; pub const SYS_ioperm: c_long = 173; pub const SYS_create_module: c_long = 174; pub const SYS_init_module: c_long = 175; pub const SYS_delete_module: c_long = 176; pub const SYS_get_kernel_syms: c_long = 177; pub const SYS_query_module: c_long = 178; pub const SYS_quotactl: c_long = 179; pub const SYS_nfsservctl: c_long = 180; pub const SYS_getpmsg: c_long = 181; pub const SYS_putpmsg: c_long = 182; pub const SYS_afs_syscall: c_long = 183; pub const SYS_tuxcall: c_long = 184; pub const SYS_security: c_long = 185; pub const SYS_gettid: c_long = 186; pub const SYS_readahead: c_long = 187; pub const SYS_setxattr: c_long = 188; pub const SYS_lsetxattr: c_long = 189; pub const SYS_fsetxattr: c_long = 190; pub const SYS_getxattr: c_long = 191; pub const SYS_lgetxattr: c_long = 192; pub const SYS_fgetxattr: c_long = 193; pub const SYS_listxattr: c_long = 194; pub const SYS_llistxattr: c_long = 195; pub const SYS_flistxattr: c_long = 196; pub const SYS_removexattr: c_long = 197; pub const SYS_lremovexattr: c_long = 198; pub const SYS_fremovexattr: c_long = 199; pub const SYS_tkill: c_long = 200; pub const SYS_time: c_long = 201; pub const SYS_futex: c_long = 202; pub const SYS_sched_setaffinity: c_long = 203; pub const SYS_sched_getaffinity: c_long = 204; pub const SYS_set_thread_area: c_long = 205; pub const SYS_io_setup: c_long = 206; pub const SYS_io_destroy: c_long = 207; pub const SYS_io_getevents: c_long = 208; pub const SYS_io_submit: c_long = 209; pub const SYS_io_cancel: c_long = 210; pub const SYS_get_thread_area: c_long = 211; pub const SYS_lookup_dcookie: c_long = 212; pub const SYS_epoll_create: c_long = 213; pub const SYS_epoll_ctl_old: c_long = 214; pub const SYS_epoll_wait_old: c_long = 215; pub const SYS_remap_file_pages: c_long = 216; pub const SYS_getdents64: c_long = 217; pub const SYS_set_tid_address: c_long = 218; pub const SYS_restart_syscall: c_long = 219; pub const SYS_semtimedop: c_long = 220; pub const SYS_fadvise64: c_long = 221; pub const SYS_timer_create: c_long = 222; pub const SYS_timer_settime: c_long = 223; pub const SYS_timer_gettime: c_long = 224; pub const SYS_timer_getoverrun: c_long = 225; pub const SYS_timer_delete: c_long = 226; pub const SYS_clock_settime: c_long = 227; pub const SYS_clock_gettime: c_long = 228; pub const SYS_clock_getres: c_long = 229; pub const SYS_clock_nanosleep: c_long = 230; pub const SYS_exit_group: c_long = 231; pub const SYS_epoll_wait: c_long = 232; pub const SYS_epoll_ctl: c_long = 233; pub const SYS_tgkill: c_long = 234; pub const SYS_utimes: c_long = 235; pub const SYS_vserver: c_long = 236; pub const SYS_mbind: c_long = 237; pub const SYS_set_mempolicy: c_long = 238; pub const SYS_get_mempolicy: c_long = 239; pub const SYS_mq_open: c_long = 240; pub const SYS_mq_unlink: c_long = 241; pub const SYS_mq_timedsend: c_long = 242; pub const SYS_mq_timedreceive: c_long = 243; pub const SYS_mq_notify: c_long = 244; pub const SYS_mq_getsetattr: c_long = 245; pub const SYS_kexec_load: c_long = 246; pub const SYS_waitid: c_long = 247; pub const SYS_add_key: c_long = 248; pub const SYS_request_key: c_long = 249; pub const SYS_keyctl: c_long = 250; pub const SYS_ioprio_set: c_long = 251; pub const SYS_ioprio_get: c_long = 252; pub const SYS_inotify_init: c_long = 253; pub const SYS_inotify_add_watch: c_long = 254; pub const SYS_inotify_rm_watch: c_long = 255; pub const SYS_migrate_pages: c_long = 256; pub const SYS_openat: c_long = 257; pub const SYS_mkdirat: c_long = 258; pub const SYS_mknodat: c_long = 259; pub const SYS_fchownat: c_long = 260; pub const SYS_futimesat: c_long = 261; pub const SYS_newfstatat: c_long = 262; pub const SYS_unlinkat: c_long = 263; pub const SYS_renameat: c_long = 264; pub const SYS_linkat: c_long = 265; pub const SYS_symlinkat: c_long = 266; pub const SYS_readlinkat: c_long = 267; pub const SYS_fchmodat: c_long = 268; pub const SYS_faccessat: c_long = 269; pub const SYS_pselect6: c_long = 270; pub const SYS_ppoll: c_long = 271; pub const SYS_unshare: c_long = 272; pub const SYS_set_robust_list: c_long = 273; pub const SYS_get_robust_list: c_long = 274; pub const SYS_splice: c_long = 275; pub const SYS_tee: c_long = 276; pub const SYS_sync_file_range: c_long = 277; pub const SYS_vmsplice: c_long = 278; pub const SYS_move_pages: c_long = 279; pub const SYS_utimensat: c_long = 280; pub const SYS_epoll_pwait: c_long = 281; pub const SYS_signalfd: c_long = 282; pub const SYS_timerfd_create: c_long = 283; pub const SYS_eventfd: c_long = 284; pub const SYS_fallocate: c_long = 285; pub const SYS_timerfd_settime: c_long = 286; pub const SYS_timerfd_gettime: c_long = 287; pub const SYS_accept4: c_long = 288; pub const SYS_signalfd4: c_long = 289; pub const SYS_eventfd2: c_long = 290; pub const SYS_epoll_create1: c_long = 291; pub const SYS_dup3: c_long = 292; pub const SYS_pipe2: c_long = 293; pub const SYS_inotify_init1: c_long = 294; pub const SYS_preadv: c_long = 295; pub const SYS_pwritev: c_long = 296; pub const SYS_rt_tgsigqueueinfo: c_long = 297; pub const SYS_perf_event_open: c_long = 298; pub const SYS_recvmmsg: c_long = 299; pub const SYS_fanotify_init: c_long = 300; pub const SYS_fanotify_mark: c_long = 301; pub const SYS_prlimit64: c_long = 302; pub const SYS_name_to_handle_at: c_long = 303; pub const SYS_open_by_handle_at: c_long = 304; pub const SYS_clock_adjtime: c_long = 305; pub const SYS_syncfs: c_long = 306; pub const SYS_sendmmsg: c_long = 307; pub const SYS_setns: c_long = 308; pub const SYS_getcpu: c_long = 309; pub const SYS_process_vm_readv: c_long = 310; pub const SYS_process_vm_writev: c_long = 311; pub const SYS_kcmp: c_long = 312; pub const SYS_finit_module: c_long = 313; pub const SYS_sched_setattr: c_long = 314; pub const SYS_sched_getattr: c_long = 315; pub const SYS_renameat2: c_long = 316; pub const SYS_seccomp: c_long = 317; pub const SYS_getrandom: c_long = 318; pub const SYS_memfd_create: c_long = 319; pub const SYS_kexec_file_load: c_long = 320; pub const SYS_bpf: c_long = 321; pub const SYS_execveat: c_long = 322; pub const SYS_userfaultfd: c_long = 323; pub const SYS_membarrier: c_long = 324; pub const SYS_mlock2: c_long = 325; pub const SYS_copy_file_range: c_long = 326; pub const SYS_preadv2: c_long = 327; pub const SYS_pwritev2: c_long = 328; pub const SYS_pkey_mprotect: c_long = 329; pub const SYS_pkey_alloc: c_long = 330; pub const SYS_pkey_free: c_long = 331; pub const SYS_statx: c_long = 332; pub const SYS_io_pgetevents: c_long = 333; pub const SYS_rseq: c_long = 334; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; // Syscall aliases for WALI pub const SYS_fadvise: c_long = SYS_fadvise64; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_32BIT: c_int = 0x0040; pub const O_APPEND: c_int = 1024; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_LARGEFILE: c_int = 0; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_ASYNC: c_int = 0x2000; pub const PTRACE_SYSEMU: c_int = 31; pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 32; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const EDEADLK: c_int = 35; pub const EDEADLOCK: c_int = EDEADLK; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; cfg_if! { if #[cfg(target_vendor = "wali")] { mod wali; pub use self::wali::*; } } libc/src/unix/linux_like/linux/musl/b64/wasm32/wali.rs0000644000175000017500000004050715105742312022366 0ustar bdrungbdrung//! WebAssembly Linux Interface syscall specification // --- Autogenerated from WALI/scripts/autogen.py --- #[link(wasm_import_module = "wali")] extern "C" { /* 0 */ #[link_name = "SYS_read"] pub fn __syscall_SYS_read(a1: i32, a2: i32, a3: u32) -> ::c_long; /* 1 */ #[link_name = "SYS_write"] pub fn __syscall_SYS_write(a1: i32, a2: i32, a3: u32) -> ::c_long; /* 2 */ #[link_name = "SYS_open"] pub fn __syscall_SYS_open(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 3 */ #[link_name = "SYS_close"] pub fn __syscall_SYS_close(a1: i32) -> ::c_long; /* 4 */ #[link_name = "SYS_stat"] pub fn __syscall_SYS_stat(a1: i32, a2: i32) -> ::c_long; /* 5 */ #[link_name = "SYS_fstat"] pub fn __syscall_SYS_fstat(a1: i32, a2: i32) -> ::c_long; /* 6 */ #[link_name = "SYS_lstat"] pub fn __syscall_SYS_lstat(a1: i32, a2: i32) -> ::c_long; /* 7 */ #[link_name = "SYS_poll"] pub fn __syscall_SYS_poll(a1: i32, a2: u32, a3: i32) -> ::c_long; /* 8 */ #[link_name = "SYS_lseek"] pub fn __syscall_SYS_lseek(a1: i32, a2: i64, a3: i32) -> ::c_long; /* 9 */ #[link_name = "SYS_mmap"] pub fn __syscall_SYS_mmap(a1: i32, a2: u32, a3: i32, a4: i32, a5: i32, a6: i64) -> ::c_long; /* 10 */ #[link_name = "SYS_mprotect"] pub fn __syscall_SYS_mprotect(a1: i32, a2: u32, a3: i32) -> ::c_long; /* 11 */ #[link_name = "SYS_munmap"] pub fn __syscall_SYS_munmap(a1: i32, a2: u32) -> ::c_long; /* 12 */ #[link_name = "SYS_brk"] pub fn __syscall_SYS_brk(a1: i32) -> ::c_long; /* 13 */ #[link_name = "SYS_rt_sigaction"] pub fn __syscall_SYS_rt_sigaction(a1: i32, a2: i32, a3: i32, a4: u32) -> ::c_long; /* 14 */ #[link_name = "SYS_rt_sigprocmask"] pub fn __syscall_SYS_rt_sigprocmask(a1: i32, a2: i32, a3: i32, a4: u32) -> ::c_long; /* 15 */ #[link_name = "SYS_rt_sigreturn"] pub fn __syscall_SYS_rt_sigreturn(a1: i64) -> ::c_long; /* 16 */ #[link_name = "SYS_ioctl"] pub fn __syscall_SYS_ioctl(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 17 */ #[link_name = "SYS_pread64"] pub fn __syscall_SYS_pread64(a1: i32, a2: i32, a3: u32, a4: i64) -> ::c_long; /* 18 */ #[link_name = "SYS_pwrite64"] pub fn __syscall_SYS_pwrite64(a1: i32, a2: i32, a3: u32, a4: i64) -> ::c_long; /* 19 */ #[link_name = "SYS_readv"] pub fn __syscall_SYS_readv(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 20 */ #[link_name = "SYS_writev"] pub fn __syscall_SYS_writev(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 21 */ #[link_name = "SYS_access"] pub fn __syscall_SYS_access(a1: i32, a2: i32) -> ::c_long; /* 22 */ #[link_name = "SYS_pipe"] pub fn __syscall_SYS_pipe(a1: i32) -> ::c_long; /* 23 */ #[link_name = "SYS_select"] pub fn __syscall_SYS_select(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) -> ::c_long; /* 24 */ #[link_name = "SYS_sched_yield"] pub fn __syscall_SYS_sched_yield() -> ::c_long; /* 25 */ #[link_name = "SYS_mremap"] pub fn __syscall_SYS_mremap(a1: i32, a2: u32, a3: u32, a4: i32, a5: i32) -> ::c_long; /* 26 */ #[link_name = "SYS_msync"] pub fn __syscall_SYS_msync(a1: i32, a2: u32, a3: i32) -> ::c_long; /* 28 */ #[link_name = "SYS_madvise"] pub fn __syscall_SYS_madvise(a1: i32, a2: u32, a3: i32) -> ::c_long; /* 32 */ #[link_name = "SYS_dup"] pub fn __syscall_SYS_dup(a1: i32) -> ::c_long; /* 33 */ #[link_name = "SYS_dup2"] pub fn __syscall_SYS_dup2(a1: i32, a2: i32) -> ::c_long; /* 35 */ #[link_name = "SYS_nanosleep"] pub fn __syscall_SYS_nanosleep(a1: i32, a2: i32) -> ::c_long; /* 37 */ #[link_name = "SYS_alarm"] pub fn __syscall_SYS_alarm(a1: i32) -> ::c_long; /* 38 */ #[link_name = "SYS_setitimer"] pub fn __syscall_SYS_setitimer(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 39 */ #[link_name = "SYS_getpid"] pub fn __syscall_SYS_getpid() -> ::c_long; /* 41 */ #[link_name = "SYS_socket"] pub fn __syscall_SYS_socket(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 42 */ #[link_name = "SYS_connect"] pub fn __syscall_SYS_connect(a1: i32, a2: i32, a3: u32) -> ::c_long; /* 43 */ #[link_name = "SYS_accept"] pub fn __syscall_SYS_accept(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 44 */ #[link_name = "SYS_sendto"] pub fn __syscall_SYS_sendto(a1: i32, a2: i32, a3: u32, a4: i32, a5: i32, a6: u32) -> ::c_long; /* 45 */ #[link_name = "SYS_recvfrom"] pub fn __syscall_SYS_recvfrom(a1: i32, a2: i32, a3: u32, a4: i32, a5: i32, a6: i32) -> ::c_long; /* 46 */ #[link_name = "SYS_sendmsg"] pub fn __syscall_SYS_sendmsg(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 47 */ #[link_name = "SYS_recvmsg"] pub fn __syscall_SYS_recvmsg(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 48 */ #[link_name = "SYS_shutdown"] pub fn __syscall_SYS_shutdown(a1: i32, a2: i32) -> ::c_long; /* 49 */ #[link_name = "SYS_bind"] pub fn __syscall_SYS_bind(a1: i32, a2: i32, a3: u32) -> ::c_long; /* 50 */ #[link_name = "SYS_listen"] pub fn __syscall_SYS_listen(a1: i32, a2: i32) -> ::c_long; /* 51 */ #[link_name = "SYS_getsockname"] pub fn __syscall_SYS_getsockname(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 52 */ #[link_name = "SYS_getpeername"] pub fn __syscall_SYS_getpeername(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 53 */ #[link_name = "SYS_socketpair"] pub fn __syscall_SYS_socketpair(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 54 */ #[link_name = "SYS_setsockopt"] pub fn __syscall_SYS_setsockopt(a1: i32, a2: i32, a3: i32, a4: i32, a5: u32) -> ::c_long; /* 55 */ #[link_name = "SYS_getsockopt"] pub fn __syscall_SYS_getsockopt(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) -> ::c_long; /* 57 */ #[link_name = "SYS_fork"] pub fn __syscall_SYS_fork() -> ::c_long; /* 59 */ #[link_name = "SYS_execve"] pub fn __syscall_SYS_execve(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 60 */ #[link_name = "SYS_exit"] pub fn __syscall_SYS_exit(a1: i32) -> ::c_long; /* 61 */ #[link_name = "SYS_wait4"] pub fn __syscall_SYS_wait4(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 62 */ #[link_name = "SYS_kill"] pub fn __syscall_SYS_kill(a1: i32, a2: i32) -> ::c_long; /* 63 */ #[link_name = "SYS_uname"] pub fn __syscall_SYS_uname(a1: i32) -> ::c_long; /* 72 */ #[link_name = "SYS_fcntl"] pub fn __syscall_SYS_fcntl(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 73 */ #[link_name = "SYS_flock"] pub fn __syscall_SYS_flock(a1: i32, a2: i32) -> ::c_long; /* 74 */ #[link_name = "SYS_fsync"] pub fn __syscall_SYS_fsync(a1: i32) -> ::c_long; /* 75 */ #[link_name = "SYS_fdatasync"] pub fn __syscall_SYS_fdatasync(a1: i32) -> ::c_long; /* 77 */ #[link_name = "SYS_ftruncate"] pub fn __syscall_SYS_ftruncate(a1: i32, a2: i64) -> ::c_long; /* 78 */ #[link_name = "SYS_getdents"] pub fn __syscall_SYS_getdents(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 79 */ #[link_name = "SYS_getcwd"] pub fn __syscall_SYS_getcwd(a1: i32, a2: u32) -> ::c_long; /* 80 */ #[link_name = "SYS_chdir"] pub fn __syscall_SYS_chdir(a1: i32) -> ::c_long; /* 81 */ #[link_name = "SYS_fchdir"] pub fn __syscall_SYS_fchdir(a1: i32) -> ::c_long; /* 82 */ #[link_name = "SYS_rename"] pub fn __syscall_SYS_rename(a1: i32, a2: i32) -> ::c_long; /* 83 */ #[link_name = "SYS_mkdir"] pub fn __syscall_SYS_mkdir(a1: i32, a2: i32) -> ::c_long; /* 84 */ #[link_name = "SYS_rmdir"] pub fn __syscall_SYS_rmdir(a1: i32) -> ::c_long; /* 86 */ #[link_name = "SYS_link"] pub fn __syscall_SYS_link(a1: i32, a2: i32) -> ::c_long; /* 87 */ #[link_name = "SYS_unlink"] pub fn __syscall_SYS_unlink(a1: i32) -> ::c_long; /* 88 */ #[link_name = "SYS_symlink"] pub fn __syscall_SYS_symlink(a1: i32, a2: i32) -> ::c_long; /* 89 */ #[link_name = "SYS_readlink"] pub fn __syscall_SYS_readlink(a1: i32, a2: i32, a3: u32) -> ::c_long; /* 90 */ #[link_name = "SYS_chmod"] pub fn __syscall_SYS_chmod(a1: i32, a2: i32) -> ::c_long; /* 91 */ #[link_name = "SYS_fchmod"] pub fn __syscall_SYS_fchmod(a1: i32, a2: i32) -> ::c_long; /* 92 */ #[link_name = "SYS_chown"] pub fn __syscall_SYS_chown(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 93 */ #[link_name = "SYS_fchown"] pub fn __syscall_SYS_fchown(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 95 */ #[link_name = "SYS_umask"] pub fn __syscall_SYS_umask(a1: i32) -> ::c_long; /* 97 */ #[link_name = "SYS_getrlimit"] pub fn __syscall_SYS_getrlimit(a1: i32, a2: i32) -> ::c_long; /* 98 */ #[link_name = "SYS_getrusage"] pub fn __syscall_SYS_getrusage(a1: i32, a2: i32) -> ::c_long; /* 99 */ #[link_name = "SYS_sysinfo"] pub fn __syscall_SYS_sysinfo(a1: i32) -> ::c_long; /* 102 */ #[link_name = "SYS_getuid"] pub fn __syscall_SYS_getuid() -> ::c_long; /* 104 */ #[link_name = "SYS_getgid"] pub fn __syscall_SYS_getgid() -> ::c_long; /* 105 */ #[link_name = "SYS_setuid"] pub fn __syscall_SYS_setuid(a1: i32) -> ::c_long; /* 106 */ #[link_name = "SYS_setgid"] pub fn __syscall_SYS_setgid(a1: i32) -> ::c_long; /* 107 */ #[link_name = "SYS_geteuid"] pub fn __syscall_SYS_geteuid() -> ::c_long; /* 108 */ #[link_name = "SYS_getegid"] pub fn __syscall_SYS_getegid() -> ::c_long; /* 109 */ #[link_name = "SYS_setpgid"] pub fn __syscall_SYS_setpgid(a1: i32, a2: i32) -> ::c_long; /* 110 */ #[link_name = "SYS_getppid"] pub fn __syscall_SYS_getppid() -> ::c_long; /* 112 */ #[link_name = "SYS_setsid"] pub fn __syscall_SYS_setsid() -> ::c_long; /* 113 */ #[link_name = "SYS_setreuid"] pub fn __syscall_SYS_setreuid(a1: i32, a2: i32) -> ::c_long; /* 114 */ #[link_name = "SYS_setregid"] pub fn __syscall_SYS_setregid(a1: i32, a2: i32) -> ::c_long; /* 115 */ #[link_name = "SYS_getgroups"] pub fn __syscall_SYS_getgroups(a1: u32, a2: i32) -> ::c_long; /* 116 */ #[link_name = "SYS_setgroups"] pub fn __syscall_SYS_setgroups(a1: u32, a2: i32) -> ::c_long; /* 117 */ #[link_name = "SYS_setresuid"] pub fn __syscall_SYS_setresuid(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 119 */ #[link_name = "SYS_setresgid"] pub fn __syscall_SYS_setresgid(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 121 */ #[link_name = "SYS_getpgid"] pub fn __syscall_SYS_getpgid(a1: i32) -> ::c_long; /* 124 */ #[link_name = "SYS_getsid"] pub fn __syscall_SYS_getsid(a1: i32) -> ::c_long; /* 127 */ #[link_name = "SYS_rt_sigpending"] pub fn __syscall_SYS_rt_sigpending(a1: i32, a2: u32) -> ::c_long; /* 130 */ #[link_name = "SYS_rt_sigsuspend"] pub fn __syscall_SYS_rt_sigsuspend(a1: i32, a2: u32) -> ::c_long; /* 131 */ #[link_name = "SYS_sigaltstack"] pub fn __syscall_SYS_sigaltstack(a1: i32, a2: i32) -> ::c_long; /* 132 */ #[link_name = "SYS_utime"] pub fn __syscall_SYS_utime(a1: i32, a2: i32) -> ::c_long; /* 137 */ #[link_name = "SYS_statfs"] pub fn __syscall_SYS_statfs(a1: i32, a2: i32) -> ::c_long; /* 138 */ #[link_name = "SYS_fstatfs"] pub fn __syscall_SYS_fstatfs(a1: i32, a2: i32) -> ::c_long; /* 157 */ #[link_name = "SYS_prctl"] pub fn __syscall_SYS_prctl(a1: i32, a2: u64, a3: u64, a4: u64, a5: u64) -> ::c_long; /* 160 */ #[link_name = "SYS_setrlimit"] pub fn __syscall_SYS_setrlimit(a1: i32, a2: i32) -> ::c_long; /* 161 */ #[link_name = "SYS_chroot"] pub fn __syscall_SYS_chroot(a1: i32) -> ::c_long; /* 186 */ #[link_name = "SYS_gettid"] pub fn __syscall_SYS_gettid() -> ::c_long; /* 200 */ #[link_name = "SYS_tkill"] pub fn __syscall_SYS_tkill(a1: i32, a2: i32) -> ::c_long; /* 202 */ #[link_name = "SYS_futex"] pub fn __syscall_SYS_futex(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32, a6: i32) -> ::c_long; /* 204 */ #[link_name = "SYS_sched_getaffinity"] pub fn __syscall_SYS_sched_getaffinity(a1: i32, a2: u32, a3: i32) -> ::c_long; /* 217 */ #[link_name = "SYS_getdents64"] pub fn __syscall_SYS_getdents64(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 218 */ #[link_name = "SYS_set_tid_address"] pub fn __syscall_SYS_set_tid_address(a1: i32) -> ::c_long; /* 221 */ #[link_name = "SYS_fadvise"] pub fn __syscall_SYS_fadvise(a1: i32, a2: i64, a3: i64, a4: i32) -> ::c_long; /* 228 */ #[link_name = "SYS_clock_gettime"] pub fn __syscall_SYS_clock_gettime(a1: i32, a2: i32) -> ::c_long; /* 229 */ #[link_name = "SYS_clock_getres"] pub fn __syscall_SYS_clock_getres(a1: i32, a2: i32) -> ::c_long; /* 230 */ #[link_name = "SYS_clock_nanosleep"] pub fn __syscall_SYS_clock_nanosleep(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 231 */ #[link_name = "SYS_exit_group"] pub fn __syscall_SYS_exit_group(a1: i32) -> ::c_long; /* 233 */ #[link_name = "SYS_epoll_ctl"] pub fn __syscall_SYS_epoll_ctl(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 257 */ #[link_name = "SYS_openat"] pub fn __syscall_SYS_openat(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 258 */ #[link_name = "SYS_mkdirat"] pub fn __syscall_SYS_mkdirat(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 260 */ #[link_name = "SYS_fchownat"] pub fn __syscall_SYS_fchownat(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) -> ::c_long; /* 262 */ #[link_name = "SYS_fstatat"] pub fn __syscall_SYS_fstatat(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 263 */ #[link_name = "SYS_unlinkat"] pub fn __syscall_SYS_unlinkat(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 265 */ #[link_name = "SYS_linkat"] pub fn __syscall_SYS_linkat(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) -> ::c_long; /* 266 */ #[link_name = "SYS_symlinkat"] pub fn __syscall_SYS_symlinkat(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 267 */ #[link_name = "SYS_readlinkat"] pub fn __syscall_SYS_readlinkat(a1: i32, a2: i32, a3: i32, a4: u32) -> ::c_long; /* 268 */ #[link_name = "SYS_fchmodat"] pub fn __syscall_SYS_fchmodat(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 269 */ #[link_name = "SYS_faccessat"] pub fn __syscall_SYS_faccessat(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 270 */ #[link_name = "SYS_pselect6"] pub fn __syscall_SYS_pselect6(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32, a6: i32) -> ::c_long; /* 271 */ #[link_name = "SYS_ppoll"] pub fn __syscall_SYS_ppoll(a1: i32, a2: u32, a3: i32, a4: i32, a5: u32) -> ::c_long; /* 280 */ #[link_name = "SYS_utimensat"] pub fn __syscall_SYS_utimensat(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 281 */ #[link_name = "SYS_epoll_pwait"] pub fn __syscall_SYS_epoll_pwait( a1: i32, a2: i32, a3: i32, a4: i32, a5: i32, a6: u32, ) -> ::c_long; /* 284 */ #[link_name = "SYS_eventfd"] pub fn __syscall_SYS_eventfd(a1: i32) -> ::c_long; /* 288 */ #[link_name = "SYS_accept4"] pub fn __syscall_SYS_accept4(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 290 */ #[link_name = "SYS_eventfd2"] pub fn __syscall_SYS_eventfd2(a1: i32, a2: i32) -> ::c_long; /* 291 */ #[link_name = "SYS_epoll_create1"] pub fn __syscall_SYS_epoll_create1(a1: i32) -> ::c_long; /* 292 */ #[link_name = "SYS_dup3"] pub fn __syscall_SYS_dup3(a1: i32, a2: i32, a3: i32) -> ::c_long; /* 293 */ #[link_name = "SYS_pipe2"] pub fn __syscall_SYS_pipe2(a1: i32, a2: i32) -> ::c_long; /* 302 */ #[link_name = "SYS_prlimit64"] pub fn __syscall_SYS_prlimit64(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; /* 316 */ #[link_name = "SYS_renameat2"] pub fn __syscall_SYS_renameat2(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) -> ::c_long; /* 318 */ #[link_name = "SYS_getrandom"] pub fn __syscall_SYS_getrandom(a1: i32, a2: u32, a3: i32) -> ::c_long; /* 332 */ #[link_name = "SYS_statx"] pub fn __syscall_SYS_statx(a1: i32, a2: i32, a3: i32, a4: i32, a5: i32) -> ::c_long; /* 439 */ #[link_name = "SYS_faccessat2"] pub fn __syscall_SYS_faccessat2(a1: i32, a2: i32, a3: i32, a4: i32) -> ::c_long; } libc/src/unix/linux_like/linux/musl/b64/s390x.rs0000644000175000017500000006212415105742312021203 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type blksize_t = i64; pub type nlink_t = u64; pub type wchar_t = i32; pub type greg_t = u64; pub type __u64 = u64; pub type __s64 = i64; s! { pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __pad1: c_long, __pad2: c_long, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, __unused: [c_long; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, __unused: [c_long; 3], } } s_no_extra_traits! { // FIXME(union): This is actually a union. pub struct fpreg_t { pub d: c_double, // f: c_float, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for fpreg_t { fn eq(&self, other: &fpreg_t) -> bool { self.d == other.d } } impl Eq for fpreg_t {} impl fmt::Debug for fpreg_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fpreg_t").field("d", &self.d).finish() } } impl hash::Hash for fpreg_t { fn hash(&self, state: &mut H) { let d: u64 = unsafe { mem::transmute(self.d) }; d.hash(state); } } } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ECONNABORTED: c_int = 103; pub const ECONNREFUSED: c_int = 111; pub const ECONNRESET: c_int = 104; pub const EDEADLK: c_int = 35; pub const ENOSYS: c_int = 38; pub const ENOTCONN: c_int = 107; pub const ETIMEDOUT: c_int = 110; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_LARGEFILE: c_int = 0x8000; pub const O_NONBLOCK: c_int = 2048; pub const SA_NOCLDWAIT: c_int = 2; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 4; pub const SIGBUS: c_int = 7; pub const SIGSTKSZ: size_t = 0x2000; pub const MINSIGSTKSZ: size_t = 2048; pub const SIG_SETMASK: c_int = 2; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const O_NOCTTY: c_int = 256; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_ANON: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const PTRACE_SYSEMU: c_int = 31; pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 32; pub const EDEADLOCK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 17; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const O_ASYNC: c_int = 0x2000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const VTIME: usize = 5; pub const VSWTC: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const VREPRINT: usize = 12; pub const VDISCARD: usize = 13; pub const VWERASE: usize = 14; pub const OLCUC: crate::tcflag_t = 0o000002; pub const ONLCR: crate::tcflag_t = 0o000004; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const TABDLY: crate::tcflag_t = 0o014000; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const BSDLY: crate::tcflag_t = 0o020000; pub const BS1: crate::tcflag_t = 0x00002000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const FF1: crate::tcflag_t = 0x00008000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const VT1: crate::tcflag_t = 0x00004000; pub const XTABS: crate::tcflag_t = 0o014000; pub const CBAUD: crate::speed_t = 0o010017; pub const CSIZE: crate::tcflag_t = 0o000060; pub const CS6: crate::tcflag_t = 0o000020; pub const CS7: crate::tcflag_t = 0o000040; pub const CS8: crate::tcflag_t = 0o000060; pub const CSTOPB: crate::tcflag_t = 0o000100; pub const CREAD: crate::tcflag_t = 0o000200; pub const PARENB: crate::tcflag_t = 0o000400; pub const PARODD: crate::tcflag_t = 0o001000; pub const HUPCL: crate::tcflag_t = 0o002000; pub const CLOCAL: crate::tcflag_t = 0o004000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const ISIG: crate::tcflag_t = 0o000001; pub const ICANON: crate::tcflag_t = 0o000002; pub const XCASE: crate::tcflag_t = 0o000004; pub const ECHOE: crate::tcflag_t = 0o000020; pub const ECHOK: crate::tcflag_t = 0o000040; pub const ECHONL: crate::tcflag_t = 0o000100; pub const NOFLSH: crate::tcflag_t = 0o000200; pub const ECHOCTL: crate::tcflag_t = 0o001000; pub const ECHOPRT: crate::tcflag_t = 0o002000; pub const ECHOKE: crate::tcflag_t = 0o004000; pub const PENDIN: crate::tcflag_t = 0o040000; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const IXON: crate::tcflag_t = 0o002000; pub const IXOFF: crate::tcflag_t = 0o010000; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_restart_syscall: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_brk: c_long = 45; pub const SYS_signal: c_long = 48; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_setpgid: c_long = 57; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_symlink: c_long = 83; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_lookup_dcookie: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; /* Syscall for Andrew File System */ pub const SYS_getdents: c_long = 141; pub const SYS_select: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 167; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_getpmsg: c_long = 188; pub const SYS_putpmsg: c_long = 189; pub const SYS_vfork: c_long = 190; pub const SYS_getrlimit: c_long = 191; pub const SYS_lchown: c_long = 198; pub const SYS_getuid: c_long = 199; pub const SYS_getgid: c_long = 200; pub const SYS_geteuid: c_long = 201; pub const SYS_getegid: c_long = 202; pub const SYS_setreuid: c_long = 203; pub const SYS_setregid: c_long = 204; pub const SYS_getgroups: c_long = 205; pub const SYS_setgroups: c_long = 206; pub const SYS_fchown: c_long = 207; pub const SYS_setresuid: c_long = 208; pub const SYS_getresuid: c_long = 209; pub const SYS_setresgid: c_long = 210; pub const SYS_getresgid: c_long = 211; pub const SYS_chown: c_long = 212; pub const SYS_setuid: c_long = 213; pub const SYS_setgid: c_long = 214; pub const SYS_setfsuid: c_long = 215; pub const SYS_setfsgid: c_long = 216; pub const SYS_pivot_root: c_long = 217; pub const SYS_mincore: c_long = 218; pub const SYS_madvise: c_long = 219; pub const SYS_getdents64: c_long = 220; pub const SYS_readahead: c_long = 222; pub const SYS_setxattr: c_long = 224; pub const SYS_lsetxattr: c_long = 225; pub const SYS_fsetxattr: c_long = 226; pub const SYS_getxattr: c_long = 227; pub const SYS_lgetxattr: c_long = 228; pub const SYS_fgetxattr: c_long = 229; pub const SYS_listxattr: c_long = 230; pub const SYS_llistxattr: c_long = 231; pub const SYS_flistxattr: c_long = 232; pub const SYS_removexattr: c_long = 233; pub const SYS_lremovexattr: c_long = 234; pub const SYS_fremovexattr: c_long = 235; pub const SYS_gettid: c_long = 236; pub const SYS_tkill: c_long = 237; pub const SYS_futex: c_long = 238; pub const SYS_sched_setaffinity: c_long = 239; pub const SYS_sched_getaffinity: c_long = 240; pub const SYS_tgkill: c_long = 241; pub const SYS_io_setup: c_long = 243; pub const SYS_io_destroy: c_long = 244; pub const SYS_io_getevents: c_long = 245; pub const SYS_io_submit: c_long = 246; pub const SYS_io_cancel: c_long = 247; pub const SYS_exit_group: c_long = 248; pub const SYS_epoll_create: c_long = 249; pub const SYS_epoll_ctl: c_long = 250; pub const SYS_epoll_wait: c_long = 251; pub const SYS_set_tid_address: c_long = 252; pub const SYS_fadvise64: c_long = 253; pub const SYS_timer_create: c_long = 254; pub const SYS_timer_settime: c_long = 255; pub const SYS_timer_gettime: c_long = 256; pub const SYS_timer_getoverrun: c_long = 257; pub const SYS_timer_delete: c_long = 258; pub const SYS_clock_settime: c_long = 259; pub const SYS_clock_gettime: c_long = 260; pub const SYS_clock_getres: c_long = 261; pub const SYS_clock_nanosleep: c_long = 262; pub const SYS_statfs64: c_long = 265; pub const SYS_fstatfs64: c_long = 266; pub const SYS_remap_file_pages: c_long = 267; pub const SYS_mbind: c_long = 268; pub const SYS_get_mempolicy: c_long = 269; pub const SYS_set_mempolicy: c_long = 270; pub const SYS_mq_open: c_long = 271; pub const SYS_mq_unlink: c_long = 272; pub const SYS_mq_timedsend: c_long = 273; pub const SYS_mq_timedreceive: c_long = 274; pub const SYS_mq_notify: c_long = 275; pub const SYS_mq_getsetattr: c_long = 276; pub const SYS_kexec_load: c_long = 277; pub const SYS_add_key: c_long = 278; pub const SYS_request_key: c_long = 279; pub const SYS_keyctl: c_long = 280; pub const SYS_waitid: c_long = 281; pub const SYS_ioprio_set: c_long = 282; pub const SYS_ioprio_get: c_long = 283; pub const SYS_inotify_init: c_long = 284; pub const SYS_inotify_add_watch: c_long = 285; pub const SYS_inotify_rm_watch: c_long = 286; pub const SYS_migrate_pages: c_long = 287; pub const SYS_openat: c_long = 288; pub const SYS_mkdirat: c_long = 289; pub const SYS_mknodat: c_long = 290; pub const SYS_fchownat: c_long = 291; pub const SYS_futimesat: c_long = 292; pub const SYS_newfstatat: c_long = 293; pub const SYS_unlinkat: c_long = 294; pub const SYS_renameat: c_long = 295; pub const SYS_linkat: c_long = 296; pub const SYS_symlinkat: c_long = 297; pub const SYS_readlinkat: c_long = 298; pub const SYS_fchmodat: c_long = 299; pub const SYS_faccessat: c_long = 300; pub const SYS_pselect6: c_long = 301; pub const SYS_ppoll: c_long = 302; pub const SYS_unshare: c_long = 303; pub const SYS_set_robust_list: c_long = 304; pub const SYS_get_robust_list: c_long = 305; pub const SYS_splice: c_long = 306; pub const SYS_sync_file_range: c_long = 307; pub const SYS_tee: c_long = 308; pub const SYS_vmsplice: c_long = 309; pub const SYS_move_pages: c_long = 310; pub const SYS_getcpu: c_long = 311; pub const SYS_epoll_pwait: c_long = 312; pub const SYS_utimes: c_long = 313; pub const SYS_fallocate: c_long = 314; pub const SYS_utimensat: c_long = 315; pub const SYS_signalfd: c_long = 316; pub const SYS_timerfd: c_long = 317; pub const SYS_eventfd: c_long = 318; pub const SYS_timerfd_create: c_long = 319; pub const SYS_timerfd_settime: c_long = 320; pub const SYS_timerfd_gettime: c_long = 321; pub const SYS_signalfd4: c_long = 322; pub const SYS_eventfd2: c_long = 323; pub const SYS_inotify_init1: c_long = 324; pub const SYS_pipe2: c_long = 325; pub const SYS_dup3: c_long = 326; pub const SYS_epoll_create1: c_long = 327; pub const SYS_preadv: c_long = 328; pub const SYS_pwritev: c_long = 329; pub const SYS_rt_tgsigqueueinfo: c_long = 330; pub const SYS_perf_event_open: c_long = 331; pub const SYS_fanotify_init: c_long = 332; pub const SYS_fanotify_mark: c_long = 333; pub const SYS_prlimit64: c_long = 334; pub const SYS_name_to_handle_at: c_long = 335; pub const SYS_open_by_handle_at: c_long = 336; pub const SYS_clock_adjtime: c_long = 337; pub const SYS_syncfs: c_long = 338; pub const SYS_setns: c_long = 339; pub const SYS_process_vm_readv: c_long = 340; pub const SYS_process_vm_writev: c_long = 341; pub const SYS_s390_runtime_instr: c_long = 342; pub const SYS_kcmp: c_long = 343; pub const SYS_finit_module: c_long = 344; pub const SYS_sched_setattr: c_long = 345; pub const SYS_sched_getattr: c_long = 346; pub const SYS_renameat2: c_long = 347; pub const SYS_seccomp: c_long = 348; pub const SYS_getrandom: c_long = 349; pub const SYS_memfd_create: c_long = 350; pub const SYS_bpf: c_long = 351; pub const SYS_s390_pci_mmio_write: c_long = 352; pub const SYS_s390_pci_mmio_read: c_long = 353; pub const SYS_execveat: c_long = 354; pub const SYS_userfaultfd: c_long = 355; pub const SYS_membarrier: c_long = 356; pub const SYS_recvmmsg: c_long = 357; pub const SYS_sendmmsg: c_long = 358; pub const SYS_socket: c_long = 359; pub const SYS_socketpair: c_long = 360; pub const SYS_bind: c_long = 361; pub const SYS_connect: c_long = 362; pub const SYS_listen: c_long = 363; pub const SYS_accept4: c_long = 364; pub const SYS_getsockopt: c_long = 365; pub const SYS_setsockopt: c_long = 366; pub const SYS_getsockname: c_long = 367; pub const SYS_getpeername: c_long = 368; pub const SYS_sendto: c_long = 369; pub const SYS_sendmsg: c_long = 370; pub const SYS_recvfrom: c_long = 371; pub const SYS_recvmsg: c_long = 372; pub const SYS_shutdown: c_long = 373; pub const SYS_mlock2: c_long = 374; pub const SYS_copy_file_range: c_long = 375; pub const SYS_preadv2: c_long = 376; pub const SYS_pwritev2: c_long = 377; pub const SYS_s390_guarded_storage: c_long = 378; pub const SYS_statx: c_long = 379; pub const SYS_s390_sthyi: c_long = 380; pub const SYS_kexec_file_load: c_long = 381; pub const SYS_io_pgetevents: c_long = 382; pub const SYS_rseq: c_long = 383; pub const SYS_pkey_mprotect: c_long = 384; pub const SYS_pkey_alloc: c_long = 385; pub const SYS_pkey_free: c_long = 386; pub const SYS_semtimedop: c_long = 392; pub const SYS_semget: c_long = 393; pub const SYS_semctl: c_long = 394; pub const SYS_shmget: c_long = 395; pub const SYS_shmctl: c_long = 396; pub const SYS_shmat: c_long = 397; pub const SYS_shmdt: c_long = 398; pub const SYS_msgget: c_long = 399; pub const SYS_msgsnd: c_long = 400; pub const SYS_msgrcv: c_long = 401; pub const SYS_msgctl: c_long = 402; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_cachestat: c_long = 451; pub const SYS_fchmodat2: c_long = 452; libc/src/unix/linux_like/linux/musl/b64/riscv64/0000775000175000017500000000000015105742312021244 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs0000644000175000017500000005626115105742312022401 0ustar bdrungbdrung//! RISC-V-specific definitions for 64-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = c_int; pub type nlink_t = c_uint; pub type blksize_t = c_int; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2usize], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } #[repr(align(8))] pub struct clone_args { pub flags: c_ulonglong, pub pidfd: c_ulonglong, pub child_tid: c_ulonglong, pub parent_tid: c_ulonglong, pub exit_signal: c_ulonglong, pub stack: c_ulonglong, pub stack_size: c_ulonglong, pub tls: c_ulonglong, pub set_tid: c_ulonglong, pub set_tid_size: c_ulonglong, pub cgroup: c_ulonglong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct ucontext_t { pub __uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct mcontext_t { pub __gregs: [c_ulong; 32], pub __fpregs: __riscv_mc_fp_state, } pub union __riscv_mc_fp_state { pub __f: __riscv_mc_f_ext_state, pub __d: __riscv_mc_d_ext_state, pub __q: __riscv_mc_q_ext_state, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_f_ext_state { pub __f: [c_uint; 32], pub __fcsr: c_uint, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_d_ext_state { pub __f: [c_ulonglong; 32], pub __fcsr: c_uint, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct __riscv_mc_q_ext_state { pub __f: [c_ulonglong; 64], pub __fcsr: c_uint, pub __glibc_reserved: [c_uint; 3], } } pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_close: c_long = 57; pub const SYS_fstat: c_long = 80; pub const SYS_lseek: c_long = 62; pub const SYS_mmap: c_long = 222; pub const SYS_mprotect: c_long = 226; pub const SYS_munmap: c_long = 215; pub const SYS_brk: c_long = 214; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_ioctl: c_long = 29; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_sched_yield: c_long = 124; pub const SYS_mremap: c_long = 216; pub const SYS_msync: c_long = 227; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_shmget: c_long = 194; pub const SYS_shmat: c_long = 196; pub const SYS_shmctl: c_long = 195; pub const SYS_dup: c_long = 23; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_getpid: c_long = 172; pub const SYS_sendfile: c_long = 71; pub const SYS_socket: c_long = 198; pub const SYS_connect: c_long = 203; pub const SYS_accept: c_long = 202; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_shutdown: c_long = 210; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_socketpair: c_long = 199; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_exit: c_long = 93; pub const SYS_wait4: c_long = 260; pub const SYS_kill: c_long = 129; pub const SYS_uname: c_long = 160; pub const SYS_semget: c_long = 190; pub const SYS_semop: c_long = 193; pub const SYS_semctl: c_long = 191; pub const SYS_shmdt: c_long = 197; pub const SYS_msgget: c_long = 186; pub const SYS_msgsnd: c_long = 189; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgctl: c_long = 187; pub const SYS_fcntl: c_long = 25; pub const SYS_flock: c_long = 32; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_getcwd: c_long = 17; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_fchmod: c_long = 52; pub const SYS_fchown: c_long = 55; pub const SYS_umask: c_long = 166; pub const SYS_gettimeofday: c_long = 169; pub const SYS_getrlimit: c_long = 163; pub const SYS_getrusage: c_long = 165; pub const SYS_sysinfo: c_long = 179; pub const SYS_times: c_long = 153; pub const SYS_ptrace: c_long = 117; pub const SYS_getuid: c_long = 174; pub const SYS_syslog: c_long = 116; pub const SYS_getgid: c_long = 176; pub const SYS_setuid: c_long = 146; pub const SYS_setgid: c_long = 144; pub const SYS_geteuid: c_long = 175; pub const SYS_getegid: c_long = 177; pub const SYS_setpgid: c_long = 154; pub const SYS_getppid: c_long = 173; pub const SYS_setsid: c_long = 157; pub const SYS_setreuid: c_long = 145; pub const SYS_setregid: c_long = 143; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_getpgid: c_long = 155; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_getsid: c_long = 156; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_sigaltstack: c_long = 132; pub const SYS_personality: c_long = 92; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_getpriority: c_long = 141; pub const SYS_setpriority: c_long = 140; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_vhangup: c_long = 58; pub const SYS_pivot_root: c_long = 41; pub const SYS_prctl: c_long = 167; pub const SYS_adjtimex: c_long = 171; pub const SYS_setrlimit: c_long = 164; pub const SYS_chroot: c_long = 51; pub const SYS_sync: c_long = 81; pub const SYS_acct: c_long = 89; pub const SYS_settimeofday: c_long = 170; pub const SYS_mount: c_long = 40; pub const SYS_umount2: c_long = 39; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_reboot: c_long = 142; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_quotactl: c_long = 60; pub const SYS_nfsservctl: c_long = 42; pub const SYS_gettid: c_long = 178; pub const SYS_readahead: c_long = 213; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_tkill: c_long = 130; pub const SYS_futex: c_long = 98; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_getevents: c_long = 4; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_getdents64: c_long = 61; pub const SYS_set_tid_address: c_long = 96; pub const SYS_restart_syscall: c_long = 128; pub const SYS_semtimedop: c_long = 192; pub const SYS_fadvise64: c_long = 223; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_exit_group: c_long = 94; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_tgkill: c_long = 131; pub const SYS_mbind: c_long = 235; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_kexec_load: c_long = 104; pub const SYS_waitid: c_long = 95; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_migrate_pages: c_long = 238; pub const SYS_openat: c_long = 56; pub const SYS_mkdirat: c_long = 34; pub const SYS_mknodat: c_long = 33; pub const SYS_fchownat: c_long = 54; pub const SYS_newfstatat: c_long = 79; pub const SYS_unlinkat: c_long = 35; pub const SYS_linkat: c_long = 37; pub const SYS_symlinkat: c_long = 36; pub const SYS_readlinkat: c_long = 78; pub const SYS_fchmodat: c_long = 53; pub const SYS_faccessat: c_long = 48; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_unshare: c_long = 97; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_sync_file_range: c_long = 84; pub const SYS_vmsplice: c_long = 75; pub const SYS_move_pages: c_long = 239; pub const SYS_utimensat: c_long = 88; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_timerfd_create: c_long = 85; pub const SYS_fallocate: c_long = 47; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_accept4: c_long = 242; pub const SYS_signalfd4: c_long = 74; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_dup3: c_long = 24; pub const SYS_pipe2: c_long = 59; pub const SYS_inotify_init1: c_long = 26; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_recvmmsg: c_long = 243; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_prlimit64: c_long = 261; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_sendmmsg: c_long = 269; pub const SYS_setns: c_long = 268; pub const SYS_getcpu: c_long = 168; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_io_pgetevents: c_long = 292; pub const SYS_rseq: c_long = 293; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const O_APPEND: c_int = 1024; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_LARGEFILE: c_int = 0; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_ASYNC: c_int = 0x2000; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const EDEADLK: c_int = 35; pub const EDEADLOCK: c_int = EDEADLK; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const NGREG: usize = 32; pub const REG_PC: usize = 0; pub const REG_RA: usize = 1; pub const REG_SP: usize = 2; pub const REG_TP: usize = 4; pub const REG_S0: usize = 8; pub const REG_S1: usize = 9; pub const REG_A0: usize = 10; pub const REG_S2: usize = 18; pub const REG_NARGS: usize = 8; libc/src/unix/linux_like/linux/musl/b64/loongarch64/0000775000175000017500000000000015105742312022072 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs0000644000175000017500000005603015105742312023221 0ustar bdrungbdrung//! LoongArch-specific definitions for 64-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = c_int; pub type nlink_t = c_uint; pub type blksize_t = c_int; pub type fsblkcnt64_t = c_ulong; pub type fsfilcnt64_t = c_ulong; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2usize], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_uint, pub __seq: c_int, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct user_regs_struct { pub regs: [u64; 32], pub orig_a0: u64, pub csr_era: u64, pub csr_badv: u64, pub reserved: [u64; 10], } pub struct user_fp_struct { pub fpr: [u64; 32], pub fcc: u64, pub fcsr: u32, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub __pc: c_ulong, pub __gregs: [c_ulong; 32], pub __flags: c_uint, pub __extcontext: [c_ulong; 0], } #[repr(align(8))] pub struct clone_args { pub flags: c_ulonglong, pub pidfd: c_ulonglong, pub child_tid: c_ulonglong, pub parent_tid: c_ulonglong, pub exit_signal: c_ulonglong, pub stack: c_ulonglong, pub stack_size: c_ulonglong, pub tls: c_ulonglong, pub set_tid: c_ulonglong, pub set_tid_size: c_ulonglong, pub cgroup: c_ulonglong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } } pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_io_getevents: c_long = 4; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_getcwd: c_long = 17; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_dup: c_long = 23; pub const SYS_dup3: c_long = 24; pub const SYS_fcntl: c_long = 25; pub const SYS_inotify_init1: c_long = 26; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_ioctl: c_long = 29; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_flock: c_long = 32; pub const SYS_mknodat: c_long = 33; pub const SYS_mkdirat: c_long = 34; pub const SYS_unlinkat: c_long = 35; pub const SYS_symlinkat: c_long = 36; pub const SYS_linkat: c_long = 37; pub const SYS_umount2: c_long = 39; pub const SYS_mount: c_long = 40; pub const SYS_pivot_root: c_long = 41; pub const SYS_nfsservctl: c_long = 42; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_fallocate: c_long = 47; pub const SYS_faccessat: c_long = 48; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_chroot: c_long = 51; pub const SYS_fchmod: c_long = 52; pub const SYS_fchmodat: c_long = 53; pub const SYS_fchownat: c_long = 54; pub const SYS_fchown: c_long = 55; pub const SYS_openat: c_long = 56; pub const SYS_close: c_long = 57; pub const SYS_vhangup: c_long = 58; pub const SYS_pipe2: c_long = 59; pub const SYS_quotactl: c_long = 60; pub const SYS_getdents64: c_long = 61; pub const SYS_lseek: c_long = 62; pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_sendfile: c_long = 71; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_signalfd4: c_long = 74; pub const SYS_vmsplice: c_long = 75; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_readlinkat: c_long = 78; pub const SYS_sync: c_long = 81; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_sync_file_range: c_long = 84; pub const SYS_timerfd_create: c_long = 85; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_utimensat: c_long = 88; pub const SYS_acct: c_long = 89; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_personality: c_long = 92; pub const SYS_exit: c_long = 93; pub const SYS_exit_group: c_long = 94; pub const SYS_waitid: c_long = 95; pub const SYS_set_tid_address: c_long = 96; pub const SYS_unshare: c_long = 97; pub const SYS_futex: c_long = 98; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_kexec_load: c_long = 104; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_syslog: c_long = 116; pub const SYS_ptrace: c_long = 117; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_sched_yield: c_long = 124; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_restart_syscall: c_long = 128; pub const SYS_kill: c_long = 129; pub const SYS_tkill: c_long = 130; pub const SYS_tgkill: c_long = 131; pub const SYS_sigaltstack: c_long = 132; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_setpriority: c_long = 140; pub const SYS_getpriority: c_long = 141; pub const SYS_reboot: c_long = 142; pub const SYS_setregid: c_long = 143; pub const SYS_setgid: c_long = 144; pub const SYS_setreuid: c_long = 145; pub const SYS_setuid: c_long = 146; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_times: c_long = 153; pub const SYS_setpgid: c_long = 154; pub const SYS_getpgid: c_long = 155; pub const SYS_getsid: c_long = 156; pub const SYS_setsid: c_long = 157; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_uname: c_long = 160; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_getrusage: c_long = 165; pub const SYS_umask: c_long = 166; pub const SYS_prctl: c_long = 167; pub const SYS_getcpu: c_long = 168; pub const SYS_gettimeofday: c_long = 169; pub const SYS_settimeofday: c_long = 170; pub const SYS_adjtimex: c_long = 171; pub const SYS_getpid: c_long = 172; pub const SYS_getppid: c_long = 173; pub const SYS_getuid: c_long = 174; pub const SYS_geteuid: c_long = 175; pub const SYS_getgid: c_long = 176; pub const SYS_getegid: c_long = 177; pub const SYS_gettid: c_long = 178; pub const SYS_sysinfo: c_long = 179; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_msgget: c_long = 186; pub const SYS_msgctl: c_long = 187; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgsnd: c_long = 189; pub const SYS_semget: c_long = 190; pub const SYS_semctl: c_long = 191; pub const SYS_semtimedop: c_long = 192; pub const SYS_semop: c_long = 193; pub const SYS_shmget: c_long = 194; pub const SYS_shmctl: c_long = 195; pub const SYS_shmat: c_long = 196; pub const SYS_shmdt: c_long = 197; pub const SYS_socket: c_long = 198; pub const SYS_socketpair: c_long = 199; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_accept: c_long = 202; pub const SYS_connect: c_long = 203; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_shutdown: c_long = 210; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_readahead: c_long = 213; pub const SYS_brk: c_long = 214; pub const SYS_munmap: c_long = 215; pub const SYS_mremap: c_long = 216; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_mmap: c_long = 222; pub const SYS_fadvise64: c_long = 223; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_mprotect: c_long = 226; pub const SYS_msync: c_long = 227; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_mbind: c_long = 235; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_migrate_pages: c_long = 238; pub const SYS_move_pages: c_long = 239; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_accept4: c_long = 242; pub const SYS_recvmmsg: c_long = 243; pub const SYS_arch_specific_syscall: c_long = 244; pub const SYS_wait4: c_long = 260; pub const SYS_prlimit64: c_long = 261; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_setns: c_long = 268; pub const SYS_sendmmsg: c_long = 269; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_io_pgetevents: c_long = 292; pub const SYS_rseq: c_long = 293; pub const SYS_kexec_file_load: c_long = 294; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_cachestat: c_long = 451; pub const SYS_fchmodat2: c_long = 452; pub const SYS_map_shadow_stack: c_long = 453; pub const SYS_futex_wake: c_long = 454; pub const SYS_futex_wait: c_long = 455; pub const SYS_futex_requeue: c_long = 456; pub const O_APPEND: c_int = 1024; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_LARGEFILE: c_int = 0o0100000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_ASYNC: c_int = 0o20000; pub const SIGSTKSZ: size_t = 16384; pub const MINSIGSTKSZ: size_t = 4096; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0; pub const SIG_UNBLOCK: c_int = 1; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const XCASE: crate::tcflag_t = 0x00000004; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const EDEADLK: c_int = 35; pub const EDEADLOCK: c_int = EDEADLK; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs0000644000175000017500000006270515105742312022153 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = i32; pub type __u64 = c_ulong; pub type __s64 = c_long; pub type nlink_t = u64; pub type blksize_t = c_long; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __reserved: [c_long; 3], } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __unused1: c_long, __unused2: c_long, } } pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_32BIT: c_int = 0x0040; pub const O_APPEND: c_int = 1024; pub const O_DIRECT: c_int = 0x20000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_LARGEFILE: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_ASYNC: c_int = 0x2000; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const PTRACE_SYSEMU: c_int = 0x1d; pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 0x1e; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_SETOWN: c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const SIGSTKSZ: size_t = 10240; pub const MINSIGSTKSZ: size_t = 4096; // Syscall table pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_waitpid: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_time: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_break: c_long = 17; pub const SYS_oldstat: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_stime: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_oldfstat: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_stty: c_long = 31; pub const SYS_gtty: c_long = 32; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_ftime: c_long = 35; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_prof: c_long = 44; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_lock: c_long = 53; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_mpx: c_long = 56; pub const SYS_setpgid: c_long = 57; pub const SYS_ulimit: c_long = 58; pub const SYS_oldolduname: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sgetmask: c_long = 68; pub const SYS_ssetmask: c_long = 69; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrlimit: c_long = 76; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_select: c_long = 82; pub const SYS_symlink: c_long = 83; pub const SYS_oldlstat: c_long = 84; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_profil: c_long = 98; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_ioperm: c_long = 101; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_olduname: c_long = 109; pub const SYS_iopl: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_vm86: c_long = 113; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_modify_ldt: c_long = 123; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; /* Syscall for Andrew File System */ pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 166; pub const SYS_poll: c_long = 167; pub const SYS_nfsservctl: c_long = 168; pub const SYS_setresgid: c_long = 169; pub const SYS_getresgid: c_long = 170; pub const SYS_prctl: c_long = 171; pub const SYS_rt_sigreturn: c_long = 172; pub const SYS_rt_sigaction: c_long = 173; pub const SYS_rt_sigprocmask: c_long = 174; pub const SYS_rt_sigpending: c_long = 175; pub const SYS_rt_sigtimedwait: c_long = 176; pub const SYS_rt_sigqueueinfo: c_long = 177; pub const SYS_rt_sigsuspend: c_long = 178; pub const SYS_pread64: c_long = 179; pub const SYS_pwrite64: c_long = 180; pub const SYS_chown: c_long = 181; pub const SYS_getcwd: c_long = 182; pub const SYS_capget: c_long = 183; pub const SYS_capset: c_long = 184; pub const SYS_sigaltstack: c_long = 185; pub const SYS_sendfile: c_long = 186; pub const SYS_getpmsg: c_long = 187; /* some people actually want streams */ pub const SYS_putpmsg: c_long = 188; /* some people actually want streams */ pub const SYS_vfork: c_long = 189; pub const SYS_ugetrlimit: c_long = 190; /* SuS compliant getrlimit */ pub const SYS_readahead: c_long = 191; pub const SYS_pciconfig_read: c_long = 198; pub const SYS_pciconfig_write: c_long = 199; pub const SYS_pciconfig_iobase: c_long = 200; pub const SYS_multiplexer: c_long = 201; pub const SYS_getdents64: c_long = 202; pub const SYS_pivot_root: c_long = 203; pub const SYS_madvise: c_long = 205; pub const SYS_mincore: c_long = 206; pub const SYS_gettid: c_long = 207; pub const SYS_tkill: c_long = 208; pub const SYS_setxattr: c_long = 209; pub const SYS_lsetxattr: c_long = 210; pub const SYS_fsetxattr: c_long = 211; pub const SYS_getxattr: c_long = 212; pub const SYS_lgetxattr: c_long = 213; pub const SYS_fgetxattr: c_long = 214; pub const SYS_listxattr: c_long = 215; pub const SYS_llistxattr: c_long = 216; pub const SYS_flistxattr: c_long = 217; pub const SYS_removexattr: c_long = 218; pub const SYS_lremovexattr: c_long = 219; pub const SYS_fremovexattr: c_long = 220; pub const SYS_futex: c_long = 221; pub const SYS_sched_setaffinity: c_long = 222; pub const SYS_sched_getaffinity: c_long = 223; pub const SYS_tuxcall: c_long = 225; pub const SYS_io_setup: c_long = 227; pub const SYS_io_destroy: c_long = 228; pub const SYS_io_getevents: c_long = 229; pub const SYS_io_submit: c_long = 230; pub const SYS_io_cancel: c_long = 231; pub const SYS_set_tid_address: c_long = 232; pub const SYS_exit_group: c_long = 234; pub const SYS_lookup_dcookie: c_long = 235; pub const SYS_epoll_create: c_long = 236; pub const SYS_epoll_ctl: c_long = 237; pub const SYS_epoll_wait: c_long = 238; pub const SYS_remap_file_pages: c_long = 239; pub const SYS_timer_create: c_long = 240; pub const SYS_timer_settime: c_long = 241; pub const SYS_timer_gettime: c_long = 242; pub const SYS_timer_getoverrun: c_long = 243; pub const SYS_timer_delete: c_long = 244; pub const SYS_clock_settime: c_long = 245; pub const SYS_clock_gettime: c_long = 246; pub const SYS_clock_getres: c_long = 247; pub const SYS_clock_nanosleep: c_long = 248; pub const SYS_swapcontext: c_long = 249; pub const SYS_tgkill: c_long = 250; pub const SYS_utimes: c_long = 251; pub const SYS_statfs64: c_long = 252; pub const SYS_fstatfs64: c_long = 253; pub const SYS_rtas: c_long = 255; pub const SYS_sys_debug_setcontext: c_long = 256; pub const SYS_migrate_pages: c_long = 258; pub const SYS_mbind: c_long = 259; pub const SYS_get_mempolicy: c_long = 260; pub const SYS_set_mempolicy: c_long = 261; pub const SYS_mq_open: c_long = 262; pub const SYS_mq_unlink: c_long = 263; pub const SYS_mq_timedsend: c_long = 264; pub const SYS_mq_timedreceive: c_long = 265; pub const SYS_mq_notify: c_long = 266; pub const SYS_mq_getsetattr: c_long = 267; pub const SYS_kexec_load: c_long = 268; pub const SYS_add_key: c_long = 269; pub const SYS_request_key: c_long = 270; pub const SYS_keyctl: c_long = 271; pub const SYS_waitid: c_long = 272; pub const SYS_ioprio_set: c_long = 273; pub const SYS_ioprio_get: c_long = 274; pub const SYS_inotify_init: c_long = 275; pub const SYS_inotify_add_watch: c_long = 276; pub const SYS_inotify_rm_watch: c_long = 277; pub const SYS_spu_run: c_long = 278; pub const SYS_spu_create: c_long = 279; pub const SYS_pselect6: c_long = 280; pub const SYS_ppoll: c_long = 281; pub const SYS_unshare: c_long = 282; pub const SYS_splice: c_long = 283; pub const SYS_tee: c_long = 284; pub const SYS_vmsplice: c_long = 285; pub const SYS_openat: c_long = 286; pub const SYS_mkdirat: c_long = 287; pub const SYS_mknodat: c_long = 288; pub const SYS_fchownat: c_long = 289; pub const SYS_futimesat: c_long = 290; pub const SYS_newfstatat: c_long = 291; pub const SYS_unlinkat: c_long = 292; pub const SYS_renameat: c_long = 293; pub const SYS_linkat: c_long = 294; pub const SYS_symlinkat: c_long = 295; pub const SYS_readlinkat: c_long = 296; pub const SYS_fchmodat: c_long = 297; pub const SYS_faccessat: c_long = 298; pub const SYS_get_robust_list: c_long = 299; pub const SYS_set_robust_list: c_long = 300; pub const SYS_move_pages: c_long = 301; pub const SYS_getcpu: c_long = 302; pub const SYS_epoll_pwait: c_long = 303; pub const SYS_utimensat: c_long = 304; pub const SYS_signalfd: c_long = 305; pub const SYS_timerfd_create: c_long = 306; pub const SYS_eventfd: c_long = 307; pub const SYS_sync_file_range2: c_long = 308; pub const SYS_fallocate: c_long = 309; pub const SYS_subpage_prot: c_long = 310; pub const SYS_timerfd_settime: c_long = 311; pub const SYS_timerfd_gettime: c_long = 312; pub const SYS_signalfd4: c_long = 313; pub const SYS_eventfd2: c_long = 314; pub const SYS_epoll_create1: c_long = 315; pub const SYS_dup3: c_long = 316; pub const SYS_pipe2: c_long = 317; pub const SYS_inotify_init1: c_long = 318; pub const SYS_perf_event_open: c_long = 319; pub const SYS_preadv: c_long = 320; pub const SYS_pwritev: c_long = 321; pub const SYS_rt_tgsigqueueinfo: c_long = 322; pub const SYS_fanotify_init: c_long = 323; pub const SYS_fanotify_mark: c_long = 324; pub const SYS_prlimit64: c_long = 325; pub const SYS_socket: c_long = 326; pub const SYS_bind: c_long = 327; pub const SYS_connect: c_long = 328; pub const SYS_listen: c_long = 329; pub const SYS_accept: c_long = 330; pub const SYS_getsockname: c_long = 331; pub const SYS_getpeername: c_long = 332; pub const SYS_socketpair: c_long = 333; pub const SYS_send: c_long = 334; pub const SYS_sendto: c_long = 335; pub const SYS_recv: c_long = 336; pub const SYS_recvfrom: c_long = 337; pub const SYS_shutdown: c_long = 338; pub const SYS_setsockopt: c_long = 339; pub const SYS_getsockopt: c_long = 340; pub const SYS_sendmsg: c_long = 341; pub const SYS_recvmsg: c_long = 342; pub const SYS_recvmmsg: c_long = 343; pub const SYS_accept4: c_long = 344; pub const SYS_name_to_handle_at: c_long = 345; pub const SYS_open_by_handle_at: c_long = 346; pub const SYS_clock_adjtime: c_long = 347; pub const SYS_syncfs: c_long = 348; pub const SYS_sendmmsg: c_long = 349; pub const SYS_setns: c_long = 350; pub const SYS_process_vm_readv: c_long = 351; pub const SYS_process_vm_writev: c_long = 352; pub const SYS_finit_module: c_long = 353; pub const SYS_kcmp: c_long = 354; pub const SYS_sched_setattr: c_long = 355; pub const SYS_sched_getattr: c_long = 356; pub const SYS_renameat2: c_long = 357; pub const SYS_seccomp: c_long = 358; pub const SYS_getrandom: c_long = 359; pub const SYS_memfd_create: c_long = 360; pub const SYS_bpf: c_long = 361; pub const SYS_execveat: c_long = 362; pub const SYS_switch_endian: c_long = 363; pub const SYS_userfaultfd: c_long = 364; pub const SYS_membarrier: c_long = 365; pub const SYS_mlock2: c_long = 378; pub const SYS_copy_file_range: c_long = 379; pub const SYS_preadv2: c_long = 380; pub const SYS_pwritev2: c_long = 381; pub const SYS_kexec_file_load: c_long = 382; pub const SYS_statx: c_long = 383; pub const SYS_pkey_alloc: c_long = 384; pub const SYS_pkey_free: c_long = 385; pub const SYS_pkey_mprotect: c_long = 386; pub const SYS_rseq: c_long = 387; pub const SYS_io_pgetevents: c_long = 388; pub const SYS_semtimedop: c_long = 392; pub const SYS_semget: c_long = 393; pub const SYS_semctl: c_long = 394; pub const SYS_shmget: c_long = 395; pub const SYS_shmctl: c_long = 396; pub const SYS_shmat: c_long = 397; pub const SYS_shmdt: c_long = 398; pub const SYS_msgget: c_long = 399; pub const SYS_msgsnd: c_long = 400; pub const SYS_msgrcv: c_long = 401; pub const SYS_msgctl: c_long = 402; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const EDEADLK: c_int = 58; pub const EDEADLOCK: c_int = EDEADLK; pub const EXTPROC: crate::tcflag_t = 0x10000000; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; pub const VMIN: usize = 5; pub const IEXTEN: crate::tcflag_t = 0x00000400; pub const TOSTOP: crate::tcflag_t = 0x00400000; pub const FLUSHO: crate::tcflag_t = 0x00800000; pub const MCL_CURRENT: c_int = 0x2000; pub const MCL_FUTURE: c_int = 0x4000; pub const MCL_ONFAULT: c_int = 0x8000; pub const CBAUD: crate::tcflag_t = 0xff; pub const TAB1: c_int = 0x400; pub const TAB2: c_int = 0x800; pub const TAB3: c_int = 0xc00; pub const CR1: c_int = 0x1000; pub const CR2: c_int = 0x2000; pub const CR3: c_int = 0x3000; pub const FF1: c_int = 0x4000; pub const BS1: c_int = 0x8000; pub const VT1: c_int = 0x10000; pub const VWERASE: usize = 10; pub const VREPRINT: usize = 11; pub const VSUSP: usize = 12; pub const VSTART: usize = 13; pub const VSTOP: usize = 14; pub const VDISCARD: usize = 16; pub const VTIME: usize = 7; pub const IXON: crate::tcflag_t = 0x00000200; pub const IXOFF: crate::tcflag_t = 0x00000400; pub const ONLCR: crate::tcflag_t = 0x2; pub const CSIZE: crate::tcflag_t = 0x00000300; pub const CS6: crate::tcflag_t = 0x00000100; pub const CS7: crate::tcflag_t = 0x00000200; pub const CS8: crate::tcflag_t = 0x00000300; pub const CSTOPB: crate::tcflag_t = 0x00000400; pub const CREAD: crate::tcflag_t = 0x00000800; pub const PARENB: crate::tcflag_t = 0x00001000; pub const PARODD: crate::tcflag_t = 0x00002000; pub const HUPCL: crate::tcflag_t = 0x00004000; pub const CLOCAL: crate::tcflag_t = 0x00008000; pub const ECHOKE: crate::tcflag_t = 0x00000001; pub const ECHOE: crate::tcflag_t = 0x00000002; pub const ECHOK: crate::tcflag_t = 0x00000004; pub const ECHONL: crate::tcflag_t = 0x00000010; pub const ECHOPRT: crate::tcflag_t = 0x00000020; pub const ECHOCTL: crate::tcflag_t = 0x00000040; pub const ISIG: crate::tcflag_t = 0x00000080; pub const ICANON: crate::tcflag_t = 0x00000100; pub const PENDIN: crate::tcflag_t = 0x20000000; pub const NOFLSH: crate::tcflag_t = 0x80000000; pub const CIBAUD: crate::tcflag_t = 0o77600000; pub const CBAUDEX: crate::tcflag_t = 0o0000020; pub const VSWTC: usize = 9; pub const OLCUC: crate::tcflag_t = 0o000004; pub const NLDLY: crate::tcflag_t = 0o0001400; pub const CRDLY: crate::tcflag_t = 0o0030000; pub const TABDLY: crate::tcflag_t = 0o0006000; pub const BSDLY: crate::tcflag_t = 0o0100000; pub const FFDLY: crate::tcflag_t = 0o0040000; pub const VTDLY: crate::tcflag_t = 0o0200000; pub const XTABS: crate::tcflag_t = 0o00006000; pub const B57600: crate::speed_t = 0o00020; pub const B115200: crate::speed_t = 0o00021; pub const B230400: crate::speed_t = 0o00022; pub const B460800: crate::speed_t = 0o00023; pub const B500000: crate::speed_t = 0o00024; pub const B576000: crate::speed_t = 0o00025; pub const B921600: crate::speed_t = 0o00026; pub const B1000000: crate::speed_t = 0o00027; pub const B1152000: crate::speed_t = 0o00030; pub const B1500000: crate::speed_t = 0o00031; pub const B2000000: crate::speed_t = 0o00032; pub const B2500000: crate::speed_t = 0o00033; pub const B3000000: crate::speed_t = 0o00034; pub const B3500000: crate::speed_t = 0o00035; pub const B4000000: crate::speed_t = 0o00036; libc/src/unix/linux_like/linux/musl/b64/mips64.rs0000644000175000017500000006361315105742312021443 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = i32; pub type __u64 = c_ulong; pub type __s64 = c_long; pub type nlink_t = u64; pub type blksize_t = i64; s! { pub struct stat { pub st_dev: crate::dev_t, __pad1: [c_int; 3], pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: [c_uint; 2], pub st_size: off_t, __pad3: c_int, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, __pad4: c_uint, pub st_blocks: crate::blkcnt_t, __pad5: [c_int; 14], } pub struct stat64 { pub st_dev: crate::dev_t, __pad1: [c_int; 3], pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: [c_uint; 2], pub st_size: off_t, __pad3: c_int, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, __pad4: c_uint, pub st_blocks: crate::blkcnt_t, __pad5: [c_int; 14], } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __pad1: c_int, __unused1: c_ulong, __unused2: c_ulong, } } pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const SYS_read: c_long = 5000 + 0; pub const SYS_write: c_long = 5000 + 1; pub const SYS_open: c_long = 5000 + 2; pub const SYS_close: c_long = 5000 + 3; pub const SYS_stat: c_long = 5000 + 4; pub const SYS_fstat: c_long = 5000 + 5; pub const SYS_lstat: c_long = 5000 + 6; pub const SYS_poll: c_long = 5000 + 7; pub const SYS_lseek: c_long = 5000 + 8; pub const SYS_mmap: c_long = 5000 + 9; pub const SYS_mprotect: c_long = 5000 + 10; pub const SYS_munmap: c_long = 5000 + 11; pub const SYS_brk: c_long = 5000 + 12; pub const SYS_rt_sigaction: c_long = 5000 + 13; pub const SYS_rt_sigprocmask: c_long = 5000 + 14; pub const SYS_ioctl: c_long = 5000 + 15; pub const SYS_pread64: c_long = 5000 + 16; pub const SYS_pwrite64: c_long = 5000 + 17; pub const SYS_readv: c_long = 5000 + 18; pub const SYS_writev: c_long = 5000 + 19; pub const SYS_access: c_long = 5000 + 20; pub const SYS_pipe: c_long = 5000 + 21; pub const SYS__newselect: c_long = 5000 + 22; pub const SYS_sched_yield: c_long = 5000 + 23; pub const SYS_mremap: c_long = 5000 + 24; pub const SYS_msync: c_long = 5000 + 25; pub const SYS_mincore: c_long = 5000 + 26; pub const SYS_madvise: c_long = 5000 + 27; pub const SYS_shmget: c_long = 5000 + 28; pub const SYS_shmat: c_long = 5000 + 29; pub const SYS_shmctl: c_long = 5000 + 30; pub const SYS_dup: c_long = 5000 + 31; pub const SYS_dup2: c_long = 5000 + 32; pub const SYS_pause: c_long = 5000 + 33; pub const SYS_nanosleep: c_long = 5000 + 34; pub const SYS_getitimer: c_long = 5000 + 35; pub const SYS_setitimer: c_long = 5000 + 36; pub const SYS_alarm: c_long = 5000 + 37; pub const SYS_getpid: c_long = 5000 + 38; pub const SYS_sendfile: c_long = 5000 + 39; pub const SYS_socket: c_long = 5000 + 40; pub const SYS_connect: c_long = 5000 + 41; pub const SYS_accept: c_long = 5000 + 42; pub const SYS_sendto: c_long = 5000 + 43; pub const SYS_recvfrom: c_long = 5000 + 44; pub const SYS_sendmsg: c_long = 5000 + 45; pub const SYS_recvmsg: c_long = 5000 + 46; pub const SYS_shutdown: c_long = 5000 + 47; pub const SYS_bind: c_long = 5000 + 48; pub const SYS_listen: c_long = 5000 + 49; pub const SYS_getsockname: c_long = 5000 + 50; pub const SYS_getpeername: c_long = 5000 + 51; pub const SYS_socketpair: c_long = 5000 + 52; pub const SYS_setsockopt: c_long = 5000 + 53; pub const SYS_getsockopt: c_long = 5000 + 54; pub const SYS_clone: c_long = 5000 + 55; pub const SYS_fork: c_long = 5000 + 56; pub const SYS_execve: c_long = 5000 + 57; pub const SYS_exit: c_long = 5000 + 58; pub const SYS_wait4: c_long = 5000 + 59; pub const SYS_kill: c_long = 5000 + 60; pub const SYS_uname: c_long = 5000 + 61; pub const SYS_semget: c_long = 5000 + 62; pub const SYS_semop: c_long = 5000 + 63; pub const SYS_semctl: c_long = 5000 + 64; pub const SYS_shmdt: c_long = 5000 + 65; pub const SYS_msgget: c_long = 5000 + 66; pub const SYS_msgsnd: c_long = 5000 + 67; pub const SYS_msgrcv: c_long = 5000 + 68; pub const SYS_msgctl: c_long = 5000 + 69; pub const SYS_fcntl: c_long = 5000 + 70; pub const SYS_flock: c_long = 5000 + 71; pub const SYS_fsync: c_long = 5000 + 72; pub const SYS_fdatasync: c_long = 5000 + 73; pub const SYS_truncate: c_long = 5000 + 74; pub const SYS_ftruncate: c_long = 5000 + 75; pub const SYS_getdents: c_long = 5000 + 76; pub const SYS_getcwd: c_long = 5000 + 77; pub const SYS_chdir: c_long = 5000 + 78; pub const SYS_fchdir: c_long = 5000 + 79; pub const SYS_rename: c_long = 5000 + 80; pub const SYS_mkdir: c_long = 5000 + 81; pub const SYS_rmdir: c_long = 5000 + 82; pub const SYS_creat: c_long = 5000 + 83; pub const SYS_link: c_long = 5000 + 84; pub const SYS_unlink: c_long = 5000 + 85; pub const SYS_symlink: c_long = 5000 + 86; pub const SYS_readlink: c_long = 5000 + 87; pub const SYS_chmod: c_long = 5000 + 88; pub const SYS_fchmod: c_long = 5000 + 89; pub const SYS_chown: c_long = 5000 + 90; pub const SYS_fchown: c_long = 5000 + 91; pub const SYS_lchown: c_long = 5000 + 92; pub const SYS_umask: c_long = 5000 + 93; pub const SYS_gettimeofday: c_long = 5000 + 94; pub const SYS_getrlimit: c_long = 5000 + 95; pub const SYS_getrusage: c_long = 5000 + 96; pub const SYS_sysinfo: c_long = 5000 + 97; pub const SYS_times: c_long = 5000 + 98; pub const SYS_ptrace: c_long = 5000 + 99; pub const SYS_getuid: c_long = 5000 + 100; pub const SYS_syslog: c_long = 5000 + 101; pub const SYS_getgid: c_long = 5000 + 102; pub const SYS_setuid: c_long = 5000 + 103; pub const SYS_setgid: c_long = 5000 + 104; pub const SYS_geteuid: c_long = 5000 + 105; pub const SYS_getegid: c_long = 5000 + 106; pub const SYS_setpgid: c_long = 5000 + 107; pub const SYS_getppid: c_long = 5000 + 108; pub const SYS_getpgrp: c_long = 5000 + 109; pub const SYS_setsid: c_long = 5000 + 110; pub const SYS_setreuid: c_long = 5000 + 111; pub const SYS_setregid: c_long = 5000 + 112; pub const SYS_getgroups: c_long = 5000 + 113; pub const SYS_setgroups: c_long = 5000 + 114; pub const SYS_setresuid: c_long = 5000 + 115; pub const SYS_getresuid: c_long = 5000 + 116; pub const SYS_setresgid: c_long = 5000 + 117; pub const SYS_getresgid: c_long = 5000 + 118; pub const SYS_getpgid: c_long = 5000 + 119; pub const SYS_setfsuid: c_long = 5000 + 120; pub const SYS_setfsgid: c_long = 5000 + 121; pub const SYS_getsid: c_long = 5000 + 122; pub const SYS_capget: c_long = 5000 + 123; pub const SYS_capset: c_long = 5000 + 124; pub const SYS_rt_sigpending: c_long = 5000 + 125; pub const SYS_rt_sigtimedwait: c_long = 5000 + 126; pub const SYS_rt_sigqueueinfo: c_long = 5000 + 127; pub const SYS_rt_sigsuspend: c_long = 5000 + 128; pub const SYS_sigaltstack: c_long = 5000 + 129; pub const SYS_utime: c_long = 5000 + 130; pub const SYS_mknod: c_long = 5000 + 131; pub const SYS_personality: c_long = 5000 + 132; pub const SYS_ustat: c_long = 5000 + 133; pub const SYS_statfs: c_long = 5000 + 134; pub const SYS_fstatfs: c_long = 5000 + 135; pub const SYS_sysfs: c_long = 5000 + 136; pub const SYS_getpriority: c_long = 5000 + 137; pub const SYS_setpriority: c_long = 5000 + 138; pub const SYS_sched_setparam: c_long = 5000 + 139; pub const SYS_sched_getparam: c_long = 5000 + 140; pub const SYS_sched_setscheduler: c_long = 5000 + 141; pub const SYS_sched_getscheduler: c_long = 5000 + 142; pub const SYS_sched_get_priority_max: c_long = 5000 + 143; pub const SYS_sched_get_priority_min: c_long = 5000 + 144; pub const SYS_sched_rr_get_interval: c_long = 5000 + 145; pub const SYS_mlock: c_long = 5000 + 146; pub const SYS_munlock: c_long = 5000 + 147; pub const SYS_mlockall: c_long = 5000 + 148; pub const SYS_munlockall: c_long = 5000 + 149; pub const SYS_vhangup: c_long = 5000 + 150; pub const SYS_pivot_root: c_long = 5000 + 151; pub const SYS__sysctl: c_long = 5000 + 152; pub const SYS_prctl: c_long = 5000 + 153; pub const SYS_adjtimex: c_long = 5000 + 154; pub const SYS_setrlimit: c_long = 5000 + 155; pub const SYS_chroot: c_long = 5000 + 156; pub const SYS_sync: c_long = 5000 + 157; pub const SYS_acct: c_long = 5000 + 158; pub const SYS_settimeofday: c_long = 5000 + 159; pub const SYS_mount: c_long = 5000 + 160; pub const SYS_umount2: c_long = 5000 + 161; pub const SYS_swapon: c_long = 5000 + 162; pub const SYS_swapoff: c_long = 5000 + 163; pub const SYS_reboot: c_long = 5000 + 164; pub const SYS_sethostname: c_long = 5000 + 165; pub const SYS_setdomainname: c_long = 5000 + 166; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 5000 + 167; pub const SYS_init_module: c_long = 5000 + 168; pub const SYS_delete_module: c_long = 5000 + 169; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 5000 + 170; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 5000 + 171; pub const SYS_quotactl: c_long = 5000 + 172; pub const SYS_nfsservctl: c_long = 5000 + 173; pub const SYS_getpmsg: c_long = 5000 + 174; pub const SYS_putpmsg: c_long = 5000 + 175; pub const SYS_afs_syscall: c_long = 5000 + 176; pub const SYS_gettid: c_long = 5000 + 178; pub const SYS_readahead: c_long = 5000 + 179; pub const SYS_setxattr: c_long = 5000 + 180; pub const SYS_lsetxattr: c_long = 5000 + 181; pub const SYS_fsetxattr: c_long = 5000 + 182; pub const SYS_getxattr: c_long = 5000 + 183; pub const SYS_lgetxattr: c_long = 5000 + 184; pub const SYS_fgetxattr: c_long = 5000 + 185; pub const SYS_listxattr: c_long = 5000 + 186; pub const SYS_llistxattr: c_long = 5000 + 187; pub const SYS_flistxattr: c_long = 5000 + 188; pub const SYS_removexattr: c_long = 5000 + 189; pub const SYS_lremovexattr: c_long = 5000 + 190; pub const SYS_fremovexattr: c_long = 5000 + 191; pub const SYS_tkill: c_long = 5000 + 192; pub const SYS_futex: c_long = 5000 + 194; pub const SYS_sched_setaffinity: c_long = 5000 + 195; pub const SYS_sched_getaffinity: c_long = 5000 + 196; pub const SYS_cacheflush: c_long = 5000 + 197; pub const SYS_cachectl: c_long = 5000 + 198; pub const SYS_sysmips: c_long = 5000 + 199; pub const SYS_io_setup: c_long = 5000 + 200; pub const SYS_io_destroy: c_long = 5000 + 201; pub const SYS_io_getevents: c_long = 5000 + 202; pub const SYS_io_submit: c_long = 5000 + 203; pub const SYS_io_cancel: c_long = 5000 + 204; pub const SYS_exit_group: c_long = 5000 + 205; pub const SYS_lookup_dcookie: c_long = 5000 + 206; pub const SYS_epoll_create: c_long = 5000 + 207; pub const SYS_epoll_ctl: c_long = 5000 + 208; pub const SYS_epoll_wait: c_long = 5000 + 209; pub const SYS_remap_file_pages: c_long = 5000 + 210; pub const SYS_rt_sigreturn: c_long = 5000 + 211; pub const SYS_set_tid_address: c_long = 5000 + 212; pub const SYS_restart_syscall: c_long = 5000 + 213; pub const SYS_semtimedop: c_long = 5000 + 214; pub const SYS_fadvise64: c_long = 5000 + 215; pub const SYS_timer_create: c_long = 5000 + 216; pub const SYS_timer_settime: c_long = 5000 + 217; pub const SYS_timer_gettime: c_long = 5000 + 218; pub const SYS_timer_getoverrun: c_long = 5000 + 219; pub const SYS_timer_delete: c_long = 5000 + 220; pub const SYS_clock_settime: c_long = 5000 + 221; pub const SYS_clock_gettime: c_long = 5000 + 222; pub const SYS_clock_getres: c_long = 5000 + 223; pub const SYS_clock_nanosleep: c_long = 5000 + 224; pub const SYS_tgkill: c_long = 5000 + 225; pub const SYS_utimes: c_long = 5000 + 226; pub const SYS_mbind: c_long = 5000 + 227; pub const SYS_get_mempolicy: c_long = 5000 + 228; pub const SYS_set_mempolicy: c_long = 5000 + 229; pub const SYS_mq_open: c_long = 5000 + 230; pub const SYS_mq_unlink: c_long = 5000 + 231; pub const SYS_mq_timedsend: c_long = 5000 + 232; pub const SYS_mq_timedreceive: c_long = 5000 + 233; pub const SYS_mq_notify: c_long = 5000 + 234; pub const SYS_mq_getsetattr: c_long = 5000 + 235; pub const SYS_vserver: c_long = 5000 + 236; pub const SYS_waitid: c_long = 5000 + 237; /* pub const SYS_sys_setaltroot: c_long = 5000 + 238; */ pub const SYS_add_key: c_long = 5000 + 239; pub const SYS_request_key: c_long = 5000 + 240; pub const SYS_keyctl: c_long = 5000 + 241; pub const SYS_set_thread_area: c_long = 5000 + 242; pub const SYS_inotify_init: c_long = 5000 + 243; pub const SYS_inotify_add_watch: c_long = 5000 + 244; pub const SYS_inotify_rm_watch: c_long = 5000 + 245; pub const SYS_migrate_pages: c_long = 5000 + 246; pub const SYS_openat: c_long = 5000 + 247; pub const SYS_mkdirat: c_long = 5000 + 248; pub const SYS_mknodat: c_long = 5000 + 249; pub const SYS_fchownat: c_long = 5000 + 250; pub const SYS_futimesat: c_long = 5000 + 251; pub const SYS_newfstatat: c_long = 5000 + 252; pub const SYS_unlinkat: c_long = 5000 + 253; pub const SYS_renameat: c_long = 5000 + 254; pub const SYS_linkat: c_long = 5000 + 255; pub const SYS_symlinkat: c_long = 5000 + 256; pub const SYS_readlinkat: c_long = 5000 + 257; pub const SYS_fchmodat: c_long = 5000 + 258; pub const SYS_faccessat: c_long = 5000 + 259; pub const SYS_pselect6: c_long = 5000 + 260; pub const SYS_ppoll: c_long = 5000 + 261; pub const SYS_unshare: c_long = 5000 + 262; pub const SYS_splice: c_long = 5000 + 263; pub const SYS_sync_file_range: c_long = 5000 + 264; pub const SYS_tee: c_long = 5000 + 265; pub const SYS_vmsplice: c_long = 5000 + 266; pub const SYS_move_pages: c_long = 5000 + 267; pub const SYS_set_robust_list: c_long = 5000 + 268; pub const SYS_get_robust_list: c_long = 5000 + 269; pub const SYS_kexec_load: c_long = 5000 + 270; pub const SYS_getcpu: c_long = 5000 + 271; pub const SYS_epoll_pwait: c_long = 5000 + 272; pub const SYS_ioprio_set: c_long = 5000 + 273; pub const SYS_ioprio_get: c_long = 5000 + 274; pub const SYS_utimensat: c_long = 5000 + 275; pub const SYS_signalfd: c_long = 5000 + 276; pub const SYS_timerfd: c_long = 5000 + 277; pub const SYS_eventfd: c_long = 5000 + 278; pub const SYS_fallocate: c_long = 5000 + 279; pub const SYS_timerfd_create: c_long = 5000 + 280; pub const SYS_timerfd_gettime: c_long = 5000 + 281; pub const SYS_timerfd_settime: c_long = 5000 + 282; pub const SYS_signalfd4: c_long = 5000 + 283; pub const SYS_eventfd2: c_long = 5000 + 284; pub const SYS_epoll_create1: c_long = 5000 + 285; pub const SYS_dup3: c_long = 5000 + 286; pub const SYS_pipe2: c_long = 5000 + 287; pub const SYS_inotify_init1: c_long = 5000 + 288; pub const SYS_preadv: c_long = 5000 + 289; pub const SYS_pwritev: c_long = 5000 + 290; pub const SYS_rt_tgsigqueueinfo: c_long = 5000 + 291; pub const SYS_perf_event_open: c_long = 5000 + 292; pub const SYS_accept4: c_long = 5000 + 293; pub const SYS_recvmmsg: c_long = 5000 + 294; pub const SYS_fanotify_init: c_long = 5000 + 295; pub const SYS_fanotify_mark: c_long = 5000 + 296; pub const SYS_prlimit64: c_long = 5000 + 297; pub const SYS_name_to_handle_at: c_long = 5000 + 298; pub const SYS_open_by_handle_at: c_long = 5000 + 299; pub const SYS_clock_adjtime: c_long = 5000 + 300; pub const SYS_syncfs: c_long = 5000 + 301; pub const SYS_sendmmsg: c_long = 5000 + 302; pub const SYS_setns: c_long = 5000 + 303; pub const SYS_process_vm_readv: c_long = 5000 + 304; pub const SYS_process_vm_writev: c_long = 5000 + 305; pub const SYS_kcmp: c_long = 5000 + 306; pub const SYS_finit_module: c_long = 5000 + 307; pub const SYS_getdents64: c_long = 5000 + 308; pub const SYS_sched_setattr: c_long = 5000 + 309; pub const SYS_sched_getattr: c_long = 5000 + 310; pub const SYS_renameat2: c_long = 5000 + 311; pub const SYS_seccomp: c_long = 5000 + 312; pub const SYS_getrandom: c_long = 5000 + 313; pub const SYS_memfd_create: c_long = 5000 + 314; pub const SYS_bpf: c_long = 5000 + 315; pub const SYS_execveat: c_long = 5000 + 316; pub const SYS_userfaultfd: c_long = 5000 + 317; pub const SYS_membarrier: c_long = 5000 + 318; pub const SYS_mlock2: c_long = 5000 + 319; pub const SYS_copy_file_range: c_long = 5000 + 320; pub const SYS_preadv2: c_long = 5000 + 321; pub const SYS_pwritev2: c_long = 5000 + 322; pub const SYS_pkey_mprotect: c_long = 5000 + 323; pub const SYS_pkey_alloc: c_long = 5000 + 324; pub const SYS_pkey_free: c_long = 5000 + 325; pub const SYS_statx: c_long = 5000 + 326; pub const SYS_pidfd_send_signal: c_long = 5000 + 424; pub const SYS_io_uring_setup: c_long = 5000 + 425; pub const SYS_io_uring_enter: c_long = 5000 + 426; pub const SYS_io_uring_register: c_long = 5000 + 427; pub const SYS_open_tree: c_long = 5000 + 428; pub const SYS_move_mount: c_long = 5000 + 429; pub const SYS_fsopen: c_long = 5000 + 430; pub const SYS_fsconfig: c_long = 5000 + 431; pub const SYS_fsmount: c_long = 5000 + 432; pub const SYS_fspick: c_long = 5000 + 433; pub const SYS_pidfd_open: c_long = 5000 + 434; pub const SYS_clone3: c_long = 5000 + 435; pub const SYS_close_range: c_long = 5000 + 436; pub const SYS_openat2: c_long = 5000 + 437; pub const SYS_pidfd_getfd: c_long = 5000 + 438; pub const SYS_faccessat2: c_long = 5000 + 439; pub const SYS_process_madvise: c_long = 5000 + 440; pub const SYS_epoll_pwait2: c_long = 5000 + 441; pub const SYS_mount_setattr: c_long = 5000 + 442; pub const SYS_quotactl_fd: c_long = 5000 + 443; pub const SYS_landlock_create_ruleset: c_long = 5000 + 444; pub const SYS_landlock_add_rule: c_long = 5000 + 445; pub const SYS_landlock_restrict_self: c_long = 5000 + 446; pub const SYS_memfd_secret: c_long = 5000 + 447; pub const SYS_process_mrelease: c_long = 5000 + 448; pub const SYS_futex_waitv: c_long = 5000 + 449; pub const SYS_set_mempolicy_home_node: c_long = 5000 + 450; pub const O_DIRECT: c_int = 0x8000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_APPEND: c_int = 8; pub const O_CREAT: c_int = 256; pub const O_EXCL: c_int = 1024; pub const O_NOCTTY: c_int = 2048; pub const O_NONBLOCK: c_int = 128; pub const O_SYNC: c_int = 0x4010; pub const O_RSYNC: c_int = 0x4010; pub const O_DSYNC: c_int = 0x10; pub const O_ASYNC: c_int = 0x1000; pub const O_LARGEFILE: c_int = 0x2000; pub const EDEADLK: c_int = 45; pub const ENAMETOOLONG: c_int = 78; pub const ENOLCK: c_int = 46; pub const ENOSYS: c_int = 89; pub const ENOTEMPTY: c_int = 93; pub const ELOOP: c_int = 90; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EBADE: c_int = 50; pub const EBADR: c_int = 51; pub const EXFULL: c_int = 52; pub const ENOANO: c_int = 53; pub const EBADRQC: c_int = 54; pub const EBADSLT: c_int = 55; pub const EDEADLOCK: c_int = 56; pub const EMULTIHOP: c_int = 74; pub const EOVERFLOW: c_int = 79; pub const ENOTUNIQ: c_int = 80; pub const EBADFD: c_int = 81; pub const EBADMSG: c_int = 77; pub const EREMCHG: c_int = 82; pub const ELIBACC: c_int = 83; pub const ELIBBAD: c_int = 84; pub const ELIBSCN: c_int = 85; pub const ELIBMAX: c_int = 86; pub const ELIBEXEC: c_int = 87; pub const EILSEQ: c_int = 88; pub const ERESTART: c_int = 91; pub const ESTRPIPE: c_int = 92; pub const EUSERS: c_int = 94; pub const ENOTSOCK: c_int = 95; pub const EDESTADDRREQ: c_int = 96; pub const EMSGSIZE: c_int = 97; pub const EPROTOTYPE: c_int = 98; pub const ENOPROTOOPT: c_int = 99; pub const EPROTONOSUPPORT: c_int = 120; pub const ESOCKTNOSUPPORT: c_int = 121; pub const EOPNOTSUPP: c_int = 122; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 123; pub const EAFNOSUPPORT: c_int = 124; pub const EADDRINUSE: c_int = 125; pub const EADDRNOTAVAIL: c_int = 126; pub const ENETDOWN: c_int = 127; pub const ENETUNREACH: c_int = 128; pub const ENETRESET: c_int = 129; pub const ECONNABORTED: c_int = 130; pub const ECONNRESET: c_int = 131; pub const ENOBUFS: c_int = 132; pub const EISCONN: c_int = 133; pub const ENOTCONN: c_int = 134; pub const ESHUTDOWN: c_int = 143; pub const ETOOMANYREFS: c_int = 144; pub const ETIMEDOUT: c_int = 145; pub const ECONNREFUSED: c_int = 146; pub const EHOSTDOWN: c_int = 147; pub const EHOSTUNREACH: c_int = 148; pub const EALREADY: c_int = 149; pub const EINPROGRESS: c_int = 150; pub const ESTALE: c_int = 151; pub const EUCLEAN: c_int = 135; pub const ENOTNAM: c_int = 137; pub const ENAVAIL: c_int = 138; pub const EISNAM: c_int = 139; pub const EREMOTEIO: c_int = 140; pub const EDQUOT: c_int = 1133; pub const ENOMEDIUM: c_int = 159; pub const EMEDIUMTYPE: c_int = 160; pub const ECANCELED: c_int = 158; pub const ENOKEY: c_int = 161; pub const EKEYEXPIRED: c_int = 162; pub const EKEYREVOKED: c_int = 163; pub const EKEYREJECTED: c_int = 164; pub const EOWNERDEAD: c_int = 165; pub const ENOTRECOVERABLE: c_int = 166; pub const ERFKILL: c_int = 167; pub const MAP_ANON: c_int = 0x800; pub const MAP_GROWSDOWN: c_int = 0x1000; pub const MAP_DENYWRITE: c_int = 0x2000; pub const MAP_EXECUTABLE: c_int = 0x4000; pub const MAP_LOCKED: c_int = 0x8000; pub const MAP_NORESERVE: c_int = 0x400; pub const MAP_POPULATE: c_int = 0x10000; pub const MAP_NONBLOCK: c_int = 0x20000; pub const MAP_STACK: c_int = 0x40000; pub const MAP_HUGETLB: c_int = 0x080000; pub const SOCK_STREAM: c_int = 2; pub const SOCK_DGRAM: c_int = 1; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000008; pub const SA_NOCLDWAIT: c_int = 0x00010000; pub const SIGCHLD: c_int = 18; pub const SIGBUS: c_int = 10; pub const SIGTTIN: c_int = 26; pub const SIGTTOU: c_int = 27; pub const SIGXCPU: c_int = 30; pub const SIGXFSZ: c_int = 31; pub const SIGVTALRM: c_int = 28; pub const SIGPROF: c_int = 29; pub const SIGWINCH: c_int = 20; pub const SIGUSR1: c_int = 16; pub const SIGUSR2: c_int = 17; pub const SIGCONT: c_int = 25; pub const SIGSTOP: c_int = 23; pub const SIGTSTP: c_int = 24; pub const SIGURG: c_int = 21; pub const SIGIO: c_int = 22; pub const SIGSYS: c_int = 12; pub const SIGPOLL: c_int = 22; pub const SIGPWR: c_int = 19; pub const SIG_SETMASK: c_int = 3; pub const SIG_BLOCK: c_int = 0x1; pub const SIG_UNBLOCK: c_int = 0x2; pub const POLLWRNORM: c_short = 0x004; pub const POLLWRBAND: c_short = 0x100; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: crate::tcflag_t = 0x00000100; pub const TOSTOP: crate::tcflag_t = 0x00008000; pub const FLUSHO: crate::tcflag_t = 0x00002000; pub const EXTPROC: crate::tcflag_t = 0o200000; pub const F_GETLK: c_int = 14; pub const F_GETOWN: c_int = 23; pub const F_SETOWN: c_int = 24; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const EHWPOISON: c_int = 168; libc/src/unix/linux_like/linux/arch/0000775000175000017500000000000015105742312017306 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/arch/mod.rs0000644000175000017500000000105215105742312020427 0ustar bdrungbdrungcfg_if! { if #[cfg(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6" ))] { mod mips; pub use self::mips::*; } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] { mod sparc; pub use self::sparc::*; } else { mod generic; pub use self::generic::*; } } libc/src/unix/linux_like/linux/arch/powerpc/0000775000175000017500000000000015105742312020765 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/arch/powerpc/mod.rs0000644000175000017500000003244615105742312022121 0ustar bdrungbdrunguse crate::prelude::*; use crate::Ioctl; // arch/powerpc/include/uapi/asm/socket.h pub const SOL_SOCKET: c_int = 1; // Defined in unix/linux_like/mod.rs // pub const SO_DEBUG: c_int = 1; pub const SO_REUSEADDR: c_int = 2; pub const SO_TYPE: c_int = 3; pub const SO_ERROR: c_int = 4; pub const SO_DONTROUTE: c_int = 5; pub const SO_BROADCAST: c_int = 6; pub const SO_SNDBUF: c_int = 7; pub const SO_RCVBUF: c_int = 8; pub const SO_KEEPALIVE: c_int = 9; pub const SO_OOBINLINE: c_int = 10; pub const SO_NO_CHECK: c_int = 11; pub const SO_PRIORITY: c_int = 12; pub const SO_LINGER: c_int = 13; pub const SO_BSDCOMPAT: c_int = 14; pub const SO_REUSEPORT: c_int = 15; // powerpc only differs in these pub const SO_RCVLOWAT: c_int = 16; pub const SO_SNDLOWAT: c_int = 17; cfg_if! { if #[cfg(linux_time_bits64)] { pub const SO_SNDTIMEO: c_int = 67; pub const SO_RCVTIMEO: c_int = 66; } else { pub const SO_SNDTIMEO: c_int = 19; pub const SO_RCVTIMEO: c_int = 18; } } // pub const SO_RCVTIMEO_OLD: c_int = 18; // pub const SO_SNDTIMEO_OLD: c_int = 19; pub const SO_PASSCRED: c_int = 20; pub const SO_PEERCRED: c_int = 21; // end pub const SO_SECURITY_AUTHENTICATION: c_int = 22; pub const SO_SECURITY_ENCRYPTION_TRANSPORT: c_int = 23; pub const SO_SECURITY_ENCRYPTION_NETWORK: c_int = 24; pub const SO_BINDTODEVICE: c_int = 25; pub const SO_ATTACH_FILTER: c_int = 26; pub const SO_DETACH_FILTER: c_int = 27; pub const SO_GET_FILTER: c_int = SO_ATTACH_FILTER; pub const SO_PEERNAME: c_int = 28; cfg_if! { if #[cfg(linux_time_bits64)] { pub const SO_TIMESTAMP: c_int = SO_TIMESTAMP_NEW; pub const SO_TIMESTAMPNS: c_int = SO_TIMESTAMPNS_NEW; pub const SO_TIMESTAMPING: c_int = SO_TIMESTAMPING_NEW; } else { pub const SO_TIMESTAMP: c_int = SO_TIMESTAMP_OLD; pub const SO_TIMESTAMPNS: c_int = SO_TIMESTAMPNS_OLD; pub const SO_TIMESTAMPING: c_int = SO_TIMESTAMPING_OLD; } } const SO_TIMESTAMP_OLD: c_int = 29; const SO_TIMESTAMPNS_OLD: c_int = 35; const SO_TIMESTAMPING_OLD: c_int = 37; pub const SO_ACCEPTCONN: c_int = 30; pub const SO_PEERSEC: c_int = 31; pub const SO_SNDBUFFORCE: c_int = 32; pub const SO_RCVBUFFORCE: c_int = 33; pub const SO_PASSSEC: c_int = 34; pub const SO_MARK: c_int = 36; pub const SO_PROTOCOL: c_int = 38; pub const SO_DOMAIN: c_int = 39; pub const SO_RXQ_OVFL: c_int = 40; pub const SO_WIFI_STATUS: c_int = 41; pub const SCM_WIFI_STATUS: c_int = SO_WIFI_STATUS; pub const SO_PEEK_OFF: c_int = 42; pub const SO_NOFCS: c_int = 43; pub const SO_LOCK_FILTER: c_int = 44; pub const SO_SELECT_ERR_QUEUE: c_int = 45; pub const SO_BUSY_POLL: c_int = 46; pub const SO_MAX_PACING_RATE: c_int = 47; pub const SO_BPF_EXTENSIONS: c_int = 48; pub const SO_INCOMING_CPU: c_int = 49; pub const SO_ATTACH_BPF: c_int = 50; pub const SO_DETACH_BPF: c_int = SO_DETACH_FILTER; pub const SO_ATTACH_REUSEPORT_CBPF: c_int = 51; pub const SO_ATTACH_REUSEPORT_EBPF: c_int = 52; pub const SO_CNX_ADVICE: c_int = 53; pub const SCM_TIMESTAMPING_OPT_STATS: c_int = 54; pub const SO_MEMINFO: c_int = 55; pub const SO_INCOMING_NAPI_ID: c_int = 56; pub const SO_COOKIE: c_int = 57; pub const SCM_TIMESTAMPING_PKTINFO: c_int = 58; pub const SO_PEERGROUPS: c_int = 59; pub const SO_ZEROCOPY: c_int = 60; pub const SO_TXTIME: c_int = 61; pub const SCM_TXTIME: c_int = SO_TXTIME; pub const SO_BINDTOIFINDEX: c_int = 62; const SO_TIMESTAMP_NEW: c_int = 63; const SO_TIMESTAMPNS_NEW: c_int = 64; const SO_TIMESTAMPING_NEW: c_int = 65; const SO_RCVTIMEO_NEW: c_int = 66; const SO_SNDTIMEO_NEW: c_int = 67; // pub const SO_DETACH_REUSEPORT_BPF: c_int = 68; pub const SO_PREFER_BUSY_POLL: c_int = 69; pub const SO_BUSY_POLL_BUDGET: c_int = 70; pub const SO_NETNS_COOKIE: c_int = 71; pub const SO_BUF_LOCK: c_int = 72; pub const SO_RESERVE_MEM: c_int = 73; pub const SO_TXREHASH: c_int = 74; pub const SO_RCVMARK: c_int = 75; pub const SO_PASSPIDFD: c_int = 76; pub const SO_PEERPIDFD: c_int = 77; pub const SO_DEVMEM_LINEAR: c_int = 78; pub const SO_DEVMEM_DMABUF: c_int = 79; pub const SO_DEVMEM_DONTNEED: c_int = 80; pub const FICLONE: c_ulong = 0x80049409; pub const FICLONERANGE: c_ulong = 0x8020940D; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: c_int = SO_TIMESTAMPING; pub const SCM_DEVMEM_LINEAR: c_int = SO_DEVMEM_LINEAR; pub const SCM_DEVMEM_DMABUF: c_int = SO_DEVMEM_DMABUF; // Ioctl Constants cfg_if! { if #[cfg(target_env = "gnu")] { pub const TCGETS: Ioctl = 0x403c7413; pub const TCSETS: Ioctl = 0x803c7414; pub const TCSETSW: Ioctl = 0x803c7415; pub const TCSETSF: Ioctl = 0x803c7416; } else if #[cfg(target_env = "musl")] { pub const TCGETS: Ioctl = 0x402c7413; pub const TCSETS: Ioctl = 0x802c7414; pub const TCSETSW: Ioctl = 0x802c7415; pub const TCSETSF: Ioctl = 0x802c7416; } } pub const TCGETA: Ioctl = 0x40147417; pub const TCSETA: Ioctl = 0x80147418; pub const TCSETAW: Ioctl = 0x80147419; pub const TCSETAF: Ioctl = 0x8014741C; pub const TCSBRK: Ioctl = 0x2000741D; pub const TCXONC: Ioctl = 0x2000741E; pub const TCFLSH: Ioctl = 0x2000741F; pub const TIOCEXCL: Ioctl = 0x540C; pub const TIOCNXCL: Ioctl = 0x540D; pub const TIOCSCTTY: Ioctl = 0x540E; pub const TIOCGPGRP: Ioctl = 0x40047477; pub const TIOCSPGRP: Ioctl = 0x80047476; pub const TIOCOUTQ: Ioctl = 0x40047473; pub const TIOCSTI: Ioctl = 0x5412; pub const TIOCGWINSZ: Ioctl = 0x40087468; pub const TIOCSWINSZ: Ioctl = 0x80087467; pub const TIOCMGET: Ioctl = 0x5415; pub const TIOCMBIS: Ioctl = 0x5416; pub const TIOCMBIC: Ioctl = 0x5417; pub const TIOCMSET: Ioctl = 0x5418; pub const TIOCGSOFTCAR: Ioctl = 0x5419; pub const TIOCSSOFTCAR: Ioctl = 0x541A; pub const FIONREAD: Ioctl = 0x4004667F; pub const TIOCINQ: Ioctl = FIONREAD; pub const TIOCLINUX: Ioctl = 0x541C; pub const TIOCCONS: Ioctl = 0x541D; pub const TIOCGSERIAL: Ioctl = 0x541E; pub const TIOCSSERIAL: Ioctl = 0x541F; pub const TIOCPKT: Ioctl = 0x5420; pub const FIONBIO: Ioctl = 0x8004667e; pub const TIOCNOTTY: Ioctl = 0x5422; pub const TIOCSETD: Ioctl = 0x5423; pub const TIOCGETD: Ioctl = 0x5424; pub const TCSBRKP: Ioctl = 0x5425; pub const TIOCSBRK: Ioctl = 0x5427; pub const TIOCCBRK: Ioctl = 0x5428; pub const TIOCGSID: Ioctl = 0x5429; pub const TIOCGRS485: Ioctl = 0x542e; pub const TIOCSRS485: Ioctl = 0x542f; pub const TIOCGPTN: Ioctl = 0x40045430; pub const TIOCSPTLCK: Ioctl = 0x80045431; pub const TIOCGDEV: Ioctl = 0x40045432; pub const TIOCSIG: Ioctl = 0x80045436; pub const TIOCVHANGUP: Ioctl = 0x5437; pub const TIOCGPKT: Ioctl = 0x40045438; pub const TIOCGPTLCK: Ioctl = 0x40045439; pub const TIOCGEXCL: Ioctl = 0x40045440; pub const TIOCGPTPEER: Ioctl = 0x20005441; //pub const TIOCGISO7816: Ioctl = 0x40285442; //pub const TIOCSISO7816: Ioctl = 0xc0285443; pub const FIONCLEX: Ioctl = 0x20006602; pub const FIOCLEX: Ioctl = 0x20006601; pub const FIOASYNC: Ioctl = 0x8004667d; pub const TIOCSERCONFIG: Ioctl = 0x5453; pub const TIOCSERGWILD: Ioctl = 0x5454; pub const TIOCSERSWILD: Ioctl = 0x5455; pub const TIOCGLCKTRMIOS: Ioctl = 0x5456; pub const TIOCSLCKTRMIOS: Ioctl = 0x5457; pub const TIOCSERGSTRUCT: Ioctl = 0x5458; pub const TIOCSERGETLSR: Ioctl = 0x5459; pub const TIOCSERGETMULTI: Ioctl = 0x545A; pub const TIOCSERSETMULTI: Ioctl = 0x545B; pub const TIOCMIWAIT: Ioctl = 0x545C; pub const TIOCGICOUNT: Ioctl = 0x545D; pub const BLKIOMIN: Ioctl = 0x20001278; pub const BLKIOOPT: Ioctl = 0x20001279; pub const BLKSSZGET: Ioctl = 0x20001268; pub const BLKPBSZGET: Ioctl = 0x2000127B; //pub const FIOQSIZE: Ioctl = 0x40086680; // linux/if_tun.h pub const TUNSETNOCSUM: Ioctl = 0x800454c8; pub const TUNSETDEBUG: Ioctl = 0x800454c9; pub const TUNSETIFF: Ioctl = 0x800454ca; pub const TUNSETPERSIST: Ioctl = 0x800454cb; pub const TUNSETOWNER: Ioctl = 0x800454cc; pub const TUNSETLINK: Ioctl = 0x800454cd; pub const TUNSETGROUP: Ioctl = 0x800454ce; pub const TUNGETFEATURES: Ioctl = 0x400454cf; pub const TUNSETOFFLOAD: Ioctl = 0x800454d0; pub const TUNSETTXFILTER: Ioctl = 0x800454d1; pub const TUNGETIFF: Ioctl = 0x400454d2; pub const TUNGETSNDBUF: Ioctl = 0x400454d3; pub const TUNSETSNDBUF: Ioctl = 0x800454d4; pub const TUNGETVNETHDRSZ: Ioctl = 0x400454d7; pub const TUNSETVNETHDRSZ: Ioctl = 0x800454d8; pub const TUNSETQUEUE: Ioctl = 0x800454d9; pub const TUNSETIFINDEX: Ioctl = 0x800454da; pub const TUNSETVNETLE: Ioctl = 0x800454dc; pub const TUNGETVNETLE: Ioctl = 0x400454dd; /* The TUNSETVNETBE and TUNGETVNETBE ioctls are for cross-endian support on * little-endian hosts. Not all kernel configurations support them, but all * configurations that support SET also support GET. */ pub const TUNSETVNETBE: Ioctl = 0x800454de; pub const TUNGETVNETBE: Ioctl = 0x400454df; pub const TUNSETSTEERINGEBPF: Ioctl = 0x400454e0; pub const TUNSETFILTEREBPF: Ioctl = 0x400454e1; cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(target_arch = "powerpc")] { pub const FS_IOC_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC_SETVERSION: Ioctl = 0x80047602; pub const FS_IOC32_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: Ioctl = 0x80047602; pub const TUNATTACHFILTER: Ioctl = 0x800854d5; pub const TUNDETACHFILTER: Ioctl = 0x800854d6; pub const TUNGETFILTER: Ioctl = 0x400854db; } else if #[cfg(target_arch = "powerpc64")] { pub const FS_IOC_GETFLAGS: Ioctl = 0x40086601; pub const FS_IOC_SETFLAGS: Ioctl = 0x80086602; pub const FS_IOC_GETVERSION: Ioctl = 0x40087601; pub const FS_IOC_SETVERSION: Ioctl = 0x80087602; pub const FS_IOC32_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: Ioctl = 0x80047602; pub const TUNATTACHFILTER: Ioctl = 0x801054d5; pub const TUNDETACHFILTER: Ioctl = 0x801054d6; pub const TUNGETFILTER: Ioctl = 0x401054db; } } pub const TIOCM_LE: c_int = 0x001; pub const TIOCM_DTR: c_int = 0x002; pub const TIOCM_RTS: c_int = 0x004; pub const TIOCM_ST: c_int = 0x008; pub const TIOCM_SR: c_int = 0x010; pub const TIOCM_CTS: c_int = 0x020; pub const TIOCM_CAR: c_int = 0x040; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RNG: c_int = 0x080; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const TIOCM_DSR: c_int = 0x100; pub const BOTHER: crate::speed_t = 0o0037; pub const IBSHIFT: crate::tcflag_t = 16; // RLIMIT Constants cfg_if! { if #[cfg(target_env = "gnu")] { pub const RLIMIT_CPU: crate::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: crate::__rlimit_resource_t = 1; pub const RLIMIT_DATA: crate::__rlimit_resource_t = 2; pub const RLIMIT_STACK: crate::__rlimit_resource_t = 3; pub const RLIMIT_CORE: crate::__rlimit_resource_t = 4; pub const RLIMIT_RSS: crate::__rlimit_resource_t = 5; pub const RLIMIT_NPROC: crate::__rlimit_resource_t = 6; pub const RLIMIT_NOFILE: crate::__rlimit_resource_t = 7; pub const RLIMIT_MEMLOCK: crate::__rlimit_resource_t = 8; pub const RLIMIT_AS: crate::__rlimit_resource_t = 9; pub const RLIMIT_LOCKS: crate::__rlimit_resource_t = 10; pub const RLIMIT_SIGPENDING: crate::__rlimit_resource_t = 11; pub const RLIMIT_MSGQUEUE: crate::__rlimit_resource_t = 12; pub const RLIMIT_NICE: crate::__rlimit_resource_t = 13; pub const RLIMIT_RTPRIO: crate::__rlimit_resource_t = 14; pub const RLIMIT_RTTIME: crate::__rlimit_resource_t = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: crate::__rlimit_resource_t = 16; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: crate::__rlimit_resource_t = RLIM_NLIMITS; } else if #[cfg(target_env = "musl")] { pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_RSS: c_int = 5; pub const RLIMIT_NPROC: c_int = 6; pub const RLIMIT_NOFILE: c_int = 7; pub const RLIMIT_MEMLOCK: c_int = 8; pub const RLIMIT_AS: c_int = 9; pub const RLIMIT_LOCKS: c_int = 10; pub const RLIMIT_SIGPENDING: c_int = 11; pub const RLIMIT_MSGQUEUE: c_int = 12; pub const RLIMIT_NICE: c_int = 13; pub const RLIMIT_RTPRIO: c_int = 14; pub const RLIMIT_RTTIME: c_int = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: c_int = RLIM_NLIMITS; } } pub const RLIM_INFINITY: crate::rlim_t = !0; libc/src/unix/linux_like/linux/arch/sparc/0000775000175000017500000000000015105742312020416 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/arch/sparc/mod.rs0000644000175000017500000003056115105742312021546 0ustar bdrungbdrunguse crate::prelude::*; use crate::Ioctl; s! { pub struct termios2 { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; 19], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } } // arch/sparc/include/uapi/asm/socket.h pub const SOL_SOCKET: c_int = 0xffff; // Defined in unix/linux_like/mod.rs // pub const SO_DEBUG: c_int = 0x0001; pub const SO_PASSCRED: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_PEERCRED: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_BSDCOMPAT: c_int = 0x0400; pub const SO_RCVLOWAT: c_int = 0x0800; pub const SO_SNDLOWAT: c_int = 0x1000; pub const SO_RCVTIMEO: c_int = 0x2000; pub const SO_SNDTIMEO: c_int = 0x4000; // pub const SO_RCVTIMEO_OLD: c_int = 0x2000; // pub const SO_SNDTIMEO_OLD: c_int = 0x4000; pub const SO_ACCEPTCONN: c_int = 0x8000; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDBUFFORCE: c_int = 0x100a; pub const SO_RCVBUFFORCE: c_int = 0x100b; pub const SO_ERROR: c_int = 0x1007; pub const SO_TYPE: c_int = 0x1008; pub const SO_PROTOCOL: c_int = 0x1028; pub const SO_DOMAIN: c_int = 0x1029; pub const SO_NO_CHECK: c_int = 0x000b; pub const SO_PRIORITY: c_int = 0x000c; pub const SO_BINDTODEVICE: c_int = 0x000d; pub const SO_ATTACH_FILTER: c_int = 0x001a; pub const SO_DETACH_FILTER: c_int = 0x001b; pub const SO_GET_FILTER: c_int = SO_ATTACH_FILTER; pub const SO_PEERNAME: c_int = 0x001c; pub const SO_PEERSEC: c_int = 0x001e; pub const SO_PASSSEC: c_int = 0x001f; pub const SO_MARK: c_int = 0x0022; pub const SO_RXQ_OVFL: c_int = 0x0024; pub const SO_WIFI_STATUS: c_int = 0x0025; pub const SCM_WIFI_STATUS: c_int = SO_WIFI_STATUS; pub const SO_PEEK_OFF: c_int = 0x0026; pub const SO_NOFCS: c_int = 0x0027; pub const SO_LOCK_FILTER: c_int = 0x0028; pub const SO_SELECT_ERR_QUEUE: c_int = 0x0029; pub const SO_BUSY_POLL: c_int = 0x0030; pub const SO_MAX_PACING_RATE: c_int = 0x0031; pub const SO_BPF_EXTENSIONS: c_int = 0x0032; pub const SO_INCOMING_CPU: c_int = 0x0033; pub const SO_ATTACH_BPF: c_int = 0x0034; pub const SO_DETACH_BPF: c_int = SO_DETACH_FILTER; pub const SO_ATTACH_REUSEPORT_CBPF: c_int = 0x0035; pub const SO_ATTACH_REUSEPORT_EBPF: c_int = 0x0036; pub const SO_CNX_ADVICE: c_int = 0x0037; pub const SCM_TIMESTAMPING_OPT_STATS: c_int = 0x0038; pub const SO_MEMINFO: c_int = 0x0039; pub const SO_INCOMING_NAPI_ID: c_int = 0x003a; pub const SO_COOKIE: c_int = 0x003b; pub const SCM_TIMESTAMPING_PKTINFO: c_int = 0x003c; pub const SO_PEERGROUPS: c_int = 0x003d; pub const SO_ZEROCOPY: c_int = 0x003e; pub const SO_TXTIME: c_int = 0x003f; pub const SCM_TXTIME: c_int = SO_TXTIME; pub const SO_BINDTOIFINDEX: c_int = 0x0041; pub const SO_SECURITY_AUTHENTICATION: c_int = 0x5001; pub const SO_SECURITY_ENCRYPTION_TRANSPORT: c_int = 0x5002; pub const SO_SECURITY_ENCRYPTION_NETWORK: c_int = 0x5004; pub const SO_TIMESTAMP: c_int = 0x001d; pub const SO_TIMESTAMPNS: c_int = 0x0021; pub const SO_TIMESTAMPING: c_int = 0x0023; // pub const SO_TIMESTAMP_OLD: c_int = 0x001d; // pub const SO_TIMESTAMPNS_OLD: c_int = 0x0021; // pub const SO_TIMESTAMPING_OLD: c_int = 0x0023; // pub const SO_TIMESTAMP_NEW: c_int = 0x0046; // pub const SO_TIMESTAMPNS_NEW: c_int = 0x0042; // pub const SO_TIMESTAMPING_NEW: c_int = 0x0043; // pub const SO_RCVTIMEO_NEW: c_int = 0x0044; // pub const SO_SNDTIMEO_NEW: c_int = 0x0045; // pub const SO_DETACH_REUSEPORT_BPF: c_int = 0x0047; pub const SO_PREFER_BUSY_POLL: c_int = 0x0048; pub const SO_BUSY_POLL_BUDGET: c_int = 0x0049; pub const SO_NETNS_COOKIE: c_int = 0x0050; pub const SO_BUF_LOCK: c_int = 0x0051; pub const SO_RESERVE_MEM: c_int = 0x0052; pub const SO_TXREHASH: c_int = 0x0053; pub const SO_RCVMARK: c_int = 0x0054; pub const SO_PASSPIDFD: c_int = 0x0055; pub const SO_PEERPIDFD: c_int = 0x0056; pub const SO_DEVMEM_LINEAR: c_int = 0x0057; pub const SO_DEVMEM_DMABUF: c_int = 0x0058; pub const SO_DEVMEM_DONTNEED: c_int = 0x0059; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: c_int = SO_TIMESTAMPING; pub const SCM_DEVMEM_LINEAR: c_int = SO_DEVMEM_LINEAR; pub const SCM_DEVMEM_DMABUF: c_int = SO_DEVMEM_DMABUF; // Ioctl Constants pub const TCGETS: Ioctl = 0x40245408; pub const TCSETS: Ioctl = 0x80245409; pub const TCSETSW: Ioctl = 0x8024540a; pub const TCSETSF: Ioctl = 0x8024540b; pub const TCGETA: Ioctl = 0x40125401; pub const TCSETA: Ioctl = 0x80125402; pub const TCSETAW: Ioctl = 0x80125403; pub const TCSETAF: Ioctl = 0x80125404; pub const TCSBRK: Ioctl = 0x20005405; pub const TCXONC: Ioctl = 0x20005406; pub const TCFLSH: Ioctl = 0x20005407; pub const TIOCEXCL: Ioctl = 0x2000740d; pub const TIOCNXCL: Ioctl = 0x2000740e; pub const TIOCSCTTY: Ioctl = 0x20007484; pub const TIOCGPGRP: Ioctl = 0x40047483; pub const TIOCSPGRP: Ioctl = 0x80047482; pub const TIOCOUTQ: Ioctl = 0x40047473; pub const TIOCSTI: Ioctl = 0x80017472; pub const TIOCGWINSZ: Ioctl = 0x40087468; pub const TIOCSWINSZ: Ioctl = 0x80087467; pub const TIOCMGET: Ioctl = 0x4004746a; pub const TIOCMBIS: Ioctl = 0x8004746c; pub const TIOCMBIC: Ioctl = 0x8004746b; pub const TIOCMSET: Ioctl = 0x8004746d; pub const TIOCGSOFTCAR: Ioctl = 0x40047464; pub const TIOCSSOFTCAR: Ioctl = 0x80047465; pub const FIONREAD: Ioctl = 0x4004667f; pub const TIOCINQ: Ioctl = FIONREAD; pub const TIOCLINUX: Ioctl = 0x541C; pub const TIOCCONS: Ioctl = 0x20007424; pub const TIOCGSERIAL: Ioctl = 0x541E; pub const TIOCSSERIAL: Ioctl = 0x541F; pub const TIOCPKT: Ioctl = 0x80047470; pub const FIONBIO: Ioctl = 0x8004667e; pub const TIOCNOTTY: Ioctl = 0x20007471; pub const TIOCSETD: Ioctl = 0x80047401; pub const TIOCGETD: Ioctl = 0x40047400; pub const TCSBRKP: Ioctl = 0x5425; pub const TIOCSBRK: Ioctl = 0x2000747b; pub const TIOCCBRK: Ioctl = 0x2000747a; pub const TIOCGSID: Ioctl = 0x40047485; pub const TCGETS2: Ioctl = 0x402c540c; pub const TCSETS2: Ioctl = 0x802c540d; pub const TCSETSW2: Ioctl = 0x802c540e; pub const TCSETSF2: Ioctl = 0x802c540f; pub const TIOCGPTN: Ioctl = 0x40047486; pub const TIOCSPTLCK: Ioctl = 0x80047487; pub const TIOCGDEV: Ioctl = 0x40045432; pub const TIOCSIG: Ioctl = 0x80047488; pub const TIOCVHANGUP: Ioctl = 0x20005437; pub const TIOCGPKT: Ioctl = 0x40045438; pub const TIOCGPTLCK: Ioctl = 0x40045439; pub const TIOCGEXCL: Ioctl = 0x40045440; pub const TIOCGPTPEER: Ioctl = 0x20007489; pub const FIONCLEX: Ioctl = 0x20006602; pub const FIOCLEX: Ioctl = 0x20006601; pub const TIOCSERCONFIG: Ioctl = 0x5453; pub const TIOCSERGWILD: Ioctl = 0x5454; pub const TIOCSERSWILD: Ioctl = 0x5455; pub const TIOCGLCKTRMIOS: Ioctl = 0x5456; pub const TIOCSLCKTRMIOS: Ioctl = 0x5457; pub const TIOCSERGSTRUCT: Ioctl = 0x5458; pub const TIOCSERGETLSR: Ioctl = 0x5459; pub const TIOCSERGETMULTI: Ioctl = 0x545A; pub const TIOCSERSETMULTI: Ioctl = 0x545B; pub const TIOCMIWAIT: Ioctl = 0x545C; pub const TIOCGICOUNT: Ioctl = 0x545D; pub const TIOCSTART: Ioctl = 0x2000746e; pub const TIOCSTOP: Ioctl = 0x2000746f; pub const BLKIOMIN: Ioctl = 0x20001278; pub const BLKIOOPT: Ioctl = 0x20001279; pub const BLKSSZGET: Ioctl = 0x20001268; pub const BLKPBSZGET: Ioctl = 0x2000127B; //pub const FIOASYNC: Ioctl = 0x4004667d; //pub const FIOQSIZE: Ioctl = ; //pub const TIOCGISO7816: Ioctl = 0x40285443; //pub const TIOCSISO7816: Ioctl = 0xc0285444; //pub const TIOCGRS485: Ioctl = 0x40205441; //pub const TIOCSRS485: Ioctl = 0xc0205442; // linux/if_tun.h pub const TUNSETNOCSUM: Ioctl = 0x800454c8; pub const TUNSETDEBUG: Ioctl = 0x800454c9; pub const TUNSETIFF: Ioctl = 0x800454ca; pub const TUNSETPERSIST: Ioctl = 0x800454cb; pub const TUNSETOWNER: Ioctl = 0x800454cc; pub const TUNSETLINK: Ioctl = 0x800454cd; pub const TUNSETGROUP: Ioctl = 0x800454ce; pub const TUNGETFEATURES: Ioctl = 0x400454cf; pub const TUNSETOFFLOAD: Ioctl = 0x800454d0; pub const TUNSETTXFILTER: Ioctl = 0x800454d1; pub const TUNGETIFF: Ioctl = 0x400454d2; pub const TUNGETSNDBUF: Ioctl = 0x400454d3; pub const TUNSETSNDBUF: Ioctl = 0x800454d4; pub const TUNGETVNETHDRSZ: Ioctl = 0x400454d7; pub const TUNSETVNETHDRSZ: Ioctl = 0x800454d8; pub const TUNSETQUEUE: Ioctl = 0x800454d9; pub const TUNSETIFINDEX: Ioctl = 0x800454da; pub const TUNSETVNETLE: Ioctl = 0x800454dc; pub const TUNGETVNETLE: Ioctl = 0x400454dd; /* The TUNSETVNETBE and TUNGETVNETBE ioctls are for cross-endian support on * little-endian hosts. Not all kernel configurations support them, but all * configurations that support SET also support GET. */ pub const TUNSETVNETBE: Ioctl = 0x800454de; pub const TUNGETVNETBE: Ioctl = 0x400454df; pub const TUNSETSTEERINGEBPF: Ioctl = 0x400454e0; pub const TUNSETFILTEREBPF: Ioctl = 0x400454e1; pub const TIOCM_LE: c_int = 0x001; pub const TIOCM_DTR: c_int = 0x002; pub const TIOCM_RTS: c_int = 0x004; pub const TIOCM_ST: c_int = 0x008; pub const TIOCM_SR: c_int = 0x010; pub const TIOCM_CTS: c_int = 0x020; pub const TIOCM_CAR: c_int = 0x040; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RNG: c_int = 0x080; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const TIOCM_DSR: c_int = 0x100; pub const BOTHER: crate::speed_t = 0x1000; pub const IBSHIFT: crate::tcflag_t = 16; // RLIMIT Constants pub const RLIMIT_CPU: crate::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: crate::__rlimit_resource_t = 1; pub const RLIMIT_DATA: crate::__rlimit_resource_t = 2; pub const RLIMIT_STACK: crate::__rlimit_resource_t = 3; pub const RLIMIT_CORE: crate::__rlimit_resource_t = 4; pub const RLIMIT_RSS: crate::__rlimit_resource_t = 5; pub const RLIMIT_NOFILE: crate::__rlimit_resource_t = 6; pub const RLIMIT_NPROC: crate::__rlimit_resource_t = 7; pub const RLIMIT_MEMLOCK: crate::__rlimit_resource_t = 8; pub const RLIMIT_AS: crate::__rlimit_resource_t = 9; pub const RLIMIT_LOCKS: crate::__rlimit_resource_t = 10; pub const RLIMIT_SIGPENDING: crate::__rlimit_resource_t = 11; pub const RLIMIT_MSGQUEUE: crate::__rlimit_resource_t = 12; pub const RLIMIT_NICE: crate::__rlimit_resource_t = 13; pub const RLIMIT_RTPRIO: crate::__rlimit_resource_t = 14; pub const RLIMIT_RTTIME: crate::__rlimit_resource_t = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: crate::__rlimit_resource_t = 16; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: crate::__rlimit_resource_t = RLIM_NLIMITS; cfg_if! { if #[cfg(target_arch = "sparc64")] { pub const RLIM_INFINITY: crate::rlim_t = !0; } else if #[cfg(target_arch = "sparc")] { pub const RLIM_INFINITY: crate::rlim_t = 0x7fffffff; } } cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(target_arch = "sparc")] { pub const FS_IOC_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC_SETVERSION: Ioctl = 0x80047602; pub const FS_IOC32_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: Ioctl = 0x80047602; pub const TUNATTACHFILTER: Ioctl = 0x800854d5; pub const TUNDETACHFILTER: Ioctl = 0x800854d6; pub const TUNGETFILTER: Ioctl = 0x400854db; } else if #[cfg(target_arch = "sparc64")] { pub const FS_IOC_GETFLAGS: Ioctl = 0x40086601; pub const FS_IOC_SETFLAGS: Ioctl = 0x80086602; pub const FS_IOC_GETVERSION: Ioctl = 0x40087601; pub const FS_IOC_SETVERSION: Ioctl = 0x80087602; pub const FS_IOC32_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: Ioctl = 0x80047602; pub const TUNATTACHFILTER: Ioctl = 0x801054d5; pub const TUNDETACHFILTER: Ioctl = 0x801054d6; pub const TUNGETFILTER: Ioctl = 0x401054db; } } libc/src/unix/linux_like/linux/arch/mips/0000775000175000017500000000000015105742312020256 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/arch/mips/mod.rs0000644000175000017500000003631015105742312021404 0ustar bdrungbdrunguse crate::prelude::*; use crate::Ioctl; s! { pub struct termios2 { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; 23], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } } // arch/mips/include/uapi/asm/socket.h pub const SOL_SOCKET: c_int = 0xffff; // Defined in unix/linux_like/mod.rs // pub const SO_DEBUG: c_int = 0x0001; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_TYPE: c_int = 0x1008; // pub const SO_STYLE: c_int = SO_TYPE; pub const SO_ERROR: c_int = 0x1007; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVLOWAT: c_int = 0x1004; // NOTE: These definitions are now being renamed with _OLD postfix, // but CI haven't support them yet. // Some related consts could be found in b32.rs and b64.rs const SO_SNDTIMEO_OLD: c_int = 0x1005; const SO_RCVTIMEO_OLD: c_int = 0x1006; cfg_if! { if #[cfg(linux_time_bits64)] { pub const SO_SNDTIMEO: c_int = SO_SNDTIMEO_NEW; pub const SO_RCVTIMEO: c_int = SO_RCVTIMEO_NEW; } else { pub const SO_SNDTIMEO: c_int = SO_SNDTIMEO_OLD; pub const SO_RCVTIMEO: c_int = SO_RCVTIMEO_OLD; } } pub const SO_ACCEPTCONN: c_int = 0x1009; pub const SO_PROTOCOL: c_int = 0x1028; pub const SO_DOMAIN: c_int = 0x1029; pub const SO_NO_CHECK: c_int = 11; pub const SO_PRIORITY: c_int = 12; pub const SO_BSDCOMPAT: c_int = 14; pub const SO_PASSCRED: c_int = 17; pub const SO_PEERCRED: c_int = 18; pub const SO_SECURITY_AUTHENTICATION: c_int = 22; pub const SO_SECURITY_ENCRYPTION_TRANSPORT: c_int = 23; pub const SO_SECURITY_ENCRYPTION_NETWORK: c_int = 24; pub const SO_BINDTODEVICE: c_int = 25; pub const SO_ATTACH_FILTER: c_int = 26; pub const SO_DETACH_FILTER: c_int = 27; pub const SO_GET_FILTER: c_int = SO_ATTACH_FILTER; pub const SO_PEERNAME: c_int = 28; pub const SO_PEERSEC: c_int = 30; pub const SO_SNDBUFFORCE: c_int = 31; pub const SO_RCVBUFFORCE: c_int = 33; pub const SO_PASSSEC: c_int = 34; pub const SO_MARK: c_int = 36; pub const SO_RXQ_OVFL: c_int = 40; pub const SO_WIFI_STATUS: c_int = 41; pub const SCM_WIFI_STATUS: c_int = SO_WIFI_STATUS; pub const SO_PEEK_OFF: c_int = 42; pub const SO_NOFCS: c_int = 43; pub const SO_LOCK_FILTER: c_int = 44; pub const SO_SELECT_ERR_QUEUE: c_int = 45; pub const SO_BUSY_POLL: c_int = 46; pub const SO_MAX_PACING_RATE: c_int = 47; pub const SO_BPF_EXTENSIONS: c_int = 48; pub const SO_INCOMING_CPU: c_int = 49; pub const SO_ATTACH_BPF: c_int = 50; pub const SO_DETACH_BPF: c_int = SO_DETACH_FILTER; pub const SO_ATTACH_REUSEPORT_CBPF: c_int = 51; pub const SO_ATTACH_REUSEPORT_EBPF: c_int = 52; pub const SO_CNX_ADVICE: c_int = 53; pub const SCM_TIMESTAMPING_OPT_STATS: c_int = 54; pub const SO_MEMINFO: c_int = 55; pub const SO_INCOMING_NAPI_ID: c_int = 56; pub const SO_COOKIE: c_int = 57; pub const SCM_TIMESTAMPING_PKTINFO: c_int = 58; pub const SO_PEERGROUPS: c_int = 59; pub const SO_ZEROCOPY: c_int = 60; pub const SO_TXTIME: c_int = 61; pub const SCM_TXTIME: c_int = SO_TXTIME; pub const SO_BINDTOIFINDEX: c_int = 62; // NOTE: These definitions are now being renamed with _OLD postfix, // but CI haven't support them yet. // Some related consts could be found in b32.rs and b64.rs const SO_TIMESTAMP_OLD: c_int = 29; const SO_RCVTIMEO_NEW: c_int = 66; const SO_SNDTIMEO_NEW: c_int = 67; const SO_TIMESTAMPNS_OLD: c_int = 35; const SO_TIMESTAMPING_OLD: c_int = 37; const SO_TIMESTAMP_NEW: c_int = 63; const SO_TIMESTAMPNS_NEW: c_int = 64; const SO_TIMESTAMPING_NEW: c_int = 65; cfg_if! { if #[cfg(linux_time_bits64)] { pub const SO_TIMESTAMP: c_int = SO_TIMESTAMP_NEW; pub const SO_TIMESTAMPNS: c_int = SO_TIMESTAMPNS_NEW; pub const SO_TIMESTAMPING: c_int = SO_TIMESTAMPING_NEW; } else { pub const SO_TIMESTAMP: c_int = SO_TIMESTAMP_OLD; pub const SO_TIMESTAMPNS: c_int = SO_TIMESTAMPNS_OLD; pub const SO_TIMESTAMPING: c_int = SO_TIMESTAMPING_OLD; } } // pub const SO_DETACH_REUSEPORT_BPF: c_int = 68; pub const SO_PREFER_BUSY_POLL: c_int = 69; pub const SO_BUSY_POLL_BUDGET: c_int = 70; pub const SO_NETNS_COOKIE: c_int = 71; pub const SO_BUF_LOCK: c_int = 72; pub const SO_RESERVE_MEM: c_int = 73; pub const SO_TXREHASH: c_int = 74; pub const SO_RCVMARK: c_int = 75; pub const SO_PASSPIDFD: c_int = 76; pub const SO_PEERPIDFD: c_int = 77; pub const SO_DEVMEM_LINEAR: c_int = 78; pub const SO_DEVMEM_DMABUF: c_int = 79; pub const SO_DEVMEM_DONTNEED: c_int = 80; pub const FICLONE: c_ulong = 0x80049409; pub const FICLONERANGE: c_ulong = 0x8020940D; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: c_int = SO_TIMESTAMPING; pub const SCM_DEVMEM_LINEAR: c_int = SO_DEVMEM_LINEAR; pub const SCM_DEVMEM_DMABUF: c_int = SO_DEVMEM_DMABUF; // Ioctl Constants pub const TCGETS: Ioctl = 0x540d; pub const TCSETS: Ioctl = 0x540e; pub const TCSETSW: Ioctl = 0x540f; pub const TCSETSF: Ioctl = 0x5410; pub const TCGETA: Ioctl = 0x5401; pub const TCSETA: Ioctl = 0x5402; pub const TCSETAW: Ioctl = 0x5403; pub const TCSETAF: Ioctl = 0x5404; pub const TCSBRK: Ioctl = 0x5405; pub const TCXONC: Ioctl = 0x5406; pub const TCFLSH: Ioctl = 0x5407; pub const TIOCEXCL: Ioctl = 0x740d; pub const TIOCNXCL: Ioctl = 0x740e; pub const TIOCSCTTY: Ioctl = 0x5480; pub const TIOCGPGRP: Ioctl = 0x40047477; pub const TIOCSPGRP: Ioctl = 0x80047476; pub const TIOCOUTQ: Ioctl = 0x7472; pub const TIOCSTI: Ioctl = 0x5472; pub const TIOCGWINSZ: Ioctl = 0x40087468; pub const TIOCSWINSZ: Ioctl = 0x80087467; pub const TIOCMGET: Ioctl = 0x741d; pub const TIOCMBIS: Ioctl = 0x741b; pub const TIOCMBIC: Ioctl = 0x741c; pub const TIOCMSET: Ioctl = 0x741a; pub const TIOCGSOFTCAR: Ioctl = 0x5481; pub const TIOCSSOFTCAR: Ioctl = 0x5482; pub const FIONREAD: Ioctl = 0x467f; pub const TIOCINQ: Ioctl = FIONREAD; pub const TIOCLINUX: Ioctl = 0x5483; pub const TIOCCONS: Ioctl = 0x80047478; pub const TIOCGSERIAL: Ioctl = 0x5484; pub const TIOCSSERIAL: Ioctl = 0x5485; pub const TIOCPKT: Ioctl = 0x5470; pub const FIONBIO: Ioctl = 0x667e; pub const TIOCNOTTY: Ioctl = 0x5471; pub const TIOCSETD: Ioctl = 0x7401; pub const TIOCGETD: Ioctl = 0x7400; pub const TCSBRKP: Ioctl = 0x5486; pub const TIOCSBRK: Ioctl = 0x5427; pub const TIOCCBRK: Ioctl = 0x5428; pub const TIOCGSID: Ioctl = 0x7416; pub const TCGETS2: Ioctl = 0x4030542a; pub const TCSETS2: Ioctl = 0x8030542b; pub const TCSETSW2: Ioctl = 0x8030542c; pub const TCSETSF2: Ioctl = 0x8030542d; pub const TIOCGPTN: Ioctl = 0x40045430; pub const TIOCSPTLCK: Ioctl = 0x80045431; pub const TIOCGDEV: Ioctl = 0x40045432; pub const TIOCSIG: Ioctl = 0x80045436; pub const TIOCVHANGUP: Ioctl = 0x5437; pub const TIOCGPKT: Ioctl = 0x40045438; pub const TIOCGPTLCK: Ioctl = 0x40045439; pub const TIOCGEXCL: Ioctl = 0x40045440; pub const TIOCGPTPEER: Ioctl = 0x20005441; //pub const TIOCGISO7816: Ioctl = 0x40285442; //pub const TIOCSISO7816: Ioctl = 0xc0285443; pub const FIONCLEX: Ioctl = 0x6602; pub const FIOCLEX: Ioctl = 0x6601; pub const FIOASYNC: Ioctl = 0x667d; pub const TIOCSERCONFIG: Ioctl = 0x5488; pub const TIOCSERGWILD: Ioctl = 0x5489; pub const TIOCSERSWILD: Ioctl = 0x548a; pub const TIOCGLCKTRMIOS: Ioctl = 0x548b; pub const TIOCSLCKTRMIOS: Ioctl = 0x548c; pub const TIOCSERGSTRUCT: Ioctl = 0x548d; pub const TIOCSERGETLSR: Ioctl = 0x548e; pub const TIOCSERGETMULTI: Ioctl = 0x548f; pub const TIOCSERSETMULTI: Ioctl = 0x5490; pub const TIOCMIWAIT: Ioctl = 0x5491; pub const TIOCGICOUNT: Ioctl = 0x5492; pub const FIOQSIZE: Ioctl = 0x667f; pub const TIOCSLTC: Ioctl = 0x7475; pub const TIOCGETP: Ioctl = 0x7408; pub const TIOCSETP: Ioctl = 0x7409; pub const TIOCSETN: Ioctl = 0x740a; pub const BLKIOMIN: Ioctl = 0x20001278; pub const BLKIOOPT: Ioctl = 0x20001279; pub const BLKSSZGET: Ioctl = 0x20001268; pub const BLKPBSZGET: Ioctl = 0x2000127B; // linux/if_tun.h pub const TUNSETNOCSUM: Ioctl = 0x800454c8; pub const TUNSETDEBUG: Ioctl = 0x800454c9; pub const TUNSETIFF: Ioctl = 0x800454ca; pub const TUNSETPERSIST: Ioctl = 0x800454cb; pub const TUNSETOWNER: Ioctl = 0x800454cc; pub const TUNSETLINK: Ioctl = 0x800454cd; pub const TUNSETGROUP: Ioctl = 0x800454ce; pub const TUNGETFEATURES: Ioctl = 0x400454cf; pub const TUNSETOFFLOAD: Ioctl = 0x800454d0; pub const TUNSETTXFILTER: Ioctl = 0x800454d1; pub const TUNGETIFF: Ioctl = 0x400454d2; pub const TUNGETSNDBUF: Ioctl = 0x400454d3; pub const TUNSETSNDBUF: Ioctl = 0x800454d4; pub const TUNGETVNETHDRSZ: Ioctl = 0x400454d7; pub const TUNSETVNETHDRSZ: Ioctl = 0x800454d8; pub const TUNSETQUEUE: Ioctl = 0x800454d9; pub const TUNSETIFINDEX: Ioctl = 0x800454da; pub const TUNSETVNETLE: Ioctl = 0x800454dc; pub const TUNGETVNETLE: Ioctl = 0x400454dd; /* The TUNSETVNETBE and TUNGETVNETBE ioctls are for cross-endian support on * little-endian hosts. Not all kernel configurations support them, but all * configurations that support SET also support GET. */ pub const TUNSETVNETBE: Ioctl = 0x800454de; pub const TUNGETVNETBE: Ioctl = 0x400454df; pub const TUNSETSTEERINGEBPF: Ioctl = 0x400454e0; pub const TUNSETFILTEREBPF: Ioctl = 0x400454e1; cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] { pub const FS_IOC_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC_SETVERSION: Ioctl = 0x80047602; pub const FS_IOC32_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: Ioctl = 0x80047602; pub const TUNATTACHFILTER: Ioctl = 0x800854d5; pub const TUNDETACHFILTER: Ioctl = 0x800854d6; pub const TUNGETFILTER: Ioctl = 0x400854db; } else if #[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))] { pub const FS_IOC_GETFLAGS: Ioctl = 0x40086601; pub const FS_IOC_SETFLAGS: Ioctl = 0x80086602; pub const FS_IOC_GETVERSION: Ioctl = 0x40087601; pub const FS_IOC_SETVERSION: Ioctl = 0x80087602; pub const FS_IOC32_GETFLAGS: Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: Ioctl = 0x80047602; pub const TUNATTACHFILTER: Ioctl = 0x801054d5; pub const TUNDETACHFILTER: Ioctl = 0x801054d6; pub const TUNGETFILTER: Ioctl = 0x401054db; } } cfg_if! { if #[cfg(target_env = "musl")] { pub const TIOCGRS485: Ioctl = 0x4020542e; pub const TIOCSRS485: Ioctl = 0xc020542f; } } pub const TIOCM_LE: c_int = 0x001; pub const TIOCM_DTR: c_int = 0x002; pub const TIOCM_RTS: c_int = 0x004; pub const TIOCM_ST: c_int = 0x010; pub const TIOCM_SR: c_int = 0x020; pub const TIOCM_CTS: c_int = 0x040; pub const TIOCM_CAR: c_int = 0x100; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RNG: c_int = 0x200; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const TIOCM_DSR: c_int = 0x400; pub const BOTHER: crate::speed_t = 0o010000; pub const IBSHIFT: crate::tcflag_t = 16; // RLIMIT Constants cfg_if! { if #[cfg(any(target_env = "gnu", target_env = "uclibc"))] { pub const RLIMIT_CPU: crate::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: crate::__rlimit_resource_t = 1; pub const RLIMIT_DATA: crate::__rlimit_resource_t = 2; pub const RLIMIT_STACK: crate::__rlimit_resource_t = 3; pub const RLIMIT_CORE: crate::__rlimit_resource_t = 4; pub const RLIMIT_NOFILE: crate::__rlimit_resource_t = 5; pub const RLIMIT_AS: crate::__rlimit_resource_t = 6; pub const RLIMIT_RSS: crate::__rlimit_resource_t = 7; pub const RLIMIT_NPROC: crate::__rlimit_resource_t = 8; pub const RLIMIT_MEMLOCK: crate::__rlimit_resource_t = 9; pub const RLIMIT_LOCKS: crate::__rlimit_resource_t = 10; pub const RLIMIT_SIGPENDING: crate::__rlimit_resource_t = 11; pub const RLIMIT_MSGQUEUE: crate::__rlimit_resource_t = 12; pub const RLIMIT_NICE: crate::__rlimit_resource_t = 13; pub const RLIMIT_RTPRIO: crate::__rlimit_resource_t = 14; pub const RLIMIT_RTTIME: crate::__rlimit_resource_t = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: crate::__rlimit_resource_t = RLIM_NLIMITS; } else if #[cfg(target_env = "musl")] { pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_NOFILE: c_int = 5; pub const RLIMIT_AS: c_int = 6; pub const RLIMIT_RSS: c_int = 7; pub const RLIMIT_NPROC: c_int = 8; pub const RLIMIT_MEMLOCK: c_int = 9; pub const RLIMIT_LOCKS: c_int = 10; pub const RLIMIT_SIGPENDING: c_int = 11; pub const RLIMIT_MSGQUEUE: c_int = 12; pub const RLIMIT_NICE: c_int = 13; pub const RLIMIT_RTPRIO: c_int = 14; pub const RLIMIT_RTTIME: c_int = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: c_int = RLIM_NLIMITS; pub const RLIM_INFINITY: crate::rlim_t = !0; } } cfg_if! { if #[cfg(target_env = "gnu")] { #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: crate::__rlimit_resource_t = 16; } else if #[cfg(target_env = "uclibc")] { #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: crate::__rlimit_resource_t = 15; } } cfg_if! { if #[cfg( any(target_arch = "mips64", target_arch = "mips64r6"), any(target_env = "gnu", target_env = "uclibc") )] { pub const RLIM_INFINITY: crate::rlim_t = !0; } } cfg_if! { if #[cfg(all( any(target_arch = "mips", target_arch = "mips32r6"), any( all(target_env = "uclibc", linux_time_bits64), all( target_env = "gnu", any(linux_time_bits64, gnu_file_offset_bits64) ) ) ))] { pub const RLIM_INFINITY: crate::rlim_t = !0; } else if #[cfg(all( any(target_arch = "mips", target_arch = "mips32r6"), any(target_env = "uclibc", target_env = "gnu"), not(linux_time_bits64) ))] { pub const RLIM_INFINITY: crate::rlim_t = 0x7fffffff; } } libc/src/unix/linux_like/linux/arch/generic/0000775000175000017500000000000015105742312020722 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/arch/generic/mod.rs0000644000175000017500000003524615105742312022057 0ustar bdrungbdrunguse crate::prelude::*; use crate::{Ioctl, _IOR, _IOW}; s! { pub struct termios2 { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; 19], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } } // include/uapi/asm-generic/socket.h // arch/alpha/include/uapi/asm/socket.h // tools/include/uapi/asm-generic/socket.h // arch/mips/include/uapi/asm/socket.h pub const SOL_SOCKET: c_int = 1; // Defined in unix/linux_like/mod.rs // pub const SO_DEBUG: c_int = 1; pub const SO_REUSEADDR: c_int = 2; pub const SO_TYPE: c_int = 3; pub const SO_ERROR: c_int = 4; pub const SO_DONTROUTE: c_int = 5; pub const SO_BROADCAST: c_int = 6; pub const SO_SNDBUF: c_int = 7; pub const SO_RCVBUF: c_int = 8; pub const SO_KEEPALIVE: c_int = 9; pub const SO_OOBINLINE: c_int = 10; pub const SO_NO_CHECK: c_int = 11; pub const SO_PRIORITY: c_int = 12; pub const SO_LINGER: c_int = 13; pub const SO_BSDCOMPAT: c_int = 14; pub const SO_REUSEPORT: c_int = 15; pub const SO_PASSCRED: c_int = 16; pub const SO_PEERCRED: c_int = 17; pub const SO_RCVLOWAT: c_int = 18; pub const SO_SNDLOWAT: c_int = 19; const SO_RCVTIMEO_OLD: c_int = 20; const SO_SNDTIMEO_OLD: c_int = 21; pub const SO_SECURITY_AUTHENTICATION: c_int = 22; pub const SO_SECURITY_ENCRYPTION_TRANSPORT: c_int = 23; pub const SO_SECURITY_ENCRYPTION_NETWORK: c_int = 24; pub const SO_BINDTODEVICE: c_int = 25; pub const SO_ATTACH_FILTER: c_int = 26; pub const SO_DETACH_FILTER: c_int = 27; pub const SO_GET_FILTER: c_int = SO_ATTACH_FILTER; pub const SO_PEERNAME: c_int = 28; const SO_TIMESTAMP_OLD: c_int = 29; const SO_TIMESTAMPNS_OLD: c_int = 35; const SO_TIMESTAMPING_OLD: c_int = 37; cfg_if! { if #[cfg(all( linux_time_bits64, any(target_arch = "arm", target_arch = "x86"), not(any(target_env = "musl", target_env = "ohos")) ))] { pub const SO_TIMESTAMP: c_int = SO_TIMESTAMP_NEW; pub const SO_TIMESTAMPNS: c_int = SO_TIMESTAMPNS_NEW; pub const SO_TIMESTAMPING: c_int = SO_TIMESTAMPING_NEW; pub const SO_RCVTIMEO: c_int = SO_RCVTIMEO_NEW; pub const SO_SNDTIMEO: c_int = SO_SNDTIMEO_NEW; } else if #[cfg(all( linux_time_bits64, any(target_arch = "arm", target_arch = "x86"), any(target_env = "musl", target_env = "ohos") ))] { pub const SO_TIMESTAMP: c_int = 63; pub const SO_TIMESTAMPNS: c_int = 64; pub const SO_TIMESTAMPING: c_int = 65; pub const SO_RCVTIMEO: c_int = 66; pub const SO_SNDTIMEO: c_int = 67; } else { pub const SO_TIMESTAMP: c_int = SO_TIMESTAMP_OLD; pub const SO_TIMESTAMPNS: c_int = SO_TIMESTAMPNS_OLD; pub const SO_TIMESTAMPING: c_int = SO_TIMESTAMPING_OLD; pub const SO_RCVTIMEO: c_int = SO_RCVTIMEO_OLD; pub const SO_SNDTIMEO: c_int = SO_SNDTIMEO_OLD; } } pub const SO_ACCEPTCONN: c_int = 30; pub const SO_PEERSEC: c_int = 31; pub const SO_SNDBUFFORCE: c_int = 32; pub const SO_RCVBUFFORCE: c_int = 33; pub const SO_PASSSEC: c_int = 34; pub const SO_MARK: c_int = 36; pub const SO_PROTOCOL: c_int = 38; pub const SO_DOMAIN: c_int = 39; pub const SO_RXQ_OVFL: c_int = 40; pub const SO_WIFI_STATUS: c_int = 41; pub const SCM_WIFI_STATUS: c_int = SO_WIFI_STATUS; pub const SO_PEEK_OFF: c_int = 42; pub const SO_NOFCS: c_int = 43; pub const SO_LOCK_FILTER: c_int = 44; pub const SO_SELECT_ERR_QUEUE: c_int = 45; pub const SO_BUSY_POLL: c_int = 46; pub const SO_MAX_PACING_RATE: c_int = 47; pub const SO_BPF_EXTENSIONS: c_int = 48; pub const SO_INCOMING_CPU: c_int = 49; pub const SO_ATTACH_BPF: c_int = 50; pub const SO_DETACH_BPF: c_int = SO_DETACH_FILTER; pub const SO_ATTACH_REUSEPORT_CBPF: c_int = 51; pub const SO_ATTACH_REUSEPORT_EBPF: c_int = 52; pub const SO_CNX_ADVICE: c_int = 53; pub const SCM_TIMESTAMPING_OPT_STATS: c_int = 54; pub const SO_MEMINFO: c_int = 55; pub const SO_INCOMING_NAPI_ID: c_int = 56; pub const SO_COOKIE: c_int = 57; pub const SCM_TIMESTAMPING_PKTINFO: c_int = 58; pub const SO_PEERGROUPS: c_int = 59; pub const SO_ZEROCOPY: c_int = 60; pub const SO_TXTIME: c_int = 61; pub const SCM_TXTIME: c_int = SO_TXTIME; pub const SO_BINDTOIFINDEX: c_int = 62; cfg_if! { // Some of these platforms in CI already have these constants. // But they may still not have those _OLD ones. if #[cfg(all( any( target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", target_arch = "csky", target_arch = "loongarch64" ), // FIXME(musl): // Musl hardcodes the SO_* constants instead // of inheriting them from the kernel headers. // For new constants you might need consider updating // musl in the CI as well. not(any(target_env = "musl", target_env = "ohos")) ))] { pub const SO_TIMESTAMP_NEW: c_int = 63; pub const SO_TIMESTAMPNS_NEW: c_int = 64; pub const SO_TIMESTAMPING_NEW: c_int = 65; pub const SO_RCVTIMEO_NEW: c_int = 66; pub const SO_SNDTIMEO_NEW: c_int = 67; pub const SO_DETACH_REUSEPORT_BPF: c_int = 68; } } pub const SO_PREFER_BUSY_POLL: c_int = 69; pub const SO_BUSY_POLL_BUDGET: c_int = 70; pub const SO_NETNS_COOKIE: c_int = 71; pub const SO_BUF_LOCK: c_int = 72; pub const SO_RESERVE_MEM: c_int = 73; pub const SO_TXREHASH: c_int = 74; pub const SO_RCVMARK: c_int = 75; pub const SO_PASSPIDFD: c_int = 76; pub const SO_PEERPIDFD: c_int = 77; pub const SO_DEVMEM_LINEAR: c_int = 78; pub const SO_DEVMEM_DMABUF: c_int = 79; pub const SO_DEVMEM_DONTNEED: c_int = 80; pub const FICLONE: Ioctl = _IOW::(0x94, 9) as Ioctl; pub const FICLONERANGE: Ioctl = _IOW::(0x94, 13) as Ioctl; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: c_int = SO_TIMESTAMPING; pub const SCM_DEVMEM_LINEAR: c_int = SO_DEVMEM_LINEAR; pub const SCM_DEVMEM_DMABUF: c_int = SO_DEVMEM_DMABUF; // Ioctl Constants pub const TCGETS: Ioctl = 0x5401; pub const TCSETS: Ioctl = 0x5402; pub const TCSETSW: Ioctl = 0x5403; pub const TCSETSF: Ioctl = 0x5404; pub const TCGETA: Ioctl = 0x5405; pub const TCSETA: Ioctl = 0x5406; pub const TCSETAW: Ioctl = 0x5407; pub const TCSETAF: Ioctl = 0x5408; pub const TCSBRK: Ioctl = 0x5409; pub const TCXONC: Ioctl = 0x540A; pub const TCFLSH: Ioctl = 0x540B; pub const TIOCEXCL: Ioctl = 0x540C; pub const TIOCNXCL: Ioctl = 0x540D; pub const TIOCSCTTY: Ioctl = 0x540E; pub const TIOCGPGRP: Ioctl = 0x540F; pub const TIOCSPGRP: Ioctl = 0x5410; pub const TIOCOUTQ: Ioctl = 0x5411; pub const TIOCSTI: Ioctl = 0x5412; pub const TIOCGWINSZ: Ioctl = 0x5413; pub const TIOCSWINSZ: Ioctl = 0x5414; pub const TIOCMGET: Ioctl = 0x5415; pub const TIOCMBIS: Ioctl = 0x5416; pub const TIOCMBIC: Ioctl = 0x5417; pub const TIOCMSET: Ioctl = 0x5418; pub const TIOCGSOFTCAR: Ioctl = 0x5419; pub const TIOCSSOFTCAR: Ioctl = 0x541A; pub const FIONREAD: Ioctl = 0x541B; pub const TIOCINQ: Ioctl = FIONREAD; pub const TIOCLINUX: Ioctl = 0x541C; pub const TIOCCONS: Ioctl = 0x541D; pub const TIOCGSERIAL: Ioctl = 0x541E; pub const TIOCSSERIAL: Ioctl = 0x541F; pub const TIOCPKT: Ioctl = 0x5420; pub const FIONBIO: Ioctl = 0x5421; pub const TIOCNOTTY: Ioctl = 0x5422; pub const TIOCSETD: Ioctl = 0x5423; pub const TIOCGETD: Ioctl = 0x5424; pub const TCSBRKP: Ioctl = 0x5425; pub const TIOCSBRK: Ioctl = 0x5427; pub const TIOCCBRK: Ioctl = 0x5428; pub const TIOCGSID: Ioctl = 0x5429; pub const TCGETS2: Ioctl = 0x802c542a; pub const TCSETS2: Ioctl = 0x402c542b; pub const TCSETSW2: Ioctl = 0x402c542c; pub const TCSETSF2: Ioctl = 0x402c542d; pub const TIOCGRS485: Ioctl = 0x542E; pub const TIOCSRS485: Ioctl = 0x542F; pub const TIOCGPTN: Ioctl = 0x80045430; pub const TIOCSPTLCK: Ioctl = 0x40045431; pub const TIOCGDEV: Ioctl = 0x80045432; pub const TCGETX: Ioctl = 0x5432; pub const TCSETX: Ioctl = 0x5433; pub const TCSETXF: Ioctl = 0x5434; pub const TCSETXW: Ioctl = 0x5435; pub const TIOCSIG: Ioctl = 0x40045436; pub const TIOCVHANGUP: Ioctl = 0x5437; pub const TIOCGPKT: Ioctl = 0x80045438; pub const TIOCGPTLCK: Ioctl = 0x80045439; pub const TIOCGEXCL: Ioctl = 0x80045440; pub const TIOCGPTPEER: Ioctl = 0x5441; // pub const TIOCGISO7816: Ioctl = 0x80285442; // pub const TIOCSISO7816: Ioctl = 0xc0285443; pub const FIONCLEX: Ioctl = 0x5450; pub const FIOCLEX: Ioctl = 0x5451; pub const FIOASYNC: Ioctl = 0x5452; pub const TIOCSERCONFIG: Ioctl = 0x5453; pub const TIOCSERGWILD: Ioctl = 0x5454; pub const TIOCSERSWILD: Ioctl = 0x5455; pub const TIOCGLCKTRMIOS: Ioctl = 0x5456; pub const TIOCSLCKTRMIOS: Ioctl = 0x5457; pub const TIOCSERGSTRUCT: Ioctl = 0x5458; pub const TIOCSERGETLSR: Ioctl = 0x5459; pub const TIOCSERGETMULTI: Ioctl = 0x545A; pub const TIOCSERSETMULTI: Ioctl = 0x545B; pub const TIOCMIWAIT: Ioctl = 0x545C; pub const TIOCGICOUNT: Ioctl = 0x545D; pub const BLKIOMIN: Ioctl = 0x1278; pub const BLKIOOPT: Ioctl = 0x1279; pub const BLKSSZGET: Ioctl = 0x1268; pub const BLKPBSZGET: Ioctl = 0x127B; // linux/if_tun.h pub const TUNSETNOCSUM: Ioctl = 0x400454c8; pub const TUNSETDEBUG: Ioctl = 0x400454c9; pub const TUNSETIFF: Ioctl = 0x400454ca; pub const TUNSETPERSIST: Ioctl = 0x400454cb; pub const TUNSETOWNER: Ioctl = 0x400454cc; pub const TUNSETLINK: Ioctl = 0x400454cd; pub const TUNSETGROUP: Ioctl = 0x400454ce; pub const TUNGETFEATURES: Ioctl = 0x800454cf; pub const TUNSETOFFLOAD: Ioctl = 0x400454d0; pub const TUNSETTXFILTER: Ioctl = 0x400454d1; pub const TUNGETIFF: Ioctl = 0x800454d2; pub const TUNGETSNDBUF: Ioctl = 0x800454d3; pub const TUNSETSNDBUF: Ioctl = 0x400454d4; pub const TUNGETVNETHDRSZ: Ioctl = 0x800454d7; pub const TUNSETVNETHDRSZ: Ioctl = 0x400454d8; pub const TUNSETQUEUE: Ioctl = 0x400454d9; pub const TUNSETIFINDEX: Ioctl = 0x400454da; pub const TUNSETVNETLE: Ioctl = 0x400454dc; pub const TUNGETVNETLE: Ioctl = 0x800454dd; /* The TUNSETVNETBE and TUNGETVNETBE ioctls are for cross-endian support on * little-endian hosts. Not all kernel configurations support them, but all * configurations that support SET also support GET. */ pub const TUNSETVNETBE: Ioctl = 0x400454de; pub const TUNGETVNETBE: Ioctl = 0x800454df; pub const TUNSETSTEERINGEBPF: Ioctl = 0x800454e0; pub const TUNSETFILTEREBPF: Ioctl = 0x800454e1; pub const FS_IOC_GETFLAGS: Ioctl = _IOR::('f' as u32, 1) as Ioctl; pub const FS_IOC_SETFLAGS: Ioctl = _IOW::('f' as u32, 2) as Ioctl; pub const FS_IOC_GETVERSION: Ioctl = _IOR::('v' as u32, 1) as Ioctl; pub const FS_IOC_SETVERSION: Ioctl = _IOW::('v' as u32, 2) as Ioctl; pub const FS_IOC32_GETFLAGS: Ioctl = _IOR::('f' as u32, 1) as Ioctl; pub const FS_IOC32_SETFLAGS: Ioctl = _IOW::('f' as u32, 2) as Ioctl; pub const FS_IOC32_GETVERSION: Ioctl = _IOR::('v' as u32, 1) as Ioctl; pub const FS_IOC32_SETVERSION: Ioctl = _IOW::('v' as u32, 2) as Ioctl; pub const TUNATTACHFILTER: Ioctl = _IOW::('T' as u32, 213) as Ioctl; pub const TUNDETACHFILTER: Ioctl = _IOW::('T' as u32, 214) as Ioctl; pub const TUNGETFILTER: Ioctl = _IOR::('T' as u32, 219) as Ioctl; cfg_if! { if #[cfg(any(target_arch = "arm", target_arch = "s390x"))] { pub const FIOQSIZE: Ioctl = 0x545E; } else { pub const FIOQSIZE: Ioctl = 0x5460; } } pub const TIOCM_LE: c_int = 0x001; pub const TIOCM_DTR: c_int = 0x002; pub const TIOCM_RTS: c_int = 0x004; pub const TIOCM_ST: c_int = 0x008; pub const TIOCM_SR: c_int = 0x010; pub const TIOCM_CTS: c_int = 0x020; pub const TIOCM_CAR: c_int = 0x040; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RNG: c_int = 0x080; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const TIOCM_DSR: c_int = 0x100; pub const BOTHER: crate::speed_t = 0o010000; pub const IBSHIFT: crate::tcflag_t = 16; // RLIMIT Constants cfg_if! { if #[cfg(any(target_env = "gnu", target_env = "uclibc"))] { pub const RLIMIT_CPU: crate::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: crate::__rlimit_resource_t = 1; pub const RLIMIT_DATA: crate::__rlimit_resource_t = 2; pub const RLIMIT_STACK: crate::__rlimit_resource_t = 3; pub const RLIMIT_CORE: crate::__rlimit_resource_t = 4; pub const RLIMIT_RSS: crate::__rlimit_resource_t = 5; pub const RLIMIT_NPROC: crate::__rlimit_resource_t = 6; pub const RLIMIT_NOFILE: crate::__rlimit_resource_t = 7; pub const RLIMIT_MEMLOCK: crate::__rlimit_resource_t = 8; pub const RLIMIT_AS: crate::__rlimit_resource_t = 9; pub const RLIMIT_LOCKS: crate::__rlimit_resource_t = 10; pub const RLIMIT_SIGPENDING: crate::__rlimit_resource_t = 11; pub const RLIMIT_MSGQUEUE: crate::__rlimit_resource_t = 12; pub const RLIMIT_NICE: crate::__rlimit_resource_t = 13; pub const RLIMIT_RTPRIO: crate::__rlimit_resource_t = 14; pub const RLIMIT_RTTIME: crate::__rlimit_resource_t = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: crate::__rlimit_resource_t = RLIM_NLIMITS; } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_RSS: c_int = 5; pub const RLIMIT_NPROC: c_int = 6; pub const RLIMIT_NOFILE: c_int = 7; pub const RLIMIT_MEMLOCK: c_int = 8; pub const RLIMIT_AS: c_int = 9; pub const RLIMIT_LOCKS: c_int = 10; pub const RLIMIT_SIGPENDING: c_int = 11; pub const RLIMIT_MSGQUEUE: c_int = 12; pub const RLIMIT_NICE: c_int = 13; pub const RLIMIT_RTPRIO: c_int = 14; pub const RLIMIT_RTTIME: c_int = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] #[cfg(not(target_arch = "loongarch64"))] pub const RLIM_NLIMITS: c_int = 15; #[cfg(target_arch = "loongarch64")] pub const RLIM_NLIMITS: c_int = 16; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: c_int = RLIM_NLIMITS; } } cfg_if! { if #[cfg(target_env = "gnu")] { #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: crate::__rlimit_resource_t = 16; } else if #[cfg(target_env = "uclibc")] { #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: crate::__rlimit_resource_t = 15; } } pub const RLIM_INFINITY: crate::rlim_t = !0; libc/src/unix/linux_like/linux/gnu/0000775000175000017500000000000015105742312017162 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/mod.rs0000644000175000017500000014162415105742312020315 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; pub type pthread_t = c_ulong; pub type __priority_which_t = c_uint; pub type __rlimit_resource_t = c_uint; pub type Lmid_t = c_long; pub type regoff_t = c_int; pub type __kernel_rwf_t = c_int; cfg_if! { if #[cfg(doc)] { // Used in `linux::arch` to define ioctl constants. pub(crate) type Ioctl = c_ulong; } else { #[doc(hidden)] pub type Ioctl = c_ulong; } } s! { pub struct aiocb { pub aio_fildes: c_int, pub aio_lio_opcode: c_int, pub aio_reqprio: c_int, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_sigevent: crate::sigevent, __next_prio: *mut aiocb, __abs_prio: c_int, __policy: c_int, __error_code: c_int, __return_value: ssize_t, pub aio_offset: off_t, #[cfg(all( not(gnu_file_offset_bits64), not(target_arch = "x86_64"), target_pointer_width = "32" ))] __unused1: [c_char; 4], __glibc_reserved: [c_char; 32], } pub struct __exit_status { pub e_termination: c_short, pub e_exit: c_short, } pub struct __timeval { pub tv_sec: i32, pub tv_usec: i32, } pub struct glob64_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: size_t, pub msg_control: *mut c_void, pub msg_controllen: size_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: size_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], #[cfg(not(any( target_arch = "sparc", target_arch = "sparc64", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6" )))] pub c_ispeed: crate::speed_t, #[cfg(not(any( target_arch = "sparc", target_arch = "sparc64", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6" )))] pub c_ospeed: crate::speed_t, } pub struct mallinfo { pub arena: c_int, pub ordblks: c_int, pub smblks: c_int, pub hblks: c_int, pub hblkhd: c_int, pub usmblks: c_int, pub fsmblks: c_int, pub uordblks: c_int, pub fordblks: c_int, pub keepcost: c_int, } pub struct mallinfo2 { pub arena: size_t, pub ordblks: size_t, pub smblks: size_t, pub hblks: size_t, pub hblkhd: size_t, pub usmblks: size_t, pub fsmblks: size_t, pub uordblks: size_t, pub fordblks: size_t, pub keepcost: size_t, } pub struct nl_pktinfo { pub group: u32, } pub struct nl_mmap_req { pub nm_block_size: c_uint, pub nm_block_nr: c_uint, pub nm_frame_size: c_uint, pub nm_frame_nr: c_uint, } pub struct nl_mmap_hdr { pub nm_status: c_uint, pub nm_len: c_uint, pub nm_group: u32, pub nm_pid: u32, pub nm_uid: u32, pub nm_gid: u32, } pub struct rtentry { pub rt_pad1: c_ulong, pub rt_dst: crate::sockaddr, pub rt_gateway: crate::sockaddr, pub rt_genmask: crate::sockaddr, pub rt_flags: c_ushort, pub rt_pad2: c_short, pub rt_pad3: c_ulong, pub rt_tos: c_uchar, pub rt_class: c_uchar, #[cfg(target_pointer_width = "64")] pub rt_pad4: [c_short; 3usize], #[cfg(not(target_pointer_width = "64"))] pub rt_pad4: c_short, pub rt_metric: c_short, pub rt_dev: *mut c_char, pub rt_mtu: c_ulong, pub rt_window: c_ulong, pub rt_irtt: c_ushort, } pub struct timex { pub modes: c_uint, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub offset: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub offset: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub freq: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub freq: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub maxerror: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub maxerror: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub esterror: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub esterror: c_long, pub status: c_int, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub constant: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub constant: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub precision: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub precision: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub tolerance: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub tolerance: c_long, pub time: crate::timeval, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub tick: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub tick: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub ppsfreq: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub ppsfreq: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub jitter: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub jitter: c_long, pub shift: c_int, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub stabil: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub stabil: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub jitcnt: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub jitcnt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub calcnt: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub calcnt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub errcnt: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub errcnt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub stbcnt: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub stbcnt: c_long, pub tai: c_int, pub __unused1: i32, pub __unused2: i32, pub __unused3: i32, pub __unused4: i32, pub __unused5: i32, pub __unused6: i32, pub __unused7: i32, pub __unused8: i32, pub __unused9: i32, pub __unused10: i32, pub __unused11: i32, } pub struct ntptimeval { pub time: crate::timeval, pub maxerror: c_long, pub esterror: c_long, pub tai: c_long, pub __glibc_reserved1: c_long, pub __glibc_reserved2: c_long, pub __glibc_reserved3: c_long, pub __glibc_reserved4: c_long, } pub struct regex_t { __buffer: *mut c_void, __allocated: size_t, __used: size_t, __syntax: c_ulong, __fastmap: *mut c_char, __translate: *mut c_char, __re_nsub: size_t, __bitfield: u8, } pub struct Elf64_Chdr { pub ch_type: crate::Elf64_Word, pub ch_reserved: crate::Elf64_Word, pub ch_size: crate::Elf64_Xword, pub ch_addralign: crate::Elf64_Xword, } pub struct Elf32_Chdr { pub ch_type: crate::Elf32_Word, pub ch_size: crate::Elf32_Word, pub ch_addralign: crate::Elf32_Word, } pub struct seminfo { pub semmap: c_int, pub semmni: c_int, pub semmns: c_int, pub semmnu: c_int, pub semmsl: c_int, pub semopm: c_int, pub semume: c_int, pub semusz: c_int, pub semvmx: c_int, pub semaem: c_int, } pub struct ptrace_peeksiginfo_args { pub off: crate::__u64, pub flags: crate::__u32, pub nr: crate::__s32, } pub struct __c_anonymous_ptrace_syscall_info_entry { pub nr: crate::__u64, pub args: [crate::__u64; 6], } pub struct __c_anonymous_ptrace_syscall_info_exit { pub sval: crate::__s64, pub is_error: crate::__u8, } pub struct __c_anonymous_ptrace_syscall_info_seccomp { pub nr: crate::__u64, pub args: [crate::__u64; 6], pub ret_data: crate::__u32, } pub struct ptrace_syscall_info { pub op: crate::__u8, pub pad: [crate::__u8; 3], pub arch: crate::__u32, pub instruction_pointer: crate::__u64, pub stack_pointer: crate::__u64, pub u: __c_anonymous_ptrace_syscall_info_data, } pub struct ptrace_sud_config { pub mode: crate::__u64, pub selector: crate::__u64, pub offset: crate::__u64, pub len: crate::__u64, } pub struct iocb { pub aio_data: crate::__u64, #[cfg(target_endian = "little")] pub aio_key: crate::__u32, #[cfg(target_endian = "little")] pub aio_rw_flags: crate::__kernel_rwf_t, #[cfg(target_endian = "big")] pub aio_rw_flags: crate::__kernel_rwf_t, #[cfg(target_endian = "big")] pub aio_key: crate::__u32, pub aio_lio_opcode: crate::__u16, pub aio_reqprio: crate::__s16, pub aio_fildes: crate::__u32, pub aio_buf: crate::__u64, pub aio_nbytes: crate::__u64, pub aio_offset: crate::__s64, aio_reserved2: crate::__u64, pub aio_flags: crate::__u32, pub aio_resfd: crate::__u32, } // netinet/tcp.h pub struct tcp_info { pub tcpi_state: u8, pub tcpi_ca_state: u8, pub tcpi_retransmits: u8, pub tcpi_probes: u8, pub tcpi_backoff: u8, pub tcpi_options: u8, /// This contains the bitfields `tcpi_snd_wscale` and `tcpi_rcv_wscale`. /// Each is 4 bits. pub tcpi_snd_rcv_wscale: u8, pub tcpi_rto: u32, pub tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub tcpi_unacked: u32, pub tcpi_sacked: u32, pub tcpi_lost: u32, pub tcpi_retrans: u32, pub tcpi_fackets: u32, pub tcpi_last_data_sent: u32, pub tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub tcpi_last_ack_recv: u32, pub tcpi_pmtu: u32, pub tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub tcpi_advmss: u32, pub tcpi_reordering: u32, pub tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_total_retrans: u32, } pub struct fanotify_event_info_pidfd { pub hdr: crate::fanotify_event_info_header, pub pidfd: crate::__s32, } pub struct fanotify_event_info_error { pub hdr: crate::fanotify_event_info_header, pub error: crate::__s32, pub error_count: crate::__u32, } // FIXME(1.0) this is actually a union #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [c_char; 16], #[cfg(target_pointer_width = "64")] __size: [c_char; 32], } pub struct mbstate_t { __count: c_int, __wchb: [c_char; 4], } pub struct fpos64_t { __pos: off64_t, __state: crate::mbstate_t, } pub struct fpos_t { #[cfg(not(gnu_file_offset_bits64))] __pos: off_t, #[cfg(gnu_file_offset_bits64)] __pos: off64_t, __state: crate::mbstate_t, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { #[repr(C)] struct siginfo_sigfault { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, si_addr: *mut c_void, } (*(self as *const siginfo_t as *const siginfo_sigfault)).si_addr } pub unsafe fn si_value(&self) -> crate::sigval { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, _si_tid: c_int, _si_overrun: c_int, si_sigval: crate::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).si_sigval } } // Internal, for casts to access union fields #[repr(C)] struct sifields_sigchld { si_pid: crate::pid_t, si_uid: crate::uid_t, si_status: c_int, si_utime: c_long, si_stime: c_long, } impl Copy for sifields_sigchld {} impl Clone for sifields_sigchld { fn clone(&self) -> sifields_sigchld { *self } } // Internal, for casts to access union fields #[repr(C)] union sifields { _align_pointer: *mut c_void, sigchld: sifields_sigchld, } // Internal, for casts to access union fields. Note that some variants // of sifields start with a pointer, which makes the alignment of // sifields vary on 32-bit and 64-bit architectures. #[repr(C)] struct siginfo_f { _siginfo_base: [c_int; 3], sifields: sifields, } impl siginfo_t { unsafe fn sifields(&self) -> &sifields { &(*(self as *const siginfo_t as *const siginfo_f)).sifields } pub unsafe fn si_pid(&self) -> crate::pid_t { self.sifields().sigchld.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.sifields().sigchld.si_uid } pub unsafe fn si_status(&self) -> c_int { self.sifields().sigchld.si_status } pub unsafe fn si_utime(&self) -> c_long { self.sifields().sigchld.si_utime } pub unsafe fn si_stime(&self) -> c_long { self.sifields().sigchld.si_stime } } pub union __c_anonymous_ptrace_syscall_info_data { pub entry: __c_anonymous_ptrace_syscall_info_entry, pub exit: __c_anonymous_ptrace_syscall_info_exit, pub seccomp: __c_anonymous_ptrace_syscall_info_seccomp, } impl Copy for __c_anonymous_ptrace_syscall_info_data {} impl Clone for __c_anonymous_ptrace_syscall_info_data { fn clone(&self) -> __c_anonymous_ptrace_syscall_info_data { *self } } s_no_extra_traits! { pub struct utmpx { pub ut_type: c_short, pub ut_pid: crate::pid_t, pub ut_line: [c_char; __UT_LINESIZE], pub ut_id: [c_char; 4], pub ut_user: [c_char; __UT_NAMESIZE], pub ut_host: [c_char; __UT_HOSTSIZE], pub ut_exit: __exit_status, #[cfg(any( target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64", all(target_pointer_width = "32", not(target_arch = "x86_64")) ))] pub ut_session: c_long, #[cfg(any( target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64", all(target_pointer_width = "32", not(target_arch = "x86_64")) ))] pub ut_tv: crate::timeval, #[cfg(not(any( target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64", all(target_pointer_width = "32", not(target_arch = "x86_64")) )))] pub ut_session: i32, #[cfg(not(any( target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64", all(target_pointer_width = "32", not(target_arch = "x86_64")) )))] pub ut_tv: __timeval, pub ut_addr_v6: [i32; 4], __glibc_reserved: [c_char; 20], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_user == other.ut_user && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_addr_v6 == other.ut_addr_v6 && self.__glibc_reserved == other.__glibc_reserved } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_line", &self.ut_line) .field("ut_id", &self.ut_id) .field("ut_user", &self.ut_user) // FIXME(debug): .field("ut_host", &self.ut_host) .field("ut_exit", &self.ut_exit) .field("ut_session", &self.ut_session) .field("ut_tv", &self.ut_tv) .field("ut_addr_v6", &self.ut_addr_v6) .field("__glibc_reserved", &self.__glibc_reserved) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_user.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_addr_v6.hash(state); self.__glibc_reserved.hash(state); } } impl PartialEq for __c_anonymous_ptrace_syscall_info_data { fn eq(&self, other: &__c_anonymous_ptrace_syscall_info_data) -> bool { unsafe { self.entry == other.entry || self.exit == other.exit || self.seccomp == other.seccomp } } } impl Eq for __c_anonymous_ptrace_syscall_info_data {} impl fmt::Debug for __c_anonymous_ptrace_syscall_info_data { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { unsafe { f.debug_struct("__c_anonymous_ptrace_syscall_info_data") .field("entry", &self.entry) .field("exit", &self.exit) .field("seccomp", &self.seccomp) .finish() } } } impl hash::Hash for __c_anonymous_ptrace_syscall_info_data { fn hash(&self, state: &mut H) { unsafe { self.entry.hash(state); self.exit.hash(state); self.seccomp.hash(state); } } } } } // include/uapi/asm-generic/hugetlb_encode.h pub const HUGETLB_FLAG_ENCODE_SHIFT: c_int = 26; pub const HUGETLB_FLAG_ENCODE_MASK: c_int = 0x3f; pub const HUGETLB_FLAG_ENCODE_64KB: c_int = 16 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_512KB: c_int = 19 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_1MB: c_int = 20 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_2MB: c_int = 21 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_8MB: c_int = 23 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_16MB: c_int = 24 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_32MB: c_int = 25 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_256MB: c_int = 28 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_512MB: c_int = 29 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_1GB: c_int = 30 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_2GB: c_int = 31 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_16GB: c_int = 34 << HUGETLB_FLAG_ENCODE_SHIFT; // include/uapi/linux/mman.h /* * Huge page size encoding when MAP_HUGETLB is specified, and a huge page * size other than the default is desired. See hugetlb_encode.h. * All known huge page size encodings are provided here. It is the * responsibility of the application to know which sizes are supported on * the running system. See mmap(2) man page for details. */ pub const MAP_HUGE_SHIFT: c_int = HUGETLB_FLAG_ENCODE_SHIFT; pub const MAP_HUGE_MASK: c_int = HUGETLB_FLAG_ENCODE_MASK; pub const MAP_HUGE_64KB: c_int = HUGETLB_FLAG_ENCODE_64KB; pub const MAP_HUGE_512KB: c_int = HUGETLB_FLAG_ENCODE_512KB; pub const MAP_HUGE_1MB: c_int = HUGETLB_FLAG_ENCODE_1MB; pub const MAP_HUGE_2MB: c_int = HUGETLB_FLAG_ENCODE_2MB; pub const MAP_HUGE_8MB: c_int = HUGETLB_FLAG_ENCODE_8MB; pub const MAP_HUGE_16MB: c_int = HUGETLB_FLAG_ENCODE_16MB; pub const MAP_HUGE_32MB: c_int = HUGETLB_FLAG_ENCODE_32MB; pub const MAP_HUGE_256MB: c_int = HUGETLB_FLAG_ENCODE_256MB; pub const MAP_HUGE_512MB: c_int = HUGETLB_FLAG_ENCODE_512MB; pub const MAP_HUGE_1GB: c_int = HUGETLB_FLAG_ENCODE_1GB; pub const MAP_HUGE_2GB: c_int = HUGETLB_FLAG_ENCODE_2GB; pub const MAP_HUGE_16GB: c_int = HUGETLB_FLAG_ENCODE_16GB; pub const PRIO_PROCESS: crate::__priority_which_t = 0; pub const PRIO_PGRP: crate::__priority_which_t = 1; pub const PRIO_USER: crate::__priority_which_t = 2; pub const MS_RMT_MASK: c_ulong = 0x02800051; pub const __UT_LINESIZE: usize = 32; pub const __UT_NAMESIZE: usize = 32; pub const __UT_HOSTSIZE: usize = 256; pub const EMPTY: c_short = 0; pub const RUN_LVL: c_short = 1; pub const BOOT_TIME: c_short = 2; pub const NEW_TIME: c_short = 3; pub const OLD_TIME: c_short = 4; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const USER_PROCESS: c_short = 7; pub const DEAD_PROCESS: c_short = 8; pub const ACCOUNTING: c_short = 9; // dlfcn.h pub const LM_ID_BASE: c_long = 0; pub const LM_ID_NEWLM: c_long = -1; pub const RTLD_DI_LMID: c_int = 1; pub const RTLD_DI_LINKMAP: c_int = 2; pub const RTLD_DI_CONFIGADDR: c_int = 3; pub const RTLD_DI_SERINFO: c_int = 4; pub const RTLD_DI_SERINFOSIZE: c_int = 5; pub const RTLD_DI_ORIGIN: c_int = 6; pub const RTLD_DI_PROFILENAME: c_int = 7; pub const RTLD_DI_PROFILEOUT: c_int = 8; pub const RTLD_DI_TLS_MODID: c_int = 9; pub const RTLD_DI_TLS_DATA: c_int = 10; pub const SOCK_NONBLOCK: c_int = O_NONBLOCK; pub const PIDFD_NONBLOCK: c_uint = O_NONBLOCK as c_uint; pub const SOL_RXRPC: c_int = 272; pub const SOL_PPPOL2TP: c_int = 273; pub const SOL_PNPIPE: c_int = 275; pub const SOL_RDS: c_int = 276; pub const SOL_IUCV: c_int = 277; pub const SOL_CAIF: c_int = 278; pub const SOL_NFC: c_int = 280; pub const MSG_TRYHARD: c_int = 4; pub const LC_PAPER: c_int = 7; pub const LC_NAME: c_int = 8; pub const LC_ADDRESS: c_int = 9; pub const LC_TELEPHONE: c_int = 10; pub const LC_MEASUREMENT: c_int = 11; pub const LC_IDENTIFICATION: c_int = 12; pub const LC_PAPER_MASK: c_int = 1 << LC_PAPER; pub const LC_NAME_MASK: c_int = 1 << LC_NAME; pub const LC_ADDRESS_MASK: c_int = 1 << LC_ADDRESS; pub const LC_TELEPHONE_MASK: c_int = 1 << LC_TELEPHONE; pub const LC_MEASUREMENT_MASK: c_int = 1 << LC_MEASUREMENT; pub const LC_IDENTIFICATION_MASK: c_int = 1 << LC_IDENTIFICATION; pub const LC_ALL_MASK: c_int = crate::LC_CTYPE_MASK | crate::LC_NUMERIC_MASK | crate::LC_TIME_MASK | crate::LC_COLLATE_MASK | crate::LC_MONETARY_MASK | crate::LC_MESSAGES_MASK | LC_PAPER_MASK | LC_NAME_MASK | LC_ADDRESS_MASK | LC_TELEPHONE_MASK | LC_MEASUREMENT_MASK | LC_IDENTIFICATION_MASK; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const SOCK_SEQPACKET: c_int = 5; pub const SOCK_DCCP: c_int = 6; #[deprecated(since = "0.2.70", note = "AF_PACKET must be used instead")] pub const SOCK_PACKET: c_int = 10; pub const AF_IB: c_int = 27; pub const AF_MPLS: c_int = 28; pub const AF_NFC: c_int = 39; pub const AF_VSOCK: c_int = 40; pub const AF_XDP: c_int = 44; pub const PF_IB: c_int = AF_IB; pub const PF_MPLS: c_int = AF_MPLS; pub const PF_NFC: c_int = AF_NFC; pub const PF_VSOCK: c_int = AF_VSOCK; pub const PF_XDP: c_int = AF_XDP; pub const SIGEV_THREAD_ID: c_int = 4; pub const BUFSIZ: c_uint = 8192; pub const TMP_MAX: c_uint = 238328; pub const FOPEN_MAX: c_uint = 16; pub const FILENAME_MAX: c_uint = 4096; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const _CS_GNU_LIBC_VERSION: c_int = 2; pub const _CS_GNU_LIBPTHREAD_VERSION: c_int = 3; pub const _CS_V6_ENV: c_int = 1148; pub const _CS_V7_ENV: c_int = 1149; pub const _SC_EQUIV_CLASS_MAX: c_int = 41; pub const _SC_CHARCLASS_NAME_MAX: c_int = 45; pub const _SC_PII: c_int = 53; pub const _SC_PII_XTI: c_int = 54; pub const _SC_PII_SOCKET: c_int = 55; pub const _SC_PII_INTERNET: c_int = 56; pub const _SC_PII_OSI: c_int = 57; pub const _SC_POLL: c_int = 58; pub const _SC_SELECT: c_int = 59; pub const _SC_PII_INTERNET_STREAM: c_int = 61; pub const _SC_PII_INTERNET_DGRAM: c_int = 62; pub const _SC_PII_OSI_COTS: c_int = 63; pub const _SC_PII_OSI_CLTS: c_int = 64; pub const _SC_PII_OSI_M: c_int = 65; pub const _SC_T_IOV_MAX: c_int = 66; pub const _SC_2_C_VERSION: c_int = 96; pub const _SC_CHAR_BIT: c_int = 101; pub const _SC_CHAR_MAX: c_int = 102; pub const _SC_CHAR_MIN: c_int = 103; pub const _SC_INT_MAX: c_int = 104; pub const _SC_INT_MIN: c_int = 105; pub const _SC_LONG_BIT: c_int = 106; pub const _SC_WORD_BIT: c_int = 107; pub const _SC_MB_LEN_MAX: c_int = 108; pub const _SC_SSIZE_MAX: c_int = 110; pub const _SC_SCHAR_MAX: c_int = 111; pub const _SC_SCHAR_MIN: c_int = 112; pub const _SC_SHRT_MAX: c_int = 113; pub const _SC_SHRT_MIN: c_int = 114; pub const _SC_UCHAR_MAX: c_int = 115; pub const _SC_UINT_MAX: c_int = 116; pub const _SC_ULONG_MAX: c_int = 117; pub const _SC_USHRT_MAX: c_int = 118; pub const _SC_NL_ARGMAX: c_int = 119; pub const _SC_NL_LANGMAX: c_int = 120; pub const _SC_NL_MSGMAX: c_int = 121; pub const _SC_NL_NMAX: c_int = 122; pub const _SC_NL_SETMAX: c_int = 123; pub const _SC_NL_TEXTMAX: c_int = 124; pub const _SC_BASE: c_int = 134; pub const _SC_C_LANG_SUPPORT: c_int = 135; pub const _SC_C_LANG_SUPPORT_R: c_int = 136; pub const _SC_DEVICE_IO: c_int = 140; pub const _SC_DEVICE_SPECIFIC: c_int = 141; pub const _SC_DEVICE_SPECIFIC_R: c_int = 142; pub const _SC_FD_MGMT: c_int = 143; pub const _SC_FIFO: c_int = 144; pub const _SC_PIPE: c_int = 145; pub const _SC_FILE_ATTRIBUTES: c_int = 146; pub const _SC_FILE_LOCKING: c_int = 147; pub const _SC_FILE_SYSTEM: c_int = 148; pub const _SC_MULTI_PROCESS: c_int = 150; pub const _SC_SINGLE_PROCESS: c_int = 151; pub const _SC_NETWORKING: c_int = 152; pub const _SC_REGEX_VERSION: c_int = 156; pub const _SC_SIGNALS: c_int = 158; pub const _SC_SYSTEM_DATABASE: c_int = 162; pub const _SC_SYSTEM_DATABASE_R: c_int = 163; pub const _SC_USER_GROUPS: c_int = 166; pub const _SC_USER_GROUPS_R: c_int = 167; pub const _SC_LEVEL1_ICACHE_SIZE: c_int = 185; pub const _SC_LEVEL1_ICACHE_ASSOC: c_int = 186; pub const _SC_LEVEL1_ICACHE_LINESIZE: c_int = 187; pub const _SC_LEVEL1_DCACHE_SIZE: c_int = 188; pub const _SC_LEVEL1_DCACHE_ASSOC: c_int = 189; pub const _SC_LEVEL1_DCACHE_LINESIZE: c_int = 190; pub const _SC_LEVEL2_CACHE_SIZE: c_int = 191; pub const _SC_LEVEL2_CACHE_ASSOC: c_int = 192; pub const _SC_LEVEL2_CACHE_LINESIZE: c_int = 193; pub const _SC_LEVEL3_CACHE_SIZE: c_int = 194; pub const _SC_LEVEL3_CACHE_ASSOC: c_int = 195; pub const _SC_LEVEL3_CACHE_LINESIZE: c_int = 196; pub const _SC_LEVEL4_CACHE_SIZE: c_int = 197; pub const _SC_LEVEL4_CACHE_ASSOC: c_int = 198; pub const _SC_LEVEL4_CACHE_LINESIZE: c_int = 199; pub const O_ACCMODE: c_int = 3; pub const ST_RELATIME: c_ulong = 4096; pub const NI_MAXHOST: crate::socklen_t = 1025; // Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the // following are only available on newer Linux versions than the versions // currently used in CI in some configurations, so we define them here. cfg_if! { if #[cfg(not(target_arch = "s390x"))] { pub const BINDERFS_SUPER_MAGIC: c_long = 0x6c6f6f70; pub const XFS_SUPER_MAGIC: c_long = 0x58465342; } else if #[cfg(target_arch = "s390x")] { pub const BINDERFS_SUPER_MAGIC: c_uint = 0x6c6f6f70; pub const XFS_SUPER_MAGIC: c_uint = 0x58465342; } } pub const CPU_SETSIZE: c_int = 0x400; pub const PTRACE_TRACEME: c_uint = 0; pub const PTRACE_PEEKTEXT: c_uint = 1; pub const PTRACE_PEEKDATA: c_uint = 2; pub const PTRACE_PEEKUSER: c_uint = 3; pub const PTRACE_POKETEXT: c_uint = 4; pub const PTRACE_POKEDATA: c_uint = 5; pub const PTRACE_POKEUSER: c_uint = 6; pub const PTRACE_CONT: c_uint = 7; pub const PTRACE_KILL: c_uint = 8; pub const PTRACE_SINGLESTEP: c_uint = 9; pub const PTRACE_ATTACH: c_uint = 16; pub const PTRACE_SYSCALL: c_uint = 24; pub const PTRACE_SETOPTIONS: c_uint = 0x4200; pub const PTRACE_GETEVENTMSG: c_uint = 0x4201; pub const PTRACE_GETSIGINFO: c_uint = 0x4202; pub const PTRACE_SETSIGINFO: c_uint = 0x4203; pub const PTRACE_GETREGSET: c_uint = 0x4204; pub const PTRACE_SETREGSET: c_uint = 0x4205; pub const PTRACE_SEIZE: c_uint = 0x4206; pub const PTRACE_INTERRUPT: c_uint = 0x4207; pub const PTRACE_LISTEN: c_uint = 0x4208; pub const PTRACE_PEEKSIGINFO: c_uint = 0x4209; pub const PTRACE_GETSIGMASK: c_uint = 0x420a; pub const PTRACE_SETSIGMASK: c_uint = 0x420b; pub const PTRACE_GET_SYSCALL_INFO: c_uint = 0x420e; pub const PTRACE_SYSCALL_INFO_NONE: crate::__u8 = 0; pub const PTRACE_SYSCALL_INFO_ENTRY: crate::__u8 = 1; pub const PTRACE_SYSCALL_INFO_EXIT: crate::__u8 = 2; pub const PTRACE_SYSCALL_INFO_SECCOMP: crate::__u8 = 3; pub const PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG: crate::__u8 = 0x4210; pub const PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG: crate::__u8 = 0x4211; // linux/fs.h // Flags for preadv2/pwritev2 pub const RWF_HIPRI: c_int = 0x00000001; pub const RWF_DSYNC: c_int = 0x00000002; pub const RWF_SYNC: c_int = 0x00000004; pub const RWF_NOWAIT: c_int = 0x00000008; pub const RWF_APPEND: c_int = 0x00000010; // linux/rtnetlink.h pub const TCA_PAD: c_ushort = 9; pub const TCA_DUMP_INVISIBLE: c_ushort = 10; pub const TCA_CHAIN: c_ushort = 11; pub const TCA_HW_OFFLOAD: c_ushort = 12; pub const RTM_DELNETCONF: u16 = 81; pub const RTM_NEWSTATS: u16 = 92; pub const RTM_GETSTATS: u16 = 94; pub const RTM_NEWCACHEREPORT: u16 = 96; pub const RTM_F_LOOKUP_TABLE: c_uint = 0x1000; pub const RTM_F_FIB_MATCH: c_uint = 0x2000; pub const RTA_VIA: c_ushort = 18; pub const RTA_NEWDST: c_ushort = 19; pub const RTA_PREF: c_ushort = 20; pub const RTA_ENCAP_TYPE: c_ushort = 21; pub const RTA_ENCAP: c_ushort = 22; pub const RTA_EXPIRES: c_ushort = 23; pub const RTA_PAD: c_ushort = 24; pub const RTA_UID: c_ushort = 25; pub const RTA_TTL_PROPAGATE: c_ushort = 26; // linux/neighbor.h pub const NTF_EXT_LEARNED: u8 = 0x10; pub const NTF_OFFLOADED: u8 = 0x20; pub const NDA_MASTER: c_ushort = 9; pub const NDA_LINK_NETNSID: c_ushort = 10; pub const NDA_SRC_VNI: c_ushort = 11; // linux/personality.h pub const UNAME26: c_int = 0x0020000; pub const FDPIC_FUNCPTRS: c_int = 0x0080000; pub const MAX_LINKS: c_int = 32; pub const GENL_UNS_ADMIN_PERM: c_int = 0x10; pub const GENL_ID_VFS_DQUOT: c_int = crate::NLMSG_MIN_TYPE + 1; pub const GENL_ID_PMCRAID: c_int = crate::NLMSG_MIN_TYPE + 2; pub const ELFOSABI_ARM_AEABI: u8 = 64; // linux/sched.h pub const CLONE_NEWTIME: c_int = 0x80; // DIFF(main): changed to `c_ulonglong` in e9abac9ac2 pub const CLONE_CLEAR_SIGHAND: c_int = 0x100000000; pub const CLONE_INTO_CGROUP: c_int = 0x200000000; // linux/keyctl.h pub const KEYCTL_DH_COMPUTE: u32 = 23; pub const KEYCTL_PKEY_QUERY: u32 = 24; pub const KEYCTL_PKEY_ENCRYPT: u32 = 25; pub const KEYCTL_PKEY_DECRYPT: u32 = 26; pub const KEYCTL_PKEY_SIGN: u32 = 27; pub const KEYCTL_PKEY_VERIFY: u32 = 28; pub const KEYCTL_RESTRICT_KEYRING: u32 = 29; pub const KEYCTL_SUPPORTS_ENCRYPT: u32 = 0x01; pub const KEYCTL_SUPPORTS_DECRYPT: u32 = 0x02; pub const KEYCTL_SUPPORTS_SIGN: u32 = 0x04; pub const KEYCTL_SUPPORTS_VERIFY: u32 = 0x08; cfg_if! { if #[cfg(not(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6" )))] { pub const KEYCTL_MOVE: u32 = 30; pub const KEYCTL_CAPABILITIES: u32 = 31; pub const KEYCTL_CAPS0_CAPABILITIES: u32 = 0x01; pub const KEYCTL_CAPS0_PERSISTENT_KEYRINGS: u32 = 0x02; pub const KEYCTL_CAPS0_DIFFIE_HELLMAN: u32 = 0x04; pub const KEYCTL_CAPS0_PUBLIC_KEY: u32 = 0x08; pub const KEYCTL_CAPS0_BIG_KEY: u32 = 0x10; pub const KEYCTL_CAPS0_INVALIDATE: u32 = 0x20; pub const KEYCTL_CAPS0_RESTRICT_KEYRING: u32 = 0x40; pub const KEYCTL_CAPS0_MOVE: u32 = 0x80; pub const KEYCTL_CAPS1_NS_KEYRING_NAME: u32 = 0x01; pub const KEYCTL_CAPS1_NS_KEY_TAG: u32 = 0x02; } } pub const M_MXFAST: c_int = 1; pub const M_NLBLKS: c_int = 2; pub const M_GRAIN: c_int = 3; pub const M_KEEP: c_int = 4; pub const M_TRIM_THRESHOLD: c_int = -1; pub const M_TOP_PAD: c_int = -2; pub const M_MMAP_THRESHOLD: c_int = -3; pub const M_MMAP_MAX: c_int = -4; pub const M_CHECK_ACTION: c_int = -5; pub const M_PERTURB: c_int = -6; pub const M_ARENA_TEST: c_int = -7; pub const M_ARENA_MAX: c_int = -8; pub const SOMAXCONN: c_int = 4096; // linux/mount.h pub const MOVE_MOUNT_F_SYMLINKS: c_uint = 0x00000001; pub const MOVE_MOUNT_F_AUTOMOUNTS: c_uint = 0x00000002; pub const MOVE_MOUNT_F_EMPTY_PATH: c_uint = 0x00000004; pub const MOVE_MOUNT_T_SYMLINKS: c_uint = 0x00000010; pub const MOVE_MOUNT_T_AUTOMOUNTS: c_uint = 0x00000020; pub const MOVE_MOUNT_T_EMPTY_PATH: c_uint = 0x00000040; pub const MOVE_MOUNT_SET_GROUP: c_uint = 0x00000100; pub const MOVE_MOUNT_BENEATH: c_uint = 0x00000200; // sys/timex.h pub const ADJ_OFFSET: c_uint = 0x0001; pub const ADJ_FREQUENCY: c_uint = 0x0002; pub const ADJ_MAXERROR: c_uint = 0x0004; pub const ADJ_ESTERROR: c_uint = 0x0008; pub const ADJ_STATUS: c_uint = 0x0010; pub const ADJ_TIMECONST: c_uint = 0x0020; pub const ADJ_TAI: c_uint = 0x0080; pub const ADJ_SETOFFSET: c_uint = 0x0100; pub const ADJ_MICRO: c_uint = 0x1000; pub const ADJ_NANO: c_uint = 0x2000; pub const ADJ_TICK: c_uint = 0x4000; pub const ADJ_OFFSET_SINGLESHOT: c_uint = 0x8001; pub const ADJ_OFFSET_SS_READ: c_uint = 0xa001; pub const MOD_OFFSET: c_uint = ADJ_OFFSET; pub const MOD_FREQUENCY: c_uint = ADJ_FREQUENCY; pub const MOD_MAXERROR: c_uint = ADJ_MAXERROR; pub const MOD_ESTERROR: c_uint = ADJ_ESTERROR; pub const MOD_STATUS: c_uint = ADJ_STATUS; pub const MOD_TIMECONST: c_uint = ADJ_TIMECONST; pub const MOD_CLKB: c_uint = ADJ_TICK; pub const MOD_CLKA: c_uint = ADJ_OFFSET_SINGLESHOT; pub const MOD_TAI: c_uint = ADJ_TAI; pub const MOD_MICRO: c_uint = ADJ_MICRO; pub const MOD_NANO: c_uint = ADJ_NANO; pub const STA_PLL: c_int = 0x0001; pub const STA_PPSFREQ: c_int = 0x0002; pub const STA_PPSTIME: c_int = 0x0004; pub const STA_FLL: c_int = 0x0008; pub const STA_INS: c_int = 0x0010; pub const STA_DEL: c_int = 0x0020; pub const STA_UNSYNC: c_int = 0x0040; pub const STA_FREQHOLD: c_int = 0x0080; pub const STA_PPSSIGNAL: c_int = 0x0100; pub const STA_PPSJITTER: c_int = 0x0200; pub const STA_PPSWANDER: c_int = 0x0400; pub const STA_PPSERROR: c_int = 0x0800; pub const STA_CLOCKERR: c_int = 0x1000; pub const STA_NANO: c_int = 0x2000; pub const STA_MODE: c_int = 0x4000; pub const STA_CLK: c_int = 0x8000; pub const STA_RONLY: c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const NTP_API: c_int = 4; pub const TIME_OK: c_int = 0; pub const TIME_INS: c_int = 1; pub const TIME_DEL: c_int = 2; pub const TIME_OOP: c_int = 3; pub const TIME_WAIT: c_int = 4; pub const TIME_ERROR: c_int = 5; pub const TIME_BAD: c_int = TIME_ERROR; pub const MAXTC: c_long = 6; // Portable GLOB_* flags are defined at the `linux_like` level. // The following are GNU extensions. pub const GLOB_PERIOD: c_int = 1 << 7; pub const GLOB_ALTDIRFUNC: c_int = 1 << 9; pub const GLOB_BRACE: c_int = 1 << 10; pub const GLOB_NOMAGIC: c_int = 1 << 11; pub const GLOB_TILDE: c_int = 1 << 12; pub const GLOB_ONLYDIR: c_int = 1 << 13; pub const GLOB_TILDE_CHECK: c_int = 1 << 14; pub const MADV_COLLAPSE: c_int = 25; cfg_if! { if #[cfg(any( target_arch = "arm", target_arch = "x86", target_arch = "x86_64", target_arch = "s390x", target_arch = "riscv64", target_arch = "riscv32" ))] { pub const PTHREAD_STACK_MIN: size_t = 16384; } else if #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] { pub const PTHREAD_STACK_MIN: size_t = 0x6000; } else { pub const PTHREAD_STACK_MIN: size_t = 131072; } } pub const PTHREAD_MUTEX_ADAPTIVE_NP: c_int = 3; pub const REG_STARTEND: c_int = 4; pub const REG_EEND: c_int = 14; pub const REG_ESIZE: c_int = 15; pub const REG_ERPAREN: c_int = 16; cfg_if! { if #[cfg(any( target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", target_arch = "loongarch64", target_arch = "riscv64", target_arch = "s390x" ))] { pub const TUNSETCARRIER: Ioctl = 0x400454e2; pub const TUNGETDEVNETNS: Ioctl = 0x54e3; } else if #[cfg(any( target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "sparc", target_arch = "sparc64" ))] { pub const TUNSETCARRIER: Ioctl = 0x800454e2; pub const TUNGETDEVNETNS: Ioctl = 0x200054e3; } else { // Unknown target_arch } } extern "C" { pub fn fgetspent_r( fp: *mut crate::FILE, spbuf: *mut crate::spwd, buf: *mut c_char, buflen: size_t, spbufp: *mut *mut crate::spwd, ) -> c_int; pub fn sgetspent_r( s: *const c_char, spbuf: *mut crate::spwd, buf: *mut c_char, buflen: size_t, spbufp: *mut *mut crate::spwd, ) -> c_int; pub fn getspent_r( spbuf: *mut crate::spwd, buf: *mut c_char, buflen: size_t, spbufp: *mut *mut crate::spwd, ) -> c_int; pub fn qsort_r( base: *mut c_void, num: size_t, size: size_t, compar: Option c_int>, arg: *mut c_void, ); pub fn sendmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_int, ) -> c_int; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_int, timeout: *mut crate::timespec, ) -> c_int; pub fn getrlimit64(resource: crate::__rlimit_resource_t, rlim: *mut crate::rlimit64) -> c_int; pub fn setrlimit64(resource: crate::__rlimit_resource_t, rlim: *const crate::rlimit64) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "getrlimit64")] pub fn getrlimit(resource: crate::__rlimit_resource_t, rlim: *mut crate::rlimit) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "setrlimit64")] pub fn setrlimit(resource: crate::__rlimit_resource_t, rlim: *const crate::rlimit) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "prlimit64")] pub fn prlimit( pid: crate::pid_t, resource: crate::__rlimit_resource_t, new_limit: *const crate::rlimit, old_limit: *mut crate::rlimit, ) -> c_int; pub fn prlimit64( pid: crate::pid_t, resource: crate::__rlimit_resource_t, new_limit: *const crate::rlimit64, old_limit: *mut crate::rlimit64, ) -> c_int; pub fn utmpname(file: *const c_char) -> c_int; pub fn utmpxname(file: *const c_char) -> c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn getpt() -> c_int; pub fn mallopt(param: c_int, value: c_int) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut crate::timezone) -> c_int; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; pub fn getauxval(type_: c_ulong) -> c_ulong; pub fn adjtimex(buf: *mut timex) -> c_int; pub fn ntp_adjtime(buf: *mut timex) -> c_int; #[link_name = "ntp_gettimex"] pub fn ntp_gettime(buf: *mut ntptimeval) -> c_int; pub fn clock_adjtime(clk_id: crate::clockid_t, buf: *mut crate::timex) -> c_int; pub fn fanotify_mark( fd: c_int, flags: c_uint, mask: u64, dirfd: c_int, path: *const c_char, ) -> c_int; #[cfg_attr(gnu_file_offset_bits64, link_name = "preadv64v2")] pub fn preadv2( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t, flags: c_int, ) -> ssize_t; #[cfg_attr(gnu_file_offset_bits64, link_name = "pwritev64v2")] pub fn pwritev2( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t, flags: c_int, ) -> ssize_t; pub fn preadv64v2( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, flags: c_int, ) -> ssize_t; pub fn pwritev64v2( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, flags: c_int, ) -> ssize_t; pub fn renameat2( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_uint, ) -> c_int; // Added in `glibc` 2.25 pub fn explicit_bzero(s: *mut c_void, len: size_t); // Added in `glibc` 2.29 pub fn reallocarray(ptr: *mut c_void, nmemb: size_t, size: size_t) -> *mut c_void; pub fn ctermid(s: *mut c_char) -> *mut c_char; pub fn backtrace(buf: *mut *mut c_void, sz: c_int) -> c_int; pub fn glob64( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut glob64_t, ) -> c_int; pub fn globfree64(pglob: *mut glob64_t); pub fn ptrace(request: c_uint, ...) -> c_long; pub fn pthread_attr_getaffinity_np( attr: *const crate::pthread_attr_t, cpusetsize: size_t, cpuset: *mut crate::cpu_set_t, ) -> c_int; pub fn pthread_attr_setaffinity_np( attr: *mut crate::pthread_attr_t, cpusetsize: size_t, cpuset: *const crate::cpu_set_t, ) -> c_int; pub fn getpriority(which: crate::__priority_which_t, who: crate::id_t) -> c_int; pub fn setpriority(which: crate::__priority_which_t, who: crate::id_t, prio: c_int) -> c_int; pub fn pthread_rwlockattr_getkind_np( attr: *const crate::pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setkind_np( attr: *mut crate::pthread_rwlockattr_t, val: c_int, ) -> c_int; pub fn pthread_sigqueue(thread: crate::pthread_t, sig: c_int, value: crate::sigval) -> c_int; pub fn mallinfo() -> crate::mallinfo; pub fn mallinfo2() -> crate::mallinfo2; pub fn malloc_stats(); pub fn malloc_info(options: c_int, stream: *mut crate::FILE) -> c_int; pub fn malloc_usable_size(ptr: *mut c_void) -> size_t; pub fn getpwent_r( pwd: *mut crate::passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::passwd, ) -> c_int; pub fn getgrent_r( grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn fgetpwent_r( stream: *mut crate::FILE, pwd: *mut crate::passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::passwd, ) -> c_int; pub fn fgetgrent_r( stream: *mut crate::FILE, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn putpwent(p: *const crate::passwd, stream: *mut crate::FILE) -> c_int; pub fn putgrent(grp: *const crate::group, stream: *mut crate::FILE) -> c_int; pub fn sethostid(hostid: c_long) -> c_int; pub fn memfd_create(name: *const c_char, flags: c_uint) -> c_int; pub fn mlock2(addr: *const c_void, len: size_t, flags: c_uint) -> c_int; pub fn euidaccess(pathname: *const c_char, mode: c_int) -> c_int; pub fn eaccess(pathname: *const c_char, mode: c_int) -> c_int; pub fn asctime_r(tm: *const crate::tm, buf: *mut c_char) -> *mut c_char; pub fn ctime_r(timep: *const time_t, buf: *mut c_char) -> *mut c_char; pub fn dirname(path: *mut c_char) -> *mut c_char; /// POSIX version of `basename(3)`, defined in `libgen.h`. #[link_name = "__xpg_basename"] pub fn posix_basename(path: *mut c_char) -> *mut c_char; /// GNU version of `basename(3)`, defined in `string.h`. #[link_name = "basename"] pub fn gnu_basename(path: *const c_char) -> *mut c_char; pub fn dlmopen(lmid: Lmid_t, filename: *const c_char, flag: c_int) -> *mut c_void; pub fn dlinfo(handle: *mut c_void, request: c_int, info: *mut c_void) -> c_int; pub fn dladdr1( addr: *const c_void, info: *mut crate::Dl_info, extra_info: *mut *mut c_void, flags: c_int, ) -> c_int; pub fn malloc_trim(__pad: size_t) -> c_int; pub fn gnu_get_libc_release() -> *const c_char; pub fn gnu_get_libc_version() -> *const c_char; // posix/spawn.h // Added in `glibc` 2.29 pub fn posix_spawn_file_actions_addchdir_np( actions: *mut crate::posix_spawn_file_actions_t, path: *const c_char, ) -> c_int; // Added in `glibc` 2.29 pub fn posix_spawn_file_actions_addfchdir_np( actions: *mut crate::posix_spawn_file_actions_t, fd: c_int, ) -> c_int; // Added in `glibc` 2.34 pub fn posix_spawn_file_actions_addclosefrom_np( actions: *mut crate::posix_spawn_file_actions_t, from: c_int, ) -> c_int; // Added in `glibc` 2.35 pub fn posix_spawn_file_actions_addtcsetpgrp_np( actions: *mut crate::posix_spawn_file_actions_t, tcfd: c_int, ) -> c_int; // mntent.h pub fn getmntent_r( stream: *mut crate::FILE, mntbuf: *mut crate::mntent, buf: *mut c_char, buflen: c_int, ) -> *mut crate::mntent; pub fn execveat( dirfd: c_int, pathname: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char, flags: c_int, ) -> c_int; // Added in `glibc` 2.34 pub fn close_range(first: c_uint, last: c_uint, flags: c_int) -> c_int; pub fn mq_notify(mqdes: crate::mqd_t, sevp: *const crate::sigevent) -> c_int; pub fn epoll_pwait2( epfd: c_int, events: *mut crate::epoll_event, maxevents: c_int, timeout: *const crate::timespec, sigmask: *const crate::sigset_t, ) -> c_int; pub fn mempcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; } cfg_if! { if #[cfg(any( target_arch = "x86", target_arch = "arm", target_arch = "m68k", target_arch = "csky", target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", target_arch = "sparc", target_arch = "riscv32" ))] { mod b32; pub use self::b32::*; } else if #[cfg(any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64", target_arch = "riscv64", target_arch = "loongarch64" ))] { mod b64; pub use self::b64::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/gnu/b32/0000775000175000017500000000000015105742312017550 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b32/mod.rs0000644000175000017500000002657015105742312020705 0ustar bdrungbdrung//! 32-bit specific definitions for linux-like values use crate::prelude::*; use crate::pthread_mutex_t; pub type clock_t = i32; pub type shmatt_t = c_ulong; pub type msgqnum_t = c_ulong; pub type msglen_t = c_ulong; pub type nlink_t = u32; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; pub type __fsword_t = i32; pub type fsblkcnt64_t = u64; pub type fsfilcnt64_t = u64; pub type __syscall_ulong_t = c_ulong; cfg_if! { if #[cfg(target_arch = "riscv32")] { pub type time_t = i64; pub type suseconds_t = i64; type __ino_t = c_ulong; type __ino64_t = u64; pub type ino_t = __ino64_t; pub type off_t = i64; pub type blkcnt_t = i64; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type rlim_t = u64; pub type blksize_t = i64; } else if #[cfg(gnu_file_offset_bits64)] { pub type time_t = i32; pub type suseconds_t = i32; type __ino_t = c_ulong; type __ino64_t = u64; pub type ino_t = __ino64_t; pub type off_t = i64; pub type blkcnt_t = i64; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type rlim_t = u64; pub type blksize_t = i32; } else { pub type time_t = i32; pub type suseconds_t = i32; type __ino_t = c_ulong; type __ino64_t = u64; pub type ino_t = __ino_t; pub type off_t = i32; pub type blkcnt_t = i32; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type rlim_t = c_ulong; pub type blksize_t = i32; } } cfg_if! { if #[cfg(not(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", target_arch = "sparc" )))] { s! { pub struct stat { pub st_dev: crate::dev_t, __pad1: c_uint, #[cfg(not(gnu_file_offset_bits64))] pub st_ino: crate::ino_t, #[cfg(all(gnu_file_offset_bits64))] __st_ino: __ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_uint, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, #[cfg(not(gnu_file_offset_bits64))] __glibc_reserved4: c_long, #[cfg(not(gnu_file_offset_bits64))] __glibc_reserved5: c_long, #[cfg(gnu_file_offset_bits64)] pub st_ino: crate::ino_t, } } } } s! { pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct pthread_attr_t { __size: [u32; 9], } pub struct sigset_t { __val: [c_ulong; 32], } pub struct sysinfo { pub uptime: c_long, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, #[deprecated( since = "0.2.58", note = "This padding field might become private in the future" )] pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub _f: [c_char; 8], } pub struct semid_ds { pub sem_perm: ipc_perm, #[cfg(target_arch = "powerpc")] __reserved: crate::__syscall_ulong_t, pub sem_otime: crate::time_t, #[cfg(not(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc" )))] __reserved: crate::__syscall_ulong_t, #[cfg(target_arch = "powerpc")] __reserved2: crate::__syscall_ulong_t, pub sem_ctime: crate::time_t, #[cfg(not(any( target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc" )))] __reserved2: crate::__syscall_ulong_t, pub sem_nsems: crate::__syscall_ulong_t, __glibc_reserved3: crate::__syscall_ulong_t, __glibc_reserved4: crate::__syscall_ulong_t, } } pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; cfg_if! { if #[cfg(target_arch = "sparc")] { pub const O_NOATIME: c_int = 0x200000; pub const O_PATH: c_int = 0x1000000; pub const O_TMPFILE: c_int = 0x2000000 | O_DIRECTORY; pub const SA_ONSTACK: c_int = 1; pub const PTRACE_DETACH: c_uint = 11; pub const F_RDLCK: c_int = 1; pub const F_WRLCK: c_int = 2; pub const F_UNLCK: c_int = 3; pub const SFD_CLOEXEC: c_int = 0x400000; pub const NCCS: usize = 17; pub const O_TRUNC: c_int = 0x400; pub const O_CLOEXEC: c_int = 0x400000; pub const EBFONT: c_int = 109; pub const ENOSTR: c_int = 72; pub const ENODATA: c_int = 111; pub const ETIME: c_int = 73; pub const ENOSR: c_int = 74; pub const ENONET: c_int = 80; pub const ENOPKG: c_int = 113; pub const EREMOTE: c_int = 71; pub const ENOLINK: c_int = 82; pub const EADV: c_int = 83; pub const ESRMNT: c_int = 84; pub const ECOMM: c_int = 85; pub const EPROTO: c_int = 86; pub const EDOTDOT: c_int = 88; pub const SA_NODEFER: c_int = 0x20; pub const SA_RESETHAND: c_int = 0x4; pub const SA_RESTART: c_int = 0x2; pub const SA_NOCLDSTOP: c_int = 0x00000008; pub const EPOLL_CLOEXEC: c_int = 0x400000; pub const EFD_CLOEXEC: c_int = 0x400000; } else { pub const O_NOATIME: c_int = 0o1000000; pub const O_PATH: c_int = 0o10000000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const SA_ONSTACK: c_int = 0x08000000; pub const PTRACE_DETACH: c_uint = 17; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_CLOEXEC: c_int = 0x80000; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; } } cfg_if! { if #[cfg(target_arch = "sparc")] { pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; } else if #[cfg(all( gnu_file_offset_bits64, any(target_arch = "mips", target_arch = "mips32r6") ))] { pub const F_SETLK: c_int = 34; pub const F_SETLKW: c_int = 35; } else if #[cfg(gnu_file_offset_bits64)] { pub const F_SETLK: c_int = 13; pub const F_SETLKW: c_int = 14; } else { pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; } } #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTRACE_GETFPREGS: c_uint = 14; pub const PTRACE_SETFPREGS: c_uint = 15; pub const PTRACE_GETREGS: c_uint = 12; pub const PTRACE_SETREGS: c_uint = 13; extern "C" { pub fn sysctl( name: *mut c_int, namelen: c_int, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; } cfg_if! { if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] { mod mips; pub use self::mips::*; } else if #[cfg(target_arch = "m68k")] { mod m68k; pub use self::m68k::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "sparc")] { mod sparc; pub use self::sparc::*; } else if #[cfg(target_arch = "riscv32")] { mod riscv32; pub use self::riscv32::*; } else if #[cfg(target_arch = "csky")] { mod csky; pub use self::csky::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/gnu/b32/csky/0000775000175000017500000000000015105742312020521 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b32/csky/mod.rs0000644000175000017500000006267515105742312021664 0ustar bdrungbdrunguse crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = u32; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, f_spare: [crate::__fsword_t; 5], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct stat64 { pub st_dev: crate::dev_t, __pad1: c_uint, __st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_uint, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino64_t, } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, __unused1: c_ulong, pub shm_dtime: crate::time_t, __unused2: c_ulong, pub shm_ctime: crate::time_t, __unused3: c_ulong, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __glibc_reserved1: c_ulong, pub msg_rtime: crate::time_t, __glibc_reserved2: c_ulong, pub msg_ctime: crate::time_t, __glibc_reserved3: c_ulong, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [i64; 2], } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_LARGEFILE: c_int = 0o100000; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const EFD_NONBLOCK: c_int = 0x800; pub const SFD_NONBLOCK: c_int = 0x0800; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; // Syscall table pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_close: c_long = 57; pub const SYS_fstat: c_long = 80; pub const SYS_lseek: c_long = 62; pub const SYS_mmap: c_long = 222; pub const SYS_mprotect: c_long = 226; pub const SYS_munmap: c_long = 215; pub const SYS_brk: c_long = 214; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_ioctl: c_long = 29; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_sched_yield: c_long = 124; pub const SYS_mremap: c_long = 216; pub const SYS_msync: c_long = 227; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_shmget: c_long = 194; pub const SYS_shmat: c_long = 196; pub const SYS_shmctl: c_long = 195; pub const SYS_dup: c_long = 23; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_getpid: c_long = 172; pub const SYS_sendfile: c_long = 71; pub const SYS_socket: c_long = 198; pub const SYS_connect: c_long = 203; pub const SYS_accept: c_long = 202; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_shutdown: c_long = 210; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_socketpair: c_long = 199; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_exit: c_long = 93; pub const SYS_wait4: c_long = 260; pub const SYS_kill: c_long = 129; pub const SYS_uname: c_long = 160; pub const SYS_semget: c_long = 190; pub const SYS_semop: c_long = 193; pub const SYS_semctl: c_long = 191; pub const SYS_shmdt: c_long = 197; pub const SYS_msgget: c_long = 186; pub const SYS_msgsnd: c_long = 189; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgctl: c_long = 187; pub const SYS_fcntl: c_long = 25; pub const SYS_flock: c_long = 32; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_getcwd: c_long = 17; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_fchmod: c_long = 52; pub const SYS_fchown: c_long = 55; pub const SYS_umask: c_long = 166; pub const SYS_gettimeofday: c_long = 169; pub const SYS_getrlimit: c_long = 163; pub const SYS_getrusage: c_long = 165; pub const SYS_sysinfo: c_long = 179; pub const SYS_times: c_long = 153; pub const SYS_ptrace: c_long = 117; pub const SYS_getuid: c_long = 174; pub const SYS_syslog: c_long = 116; pub const SYS_getgid: c_long = 176; pub const SYS_setuid: c_long = 146; pub const SYS_setgid: c_long = 144; pub const SYS_geteuid: c_long = 175; pub const SYS_getegid: c_long = 177; pub const SYS_setpgid: c_long = 154; pub const SYS_getppid: c_long = 173; pub const SYS_setsid: c_long = 157; pub const SYS_setreuid: c_long = 145; pub const SYS_setregid: c_long = 143; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_getpgid: c_long = 155; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_getsid: c_long = 156; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_sigaltstack: c_long = 132; pub const SYS_personality: c_long = 92; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_getpriority: c_long = 141; pub const SYS_setpriority: c_long = 140; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_vhangup: c_long = 58; pub const SYS_pivot_root: c_long = 41; pub const SYS_prctl: c_long = 167; pub const SYS_adjtimex: c_long = 171; pub const SYS_setrlimit: c_long = 164; pub const SYS_chroot: c_long = 51; pub const SYS_sync: c_long = 81; pub const SYS_acct: c_long = 89; pub const SYS_settimeofday: c_long = 170; pub const SYS_mount: c_long = 40; pub const SYS_umount2: c_long = 39; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_reboot: c_long = 142; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_quotactl: c_long = 60; pub const SYS_nfsservctl: c_long = 42; pub const SYS_gettid: c_long = 178; pub const SYS_readahead: c_long = 213; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_tkill: c_long = 130; pub const SYS_futex: c_long = 98; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_getevents: c_long = 4; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_getdents64: c_long = 61; pub const SYS_set_tid_address: c_long = 96; pub const SYS_restart_syscall: c_long = 128; pub const SYS_semtimedop: c_long = 192; pub const SYS_fadvise64: c_long = 223; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_exit_group: c_long = 94; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_tgkill: c_long = 131; pub const SYS_mbind: c_long = 235; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_kexec_load: c_long = 104; pub const SYS_waitid: c_long = 95; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_migrate_pages: c_long = 238; pub const SYS_openat: c_long = 56; pub const SYS_mkdirat: c_long = 34; pub const SYS_mknodat: c_long = 33; pub const SYS_fchownat: c_long = 54; pub const SYS_newfstatat: c_long = 79; pub const SYS_unlinkat: c_long = 35; pub const SYS_linkat: c_long = 37; pub const SYS_symlinkat: c_long = 36; pub const SYS_readlinkat: c_long = 78; pub const SYS_fchmodat: c_long = 53; pub const SYS_faccessat: c_long = 48; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_unshare: c_long = 97; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_sync_file_range: c_long = 84; pub const SYS_vmsplice: c_long = 75; pub const SYS_move_pages: c_long = 239; pub const SYS_utimensat: c_long = 88; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_timerfd_create: c_long = 85; pub const SYS_fallocate: c_long = 47; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_accept4: c_long = 242; pub const SYS_signalfd4: c_long = 74; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_dup3: c_long = 24; pub const SYS_pipe2: c_long = 59; pub const SYS_inotify_init1: c_long = 26; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_recvmmsg: c_long = 243; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_prlimit64: c_long = 261; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_sendmmsg: c_long = 269; pub const SYS_setns: c_long = 268; pub const SYS_getcpu: c_long = 168; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_rseq: c_long = 293; pub const SYS_syscall: c_long = 294; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs0000644000175000017500000007352415105742312021606 0ustar bdrungbdrunguse crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = i32; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, f_spare: [crate::__fsword_t; 4], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct ipc_perm { __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, __seq: u32, __pad1: u32, __glibc_reserved1: u64, __glibc_reserved2: u64, } pub struct stat { pub st_dev: crate::dev_t, #[cfg(not(gnu_file_offset_bits64))] __pad1: c_ushort, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_ushort, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_ushort, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, __glibc_reserved1: c_uint, pub shm_atime: crate::time_t, __glibc_reserved2: c_uint, pub shm_dtime: crate::time_t, __glibc_reserved3: c_uint, pub shm_ctime: crate::time_t, __glibc_reserved4: c_uint, pub shm_segsz: size_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __glibc_reserved5: c_ulong, __glibc_reserved6: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, __glibc_reserved1: c_uint, pub msg_stime: crate::time_t, __glibc_reserved2: c_uint, pub msg_rtime: crate::time_t, __glibc_reserved3: c_uint, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_DIRECT: c_int = 0x20000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_LARGEFILE: c_int = 0o200000; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_LOCKED: c_int = 0x00080; pub const MAP_NORESERVE: c_int = 0x00040; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 58; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const MCL_CURRENT: c_int = 0x2000; pub const MCL_FUTURE: c_int = 0x4000; pub const MCL_ONFAULT: c_int = 0x8000; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; cfg_if! { if #[cfg(gnu_file_offset_bits64)] { pub const F_GETLK: c_int = 12; } else { pub const F_GETLK: c_int = 5; } } pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const EFD_NONBLOCK: c_int = 0x800; pub const SFD_NONBLOCK: c_int = 0x0800; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGSTKSZ: size_t = 0x4000; pub const MINSIGSTKSZ: size_t = 4096; pub const CBAUD: crate::tcflag_t = 0xff; pub const TAB1: crate::tcflag_t = 0x400; pub const TAB2: crate::tcflag_t = 0x800; pub const TAB3: crate::tcflag_t = 0xc00; pub const CR1: crate::tcflag_t = 0x1000; pub const CR2: crate::tcflag_t = 0x2000; pub const CR3: crate::tcflag_t = 0x3000; pub const FF1: crate::tcflag_t = 0x4000; pub const BS1: crate::tcflag_t = 0x8000; pub const VT1: crate::tcflag_t = 0x10000; pub const VWERASE: usize = 0xa; pub const VREPRINT: usize = 0xb; pub const VSUSP: usize = 0xc; pub const VSTART: usize = 0xd; pub const VSTOP: usize = 0xe; pub const VDISCARD: usize = 0x10; pub const VTIME: usize = 0x7; pub const IXON: crate::tcflag_t = 0x200; pub const IXOFF: crate::tcflag_t = 0x400; pub const ONLCR: crate::tcflag_t = 0x2; pub const CSIZE: crate::tcflag_t = 0x300; pub const CS6: crate::tcflag_t = 0x100; pub const CS7: crate::tcflag_t = 0x200; pub const CS8: crate::tcflag_t = 0x300; pub const CSTOPB: crate::tcflag_t = 0x400; pub const CREAD: crate::tcflag_t = 0x800; pub const PARENB: crate::tcflag_t = 0x1000; pub const PARODD: crate::tcflag_t = 0x2000; pub const HUPCL: crate::tcflag_t = 0x4000; pub const CLOCAL: crate::tcflag_t = 0x8000; pub const ECHOKE: crate::tcflag_t = 0x1; pub const ECHOE: crate::tcflag_t = 0x2; pub const ECHOK: crate::tcflag_t = 0x4; pub const ECHONL: crate::tcflag_t = 0x10; pub const ECHOPRT: crate::tcflag_t = 0x20; pub const ECHOCTL: crate::tcflag_t = 0x40; pub const ISIG: crate::tcflag_t = 0x80; pub const ICANON: crate::tcflag_t = 0x100; pub const PENDIN: crate::tcflag_t = 0x20000000; pub const NOFLSH: crate::tcflag_t = 0x80000000; pub const VSWTC: usize = 9; pub const OLCUC: crate::tcflag_t = 0o000004; pub const NLDLY: crate::tcflag_t = 0o001400; pub const CRDLY: crate::tcflag_t = 0o030000; pub const TABDLY: crate::tcflag_t = 0o006000; pub const BSDLY: crate::tcflag_t = 0o100000; pub const FFDLY: crate::tcflag_t = 0o040000; pub const VTDLY: crate::tcflag_t = 0o200000; pub const XTABS: crate::tcflag_t = 0o006000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const CBAUDEX: crate::speed_t = 0o000020; pub const B57600: crate::speed_t = 0o0020; pub const B115200: crate::speed_t = 0o0021; pub const B230400: crate::speed_t = 0o0022; pub const B460800: crate::speed_t = 0o0023; pub const B500000: crate::speed_t = 0o0024; pub const B576000: crate::speed_t = 0o0025; pub const B921600: crate::speed_t = 0o0026; pub const B1000000: crate::speed_t = 0o0027; pub const B1152000: crate::speed_t = 0o0030; pub const B1500000: crate::speed_t = 0o0031; pub const B2000000: crate::speed_t = 0o0032; pub const B2500000: crate::speed_t = 0o0033; pub const B3000000: crate::speed_t = 0o0034; pub const B3500000: crate::speed_t = 0o0035; pub const B4000000: crate::speed_t = 0o0036; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; pub const VMIN: usize = 5; pub const IEXTEN: crate::tcflag_t = 0x400; pub const TOSTOP: crate::tcflag_t = 0x400000; pub const FLUSHO: crate::tcflag_t = 0x800000; pub const EXTPROC: crate::tcflag_t = 0x10000000; pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_waitpid: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_time: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_break: c_long = 17; pub const SYS_oldstat: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_stime: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_oldfstat: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_stty: c_long = 31; pub const SYS_gtty: c_long = 32; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_ftime: c_long = 35; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_prof: c_long = 44; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_lock: c_long = 53; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_mpx: c_long = 56; pub const SYS_setpgid: c_long = 57; pub const SYS_ulimit: c_long = 58; pub const SYS_oldolduname: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sgetmask: c_long = 68; pub const SYS_ssetmask: c_long = 69; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrlimit: c_long = 76; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_select: c_long = 82; pub const SYS_symlink: c_long = 83; pub const SYS_oldlstat: c_long = 84; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_profil: c_long = 98; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_ioperm: c_long = 101; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_olduname: c_long = 109; pub const SYS_iopl: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_vm86: c_long = 113; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_modify_ldt: c_long = 123; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; /* Syscall for Andrew File System */ pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 166; pub const SYS_poll: c_long = 167; pub const SYS_nfsservctl: c_long = 168; pub const SYS_setresgid: c_long = 169; pub const SYS_getresgid: c_long = 170; pub const SYS_prctl: c_long = 171; pub const SYS_rt_sigreturn: c_long = 172; pub const SYS_rt_sigaction: c_long = 173; pub const SYS_rt_sigprocmask: c_long = 174; pub const SYS_rt_sigpending: c_long = 175; pub const SYS_rt_sigtimedwait: c_long = 176; pub const SYS_rt_sigqueueinfo: c_long = 177; pub const SYS_rt_sigsuspend: c_long = 178; pub const SYS_pread64: c_long = 179; pub const SYS_pwrite64: c_long = 180; pub const SYS_chown: c_long = 181; pub const SYS_getcwd: c_long = 182; pub const SYS_capget: c_long = 183; pub const SYS_capset: c_long = 184; pub const SYS_sigaltstack: c_long = 185; pub const SYS_sendfile: c_long = 186; pub const SYS_getpmsg: c_long = 187; /* some people actually want streams */ pub const SYS_putpmsg: c_long = 188; /* some people actually want streams */ pub const SYS_vfork: c_long = 189; pub const SYS_ugetrlimit: c_long = 190; /* SuS compliant getrlimit */ pub const SYS_readahead: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_pciconfig_read: c_long = 198; pub const SYS_pciconfig_write: c_long = 199; pub const SYS_pciconfig_iobase: c_long = 200; pub const SYS_multiplexer: c_long = 201; pub const SYS_getdents64: c_long = 202; pub const SYS_pivot_root: c_long = 203; pub const SYS_fcntl64: c_long = 204; pub const SYS_madvise: c_long = 205; pub const SYS_mincore: c_long = 206; pub const SYS_gettid: c_long = 207; pub const SYS_tkill: c_long = 208; pub const SYS_setxattr: c_long = 209; pub const SYS_lsetxattr: c_long = 210; pub const SYS_fsetxattr: c_long = 211; pub const SYS_getxattr: c_long = 212; pub const SYS_lgetxattr: c_long = 213; pub const SYS_fgetxattr: c_long = 214; pub const SYS_listxattr: c_long = 215; pub const SYS_llistxattr: c_long = 216; pub const SYS_flistxattr: c_long = 217; pub const SYS_removexattr: c_long = 218; pub const SYS_lremovexattr: c_long = 219; pub const SYS_fremovexattr: c_long = 220; pub const SYS_futex: c_long = 221; pub const SYS_sched_setaffinity: c_long = 222; pub const SYS_sched_getaffinity: c_long = 223; pub const SYS_tuxcall: c_long = 225; pub const SYS_sendfile64: c_long = 226; pub const SYS_io_setup: c_long = 227; pub const SYS_io_destroy: c_long = 228; pub const SYS_io_getevents: c_long = 229; pub const SYS_io_submit: c_long = 230; pub const SYS_io_cancel: c_long = 231; pub const SYS_set_tid_address: c_long = 232; pub const SYS_fadvise64: c_long = 233; pub const SYS_exit_group: c_long = 234; pub const SYS_lookup_dcookie: c_long = 235; pub const SYS_epoll_create: c_long = 236; pub const SYS_epoll_ctl: c_long = 237; pub const SYS_epoll_wait: c_long = 238; pub const SYS_remap_file_pages: c_long = 239; pub const SYS_timer_create: c_long = 240; pub const SYS_timer_settime: c_long = 241; pub const SYS_timer_gettime: c_long = 242; pub const SYS_timer_getoverrun: c_long = 243; pub const SYS_timer_delete: c_long = 244; pub const SYS_clock_settime: c_long = 245; pub const SYS_clock_gettime: c_long = 246; pub const SYS_clock_getres: c_long = 247; pub const SYS_clock_nanosleep: c_long = 248; pub const SYS_swapcontext: c_long = 249; pub const SYS_tgkill: c_long = 250; pub const SYS_utimes: c_long = 251; pub const SYS_statfs64: c_long = 252; pub const SYS_fstatfs64: c_long = 253; pub const SYS_fadvise64_64: c_long = 254; pub const SYS_rtas: c_long = 255; pub const SYS_sys_debug_setcontext: c_long = 256; pub const SYS_migrate_pages: c_long = 258; pub const SYS_mbind: c_long = 259; pub const SYS_get_mempolicy: c_long = 260; pub const SYS_set_mempolicy: c_long = 261; pub const SYS_mq_open: c_long = 262; pub const SYS_mq_unlink: c_long = 263; pub const SYS_mq_timedsend: c_long = 264; pub const SYS_mq_timedreceive: c_long = 265; pub const SYS_mq_notify: c_long = 266; pub const SYS_mq_getsetattr: c_long = 267; pub const SYS_kexec_load: c_long = 268; pub const SYS_add_key: c_long = 269; pub const SYS_request_key: c_long = 270; pub const SYS_keyctl: c_long = 271; pub const SYS_waitid: c_long = 272; pub const SYS_ioprio_set: c_long = 273; pub const SYS_ioprio_get: c_long = 274; pub const SYS_inotify_init: c_long = 275; pub const SYS_inotify_add_watch: c_long = 276; pub const SYS_inotify_rm_watch: c_long = 277; pub const SYS_spu_run: c_long = 278; pub const SYS_spu_create: c_long = 279; pub const SYS_pselect6: c_long = 280; pub const SYS_ppoll: c_long = 281; pub const SYS_unshare: c_long = 282; pub const SYS_splice: c_long = 283; pub const SYS_tee: c_long = 284; pub const SYS_vmsplice: c_long = 285; pub const SYS_openat: c_long = 286; pub const SYS_mkdirat: c_long = 287; pub const SYS_mknodat: c_long = 288; pub const SYS_fchownat: c_long = 289; pub const SYS_futimesat: c_long = 290; pub const SYS_fstatat64: c_long = 291; pub const SYS_unlinkat: c_long = 292; pub const SYS_renameat: c_long = 293; pub const SYS_linkat: c_long = 294; pub const SYS_symlinkat: c_long = 295; pub const SYS_readlinkat: c_long = 296; pub const SYS_fchmodat: c_long = 297; pub const SYS_faccessat: c_long = 298; pub const SYS_get_robust_list: c_long = 299; pub const SYS_set_robust_list: c_long = 300; pub const SYS_move_pages: c_long = 301; pub const SYS_getcpu: c_long = 302; pub const SYS_epoll_pwait: c_long = 303; pub const SYS_utimensat: c_long = 304; pub const SYS_signalfd: c_long = 305; pub const SYS_timerfd_create: c_long = 306; pub const SYS_eventfd: c_long = 307; pub const SYS_sync_file_range2: c_long = 308; pub const SYS_fallocate: c_long = 309; pub const SYS_subpage_prot: c_long = 310; pub const SYS_timerfd_settime: c_long = 311; pub const SYS_timerfd_gettime: c_long = 312; pub const SYS_signalfd4: c_long = 313; pub const SYS_eventfd2: c_long = 314; pub const SYS_epoll_create1: c_long = 315; pub const SYS_dup3: c_long = 316; pub const SYS_pipe2: c_long = 317; pub const SYS_inotify_init1: c_long = 318; pub const SYS_perf_event_open: c_long = 319; pub const SYS_preadv: c_long = 320; pub const SYS_pwritev: c_long = 321; pub const SYS_rt_tgsigqueueinfo: c_long = 322; pub const SYS_fanotify_init: c_long = 323; pub const SYS_fanotify_mark: c_long = 324; pub const SYS_prlimit64: c_long = 325; pub const SYS_socket: c_long = 326; pub const SYS_bind: c_long = 327; pub const SYS_connect: c_long = 328; pub const SYS_listen: c_long = 329; pub const SYS_accept: c_long = 330; pub const SYS_getsockname: c_long = 331; pub const SYS_getpeername: c_long = 332; pub const SYS_socketpair: c_long = 333; pub const SYS_send: c_long = 334; pub const SYS_sendto: c_long = 335; pub const SYS_recv: c_long = 336; pub const SYS_recvfrom: c_long = 337; pub const SYS_shutdown: c_long = 338; pub const SYS_setsockopt: c_long = 339; pub const SYS_getsockopt: c_long = 340; pub const SYS_sendmsg: c_long = 341; pub const SYS_recvmsg: c_long = 342; pub const SYS_recvmmsg: c_long = 343; pub const SYS_accept4: c_long = 344; pub const SYS_name_to_handle_at: c_long = 345; pub const SYS_open_by_handle_at: c_long = 346; pub const SYS_clock_adjtime: c_long = 347; pub const SYS_syncfs: c_long = 348; pub const SYS_sendmmsg: c_long = 349; pub const SYS_setns: c_long = 350; pub const SYS_process_vm_readv: c_long = 351; pub const SYS_process_vm_writev: c_long = 352; pub const SYS_finit_module: c_long = 353; pub const SYS_kcmp: c_long = 354; pub const SYS_sched_setattr: c_long = 355; pub const SYS_sched_getattr: c_long = 356; pub const SYS_renameat2: c_long = 357; pub const SYS_seccomp: c_long = 358; pub const SYS_getrandom: c_long = 359; pub const SYS_memfd_create: c_long = 360; pub const SYS_bpf: c_long = 361; pub const SYS_execveat: c_long = 362; pub const SYS_switch_endian: c_long = 363; pub const SYS_userfaultfd: c_long = 364; pub const SYS_membarrier: c_long = 365; pub const SYS_mlock2: c_long = 378; pub const SYS_copy_file_range: c_long = 379; pub const SYS_preadv2: c_long = 380; pub const SYS_pwritev2: c_long = 381; pub const SYS_kexec_file_load: c_long = 382; pub const SYS_statx: c_long = 383; pub const SYS_rseq: c_long = 387; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_mseal: c_long = 462; libc/src/unix/linux_like/linux/gnu/b32/arm/0000775000175000017500000000000015105742312020327 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs0000644000175000017500000007654415105742312021472 0ustar bdrungbdrunguse crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = u32; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, f_spare: [crate::__fsword_t; 4], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct stat64 { pub st_dev: crate::dev_t, __pad1: c_uint, __st_ino: c_ulong, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_uint, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino64_t, } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, __unused1: c_ulong, pub shm_dtime: crate::time_t, __unused2: c_ulong, pub shm_ctime: crate::time_t, __unused3: c_ulong, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __glibc_reserved1: c_ulong, pub msg_rtime: crate::time_t, __glibc_reserved2: c_ulong, pub msg_ctime: crate::time_t, __glibc_reserved3: c_ulong, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct mcontext_t { pub trap_no: c_ulong, pub error_code: c_ulong, pub oldmask: c_ulong, pub arm_r0: c_ulong, pub arm_r1: c_ulong, pub arm_r2: c_ulong, pub arm_r3: c_ulong, pub arm_r4: c_ulong, pub arm_r5: c_ulong, pub arm_r6: c_ulong, pub arm_r7: c_ulong, pub arm_r8: c_ulong, pub arm_r9: c_ulong, pub arm_r10: c_ulong, pub arm_fp: c_ulong, pub arm_ip: c_ulong, pub arm_sp: c_ulong, pub arm_lr: c_ulong, pub arm_pc: c_ulong, pub arm_cpsr: c_ulong, pub fault_address: c_ulong, } pub struct user_regs { pub arm_r0: c_ulong, pub arm_r1: c_ulong, pub arm_r2: c_ulong, pub arm_r3: c_ulong, pub arm_r4: c_ulong, pub arm_r5: c_ulong, pub arm_r6: c_ulong, pub arm_r7: c_ulong, pub arm_r8: c_ulong, pub arm_r9: c_ulong, pub arm_r10: c_ulong, pub arm_fp: c_ulong, pub arm_ip: c_ulong, pub arm_sp: c_ulong, pub arm_lr: c_ulong, pub arm_pc: c_ulong, pub arm_cpsr: c_ulong, pub arm_orig_r0: c_ulong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [i64; 2], } #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: crate::mcontext_t, pub uc_sigmask: crate::sigset_t, pub uc_regspace: [c_ulong; 128], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_link) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); } } } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_DIRECT: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_LARGEFILE: c_int = 0o400000; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; cfg_if! { if #[cfg(gnu_file_offset_bits64)] { pub const F_GETLK: c_int = 12; } else { pub const F_GETLK: c_int = 5; } } pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const EFD_NONBLOCK: c_int = 0x800; pub const SFD_NONBLOCK: c_int = 0x0800; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; // Syscall table pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_ptrace: c_long = 26; pub const SYS_pause: c_long = 29; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_setpgid: c_long = 57; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_symlink: c_long = 83; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_vhangup: c_long = 111; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_setresgid: c_long = 170; pub const SYS_getresgid: c_long = 171; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_chown: c_long = 182; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_vfork: c_long = 190; pub const SYS_ugetrlimit: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_lchown32: c_long = 198; pub const SYS_getuid32: c_long = 199; pub const SYS_getgid32: c_long = 200; pub const SYS_geteuid32: c_long = 201; pub const SYS_getegid32: c_long = 202; pub const SYS_setreuid32: c_long = 203; pub const SYS_setregid32: c_long = 204; pub const SYS_getgroups32: c_long = 205; pub const SYS_setgroups32: c_long = 206; pub const SYS_fchown32: c_long = 207; pub const SYS_setresuid32: c_long = 208; pub const SYS_getresuid32: c_long = 209; pub const SYS_setresgid32: c_long = 210; pub const SYS_getresgid32: c_long = 211; pub const SYS_chown32: c_long = 212; pub const SYS_setuid32: c_long = 213; pub const SYS_setgid32: c_long = 214; pub const SYS_setfsuid32: c_long = 215; pub const SYS_setfsgid32: c_long = 216; pub const SYS_getdents64: c_long = 217; pub const SYS_pivot_root: c_long = 218; pub const SYS_mincore: c_long = 219; pub const SYS_madvise: c_long = 220; pub const SYS_fcntl64: c_long = 221; pub const SYS_gettid: c_long = 224; pub const SYS_readahead: c_long = 225; pub const SYS_setxattr: c_long = 226; pub const SYS_lsetxattr: c_long = 227; pub const SYS_fsetxattr: c_long = 228; pub const SYS_getxattr: c_long = 229; pub const SYS_lgetxattr: c_long = 230; pub const SYS_fgetxattr: c_long = 231; pub const SYS_listxattr: c_long = 232; pub const SYS_llistxattr: c_long = 233; pub const SYS_flistxattr: c_long = 234; pub const SYS_removexattr: c_long = 235; pub const SYS_lremovexattr: c_long = 236; pub const SYS_fremovexattr: c_long = 237; pub const SYS_tkill: c_long = 238; pub const SYS_sendfile64: c_long = 239; pub const SYS_futex: c_long = 240; pub const SYS_sched_setaffinity: c_long = 241; pub const SYS_sched_getaffinity: c_long = 242; pub const SYS_io_setup: c_long = 243; pub const SYS_io_destroy: c_long = 244; pub const SYS_io_getevents: c_long = 245; pub const SYS_io_submit: c_long = 246; pub const SYS_io_cancel: c_long = 247; pub const SYS_exit_group: c_long = 248; pub const SYS_lookup_dcookie: c_long = 249; pub const SYS_epoll_create: c_long = 250; pub const SYS_epoll_ctl: c_long = 251; pub const SYS_epoll_wait: c_long = 252; pub const SYS_remap_file_pages: c_long = 253; pub const SYS_set_tid_address: c_long = 256; pub const SYS_timer_create: c_long = 257; pub const SYS_timer_settime: c_long = 258; pub const SYS_timer_gettime: c_long = 259; pub const SYS_timer_getoverrun: c_long = 260; pub const SYS_timer_delete: c_long = 261; pub const SYS_clock_settime: c_long = 262; pub const SYS_clock_gettime: c_long = 263; pub const SYS_clock_getres: c_long = 264; pub const SYS_clock_nanosleep: c_long = 265; pub const SYS_statfs64: c_long = 266; pub const SYS_fstatfs64: c_long = 267; pub const SYS_tgkill: c_long = 268; pub const SYS_utimes: c_long = 269; pub const SYS_arm_fadvise64_64: c_long = 270; pub const SYS_pciconfig_iobase: c_long = 271; pub const SYS_pciconfig_read: c_long = 272; pub const SYS_pciconfig_write: c_long = 273; pub const SYS_mq_open: c_long = 274; pub const SYS_mq_unlink: c_long = 275; pub const SYS_mq_timedsend: c_long = 276; pub const SYS_mq_timedreceive: c_long = 277; pub const SYS_mq_notify: c_long = 278; pub const SYS_mq_getsetattr: c_long = 279; pub const SYS_waitid: c_long = 280; pub const SYS_socket: c_long = 281; pub const SYS_bind: c_long = 282; pub const SYS_connect: c_long = 283; pub const SYS_listen: c_long = 284; pub const SYS_accept: c_long = 285; pub const SYS_getsockname: c_long = 286; pub const SYS_getpeername: c_long = 287; pub const SYS_socketpair: c_long = 288; pub const SYS_send: c_long = 289; pub const SYS_sendto: c_long = 290; pub const SYS_recv: c_long = 291; pub const SYS_recvfrom: c_long = 292; pub const SYS_shutdown: c_long = 293; pub const SYS_setsockopt: c_long = 294; pub const SYS_getsockopt: c_long = 295; pub const SYS_sendmsg: c_long = 296; pub const SYS_recvmsg: c_long = 297; pub const SYS_semop: c_long = 298; pub const SYS_semget: c_long = 299; pub const SYS_semctl: c_long = 300; pub const SYS_msgsnd: c_long = 301; pub const SYS_msgrcv: c_long = 302; pub const SYS_msgget: c_long = 303; pub const SYS_msgctl: c_long = 304; pub const SYS_shmat: c_long = 305; pub const SYS_shmdt: c_long = 306; pub const SYS_shmget: c_long = 307; pub const SYS_shmctl: c_long = 308; pub const SYS_add_key: c_long = 309; pub const SYS_request_key: c_long = 310; pub const SYS_keyctl: c_long = 311; pub const SYS_semtimedop: c_long = 312; pub const SYS_vserver: c_long = 313; pub const SYS_ioprio_set: c_long = 314; pub const SYS_ioprio_get: c_long = 315; pub const SYS_inotify_init: c_long = 316; pub const SYS_inotify_add_watch: c_long = 317; pub const SYS_inotify_rm_watch: c_long = 318; pub const SYS_mbind: c_long = 319; pub const SYS_get_mempolicy: c_long = 320; pub const SYS_set_mempolicy: c_long = 321; pub const SYS_openat: c_long = 322; pub const SYS_mkdirat: c_long = 323; pub const SYS_mknodat: c_long = 324; pub const SYS_fchownat: c_long = 325; pub const SYS_futimesat: c_long = 326; pub const SYS_fstatat64: c_long = 327; pub const SYS_unlinkat: c_long = 328; pub const SYS_renameat: c_long = 329; pub const SYS_linkat: c_long = 330; pub const SYS_symlinkat: c_long = 331; pub const SYS_readlinkat: c_long = 332; pub const SYS_fchmodat: c_long = 333; pub const SYS_faccessat: c_long = 334; pub const SYS_pselect6: c_long = 335; pub const SYS_ppoll: c_long = 336; pub const SYS_unshare: c_long = 337; pub const SYS_set_robust_list: c_long = 338; pub const SYS_get_robust_list: c_long = 339; pub const SYS_splice: c_long = 340; pub const SYS_arm_sync_file_range: c_long = 341; pub const SYS_tee: c_long = 342; pub const SYS_vmsplice: c_long = 343; pub const SYS_move_pages: c_long = 344; pub const SYS_getcpu: c_long = 345; pub const SYS_epoll_pwait: c_long = 346; pub const SYS_kexec_load: c_long = 347; pub const SYS_utimensat: c_long = 348; pub const SYS_signalfd: c_long = 349; pub const SYS_timerfd_create: c_long = 350; pub const SYS_eventfd: c_long = 351; pub const SYS_fallocate: c_long = 352; pub const SYS_timerfd_settime: c_long = 353; pub const SYS_timerfd_gettime: c_long = 354; pub const SYS_signalfd4: c_long = 355; pub const SYS_eventfd2: c_long = 356; pub const SYS_epoll_create1: c_long = 357; pub const SYS_dup3: c_long = 358; pub const SYS_pipe2: c_long = 359; pub const SYS_inotify_init1: c_long = 360; pub const SYS_preadv: c_long = 361; pub const SYS_pwritev: c_long = 362; pub const SYS_rt_tgsigqueueinfo: c_long = 363; pub const SYS_perf_event_open: c_long = 364; pub const SYS_recvmmsg: c_long = 365; pub const SYS_accept4: c_long = 366; pub const SYS_fanotify_init: c_long = 367; pub const SYS_fanotify_mark: c_long = 368; pub const SYS_prlimit64: c_long = 369; pub const SYS_name_to_handle_at: c_long = 370; pub const SYS_open_by_handle_at: c_long = 371; pub const SYS_clock_adjtime: c_long = 372; pub const SYS_syncfs: c_long = 373; pub const SYS_sendmmsg: c_long = 374; pub const SYS_setns: c_long = 375; pub const SYS_process_vm_readv: c_long = 376; pub const SYS_process_vm_writev: c_long = 377; pub const SYS_kcmp: c_long = 378; pub const SYS_finit_module: c_long = 379; pub const SYS_sched_setattr: c_long = 380; pub const SYS_sched_getattr: c_long = 381; pub const SYS_renameat2: c_long = 382; pub const SYS_seccomp: c_long = 383; pub const SYS_getrandom: c_long = 384; pub const SYS_memfd_create: c_long = 385; pub const SYS_bpf: c_long = 386; pub const SYS_execveat: c_long = 387; pub const SYS_userfaultfd: c_long = 388; pub const SYS_membarrier: c_long = 389; pub const SYS_mlock2: c_long = 390; pub const SYS_copy_file_range: c_long = 391; pub const SYS_preadv2: c_long = 392; pub const SYS_pwritev2: c_long = 393; pub const SYS_pkey_mprotect: c_long = 394; pub const SYS_pkey_alloc: c_long = 395; pub const SYS_pkey_free: c_long = 396; pub const SYS_statx: c_long = 397; pub const SYS_rseq: c_long = 398; pub const SYS_kexec_file_load: c_long = 401; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_mseal: c_long = 462; libc/src/unix/linux_like/linux/gnu/b32/sparc/0000775000175000017500000000000015105742312020660 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs0000644000175000017500000007204715105742312022015 0ustar bdrungbdrung//! SPARC-specific definitions for 32-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = i32; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, f_spare: [crate::__fsword_t; 4], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, _pad: [c_int; 29], _align: [usize; 0], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, __reserved: c_short, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct stat { pub st_dev: crate::dev_t, #[cfg(not(gnu_file_offset_bits64))] __pad1: c_ushort, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_ushort, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_ushort, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, __pad1: c_ushort, pub mode: c_ushort, __pad2: c_ushort, pub __seq: c_ushort, __unused1: c_ulonglong, __unused2: c_ulonglong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, __pad1: c_uint, pub shm_atime: crate::time_t, __pad2: c_uint, pub shm_dtime: crate::time_t, __pad3: c_uint, pub shm_ctime: crate::time_t, pub shm_segsz: size_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __reserved1: c_ulong, __reserved2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, __pad1: c_uint, pub msg_stime: crate::time_t, __pad2: c_uint, pub msg_rtime: crate::time_t, __pad3: c_uint, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ushort, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved1: c_ulong, __glibc_reserved2: c_ulong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [i64; 3], } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_APPEND: c_int = 0x8; pub const O_CREAT: c_int = 0x200; pub const O_EXCL: c_int = 0x800; pub const O_NOCTTY: c_int = 0x8000; pub const O_NONBLOCK: c_int = 0x4000; pub const O_SYNC: c_int = 0x802000; pub const O_RSYNC: c_int = 0x802000; pub const O_DSYNC: c_int = 0x2000; pub const O_FSYNC: c_int = 0x802000; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 0x0200; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLK: c_int = 78; pub const ENAMETOOLONG: c_int = 63; pub const ENOLCK: c_int = 79; pub const ENOSYS: c_int = 90; pub const ENOTEMPTY: c_int = 66; pub const ELOOP: c_int = 62; pub const ENOMSG: c_int = 75; pub const EIDRM: c_int = 77; pub const ECHRNG: c_int = 94; pub const EL2NSYNC: c_int = 95; pub const EL3HLT: c_int = 96; pub const EL3RST: c_int = 97; pub const ELNRNG: c_int = 98; pub const EUNATCH: c_int = 99; pub const ENOCSI: c_int = 100; pub const EL2HLT: c_int = 101; pub const EBADE: c_int = 102; pub const EBADR: c_int = 103; pub const EXFULL: c_int = 104; pub const ENOANO: c_int = 105; pub const EBADRQC: c_int = 106; pub const EBADSLT: c_int = 107; pub const EMULTIHOP: c_int = 87; pub const EOVERFLOW: c_int = 92; pub const ENOTUNIQ: c_int = 115; pub const EBADFD: c_int = 93; pub const EBADMSG: c_int = 76; pub const EREMCHG: c_int = 89; pub const ELIBACC: c_int = 114; pub const ELIBBAD: c_int = 112; pub const ELIBSCN: c_int = 124; pub const ELIBMAX: c_int = 123; pub const ELIBEXEC: c_int = 110; pub const EILSEQ: c_int = 122; pub const ERESTART: c_int = 116; pub const ESTRPIPE: c_int = 91; pub const EUSERS: c_int = 68; pub const ENOTSOCK: c_int = 38; pub const EDESTADDRREQ: c_int = 39; pub const EMSGSIZE: c_int = 40; pub const EPROTOTYPE: c_int = 41; pub const ENOPROTOOPT: c_int = 42; pub const EPROTONOSUPPORT: c_int = 43; pub const ESOCKTNOSUPPORT: c_int = 44; pub const EOPNOTSUPP: c_int = 45; pub const EPFNOSUPPORT: c_int = 46; pub const EAFNOSUPPORT: c_int = 47; pub const EADDRINUSE: c_int = 48; pub const EADDRNOTAVAIL: c_int = 49; pub const ENETDOWN: c_int = 50; pub const ENETUNREACH: c_int = 51; pub const ENETRESET: c_int = 52; pub const ECONNABORTED: c_int = 53; pub const ECONNRESET: c_int = 54; pub const ENOBUFS: c_int = 55; pub const EISCONN: c_int = 56; pub const ENOTCONN: c_int = 57; pub const ESHUTDOWN: c_int = 58; pub const ETOOMANYREFS: c_int = 59; pub const ETIMEDOUT: c_int = 60; pub const ECONNREFUSED: c_int = 61; pub const EHOSTDOWN: c_int = 64; pub const EHOSTUNREACH: c_int = 65; pub const EALREADY: c_int = 37; pub const EINPROGRESS: c_int = 36; pub const ESTALE: c_int = 70; pub const EDQUOT: c_int = 69; pub const ENOMEDIUM: c_int = 125; pub const EMEDIUMTYPE: c_int = 126; pub const ECANCELED: c_int = 127; pub const ENOKEY: c_int = 128; pub const EKEYEXPIRED: c_int = 129; pub const EKEYREVOKED: c_int = 130; pub const EKEYREJECTED: c_int = 131; pub const EOWNERDEAD: c_int = 132; pub const ENOTRECOVERABLE: c_int = 133; pub const EHWPOISON: c_int = 135; pub const ERFKILL: c_int = 134; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_SIGINFO: c_int = 0x200; pub const SA_NOCLDWAIT: c_int = 0x100; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 20; pub const SIGBUS: c_int = 10; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGCONT: c_int = 19; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGURG: c_int = 16; pub const SIGIO: c_int = 23; pub const SIGSYS: c_int = 12; pub const SIGPOLL: c_int = 23; pub const SIGPWR: c_int = 29; pub const SIG_SETMASK: c_int = 4; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const POLLWRNORM: c_short = 4; pub const POLLWRBAND: c_short = 0x100; pub const O_ASYNC: c_int = 0x40; pub const O_NDELAY: c_int = 0x4004; pub const EFD_NONBLOCK: c_int = 0x4000; pub const F_GETLK: c_int = 7; pub const F_GETOWN: c_int = 5; pub const F_SETOWN: c_int = 6; pub const SFD_NONBLOCK: c_int = 0x4000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const O_DIRECTORY: c_int = 0o200000; pub const O_NOFOLLOW: c_int = 0o400000; pub const O_LARGEFILE: c_int = 0x40000; pub const O_DIRECT: c_int = 0x100000; pub const MAP_LOCKED: c_int = 0x0100; pub const MAP_NORESERVE: c_int = 0x00040; pub const EDEADLOCK: c_int = 108; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const MCL_CURRENT: c_int = 0x2000; pub const MCL_FUTURE: c_int = 0x4000; pub const MCL_ONFAULT: c_int = 0x8000; pub const SIGSTKSZ: size_t = 16384; pub const MINSIGSTKSZ: size_t = 4096; pub const CBAUD: crate::tcflag_t = 0x0000100f; pub const TAB1: crate::tcflag_t = 0x800; pub const TAB2: crate::tcflag_t = 0x1000; pub const TAB3: crate::tcflag_t = 0x1800; pub const CR1: crate::tcflag_t = 0x200; pub const CR2: crate::tcflag_t = 0x400; pub const CR3: crate::tcflag_t = 0x600; pub const FF1: crate::tcflag_t = 0x8000; pub const BS1: crate::tcflag_t = 0x2000; pub const VT1: crate::tcflag_t = 0x4000; pub const VWERASE: usize = 0xe; pub const VREPRINT: usize = 0xc; pub const VSUSP: usize = 0xa; pub const VSTART: usize = 0x8; pub const VSTOP: usize = 0x9; pub const VDISCARD: usize = 0xd; pub const VTIME: usize = 0x5; pub const IXON: crate::tcflag_t = 0x400; pub const IXOFF: crate::tcflag_t = 0x1000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x30; pub const CS6: crate::tcflag_t = 0x10; pub const CS7: crate::tcflag_t = 0x20; pub const CS8: crate::tcflag_t = 0x30; pub const CSTOPB: crate::tcflag_t = 0x40; pub const CREAD: crate::tcflag_t = 0x80; pub const PARENB: crate::tcflag_t = 0x100; pub const PARODD: crate::tcflag_t = 0x200; pub const HUPCL: crate::tcflag_t = 0x400; pub const CLOCAL: crate::tcflag_t = 0x800; pub const ECHOKE: crate::tcflag_t = 0x800; pub const ECHOE: crate::tcflag_t = 0x10; pub const ECHOK: crate::tcflag_t = 0x20; pub const ECHONL: crate::tcflag_t = 0x40; pub const ECHOPRT: crate::tcflag_t = 0x400; pub const ECHOCTL: crate::tcflag_t = 0x200; pub const ISIG: crate::tcflag_t = 0x1; pub const ICANON: crate::tcflag_t = 0x2; pub const PENDIN: crate::tcflag_t = 0x4000; pub const NOFLSH: crate::tcflag_t = 0x80; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0x00001000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0x1001; pub const B115200: crate::speed_t = 0x1002; pub const B230400: crate::speed_t = 0x1003; pub const B460800: crate::speed_t = 0x1004; pub const B76800: crate::speed_t = 0x1005; pub const B153600: crate::speed_t = 0x1006; pub const B307200: crate::speed_t = 0x1007; pub const B614400: crate::speed_t = 0x1008; pub const B921600: crate::speed_t = 0x1009; pub const B500000: crate::speed_t = 0x100a; pub const B576000: crate::speed_t = 0x100b; pub const B1000000: crate::speed_t = 0x100c; pub const B1152000: crate::speed_t = 0x100d; pub const B1500000: crate::speed_t = 0x100e; pub const B2000000: crate::speed_t = 0x100f; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: crate::tcflag_t = 0x8000; pub const TOSTOP: crate::tcflag_t = 0x100; pub const FLUSHO: crate::tcflag_t = 0x1000; pub const EXTPROC: crate::tcflag_t = 0x10000; pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_wait4: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execv: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_chown: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_brk: c_long = 17; pub const SYS_perfctr: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_capget: c_long = 21; pub const SYS_capset: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_vmsplice: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_sigaltstack: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_lchown32: c_long = 31; pub const SYS_fchown32: c_long = 32; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_chown32: c_long = 35; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_stat: c_long = 38; pub const SYS_sendfile: c_long = 39; pub const SYS_lstat: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_getuid32: c_long = 44; pub const SYS_umount2: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_getgid32: c_long = 53; pub const SYS_ioctl: c_long = 54; pub const SYS_reboot: c_long = 55; pub const SYS_mmap2: c_long = 56; pub const SYS_symlink: c_long = 57; pub const SYS_readlink: c_long = 58; pub const SYS_execve: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_fstat: c_long = 62; pub const SYS_fstat64: c_long = 63; pub const SYS_getpagesize: c_long = 64; pub const SYS_msync: c_long = 65; pub const SYS_vfork: c_long = 66; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_geteuid32: c_long = 69; pub const SYS_getegid32: c_long = 70; pub const SYS_mmap: c_long = 71; pub const SYS_setreuid32: c_long = 72; pub const SYS_munmap: c_long = 73; pub const SYS_mprotect: c_long = 74; pub const SYS_madvise: c_long = 75; pub const SYS_vhangup: c_long = 76; pub const SYS_truncate64: c_long = 77; pub const SYS_mincore: c_long = 78; pub const SYS_getgroups: c_long = 79; pub const SYS_setgroups: c_long = 80; pub const SYS_getpgrp: c_long = 81; pub const SYS_setgroups32: c_long = 82; pub const SYS_setitimer: c_long = 83; pub const SYS_ftruncate64: c_long = 84; pub const SYS_swapon: c_long = 85; pub const SYS_getitimer: c_long = 86; pub const SYS_setuid32: c_long = 87; pub const SYS_sethostname: c_long = 88; pub const SYS_setgid32: c_long = 89; pub const SYS_dup2: c_long = 90; pub const SYS_setfsuid32: c_long = 91; pub const SYS_fcntl: c_long = 92; pub const SYS_select: c_long = 93; pub const SYS_setfsgid32: c_long = 94; pub const SYS_fsync: c_long = 95; pub const SYS_setpriority: c_long = 96; pub const SYS_socket: c_long = 97; pub const SYS_connect: c_long = 98; pub const SYS_accept: c_long = 99; pub const SYS_getpriority: c_long = 100; pub const SYS_rt_sigreturn: c_long = 101; pub const SYS_rt_sigaction: c_long = 102; pub const SYS_rt_sigprocmask: c_long = 103; pub const SYS_rt_sigpending: c_long = 104; pub const SYS_rt_sigtimedwait: c_long = 105; pub const SYS_rt_sigqueueinfo: c_long = 106; pub const SYS_rt_sigsuspend: c_long = 107; pub const SYS_setresuid32: c_long = 108; pub const SYS_getresuid32: c_long = 109; pub const SYS_setresgid32: c_long = 110; pub const SYS_getresgid32: c_long = 111; pub const SYS_setregid32: c_long = 112; pub const SYS_recvmsg: c_long = 113; pub const SYS_sendmsg: c_long = 114; pub const SYS_getgroups32: c_long = 115; pub const SYS_gettimeofday: c_long = 116; pub const SYS_getrusage: c_long = 117; pub const SYS_getsockopt: c_long = 118; pub const SYS_getcwd: c_long = 119; pub const SYS_readv: c_long = 120; pub const SYS_writev: c_long = 121; pub const SYS_settimeofday: c_long = 122; pub const SYS_fchown: c_long = 123; pub const SYS_fchmod: c_long = 124; pub const SYS_recvfrom: c_long = 125; pub const SYS_setreuid: c_long = 126; pub const SYS_setregid: c_long = 127; pub const SYS_rename: c_long = 128; pub const SYS_truncate: c_long = 129; pub const SYS_ftruncate: c_long = 130; pub const SYS_flock: c_long = 131; pub const SYS_lstat64: c_long = 132; pub const SYS_sendto: c_long = 133; pub const SYS_shutdown: c_long = 134; pub const SYS_socketpair: c_long = 135; pub const SYS_mkdir: c_long = 136; pub const SYS_rmdir: c_long = 137; pub const SYS_utimes: c_long = 138; pub const SYS_stat64: c_long = 139; pub const SYS_sendfile64: c_long = 140; pub const SYS_getpeername: c_long = 141; pub const SYS_futex: c_long = 142; pub const SYS_gettid: c_long = 143; pub const SYS_getrlimit: c_long = 144; pub const SYS_setrlimit: c_long = 145; pub const SYS_pivot_root: c_long = 146; pub const SYS_prctl: c_long = 147; pub const SYS_pciconfig_read: c_long = 148; pub const SYS_pciconfig_write: c_long = 149; pub const SYS_getsockname: c_long = 150; pub const SYS_inotify_init: c_long = 151; pub const SYS_inotify_add_watch: c_long = 152; pub const SYS_poll: c_long = 153; pub const SYS_getdents64: c_long = 154; pub const SYS_fcntl64: c_long = 155; pub const SYS_inotify_rm_watch: c_long = 156; pub const SYS_statfs: c_long = 157; pub const SYS_fstatfs: c_long = 158; pub const SYS_umount: c_long = 159; pub const SYS_sched_set_affinity: c_long = 160; pub const SYS_sched_get_affinity: c_long = 161; pub const SYS_getdomainname: c_long = 162; pub const SYS_setdomainname: c_long = 163; pub const SYS_quotactl: c_long = 165; pub const SYS_set_tid_address: c_long = 166; pub const SYS_mount: c_long = 167; pub const SYS_ustat: c_long = 168; pub const SYS_setxattr: c_long = 169; pub const SYS_lsetxattr: c_long = 170; pub const SYS_fsetxattr: c_long = 171; pub const SYS_getxattr: c_long = 172; pub const SYS_lgetxattr: c_long = 173; pub const SYS_getdents: c_long = 174; pub const SYS_setsid: c_long = 175; pub const SYS_fchdir: c_long = 176; pub const SYS_fgetxattr: c_long = 177; pub const SYS_listxattr: c_long = 178; pub const SYS_llistxattr: c_long = 179; pub const SYS_flistxattr: c_long = 180; pub const SYS_removexattr: c_long = 181; pub const SYS_lremovexattr: c_long = 182; pub const SYS_sigpending: c_long = 183; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 184; pub const SYS_setpgid: c_long = 185; pub const SYS_fremovexattr: c_long = 186; pub const SYS_tkill: c_long = 187; pub const SYS_exit_group: c_long = 188; pub const SYS_uname: c_long = 189; pub const SYS_init_module: c_long = 190; pub const SYS_personality: c_long = 191; pub const SYS_remap_file_pages: c_long = 192; pub const SYS_epoll_create: c_long = 193; pub const SYS_epoll_ctl: c_long = 194; pub const SYS_epoll_wait: c_long = 195; pub const SYS_ioprio_set: c_long = 196; pub const SYS_getppid: c_long = 197; pub const SYS_sigaction: c_long = 198; pub const SYS_sgetmask: c_long = 199; pub const SYS_ssetmask: c_long = 200; pub const SYS_sigsuspend: c_long = 201; pub const SYS_oldlstat: c_long = 202; pub const SYS_uselib: c_long = 203; pub const SYS_readdir: c_long = 204; pub const SYS_readahead: c_long = 205; pub const SYS_socketcall: c_long = 206; pub const SYS_syslog: c_long = 207; pub const SYS_lookup_dcookie: c_long = 208; pub const SYS_fadvise64: c_long = 209; pub const SYS_fadvise64_64: c_long = 210; pub const SYS_tgkill: c_long = 211; pub const SYS_waitpid: c_long = 212; pub const SYS_swapoff: c_long = 213; pub const SYS_sysinfo: c_long = 214; pub const SYS_ipc: c_long = 215; pub const SYS_sigreturn: c_long = 216; pub const SYS_clone: c_long = 217; pub const SYS_ioprio_get: c_long = 218; pub const SYS_adjtimex: c_long = 219; pub const SYS_sigprocmask: c_long = 220; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 221; pub const SYS_delete_module: c_long = 222; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 223; pub const SYS_getpgid: c_long = 224; pub const SYS_bdflush: c_long = 225; pub const SYS_sysfs: c_long = 226; pub const SYS_afs_syscall: c_long = 227; pub const SYS_setfsuid: c_long = 228; pub const SYS_setfsgid: c_long = 229; pub const SYS__newselect: c_long = 230; pub const SYS_time: c_long = 231; pub const SYS_splice: c_long = 232; pub const SYS_stime: c_long = 233; pub const SYS_statfs64: c_long = 234; pub const SYS_fstatfs64: c_long = 235; pub const SYS__llseek: c_long = 236; pub const SYS_mlock: c_long = 237; pub const SYS_munlock: c_long = 238; pub const SYS_mlockall: c_long = 239; pub const SYS_munlockall: c_long = 240; pub const SYS_sched_setparam: c_long = 241; pub const SYS_sched_getparam: c_long = 242; pub const SYS_sched_setscheduler: c_long = 243; pub const SYS_sched_getscheduler: c_long = 244; pub const SYS_sched_yield: c_long = 245; pub const SYS_sched_get_priority_max: c_long = 246; pub const SYS_sched_get_priority_min: c_long = 247; pub const SYS_sched_rr_get_interval: c_long = 248; pub const SYS_nanosleep: c_long = 249; pub const SYS_mremap: c_long = 250; pub const SYS__sysctl: c_long = 251; pub const SYS_getsid: c_long = 252; pub const SYS_fdatasync: c_long = 253; pub const SYS_nfsservctl: c_long = 254; pub const SYS_sync_file_range: c_long = 255; pub const SYS_clock_settime: c_long = 256; pub const SYS_clock_gettime: c_long = 257; pub const SYS_clock_getres: c_long = 258; pub const SYS_clock_nanosleep: c_long = 259; pub const SYS_sched_getaffinity: c_long = 260; pub const SYS_sched_setaffinity: c_long = 261; pub const SYS_timer_settime: c_long = 262; pub const SYS_timer_gettime: c_long = 263; pub const SYS_timer_getoverrun: c_long = 264; pub const SYS_timer_delete: c_long = 265; pub const SYS_timer_create: c_long = 266; pub const SYS_io_setup: c_long = 268; pub const SYS_io_destroy: c_long = 269; pub const SYS_io_submit: c_long = 270; pub const SYS_io_cancel: c_long = 271; pub const SYS_io_getevents: c_long = 272; pub const SYS_mq_open: c_long = 273; pub const SYS_mq_unlink: c_long = 274; pub const SYS_mq_timedsend: c_long = 275; pub const SYS_mq_timedreceive: c_long = 276; pub const SYS_mq_notify: c_long = 277; pub const SYS_mq_getsetattr: c_long = 278; pub const SYS_waitid: c_long = 279; pub const SYS_tee: c_long = 280; pub const SYS_add_key: c_long = 281; pub const SYS_request_key: c_long = 282; pub const SYS_keyctl: c_long = 283; pub const SYS_openat: c_long = 284; pub const SYS_mkdirat: c_long = 285; pub const SYS_mknodat: c_long = 286; pub const SYS_fchownat: c_long = 287; pub const SYS_futimesat: c_long = 288; pub const SYS_fstatat64: c_long = 289; pub const SYS_unlinkat: c_long = 290; pub const SYS_renameat: c_long = 291; pub const SYS_linkat: c_long = 292; pub const SYS_symlinkat: c_long = 293; pub const SYS_readlinkat: c_long = 294; pub const SYS_fchmodat: c_long = 295; pub const SYS_faccessat: c_long = 296; pub const SYS_pselect6: c_long = 297; pub const SYS_ppoll: c_long = 298; pub const SYS_unshare: c_long = 299; pub const SYS_set_robust_list: c_long = 300; pub const SYS_get_robust_list: c_long = 301; pub const SYS_migrate_pages: c_long = 302; pub const SYS_mbind: c_long = 303; pub const SYS_get_mempolicy: c_long = 304; pub const SYS_set_mempolicy: c_long = 305; pub const SYS_kexec_load: c_long = 306; pub const SYS_move_pages: c_long = 307; pub const SYS_getcpu: c_long = 308; pub const SYS_epoll_pwait: c_long = 309; pub const SYS_utimensat: c_long = 310; pub const SYS_signalfd: c_long = 311; pub const SYS_timerfd_create: c_long = 312; pub const SYS_eventfd: c_long = 313; pub const SYS_fallocate: c_long = 314; pub const SYS_timerfd_settime: c_long = 315; pub const SYS_timerfd_gettime: c_long = 316; pub const SYS_signalfd4: c_long = 317; pub const SYS_eventfd2: c_long = 318; pub const SYS_epoll_create1: c_long = 319; pub const SYS_dup3: c_long = 320; pub const SYS_pipe2: c_long = 321; pub const SYS_inotify_init1: c_long = 322; pub const SYS_accept4: c_long = 323; pub const SYS_preadv: c_long = 324; pub const SYS_pwritev: c_long = 325; pub const SYS_rt_tgsigqueueinfo: c_long = 326; pub const SYS_perf_event_open: c_long = 327; pub const SYS_recvmmsg: c_long = 328; pub const SYS_fanotify_init: c_long = 329; pub const SYS_fanotify_mark: c_long = 330; pub const SYS_prlimit64: c_long = 331; pub const SYS_name_to_handle_at: c_long = 332; pub const SYS_open_by_handle_at: c_long = 333; pub const SYS_clock_adjtime: c_long = 334; pub const SYS_syncfs: c_long = 335; pub const SYS_sendmmsg: c_long = 336; pub const SYS_setns: c_long = 337; pub const SYS_process_vm_readv: c_long = 338; pub const SYS_process_vm_writev: c_long = 339; pub const SYS_kern_features: c_long = 340; pub const SYS_kcmp: c_long = 341; pub const SYS_finit_module: c_long = 342; pub const SYS_sched_setattr: c_long = 343; pub const SYS_sched_getattr: c_long = 344; pub const SYS_renameat2: c_long = 345; pub const SYS_seccomp: c_long = 346; pub const SYS_getrandom: c_long = 347; pub const SYS_memfd_create: c_long = 348; pub const SYS_bpf: c_long = 349; pub const SYS_execveat: c_long = 350; pub const SYS_membarrier: c_long = 351; pub const SYS_userfaultfd: c_long = 352; pub const SYS_bind: c_long = 353; pub const SYS_listen: c_long = 354; pub const SYS_setsockopt: c_long = 355; pub const SYS_mlock2: c_long = 356; pub const SYS_copy_file_range: c_long = 357; pub const SYS_preadv2: c_long = 358; pub const SYS_pwritev2: c_long = 359; pub const SYS_statx: c_long = 360; pub const SYS_rseq: c_long = 365; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; // Reserved in the kernel, but not actually implemented yet pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; libc/src/unix/linux_like/linux/gnu/b32/mips/0000775000175000017500000000000015105742312020520 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs0000644000175000017500000010013715105742312021645 0ustar bdrungbdrunguse crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = i32; s! { pub struct stat { pub st_dev: c_ulong, st_pad1: [c_long; 3], pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulong, #[cfg(not(gnu_file_offset_bits64))] st_pad2: [c_long; 2], #[cfg(gnu_file_offset_bits64)] st_pad2: [c_long; 3], pub st_size: off_t, #[cfg(not(gnu_file_offset_bits64))] st_pad3: c_long, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, #[cfg(gnu_file_offset_bits64)] st_pad4: c_long, pub st_blocks: crate::blkcnt_t, st_pad5: [c_long; 14], } pub struct stat64 { pub st_dev: c_ulong, st_pad1: [c_long; 3], pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulong, st_pad2: [c_long; 3], pub st_size: off64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, st_pad3: c_long, pub st_blocks: crate::blkcnt64_t, st_pad5: [c_long; 14], } pub struct statfs { pub f_type: c_long, pub f_bsize: c_long, pub f_frsize: c_long, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_files: crate::fsblkcnt_t, pub f_ffree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, pub f_flags: c_long, f_spare: [c_long; 5], } pub struct statfs64 { pub f_type: c_long, pub f_bsize: c_long, pub f_frsize: c_long, pub f_blocks: u64, pub f_bfree: u64, pub f_files: u64, pub f_ffree: u64, pub f_bavail: u64, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, pub f_flags: c_long, pub f_spare: [c_long; 5], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct sigaction { pub sa_flags: c_int, pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_restorer: Option, _resv: [c_int; 1], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, pub _pad: [c_int; 29], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_uint, pub __seq: c_ushort, __pad1: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, #[cfg(target_endian = "big")] __glibc_reserved1: c_ulong, pub msg_stime: crate::time_t, #[cfg(target_endian = "little")] __glibc_reserved1: c_ulong, #[cfg(target_endian = "big")] __glibc_reserved2: c_ulong, pub msg_rtime: crate::time_t, #[cfg(target_endian = "little")] __glibc_reserved2: c_ulong, #[cfg(target_endian = "big")] __glibc_reserved3: c_ulong, pub msg_ctime: crate::time_t, #[cfg(target_endian = "little")] __glibc_reserved3: c_ulong, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, #[cfg(not(gnu_file_offset_bits64))] pub l_sysid: c_long, pub l_pid: crate::pid_t, #[cfg(not(gnu_file_offset_bits64))] __glibc_reserved0: [c_long; 4], } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f32; 4], } } pub const O_LARGEFILE: c_int = 0x2000; pub const SYS_syscall: c_long = 4000 + 0; pub const SYS_exit: c_long = 4000 + 1; pub const SYS_fork: c_long = 4000 + 2; pub const SYS_read: c_long = 4000 + 3; pub const SYS_write: c_long = 4000 + 4; pub const SYS_open: c_long = 4000 + 5; pub const SYS_close: c_long = 4000 + 6; pub const SYS_waitpid: c_long = 4000 + 7; pub const SYS_creat: c_long = 4000 + 8; pub const SYS_link: c_long = 4000 + 9; pub const SYS_unlink: c_long = 4000 + 10; pub const SYS_execve: c_long = 4000 + 11; pub const SYS_chdir: c_long = 4000 + 12; pub const SYS_time: c_long = 4000 + 13; pub const SYS_mknod: c_long = 4000 + 14; pub const SYS_chmod: c_long = 4000 + 15; pub const SYS_lchown: c_long = 4000 + 16; pub const SYS_break: c_long = 4000 + 17; pub const SYS_lseek: c_long = 4000 + 19; pub const SYS_getpid: c_long = 4000 + 20; pub const SYS_mount: c_long = 4000 + 21; pub const SYS_umount: c_long = 4000 + 22; pub const SYS_setuid: c_long = 4000 + 23; pub const SYS_getuid: c_long = 4000 + 24; pub const SYS_stime: c_long = 4000 + 25; pub const SYS_ptrace: c_long = 4000 + 26; pub const SYS_alarm: c_long = 4000 + 27; pub const SYS_pause: c_long = 4000 + 29; pub const SYS_utime: c_long = 4000 + 30; pub const SYS_stty: c_long = 4000 + 31; pub const SYS_gtty: c_long = 4000 + 32; pub const SYS_access: c_long = 4000 + 33; pub const SYS_nice: c_long = 4000 + 34; pub const SYS_ftime: c_long = 4000 + 35; pub const SYS_sync: c_long = 4000 + 36; pub const SYS_kill: c_long = 4000 + 37; pub const SYS_rename: c_long = 4000 + 38; pub const SYS_mkdir: c_long = 4000 + 39; pub const SYS_rmdir: c_long = 4000 + 40; pub const SYS_dup: c_long = 4000 + 41; pub const SYS_pipe: c_long = 4000 + 42; pub const SYS_times: c_long = 4000 + 43; pub const SYS_prof: c_long = 4000 + 44; pub const SYS_brk: c_long = 4000 + 45; pub const SYS_setgid: c_long = 4000 + 46; pub const SYS_getgid: c_long = 4000 + 47; pub const SYS_signal: c_long = 4000 + 48; pub const SYS_geteuid: c_long = 4000 + 49; pub const SYS_getegid: c_long = 4000 + 50; pub const SYS_acct: c_long = 4000 + 51; pub const SYS_umount2: c_long = 4000 + 52; pub const SYS_lock: c_long = 4000 + 53; pub const SYS_ioctl: c_long = 4000 + 54; pub const SYS_fcntl: c_long = 4000 + 55; pub const SYS_mpx: c_long = 4000 + 56; pub const SYS_setpgid: c_long = 4000 + 57; pub const SYS_ulimit: c_long = 4000 + 58; pub const SYS_umask: c_long = 4000 + 60; pub const SYS_chroot: c_long = 4000 + 61; pub const SYS_ustat: c_long = 4000 + 62; pub const SYS_dup2: c_long = 4000 + 63; pub const SYS_getppid: c_long = 4000 + 64; pub const SYS_getpgrp: c_long = 4000 + 65; pub const SYS_setsid: c_long = 4000 + 66; pub const SYS_sigaction: c_long = 4000 + 67; pub const SYS_sgetmask: c_long = 4000 + 68; pub const SYS_ssetmask: c_long = 4000 + 69; pub const SYS_setreuid: c_long = 4000 + 70; pub const SYS_setregid: c_long = 4000 + 71; pub const SYS_sigsuspend: c_long = 4000 + 72; pub const SYS_sigpending: c_long = 4000 + 73; pub const SYS_sethostname: c_long = 4000 + 74; pub const SYS_setrlimit: c_long = 4000 + 75; pub const SYS_getrlimit: c_long = 4000 + 76; pub const SYS_getrusage: c_long = 4000 + 77; pub const SYS_gettimeofday: c_long = 4000 + 78; pub const SYS_settimeofday: c_long = 4000 + 79; pub const SYS_getgroups: c_long = 4000 + 80; pub const SYS_setgroups: c_long = 4000 + 81; pub const SYS_symlink: c_long = 4000 + 83; pub const SYS_readlink: c_long = 4000 + 85; pub const SYS_uselib: c_long = 4000 + 86; pub const SYS_swapon: c_long = 4000 + 87; pub const SYS_reboot: c_long = 4000 + 88; pub const SYS_readdir: c_long = 4000 + 89; pub const SYS_mmap: c_long = 4000 + 90; pub const SYS_munmap: c_long = 4000 + 91; pub const SYS_truncate: c_long = 4000 + 92; pub const SYS_ftruncate: c_long = 4000 + 93; pub const SYS_fchmod: c_long = 4000 + 94; pub const SYS_fchown: c_long = 4000 + 95; pub const SYS_getpriority: c_long = 4000 + 96; pub const SYS_setpriority: c_long = 4000 + 97; pub const SYS_profil: c_long = 4000 + 98; pub const SYS_statfs: c_long = 4000 + 99; pub const SYS_fstatfs: c_long = 4000 + 100; pub const SYS_ioperm: c_long = 4000 + 101; pub const SYS_socketcall: c_long = 4000 + 102; pub const SYS_syslog: c_long = 4000 + 103; pub const SYS_setitimer: c_long = 4000 + 104; pub const SYS_getitimer: c_long = 4000 + 105; pub const SYS_stat: c_long = 4000 + 106; pub const SYS_lstat: c_long = 4000 + 107; pub const SYS_fstat: c_long = 4000 + 108; pub const SYS_iopl: c_long = 4000 + 110; pub const SYS_vhangup: c_long = 4000 + 111; pub const SYS_idle: c_long = 4000 + 112; pub const SYS_vm86: c_long = 4000 + 113; pub const SYS_wait4: c_long = 4000 + 114; pub const SYS_swapoff: c_long = 4000 + 115; pub const SYS_sysinfo: c_long = 4000 + 116; pub const SYS_ipc: c_long = 4000 + 117; pub const SYS_fsync: c_long = 4000 + 118; pub const SYS_sigreturn: c_long = 4000 + 119; pub const SYS_clone: c_long = 4000 + 120; pub const SYS_setdomainname: c_long = 4000 + 121; pub const SYS_uname: c_long = 4000 + 122; pub const SYS_modify_ldt: c_long = 4000 + 123; pub const SYS_adjtimex: c_long = 4000 + 124; pub const SYS_mprotect: c_long = 4000 + 125; pub const SYS_sigprocmask: c_long = 4000 + 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 4000 + 127; pub const SYS_init_module: c_long = 4000 + 128; pub const SYS_delete_module: c_long = 4000 + 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 4000 + 130; pub const SYS_quotactl: c_long = 4000 + 131; pub const SYS_getpgid: c_long = 4000 + 132; pub const SYS_fchdir: c_long = 4000 + 133; pub const SYS_bdflush: c_long = 4000 + 134; pub const SYS_sysfs: c_long = 4000 + 135; pub const SYS_personality: c_long = 4000 + 136; pub const SYS_afs_syscall: c_long = 4000 + 137; pub const SYS_setfsuid: c_long = 4000 + 138; pub const SYS_setfsgid: c_long = 4000 + 139; pub const SYS__llseek: c_long = 4000 + 140; pub const SYS_getdents: c_long = 4000 + 141; pub const SYS__newselect: c_long = 4000 + 142; pub const SYS_flock: c_long = 4000 + 143; pub const SYS_msync: c_long = 4000 + 144; pub const SYS_readv: c_long = 4000 + 145; pub const SYS_writev: c_long = 4000 + 146; pub const SYS_cacheflush: c_long = 4000 + 147; pub const SYS_cachectl: c_long = 4000 + 148; pub const SYS_sysmips: c_long = 4000 + 149; pub const SYS_getsid: c_long = 4000 + 151; pub const SYS_fdatasync: c_long = 4000 + 152; pub const SYS__sysctl: c_long = 4000 + 153; pub const SYS_mlock: c_long = 4000 + 154; pub const SYS_munlock: c_long = 4000 + 155; pub const SYS_mlockall: c_long = 4000 + 156; pub const SYS_munlockall: c_long = 4000 + 157; pub const SYS_sched_setparam: c_long = 4000 + 158; pub const SYS_sched_getparam: c_long = 4000 + 159; pub const SYS_sched_setscheduler: c_long = 4000 + 160; pub const SYS_sched_getscheduler: c_long = 4000 + 161; pub const SYS_sched_yield: c_long = 4000 + 162; pub const SYS_sched_get_priority_max: c_long = 4000 + 163; pub const SYS_sched_get_priority_min: c_long = 4000 + 164; pub const SYS_sched_rr_get_interval: c_long = 4000 + 165; pub const SYS_nanosleep: c_long = 4000 + 166; pub const SYS_mremap: c_long = 4000 + 167; pub const SYS_accept: c_long = 4000 + 168; pub const SYS_bind: c_long = 4000 + 169; pub const SYS_connect: c_long = 4000 + 170; pub const SYS_getpeername: c_long = 4000 + 171; pub const SYS_getsockname: c_long = 4000 + 172; pub const SYS_getsockopt: c_long = 4000 + 173; pub const SYS_listen: c_long = 4000 + 174; pub const SYS_recv: c_long = 4000 + 175; pub const SYS_recvfrom: c_long = 4000 + 176; pub const SYS_recvmsg: c_long = 4000 + 177; pub const SYS_send: c_long = 4000 + 178; pub const SYS_sendmsg: c_long = 4000 + 179; pub const SYS_sendto: c_long = 4000 + 180; pub const SYS_setsockopt: c_long = 4000 + 181; pub const SYS_shutdown: c_long = 4000 + 182; pub const SYS_socket: c_long = 4000 + 183; pub const SYS_socketpair: c_long = 4000 + 184; pub const SYS_setresuid: c_long = 4000 + 185; pub const SYS_getresuid: c_long = 4000 + 186; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 4000 + 187; pub const SYS_poll: c_long = 4000 + 188; pub const SYS_nfsservctl: c_long = 4000 + 189; pub const SYS_setresgid: c_long = 4000 + 190; pub const SYS_getresgid: c_long = 4000 + 191; pub const SYS_prctl: c_long = 4000 + 192; pub const SYS_rt_sigreturn: c_long = 4000 + 193; pub const SYS_rt_sigaction: c_long = 4000 + 194; pub const SYS_rt_sigprocmask: c_long = 4000 + 195; pub const SYS_rt_sigpending: c_long = 4000 + 196; pub const SYS_rt_sigtimedwait: c_long = 4000 + 197; pub const SYS_rt_sigqueueinfo: c_long = 4000 + 198; pub const SYS_rt_sigsuspend: c_long = 4000 + 199; pub const SYS_pread64: c_long = 4000 + 200; pub const SYS_pwrite64: c_long = 4000 + 201; pub const SYS_chown: c_long = 4000 + 202; pub const SYS_getcwd: c_long = 4000 + 203; pub const SYS_capget: c_long = 4000 + 204; pub const SYS_capset: c_long = 4000 + 205; pub const SYS_sigaltstack: c_long = 4000 + 206; pub const SYS_sendfile: c_long = 4000 + 207; pub const SYS_getpmsg: c_long = 4000 + 208; pub const SYS_putpmsg: c_long = 4000 + 209; pub const SYS_mmap2: c_long = 4000 + 210; pub const SYS_truncate64: c_long = 4000 + 211; pub const SYS_ftruncate64: c_long = 4000 + 212; pub const SYS_stat64: c_long = 4000 + 213; pub const SYS_lstat64: c_long = 4000 + 214; pub const SYS_fstat64: c_long = 4000 + 215; pub const SYS_pivot_root: c_long = 4000 + 216; pub const SYS_mincore: c_long = 4000 + 217; pub const SYS_madvise: c_long = 4000 + 218; pub const SYS_getdents64: c_long = 4000 + 219; pub const SYS_fcntl64: c_long = 4000 + 220; pub const SYS_gettid: c_long = 4000 + 222; pub const SYS_readahead: c_long = 4000 + 223; pub const SYS_setxattr: c_long = 4000 + 224; pub const SYS_lsetxattr: c_long = 4000 + 225; pub const SYS_fsetxattr: c_long = 4000 + 226; pub const SYS_getxattr: c_long = 4000 + 227; pub const SYS_lgetxattr: c_long = 4000 + 228; pub const SYS_fgetxattr: c_long = 4000 + 229; pub const SYS_listxattr: c_long = 4000 + 230; pub const SYS_llistxattr: c_long = 4000 + 231; pub const SYS_flistxattr: c_long = 4000 + 232; pub const SYS_removexattr: c_long = 4000 + 233; pub const SYS_lremovexattr: c_long = 4000 + 234; pub const SYS_fremovexattr: c_long = 4000 + 235; pub const SYS_tkill: c_long = 4000 + 236; pub const SYS_sendfile64: c_long = 4000 + 237; pub const SYS_futex: c_long = 4000 + 238; pub const SYS_sched_setaffinity: c_long = 4000 + 239; pub const SYS_sched_getaffinity: c_long = 4000 + 240; pub const SYS_io_setup: c_long = 4000 + 241; pub const SYS_io_destroy: c_long = 4000 + 242; pub const SYS_io_getevents: c_long = 4000 + 243; pub const SYS_io_submit: c_long = 4000 + 244; pub const SYS_io_cancel: c_long = 4000 + 245; pub const SYS_exit_group: c_long = 4000 + 246; pub const SYS_lookup_dcookie: c_long = 4000 + 247; pub const SYS_epoll_create: c_long = 4000 + 248; pub const SYS_epoll_ctl: c_long = 4000 + 249; pub const SYS_epoll_wait: c_long = 4000 + 250; pub const SYS_remap_file_pages: c_long = 4000 + 251; pub const SYS_set_tid_address: c_long = 4000 + 252; pub const SYS_restart_syscall: c_long = 4000 + 253; pub const SYS_fadvise64: c_long = 4000 + 254; pub const SYS_statfs64: c_long = 4000 + 255; pub const SYS_fstatfs64: c_long = 4000 + 256; pub const SYS_timer_create: c_long = 4000 + 257; pub const SYS_timer_settime: c_long = 4000 + 258; pub const SYS_timer_gettime: c_long = 4000 + 259; pub const SYS_timer_getoverrun: c_long = 4000 + 260; pub const SYS_timer_delete: c_long = 4000 + 261; pub const SYS_clock_settime: c_long = 4000 + 262; pub const SYS_clock_gettime: c_long = 4000 + 263; pub const SYS_clock_getres: c_long = 4000 + 264; pub const SYS_clock_nanosleep: c_long = 4000 + 265; pub const SYS_tgkill: c_long = 4000 + 266; pub const SYS_utimes: c_long = 4000 + 267; pub const SYS_mbind: c_long = 4000 + 268; pub const SYS_get_mempolicy: c_long = 4000 + 269; pub const SYS_set_mempolicy: c_long = 4000 + 270; pub const SYS_mq_open: c_long = 4000 + 271; pub const SYS_mq_unlink: c_long = 4000 + 272; pub const SYS_mq_timedsend: c_long = 4000 + 273; pub const SYS_mq_timedreceive: c_long = 4000 + 274; pub const SYS_mq_notify: c_long = 4000 + 275; pub const SYS_mq_getsetattr: c_long = 4000 + 276; pub const SYS_vserver: c_long = 4000 + 277; pub const SYS_waitid: c_long = 4000 + 278; /* pub const SYS_sys_setaltroot: c_long = 4000 + 279; */ pub const SYS_add_key: c_long = 4000 + 280; pub const SYS_request_key: c_long = 4000 + 281; pub const SYS_keyctl: c_long = 4000 + 282; pub const SYS_set_thread_area: c_long = 4000 + 283; pub const SYS_inotify_init: c_long = 4000 + 284; pub const SYS_inotify_add_watch: c_long = 4000 + 285; pub const SYS_inotify_rm_watch: c_long = 4000 + 286; pub const SYS_migrate_pages: c_long = 4000 + 287; pub const SYS_openat: c_long = 4000 + 288; pub const SYS_mkdirat: c_long = 4000 + 289; pub const SYS_mknodat: c_long = 4000 + 290; pub const SYS_fchownat: c_long = 4000 + 291; pub const SYS_futimesat: c_long = 4000 + 292; pub const SYS_fstatat64: c_long = 4000 + 293; pub const SYS_unlinkat: c_long = 4000 + 294; pub const SYS_renameat: c_long = 4000 + 295; pub const SYS_linkat: c_long = 4000 + 296; pub const SYS_symlinkat: c_long = 4000 + 297; pub const SYS_readlinkat: c_long = 4000 + 298; pub const SYS_fchmodat: c_long = 4000 + 299; pub const SYS_faccessat: c_long = 4000 + 300; pub const SYS_pselect6: c_long = 4000 + 301; pub const SYS_ppoll: c_long = 4000 + 302; pub const SYS_unshare: c_long = 4000 + 303; pub const SYS_splice: c_long = 4000 + 304; pub const SYS_sync_file_range: c_long = 4000 + 305; pub const SYS_tee: c_long = 4000 + 306; pub const SYS_vmsplice: c_long = 4000 + 307; pub const SYS_move_pages: c_long = 4000 + 308; pub const SYS_set_robust_list: c_long = 4000 + 309; pub const SYS_get_robust_list: c_long = 4000 + 310; pub const SYS_kexec_load: c_long = 4000 + 311; pub const SYS_getcpu: c_long = 4000 + 312; pub const SYS_epoll_pwait: c_long = 4000 + 313; pub const SYS_ioprio_set: c_long = 4000 + 314; pub const SYS_ioprio_get: c_long = 4000 + 315; pub const SYS_utimensat: c_long = 4000 + 316; pub const SYS_signalfd: c_long = 4000 + 317; pub const SYS_timerfd: c_long = 4000 + 318; pub const SYS_eventfd: c_long = 4000 + 319; pub const SYS_fallocate: c_long = 4000 + 320; pub const SYS_timerfd_create: c_long = 4000 + 321; pub const SYS_timerfd_gettime: c_long = 4000 + 322; pub const SYS_timerfd_settime: c_long = 4000 + 323; pub const SYS_signalfd4: c_long = 4000 + 324; pub const SYS_eventfd2: c_long = 4000 + 325; pub const SYS_epoll_create1: c_long = 4000 + 326; pub const SYS_dup3: c_long = 4000 + 327; pub const SYS_pipe2: c_long = 4000 + 328; pub const SYS_inotify_init1: c_long = 4000 + 329; pub const SYS_preadv: c_long = 4000 + 330; pub const SYS_pwritev: c_long = 4000 + 331; pub const SYS_rt_tgsigqueueinfo: c_long = 4000 + 332; pub const SYS_perf_event_open: c_long = 4000 + 333; pub const SYS_accept4: c_long = 4000 + 334; pub const SYS_recvmmsg: c_long = 4000 + 335; pub const SYS_fanotify_init: c_long = 4000 + 336; pub const SYS_fanotify_mark: c_long = 4000 + 337; pub const SYS_prlimit64: c_long = 4000 + 338; pub const SYS_name_to_handle_at: c_long = 4000 + 339; pub const SYS_open_by_handle_at: c_long = 4000 + 340; pub const SYS_clock_adjtime: c_long = 4000 + 341; pub const SYS_syncfs: c_long = 4000 + 342; pub const SYS_sendmmsg: c_long = 4000 + 343; pub const SYS_setns: c_long = 4000 + 344; pub const SYS_process_vm_readv: c_long = 4000 + 345; pub const SYS_process_vm_writev: c_long = 4000 + 346; pub const SYS_kcmp: c_long = 4000 + 347; pub const SYS_finit_module: c_long = 4000 + 348; pub const SYS_sched_setattr: c_long = 4000 + 349; pub const SYS_sched_getattr: c_long = 4000 + 350; pub const SYS_renameat2: c_long = 4000 + 351; pub const SYS_seccomp: c_long = 4000 + 352; pub const SYS_getrandom: c_long = 4000 + 353; pub const SYS_memfd_create: c_long = 4000 + 354; pub const SYS_bpf: c_long = 4000 + 355; pub const SYS_execveat: c_long = 4000 + 356; pub const SYS_userfaultfd: c_long = 4000 + 357; pub const SYS_membarrier: c_long = 4000 + 358; pub const SYS_mlock2: c_long = 4000 + 359; pub const SYS_copy_file_range: c_long = 4000 + 360; pub const SYS_preadv2: c_long = 4000 + 361; pub const SYS_pwritev2: c_long = 4000 + 362; pub const SYS_pkey_mprotect: c_long = 4000 + 363; pub const SYS_pkey_alloc: c_long = 4000 + 364; pub const SYS_pkey_free: c_long = 4000 + 365; pub const SYS_statx: c_long = 4000 + 366; pub const SYS_rseq: c_long = 4000 + 367; pub const SYS_pidfd_send_signal: c_long = 4000 + 424; pub const SYS_io_uring_setup: c_long = 4000 + 425; pub const SYS_io_uring_enter: c_long = 4000 + 426; pub const SYS_io_uring_register: c_long = 4000 + 427; pub const SYS_open_tree: c_long = 4000 + 428; pub const SYS_move_mount: c_long = 4000 + 429; pub const SYS_fsopen: c_long = 4000 + 430; pub const SYS_fsconfig: c_long = 4000 + 431; pub const SYS_fsmount: c_long = 4000 + 432; pub const SYS_fspick: c_long = 4000 + 433; pub const SYS_pidfd_open: c_long = 4000 + 434; pub const SYS_clone3: c_long = 4000 + 435; pub const SYS_close_range: c_long = 4000 + 436; pub const SYS_openat2: c_long = 4000 + 437; pub const SYS_pidfd_getfd: c_long = 4000 + 438; pub const SYS_faccessat2: c_long = 4000 + 439; pub const SYS_process_madvise: c_long = 4000 + 440; pub const SYS_epoll_pwait2: c_long = 4000 + 441; pub const SYS_mount_setattr: c_long = 4000 + 442; pub const SYS_quotactl_fd: c_long = 4000 + 443; pub const SYS_landlock_create_ruleset: c_long = 4000 + 444; pub const SYS_landlock_add_rule: c_long = 4000 + 445; pub const SYS_landlock_restrict_self: c_long = 4000 + 446; pub const SYS_memfd_secret: c_long = 4000 + 447; pub const SYS_process_mrelease: c_long = 4000 + 448; pub const SYS_futex_waitv: c_long = 4000 + 449; pub const SYS_set_mempolicy_home_node: c_long = 4000 + 450; pub const O_DIRECT: c_int = 0x8000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_APPEND: c_int = 8; pub const O_CREAT: c_int = 256; pub const O_EXCL: c_int = 1024; pub const O_NOCTTY: c_int = 2048; pub const O_NONBLOCK: c_int = 128; pub const O_SYNC: c_int = 0x4010; pub const O_RSYNC: c_int = 0x4010; pub const O_DSYNC: c_int = 0x10; pub const O_FSYNC: c_int = 0x4010; pub const O_ASYNC: c_int = 0x1000; pub const O_NDELAY: c_int = 0x80; pub const EDEADLK: c_int = 45; pub const ENAMETOOLONG: c_int = 78; pub const ENOLCK: c_int = 46; pub const ENOSYS: c_int = 89; pub const ENOTEMPTY: c_int = 93; pub const ELOOP: c_int = 90; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EBADE: c_int = 50; pub const EBADR: c_int = 51; pub const EXFULL: c_int = 52; pub const ENOANO: c_int = 53; pub const EBADRQC: c_int = 54; pub const EBADSLT: c_int = 55; pub const EDEADLOCK: c_int = 56; pub const EMULTIHOP: c_int = 74; pub const EOVERFLOW: c_int = 79; pub const ENOTUNIQ: c_int = 80; pub const EBADFD: c_int = 81; pub const EBADMSG: c_int = 77; pub const EREMCHG: c_int = 82; pub const ELIBACC: c_int = 83; pub const ELIBBAD: c_int = 84; pub const ELIBSCN: c_int = 85; pub const ELIBMAX: c_int = 86; pub const ELIBEXEC: c_int = 87; pub const EILSEQ: c_int = 88; pub const ERESTART: c_int = 91; pub const ESTRPIPE: c_int = 92; pub const EUSERS: c_int = 94; pub const ENOTSOCK: c_int = 95; pub const EDESTADDRREQ: c_int = 96; pub const EMSGSIZE: c_int = 97; pub const EPROTOTYPE: c_int = 98; pub const ENOPROTOOPT: c_int = 99; pub const EPROTONOSUPPORT: c_int = 120; pub const ESOCKTNOSUPPORT: c_int = 121; pub const EOPNOTSUPP: c_int = 122; pub const EPFNOSUPPORT: c_int = 123; pub const EAFNOSUPPORT: c_int = 124; pub const EADDRINUSE: c_int = 125; pub const EADDRNOTAVAIL: c_int = 126; pub const ENETDOWN: c_int = 127; pub const ENETUNREACH: c_int = 128; pub const ENETRESET: c_int = 129; pub const ECONNABORTED: c_int = 130; pub const ECONNRESET: c_int = 131; pub const ENOBUFS: c_int = 132; pub const EISCONN: c_int = 133; pub const ENOTCONN: c_int = 134; pub const ESHUTDOWN: c_int = 143; pub const ETOOMANYREFS: c_int = 144; pub const ETIMEDOUT: c_int = 145; pub const ECONNREFUSED: c_int = 146; pub const EHOSTDOWN: c_int = 147; pub const EHOSTUNREACH: c_int = 148; pub const EALREADY: c_int = 149; pub const EINPROGRESS: c_int = 150; pub const ESTALE: c_int = 151; pub const EUCLEAN: c_int = 135; pub const ENOTNAM: c_int = 137; pub const ENAVAIL: c_int = 138; pub const EISNAM: c_int = 139; pub const EREMOTEIO: c_int = 140; pub const EDQUOT: c_int = 1133; pub const ENOMEDIUM: c_int = 159; pub const EMEDIUMTYPE: c_int = 160; pub const ECANCELED: c_int = 158; pub const ENOKEY: c_int = 161; pub const EKEYEXPIRED: c_int = 162; pub const EKEYREVOKED: c_int = 163; pub const EKEYREJECTED: c_int = 164; pub const EOWNERDEAD: c_int = 165; pub const ENOTRECOVERABLE: c_int = 166; pub const ERFKILL: c_int = 167; pub const MAP_NORESERVE: c_int = 0x400; pub const MAP_ANON: c_int = 0x800; pub const MAP_ANONYMOUS: c_int = 0x800; pub const MAP_GROWSDOWN: c_int = 0x1000; pub const MAP_DENYWRITE: c_int = 0x2000; pub const MAP_EXECUTABLE: c_int = 0x4000; pub const MAP_LOCKED: c_int = 0x8000; pub const MAP_POPULATE: c_int = 0x10000; pub const MAP_NONBLOCK: c_int = 0x20000; pub const MAP_STACK: c_int = 0x40000; pub const SOCK_STREAM: c_int = 2; pub const SOCK_DGRAM: c_int = 1; pub const SA_SIGINFO: c_int = 0x00000008; pub const SA_NOCLDWAIT: c_int = 0x00010000; pub const SIGCHLD: c_int = 18; pub const SIGBUS: c_int = 10; pub const SIGTTIN: c_int = 26; pub const SIGTTOU: c_int = 27; pub const SIGXCPU: c_int = 30; pub const SIGXFSZ: c_int = 31; pub const SIGVTALRM: c_int = 28; pub const SIGPROF: c_int = 29; pub const SIGWINCH: c_int = 20; pub const SIGUSR1: c_int = 16; pub const SIGUSR2: c_int = 17; pub const SIGCONT: c_int = 25; pub const SIGSTOP: c_int = 23; pub const SIGTSTP: c_int = 24; pub const SIGURG: c_int = 21; pub const SIGIO: c_int = 22; pub const SIGSYS: c_int = 12; pub const SIGPOLL: c_int = 22; pub const SIGPWR: c_int = 19; pub const SIG_SETMASK: c_int = 3; pub const SIG_BLOCK: c_int = 0x1; pub const SIG_UNBLOCK: c_int = 0x2; pub const POLLWRNORM: c_short = 0x004; pub const POLLWRBAND: c_short = 0x100; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: crate::tcflag_t = 0x00000100; pub const TOSTOP: crate::tcflag_t = 0x00008000; pub const FLUSHO: crate::tcflag_t = 0x00002000; pub const EXTPROC: crate::tcflag_t = 0o200000; pub const TCSANOW: c_int = 0x540e; pub const TCSADRAIN: c_int = 0x540f; pub const TCSAFLUSH: c_int = 0x5410; pub const PTRACE_GETFPXREGS: c_uint = 18; pub const PTRACE_SETFPXREGS: c_uint = 19; pub const MAP_HUGETLB: c_int = 0x080000; pub const EFD_NONBLOCK: c_int = 0x80; cfg_if! { if #[cfg(gnu_file_offset_bits64)] { pub const F_GETLK: c_int = 33; } else { pub const F_GETLK: c_int = 14; } } pub const F_GETOWN: c_int = 23; pub const F_SETOWN: c_int = 24; pub const SFD_NONBLOCK: c_int = 0x80; pub const RTLD_DEEPBIND: c_int = 0x10; pub const RTLD_GLOBAL: c_int = 0x4; pub const RTLD_NOLOAD: c_int = 0x8; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const EHWPOISON: c_int = 168; libc/src/unix/linux_like/linux/gnu/b32/riscv32/0000775000175000017500000000000015105742312021043 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs0000644000175000017500000006613115105742312022175 0ustar bdrungbdrung//! RISC-V-specific definitions for 32-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = c_int; s! { pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct statfs { pub f_type: c_long, pub f_bsize: c_long, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, pub f_frsize: c_long, pub f_flags: c_long, pub f_spare: [c_long; 4], } pub struct statfs64 { pub f_type: c_long, pub f_bsize: c_long, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, pub f_frsize: c_long, pub f_flags: c_long, pub f_spare: [c_long; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_favail: crate::fsfilcnt64_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, pub __f_spare: [c_int; 6], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [u64; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused5: c_ulong, __unused6: c_ulong, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct user_regs_struct { pub pc: c_ulong, pub ra: c_ulong, pub sp: c_ulong, pub gp: c_ulong, pub tp: c_ulong, pub t0: c_ulong, pub t1: c_ulong, pub t2: c_ulong, pub s0: c_ulong, pub s1: c_ulong, pub a0: c_ulong, pub a1: c_ulong, pub a2: c_ulong, pub a3: c_ulong, pub a4: c_ulong, pub a5: c_ulong, pub a6: c_ulong, pub a7: c_ulong, pub s2: c_ulong, pub s3: c_ulong, pub s4: c_ulong, pub s5: c_ulong, pub s6: c_ulong, pub s7: c_ulong, pub s8: c_ulong, pub s9: c_ulong, pub s10: c_ulong, pub s11: c_ulong, pub t3: c_ulong, pub t4: c_ulong, pub t5: c_ulong, pub t6: c_ulong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct ucontext_t { pub __uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct mcontext_t { pub __gregs: [c_ulong; 32], pub __fpregs: __riscv_mc_fp_state, } pub union __riscv_mc_fp_state { pub __f: __riscv_mc_f_ext_state, pub __d: __riscv_mc_d_ext_state, pub __q: __riscv_mc_q_ext_state, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_f_ext_state { pub __f: [c_uint; 32], pub __fcsr: c_uint, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_d_ext_state { pub __f: [c_ulonglong; 32], pub __fcsr: c_uint, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct __riscv_mc_q_ext_state { pub __f: [c_ulonglong; 64], pub __fcsr: c_uint, pub __glibc_reserved: [c_uint; 3], } } pub const O_LARGEFILE: c_int = 0; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 1052672; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 256; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_SIGINFO: c_int = 4; pub const SA_NOCLDWAIT: c_int = 2; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0; pub const SIG_UNBLOCK: c_int = 1; pub const POLLWRNORM: c_short = 256; pub const POLLWRBAND: c_short = 512; pub const O_ASYNC: c_int = 8192; pub const O_NDELAY: c_int = 2048; pub const EFD_NONBLOCK: c_int = 2048; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const SFD_NONBLOCK: c_int = 2048; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const O_DIRECT: c_int = 16384; pub const O_DIRECTORY: c_int = 65536; pub const O_NOFOLLOW: c_int = 131072; pub const MAP_HUGETLB: c_int = 262144; pub const MAP_LOCKED: c_int = 8192; pub const MAP_NORESERVE: c_int = 16384; pub const MAP_ANON: c_int = 32; pub const MAP_ANONYMOUS: c_int = 32; pub const MAP_DENYWRITE: c_int = 2048; pub const MAP_EXECUTABLE: c_int = 4096; pub const MAP_POPULATE: c_int = 32768; pub const MAP_NONBLOCK: c_int = 65536; pub const MAP_STACK: c_int = 131072; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const MCL_CURRENT: c_int = 1; pub const MCL_FUTURE: c_int = 2; pub const MCL_ONFAULT: c_int = 4; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 4111; pub const TAB1: crate::tcflag_t = 2048; pub const TAB2: crate::tcflag_t = 4096; pub const TAB3: crate::tcflag_t = 6144; pub const CR1: crate::tcflag_t = 512; pub const CR2: crate::tcflag_t = 1024; pub const CR3: crate::tcflag_t = 1536; pub const FF1: crate::tcflag_t = 32768; pub const BS1: crate::tcflag_t = 8192; pub const VT1: crate::tcflag_t = 16384; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 1024; pub const IXOFF: crate::tcflag_t = 4096; pub const ONLCR: crate::tcflag_t = 4; pub const CSIZE: crate::tcflag_t = 48; pub const CS6: crate::tcflag_t = 16; pub const CS7: crate::tcflag_t = 32; pub const CS8: crate::tcflag_t = 48; pub const CSTOPB: crate::tcflag_t = 64; pub const CREAD: crate::tcflag_t = 128; pub const PARENB: crate::tcflag_t = 256; pub const PARODD: crate::tcflag_t = 512; pub const HUPCL: crate::tcflag_t = 1024; pub const CLOCAL: crate::tcflag_t = 2048; pub const ECHOKE: crate::tcflag_t = 2048; pub const ECHOE: crate::tcflag_t = 16; pub const ECHOK: crate::tcflag_t = 32; pub const ECHONL: crate::tcflag_t = 64; pub const ECHOPRT: crate::tcflag_t = 1024; pub const ECHOCTL: crate::tcflag_t = 512; pub const ISIG: crate::tcflag_t = 1; pub const ICANON: crate::tcflag_t = 2; pub const PENDIN: crate::tcflag_t = 16384; pub const NOFLSH: crate::tcflag_t = 128; pub const CIBAUD: crate::tcflag_t = 269418496; pub const CBAUDEX: crate::tcflag_t = 4096; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 2; pub const NLDLY: crate::tcflag_t = 256; pub const CRDLY: crate::tcflag_t = 1536; pub const TABDLY: crate::tcflag_t = 6144; pub const BSDLY: crate::tcflag_t = 8192; pub const FFDLY: crate::tcflag_t = 32768; pub const VTDLY: crate::tcflag_t = 16384; pub const XTABS: crate::tcflag_t = 6144; pub const B0: crate::speed_t = 0; pub const B50: crate::speed_t = 1; pub const B75: crate::speed_t = 2; pub const B110: crate::speed_t = 3; pub const B134: crate::speed_t = 4; pub const B150: crate::speed_t = 5; pub const B200: crate::speed_t = 6; pub const B300: crate::speed_t = 7; pub const B600: crate::speed_t = 8; pub const B1200: crate::speed_t = 9; pub const B1800: crate::speed_t = 10; pub const B2400: crate::speed_t = 11; pub const B4800: crate::speed_t = 12; pub const B9600: crate::speed_t = 13; pub const B19200: crate::speed_t = 14; pub const B38400: crate::speed_t = 15; pub const EXTA: crate::speed_t = 14; pub const EXTB: crate::speed_t = 15; pub const B57600: crate::speed_t = 4097; pub const B115200: crate::speed_t = 4098; pub const B230400: crate::speed_t = 4099; pub const B460800: crate::speed_t = 4100; pub const B500000: crate::speed_t = 4101; pub const B576000: crate::speed_t = 4102; pub const B921600: crate::speed_t = 4103; pub const B1000000: crate::speed_t = 4104; pub const B1152000: crate::speed_t = 4105; pub const B1500000: crate::speed_t = 4106; pub const B2000000: crate::speed_t = 4107; pub const B2500000: crate::speed_t = 4108; pub const B3000000: crate::speed_t = 4109; pub const B3500000: crate::speed_t = 4110; pub const B4000000: crate::speed_t = 4111; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 32768; pub const TOSTOP: crate::tcflag_t = 256; pub const FLUSHO: crate::tcflag_t = 4096; pub const EXTPROC: crate::tcflag_t = 65536; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const NGREG: usize = 32; pub const REG_PC: usize = 0; pub const REG_RA: usize = 1; pub const REG_SP: usize = 2; pub const REG_TP: usize = 4; pub const REG_S0: usize = 8; pub const REG_S1: usize = 9; pub const REG_A0: usize = 10; pub const REG_S2: usize = 18; pub const REG_NARGS: usize = 8; pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_close: c_long = 57; pub const SYS_fstat: c_long = 80; pub const SYS_lseek: c_long = 62; pub const SYS_mmap: c_long = 222; pub const SYS_mprotect: c_long = 226; pub const SYS_munmap: c_long = 215; pub const SYS_brk: c_long = 214; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_ioctl: c_long = 29; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_sched_yield: c_long = 124; pub const SYS_mremap: c_long = 216; pub const SYS_msync: c_long = 227; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_shmget: c_long = 194; pub const SYS_shmat: c_long = 196; pub const SYS_shmctl: c_long = 195; pub const SYS_dup: c_long = 23; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_getpid: c_long = 172; pub const SYS_sendfile: c_long = 71; pub const SYS_socket: c_long = 198; pub const SYS_connect: c_long = 203; pub const SYS_accept: c_long = 202; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_shutdown: c_long = 210; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_socketpair: c_long = 199; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_exit: c_long = 93; pub const SYS_wait4: c_long = 260; pub const SYS_kill: c_long = 129; pub const SYS_uname: c_long = 160; pub const SYS_semget: c_long = 190; pub const SYS_semop: c_long = 193; pub const SYS_semctl: c_long = 191; pub const SYS_shmdt: c_long = 197; pub const SYS_msgget: c_long = 186; pub const SYS_msgsnd: c_long = 189; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgctl: c_long = 187; pub const SYS_fcntl: c_long = 25; pub const SYS_flock: c_long = 32; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_getcwd: c_long = 17; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_fchmod: c_long = 52; pub const SYS_fchown: c_long = 55; pub const SYS_umask: c_long = 166; pub const SYS_gettimeofday: c_long = 169; pub const SYS_getrlimit: c_long = 163; pub const SYS_getrusage: c_long = 165; pub const SYS_sysinfo: c_long = 179; pub const SYS_times: c_long = 153; pub const SYS_ptrace: c_long = 117; pub const SYS_getuid: c_long = 174; pub const SYS_syslog: c_long = 116; pub const SYS_getgid: c_long = 176; pub const SYS_setuid: c_long = 146; pub const SYS_setgid: c_long = 144; pub const SYS_geteuid: c_long = 175; pub const SYS_getegid: c_long = 177; pub const SYS_setpgid: c_long = 154; pub const SYS_getppid: c_long = 173; pub const SYS_setsid: c_long = 157; pub const SYS_setreuid: c_long = 145; pub const SYS_setregid: c_long = 143; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_getpgid: c_long = 155; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_getsid: c_long = 156; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_sigaltstack: c_long = 132; pub const SYS_personality: c_long = 92; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_getpriority: c_long = 141; pub const SYS_setpriority: c_long = 140; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_vhangup: c_long = 58; pub const SYS_pivot_root: c_long = 41; pub const SYS_prctl: c_long = 167; pub const SYS_adjtimex: c_long = 171; pub const SYS_setrlimit: c_long = 164; pub const SYS_chroot: c_long = 51; pub const SYS_sync: c_long = 81; pub const SYS_acct: c_long = 89; pub const SYS_settimeofday: c_long = 170; pub const SYS_mount: c_long = 40; pub const SYS_umount2: c_long = 39; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_reboot: c_long = 142; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_quotactl: c_long = 60; pub const SYS_nfsservctl: c_long = 42; pub const SYS_gettid: c_long = 178; pub const SYS_readahead: c_long = 213; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_tkill: c_long = 130; pub const SYS_futex: c_long = 98; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_getevents: c_long = 4; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_getdents64: c_long = 61; pub const SYS_set_tid_address: c_long = 96; pub const SYS_restart_syscall: c_long = 128; pub const SYS_semtimedop: c_long = 192; pub const SYS_fadvise64: c_long = 223; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_exit_group: c_long = 94; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_tgkill: c_long = 131; pub const SYS_mbind: c_long = 235; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_kexec_load: c_long = 104; pub const SYS_waitid: c_long = 95; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_migrate_pages: c_long = 238; pub const SYS_openat: c_long = 56; pub const SYS_mkdirat: c_long = 34; pub const SYS_mknodat: c_long = 33; pub const SYS_fchownat: c_long = 54; pub const SYS_newfstatat: c_long = 79; pub const SYS_unlinkat: c_long = 35; pub const SYS_linkat: c_long = 37; pub const SYS_symlinkat: c_long = 36; pub const SYS_readlinkat: c_long = 78; pub const SYS_fchmodat: c_long = 53; pub const SYS_faccessat: c_long = 48; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_unshare: c_long = 97; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_sync_file_range: c_long = 84; pub const SYS_vmsplice: c_long = 75; pub const SYS_move_pages: c_long = 239; pub const SYS_utimensat: c_long = 88; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_timerfd_create: c_long = 85; pub const SYS_fallocate: c_long = 47; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_accept4: c_long = 242; pub const SYS_signalfd4: c_long = 74; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_dup3: c_long = 24; pub const SYS_pipe2: c_long = 59; pub const SYS_inotify_init1: c_long = 26; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_recvmmsg: c_long = 243; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_prlimit64: c_long = 261; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_sendmmsg: c_long = 269; pub const SYS_setns: c_long = 268; pub const SYS_getcpu: c_long = 168; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_rseq: c_long = 293; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; libc/src/unix/linux_like/linux/gnu/b32/x86/0000775000175000017500000000000015105742312020175 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs0000644000175000017500000011261015105742312021321 0ustar bdrungbdrunguse crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = i32; pub type greg_t = i32; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, f_spare: [crate::__fsword_t; 4], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct _libc_fpreg { pub significand: [u16; 4], pub exponent: u16, } pub struct _libc_fpstate { pub cw: c_ulong, pub sw: c_ulong, pub tag: c_ulong, pub ipoff: c_ulong, pub cssel: c_ulong, pub dataoff: c_ulong, pub datasel: c_ulong, pub _st: [_libc_fpreg; 8], pub status: c_ulong, } pub struct user_fpregs_struct { pub cwd: c_long, pub swd: c_long, pub twd: c_long, pub fip: c_long, pub fcs: c_long, pub foo: c_long, pub fos: c_long, pub st_space: [c_long; 20], } pub struct user_regs_struct { pub ebx: c_long, pub ecx: c_long, pub edx: c_long, pub esi: c_long, pub edi: c_long, pub ebp: c_long, pub eax: c_long, pub xds: c_long, pub xes: c_long, pub xfs: c_long, pub xgs: c_long, pub orig_eax: c_long, pub eip: c_long, pub xcs: c_long, pub eflags: c_long, pub esp: c_long, pub xss: c_long, } pub struct user { pub regs: user_regs_struct, pub u_fpvalid: c_int, pub i387: user_fpregs_struct, pub u_tsize: c_ulong, pub u_dsize: c_ulong, pub u_ssize: c_ulong, pub start_code: c_ulong, pub start_stack: c_ulong, pub signal: c_long, __reserved: c_int, pub u_ar0: *mut user_regs_struct, pub u_fpstate: *mut user_fpregs_struct, pub magic: c_ulong, pub u_comm: [c_char; 32], pub u_debugreg: [c_int; 8], } pub struct mcontext_t { pub gregs: [greg_t; 19], pub fpregs: *mut _libc_fpstate, pub oldmask: c_ulong, pub cr2: c_ulong, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct stat64 { pub st_dev: crate::dev_t, __pad1: c_uint, __st_ino: c_ulong, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_uint, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino64_t, } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, __unused1: c_ulong, pub shm_dtime: crate::time_t, __unused2: c_ulong, pub shm_ctime: crate::time_t, __unused3: c_ulong, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __glibc_reserved1: c_ulong, pub msg_rtime: crate::time_t, __glibc_reserved2: c_ulong, pub msg_ctime: crate::time_t, __glibc_reserved3: c_ulong, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } } s_no_extra_traits! { pub struct user_fpxregs_struct { pub cwd: c_ushort, pub swd: c_ushort, pub twd: c_ushort, pub fop: c_ushort, pub fip: c_long, pub fcs: c_long, pub foo: c_long, pub fos: c_long, pub mxcsr: c_long, __reserved: c_long, pub st_space: [c_long; 32], pub xmm_space: [c_long; 32], padding: [c_long; 56], } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: crate::sigset_t, __private: [u8; 112], __ssp: [c_ulong; 4], } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 6], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for user_fpxregs_struct { fn eq(&self, other: &user_fpxregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.twd == other.twd && self.fop == other.fop && self.fip == other.fip && self.fcs == other.fcs && self.foo == other.foo && self.fos == other.fos && self.mxcsr == other.mxcsr // Ignore __reserved field && self.st_space == other.st_space && self.xmm_space == other.xmm_space // Ignore padding field } } impl Eq for user_fpxregs_struct {} impl fmt::Debug for user_fpxregs_struct { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("user_fpxregs_struct") .field("cwd", &self.cwd) .field("swd", &self.swd) .field("twd", &self.twd) .field("fop", &self.fop) .field("fip", &self.fip) .field("fcs", &self.fcs) .field("foo", &self.foo) .field("fos", &self.fos) .field("mxcsr", &self.mxcsr) // Ignore __reserved field .field("st_space", &self.st_space) .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl hash::Hash for user_fpxregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.swd.hash(state); self.twd.hash(state); self.fop.hash(state); self.fip.hash(state); self.fcs.hash(state); self.foo.hash(state); self.fos.hash(state); self.mxcsr.hash(state); // Ignore __reserved field self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask // Ignore __private field } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // Ignore __private field .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); // Ignore __private field } } } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_LARGEFILE: c_int = 0o0100000; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_32BIT: c_int = 0x0040; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; cfg_if! { if #[cfg(gnu_file_offset_bits64)] { pub const F_GETLK: c_int = 12; } else { pub const F_GETLK: c_int = 5; } } pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const PTRACE_GETFPXREGS: c_uint = 18; pub const PTRACE_SETFPXREGS: c_uint = 19; pub const PTRACE_SYSEMU: c_uint = 31; pub const PTRACE_SYSEMU_SINGLESTEP: c_uint = 32; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const EFD_NONBLOCK: c_int = 0x800; pub const SFD_NONBLOCK: c_int = 0x0800; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; // Syscall table pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_waitpid: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_time: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_break: c_long = 17; pub const SYS_oldstat: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_stime: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_oldfstat: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_stty: c_long = 31; pub const SYS_gtty: c_long = 32; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_ftime: c_long = 35; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_prof: c_long = 44; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_lock: c_long = 53; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_mpx: c_long = 56; pub const SYS_setpgid: c_long = 57; pub const SYS_ulimit: c_long = 58; pub const SYS_oldolduname: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sgetmask: c_long = 68; pub const SYS_ssetmask: c_long = 69; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrlimit: c_long = 76; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_select: c_long = 82; pub const SYS_symlink: c_long = 83; pub const SYS_oldlstat: c_long = 84; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_profil: c_long = 98; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_ioperm: c_long = 101; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_olduname: c_long = 109; pub const SYS_iopl: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_vm86old: c_long = 113; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_modify_ldt: c_long = 123; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; pub const SYS_vm86: c_long = 166; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 167; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_setresgid: c_long = 170; pub const SYS_getresgid: c_long = 171; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_chown: c_long = 182; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_getpmsg: c_long = 188; pub const SYS_putpmsg: c_long = 189; pub const SYS_vfork: c_long = 190; pub const SYS_ugetrlimit: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_lchown32: c_long = 198; pub const SYS_getuid32: c_long = 199; pub const SYS_getgid32: c_long = 200; pub const SYS_geteuid32: c_long = 201; pub const SYS_getegid32: c_long = 202; pub const SYS_setreuid32: c_long = 203; pub const SYS_setregid32: c_long = 204; pub const SYS_getgroups32: c_long = 205; pub const SYS_setgroups32: c_long = 206; pub const SYS_fchown32: c_long = 207; pub const SYS_setresuid32: c_long = 208; pub const SYS_getresuid32: c_long = 209; pub const SYS_setresgid32: c_long = 210; pub const SYS_getresgid32: c_long = 211; pub const SYS_chown32: c_long = 212; pub const SYS_setuid32: c_long = 213; pub const SYS_setgid32: c_long = 214; pub const SYS_setfsuid32: c_long = 215; pub const SYS_setfsgid32: c_long = 216; pub const SYS_pivot_root: c_long = 217; pub const SYS_mincore: c_long = 218; pub const SYS_madvise: c_long = 219; pub const SYS_getdents64: c_long = 220; pub const SYS_fcntl64: c_long = 221; pub const SYS_gettid: c_long = 224; pub const SYS_readahead: c_long = 225; pub const SYS_setxattr: c_long = 226; pub const SYS_lsetxattr: c_long = 227; pub const SYS_fsetxattr: c_long = 228; pub const SYS_getxattr: c_long = 229; pub const SYS_lgetxattr: c_long = 230; pub const SYS_fgetxattr: c_long = 231; pub const SYS_listxattr: c_long = 232; pub const SYS_llistxattr: c_long = 233; pub const SYS_flistxattr: c_long = 234; pub const SYS_removexattr: c_long = 235; pub const SYS_lremovexattr: c_long = 236; pub const SYS_fremovexattr: c_long = 237; pub const SYS_tkill: c_long = 238; pub const SYS_sendfile64: c_long = 239; pub const SYS_futex: c_long = 240; pub const SYS_sched_setaffinity: c_long = 241; pub const SYS_sched_getaffinity: c_long = 242; pub const SYS_set_thread_area: c_long = 243; pub const SYS_get_thread_area: c_long = 244; pub const SYS_io_setup: c_long = 245; pub const SYS_io_destroy: c_long = 246; pub const SYS_io_getevents: c_long = 247; pub const SYS_io_submit: c_long = 248; pub const SYS_io_cancel: c_long = 249; pub const SYS_fadvise64: c_long = 250; pub const SYS_exit_group: c_long = 252; pub const SYS_lookup_dcookie: c_long = 253; pub const SYS_epoll_create: c_long = 254; pub const SYS_epoll_ctl: c_long = 255; pub const SYS_epoll_wait: c_long = 256; pub const SYS_remap_file_pages: c_long = 257; pub const SYS_set_tid_address: c_long = 258; pub const SYS_timer_create: c_long = 259; pub const SYS_timer_settime: c_long = 260; pub const SYS_timer_gettime: c_long = 261; pub const SYS_timer_getoverrun: c_long = 262; pub const SYS_timer_delete: c_long = 263; pub const SYS_clock_settime: c_long = 264; pub const SYS_clock_gettime: c_long = 265; pub const SYS_clock_getres: c_long = 266; pub const SYS_clock_nanosleep: c_long = 267; pub const SYS_statfs64: c_long = 268; pub const SYS_fstatfs64: c_long = 269; pub const SYS_tgkill: c_long = 270; pub const SYS_utimes: c_long = 271; pub const SYS_fadvise64_64: c_long = 272; pub const SYS_vserver: c_long = 273; pub const SYS_mbind: c_long = 274; pub const SYS_get_mempolicy: c_long = 275; pub const SYS_set_mempolicy: c_long = 276; pub const SYS_mq_open: c_long = 277; pub const SYS_mq_unlink: c_long = 278; pub const SYS_mq_timedsend: c_long = 279; pub const SYS_mq_timedreceive: c_long = 280; pub const SYS_mq_notify: c_long = 281; pub const SYS_mq_getsetattr: c_long = 282; pub const SYS_kexec_load: c_long = 283; pub const SYS_waitid: c_long = 284; pub const SYS_add_key: c_long = 286; pub const SYS_request_key: c_long = 287; pub const SYS_keyctl: c_long = 288; pub const SYS_ioprio_set: c_long = 289; pub const SYS_ioprio_get: c_long = 290; pub const SYS_inotify_init: c_long = 291; pub const SYS_inotify_add_watch: c_long = 292; pub const SYS_inotify_rm_watch: c_long = 293; pub const SYS_migrate_pages: c_long = 294; pub const SYS_openat: c_long = 295; pub const SYS_mkdirat: c_long = 296; pub const SYS_mknodat: c_long = 297; pub const SYS_fchownat: c_long = 298; pub const SYS_futimesat: c_long = 299; pub const SYS_fstatat64: c_long = 300; pub const SYS_unlinkat: c_long = 301; pub const SYS_renameat: c_long = 302; pub const SYS_linkat: c_long = 303; pub const SYS_symlinkat: c_long = 304; pub const SYS_readlinkat: c_long = 305; pub const SYS_fchmodat: c_long = 306; pub const SYS_faccessat: c_long = 307; pub const SYS_pselect6: c_long = 308; pub const SYS_ppoll: c_long = 309; pub const SYS_unshare: c_long = 310; pub const SYS_set_robust_list: c_long = 311; pub const SYS_get_robust_list: c_long = 312; pub const SYS_splice: c_long = 313; pub const SYS_sync_file_range: c_long = 314; pub const SYS_tee: c_long = 315; pub const SYS_vmsplice: c_long = 316; pub const SYS_move_pages: c_long = 317; pub const SYS_getcpu: c_long = 318; pub const SYS_epoll_pwait: c_long = 319; pub const SYS_utimensat: c_long = 320; pub const SYS_signalfd: c_long = 321; pub const SYS_timerfd_create: c_long = 322; pub const SYS_eventfd: c_long = 323; pub const SYS_fallocate: c_long = 324; pub const SYS_timerfd_settime: c_long = 325; pub const SYS_timerfd_gettime: c_long = 326; pub const SYS_signalfd4: c_long = 327; pub const SYS_eventfd2: c_long = 328; pub const SYS_epoll_create1: c_long = 329; pub const SYS_dup3: c_long = 330; pub const SYS_pipe2: c_long = 331; pub const SYS_inotify_init1: c_long = 332; pub const SYS_preadv: c_long = 333; pub const SYS_pwritev: c_long = 334; pub const SYS_rt_tgsigqueueinfo: c_long = 335; pub const SYS_perf_event_open: c_long = 336; pub const SYS_recvmmsg: c_long = 337; pub const SYS_fanotify_init: c_long = 338; pub const SYS_fanotify_mark: c_long = 339; pub const SYS_prlimit64: c_long = 340; pub const SYS_name_to_handle_at: c_long = 341; pub const SYS_open_by_handle_at: c_long = 342; pub const SYS_clock_adjtime: c_long = 343; pub const SYS_syncfs: c_long = 344; pub const SYS_sendmmsg: c_long = 345; pub const SYS_setns: c_long = 346; pub const SYS_process_vm_readv: c_long = 347; pub const SYS_process_vm_writev: c_long = 348; pub const SYS_kcmp: c_long = 349; pub const SYS_finit_module: c_long = 350; pub const SYS_sched_setattr: c_long = 351; pub const SYS_sched_getattr: c_long = 352; pub const SYS_renameat2: c_long = 353; pub const SYS_seccomp: c_long = 354; pub const SYS_getrandom: c_long = 355; pub const SYS_memfd_create: c_long = 356; pub const SYS_bpf: c_long = 357; pub const SYS_execveat: c_long = 358; pub const SYS_socket: c_long = 359; pub const SYS_socketpair: c_long = 360; pub const SYS_bind: c_long = 361; pub const SYS_connect: c_long = 362; pub const SYS_listen: c_long = 363; pub const SYS_accept4: c_long = 364; pub const SYS_getsockopt: c_long = 365; pub const SYS_setsockopt: c_long = 366; pub const SYS_getsockname: c_long = 367; pub const SYS_getpeername: c_long = 368; pub const SYS_sendto: c_long = 369; pub const SYS_sendmsg: c_long = 370; pub const SYS_recvfrom: c_long = 371; pub const SYS_recvmsg: c_long = 372; pub const SYS_shutdown: c_long = 373; pub const SYS_userfaultfd: c_long = 374; pub const SYS_membarrier: c_long = 375; pub const SYS_mlock2: c_long = 376; pub const SYS_copy_file_range: c_long = 377; pub const SYS_preadv2: c_long = 378; pub const SYS_pwritev2: c_long = 379; pub const SYS_pkey_mprotect: c_long = 380; pub const SYS_pkey_alloc: c_long = 381; pub const SYS_pkey_free: c_long = 382; pub const SYS_statx: c_long = 383; pub const SYS_rseq: c_long = 386; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_fchmodat2: c_long = 452; pub const SYS_mseal: c_long = 462; // offsets in user_regs_structs, from sys/reg.h pub const EBX: c_int = 0; pub const ECX: c_int = 1; pub const EDX: c_int = 2; pub const ESI: c_int = 3; pub const EDI: c_int = 4; pub const EBP: c_int = 5; pub const EAX: c_int = 6; pub const DS: c_int = 7; pub const ES: c_int = 8; pub const FS: c_int = 9; pub const GS: c_int = 10; pub const ORIG_EAX: c_int = 11; pub const EIP: c_int = 12; pub const CS: c_int = 13; pub const EFL: c_int = 14; pub const UESP: c_int = 15; pub const SS: c_int = 16; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_GS: c_int = 0; pub const REG_FS: c_int = 1; pub const REG_ES: c_int = 2; pub const REG_DS: c_int = 3; pub const REG_EDI: c_int = 4; pub const REG_ESI: c_int = 5; pub const REG_EBP: c_int = 6; pub const REG_ESP: c_int = 7; pub const REG_EBX: c_int = 8; pub const REG_EDX: c_int = 9; pub const REG_ECX: c_int = 10; pub const REG_EAX: c_int = 11; pub const REG_TRAPNO: c_int = 12; pub const REG_ERR: c_int = 13; pub const REG_EIP: c_int = 14; pub const REG_CS: c_int = 15; pub const REG_EFL: c_int = 16; pub const REG_UESP: c_int = 17; pub const REG_SS: c_int = 18; extern "C" { pub fn getcontext(ucp: *mut ucontext_t) -> c_int; pub fn setcontext(ucp: *const ucontext_t) -> c_int; pub fn makecontext(ucp: *mut ucontext_t, func: extern "C" fn(), argc: c_int, ...); pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> c_int; } libc/src/unix/linux_like/linux/gnu/b32/m68k/0000775000175000017500000000000015105742312020335 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b32/m68k/mod.rs0000644000175000017500000007467215105742312021500 0ustar bdrungbdrunguse crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = i32; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, f_spare: [crate::__fsword_t; 4], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct ipc_perm { __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, __seq: c_ushort, __pad1: c_ushort, __glibc_reserved1: c_ulong, __glibc_reserved2: c_ulong, } pub struct stat64 { pub st_dev: crate::dev_t, __pad1: c_ushort, pub __st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_ushort, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_ulong, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_ulong, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_ulong, pub st_ino: crate::ino64_t, } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsblkcnt64_t, pub f_ffree: crate::fsblkcnt64_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsblkcnt64_t, pub f_ffree: crate::fsblkcnt64_t, pub f_favail: crate::fsblkcnt64_t, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, __glibc_reserved1: c_long, pub shm_dtime: crate::time_t, __glibc_reserved2: c_long, pub shm_ctime: crate::time_t, __glibc_reserved3: c_long, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __glibc_reserved5: c_ulong, __glibc_reserved6: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, __glibc_reserved1: c_uint, pub msg_rtime: crate::time_t, __glibc_reserved2: c_uint, pub msg_ctime: crate::time_t, __glibc_reserved3: c_uint, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: c_ulong, __glibc_reserved5: c_ulong, } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, _pad: [c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(2))] pub struct max_align_t { priv_: [i8; 20], } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_DIRECT: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_LARGEFILE: c_int = 0x20000; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_32BIT: c_int = 0x0040; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const PTRACE_GETFPXREGS: c_uint = 18; pub const PTRACE_SETFPXREGS: c_uint = 19; pub const PTRACE_SYSEMU: c_uint = 31; pub const PTRACE_SYSEMU_SINGLESTEP: c_uint = 32; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const EFD_NONBLOCK: c_int = 0x800; pub const SFD_NONBLOCK: c_int = 0x0800; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_waitpid: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_time32: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_chown16: c_long = 16; pub const SYS_stat: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_oldumount: c_long = 22; pub const SYS_setuid16: c_long = 23; pub const SYS_getuid16: c_long = 24; pub const SYS_stime32: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_fstat: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime32: c_long = 30; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_brk: c_long = 45; pub const SYS_setgid16: c_long = 46; pub const SYS_getgid16: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid16: c_long = 49; pub const SYS_getegid16: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount: c_long = 52; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_setpgid: c_long = 57; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sgetmask: c_long = 68; pub const SYS_ssetmask: c_long = 69; pub const SYS_setreuid16: c_long = 70; pub const SYS_setregid16: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_old_getrlimit: c_long = 76; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups16: c_long = 80; pub const SYS_setgroups16: c_long = 81; pub const SYS_old_select: c_long = 82; pub const SYS_symlink: c_long = 83; pub const SYS_lstat: c_long = 84; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_old_readdir: c_long = 89; pub const SYS_old_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown16: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_newstat: c_long = 106; pub const SYS_newlstat: c_long = 107; pub const SYS_newfstat: c_long = 108; pub const SYS_vhangup: c_long = 111; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_newuname: c_long = 122; pub const SYS_cacheflush: c_long = 123; pub const SYS_adjtimex_time32: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_setfsuid16: c_long = 138; pub const SYS_setfsgid16: c_long = 139; pub const SYS_llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS_select: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval_time32: c_long = 161; pub const SYS_nanosleep_time32: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid16: c_long = 164; pub const SYS_getresuid16: c_long = 165; pub const SYS_getpagesize: c_long = 166; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 167; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_setresgid16: c_long = 170; pub const SYS_getresgid16: c_long = 171; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait_time32: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_lchown16: c_long = 182; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_getpmsg: c_long = 188; pub const SYS_putpmsg: c_long = 189; pub const SYS_vfork: c_long = 190; pub const SYS_getrlimit: c_long = 191; pub const SYS_mmap2: c_long = 192; pub const SYS_truncate64: c_long = 193; pub const SYS_ftruncate64: c_long = 194; pub const SYS_stat64: c_long = 195; pub const SYS_lstat64: c_long = 196; pub const SYS_fstat64: c_long = 197; pub const SYS_chown: c_long = 198; pub const SYS_getuid: c_long = 199; pub const SYS_getgid: c_long = 200; pub const SYS_geteuid: c_long = 201; pub const SYS_getegid: c_long = 202; pub const SYS_setreuid: c_long = 203; pub const SYS_setregid: c_long = 204; pub const SYS_getgroups: c_long = 205; pub const SYS_setgroups: c_long = 206; pub const SYS_fchown: c_long = 207; pub const SYS_setresuid: c_long = 208; pub const SYS_getresuid: c_long = 209; pub const SYS_setresgid: c_long = 210; pub const SYS_getresgid: c_long = 211; pub const SYS_lchown: c_long = 212; pub const SYS_setuid: c_long = 213; pub const SYS_setgid: c_long = 214; pub const SYS_setfsuid: c_long = 215; pub const SYS_setfsgid: c_long = 216; pub const SYS_pivot_root: c_long = 217; pub const SYS_getdents64: c_long = 220; pub const SYS_gettid: c_long = 221; pub const SYS_tkill: c_long = 222; pub const SYS_setxattr: c_long = 223; pub const SYS_lsetxattr: c_long = 224; pub const SYS_fsetxattr: c_long = 225; pub const SYS_getxattr: c_long = 226; pub const SYS_lgetxattr: c_long = 227; pub const SYS_fgetxattr: c_long = 228; pub const SYS_listxattr: c_long = 229; pub const SYS_llistxattr: c_long = 230; pub const SYS_flistxattr: c_long = 231; pub const SYS_removexattr: c_long = 232; pub const SYS_lremovexattr: c_long = 233; pub const SYS_fremovexattr: c_long = 234; pub const SYS_futex_time32: c_long = 235; pub const SYS_sendfile64: c_long = 236; pub const SYS_mincore: c_long = 237; pub const SYS_madvise: c_long = 238; pub const SYS_fcntl64: c_long = 239; pub const SYS_readahead: c_long = 240; pub const SYS_io_setup: c_long = 241; pub const SYS_io_destroy: c_long = 242; pub const SYS_io_getevents_time32: c_long = 243; pub const SYS_io_submit: c_long = 244; pub const SYS_io_cancel: c_long = 245; pub const SYS_fadvise64: c_long = 246; pub const SYS_exit_group: c_long = 247; pub const SYS_lookup_dcookie: c_long = 248; pub const SYS_epoll_create: c_long = 249; pub const SYS_epoll_ctl: c_long = 250; pub const SYS_epoll_wait: c_long = 251; pub const SYS_remap_file_pages: c_long = 252; pub const SYS_set_tid_address: c_long = 253; pub const SYS_timer_create: c_long = 254; pub const SYS_timer_settime32: c_long = 255; pub const SYS_timer_gettime32: c_long = 256; pub const SYS_timer_getoverrun: c_long = 257; pub const SYS_timer_delete: c_long = 258; pub const SYS_clock_settime32: c_long = 259; pub const SYS_clock_gettime32: c_long = 260; pub const SYS_clock_getres_time32: c_long = 261; pub const SYS_clock_nanosleep_time32: c_long = 262; pub const SYS_statfs64: c_long = 263; pub const SYS_fstatfs64: c_long = 264; pub const SYS_tgkill: c_long = 265; pub const SYS_utimes_time32: c_long = 266; pub const SYS_fadvise64_64: c_long = 267; pub const SYS_mbind: c_long = 268; pub const SYS_get_mempolicy: c_long = 269; pub const SYS_set_mempolicy: c_long = 270; pub const SYS_mq_open: c_long = 271; pub const SYS_mq_unlink: c_long = 272; pub const SYS_mq_timedsend_time32: c_long = 273; pub const SYS_mq_timedreceive_time32: c_long = 274; pub const SYS_mq_notify: c_long = 275; pub const SYS_mq_getsetattr: c_long = 276; pub const SYS_waitid: c_long = 277; pub const SYS_add_key: c_long = 279; pub const SYS_request_key: c_long = 280; pub const SYS_keyctl: c_long = 281; pub const SYS_ioprio_set: c_long = 282; pub const SYS_ioprio_get: c_long = 283; pub const SYS_inotify_init: c_long = 284; pub const SYS_inotify_add_watch: c_long = 285; pub const SYS_inotify_rm_watch: c_long = 286; pub const SYS_migrate_pages: c_long = 287; pub const SYS_openat: c_long = 288; pub const SYS_mkdirat: c_long = 289; pub const SYS_mknodat: c_long = 290; pub const SYS_fchownat: c_long = 291; pub const SYS_futimesat_time32: c_long = 292; pub const SYS_fstatat64: c_long = 293; pub const SYS_unlinkat: c_long = 294; pub const SYS_renameat: c_long = 295; pub const SYS_linkat: c_long = 296; pub const SYS_symlinkat: c_long = 297; pub const SYS_readlinkat: c_long = 298; pub const SYS_fchmodat: c_long = 299; pub const SYS_faccessat: c_long = 300; pub const SYS_pselect6_time32: c_long = 301; pub const SYS_ppoll_time32: c_long = 302; pub const SYS_unshare: c_long = 303; pub const SYS_set_robust_list: c_long = 304; pub const SYS_get_robust_list: c_long = 305; pub const SYS_splice: c_long = 306; pub const SYS_sync_file_range: c_long = 307; pub const SYS_tee: c_long = 308; pub const SYS_vmsplice: c_long = 309; pub const SYS_move_pages: c_long = 310; pub const SYS_sched_setaffinity: c_long = 311; pub const SYS_sched_getaffinity: c_long = 312; pub const SYS_kexec_load: c_long = 313; pub const SYS_getcpu: c_long = 314; pub const SYS_epoll_pwait: c_long = 315; pub const SYS_utimensat_time32: c_long = 316; pub const SYS_signalfd: c_long = 317; pub const SYS_timerfd_create: c_long = 318; pub const SYS_eventfd: c_long = 319; pub const SYS_fallocate: c_long = 320; pub const SYS_timerfd_settime32: c_long = 321; pub const SYS_timerfd_gettime32: c_long = 322; pub const SYS_signalfd4: c_long = 323; pub const SYS_eventfd2: c_long = 324; pub const SYS_epoll_create1: c_long = 325; pub const SYS_dup3: c_long = 326; pub const SYS_pipe2: c_long = 327; pub const SYS_inotify_init1: c_long = 328; pub const SYS_preadv: c_long = 329; pub const SYS_pwritev: c_long = 330; pub const SYS_rt_tgsigqueueinfo: c_long = 331; pub const SYS_perf_event_open: c_long = 332; pub const SYS_get_thread_area: c_long = 333; pub const SYS_set_thread_area: c_long = 334; pub const SYS_atomic_cmpxchg_32: c_long = 335; pub const SYS_atomic_barrier: c_long = 336; pub const SYS_fanotify_init: c_long = 337; pub const SYS_fanotify_mark: c_long = 338; pub const SYS_prlimit64: c_long = 339; pub const SYS_name_to_handle_at: c_long = 340; pub const SYS_open_by_handle_at: c_long = 341; pub const SYS_clock_adjtime32: c_long = 342; pub const SYS_syncfs: c_long = 343; pub const SYS_setns: c_long = 344; pub const SYS_process_vm_readv: c_long = 345; pub const SYS_process_vm_writev: c_long = 346; pub const SYS_kcmp: c_long = 347; pub const SYS_finit_module: c_long = 348; pub const SYS_sched_setattr: c_long = 349; pub const SYS_sched_getattr: c_long = 350; pub const SYS_renameat2: c_long = 351; pub const SYS_getrandom: c_long = 352; pub const SYS_memfd_create: c_long = 353; pub const SYS_bpf: c_long = 354; pub const SYS_execveat: c_long = 355; pub const SYS_socket: c_long = 356; pub const SYS_socketpair: c_long = 357; pub const SYS_bind: c_long = 358; pub const SYS_connect: c_long = 359; pub const SYS_listen: c_long = 360; pub const SYS_accept4: c_long = 361; pub const SYS_getsockopt: c_long = 362; pub const SYS_setsockopt: c_long = 363; pub const SYS_getsockname: c_long = 364; pub const SYS_getpeername: c_long = 365; pub const SYS_sendto: c_long = 366; pub const SYS_sendmsg: c_long = 367; pub const SYS_recvfrom: c_long = 368; pub const SYS_recvmsg: c_long = 369; pub const SYS_shutdown: c_long = 370; pub const SYS_recvmmsg_time32: c_long = 371; pub const SYS_sendmmsg: c_long = 372; pub const SYS_userfaultfd: c_long = 373; pub const SYS_membarrier: c_long = 374; pub const SYS_mlock2: c_long = 375; pub const SYS_copy_file_range: c_long = 376; pub const SYS_preadv2: c_long = 377; pub const SYS_pwritev2: c_long = 378; pub const SYS_statx: c_long = 379; pub const SYS_seccomp: c_long = 380; pub const SYS_pkey_mprotect: c_long = 381; pub const SYS_pkey_alloc: c_long = 382; pub const SYS_pkey_free: c_long = 383; pub const SYS_rseq: c_long = 384; pub const SYS_semget: c_long = 393; pub const SYS_semctl: c_long = 394; pub const SYS_shmget: c_long = 395; pub const SYS_shmctl: c_long = 396; pub const SYS_shmat: c_long = 397; pub const SYS_shmdt: c_long = 398; pub const SYS_msgget: c_long = 399; pub const SYS_msgsnd: c_long = 400; pub const SYS_msgrcv: c_long = 401; pub const SYS_msgctl: c_long = 402; pub const SYS_clock_gettime: c_long = 403; pub const SYS_clock_settime: c_long = 404; pub const SYS_clock_adjtime: c_long = 405; pub const SYS_clock_getres: c_long = 406; pub const SYS_clock_nanosleep: c_long = 407; pub const SYS_timer_gettime: c_long = 408; pub const SYS_timer_settime: c_long = 409; pub const SYS_timerfd_gettime: c_long = 410; pub const SYS_timerfd_settime: c_long = 411; pub const SYS_utimensat: c_long = 412; pub const SYS_pselect6: c_long = 413; pub const SYS_ppoll: c_long = 414; pub const SYS_io_pgetevents: c_long = 416; pub const SYS_recvmmsg: c_long = 417; pub const SYS_mq_timedsend: c_long = 418; pub const SYS_mq_timedreceive: c_long = 419; pub const SYS_semtimedop: c_long = 420; pub const SYS_rt_sigtimedwait: c_long = 421; pub const SYS_futex: c_long = 422; pub const SYS_sched_rr_get_interval: c_long = 423; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; libc/src/unix/linux_like/linux/gnu/b64/0000775000175000017500000000000015105742312017555 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b64/mod.rs0000644000175000017500000000755715105742312020716 0ustar bdrungbdrung//! 64-bit specific definitions for linux-like values use crate::prelude::*; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i64; pub type shmatt_t = u64; pub type msgqnum_t = u64; pub type msglen_t = u64; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type rlim_t = u64; #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub type __syscall_ulong_t = c_ulonglong; #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub type __syscall_ulong_t = c_ulong; cfg_if! { if #[cfg(all(target_arch = "aarch64", target_pointer_width = "32"))] { pub type clock_t = i32; pub type time_t = i32; pub type __fsword_t = i32; } else { pub type __fsword_t = i64; pub type clock_t = i64; pub type time_t = i64; } } s! { pub struct sigset_t { #[cfg(target_pointer_width = "32")] __val: [u32; 32], #[cfg(target_pointer_width = "64")] __val: [u64; 16], } pub struct sysinfo { pub uptime: i64, pub loads: [u64; 3], pub totalram: u64, pub freeram: u64, pub sharedram: u64, pub bufferram: u64, pub totalswap: u64, pub freeswap: u64, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: u64, pub freehigh: u64, pub mem_unit: c_uint, pub _f: [c_char; 0], } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, pub __msg_cbytes: u64, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __glibc_reserved4: u64, __glibc_reserved5: u64, } pub struct semid_ds { pub sem_perm: ipc_perm, pub sem_otime: crate::time_t, #[cfg(not(any( target_arch = "aarch64", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "sparc64", target_arch = "s390x", )))] __reserved: crate::__syscall_ulong_t, pub sem_ctime: crate::time_t, #[cfg(not(any( target_arch = "aarch64", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "sparc64", target_arch = "s390x", )))] __reserved2: crate::__syscall_ulong_t, pub sem_nsems: crate::__syscall_ulong_t, __glibc_reserved3: crate::__syscall_ulong_t, __glibc_reserved4: crate::__syscall_ulong_t, } } pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const O_LARGEFILE: c_int = 0; cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(any(target_arch = "powerpc64"))] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(any(target_arch = "sparc64"))] { mod sparc64; pub use self::sparc64::*; } else if #[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))] { mod mips64; pub use self::mips64::*; } else if #[cfg(any(target_arch = "s390x"))] { mod s390x; pub use self::s390x::*; } else if #[cfg(any(target_arch = "x86_64"))] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(any(target_arch = "riscv64"))] { mod riscv64; pub use self::riscv64::*; } else if #[cfg(any(target_arch = "loongarch64"))] { mod loongarch64; pub use self::loongarch64::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/gnu/b64/x86_64/0000775000175000017500000000000015105742312020513 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs0000644000175000017500000006341015105742312021642 0ustar bdrungbdrung//! x86_64-specific definitions for 64-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = i64; pub type greg_t = i64; pub type suseconds_t = i64; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, #[cfg(target_arch = "sparc64")] __reserved0: c_int, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, f_spare: [crate::__fsword_t; 5], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [u64; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: i64, pub st_mtime: crate::time_t, pub st_mtime_nsec: i64, pub st_ctime: crate::time_t, pub st_ctime_nsec: i64, __unused: [i64; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: i64, pub st_mtime: crate::time_t, pub st_mtime_nsec: i64, pub st_ctime: crate::time_t, pub st_ctime_nsec: i64, __reserved: [i64; 3], } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct pthread_attr_t { #[cfg(target_pointer_width = "32")] __size: [u32; 8], #[cfg(target_pointer_width = "64")] __size: [u64; 7], } pub struct _libc_fpxreg { pub significand: [u16; 4], pub exponent: u16, __private: [u16; 3], } pub struct _libc_xmmreg { pub element: [u32; 4], } pub struct _libc_fpstate { pub cwd: u16, pub swd: u16, pub ftw: u16, pub fop: u16, pub rip: u64, pub rdp: u64, pub mxcsr: u32, pub mxcr_mask: u32, pub _st: [_libc_fpxreg; 8], pub _xmm: [_libc_xmmreg; 16], __private: [u64; 12], } pub struct user_regs_struct { pub r15: c_ulonglong, pub r14: c_ulonglong, pub r13: c_ulonglong, pub r12: c_ulonglong, pub rbp: c_ulonglong, pub rbx: c_ulonglong, pub r11: c_ulonglong, pub r10: c_ulonglong, pub r9: c_ulonglong, pub r8: c_ulonglong, pub rax: c_ulonglong, pub rcx: c_ulonglong, pub rdx: c_ulonglong, pub rsi: c_ulonglong, pub rdi: c_ulonglong, pub orig_rax: c_ulonglong, pub rip: c_ulonglong, pub cs: c_ulonglong, pub eflags: c_ulonglong, pub rsp: c_ulonglong, pub ss: c_ulonglong, pub fs_base: c_ulonglong, pub gs_base: c_ulonglong, pub ds: c_ulonglong, pub es: c_ulonglong, pub fs: c_ulonglong, pub gs: c_ulonglong, } pub struct user { pub regs: user_regs_struct, pub u_fpvalid: c_int, pub i387: user_fpregs_struct, pub u_tsize: c_ulonglong, pub u_dsize: c_ulonglong, pub u_ssize: c_ulonglong, pub start_code: c_ulonglong, pub start_stack: c_ulonglong, pub signal: c_longlong, __reserved: c_int, #[cfg(target_pointer_width = "32")] __pad1: u32, pub u_ar0: *mut user_regs_struct, #[cfg(target_pointer_width = "32")] __pad2: u32, pub u_fpstate: *mut user_fpregs_struct, pub magic: c_ulonglong, pub u_comm: [c_char; 32], pub u_debugreg: [c_ulonglong; 8], } pub struct mcontext_t { pub gregs: [greg_t; 23], pub fpregs: *mut _libc_fpstate, __private: [u64; 8], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: u64, __unused2: u64, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: u64, __unused5: u64, } pub struct ptrace_rseq_configuration { pub rseq_abi_pointer: crate::__u64, pub rseq_abi_size: crate::__u32, pub signature: crate::__u32, pub flags: crate::__u32, pub pad: crate::__u32, } #[repr(align(8))] pub struct clone_args { pub flags: c_ulonglong, pub pidfd: c_ulonglong, pub child_tid: c_ulonglong, pub parent_tid: c_ulonglong, pub exit_signal: c_ulonglong, pub stack: c_ulonglong, pub stack_size: c_ulonglong, pub tls: c_ulonglong, pub set_tid: c_ulonglong, pub set_tid_size: c_ulonglong, pub cgroup: c_ulonglong, } } s_no_extra_traits! { pub struct user_fpregs_struct { pub cwd: c_ushort, pub swd: c_ushort, pub ftw: c_ushort, pub fop: c_ushort, pub rip: c_ulonglong, pub rdp: c_ulonglong, pub mxcsr: c_uint, pub mxcr_mask: c_uint, pub st_space: [c_uint; 32], pub xmm_space: [c_uint; 64], padding: [c_uint; 24], } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: crate::sigset_t, __private: [u8; 512], // FIXME(glibc): the shadow stack field requires glibc >= 2.28. // Re-add once we drop compatibility with glibc versions older than // 2.28. // // __ssp: [c_ulonglong; 4], } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for user_fpregs_struct { fn eq(&self, other: &user_fpregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.ftw == other.ftw && self.fop == other.fop && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mxcr_mask == other.mxcr_mask && self.st_space == other.st_space && self .xmm_space .iter() .zip(other.xmm_space.iter()) .all(|(a, b)| a == b) // Ignore padding field } } impl Eq for user_fpregs_struct {} impl fmt::Debug for user_fpregs_struct { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("user_fpregs_struct") .field("cwd", &self.cwd) .field("ftw", &self.ftw) .field("fop", &self.fop) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mxcr_mask", &self.mxcr_mask) .field("st_space", &self.st_space) // FIXME(debug): .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl hash::Hash for user_fpregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.ftw.hash(state); self.fop.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mxcr_mask.hash(state); self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask // Ignore __private field } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // Ignore __private field .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); // Ignore __private field } } } } pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_NOATIME: c_int = 0o1000000; pub const O_PATH: c_int = 0o10000000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const PTRACE_DETACH: c_uint = 17; pub const PTRACE_GET_RSEQ_CONFIGURATION: c_uint = 0x420f; pub const EFD_NONBLOCK: c_int = 0x800; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const SFD_NONBLOCK: c_int = 0x0800; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_CLOEXEC: c_int = 0x80000; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_32BIT: c_int = 0x0040; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const PTRACE_GETFPREGS: c_uint = 14; pub const PTRACE_SETFPREGS: c_uint = 15; pub const PTRACE_GETFPXREGS: c_uint = 18; pub const PTRACE_SETFPXREGS: c_uint = 19; pub const PTRACE_GETREGS: c_uint = 12; pub const PTRACE_SETREGS: c_uint = 13; pub const PTRACE_PEEKSIGINFO_SHARED: c_uint = 1; pub const PTRACE_SYSEMU: c_uint = 31; pub const PTRACE_SYSEMU_SINGLESTEP: c_uint = 32; pub const PR_GET_SPECULATION_CTRL: c_int = 52; pub const PR_SET_SPECULATION_CTRL: c_int = 53; pub const PR_SPEC_NOT_AFFECTED: c_uint = 0; pub const PR_SPEC_PRCTL: c_uint = 1 << 0; pub const PR_SPEC_ENABLE: c_uint = 1 << 1; pub const PR_SPEC_DISABLE: c_uint = 1 << 2; pub const PR_SPEC_FORCE_DISABLE: c_uint = 1 << 3; pub const PR_SPEC_DISABLE_NOEXEC: c_uint = 1 << 4; pub const PR_SPEC_STORE_BYPASS: c_int = 0; pub const PR_SPEC_INDIRECT_BRANCH: c_int = 1; // FIXME(linux): perharps for later //pub const PR_SPEC_L1D_FLUSH: c_int = 2; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; // offsets in user_regs_structs, from sys/reg.h pub const R15: c_int = 0; pub const R14: c_int = 1; pub const R13: c_int = 2; pub const R12: c_int = 3; pub const RBP: c_int = 4; pub const RBX: c_int = 5; pub const R11: c_int = 6; pub const R10: c_int = 7; pub const R9: c_int = 8; pub const R8: c_int = 9; pub const RAX: c_int = 10; pub const RCX: c_int = 11; pub const RDX: c_int = 12; pub const RSI: c_int = 13; pub const RDI: c_int = 14; pub const ORIG_RAX: c_int = 15; pub const RIP: c_int = 16; pub const CS: c_int = 17; pub const EFLAGS: c_int = 18; pub const RSP: c_int = 19; pub const SS: c_int = 20; pub const FS_BASE: c_int = 21; pub const GS_BASE: c_int = 22; pub const DS: c_int = 23; pub const ES: c_int = 24; pub const FS: c_int = 25; pub const GS: c_int = 26; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_R8: c_int = 0; pub const REG_R9: c_int = 1; pub const REG_R10: c_int = 2; pub const REG_R11: c_int = 3; pub const REG_R12: c_int = 4; pub const REG_R13: c_int = 5; pub const REG_R14: c_int = 6; pub const REG_R15: c_int = 7; pub const REG_RDI: c_int = 8; pub const REG_RSI: c_int = 9; pub const REG_RBP: c_int = 10; pub const REG_RBX: c_int = 11; pub const REG_RDX: c_int = 12; pub const REG_RAX: c_int = 13; pub const REG_RCX: c_int = 14; pub const REG_RSP: c_int = 15; pub const REG_RIP: c_int = 16; pub const REG_EFL: c_int = 17; pub const REG_CSGSFS: c_int = 18; pub const REG_ERR: c_int = 19; pub const REG_TRAPNO: c_int = 20; pub const REG_OLDMASK: c_int = 21; pub const REG_CR2: c_int = 22; extern "C" { pub fn getcontext(ucp: *mut ucontext_t) -> c_int; pub fn setcontext(ucp: *const ucontext_t) -> c_int; pub fn makecontext(ucp: *mut ucontext_t, func: extern "C" fn(), argc: c_int, ...); pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> c_int; } cfg_if! { if #[cfg(target_pointer_width = "32")] { mod x32; pub use self::x32::*; } else { mod not_x32; pub use self::not_x32::*; } } libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs0000644000175000017500000004071615105742312022363 0ustar bdrungbdrunguse crate::prelude::*; use crate::pthread_mutex_t; s! { pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } } pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; // Syscall table pub const SYS_read: c_long = 0; pub const SYS_write: c_long = 1; pub const SYS_open: c_long = 2; pub const SYS_close: c_long = 3; pub const SYS_stat: c_long = 4; pub const SYS_fstat: c_long = 5; pub const SYS_lstat: c_long = 6; pub const SYS_poll: c_long = 7; pub const SYS_lseek: c_long = 8; pub const SYS_mmap: c_long = 9; pub const SYS_mprotect: c_long = 10; pub const SYS_munmap: c_long = 11; pub const SYS_brk: c_long = 12; pub const SYS_rt_sigaction: c_long = 13; pub const SYS_rt_sigprocmask: c_long = 14; pub const SYS_rt_sigreturn: c_long = 15; pub const SYS_ioctl: c_long = 16; pub const SYS_pread64: c_long = 17; pub const SYS_pwrite64: c_long = 18; pub const SYS_readv: c_long = 19; pub const SYS_writev: c_long = 20; pub const SYS_access: c_long = 21; pub const SYS_pipe: c_long = 22; pub const SYS_select: c_long = 23; pub const SYS_sched_yield: c_long = 24; pub const SYS_mremap: c_long = 25; pub const SYS_msync: c_long = 26; pub const SYS_mincore: c_long = 27; pub const SYS_madvise: c_long = 28; pub const SYS_shmget: c_long = 29; pub const SYS_shmat: c_long = 30; pub const SYS_shmctl: c_long = 31; pub const SYS_dup: c_long = 32; pub const SYS_dup2: c_long = 33; pub const SYS_pause: c_long = 34; pub const SYS_nanosleep: c_long = 35; pub const SYS_getitimer: c_long = 36; pub const SYS_alarm: c_long = 37; pub const SYS_setitimer: c_long = 38; pub const SYS_getpid: c_long = 39; pub const SYS_sendfile: c_long = 40; pub const SYS_socket: c_long = 41; pub const SYS_connect: c_long = 42; pub const SYS_accept: c_long = 43; pub const SYS_sendto: c_long = 44; pub const SYS_recvfrom: c_long = 45; pub const SYS_sendmsg: c_long = 46; pub const SYS_recvmsg: c_long = 47; pub const SYS_shutdown: c_long = 48; pub const SYS_bind: c_long = 49; pub const SYS_listen: c_long = 50; pub const SYS_getsockname: c_long = 51; pub const SYS_getpeername: c_long = 52; pub const SYS_socketpair: c_long = 53; pub const SYS_setsockopt: c_long = 54; pub const SYS_getsockopt: c_long = 55; pub const SYS_clone: c_long = 56; pub const SYS_fork: c_long = 57; pub const SYS_vfork: c_long = 58; pub const SYS_execve: c_long = 59; pub const SYS_exit: c_long = 60; pub const SYS_wait4: c_long = 61; pub const SYS_kill: c_long = 62; pub const SYS_uname: c_long = 63; pub const SYS_semget: c_long = 64; pub const SYS_semop: c_long = 65; pub const SYS_semctl: c_long = 66; pub const SYS_shmdt: c_long = 67; pub const SYS_msgget: c_long = 68; pub const SYS_msgsnd: c_long = 69; pub const SYS_msgrcv: c_long = 70; pub const SYS_msgctl: c_long = 71; pub const SYS_fcntl: c_long = 72; pub const SYS_flock: c_long = 73; pub const SYS_fsync: c_long = 74; pub const SYS_fdatasync: c_long = 75; pub const SYS_truncate: c_long = 76; pub const SYS_ftruncate: c_long = 77; pub const SYS_getdents: c_long = 78; pub const SYS_getcwd: c_long = 79; pub const SYS_chdir: c_long = 80; pub const SYS_fchdir: c_long = 81; pub const SYS_rename: c_long = 82; pub const SYS_mkdir: c_long = 83; pub const SYS_rmdir: c_long = 84; pub const SYS_creat: c_long = 85; pub const SYS_link: c_long = 86; pub const SYS_unlink: c_long = 87; pub const SYS_symlink: c_long = 88; pub const SYS_readlink: c_long = 89; pub const SYS_chmod: c_long = 90; pub const SYS_fchmod: c_long = 91; pub const SYS_chown: c_long = 92; pub const SYS_fchown: c_long = 93; pub const SYS_lchown: c_long = 94; pub const SYS_umask: c_long = 95; pub const SYS_gettimeofday: c_long = 96; pub const SYS_getrlimit: c_long = 97; pub const SYS_getrusage: c_long = 98; pub const SYS_sysinfo: c_long = 99; pub const SYS_times: c_long = 100; pub const SYS_ptrace: c_long = 101; pub const SYS_getuid: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_getgid: c_long = 104; pub const SYS_setuid: c_long = 105; pub const SYS_setgid: c_long = 106; pub const SYS_geteuid: c_long = 107; pub const SYS_getegid: c_long = 108; pub const SYS_setpgid: c_long = 109; pub const SYS_getppid: c_long = 110; pub const SYS_getpgrp: c_long = 111; pub const SYS_setsid: c_long = 112; pub const SYS_setreuid: c_long = 113; pub const SYS_setregid: c_long = 114; pub const SYS_getgroups: c_long = 115; pub const SYS_setgroups: c_long = 116; pub const SYS_setresuid: c_long = 117; pub const SYS_getresuid: c_long = 118; pub const SYS_setresgid: c_long = 119; pub const SYS_getresgid: c_long = 120; pub const SYS_getpgid: c_long = 121; pub const SYS_setfsuid: c_long = 122; pub const SYS_setfsgid: c_long = 123; pub const SYS_getsid: c_long = 124; pub const SYS_capget: c_long = 125; pub const SYS_capset: c_long = 126; pub const SYS_rt_sigpending: c_long = 127; pub const SYS_rt_sigtimedwait: c_long = 128; pub const SYS_rt_sigqueueinfo: c_long = 129; pub const SYS_rt_sigsuspend: c_long = 130; pub const SYS_sigaltstack: c_long = 131; pub const SYS_utime: c_long = 132; pub const SYS_mknod: c_long = 133; pub const SYS_uselib: c_long = 134; pub const SYS_personality: c_long = 135; pub const SYS_ustat: c_long = 136; pub const SYS_statfs: c_long = 137; pub const SYS_fstatfs: c_long = 138; pub const SYS_sysfs: c_long = 139; pub const SYS_getpriority: c_long = 140; pub const SYS_setpriority: c_long = 141; pub const SYS_sched_setparam: c_long = 142; pub const SYS_sched_getparam: c_long = 143; pub const SYS_sched_setscheduler: c_long = 144; pub const SYS_sched_getscheduler: c_long = 145; pub const SYS_sched_get_priority_max: c_long = 146; pub const SYS_sched_get_priority_min: c_long = 147; pub const SYS_sched_rr_get_interval: c_long = 148; pub const SYS_mlock: c_long = 149; pub const SYS_munlock: c_long = 150; pub const SYS_mlockall: c_long = 151; pub const SYS_munlockall: c_long = 152; pub const SYS_vhangup: c_long = 153; pub const SYS_modify_ldt: c_long = 154; pub const SYS_pivot_root: c_long = 155; pub const SYS__sysctl: c_long = 156; pub const SYS_prctl: c_long = 157; pub const SYS_arch_prctl: c_long = 158; pub const SYS_adjtimex: c_long = 159; pub const SYS_setrlimit: c_long = 160; pub const SYS_chroot: c_long = 161; pub const SYS_sync: c_long = 162; pub const SYS_acct: c_long = 163; pub const SYS_settimeofday: c_long = 164; pub const SYS_mount: c_long = 165; pub const SYS_umount2: c_long = 166; pub const SYS_swapon: c_long = 167; pub const SYS_swapoff: c_long = 168; pub const SYS_reboot: c_long = 169; pub const SYS_sethostname: c_long = 170; pub const SYS_setdomainname: c_long = 171; pub const SYS_iopl: c_long = 172; pub const SYS_ioperm: c_long = 173; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 174; pub const SYS_init_module: c_long = 175; pub const SYS_delete_module: c_long = 176; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 177; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 178; pub const SYS_quotactl: c_long = 179; pub const SYS_nfsservctl: c_long = 180; pub const SYS_getpmsg: c_long = 181; pub const SYS_putpmsg: c_long = 182; pub const SYS_afs_syscall: c_long = 183; pub const SYS_tuxcall: c_long = 184; pub const SYS_security: c_long = 185; pub const SYS_gettid: c_long = 186; pub const SYS_readahead: c_long = 187; pub const SYS_setxattr: c_long = 188; pub const SYS_lsetxattr: c_long = 189; pub const SYS_fsetxattr: c_long = 190; pub const SYS_getxattr: c_long = 191; pub const SYS_lgetxattr: c_long = 192; pub const SYS_fgetxattr: c_long = 193; pub const SYS_listxattr: c_long = 194; pub const SYS_llistxattr: c_long = 195; pub const SYS_flistxattr: c_long = 196; pub const SYS_removexattr: c_long = 197; pub const SYS_lremovexattr: c_long = 198; pub const SYS_fremovexattr: c_long = 199; pub const SYS_tkill: c_long = 200; pub const SYS_time: c_long = 201; pub const SYS_futex: c_long = 202; pub const SYS_sched_setaffinity: c_long = 203; pub const SYS_sched_getaffinity: c_long = 204; pub const SYS_set_thread_area: c_long = 205; pub const SYS_io_setup: c_long = 206; pub const SYS_io_destroy: c_long = 207; pub const SYS_io_getevents: c_long = 208; pub const SYS_io_submit: c_long = 209; pub const SYS_io_cancel: c_long = 210; pub const SYS_get_thread_area: c_long = 211; pub const SYS_lookup_dcookie: c_long = 212; pub const SYS_epoll_create: c_long = 213; pub const SYS_epoll_ctl_old: c_long = 214; pub const SYS_epoll_wait_old: c_long = 215; pub const SYS_remap_file_pages: c_long = 216; pub const SYS_getdents64: c_long = 217; pub const SYS_set_tid_address: c_long = 218; pub const SYS_restart_syscall: c_long = 219; pub const SYS_semtimedop: c_long = 220; pub const SYS_fadvise64: c_long = 221; pub const SYS_timer_create: c_long = 222; pub const SYS_timer_settime: c_long = 223; pub const SYS_timer_gettime: c_long = 224; pub const SYS_timer_getoverrun: c_long = 225; pub const SYS_timer_delete: c_long = 226; pub const SYS_clock_settime: c_long = 227; pub const SYS_clock_gettime: c_long = 228; pub const SYS_clock_getres: c_long = 229; pub const SYS_clock_nanosleep: c_long = 230; pub const SYS_exit_group: c_long = 231; pub const SYS_epoll_wait: c_long = 232; pub const SYS_epoll_ctl: c_long = 233; pub const SYS_tgkill: c_long = 234; pub const SYS_utimes: c_long = 235; pub const SYS_vserver: c_long = 236; pub const SYS_mbind: c_long = 237; pub const SYS_set_mempolicy: c_long = 238; pub const SYS_get_mempolicy: c_long = 239; pub const SYS_mq_open: c_long = 240; pub const SYS_mq_unlink: c_long = 241; pub const SYS_mq_timedsend: c_long = 242; pub const SYS_mq_timedreceive: c_long = 243; pub const SYS_mq_notify: c_long = 244; pub const SYS_mq_getsetattr: c_long = 245; pub const SYS_kexec_load: c_long = 246; pub const SYS_waitid: c_long = 247; pub const SYS_add_key: c_long = 248; pub const SYS_request_key: c_long = 249; pub const SYS_keyctl: c_long = 250; pub const SYS_ioprio_set: c_long = 251; pub const SYS_ioprio_get: c_long = 252; pub const SYS_inotify_init: c_long = 253; pub const SYS_inotify_add_watch: c_long = 254; pub const SYS_inotify_rm_watch: c_long = 255; pub const SYS_migrate_pages: c_long = 256; pub const SYS_openat: c_long = 257; pub const SYS_mkdirat: c_long = 258; pub const SYS_mknodat: c_long = 259; pub const SYS_fchownat: c_long = 260; pub const SYS_futimesat: c_long = 261; pub const SYS_newfstatat: c_long = 262; pub const SYS_unlinkat: c_long = 263; pub const SYS_renameat: c_long = 264; pub const SYS_linkat: c_long = 265; pub const SYS_symlinkat: c_long = 266; pub const SYS_readlinkat: c_long = 267; pub const SYS_fchmodat: c_long = 268; pub const SYS_faccessat: c_long = 269; pub const SYS_pselect6: c_long = 270; pub const SYS_ppoll: c_long = 271; pub const SYS_unshare: c_long = 272; pub const SYS_set_robust_list: c_long = 273; pub const SYS_get_robust_list: c_long = 274; pub const SYS_splice: c_long = 275; pub const SYS_tee: c_long = 276; pub const SYS_sync_file_range: c_long = 277; pub const SYS_vmsplice: c_long = 278; pub const SYS_move_pages: c_long = 279; pub const SYS_utimensat: c_long = 280; pub const SYS_epoll_pwait: c_long = 281; pub const SYS_signalfd: c_long = 282; pub const SYS_timerfd_create: c_long = 283; pub const SYS_eventfd: c_long = 284; pub const SYS_fallocate: c_long = 285; pub const SYS_timerfd_settime: c_long = 286; pub const SYS_timerfd_gettime: c_long = 287; pub const SYS_accept4: c_long = 288; pub const SYS_signalfd4: c_long = 289; pub const SYS_eventfd2: c_long = 290; pub const SYS_epoll_create1: c_long = 291; pub const SYS_dup3: c_long = 292; pub const SYS_pipe2: c_long = 293; pub const SYS_inotify_init1: c_long = 294; pub const SYS_preadv: c_long = 295; pub const SYS_pwritev: c_long = 296; pub const SYS_rt_tgsigqueueinfo: c_long = 297; pub const SYS_perf_event_open: c_long = 298; pub const SYS_recvmmsg: c_long = 299; pub const SYS_fanotify_init: c_long = 300; pub const SYS_fanotify_mark: c_long = 301; pub const SYS_prlimit64: c_long = 302; pub const SYS_name_to_handle_at: c_long = 303; pub const SYS_open_by_handle_at: c_long = 304; pub const SYS_clock_adjtime: c_long = 305; pub const SYS_syncfs: c_long = 306; pub const SYS_sendmmsg: c_long = 307; pub const SYS_setns: c_long = 308; pub const SYS_getcpu: c_long = 309; pub const SYS_process_vm_readv: c_long = 310; pub const SYS_process_vm_writev: c_long = 311; pub const SYS_kcmp: c_long = 312; pub const SYS_finit_module: c_long = 313; pub const SYS_sched_setattr: c_long = 314; pub const SYS_sched_getattr: c_long = 315; pub const SYS_renameat2: c_long = 316; pub const SYS_seccomp: c_long = 317; pub const SYS_getrandom: c_long = 318; pub const SYS_memfd_create: c_long = 319; pub const SYS_kexec_file_load: c_long = 320; pub const SYS_bpf: c_long = 321; pub const SYS_execveat: c_long = 322; pub const SYS_userfaultfd: c_long = 323; pub const SYS_membarrier: c_long = 324; pub const SYS_mlock2: c_long = 325; pub const SYS_copy_file_range: c_long = 326; pub const SYS_preadv2: c_long = 327; pub const SYS_pwritev2: c_long = 328; pub const SYS_pkey_mprotect: c_long = 329; pub const SYS_pkey_alloc: c_long = 330; pub const SYS_pkey_free: c_long = 331; pub const SYS_statx: c_long = 332; pub const SYS_rseq: c_long = 334; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_fchmodat2: c_long = 452; pub const SYS_mseal: c_long = 462; extern "C" { pub fn sysctl( name: *mut c_int, namelen: c_int, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; } libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs0000644000175000017500000005276315105742312021510 0ustar bdrungbdrunguse crate::prelude::*; use crate::pthread_mutex_t; s! { pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } } pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 44; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; // Syscall table pub const __X32_SYSCALL_BIT: c_long = 0x40000000; pub const SYS_read: c_long = __X32_SYSCALL_BIT + 0; pub const SYS_write: c_long = __X32_SYSCALL_BIT + 1; pub const SYS_open: c_long = __X32_SYSCALL_BIT + 2; pub const SYS_close: c_long = __X32_SYSCALL_BIT + 3; pub const SYS_stat: c_long = __X32_SYSCALL_BIT + 4; pub const SYS_fstat: c_long = __X32_SYSCALL_BIT + 5; pub const SYS_lstat: c_long = __X32_SYSCALL_BIT + 6; pub const SYS_poll: c_long = __X32_SYSCALL_BIT + 7; pub const SYS_lseek: c_long = __X32_SYSCALL_BIT + 8; pub const SYS_mmap: c_long = __X32_SYSCALL_BIT + 9; pub const SYS_mprotect: c_long = __X32_SYSCALL_BIT + 10; pub const SYS_munmap: c_long = __X32_SYSCALL_BIT + 11; pub const SYS_brk: c_long = __X32_SYSCALL_BIT + 12; pub const SYS_rt_sigprocmask: c_long = __X32_SYSCALL_BIT + 14; pub const SYS_pread64: c_long = __X32_SYSCALL_BIT + 17; pub const SYS_pwrite64: c_long = __X32_SYSCALL_BIT + 18; pub const SYS_access: c_long = __X32_SYSCALL_BIT + 21; pub const SYS_pipe: c_long = __X32_SYSCALL_BIT + 22; pub const SYS_select: c_long = __X32_SYSCALL_BIT + 23; pub const SYS_sched_yield: c_long = __X32_SYSCALL_BIT + 24; pub const SYS_mremap: c_long = __X32_SYSCALL_BIT + 25; pub const SYS_msync: c_long = __X32_SYSCALL_BIT + 26; pub const SYS_mincore: c_long = __X32_SYSCALL_BIT + 27; pub const SYS_madvise: c_long = __X32_SYSCALL_BIT + 28; pub const SYS_shmget: c_long = __X32_SYSCALL_BIT + 29; pub const SYS_shmat: c_long = __X32_SYSCALL_BIT + 30; pub const SYS_shmctl: c_long = __X32_SYSCALL_BIT + 31; pub const SYS_dup: c_long = __X32_SYSCALL_BIT + 32; pub const SYS_dup2: c_long = __X32_SYSCALL_BIT + 33; pub const SYS_pause: c_long = __X32_SYSCALL_BIT + 34; pub const SYS_nanosleep: c_long = __X32_SYSCALL_BIT + 35; pub const SYS_getitimer: c_long = __X32_SYSCALL_BIT + 36; pub const SYS_alarm: c_long = __X32_SYSCALL_BIT + 37; pub const SYS_setitimer: c_long = __X32_SYSCALL_BIT + 38; pub const SYS_getpid: c_long = __X32_SYSCALL_BIT + 39; pub const SYS_sendfile: c_long = __X32_SYSCALL_BIT + 40; pub const SYS_socket: c_long = __X32_SYSCALL_BIT + 41; pub const SYS_connect: c_long = __X32_SYSCALL_BIT + 42; pub const SYS_accept: c_long = __X32_SYSCALL_BIT + 43; pub const SYS_sendto: c_long = __X32_SYSCALL_BIT + 44; pub const SYS_shutdown: c_long = __X32_SYSCALL_BIT + 48; pub const SYS_bind: c_long = __X32_SYSCALL_BIT + 49; pub const SYS_listen: c_long = __X32_SYSCALL_BIT + 50; pub const SYS_getsockname: c_long = __X32_SYSCALL_BIT + 51; pub const SYS_getpeername: c_long = __X32_SYSCALL_BIT + 52; pub const SYS_socketpair: c_long = __X32_SYSCALL_BIT + 53; pub const SYS_clone: c_long = __X32_SYSCALL_BIT + 56; pub const SYS_fork: c_long = __X32_SYSCALL_BIT + 57; pub const SYS_vfork: c_long = __X32_SYSCALL_BIT + 58; pub const SYS_exit: c_long = __X32_SYSCALL_BIT + 60; pub const SYS_wait4: c_long = __X32_SYSCALL_BIT + 61; pub const SYS_kill: c_long = __X32_SYSCALL_BIT + 62; pub const SYS_uname: c_long = __X32_SYSCALL_BIT + 63; pub const SYS_semget: c_long = __X32_SYSCALL_BIT + 64; pub const SYS_semop: c_long = __X32_SYSCALL_BIT + 65; pub const SYS_semctl: c_long = __X32_SYSCALL_BIT + 66; pub const SYS_shmdt: c_long = __X32_SYSCALL_BIT + 67; pub const SYS_msgget: c_long = __X32_SYSCALL_BIT + 68; pub const SYS_msgsnd: c_long = __X32_SYSCALL_BIT + 69; pub const SYS_msgrcv: c_long = __X32_SYSCALL_BIT + 70; pub const SYS_msgctl: c_long = __X32_SYSCALL_BIT + 71; pub const SYS_fcntl: c_long = __X32_SYSCALL_BIT + 72; pub const SYS_flock: c_long = __X32_SYSCALL_BIT + 73; pub const SYS_fsync: c_long = __X32_SYSCALL_BIT + 74; pub const SYS_fdatasync: c_long = __X32_SYSCALL_BIT + 75; pub const SYS_truncate: c_long = __X32_SYSCALL_BIT + 76; pub const SYS_ftruncate: c_long = __X32_SYSCALL_BIT + 77; pub const SYS_getdents: c_long = __X32_SYSCALL_BIT + 78; pub const SYS_getcwd: c_long = __X32_SYSCALL_BIT + 79; pub const SYS_chdir: c_long = __X32_SYSCALL_BIT + 80; pub const SYS_fchdir: c_long = __X32_SYSCALL_BIT + 81; pub const SYS_rename: c_long = __X32_SYSCALL_BIT + 82; pub const SYS_mkdir: c_long = __X32_SYSCALL_BIT + 83; pub const SYS_rmdir: c_long = __X32_SYSCALL_BIT + 84; pub const SYS_creat: c_long = __X32_SYSCALL_BIT + 85; pub const SYS_link: c_long = __X32_SYSCALL_BIT + 86; pub const SYS_unlink: c_long = __X32_SYSCALL_BIT + 87; pub const SYS_symlink: c_long = __X32_SYSCALL_BIT + 88; pub const SYS_readlink: c_long = __X32_SYSCALL_BIT + 89; pub const SYS_chmod: c_long = __X32_SYSCALL_BIT + 90; pub const SYS_fchmod: c_long = __X32_SYSCALL_BIT + 91; pub const SYS_chown: c_long = __X32_SYSCALL_BIT + 92; pub const SYS_fchown: c_long = __X32_SYSCALL_BIT + 93; pub const SYS_lchown: c_long = __X32_SYSCALL_BIT + 94; pub const SYS_umask: c_long = __X32_SYSCALL_BIT + 95; pub const SYS_gettimeofday: c_long = __X32_SYSCALL_BIT + 96; pub const SYS_getrlimit: c_long = __X32_SYSCALL_BIT + 97; pub const SYS_getrusage: c_long = __X32_SYSCALL_BIT + 98; pub const SYS_sysinfo: c_long = __X32_SYSCALL_BIT + 99; pub const SYS_times: c_long = __X32_SYSCALL_BIT + 100; pub const SYS_getuid: c_long = __X32_SYSCALL_BIT + 102; pub const SYS_syslog: c_long = __X32_SYSCALL_BIT + 103; pub const SYS_getgid: c_long = __X32_SYSCALL_BIT + 104; pub const SYS_setuid: c_long = __X32_SYSCALL_BIT + 105; pub const SYS_setgid: c_long = __X32_SYSCALL_BIT + 106; pub const SYS_geteuid: c_long = __X32_SYSCALL_BIT + 107; pub const SYS_getegid: c_long = __X32_SYSCALL_BIT + 108; pub const SYS_setpgid: c_long = __X32_SYSCALL_BIT + 109; pub const SYS_getppid: c_long = __X32_SYSCALL_BIT + 110; pub const SYS_getpgrp: c_long = __X32_SYSCALL_BIT + 111; pub const SYS_setsid: c_long = __X32_SYSCALL_BIT + 112; pub const SYS_setreuid: c_long = __X32_SYSCALL_BIT + 113; pub const SYS_setregid: c_long = __X32_SYSCALL_BIT + 114; pub const SYS_getgroups: c_long = __X32_SYSCALL_BIT + 115; pub const SYS_setgroups: c_long = __X32_SYSCALL_BIT + 116; pub const SYS_setresuid: c_long = __X32_SYSCALL_BIT + 117; pub const SYS_getresuid: c_long = __X32_SYSCALL_BIT + 118; pub const SYS_setresgid: c_long = __X32_SYSCALL_BIT + 119; pub const SYS_getresgid: c_long = __X32_SYSCALL_BIT + 120; pub const SYS_getpgid: c_long = __X32_SYSCALL_BIT + 121; pub const SYS_setfsuid: c_long = __X32_SYSCALL_BIT + 122; pub const SYS_setfsgid: c_long = __X32_SYSCALL_BIT + 123; pub const SYS_getsid: c_long = __X32_SYSCALL_BIT + 124; pub const SYS_capget: c_long = __X32_SYSCALL_BIT + 125; pub const SYS_capset: c_long = __X32_SYSCALL_BIT + 126; pub const SYS_rt_sigsuspend: c_long = __X32_SYSCALL_BIT + 130; pub const SYS_utime: c_long = __X32_SYSCALL_BIT + 132; pub const SYS_mknod: c_long = __X32_SYSCALL_BIT + 133; pub const SYS_personality: c_long = __X32_SYSCALL_BIT + 135; pub const SYS_ustat: c_long = __X32_SYSCALL_BIT + 136; pub const SYS_statfs: c_long = __X32_SYSCALL_BIT + 137; pub const SYS_fstatfs: c_long = __X32_SYSCALL_BIT + 138; pub const SYS_sysfs: c_long = __X32_SYSCALL_BIT + 139; pub const SYS_getpriority: c_long = __X32_SYSCALL_BIT + 140; pub const SYS_setpriority: c_long = __X32_SYSCALL_BIT + 141; pub const SYS_sched_setparam: c_long = __X32_SYSCALL_BIT + 142; pub const SYS_sched_getparam: c_long = __X32_SYSCALL_BIT + 143; pub const SYS_sched_setscheduler: c_long = __X32_SYSCALL_BIT + 144; pub const SYS_sched_getscheduler: c_long = __X32_SYSCALL_BIT + 145; pub const SYS_sched_get_priority_max: c_long = __X32_SYSCALL_BIT + 146; pub const SYS_sched_get_priority_min: c_long = __X32_SYSCALL_BIT + 147; pub const SYS_sched_rr_get_interval: c_long = __X32_SYSCALL_BIT + 148; pub const SYS_mlock: c_long = __X32_SYSCALL_BIT + 149; pub const SYS_munlock: c_long = __X32_SYSCALL_BIT + 150; pub const SYS_mlockall: c_long = __X32_SYSCALL_BIT + 151; pub const SYS_munlockall: c_long = __X32_SYSCALL_BIT + 152; pub const SYS_vhangup: c_long = __X32_SYSCALL_BIT + 153; pub const SYS_modify_ldt: c_long = __X32_SYSCALL_BIT + 154; pub const SYS_pivot_root: c_long = __X32_SYSCALL_BIT + 155; pub const SYS_prctl: c_long = __X32_SYSCALL_BIT + 157; pub const SYS_arch_prctl: c_long = __X32_SYSCALL_BIT + 158; pub const SYS_adjtimex: c_long = __X32_SYSCALL_BIT + 159; pub const SYS_setrlimit: c_long = __X32_SYSCALL_BIT + 160; pub const SYS_chroot: c_long = __X32_SYSCALL_BIT + 161; pub const SYS_sync: c_long = __X32_SYSCALL_BIT + 162; pub const SYS_acct: c_long = __X32_SYSCALL_BIT + 163; pub const SYS_settimeofday: c_long = __X32_SYSCALL_BIT + 164; pub const SYS_mount: c_long = __X32_SYSCALL_BIT + 165; pub const SYS_umount2: c_long = __X32_SYSCALL_BIT + 166; pub const SYS_swapon: c_long = __X32_SYSCALL_BIT + 167; pub const SYS_swapoff: c_long = __X32_SYSCALL_BIT + 168; pub const SYS_reboot: c_long = __X32_SYSCALL_BIT + 169; pub const SYS_sethostname: c_long = __X32_SYSCALL_BIT + 170; pub const SYS_setdomainname: c_long = __X32_SYSCALL_BIT + 171; pub const SYS_iopl: c_long = __X32_SYSCALL_BIT + 172; pub const SYS_ioperm: c_long = __X32_SYSCALL_BIT + 173; pub const SYS_init_module: c_long = __X32_SYSCALL_BIT + 175; pub const SYS_delete_module: c_long = __X32_SYSCALL_BIT + 176; pub const SYS_quotactl: c_long = __X32_SYSCALL_BIT + 179; pub const SYS_getpmsg: c_long = __X32_SYSCALL_BIT + 181; pub const SYS_putpmsg: c_long = __X32_SYSCALL_BIT + 182; pub const SYS_afs_syscall: c_long = __X32_SYSCALL_BIT + 183; pub const SYS_tuxcall: c_long = __X32_SYSCALL_BIT + 184; pub const SYS_security: c_long = __X32_SYSCALL_BIT + 185; pub const SYS_gettid: c_long = __X32_SYSCALL_BIT + 186; pub const SYS_readahead: c_long = __X32_SYSCALL_BIT + 187; pub const SYS_setxattr: c_long = __X32_SYSCALL_BIT + 188; pub const SYS_lsetxattr: c_long = __X32_SYSCALL_BIT + 189; pub const SYS_fsetxattr: c_long = __X32_SYSCALL_BIT + 190; pub const SYS_getxattr: c_long = __X32_SYSCALL_BIT + 191; pub const SYS_lgetxattr: c_long = __X32_SYSCALL_BIT + 192; pub const SYS_fgetxattr: c_long = __X32_SYSCALL_BIT + 193; pub const SYS_listxattr: c_long = __X32_SYSCALL_BIT + 194; pub const SYS_llistxattr: c_long = __X32_SYSCALL_BIT + 195; pub const SYS_flistxattr: c_long = __X32_SYSCALL_BIT + 196; pub const SYS_removexattr: c_long = __X32_SYSCALL_BIT + 197; pub const SYS_lremovexattr: c_long = __X32_SYSCALL_BIT + 198; pub const SYS_fremovexattr: c_long = __X32_SYSCALL_BIT + 199; pub const SYS_tkill: c_long = __X32_SYSCALL_BIT + 200; pub const SYS_time: c_long = __X32_SYSCALL_BIT + 201; pub const SYS_futex: c_long = __X32_SYSCALL_BIT + 202; pub const SYS_sched_setaffinity: c_long = __X32_SYSCALL_BIT + 203; pub const SYS_sched_getaffinity: c_long = __X32_SYSCALL_BIT + 204; pub const SYS_io_destroy: c_long = __X32_SYSCALL_BIT + 207; pub const SYS_io_getevents: c_long = __X32_SYSCALL_BIT + 208; pub const SYS_io_cancel: c_long = __X32_SYSCALL_BIT + 210; pub const SYS_lookup_dcookie: c_long = __X32_SYSCALL_BIT + 212; pub const SYS_epoll_create: c_long = __X32_SYSCALL_BIT + 213; pub const SYS_remap_file_pages: c_long = __X32_SYSCALL_BIT + 216; pub const SYS_getdents64: c_long = __X32_SYSCALL_BIT + 217; pub const SYS_set_tid_address: c_long = __X32_SYSCALL_BIT + 218; pub const SYS_restart_syscall: c_long = __X32_SYSCALL_BIT + 219; pub const SYS_semtimedop: c_long = __X32_SYSCALL_BIT + 220; pub const SYS_fadvise64: c_long = __X32_SYSCALL_BIT + 221; pub const SYS_timer_settime: c_long = __X32_SYSCALL_BIT + 223; pub const SYS_timer_gettime: c_long = __X32_SYSCALL_BIT + 224; pub const SYS_timer_getoverrun: c_long = __X32_SYSCALL_BIT + 225; pub const SYS_timer_delete: c_long = __X32_SYSCALL_BIT + 226; pub const SYS_clock_settime: c_long = __X32_SYSCALL_BIT + 227; pub const SYS_clock_gettime: c_long = __X32_SYSCALL_BIT + 228; pub const SYS_clock_getres: c_long = __X32_SYSCALL_BIT + 229; pub const SYS_clock_nanosleep: c_long = __X32_SYSCALL_BIT + 230; pub const SYS_exit_group: c_long = __X32_SYSCALL_BIT + 231; pub const SYS_epoll_wait: c_long = __X32_SYSCALL_BIT + 232; pub const SYS_epoll_ctl: c_long = __X32_SYSCALL_BIT + 233; pub const SYS_tgkill: c_long = __X32_SYSCALL_BIT + 234; pub const SYS_utimes: c_long = __X32_SYSCALL_BIT + 235; pub const SYS_mbind: c_long = __X32_SYSCALL_BIT + 237; pub const SYS_set_mempolicy: c_long = __X32_SYSCALL_BIT + 238; pub const SYS_get_mempolicy: c_long = __X32_SYSCALL_BIT + 239; pub const SYS_mq_open: c_long = __X32_SYSCALL_BIT + 240; pub const SYS_mq_unlink: c_long = __X32_SYSCALL_BIT + 241; pub const SYS_mq_timedsend: c_long = __X32_SYSCALL_BIT + 242; pub const SYS_mq_timedreceive: c_long = __X32_SYSCALL_BIT + 243; pub const SYS_mq_getsetattr: c_long = __X32_SYSCALL_BIT + 245; pub const SYS_add_key: c_long = __X32_SYSCALL_BIT + 248; pub const SYS_request_key: c_long = __X32_SYSCALL_BIT + 249; pub const SYS_keyctl: c_long = __X32_SYSCALL_BIT + 250; pub const SYS_ioprio_set: c_long = __X32_SYSCALL_BIT + 251; pub const SYS_ioprio_get: c_long = __X32_SYSCALL_BIT + 252; pub const SYS_inotify_init: c_long = __X32_SYSCALL_BIT + 253; pub const SYS_inotify_add_watch: c_long = __X32_SYSCALL_BIT + 254; pub const SYS_inotify_rm_watch: c_long = __X32_SYSCALL_BIT + 255; pub const SYS_migrate_pages: c_long = __X32_SYSCALL_BIT + 256; pub const SYS_openat: c_long = __X32_SYSCALL_BIT + 257; pub const SYS_mkdirat: c_long = __X32_SYSCALL_BIT + 258; pub const SYS_mknodat: c_long = __X32_SYSCALL_BIT + 259; pub const SYS_fchownat: c_long = __X32_SYSCALL_BIT + 260; pub const SYS_futimesat: c_long = __X32_SYSCALL_BIT + 261; pub const SYS_newfstatat: c_long = __X32_SYSCALL_BIT + 262; pub const SYS_unlinkat: c_long = __X32_SYSCALL_BIT + 263; pub const SYS_renameat: c_long = __X32_SYSCALL_BIT + 264; pub const SYS_linkat: c_long = __X32_SYSCALL_BIT + 265; pub const SYS_symlinkat: c_long = __X32_SYSCALL_BIT + 266; pub const SYS_readlinkat: c_long = __X32_SYSCALL_BIT + 267; pub const SYS_fchmodat: c_long = __X32_SYSCALL_BIT + 268; pub const SYS_faccessat: c_long = __X32_SYSCALL_BIT + 269; pub const SYS_pselect6: c_long = __X32_SYSCALL_BIT + 270; pub const SYS_ppoll: c_long = __X32_SYSCALL_BIT + 271; pub const SYS_unshare: c_long = __X32_SYSCALL_BIT + 272; pub const SYS_splice: c_long = __X32_SYSCALL_BIT + 275; pub const SYS_tee: c_long = __X32_SYSCALL_BIT + 276; pub const SYS_sync_file_range: c_long = __X32_SYSCALL_BIT + 277; pub const SYS_utimensat: c_long = __X32_SYSCALL_BIT + 280; pub const SYS_epoll_pwait: c_long = __X32_SYSCALL_BIT + 281; pub const SYS_signalfd: c_long = __X32_SYSCALL_BIT + 282; pub const SYS_timerfd_create: c_long = __X32_SYSCALL_BIT + 283; pub const SYS_eventfd: c_long = __X32_SYSCALL_BIT + 284; pub const SYS_fallocate: c_long = __X32_SYSCALL_BIT + 285; pub const SYS_timerfd_settime: c_long = __X32_SYSCALL_BIT + 286; pub const SYS_timerfd_gettime: c_long = __X32_SYSCALL_BIT + 287; pub const SYS_accept4: c_long = __X32_SYSCALL_BIT + 288; pub const SYS_signalfd4: c_long = __X32_SYSCALL_BIT + 289; pub const SYS_eventfd2: c_long = __X32_SYSCALL_BIT + 290; pub const SYS_epoll_create1: c_long = __X32_SYSCALL_BIT + 291; pub const SYS_dup3: c_long = __X32_SYSCALL_BIT + 292; pub const SYS_pipe2: c_long = __X32_SYSCALL_BIT + 293; pub const SYS_inotify_init1: c_long = __X32_SYSCALL_BIT + 294; pub const SYS_perf_event_open: c_long = __X32_SYSCALL_BIT + 298; pub const SYS_fanotify_init: c_long = __X32_SYSCALL_BIT + 300; pub const SYS_fanotify_mark: c_long = __X32_SYSCALL_BIT + 301; pub const SYS_prlimit64: c_long = __X32_SYSCALL_BIT + 302; pub const SYS_name_to_handle_at: c_long = __X32_SYSCALL_BIT + 303; pub const SYS_open_by_handle_at: c_long = __X32_SYSCALL_BIT + 304; pub const SYS_clock_adjtime: c_long = __X32_SYSCALL_BIT + 305; pub const SYS_syncfs: c_long = __X32_SYSCALL_BIT + 306; pub const SYS_setns: c_long = __X32_SYSCALL_BIT + 308; pub const SYS_getcpu: c_long = __X32_SYSCALL_BIT + 309; pub const SYS_kcmp: c_long = __X32_SYSCALL_BIT + 312; pub const SYS_finit_module: c_long = __X32_SYSCALL_BIT + 313; pub const SYS_sched_setattr: c_long = __X32_SYSCALL_BIT + 314; pub const SYS_sched_getattr: c_long = __X32_SYSCALL_BIT + 315; pub const SYS_renameat2: c_long = __X32_SYSCALL_BIT + 316; pub const SYS_seccomp: c_long = __X32_SYSCALL_BIT + 317; pub const SYS_getrandom: c_long = __X32_SYSCALL_BIT + 318; pub const SYS_memfd_create: c_long = __X32_SYSCALL_BIT + 319; pub const SYS_kexec_file_load: c_long = __X32_SYSCALL_BIT + 320; pub const SYS_bpf: c_long = __X32_SYSCALL_BIT + 321; pub const SYS_userfaultfd: c_long = __X32_SYSCALL_BIT + 323; pub const SYS_membarrier: c_long = __X32_SYSCALL_BIT + 324; pub const SYS_mlock2: c_long = __X32_SYSCALL_BIT + 325; pub const SYS_copy_file_range: c_long = __X32_SYSCALL_BIT + 326; pub const SYS_pkey_mprotect: c_long = __X32_SYSCALL_BIT + 329; pub const SYS_pkey_alloc: c_long = __X32_SYSCALL_BIT + 330; pub const SYS_pkey_free: c_long = __X32_SYSCALL_BIT + 331; pub const SYS_statx: c_long = __X32_SYSCALL_BIT + 332; pub const SYS_rseq: c_long = __X32_SYSCALL_BIT + 334; pub const SYS_pidfd_send_signal: c_long = __X32_SYSCALL_BIT + 424; pub const SYS_io_uring_setup: c_long = __X32_SYSCALL_BIT + 425; pub const SYS_io_uring_enter: c_long = __X32_SYSCALL_BIT + 426; pub const SYS_io_uring_register: c_long = __X32_SYSCALL_BIT + 427; pub const SYS_open_tree: c_long = __X32_SYSCALL_BIT + 428; pub const SYS_move_mount: c_long = __X32_SYSCALL_BIT + 429; pub const SYS_fsopen: c_long = __X32_SYSCALL_BIT + 430; pub const SYS_fsconfig: c_long = __X32_SYSCALL_BIT + 431; pub const SYS_fsmount: c_long = __X32_SYSCALL_BIT + 432; pub const SYS_fspick: c_long = __X32_SYSCALL_BIT + 433; pub const SYS_pidfd_open: c_long = __X32_SYSCALL_BIT + 434; pub const SYS_clone3: c_long = __X32_SYSCALL_BIT + 435; pub const SYS_close_range: c_long = __X32_SYSCALL_BIT + 436; pub const SYS_openat2: c_long = __X32_SYSCALL_BIT + 437; pub const SYS_pidfd_getfd: c_long = __X32_SYSCALL_BIT + 438; pub const SYS_faccessat2: c_long = __X32_SYSCALL_BIT + 439; pub const SYS_process_madvise: c_long = __X32_SYSCALL_BIT + 440; pub const SYS_epoll_pwait2: c_long = __X32_SYSCALL_BIT + 441; pub const SYS_mount_setattr: c_long = __X32_SYSCALL_BIT + 442; pub const SYS_quotactl_fd: c_long = __X32_SYSCALL_BIT + 443; pub const SYS_landlock_create_ruleset: c_long = __X32_SYSCALL_BIT + 444; pub const SYS_landlock_add_rule: c_long = __X32_SYSCALL_BIT + 445; pub const SYS_landlock_restrict_self: c_long = __X32_SYSCALL_BIT + 446; pub const SYS_memfd_secret: c_long = __X32_SYSCALL_BIT + 447; pub const SYS_process_mrelease: c_long = __X32_SYSCALL_BIT + 448; pub const SYS_futex_waitv: c_long = __X32_SYSCALL_BIT + 449; pub const SYS_set_mempolicy_home_node: c_long = __X32_SYSCALL_BIT + 450; pub const SYS_fchmodat2: c_long = __X32_SYSCALL_BIT + 452; pub const SYS_rt_sigaction: c_long = __X32_SYSCALL_BIT + 512; pub const SYS_rt_sigreturn: c_long = __X32_SYSCALL_BIT + 513; pub const SYS_ioctl: c_long = __X32_SYSCALL_BIT + 514; pub const SYS_readv: c_long = __X32_SYSCALL_BIT + 515; pub const SYS_writev: c_long = __X32_SYSCALL_BIT + 516; pub const SYS_recvfrom: c_long = __X32_SYSCALL_BIT + 517; pub const SYS_sendmsg: c_long = __X32_SYSCALL_BIT + 518; pub const SYS_recvmsg: c_long = __X32_SYSCALL_BIT + 519; pub const SYS_execve: c_long = __X32_SYSCALL_BIT + 520; pub const SYS_ptrace: c_long = __X32_SYSCALL_BIT + 521; pub const SYS_rt_sigpending: c_long = __X32_SYSCALL_BIT + 522; pub const SYS_rt_sigtimedwait: c_long = __X32_SYSCALL_BIT + 523; pub const SYS_rt_sigqueueinfo: c_long = __X32_SYSCALL_BIT + 524; pub const SYS_sigaltstack: c_long = __X32_SYSCALL_BIT + 525; pub const SYS_timer_create: c_long = __X32_SYSCALL_BIT + 526; pub const SYS_mq_notify: c_long = __X32_SYSCALL_BIT + 527; pub const SYS_kexec_load: c_long = __X32_SYSCALL_BIT + 528; pub const SYS_waitid: c_long = __X32_SYSCALL_BIT + 529; pub const SYS_set_robust_list: c_long = __X32_SYSCALL_BIT + 530; pub const SYS_get_robust_list: c_long = __X32_SYSCALL_BIT + 531; pub const SYS_vmsplice: c_long = __X32_SYSCALL_BIT + 532; pub const SYS_move_pages: c_long = __X32_SYSCALL_BIT + 533; pub const SYS_preadv: c_long = __X32_SYSCALL_BIT + 534; pub const SYS_pwritev: c_long = __X32_SYSCALL_BIT + 535; pub const SYS_rt_tgsigqueueinfo: c_long = __X32_SYSCALL_BIT + 536; pub const SYS_recvmmsg: c_long = __X32_SYSCALL_BIT + 537; pub const SYS_sendmmsg: c_long = __X32_SYSCALL_BIT + 538; pub const SYS_process_vm_readv: c_long = __X32_SYSCALL_BIT + 539; pub const SYS_process_vm_writev: c_long = __X32_SYSCALL_BIT + 540; pub const SYS_setsockopt: c_long = __X32_SYSCALL_BIT + 541; pub const SYS_getsockopt: c_long = __X32_SYSCALL_BIT + 542; pub const SYS_io_setup: c_long = __X32_SYSCALL_BIT + 543; pub const SYS_io_submit: c_long = __X32_SYSCALL_BIT + 544; pub const SYS_execveat: c_long = __X32_SYSCALL_BIT + 545; pub const SYS_preadv2: c_long = __X32_SYSCALL_BIT + 546; pub const SYS_pwritev2: c_long = __X32_SYSCALL_BIT + 547; libc/src/unix/linux_like/linux/gnu/b64/aarch64/0000775000175000017500000000000015105742312021005 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs0000644000175000017500000010006015105742312022125 0ustar bdrungbdrung//! AArch64-specific definitions for 64-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = u32; pub type nlink_t = u32; pub type blksize_t = i32; pub type suseconds_t = i64; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, #[cfg(target_arch = "sparc64")] __reserved0: c_int, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, f_spare: [crate::__fsword_t; 5], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: crate::dev_t, pub st_size: off64_t, pub st_blksize: crate::blksize_t, __pad2: c_int, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct pthread_attr_t { __size: [usize; 8], } pub struct user_regs_struct { pub regs: [c_ulonglong; 31], pub sp: c_ulonglong, pub pc: c_ulonglong, pub pstate: c_ulonglong, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_uint, pub __seq: c_ushort, __pad1: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub fault_address: c_ulonglong, pub regs: [c_ulonglong; 31], pub sp: c_ulonglong, pub pc: c_ulonglong, pub pstate: c_ulonglong, __reserved: [u64; 512], } pub struct user_fpsimd_struct { pub vregs: [crate::__uint128_t; 32], pub fpsr: c_uint, pub fpcr: c_uint, } #[repr(align(8))] pub struct clone_args { pub flags: c_ulonglong, pub pidfd: c_ulonglong, pub child_tid: c_ulonglong, pub parent_tid: c_ulonglong, pub exit_signal: c_ulonglong, pub stack: c_ulonglong, pub stack_size: c_ulonglong, pub tls: c_ulonglong, pub set_tid: c_ulonglong, pub set_tid_size: c_ulonglong, pub cgroup: c_ulonglong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f32; 8], } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_NOATIME: c_int = 0o1000000; pub const O_PATH: c_int = 0o10000000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const PTRACE_DETACH: c_uint = 17; pub const EFD_NONBLOCK: c_int = 0x800; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const SFD_NONBLOCK: c_int = 0x0800; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_CLOEXEC: c_int = 0x80000; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const O_DIRECT: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const SIGSTKSZ: size_t = 16384; pub const MINSIGSTKSZ: size_t = 5120; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; // sys/auxv.h pub const HWCAP_FP: c_ulong = 1 << 0; pub const HWCAP_ASIMD: c_ulong = 1 << 1; pub const HWCAP_EVTSTRM: c_ulong = 1 << 2; pub const HWCAP_AES: c_ulong = 1 << 3; pub const HWCAP_PMULL: c_ulong = 1 << 4; pub const HWCAP_SHA1: c_ulong = 1 << 5; pub const HWCAP_SHA2: c_ulong = 1 << 6; pub const HWCAP_CRC32: c_ulong = 1 << 7; pub const HWCAP_ATOMICS: c_ulong = 1 << 8; pub const HWCAP_FPHP: c_ulong = 1 << 9; pub const HWCAP_ASIMDHP: c_ulong = 1 << 10; pub const HWCAP_CPUID: c_ulong = 1 << 11; pub const HWCAP_ASIMDRDM: c_ulong = 1 << 12; pub const HWCAP_JSCVT: c_ulong = 1 << 13; pub const HWCAP_FCMA: c_ulong = 1 << 14; pub const HWCAP_LRCPC: c_ulong = 1 << 15; pub const HWCAP_DCPOP: c_ulong = 1 << 16; pub const HWCAP_SHA3: c_ulong = 1 << 17; pub const HWCAP_SM3: c_ulong = 1 << 18; pub const HWCAP_SM4: c_ulong = 1 << 19; pub const HWCAP_ASIMDDP: c_ulong = 1 << 20; pub const HWCAP_SHA512: c_ulong = 1 << 21; pub const HWCAP_SVE: c_ulong = 1 << 22; pub const HWCAP_ASIMDFHM: c_ulong = 1 << 23; pub const HWCAP_DIT: c_ulong = 1 << 24; pub const HWCAP_USCAT: c_ulong = 1 << 25; pub const HWCAP_ILRCPC: c_ulong = 1 << 26; pub const HWCAP_FLAGM: c_ulong = 1 << 27; pub const HWCAP_SSBS: c_ulong = 1 << 28; pub const HWCAP_SB: c_ulong = 1 << 29; pub const HWCAP_PACA: c_ulong = 1 << 30; pub const HWCAP_PACG: c_ulong = 1 << 31; // FIXME(linux): enable these again once linux-api-headers are up to date enough on CI. // See discussion in https://github.com/rust-lang/libc/pull/1638 //pub const HWCAP2_DCPODP: c_ulong = 1 << 0; //pub const HWCAP2_SVE2: c_ulong = 1 << 1; //pub const HWCAP2_SVEAES: c_ulong = 1 << 2; //pub const HWCAP2_SVEPMULL: c_ulong = 1 << 3; //pub const HWCAP2_SVEBITPERM: c_ulong = 1 << 4; //pub const HWCAP2_SVESHA3: c_ulong = 1 << 5; //pub const HWCAP2_SVESM4: c_ulong = 1 << 6; //pub const HWCAP2_FLAGM2: c_ulong = 1 << 7; //pub const HWCAP2_FRINT: c_ulong = 1 << 8; //pub const HWCAP2_MTE: c_ulong = 1 << 18; // linux/prctl.h pub const PR_PAC_RESET_KEYS: c_int = 54; pub const PR_SET_TAGGED_ADDR_CTRL: c_int = 55; pub const PR_GET_TAGGED_ADDR_CTRL: c_int = 56; pub const PR_PAC_SET_ENABLED_KEYS: c_int = 60; pub const PR_PAC_GET_ENABLED_KEYS: c_int = 61; pub const PR_TAGGED_ADDR_ENABLE: c_ulong = 1; pub const PR_PAC_APIAKEY: c_ulong = 1 << 0; pub const PR_PAC_APIBKEY: c_ulong = 1 << 1; pub const PR_PAC_APDAKEY: c_ulong = 1 << 2; pub const PR_PAC_APDBKEY: c_ulong = 1 << 3; pub const PR_PAC_APGAKEY: c_ulong = 1 << 4; pub const PR_SME_SET_VL: c_int = 63; pub const PR_SME_GET_VL: c_int = 64; pub const PR_SME_VL_LEN_MAX: c_int = 0xffff; pub const PR_SME_SET_VL_INHERIT: c_ulong = 1 << 17; pub const PR_SME_SET_VL_ONE_EXEC: c_ulong = 1 << 18; // Syscall table pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_io_getevents: c_long = 4; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_getcwd: c_long = 17; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_dup: c_long = 23; pub const SYS_dup3: c_long = 24; pub const SYS_fcntl: c_long = 25; pub const SYS_inotify_init1: c_long = 26; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_ioctl: c_long = 29; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_flock: c_long = 32; pub const SYS_mknodat: c_long = 33; pub const SYS_mkdirat: c_long = 34; pub const SYS_unlinkat: c_long = 35; pub const SYS_symlinkat: c_long = 36; pub const SYS_linkat: c_long = 37; // 38 is renameat only on LP64 pub const SYS_umount2: c_long = 39; pub const SYS_mount: c_long = 40; pub const SYS_pivot_root: c_long = 41; pub const SYS_nfsservctl: c_long = 42; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_fallocate: c_long = 47; pub const SYS_faccessat: c_long = 48; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_chroot: c_long = 51; pub const SYS_fchmod: c_long = 52; pub const SYS_fchmodat: c_long = 53; pub const SYS_fchownat: c_long = 54; pub const SYS_fchown: c_long = 55; pub const SYS_openat: c_long = 56; pub const SYS_close: c_long = 57; pub const SYS_vhangup: c_long = 58; pub const SYS_pipe2: c_long = 59; pub const SYS_quotactl: c_long = 60; pub const SYS_getdents64: c_long = 61; pub const SYS_lseek: c_long = 62; pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_signalfd4: c_long = 74; pub const SYS_vmsplice: c_long = 75; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_readlinkat: c_long = 78; pub const SYS_newfstatat: c_long = 79; pub const SYS_fstat: c_long = 80; pub const SYS_sync: c_long = 81; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; // 84 sync_file_range on LP64 and sync_file_range2 on ILP32 pub const SYS_timerfd_create: c_long = 85; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_utimensat: c_long = 88; pub const SYS_acct: c_long = 89; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_personality: c_long = 92; pub const SYS_exit: c_long = 93; pub const SYS_exit_group: c_long = 94; pub const SYS_waitid: c_long = 95; pub const SYS_set_tid_address: c_long = 96; pub const SYS_unshare: c_long = 97; pub const SYS_futex: c_long = 98; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_kexec_load: c_long = 104; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_syslog: c_long = 116; pub const SYS_ptrace: c_long = 117; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_sched_yield: c_long = 124; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_restart_syscall: c_long = 128; pub const SYS_kill: c_long = 129; pub const SYS_tkill: c_long = 130; pub const SYS_tgkill: c_long = 131; pub const SYS_sigaltstack: c_long = 132; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_setpriority: c_long = 140; pub const SYS_getpriority: c_long = 141; pub const SYS_reboot: c_long = 142; pub const SYS_setregid: c_long = 143; pub const SYS_setgid: c_long = 144; pub const SYS_setreuid: c_long = 145; pub const SYS_setuid: c_long = 146; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_times: c_long = 153; pub const SYS_setpgid: c_long = 154; pub const SYS_getpgid: c_long = 155; pub const SYS_getsid: c_long = 156; pub const SYS_setsid: c_long = 157; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_uname: c_long = 160; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; // 163 is getrlimit only on LP64 // 164 is setrlimit only on LP64 pub const SYS_getrusage: c_long = 165; pub const SYS_umask: c_long = 166; pub const SYS_prctl: c_long = 167; pub const SYS_getcpu: c_long = 168; pub const SYS_gettimeofday: c_long = 169; pub const SYS_settimeofday: c_long = 170; pub const SYS_adjtimex: c_long = 171; pub const SYS_getpid: c_long = 172; pub const SYS_getppid: c_long = 173; pub const SYS_getuid: c_long = 174; pub const SYS_geteuid: c_long = 175; pub const SYS_getgid: c_long = 176; pub const SYS_getegid: c_long = 177; pub const SYS_gettid: c_long = 178; pub const SYS_sysinfo: c_long = 179; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_msgget: c_long = 186; pub const SYS_msgctl: c_long = 187; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgsnd: c_long = 189; pub const SYS_semget: c_long = 190; pub const SYS_semctl: c_long = 191; pub const SYS_semtimedop: c_long = 192; pub const SYS_semop: c_long = 193; pub const SYS_shmget: c_long = 194; pub const SYS_shmctl: c_long = 195; pub const SYS_shmat: c_long = 196; pub const SYS_shmdt: c_long = 197; pub const SYS_socket: c_long = 198; pub const SYS_socketpair: c_long = 199; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_accept: c_long = 202; pub const SYS_connect: c_long = 203; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_shutdown: c_long = 210; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_readahead: c_long = 213; pub const SYS_brk: c_long = 214; pub const SYS_munmap: c_long = 215; pub const SYS_mremap: c_long = 216; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_mmap: c_long = 222; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_mprotect: c_long = 226; pub const SYS_msync: c_long = 227; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_mbind: c_long = 235; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_migrate_pages: c_long = 238; pub const SYS_move_pages: c_long = 239; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_accept4: c_long = 242; pub const SYS_recvmmsg: c_long = 243; pub const SYS_wait4: c_long = 260; pub const SYS_prlimit64: c_long = 261; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_setns: c_long = 268; pub const SYS_sendmmsg: c_long = 269; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_rseq: c_long = 293; pub const SYS_kexec_file_load: c_long = 294; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_mseal: c_long = 462; pub const PROT_BTI: c_int = 0x10; pub const PROT_MTE: c_int = 0x20; extern "C" { pub fn sysctl( name: *mut c_int, namelen: c_int, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; pub fn getcontext(ucp: *mut ucontext_t) -> c_int; pub fn setcontext(ucp: *const ucontext_t) -> c_int; pub fn makecontext(ucp: *mut ucontext_t, func: extern "C" fn(), argc: c_int, ...); pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> c_int; } cfg_if! { if #[cfg(target_pointer_width = "32")] { mod ilp32; pub use self::ilp32::*; } else { mod lp64; pub use self::lp64::*; } } libc/src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs0000644000175000017500000000363715105742312022313 0ustar bdrungbdrunguse crate::prelude::*; use crate::pthread_mutex_t; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 48; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const SYS_sync_file_range2: c_long = 84; libc/src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs0000644000175000017500000000446115105742312022143 0ustar bdrungbdrunguse crate::prelude::*; use crate::pthread_mutex_t; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 48; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const SYS_renameat: c_long = 38; pub const SYS_sync_file_range: c_long = 84; pub const SYS_getrlimit: c_long = 163; pub const SYS_setrlimit: c_long = 164; libc/src/unix/linux_like/linux/gnu/b64/sparc64/0000775000175000017500000000000015105742312021037 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs0000644000175000017500000007612215105742312022172 0ustar bdrungbdrung//! SPARC64-specific definitions for 64-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t, pthread_mutex_t}; pub type wchar_t = i32; pub type nlink_t = u32; pub type blksize_t = i64; pub type suseconds_t = i32; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, #[cfg(target_arch = "sparc64")] __reserved0: c_int, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, f_spare: [crate::__fsword_t; 5], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [usize; 0], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, __reserved: c_short, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct stat { pub st_dev: crate::dev_t, __pad0: u64, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: u64, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 2], } pub struct stat64 { pub st_dev: crate::dev_t, __pad0: u64, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad2: c_int, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __reserved: [c_long; 2], } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct pthread_attr_t { __size: [u64; 7], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, __pad0: u16, pub __seq: c_ushort, __unused1: c_ulonglong, __unused2: c_ulonglong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_segsz: size_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __reserved1: c_ulong, __reserved2: c_ulong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [i64; 4], } } pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const O_APPEND: c_int = 0x8; pub const O_CREAT: c_int = 0x200; pub const O_EXCL: c_int = 0x800; pub const O_NOCTTY: c_int = 0x8000; pub const O_NONBLOCK: c_int = 0x4000; pub const O_SYNC: c_int = 0x802000; pub const O_RSYNC: c_int = 0x802000; pub const O_DSYNC: c_int = 0x2000; pub const O_FSYNC: c_int = 0x802000; pub const O_NOATIME: c_int = 0x200000; pub const O_PATH: c_int = 0x1000000; pub const O_TMPFILE: c_int = 0x2000000 | O_DIRECTORY; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 0x0200; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLK: c_int = 78; pub const ENAMETOOLONG: c_int = 63; pub const ENOLCK: c_int = 79; pub const ENOSYS: c_int = 90; pub const ENOTEMPTY: c_int = 66; pub const ELOOP: c_int = 62; pub const ENOMSG: c_int = 75; pub const EIDRM: c_int = 77; pub const ECHRNG: c_int = 94; pub const EL2NSYNC: c_int = 95; pub const EL3HLT: c_int = 96; pub const EL3RST: c_int = 97; pub const ELNRNG: c_int = 98; pub const EUNATCH: c_int = 99; pub const ENOCSI: c_int = 100; pub const EL2HLT: c_int = 101; pub const EBADE: c_int = 102; pub const EBADR: c_int = 103; pub const EXFULL: c_int = 104; pub const ENOANO: c_int = 105; pub const EBADRQC: c_int = 106; pub const EBADSLT: c_int = 107; pub const EMULTIHOP: c_int = 87; pub const EOVERFLOW: c_int = 92; pub const ENOTUNIQ: c_int = 115; pub const EBADFD: c_int = 93; pub const EBADMSG: c_int = 76; pub const EREMCHG: c_int = 89; pub const ELIBACC: c_int = 114; pub const ELIBBAD: c_int = 112; pub const ELIBSCN: c_int = 124; pub const ELIBMAX: c_int = 123; pub const ELIBEXEC: c_int = 110; pub const EILSEQ: c_int = 122; pub const ERESTART: c_int = 116; pub const ESTRPIPE: c_int = 91; pub const EUSERS: c_int = 68; pub const ENOTSOCK: c_int = 38; pub const EDESTADDRREQ: c_int = 39; pub const EMSGSIZE: c_int = 40; pub const EPROTOTYPE: c_int = 41; pub const ENOPROTOOPT: c_int = 42; pub const EPROTONOSUPPORT: c_int = 43; pub const ESOCKTNOSUPPORT: c_int = 44; pub const EOPNOTSUPP: c_int = 45; pub const EPFNOSUPPORT: c_int = 46; pub const EAFNOSUPPORT: c_int = 47; pub const EADDRINUSE: c_int = 48; pub const EADDRNOTAVAIL: c_int = 49; pub const ENETDOWN: c_int = 50; pub const ENETUNREACH: c_int = 51; pub const ENETRESET: c_int = 52; pub const ECONNABORTED: c_int = 53; pub const ECONNRESET: c_int = 54; pub const ENOBUFS: c_int = 55; pub const EISCONN: c_int = 56; pub const ENOTCONN: c_int = 57; pub const ESHUTDOWN: c_int = 58; pub const ETOOMANYREFS: c_int = 59; pub const ETIMEDOUT: c_int = 60; pub const ECONNREFUSED: c_int = 61; pub const EHOSTDOWN: c_int = 64; pub const EHOSTUNREACH: c_int = 65; pub const EALREADY: c_int = 37; pub const EINPROGRESS: c_int = 36; pub const ESTALE: c_int = 70; pub const EDQUOT: c_int = 69; pub const ENOMEDIUM: c_int = 125; pub const EMEDIUMTYPE: c_int = 126; pub const ECANCELED: c_int = 127; pub const ENOKEY: c_int = 128; pub const EKEYEXPIRED: c_int = 129; pub const EKEYREVOKED: c_int = 130; pub const EKEYREJECTED: c_int = 131; pub const EOWNERDEAD: c_int = 132; pub const ENOTRECOVERABLE: c_int = 133; pub const EHWPOISON: c_int = 135; pub const ERFKILL: c_int = 134; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_ONSTACK: c_int = 1; pub const SA_SIGINFO: c_int = 0x200; pub const SA_NOCLDWAIT: c_int = 0x100; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 20; pub const SIGBUS: c_int = 10; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGCONT: c_int = 19; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGURG: c_int = 16; pub const SIGIO: c_int = 23; pub const SIGSYS: c_int = 12; pub const SIGPOLL: c_int = 23; pub const SIGPWR: c_int = 29; pub const SIG_SETMASK: c_int = 4; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const POLLWRNORM: c_short = 4; pub const POLLWRBAND: c_short = 0x100; pub const O_ASYNC: c_int = 0x40; pub const O_NDELAY: c_int = 0x4004; pub const PTRACE_DETACH: c_uint = 17; pub const EFD_NONBLOCK: c_int = 0x4000; pub const F_GETLK: c_int = 7; pub const F_GETOWN: c_int = 5; pub const F_SETOWN: c_int = 6; pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const F_RDLCK: c_int = 1; pub const F_WRLCK: c_int = 2; pub const F_UNLCK: c_int = 3; pub const SFD_NONBLOCK: c_int = 0x4000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const SFD_CLOEXEC: c_int = 0x400000; pub const NCCS: usize = 17; pub const O_TRUNC: c_int = 0x400; pub const O_CLOEXEC: c_int = 0x400000; pub const EBFONT: c_int = 109; pub const ENOSTR: c_int = 72; pub const ENODATA: c_int = 111; pub const ETIME: c_int = 73; pub const ENOSR: c_int = 74; pub const ENONET: c_int = 80; pub const ENOPKG: c_int = 113; pub const EREMOTE: c_int = 71; pub const ENOLINK: c_int = 82; pub const EADV: c_int = 83; pub const ESRMNT: c_int = 84; pub const ECOMM: c_int = 85; pub const EPROTO: c_int = 86; pub const EDOTDOT: c_int = 88; pub const SA_NODEFER: c_int = 0x20; pub const SA_RESETHAND: c_int = 0x4; pub const SA_RESTART: c_int = 0x2; pub const SA_NOCLDSTOP: c_int = 0x00000008; pub const EPOLL_CLOEXEC: c_int = 0x400000; pub const EFD_CLOEXEC: c_int = 0x400000; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const O_DIRECTORY: c_int = 0o200000; pub const O_NOFOLLOW: c_int = 0o400000; pub const O_DIRECT: c_int = 0x100000; pub const MAP_LOCKED: c_int = 0x0100; pub const MAP_NORESERVE: c_int = 0x00040; pub const EDEADLOCK: c_int = 108; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const MCL_CURRENT: c_int = 0x2000; pub const MCL_FUTURE: c_int = 0x4000; pub const MCL_ONFAULT: c_int = 0x8000; pub const SIGSTKSZ: size_t = 16384; pub const MINSIGSTKSZ: size_t = 4096; pub const CBAUD: crate::tcflag_t = 0x0000100f; pub const TAB1: crate::tcflag_t = 0x800; pub const TAB2: crate::tcflag_t = 0x1000; pub const TAB3: crate::tcflag_t = 0x1800; pub const CR1: crate::tcflag_t = 0x200; pub const CR2: crate::tcflag_t = 0x400; pub const CR3: crate::tcflag_t = 0x600; pub const FF1: crate::tcflag_t = 0x8000; pub const BS1: crate::tcflag_t = 0x2000; pub const VT1: crate::tcflag_t = 0x4000; pub const VWERASE: usize = 0xe; pub const VREPRINT: usize = 0xc; pub const VSUSP: usize = 0xa; pub const VSTART: usize = 0x8; pub const VSTOP: usize = 0x9; pub const VDISCARD: usize = 0xd; pub const VTIME: usize = 0x5; pub const IXON: crate::tcflag_t = 0x400; pub const IXOFF: crate::tcflag_t = 0x1000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x30; pub const CS6: crate::tcflag_t = 0x10; pub const CS7: crate::tcflag_t = 0x20; pub const CS8: crate::tcflag_t = 0x30; pub const CSTOPB: crate::tcflag_t = 0x40; pub const CREAD: crate::tcflag_t = 0x80; pub const PARENB: crate::tcflag_t = 0x100; pub const PARODD: crate::tcflag_t = 0x200; pub const HUPCL: crate::tcflag_t = 0x400; pub const CLOCAL: crate::tcflag_t = 0x800; pub const ECHOKE: crate::tcflag_t = 0x800; pub const ECHOE: crate::tcflag_t = 0x10; pub const ECHOK: crate::tcflag_t = 0x20; pub const ECHONL: crate::tcflag_t = 0x40; pub const ECHOPRT: crate::tcflag_t = 0x400; pub const ECHOCTL: crate::tcflag_t = 0x200; pub const ISIG: crate::tcflag_t = 0x1; pub const ICANON: crate::tcflag_t = 0x2; pub const PENDIN: crate::tcflag_t = 0x4000; pub const NOFLSH: crate::tcflag_t = 0x80; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0x00001000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0x1001; pub const B115200: crate::speed_t = 0x1002; pub const B230400: crate::speed_t = 0x1003; pub const B460800: crate::speed_t = 0x1004; pub const B76800: crate::speed_t = 0x1005; pub const B153600: crate::speed_t = 0x1006; pub const B307200: crate::speed_t = 0x1007; pub const B614400: crate::speed_t = 0x1008; pub const B921600: crate::speed_t = 0x1009; pub const B500000: crate::speed_t = 0x100a; pub const B576000: crate::speed_t = 0x100b; pub const B1000000: crate::speed_t = 0x100c; pub const B1152000: crate::speed_t = 0x100d; pub const B1500000: crate::speed_t = 0x100e; pub const B2000000: crate::speed_t = 0x100f; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: crate::tcflag_t = 0x8000; pub const TOSTOP: crate::tcflag_t = 0x100; pub const FLUSHO: crate::tcflag_t = 0x1000; pub const EXTPROC: crate::tcflag_t = 0x10000; pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_wait4: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execv: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_chown: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_brk: c_long = 17; pub const SYS_perfctr: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_capget: c_long = 21; pub const SYS_capset: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_vmsplice: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_sigaltstack: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_stat: c_long = 38; pub const SYS_sendfile: c_long = 39; pub const SYS_lstat: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_umount2: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_memory_ordering: c_long = 52; pub const SYS_ioctl: c_long = 54; pub const SYS_reboot: c_long = 55; pub const SYS_symlink: c_long = 57; pub const SYS_readlink: c_long = 58; pub const SYS_execve: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_fstat: c_long = 62; pub const SYS_fstat64: c_long = 63; pub const SYS_getpagesize: c_long = 64; pub const SYS_msync: c_long = 65; pub const SYS_vfork: c_long = 66; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_mmap: c_long = 71; pub const SYS_munmap: c_long = 73; pub const SYS_mprotect: c_long = 74; pub const SYS_madvise: c_long = 75; pub const SYS_vhangup: c_long = 76; pub const SYS_mincore: c_long = 78; pub const SYS_getgroups: c_long = 79; pub const SYS_setgroups: c_long = 80; pub const SYS_getpgrp: c_long = 81; pub const SYS_setitimer: c_long = 83; pub const SYS_swapon: c_long = 85; pub const SYS_getitimer: c_long = 86; pub const SYS_sethostname: c_long = 88; pub const SYS_dup2: c_long = 90; pub const SYS_fcntl: c_long = 92; pub const SYS_select: c_long = 93; pub const SYS_fsync: c_long = 95; pub const SYS_setpriority: c_long = 96; pub const SYS_socket: c_long = 97; pub const SYS_connect: c_long = 98; pub const SYS_accept: c_long = 99; pub const SYS_getpriority: c_long = 100; pub const SYS_rt_sigreturn: c_long = 101; pub const SYS_rt_sigaction: c_long = 102; pub const SYS_rt_sigprocmask: c_long = 103; pub const SYS_rt_sigpending: c_long = 104; pub const SYS_rt_sigtimedwait: c_long = 105; pub const SYS_rt_sigqueueinfo: c_long = 106; pub const SYS_rt_sigsuspend: c_long = 107; pub const SYS_setresuid: c_long = 108; pub const SYS_getresuid: c_long = 109; pub const SYS_setresgid: c_long = 110; pub const SYS_getresgid: c_long = 111; pub const SYS_recvmsg: c_long = 113; pub const SYS_sendmsg: c_long = 114; pub const SYS_gettimeofday: c_long = 116; pub const SYS_getrusage: c_long = 117; pub const SYS_getsockopt: c_long = 118; pub const SYS_getcwd: c_long = 119; pub const SYS_readv: c_long = 120; pub const SYS_writev: c_long = 121; pub const SYS_settimeofday: c_long = 122; pub const SYS_fchown: c_long = 123; pub const SYS_fchmod: c_long = 124; pub const SYS_recvfrom: c_long = 125; pub const SYS_setreuid: c_long = 126; pub const SYS_setregid: c_long = 127; pub const SYS_rename: c_long = 128; pub const SYS_truncate: c_long = 129; pub const SYS_ftruncate: c_long = 130; pub const SYS_flock: c_long = 131; pub const SYS_lstat64: c_long = 132; pub const SYS_sendto: c_long = 133; pub const SYS_shutdown: c_long = 134; pub const SYS_socketpair: c_long = 135; pub const SYS_mkdir: c_long = 136; pub const SYS_rmdir: c_long = 137; pub const SYS_utimes: c_long = 138; pub const SYS_stat64: c_long = 139; pub const SYS_sendfile64: c_long = 140; pub const SYS_getpeername: c_long = 141; pub const SYS_futex: c_long = 142; pub const SYS_gettid: c_long = 143; pub const SYS_getrlimit: c_long = 144; pub const SYS_setrlimit: c_long = 145; pub const SYS_pivot_root: c_long = 146; pub const SYS_prctl: c_long = 147; pub const SYS_pciconfig_read: c_long = 148; pub const SYS_pciconfig_write: c_long = 149; pub const SYS_getsockname: c_long = 150; pub const SYS_inotify_init: c_long = 151; pub const SYS_inotify_add_watch: c_long = 152; pub const SYS_poll: c_long = 153; pub const SYS_getdents64: c_long = 154; pub const SYS_inotify_rm_watch: c_long = 156; pub const SYS_statfs: c_long = 157; pub const SYS_fstatfs: c_long = 158; pub const SYS_umount: c_long = 159; pub const SYS_sched_set_affinity: c_long = 160; pub const SYS_sched_get_affinity: c_long = 161; pub const SYS_getdomainname: c_long = 162; pub const SYS_setdomainname: c_long = 163; pub const SYS_utrap_install: c_long = 164; pub const SYS_quotactl: c_long = 165; pub const SYS_set_tid_address: c_long = 166; pub const SYS_mount: c_long = 167; pub const SYS_ustat: c_long = 168; pub const SYS_setxattr: c_long = 169; pub const SYS_lsetxattr: c_long = 170; pub const SYS_fsetxattr: c_long = 171; pub const SYS_getxattr: c_long = 172; pub const SYS_lgetxattr: c_long = 173; pub const SYS_getdents: c_long = 174; pub const SYS_setsid: c_long = 175; pub const SYS_fchdir: c_long = 176; pub const SYS_fgetxattr: c_long = 177; pub const SYS_listxattr: c_long = 178; pub const SYS_llistxattr: c_long = 179; pub const SYS_flistxattr: c_long = 180; pub const SYS_removexattr: c_long = 181; pub const SYS_lremovexattr: c_long = 182; pub const SYS_sigpending: c_long = 183; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 184; pub const SYS_setpgid: c_long = 185; pub const SYS_fremovexattr: c_long = 186; pub const SYS_tkill: c_long = 187; pub const SYS_exit_group: c_long = 188; pub const SYS_uname: c_long = 189; pub const SYS_init_module: c_long = 190; pub const SYS_personality: c_long = 191; pub const SYS_remap_file_pages: c_long = 192; pub const SYS_epoll_create: c_long = 193; pub const SYS_epoll_ctl: c_long = 194; pub const SYS_epoll_wait: c_long = 195; pub const SYS_ioprio_set: c_long = 196; pub const SYS_getppid: c_long = 197; pub const SYS_sigaction: c_long = 198; pub const SYS_sgetmask: c_long = 199; pub const SYS_ssetmask: c_long = 200; pub const SYS_sigsuspend: c_long = 201; pub const SYS_oldlstat: c_long = 202; pub const SYS_uselib: c_long = 203; pub const SYS_readdir: c_long = 204; pub const SYS_readahead: c_long = 205; pub const SYS_socketcall: c_long = 206; pub const SYS_syslog: c_long = 207; pub const SYS_lookup_dcookie: c_long = 208; pub const SYS_fadvise64: c_long = 209; pub const SYS_fadvise64_64: c_long = 210; pub const SYS_tgkill: c_long = 211; pub const SYS_waitpid: c_long = 212; pub const SYS_swapoff: c_long = 213; pub const SYS_sysinfo: c_long = 214; pub const SYS_ipc: c_long = 215; pub const SYS_sigreturn: c_long = 216; pub const SYS_clone: c_long = 217; pub const SYS_ioprio_get: c_long = 218; pub const SYS_adjtimex: c_long = 219; pub const SYS_sigprocmask: c_long = 220; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 221; pub const SYS_delete_module: c_long = 222; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 223; pub const SYS_getpgid: c_long = 224; pub const SYS_bdflush: c_long = 225; pub const SYS_sysfs: c_long = 226; pub const SYS_afs_syscall: c_long = 227; pub const SYS_setfsuid: c_long = 228; pub const SYS_setfsgid: c_long = 229; pub const SYS__newselect: c_long = 230; pub const SYS_splice: c_long = 232; pub const SYS_stime: c_long = 233; pub const SYS_statfs64: c_long = 234; pub const SYS_fstatfs64: c_long = 235; pub const SYS__llseek: c_long = 236; pub const SYS_mlock: c_long = 237; pub const SYS_munlock: c_long = 238; pub const SYS_mlockall: c_long = 239; pub const SYS_munlockall: c_long = 240; pub const SYS_sched_setparam: c_long = 241; pub const SYS_sched_getparam: c_long = 242; pub const SYS_sched_setscheduler: c_long = 243; pub const SYS_sched_getscheduler: c_long = 244; pub const SYS_sched_yield: c_long = 245; pub const SYS_sched_get_priority_max: c_long = 246; pub const SYS_sched_get_priority_min: c_long = 247; pub const SYS_sched_rr_get_interval: c_long = 248; pub const SYS_nanosleep: c_long = 249; pub const SYS_mremap: c_long = 250; pub const SYS__sysctl: c_long = 251; pub const SYS_getsid: c_long = 252; pub const SYS_fdatasync: c_long = 253; pub const SYS_nfsservctl: c_long = 254; pub const SYS_sync_file_range: c_long = 255; pub const SYS_clock_settime: c_long = 256; pub const SYS_clock_gettime: c_long = 257; pub const SYS_clock_getres: c_long = 258; pub const SYS_clock_nanosleep: c_long = 259; pub const SYS_sched_getaffinity: c_long = 260; pub const SYS_sched_setaffinity: c_long = 261; pub const SYS_timer_settime: c_long = 262; pub const SYS_timer_gettime: c_long = 263; pub const SYS_timer_getoverrun: c_long = 264; pub const SYS_timer_delete: c_long = 265; pub const SYS_timer_create: c_long = 266; pub const SYS_io_setup: c_long = 268; pub const SYS_io_destroy: c_long = 269; pub const SYS_io_submit: c_long = 270; pub const SYS_io_cancel: c_long = 271; pub const SYS_io_getevents: c_long = 272; pub const SYS_mq_open: c_long = 273; pub const SYS_mq_unlink: c_long = 274; pub const SYS_mq_timedsend: c_long = 275; pub const SYS_mq_timedreceive: c_long = 276; pub const SYS_mq_notify: c_long = 277; pub const SYS_mq_getsetattr: c_long = 278; pub const SYS_waitid: c_long = 279; pub const SYS_tee: c_long = 280; pub const SYS_add_key: c_long = 281; pub const SYS_request_key: c_long = 282; pub const SYS_keyctl: c_long = 283; pub const SYS_openat: c_long = 284; pub const SYS_mkdirat: c_long = 285; pub const SYS_mknodat: c_long = 286; pub const SYS_fchownat: c_long = 287; pub const SYS_futimesat: c_long = 288; pub const SYS_fstatat64: c_long = 289; pub const SYS_unlinkat: c_long = 290; pub const SYS_renameat: c_long = 291; pub const SYS_linkat: c_long = 292; pub const SYS_symlinkat: c_long = 293; pub const SYS_readlinkat: c_long = 294; pub const SYS_fchmodat: c_long = 295; pub const SYS_faccessat: c_long = 296; pub const SYS_pselect6: c_long = 297; pub const SYS_ppoll: c_long = 298; pub const SYS_unshare: c_long = 299; pub const SYS_set_robust_list: c_long = 300; pub const SYS_get_robust_list: c_long = 301; pub const SYS_migrate_pages: c_long = 302; pub const SYS_mbind: c_long = 303; pub const SYS_get_mempolicy: c_long = 304; pub const SYS_set_mempolicy: c_long = 305; pub const SYS_kexec_load: c_long = 306; pub const SYS_move_pages: c_long = 307; pub const SYS_getcpu: c_long = 308; pub const SYS_epoll_pwait: c_long = 309; pub const SYS_utimensat: c_long = 310; pub const SYS_signalfd: c_long = 311; pub const SYS_timerfd_create: c_long = 312; pub const SYS_eventfd: c_long = 313; pub const SYS_fallocate: c_long = 314; pub const SYS_timerfd_settime: c_long = 315; pub const SYS_timerfd_gettime: c_long = 316; pub const SYS_signalfd4: c_long = 317; pub const SYS_eventfd2: c_long = 318; pub const SYS_epoll_create1: c_long = 319; pub const SYS_dup3: c_long = 320; pub const SYS_pipe2: c_long = 321; pub const SYS_inotify_init1: c_long = 322; pub const SYS_accept4: c_long = 323; pub const SYS_preadv: c_long = 324; pub const SYS_pwritev: c_long = 325; pub const SYS_rt_tgsigqueueinfo: c_long = 326; pub const SYS_perf_event_open: c_long = 327; pub const SYS_recvmmsg: c_long = 328; pub const SYS_fanotify_init: c_long = 329; pub const SYS_fanotify_mark: c_long = 330; pub const SYS_prlimit64: c_long = 331; pub const SYS_name_to_handle_at: c_long = 332; pub const SYS_open_by_handle_at: c_long = 333; pub const SYS_clock_adjtime: c_long = 334; pub const SYS_syncfs: c_long = 335; pub const SYS_sendmmsg: c_long = 336; pub const SYS_setns: c_long = 337; pub const SYS_process_vm_readv: c_long = 338; pub const SYS_process_vm_writev: c_long = 339; pub const SYS_kern_features: c_long = 340; pub const SYS_kcmp: c_long = 341; pub const SYS_finit_module: c_long = 342; pub const SYS_sched_setattr: c_long = 343; pub const SYS_sched_getattr: c_long = 344; pub const SYS_renameat2: c_long = 345; pub const SYS_seccomp: c_long = 346; pub const SYS_getrandom: c_long = 347; pub const SYS_memfd_create: c_long = 348; pub const SYS_bpf: c_long = 349; pub const SYS_execveat: c_long = 350; pub const SYS_membarrier: c_long = 351; pub const SYS_userfaultfd: c_long = 352; pub const SYS_bind: c_long = 353; pub const SYS_listen: c_long = 354; pub const SYS_setsockopt: c_long = 355; pub const SYS_mlock2: c_long = 356; pub const SYS_copy_file_range: c_long = 357; pub const SYS_preadv2: c_long = 358; pub const SYS_pwritev2: c_long = 359; pub const SYS_statx: c_long = 360; pub const SYS_rseq: c_long = 365; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; // Reserved in the kernel, but not actually implemented yet pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; extern "C" { pub fn sysctl( name: *mut c_int, namelen: c_int, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; } libc/src/unix/linux_like/linux/gnu/b64/s390x.rs0000644000175000017500000007750415105742312021024 0ustar bdrungbdrung//! s390x use crate::prelude::*; use crate::{off64_t, off_t, pthread_mutex_t}; pub type blksize_t = i64; pub type nlink_t = u64; pub type suseconds_t = i64; pub type wchar_t = i32; pub type greg_t = u64; pub type __u64 = u64; pub type __s64 = i64; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, __glibc_reserved0: c_int, pub sa_flags: c_int, pub sa_restorer: Option, pub sa_mask: crate::sigset_t, } pub struct statfs { pub f_type: c_uint, pub f_bsize: c_uint, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_uint, pub f_frsize: c_uint, pub f_flags: c_uint, f_spare: [c_uint; 4], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, _pad: c_int, _pad2: [c_long; 14], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, st_pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, __glibc_reserved: [c_long; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, st_pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, __glibc_reserved: [c_long; 3], } pub struct pthread_attr_t { __size: [c_ulong; 7], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_ushort, __pad1: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct __psw_t { pub mask: u64, pub addr: u64, } pub struct fpregset_t { pub fpc: u32, __pad: u32, pub fprs: [fpreg_t; 16], } pub struct mcontext_t { pub psw: __psw_t, pub gregs: [u64; 16], pub aregs: [u32; 16], pub fpregs: fpregset_t, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: crate::sigset_t, } pub struct statfs64 { pub f_type: c_uint, pub f_bsize: c_uint, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: c_uint, pub f_frsize: c_uint, pub f_flags: c_uint, pub f_spare: [c_uint; 4], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } } s_no_extra_traits! { // FIXME(union): This is actually a union. pub struct fpreg_t { pub d: c_double, // f: c_float, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for fpreg_t { fn eq(&self, other: &fpreg_t) -> bool { self.d == other.d } } impl Eq for fpreg_t {} impl fmt::Debug for fpreg_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fpreg_t").field("d", &self.d).finish() } } impl hash::Hash for fpreg_t { fn hash(&self, state: &mut H) { let d: u64 = unsafe { mem::transmute(self.d) }; d.hash(state); } } } } pub const POSIX_FADV_DONTNEED: c_int = 6; pub const POSIX_FADV_NOREUSE: c_int = 7; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_NOATIME: c_int = 0o1000000; pub const O_CLOEXEC: c_int = 0x80000; pub const O_PATH: c_int = 0o10000000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ECONNABORTED: c_int = 103; pub const ECONNREFUSED: c_int = 111; pub const ECONNRESET: c_int = 104; pub const EDEADLK: c_int = 35; pub const ENOSYS: c_int = 38; pub const ENOTCONN: c_int = 107; pub const ETIMEDOUT: c_int = 110; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NONBLOCK: c_int = 2048; pub const SA_NOCLDWAIT: c_int = 2; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 4; pub const SIGBUS: c_int = 7; pub const SIGSTKSZ: size_t = 0x2000; pub const MINSIGSTKSZ: size_t = 2048; pub const SIG_SETMASK: c_int = 2; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const O_NOCTTY: c_int = 256; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 17; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const PTRACE_DETACH: c_uint = 17; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const EFD_NONBLOCK: c_int = 0x800; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const SFD_NONBLOCK: c_int = 0x0800; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const VTIME: usize = 5; pub const VSWTC: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const VREPRINT: usize = 12; pub const VDISCARD: usize = 13; pub const VWERASE: usize = 14; pub const OLCUC: crate::tcflag_t = 0o000002; pub const ONLCR: crate::tcflag_t = 0o000004; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const TABDLY: crate::tcflag_t = 0o014000; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const BSDLY: crate::tcflag_t = 0o020000; pub const BS1: crate::tcflag_t = 0x00002000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const FF1: crate::tcflag_t = 0x00008000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const VT1: crate::tcflag_t = 0x00004000; pub const XTABS: crate::tcflag_t = 0o014000; pub const CBAUD: crate::speed_t = 0o010017; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const CSIZE: crate::tcflag_t = 0o000060; pub const CS6: crate::tcflag_t = 0o000020; pub const CS7: crate::tcflag_t = 0o000040; pub const CS8: crate::tcflag_t = 0o000060; pub const CSTOPB: crate::tcflag_t = 0o000100; pub const CREAD: crate::tcflag_t = 0o000200; pub const PARENB: crate::tcflag_t = 0o000400; pub const PARODD: crate::tcflag_t = 0o001000; pub const HUPCL: crate::tcflag_t = 0o002000; pub const CLOCAL: crate::tcflag_t = 0o004000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const ISIG: crate::tcflag_t = 0o000001; pub const ICANON: crate::tcflag_t = 0o000002; pub const XCASE: crate::tcflag_t = 0o000004; pub const ECHOE: crate::tcflag_t = 0o000020; pub const ECHOK: crate::tcflag_t = 0o000040; pub const ECHONL: crate::tcflag_t = 0o000100; pub const NOFLSH: crate::tcflag_t = 0o000200; pub const ECHOCTL: crate::tcflag_t = 0o001000; pub const ECHOPRT: crate::tcflag_t = 0o002000; pub const ECHOKE: crate::tcflag_t = 0o004000; pub const PENDIN: crate::tcflag_t = 0o040000; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const IXON: crate::tcflag_t = 0o002000; pub const IXOFF: crate::tcflag_t = 0o010000; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_restart_syscall: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_brk: c_long = 45; pub const SYS_signal: c_long = 48; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_setpgid: c_long = 57; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_symlink: c_long = 83; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_lookup_dcookie: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; /* Syscall for Andrew File System */ pub const SYS_getdents: c_long = 141; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 167; pub const SYS_poll: c_long = 168; pub const SYS_nfsservctl: c_long = 169; pub const SYS_prctl: c_long = 172; pub const SYS_rt_sigreturn: c_long = 173; pub const SYS_rt_sigaction: c_long = 174; pub const SYS_rt_sigprocmask: c_long = 175; pub const SYS_rt_sigpending: c_long = 176; pub const SYS_rt_sigtimedwait: c_long = 177; pub const SYS_rt_sigqueueinfo: c_long = 178; pub const SYS_rt_sigsuspend: c_long = 179; pub const SYS_pread64: c_long = 180; pub const SYS_pwrite64: c_long = 181; pub const SYS_getcwd: c_long = 183; pub const SYS_capget: c_long = 184; pub const SYS_capset: c_long = 185; pub const SYS_sigaltstack: c_long = 186; pub const SYS_sendfile: c_long = 187; pub const SYS_getpmsg: c_long = 188; pub const SYS_putpmsg: c_long = 189; pub const SYS_vfork: c_long = 190; pub const SYS_pivot_root: c_long = 217; pub const SYS_mincore: c_long = 218; pub const SYS_madvise: c_long = 219; pub const SYS_getdents64: c_long = 220; pub const SYS_readahead: c_long = 222; pub const SYS_setxattr: c_long = 224; pub const SYS_lsetxattr: c_long = 225; pub const SYS_fsetxattr: c_long = 226; pub const SYS_getxattr: c_long = 227; pub const SYS_lgetxattr: c_long = 228; pub const SYS_fgetxattr: c_long = 229; pub const SYS_listxattr: c_long = 230; pub const SYS_llistxattr: c_long = 231; pub const SYS_flistxattr: c_long = 232; pub const SYS_removexattr: c_long = 233; pub const SYS_lremovexattr: c_long = 234; pub const SYS_fremovexattr: c_long = 235; pub const SYS_gettid: c_long = 236; pub const SYS_tkill: c_long = 237; pub const SYS_futex: c_long = 238; pub const SYS_sched_setaffinity: c_long = 239; pub const SYS_sched_getaffinity: c_long = 240; pub const SYS_tgkill: c_long = 241; pub const SYS_io_setup: c_long = 243; pub const SYS_io_destroy: c_long = 244; pub const SYS_io_getevents: c_long = 245; pub const SYS_io_submit: c_long = 246; pub const SYS_io_cancel: c_long = 247; pub const SYS_exit_group: c_long = 248; pub const SYS_epoll_create: c_long = 249; pub const SYS_epoll_ctl: c_long = 250; pub const SYS_epoll_wait: c_long = 251; pub const SYS_set_tid_address: c_long = 252; pub const SYS_fadvise64: c_long = 253; pub const SYS_timer_create: c_long = 254; pub const SYS_timer_settime: c_long = 255; pub const SYS_timer_gettime: c_long = 256; pub const SYS_timer_getoverrun: c_long = 257; pub const SYS_timer_delete: c_long = 258; pub const SYS_clock_settime: c_long = 259; pub const SYS_clock_gettime: c_long = 260; pub const SYS_clock_getres: c_long = 261; pub const SYS_clock_nanosleep: c_long = 262; pub const SYS_statfs64: c_long = 265; pub const SYS_fstatfs64: c_long = 266; pub const SYS_remap_file_pages: c_long = 267; pub const SYS_mbind: c_long = 268; pub const SYS_get_mempolicy: c_long = 269; pub const SYS_set_mempolicy: c_long = 270; pub const SYS_mq_open: c_long = 271; pub const SYS_mq_unlink: c_long = 272; pub const SYS_mq_timedsend: c_long = 273; pub const SYS_mq_timedreceive: c_long = 274; pub const SYS_mq_notify: c_long = 275; pub const SYS_mq_getsetattr: c_long = 276; pub const SYS_kexec_load: c_long = 277; pub const SYS_add_key: c_long = 278; pub const SYS_request_key: c_long = 279; pub const SYS_keyctl: c_long = 280; pub const SYS_waitid: c_long = 281; pub const SYS_ioprio_set: c_long = 282; pub const SYS_ioprio_get: c_long = 283; pub const SYS_inotify_init: c_long = 284; pub const SYS_inotify_add_watch: c_long = 285; pub const SYS_inotify_rm_watch: c_long = 286; pub const SYS_migrate_pages: c_long = 287; pub const SYS_openat: c_long = 288; pub const SYS_mkdirat: c_long = 289; pub const SYS_mknodat: c_long = 290; pub const SYS_fchownat: c_long = 291; pub const SYS_futimesat: c_long = 292; pub const SYS_unlinkat: c_long = 294; pub const SYS_renameat: c_long = 295; pub const SYS_linkat: c_long = 296; pub const SYS_symlinkat: c_long = 297; pub const SYS_readlinkat: c_long = 298; pub const SYS_fchmodat: c_long = 299; pub const SYS_faccessat: c_long = 300; pub const SYS_pselect6: c_long = 301; pub const SYS_ppoll: c_long = 302; pub const SYS_unshare: c_long = 303; pub const SYS_set_robust_list: c_long = 304; pub const SYS_get_robust_list: c_long = 305; pub const SYS_splice: c_long = 306; pub const SYS_sync_file_range: c_long = 307; pub const SYS_tee: c_long = 308; pub const SYS_vmsplice: c_long = 309; pub const SYS_move_pages: c_long = 310; pub const SYS_getcpu: c_long = 311; pub const SYS_epoll_pwait: c_long = 312; pub const SYS_utimes: c_long = 313; pub const SYS_fallocate: c_long = 314; pub const SYS_utimensat: c_long = 315; pub const SYS_signalfd: c_long = 316; pub const SYS_timerfd: c_long = 317; pub const SYS_eventfd: c_long = 318; pub const SYS_timerfd_create: c_long = 319; pub const SYS_timerfd_settime: c_long = 320; pub const SYS_timerfd_gettime: c_long = 321; pub const SYS_signalfd4: c_long = 322; pub const SYS_eventfd2: c_long = 323; pub const SYS_inotify_init1: c_long = 324; pub const SYS_pipe2: c_long = 325; pub const SYS_dup3: c_long = 326; pub const SYS_epoll_create1: c_long = 327; pub const SYS_preadv: c_long = 328; pub const SYS_pwritev: c_long = 329; pub const SYS_rt_tgsigqueueinfo: c_long = 330; pub const SYS_perf_event_open: c_long = 331; pub const SYS_fanotify_init: c_long = 332; pub const SYS_fanotify_mark: c_long = 333; pub const SYS_prlimit64: c_long = 334; pub const SYS_name_to_handle_at: c_long = 335; pub const SYS_open_by_handle_at: c_long = 336; pub const SYS_clock_adjtime: c_long = 337; pub const SYS_syncfs: c_long = 338; pub const SYS_setns: c_long = 339; pub const SYS_process_vm_readv: c_long = 340; pub const SYS_process_vm_writev: c_long = 341; pub const SYS_s390_runtime_instr: c_long = 342; pub const SYS_kcmp: c_long = 343; pub const SYS_finit_module: c_long = 344; pub const SYS_sched_setattr: c_long = 345; pub const SYS_sched_getattr: c_long = 346; pub const SYS_renameat2: c_long = 347; pub const SYS_seccomp: c_long = 348; pub const SYS_getrandom: c_long = 349; pub const SYS_memfd_create: c_long = 350; pub const SYS_bpf: c_long = 351; pub const SYS_s390_pci_mmio_write: c_long = 352; pub const SYS_s390_pci_mmio_read: c_long = 353; pub const SYS_execveat: c_long = 354; pub const SYS_userfaultfd: c_long = 355; pub const SYS_membarrier: c_long = 356; pub const SYS_recvmmsg: c_long = 357; pub const SYS_sendmmsg: c_long = 358; pub const SYS_socket: c_long = 359; pub const SYS_socketpair: c_long = 360; pub const SYS_bind: c_long = 361; pub const SYS_connect: c_long = 362; pub const SYS_listen: c_long = 363; pub const SYS_accept4: c_long = 364; pub const SYS_getsockopt: c_long = 365; pub const SYS_setsockopt: c_long = 366; pub const SYS_getsockname: c_long = 367; pub const SYS_getpeername: c_long = 368; pub const SYS_sendto: c_long = 369; pub const SYS_sendmsg: c_long = 370; pub const SYS_recvfrom: c_long = 371; pub const SYS_recvmsg: c_long = 372; pub const SYS_shutdown: c_long = 373; pub const SYS_mlock2: c_long = 374; pub const SYS_copy_file_range: c_long = 375; pub const SYS_preadv2: c_long = 376; pub const SYS_pwritev2: c_long = 377; pub const SYS_lchown: c_long = 198; pub const SYS_setuid: c_long = 213; pub const SYS_getuid: c_long = 199; pub const SYS_setgid: c_long = 214; pub const SYS_getgid: c_long = 200; pub const SYS_geteuid: c_long = 201; pub const SYS_setreuid: c_long = 203; pub const SYS_setregid: c_long = 204; pub const SYS_getrlimit: c_long = 191; pub const SYS_getgroups: c_long = 205; pub const SYS_fchown: c_long = 207; pub const SYS_setresuid: c_long = 208; pub const SYS_setresgid: c_long = 210; pub const SYS_getresgid: c_long = 211; pub const SYS_select: c_long = 142; pub const SYS_getegid: c_long = 202; pub const SYS_setgroups: c_long = 206; pub const SYS_getresuid: c_long = 209; pub const SYS_chown: c_long = 212; pub const SYS_setfsuid: c_long = 215; pub const SYS_setfsgid: c_long = 216; pub const SYS_newfstatat: c_long = 293; pub const SYS_statx: c_long = 379; pub const SYS_rseq: c_long = 383; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const SYS_mseal: c_long = 462; extern "C" { pub fn sysctl( name: *mut c_int, namelen: c_int, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; pub fn getcontext(ucp: *mut crate::ucontext_t) -> c_int; pub fn setcontext(ucp: *const crate::ucontext_t) -> c_int; pub fn makecontext(ucp: *mut crate::ucontext_t, func: extern "C" fn(), argc: c_int, ...); pub fn swapcontext(uocp: *mut crate::ucontext_t, ucp: *const crate::ucontext_t) -> c_int; } libc/src/unix/linux_like/linux/gnu/b64/riscv64/0000775000175000017500000000000015105742312021055 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs0000644000175000017500000007461415105742312022214 0ustar bdrungbdrung//! RISC-V-specific definitions for 64-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t}; pub type wchar_t = c_int; pub type nlink_t = c_uint; pub type blksize_t = c_int; pub type fsblkcnt64_t = c_ulong; pub type fsfilcnt64_t = c_ulong; pub type suseconds_t = i64; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct pthread_attr_t { __size: [c_ulong; 7], } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2usize], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct statfs { pub f_type: c_long, pub f_bsize: c_long, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, pub f_frsize: c_long, pub f_flags: c_long, pub f_spare: [c_long; 4], } pub struct statfs64 { pub f_type: c_long, pub f_bsize: c_long, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, pub f_frsize: c_long, pub f_flags: c_long, pub f_spare: [c_long; 4], } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, pub __f_spare: [c_int; 6], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt64_t, pub f_bfree: crate::fsblkcnt64_t, pub f_bavail: crate::fsblkcnt64_t, pub f_files: crate::fsfilcnt64_t, pub f_ffree: crate::fsfilcnt64_t, pub f_favail: crate::fsfilcnt64_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, pub __f_spare: [c_int; 6], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [u64; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_ushort, __pad1: c_ushort, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused5: c_ulong, __unused6: c_ulong, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct user_regs_struct { pub pc: c_ulong, pub ra: c_ulong, pub sp: c_ulong, pub gp: c_ulong, pub tp: c_ulong, pub t0: c_ulong, pub t1: c_ulong, pub t2: c_ulong, pub s0: c_ulong, pub s1: c_ulong, pub a0: c_ulong, pub a1: c_ulong, pub a2: c_ulong, pub a3: c_ulong, pub a4: c_ulong, pub a5: c_ulong, pub a6: c_ulong, pub a7: c_ulong, pub s2: c_ulong, pub s3: c_ulong, pub s4: c_ulong, pub s5: c_ulong, pub s6: c_ulong, pub s7: c_ulong, pub s8: c_ulong, pub s9: c_ulong, pub s10: c_ulong, pub s11: c_ulong, pub t3: c_ulong, pub t4: c_ulong, pub t5: c_ulong, pub t6: c_ulong, } #[repr(align(8))] pub struct clone_args { pub flags: c_ulonglong, pub pidfd: c_ulonglong, pub child_tid: c_ulonglong, pub parent_tid: c_ulonglong, pub exit_signal: c_ulonglong, pub stack: c_ulonglong, pub stack_size: c_ulonglong, pub tls: c_ulonglong, pub set_tid: c_ulonglong, pub set_tid_size: c_ulonglong, pub cgroup: c_ulonglong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct ucontext_t { pub __uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct mcontext_t { pub __gregs: [c_ulong; 32], pub __fpregs: __riscv_mc_fp_state, } pub union __riscv_mc_fp_state { pub __f: __riscv_mc_f_ext_state, pub __d: __riscv_mc_d_ext_state, pub __q: __riscv_mc_q_ext_state, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_f_ext_state { pub __f: [c_uint; 32], pub __fcsr: c_uint, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_d_ext_state { pub __f: [c_ulonglong; 32], pub __fcsr: c_uint, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct __riscv_mc_q_ext_state { pub __f: [c_ulonglong; 64], pub __fcsr: c_uint, pub __glibc_reserved: [c_uint; 3], } } pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 1052672; pub const O_NOATIME: c_int = 262144; pub const O_PATH: c_int = 2097152; pub const O_TMPFILE: c_int = 4259840; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 256; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_ONSTACK: c_int = 134217728; pub const SA_SIGINFO: c_int = 4; pub const SA_NOCLDWAIT: c_int = 2; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0; pub const SIG_UNBLOCK: c_int = 1; pub const POLLWRNORM: c_short = 256; pub const POLLWRBAND: c_short = 512; pub const O_ASYNC: c_int = 8192; pub const O_NDELAY: c_int = 2048; pub const PTRACE_DETACH: c_uint = 17; pub const EFD_NONBLOCK: c_int = 2048; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const SFD_NONBLOCK: c_int = 2048; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const SFD_CLOEXEC: c_int = 524288; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_CLOEXEC: c_int = 524288; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_int = 1073741824; pub const SA_RESETHAND: c_int = -2147483648; pub const SA_RESTART: c_int = 268435456; pub const SA_NOCLDSTOP: c_int = 1; pub const EPOLL_CLOEXEC: c_int = 524288; pub const EFD_CLOEXEC: c_int = 524288; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const O_DIRECT: c_int = 16384; pub const O_DIRECTORY: c_int = 65536; pub const O_NOFOLLOW: c_int = 131072; pub const MAP_HUGETLB: c_int = 262144; pub const MAP_LOCKED: c_int = 8192; pub const MAP_NORESERVE: c_int = 16384; pub const MAP_ANON: c_int = 32; pub const MAP_ANONYMOUS: c_int = 32; pub const MAP_DENYWRITE: c_int = 2048; pub const MAP_EXECUTABLE: c_int = 4096; pub const MAP_POPULATE: c_int = 32768; pub const MAP_NONBLOCK: c_int = 65536; pub const MAP_STACK: c_int = 131072; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 35; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const PTRACE_GETFPREGS: c_uint = 14; pub const PTRACE_SETFPREGS: c_uint = 15; pub const PTRACE_GETFPXREGS: c_uint = 18; pub const PTRACE_SETFPXREGS: c_uint = 19; pub const PTRACE_GETREGS: c_uint = 12; pub const PTRACE_SETREGS: c_uint = 13; pub const MCL_CURRENT: c_int = 1; pub const MCL_FUTURE: c_int = 2; pub const MCL_ONFAULT: c_int = 4; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 4111; pub const TAB1: crate::tcflag_t = 2048; pub const TAB2: crate::tcflag_t = 4096; pub const TAB3: crate::tcflag_t = 6144; pub const CR1: crate::tcflag_t = 512; pub const CR2: crate::tcflag_t = 1024; pub const CR3: crate::tcflag_t = 1536; pub const FF1: crate::tcflag_t = 32768; pub const BS1: crate::tcflag_t = 8192; pub const VT1: crate::tcflag_t = 16384; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 1024; pub const IXOFF: crate::tcflag_t = 4096; pub const ONLCR: crate::tcflag_t = 4; pub const CSIZE: crate::tcflag_t = 48; pub const CS6: crate::tcflag_t = 16; pub const CS7: crate::tcflag_t = 32; pub const CS8: crate::tcflag_t = 48; pub const CSTOPB: crate::tcflag_t = 64; pub const CREAD: crate::tcflag_t = 128; pub const PARENB: crate::tcflag_t = 256; pub const PARODD: crate::tcflag_t = 512; pub const HUPCL: crate::tcflag_t = 1024; pub const CLOCAL: crate::tcflag_t = 2048; pub const ECHOKE: crate::tcflag_t = 2048; pub const ECHOE: crate::tcflag_t = 16; pub const ECHOK: crate::tcflag_t = 32; pub const ECHONL: crate::tcflag_t = 64; pub const ECHOPRT: crate::tcflag_t = 1024; pub const ECHOCTL: crate::tcflag_t = 512; pub const ISIG: crate::tcflag_t = 1; pub const ICANON: crate::tcflag_t = 2; pub const PENDIN: crate::tcflag_t = 16384; pub const NOFLSH: crate::tcflag_t = 128; pub const CIBAUD: crate::tcflag_t = 269418496; pub const CBAUDEX: crate::tcflag_t = 4096; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 2; pub const NLDLY: crate::tcflag_t = 256; pub const CRDLY: crate::tcflag_t = 1536; pub const TABDLY: crate::tcflag_t = 6144; pub const BSDLY: crate::tcflag_t = 8192; pub const FFDLY: crate::tcflag_t = 32768; pub const VTDLY: crate::tcflag_t = 16384; pub const XTABS: crate::tcflag_t = 6144; pub const B0: crate::speed_t = 0; pub const B50: crate::speed_t = 1; pub const B75: crate::speed_t = 2; pub const B110: crate::speed_t = 3; pub const B134: crate::speed_t = 4; pub const B150: crate::speed_t = 5; pub const B200: crate::speed_t = 6; pub const B300: crate::speed_t = 7; pub const B600: crate::speed_t = 8; pub const B1200: crate::speed_t = 9; pub const B1800: crate::speed_t = 10; pub const B2400: crate::speed_t = 11; pub const B4800: crate::speed_t = 12; pub const B9600: crate::speed_t = 13; pub const B19200: crate::speed_t = 14; pub const B38400: crate::speed_t = 15; pub const EXTA: crate::speed_t = 14; pub const EXTB: crate::speed_t = 15; pub const B57600: crate::speed_t = 4097; pub const B115200: crate::speed_t = 4098; pub const B230400: crate::speed_t = 4099; pub const B460800: crate::speed_t = 4100; pub const B500000: crate::speed_t = 4101; pub const B576000: crate::speed_t = 4102; pub const B921600: crate::speed_t = 4103; pub const B1000000: crate::speed_t = 4104; pub const B1152000: crate::speed_t = 4105; pub const B1500000: crate::speed_t = 4106; pub const B2000000: crate::speed_t = 4107; pub const B2500000: crate::speed_t = 4108; pub const B3000000: crate::speed_t = 4109; pub const B3500000: crate::speed_t = 4110; pub const B4000000: crate::speed_t = 4111; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 32768; pub const TOSTOP: crate::tcflag_t = 256; pub const FLUSHO: crate::tcflag_t = 4096; pub const EXTPROC: crate::tcflag_t = 65536; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const NGREG: usize = 32; pub const REG_PC: usize = 0; pub const REG_RA: usize = 1; pub const REG_SP: usize = 2; pub const REG_TP: usize = 4; pub const REG_S0: usize = 8; pub const REG_S1: usize = 9; pub const REG_A0: usize = 10; pub const REG_S2: usize = 18; pub const REG_NARGS: usize = 8; pub const COMPAT_HWCAP_ISA_I: c_ulong = 1 << (b'I' - b'A'); pub const COMPAT_HWCAP_ISA_M: c_ulong = 1 << (b'M' - b'A'); pub const COMPAT_HWCAP_ISA_A: c_ulong = 1 << (b'A' - b'A'); pub const COMPAT_HWCAP_ISA_F: c_ulong = 1 << (b'F' - b'A'); pub const COMPAT_HWCAP_ISA_D: c_ulong = 1 << (b'D' - b'A'); pub const COMPAT_HWCAP_ISA_C: c_ulong = 1 << (b'C' - b'A'); pub const COMPAT_HWCAP_ISA_V: c_ulong = 1 << (b'V' - b'A'); pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_close: c_long = 57; pub const SYS_fstat: c_long = 80; pub const SYS_lseek: c_long = 62; pub const SYS_mmap: c_long = 222; pub const SYS_mprotect: c_long = 226; pub const SYS_munmap: c_long = 215; pub const SYS_brk: c_long = 214; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_ioctl: c_long = 29; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_sched_yield: c_long = 124; pub const SYS_mremap: c_long = 216; pub const SYS_msync: c_long = 227; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_shmget: c_long = 194; pub const SYS_shmat: c_long = 196; pub const SYS_shmctl: c_long = 195; pub const SYS_dup: c_long = 23; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_getpid: c_long = 172; pub const SYS_sendfile: c_long = 71; pub const SYS_socket: c_long = 198; pub const SYS_connect: c_long = 203; pub const SYS_accept: c_long = 202; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_shutdown: c_long = 210; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_socketpair: c_long = 199; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_exit: c_long = 93; pub const SYS_wait4: c_long = 260; pub const SYS_kill: c_long = 129; pub const SYS_uname: c_long = 160; pub const SYS_semget: c_long = 190; pub const SYS_semop: c_long = 193; pub const SYS_semctl: c_long = 191; pub const SYS_shmdt: c_long = 197; pub const SYS_msgget: c_long = 186; pub const SYS_msgsnd: c_long = 189; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgctl: c_long = 187; pub const SYS_fcntl: c_long = 25; pub const SYS_flock: c_long = 32; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_getcwd: c_long = 17; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_fchmod: c_long = 52; pub const SYS_fchown: c_long = 55; pub const SYS_umask: c_long = 166; pub const SYS_gettimeofday: c_long = 169; pub const SYS_getrlimit: c_long = 163; pub const SYS_getrusage: c_long = 165; pub const SYS_sysinfo: c_long = 179; pub const SYS_times: c_long = 153; pub const SYS_ptrace: c_long = 117; pub const SYS_getuid: c_long = 174; pub const SYS_syslog: c_long = 116; pub const SYS_getgid: c_long = 176; pub const SYS_setuid: c_long = 146; pub const SYS_setgid: c_long = 144; pub const SYS_geteuid: c_long = 175; pub const SYS_getegid: c_long = 177; pub const SYS_setpgid: c_long = 154; pub const SYS_getppid: c_long = 173; pub const SYS_setsid: c_long = 157; pub const SYS_setreuid: c_long = 145; pub const SYS_setregid: c_long = 143; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_getpgid: c_long = 155; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_getsid: c_long = 156; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_sigaltstack: c_long = 132; pub const SYS_personality: c_long = 92; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_getpriority: c_long = 141; pub const SYS_setpriority: c_long = 140; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_vhangup: c_long = 58; pub const SYS_pivot_root: c_long = 41; pub const SYS_prctl: c_long = 167; pub const SYS_adjtimex: c_long = 171; pub const SYS_setrlimit: c_long = 164; pub const SYS_chroot: c_long = 51; pub const SYS_sync: c_long = 81; pub const SYS_acct: c_long = 89; pub const SYS_settimeofday: c_long = 170; pub const SYS_mount: c_long = 40; pub const SYS_umount2: c_long = 39; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_reboot: c_long = 142; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_quotactl: c_long = 60; pub const SYS_nfsservctl: c_long = 42; pub const SYS_gettid: c_long = 178; pub const SYS_readahead: c_long = 213; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_tkill: c_long = 130; pub const SYS_futex: c_long = 98; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_getevents: c_long = 4; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_getdents64: c_long = 61; pub const SYS_set_tid_address: c_long = 96; pub const SYS_restart_syscall: c_long = 128; pub const SYS_semtimedop: c_long = 192; pub const SYS_fadvise64: c_long = 223; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_exit_group: c_long = 94; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_tgkill: c_long = 131; pub const SYS_mbind: c_long = 235; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_kexec_load: c_long = 104; pub const SYS_waitid: c_long = 95; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_migrate_pages: c_long = 238; pub const SYS_openat: c_long = 56; pub const SYS_mkdirat: c_long = 34; pub const SYS_mknodat: c_long = 33; pub const SYS_fchownat: c_long = 54; pub const SYS_newfstatat: c_long = 79; pub const SYS_unlinkat: c_long = 35; pub const SYS_linkat: c_long = 37; pub const SYS_symlinkat: c_long = 36; pub const SYS_readlinkat: c_long = 78; pub const SYS_fchmodat: c_long = 53; pub const SYS_faccessat: c_long = 48; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_unshare: c_long = 97; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_sync_file_range: c_long = 84; pub const SYS_vmsplice: c_long = 75; pub const SYS_move_pages: c_long = 239; pub const SYS_utimensat: c_long = 88; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_timerfd_create: c_long = 85; pub const SYS_fallocate: c_long = 47; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_accept4: c_long = 242; pub const SYS_signalfd4: c_long = 74; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_dup3: c_long = 24; pub const SYS_pipe2: c_long = 59; pub const SYS_inotify_init1: c_long = 26; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_recvmmsg: c_long = 243; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_prlimit64: c_long = 261; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_sendmmsg: c_long = 269; pub const SYS_setns: c_long = 268; pub const SYS_getcpu: c_long = 168; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_rseq: c_long = 293; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; libc/src/unix/linux_like/linux/gnu/b64/loongarch64/0000775000175000017500000000000015105742312021703 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs0000644000175000017500000007700515105742312023037 0ustar bdrungbdrunguse crate::prelude::*; use crate::{off64_t, off_t, pthread_mutex_t}; pub type wchar_t = i32; pub type blksize_t = i32; pub type nlink_t = u32; pub type suseconds_t = i64; pub type __u64 = c_ulonglong; pub type __s64 = c_longlong; s! { pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, __pad1: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub __pad1: crate::dev_t, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub __pad2: c_int, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_int; 2], } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct pthread_attr_t { __size: [c_ulong; 7], } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [u64; 0], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_uint, pub __seq: c_ushort, __pad2: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct user_regs_struct { pub regs: [u64; 32], pub orig_a0: u64, pub csr_era: u64, pub csr_badv: u64, pub reserved: [u64; 10], } pub struct user_fp_struct { pub fpr: [u64; 32], pub fcc: u64, pub fcsr: u32, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub __pc: c_ulonglong, pub __gregs: [c_ulonglong; 32], pub __flags: c_uint, pub __extcontext: [c_ulonglong; 0], } #[repr(align(8))] pub struct clone_args { pub flags: c_ulonglong, pub pidfd: c_ulonglong, pub child_tid: c_ulonglong, pub parent_tid: c_ulonglong, pub exit_signal: c_ulonglong, pub stack: c_ulonglong, pub stack_size: c_ulonglong, pub tls: c_ulonglong, pub set_tid: c_ulonglong, pub set_tid_size: c_ulonglong, pub cgroup: c_ulonglong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const HWCAP_LOONGARCH_CPUCFG: c_ulong = 1 << 0; pub const HWCAP_LOONGARCH_LAM: c_ulong = 1 << 1; pub const HWCAP_LOONGARCH_UAL: c_ulong = 1 << 2; pub const HWCAP_LOONGARCH_FPU: c_ulong = 1 << 3; pub const HWCAP_LOONGARCH_LSX: c_ulong = 1 << 4; pub const HWCAP_LOONGARCH_LASX: c_ulong = 1 << 5; pub const HWCAP_LOONGARCH_CRC32: c_ulong = 1 << 6; pub const HWCAP_LOONGARCH_COMPLEX: c_ulong = 1 << 7; pub const HWCAP_LOONGARCH_CRYPTO: c_ulong = 1 << 8; pub const HWCAP_LOONGARCH_LVZ: c_ulong = 1 << 9; pub const HWCAP_LOONGARCH_LBT_X86: c_ulong = 1 << 10; pub const HWCAP_LOONGARCH_LBT_ARM: c_ulong = 1 << 11; pub const HWCAP_LOONGARCH_LBT_MIPS: c_ulong = 1 << 12; pub const HWCAP_LOONGARCH_PTW: c_ulong = 1 << 13; pub const SYS_io_setup: c_long = 0; pub const SYS_io_destroy: c_long = 1; pub const SYS_io_submit: c_long = 2; pub const SYS_io_cancel: c_long = 3; pub const SYS_io_getevents: c_long = 4; pub const SYS_setxattr: c_long = 5; pub const SYS_lsetxattr: c_long = 6; pub const SYS_fsetxattr: c_long = 7; pub const SYS_getxattr: c_long = 8; pub const SYS_lgetxattr: c_long = 9; pub const SYS_fgetxattr: c_long = 10; pub const SYS_listxattr: c_long = 11; pub const SYS_llistxattr: c_long = 12; pub const SYS_flistxattr: c_long = 13; pub const SYS_removexattr: c_long = 14; pub const SYS_lremovexattr: c_long = 15; pub const SYS_fremovexattr: c_long = 16; pub const SYS_getcwd: c_long = 17; pub const SYS_lookup_dcookie: c_long = 18; pub const SYS_eventfd2: c_long = 19; pub const SYS_epoll_create1: c_long = 20; pub const SYS_epoll_ctl: c_long = 21; pub const SYS_epoll_pwait: c_long = 22; pub const SYS_dup: c_long = 23; pub const SYS_dup3: c_long = 24; pub const SYS_fcntl: c_long = 25; pub const SYS_inotify_init1: c_long = 26; pub const SYS_inotify_add_watch: c_long = 27; pub const SYS_inotify_rm_watch: c_long = 28; pub const SYS_ioctl: c_long = 29; pub const SYS_ioprio_set: c_long = 30; pub const SYS_ioprio_get: c_long = 31; pub const SYS_flock: c_long = 32; pub const SYS_mknodat: c_long = 33; pub const SYS_mkdirat: c_long = 34; pub const SYS_unlinkat: c_long = 35; pub const SYS_symlinkat: c_long = 36; pub const SYS_linkat: c_long = 37; pub const SYS_umount2: c_long = 39; pub const SYS_mount: c_long = 40; pub const SYS_pivot_root: c_long = 41; pub const SYS_nfsservctl: c_long = 42; pub const SYS_statfs: c_long = 43; pub const SYS_fstatfs: c_long = 44; pub const SYS_truncate: c_long = 45; pub const SYS_ftruncate: c_long = 46; pub const SYS_fallocate: c_long = 47; pub const SYS_faccessat: c_long = 48; pub const SYS_chdir: c_long = 49; pub const SYS_fchdir: c_long = 50; pub const SYS_chroot: c_long = 51; pub const SYS_fchmod: c_long = 52; pub const SYS_fchmodat: c_long = 53; pub const SYS_fchownat: c_long = 54; pub const SYS_fchown: c_long = 55; pub const SYS_openat: c_long = 56; pub const SYS_close: c_long = 57; pub const SYS_vhangup: c_long = 58; pub const SYS_pipe2: c_long = 59; pub const SYS_quotactl: c_long = 60; pub const SYS_getdents64: c_long = 61; pub const SYS_lseek: c_long = 62; pub const SYS_read: c_long = 63; pub const SYS_write: c_long = 64; pub const SYS_readv: c_long = 65; pub const SYS_writev: c_long = 66; pub const SYS_pread64: c_long = 67; pub const SYS_pwrite64: c_long = 68; pub const SYS_preadv: c_long = 69; pub const SYS_pwritev: c_long = 70; pub const SYS_sendfile: c_long = 71; pub const SYS_pselect6: c_long = 72; pub const SYS_ppoll: c_long = 73; pub const SYS_signalfd4: c_long = 74; pub const SYS_vmsplice: c_long = 75; pub const SYS_splice: c_long = 76; pub const SYS_tee: c_long = 77; pub const SYS_readlinkat: c_long = 78; pub const SYS_sync: c_long = 81; pub const SYS_fsync: c_long = 82; pub const SYS_fdatasync: c_long = 83; pub const SYS_sync_file_range: c_long = 84; pub const SYS_timerfd_create: c_long = 85; pub const SYS_timerfd_settime: c_long = 86; pub const SYS_timerfd_gettime: c_long = 87; pub const SYS_utimensat: c_long = 88; pub const SYS_acct: c_long = 89; pub const SYS_capget: c_long = 90; pub const SYS_capset: c_long = 91; pub const SYS_personality: c_long = 92; pub const SYS_exit: c_long = 93; pub const SYS_exit_group: c_long = 94; pub const SYS_waitid: c_long = 95; pub const SYS_set_tid_address: c_long = 96; pub const SYS_unshare: c_long = 97; pub const SYS_futex: c_long = 98; pub const SYS_set_robust_list: c_long = 99; pub const SYS_get_robust_list: c_long = 100; pub const SYS_nanosleep: c_long = 101; pub const SYS_getitimer: c_long = 102; pub const SYS_setitimer: c_long = 103; pub const SYS_kexec_load: c_long = 104; pub const SYS_init_module: c_long = 105; pub const SYS_delete_module: c_long = 106; pub const SYS_timer_create: c_long = 107; pub const SYS_timer_gettime: c_long = 108; pub const SYS_timer_getoverrun: c_long = 109; pub const SYS_timer_settime: c_long = 110; pub const SYS_timer_delete: c_long = 111; pub const SYS_clock_settime: c_long = 112; pub const SYS_clock_gettime: c_long = 113; pub const SYS_clock_getres: c_long = 114; pub const SYS_clock_nanosleep: c_long = 115; pub const SYS_syslog: c_long = 116; pub const SYS_ptrace: c_long = 117; pub const SYS_sched_setparam: c_long = 118; pub const SYS_sched_setscheduler: c_long = 119; pub const SYS_sched_getscheduler: c_long = 120; pub const SYS_sched_getparam: c_long = 121; pub const SYS_sched_setaffinity: c_long = 122; pub const SYS_sched_getaffinity: c_long = 123; pub const SYS_sched_yield: c_long = 124; pub const SYS_sched_get_priority_max: c_long = 125; pub const SYS_sched_get_priority_min: c_long = 126; pub const SYS_sched_rr_get_interval: c_long = 127; pub const SYS_restart_syscall: c_long = 128; pub const SYS_kill: c_long = 129; pub const SYS_tkill: c_long = 130; pub const SYS_tgkill: c_long = 131; pub const SYS_sigaltstack: c_long = 132; pub const SYS_rt_sigsuspend: c_long = 133; pub const SYS_rt_sigaction: c_long = 134; pub const SYS_rt_sigprocmask: c_long = 135; pub const SYS_rt_sigpending: c_long = 136; pub const SYS_rt_sigtimedwait: c_long = 137; pub const SYS_rt_sigqueueinfo: c_long = 138; pub const SYS_rt_sigreturn: c_long = 139; pub const SYS_setpriority: c_long = 140; pub const SYS_getpriority: c_long = 141; pub const SYS_reboot: c_long = 142; pub const SYS_setregid: c_long = 143; pub const SYS_setgid: c_long = 144; pub const SYS_setreuid: c_long = 145; pub const SYS_setuid: c_long = 146; pub const SYS_setresuid: c_long = 147; pub const SYS_getresuid: c_long = 148; pub const SYS_setresgid: c_long = 149; pub const SYS_getresgid: c_long = 150; pub const SYS_setfsuid: c_long = 151; pub const SYS_setfsgid: c_long = 152; pub const SYS_times: c_long = 153; pub const SYS_setpgid: c_long = 154; pub const SYS_getpgid: c_long = 155; pub const SYS_getsid: c_long = 156; pub const SYS_setsid: c_long = 157; pub const SYS_getgroups: c_long = 158; pub const SYS_setgroups: c_long = 159; pub const SYS_uname: c_long = 160; pub const SYS_sethostname: c_long = 161; pub const SYS_setdomainname: c_long = 162; pub const SYS_getrusage: c_long = 165; pub const SYS_umask: c_long = 166; pub const SYS_prctl: c_long = 167; pub const SYS_getcpu: c_long = 168; pub const SYS_gettimeofday: c_long = 169; pub const SYS_settimeofday: c_long = 170; pub const SYS_adjtimex: c_long = 171; pub const SYS_getpid: c_long = 172; pub const SYS_getppid: c_long = 173; pub const SYS_getuid: c_long = 174; pub const SYS_geteuid: c_long = 175; pub const SYS_getgid: c_long = 176; pub const SYS_getegid: c_long = 177; pub const SYS_gettid: c_long = 178; pub const SYS_sysinfo: c_long = 179; pub const SYS_mq_open: c_long = 180; pub const SYS_mq_unlink: c_long = 181; pub const SYS_mq_timedsend: c_long = 182; pub const SYS_mq_timedreceive: c_long = 183; pub const SYS_mq_notify: c_long = 184; pub const SYS_mq_getsetattr: c_long = 185; pub const SYS_msgget: c_long = 186; pub const SYS_msgctl: c_long = 187; pub const SYS_msgrcv: c_long = 188; pub const SYS_msgsnd: c_long = 189; pub const SYS_semget: c_long = 190; pub const SYS_semctl: c_long = 191; pub const SYS_semtimedop: c_long = 192; pub const SYS_semop: c_long = 193; pub const SYS_shmget: c_long = 194; pub const SYS_shmctl: c_long = 195; pub const SYS_shmat: c_long = 196; pub const SYS_shmdt: c_long = 197; pub const SYS_socket: c_long = 198; pub const SYS_socketpair: c_long = 199; pub const SYS_bind: c_long = 200; pub const SYS_listen: c_long = 201; pub const SYS_accept: c_long = 202; pub const SYS_connect: c_long = 203; pub const SYS_getsockname: c_long = 204; pub const SYS_getpeername: c_long = 205; pub const SYS_sendto: c_long = 206; pub const SYS_recvfrom: c_long = 207; pub const SYS_setsockopt: c_long = 208; pub const SYS_getsockopt: c_long = 209; pub const SYS_shutdown: c_long = 210; pub const SYS_sendmsg: c_long = 211; pub const SYS_recvmsg: c_long = 212; pub const SYS_readahead: c_long = 213; pub const SYS_brk: c_long = 214; pub const SYS_munmap: c_long = 215; pub const SYS_mremap: c_long = 216; pub const SYS_add_key: c_long = 217; pub const SYS_request_key: c_long = 218; pub const SYS_keyctl: c_long = 219; pub const SYS_clone: c_long = 220; pub const SYS_execve: c_long = 221; pub const SYS_mmap: c_long = 222; pub const SYS_fadvise64: c_long = 223; pub const SYS_swapon: c_long = 224; pub const SYS_swapoff: c_long = 225; pub const SYS_mprotect: c_long = 226; pub const SYS_msync: c_long = 227; pub const SYS_mlock: c_long = 228; pub const SYS_munlock: c_long = 229; pub const SYS_mlockall: c_long = 230; pub const SYS_munlockall: c_long = 231; pub const SYS_mincore: c_long = 232; pub const SYS_madvise: c_long = 233; pub const SYS_remap_file_pages: c_long = 234; pub const SYS_mbind: c_long = 235; pub const SYS_get_mempolicy: c_long = 236; pub const SYS_set_mempolicy: c_long = 237; pub const SYS_migrate_pages: c_long = 238; pub const SYS_move_pages: c_long = 239; pub const SYS_rt_tgsigqueueinfo: c_long = 240; pub const SYS_perf_event_open: c_long = 241; pub const SYS_accept4: c_long = 242; pub const SYS_recvmmsg: c_long = 243; //pub const SYS_arch_specific_syscall: c_long = 244; pub const SYS_wait4: c_long = 260; pub const SYS_prlimit64: c_long = 261; pub const SYS_fanotify_init: c_long = 262; pub const SYS_fanotify_mark: c_long = 263; pub const SYS_name_to_handle_at: c_long = 264; pub const SYS_open_by_handle_at: c_long = 265; pub const SYS_clock_adjtime: c_long = 266; pub const SYS_syncfs: c_long = 267; pub const SYS_setns: c_long = 268; pub const SYS_sendmmsg: c_long = 269; pub const SYS_process_vm_readv: c_long = 270; pub const SYS_process_vm_writev: c_long = 271; pub const SYS_kcmp: c_long = 272; pub const SYS_finit_module: c_long = 273; pub const SYS_sched_setattr: c_long = 274; pub const SYS_sched_getattr: c_long = 275; pub const SYS_renameat2: c_long = 276; pub const SYS_seccomp: c_long = 277; pub const SYS_getrandom: c_long = 278; pub const SYS_memfd_create: c_long = 279; pub const SYS_bpf: c_long = 280; pub const SYS_execveat: c_long = 281; pub const SYS_userfaultfd: c_long = 282; pub const SYS_membarrier: c_long = 283; pub const SYS_mlock2: c_long = 284; pub const SYS_copy_file_range: c_long = 285; pub const SYS_preadv2: c_long = 286; pub const SYS_pwritev2: c_long = 287; pub const SYS_pkey_mprotect: c_long = 288; pub const SYS_pkey_alloc: c_long = 289; pub const SYS_pkey_free: c_long = 290; pub const SYS_statx: c_long = 291; pub const SYS_io_pgetevents: c_long = 292; pub const SYS_rseq: c_long = 293; pub const SYS_kexec_file_load: c_long = 294; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const O_DIRECT: c_int = 0o00040000; pub const O_DIRECTORY: c_int = 0o00200000; pub const O_NOFOLLOW: c_int = 0o00400000; pub const O_TRUNC: c_int = 0o00001000; pub const O_NOATIME: c_int = 0o1000000; pub const O_CLOEXEC: c_int = 0o02000000; pub const O_PATH: c_int = 0o10000000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const O_APPEND: c_int = 0o00002000; pub const O_CREAT: c_int = 0o00000100; pub const O_EXCL: c_int = 0o00000200; pub const O_NOCTTY: c_int = 0o00000400; pub const O_NONBLOCK: c_int = 0o00004000; pub const FASYNC: c_int = 0o00020000; pub const O_SYNC: c_int = 0o04010000; pub const O_RSYNC: c_int = 0o04010000; pub const O_FSYNC: c_int = O_SYNC; pub const O_ASYNC: c_int = 0o00020000; pub const O_DSYNC: c_int = 0o00010000; pub const O_NDELAY: c_int = O_NONBLOCK; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const F_GETLK: c_int = 5; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_SETOWN: c_int = 8; pub const F_GETOWN: c_int = 9; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const EDEADLK: c_int = 35; pub const EDEADLOCK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_NORESERVE: c_int = 0x4000; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x1000; pub const MAP_LOCKED: c_int = 0x2000; pub const MAP_POPULATE: c_int = 0x8000; pub const MAP_NONBLOCK: c_int = 0x10000; pub const MAP_STACK: c_int = 0x20000; pub const MAP_HUGETLB: c_int = 0x40000; pub const MAP_SYNC: c_int = 0x080000; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SFD_NONBLOCK: c_int = 0x800; pub const SFD_CLOEXEC: c_int = 0x080000; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIG_BLOCK: c_int = 0; pub const SIG_UNBLOCK: c_int = 1; pub const SIG_SETMASK: c_int = 2; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGSTKFLT: c_int = 16; pub const SIGCHLD: c_int = 17; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGURG: c_int = 23; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGIO: c_int = 29; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIGSYS: c_int = 31; pub const SIGUNUSED: c_int = 31; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const PTRACE_GETFPREGS: c_uint = 14; pub const PTRACE_SETFPREGS: c_uint = 15; pub const PTRACE_DETACH: c_uint = 17; pub const PTRACE_GETFPXREGS: c_uint = 18; pub const PTRACE_SETFPXREGS: c_uint = 19; pub const PTRACE_GETREGS: c_uint = 12; pub const PTRACE_SETREGS: c_uint = 13; pub const PTRACE_SYSEMU: c_uint = 31; pub const PTRACE_SYSEMU_SINGLESTEP: c_uint = 32; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const VEOF: usize = 4; pub const VTIME: usize = 5; pub const VMIN: usize = 6; pub const VSWTC: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const VEOL: usize = 11; pub const VREPRINT: usize = 12; pub const VDISCARD: usize = 13; pub const VWERASE: usize = 14; pub const VEOL2: usize = 16; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const SIGSTKSZ: size_t = 16384; pub const MINSIGSTKSZ: size_t = 4096; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const VT1: crate::tcflag_t = 0x00004000; pub const ONLCR: crate::tcflag_t = 0x4; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const XCASE: crate::tcflag_t = 0x00000004; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const NCCS: usize = 32; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const EFD_NONBLOCK: c_int = 0x800; libc/src/unix/linux_like/linux/gnu/b64/mips64/0000775000175000017500000000000015105742312020677 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs0000644000175000017500000010326315105742312022027 0ustar bdrungbdrunguse crate::prelude::*; use crate::{off64_t, off_t, pthread_mutex_t}; pub type blksize_t = i64; pub type nlink_t = u64; pub type suseconds_t = i64; pub type wchar_t = i32; pub type __u64 = c_ulong; pub type __s64 = c_long; s! { pub struct stat { pub st_dev: c_ulong, st_pad1: [c_long; 2], pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulong, st_pad2: [c_ulong; 1], pub st_size: off_t, st_pad3: c_long, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, st_pad4: c_long, pub st_blocks: crate::blkcnt_t, st_pad5: [c_long; 7], } pub struct statfs { pub f_type: c_long, pub f_bsize: c_long, pub f_frsize: c_long, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_files: crate::fsblkcnt_t, pub f_ffree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, f_spare: [c_long; 6], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct stat64 { pub st_dev: c_ulong, st_pad1: [c_long; 2], pub st_ino: crate::ino64_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: c_ulong, st_pad2: [c_long; 2], pub st_size: off64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, st_pad3: c_long, pub st_blocks: crate::blkcnt64_t, st_pad5: [c_long; 7], } pub struct statfs64 { pub f_type: c_long, pub f_bsize: c_long, pub f_frsize: c_long, pub f_blocks: u64, pub f_bfree: u64, pub f_files: u64, pub f_ffree: u64, pub f_bavail: u64, pub f_fsid: crate::fsid_t, pub f_namelen: c_long, pub f_flags: c_long, pub f_spare: [c_long; 5], } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct pthread_attr_t { __size: [c_ulong; 7], } pub struct sigaction { pub sa_flags: c_int, pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_restorer: Option, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, _pad: c_int, _pad2: [c_long; 14], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: c_uint, pub __seq: c_ushort, __pad1: c_ushort, __unused1: c_ulong, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const SYS_read: c_long = 5000 + 0; pub const SYS_write: c_long = 5000 + 1; pub const SYS_open: c_long = 5000 + 2; pub const SYS_close: c_long = 5000 + 3; pub const SYS_stat: c_long = 5000 + 4; pub const SYS_fstat: c_long = 5000 + 5; pub const SYS_lstat: c_long = 5000 + 6; pub const SYS_poll: c_long = 5000 + 7; pub const SYS_lseek: c_long = 5000 + 8; pub const SYS_mmap: c_long = 5000 + 9; pub const SYS_mprotect: c_long = 5000 + 10; pub const SYS_munmap: c_long = 5000 + 11; pub const SYS_brk: c_long = 5000 + 12; pub const SYS_rt_sigaction: c_long = 5000 + 13; pub const SYS_rt_sigprocmask: c_long = 5000 + 14; pub const SYS_ioctl: c_long = 5000 + 15; pub const SYS_pread64: c_long = 5000 + 16; pub const SYS_pwrite64: c_long = 5000 + 17; pub const SYS_readv: c_long = 5000 + 18; pub const SYS_writev: c_long = 5000 + 19; pub const SYS_access: c_long = 5000 + 20; pub const SYS_pipe: c_long = 5000 + 21; pub const SYS__newselect: c_long = 5000 + 22; pub const SYS_sched_yield: c_long = 5000 + 23; pub const SYS_mremap: c_long = 5000 + 24; pub const SYS_msync: c_long = 5000 + 25; pub const SYS_mincore: c_long = 5000 + 26; pub const SYS_madvise: c_long = 5000 + 27; pub const SYS_shmget: c_long = 5000 + 28; pub const SYS_shmat: c_long = 5000 + 29; pub const SYS_shmctl: c_long = 5000 + 30; pub const SYS_dup: c_long = 5000 + 31; pub const SYS_dup2: c_long = 5000 + 32; pub const SYS_pause: c_long = 5000 + 33; pub const SYS_nanosleep: c_long = 5000 + 34; pub const SYS_getitimer: c_long = 5000 + 35; pub const SYS_setitimer: c_long = 5000 + 36; pub const SYS_alarm: c_long = 5000 + 37; pub const SYS_getpid: c_long = 5000 + 38; pub const SYS_sendfile: c_long = 5000 + 39; pub const SYS_socket: c_long = 5000 + 40; pub const SYS_connect: c_long = 5000 + 41; pub const SYS_accept: c_long = 5000 + 42; pub const SYS_sendto: c_long = 5000 + 43; pub const SYS_recvfrom: c_long = 5000 + 44; pub const SYS_sendmsg: c_long = 5000 + 45; pub const SYS_recvmsg: c_long = 5000 + 46; pub const SYS_shutdown: c_long = 5000 + 47; pub const SYS_bind: c_long = 5000 + 48; pub const SYS_listen: c_long = 5000 + 49; pub const SYS_getsockname: c_long = 5000 + 50; pub const SYS_getpeername: c_long = 5000 + 51; pub const SYS_socketpair: c_long = 5000 + 52; pub const SYS_setsockopt: c_long = 5000 + 53; pub const SYS_getsockopt: c_long = 5000 + 54; pub const SYS_clone: c_long = 5000 + 55; pub const SYS_fork: c_long = 5000 + 56; pub const SYS_execve: c_long = 5000 + 57; pub const SYS_exit: c_long = 5000 + 58; pub const SYS_wait4: c_long = 5000 + 59; pub const SYS_kill: c_long = 5000 + 60; pub const SYS_uname: c_long = 5000 + 61; pub const SYS_semget: c_long = 5000 + 62; pub const SYS_semop: c_long = 5000 + 63; pub const SYS_semctl: c_long = 5000 + 64; pub const SYS_shmdt: c_long = 5000 + 65; pub const SYS_msgget: c_long = 5000 + 66; pub const SYS_msgsnd: c_long = 5000 + 67; pub const SYS_msgrcv: c_long = 5000 + 68; pub const SYS_msgctl: c_long = 5000 + 69; pub const SYS_fcntl: c_long = 5000 + 70; pub const SYS_flock: c_long = 5000 + 71; pub const SYS_fsync: c_long = 5000 + 72; pub const SYS_fdatasync: c_long = 5000 + 73; pub const SYS_truncate: c_long = 5000 + 74; pub const SYS_ftruncate: c_long = 5000 + 75; pub const SYS_getdents: c_long = 5000 + 76; pub const SYS_getcwd: c_long = 5000 + 77; pub const SYS_chdir: c_long = 5000 + 78; pub const SYS_fchdir: c_long = 5000 + 79; pub const SYS_rename: c_long = 5000 + 80; pub const SYS_mkdir: c_long = 5000 + 81; pub const SYS_rmdir: c_long = 5000 + 82; pub const SYS_creat: c_long = 5000 + 83; pub const SYS_link: c_long = 5000 + 84; pub const SYS_unlink: c_long = 5000 + 85; pub const SYS_symlink: c_long = 5000 + 86; pub const SYS_readlink: c_long = 5000 + 87; pub const SYS_chmod: c_long = 5000 + 88; pub const SYS_fchmod: c_long = 5000 + 89; pub const SYS_chown: c_long = 5000 + 90; pub const SYS_fchown: c_long = 5000 + 91; pub const SYS_lchown: c_long = 5000 + 92; pub const SYS_umask: c_long = 5000 + 93; pub const SYS_gettimeofday: c_long = 5000 + 94; pub const SYS_getrlimit: c_long = 5000 + 95; pub const SYS_getrusage: c_long = 5000 + 96; pub const SYS_sysinfo: c_long = 5000 + 97; pub const SYS_times: c_long = 5000 + 98; pub const SYS_ptrace: c_long = 5000 + 99; pub const SYS_getuid: c_long = 5000 + 100; pub const SYS_syslog: c_long = 5000 + 101; pub const SYS_getgid: c_long = 5000 + 102; pub const SYS_setuid: c_long = 5000 + 103; pub const SYS_setgid: c_long = 5000 + 104; pub const SYS_geteuid: c_long = 5000 + 105; pub const SYS_getegid: c_long = 5000 + 106; pub const SYS_setpgid: c_long = 5000 + 107; pub const SYS_getppid: c_long = 5000 + 108; pub const SYS_getpgrp: c_long = 5000 + 109; pub const SYS_setsid: c_long = 5000 + 110; pub const SYS_setreuid: c_long = 5000 + 111; pub const SYS_setregid: c_long = 5000 + 112; pub const SYS_getgroups: c_long = 5000 + 113; pub const SYS_setgroups: c_long = 5000 + 114; pub const SYS_setresuid: c_long = 5000 + 115; pub const SYS_getresuid: c_long = 5000 + 116; pub const SYS_setresgid: c_long = 5000 + 117; pub const SYS_getresgid: c_long = 5000 + 118; pub const SYS_getpgid: c_long = 5000 + 119; pub const SYS_setfsuid: c_long = 5000 + 120; pub const SYS_setfsgid: c_long = 5000 + 121; pub const SYS_getsid: c_long = 5000 + 122; pub const SYS_capget: c_long = 5000 + 123; pub const SYS_capset: c_long = 5000 + 124; pub const SYS_rt_sigpending: c_long = 5000 + 125; pub const SYS_rt_sigtimedwait: c_long = 5000 + 126; pub const SYS_rt_sigqueueinfo: c_long = 5000 + 127; pub const SYS_rt_sigsuspend: c_long = 5000 + 128; pub const SYS_sigaltstack: c_long = 5000 + 129; pub const SYS_utime: c_long = 5000 + 130; pub const SYS_mknod: c_long = 5000 + 131; pub const SYS_personality: c_long = 5000 + 132; pub const SYS_ustat: c_long = 5000 + 133; pub const SYS_statfs: c_long = 5000 + 134; pub const SYS_fstatfs: c_long = 5000 + 135; pub const SYS_sysfs: c_long = 5000 + 136; pub const SYS_getpriority: c_long = 5000 + 137; pub const SYS_setpriority: c_long = 5000 + 138; pub const SYS_sched_setparam: c_long = 5000 + 139; pub const SYS_sched_getparam: c_long = 5000 + 140; pub const SYS_sched_setscheduler: c_long = 5000 + 141; pub const SYS_sched_getscheduler: c_long = 5000 + 142; pub const SYS_sched_get_priority_max: c_long = 5000 + 143; pub const SYS_sched_get_priority_min: c_long = 5000 + 144; pub const SYS_sched_rr_get_interval: c_long = 5000 + 145; pub const SYS_mlock: c_long = 5000 + 146; pub const SYS_munlock: c_long = 5000 + 147; pub const SYS_mlockall: c_long = 5000 + 148; pub const SYS_munlockall: c_long = 5000 + 149; pub const SYS_vhangup: c_long = 5000 + 150; pub const SYS_pivot_root: c_long = 5000 + 151; pub const SYS__sysctl: c_long = 5000 + 152; pub const SYS_prctl: c_long = 5000 + 153; pub const SYS_adjtimex: c_long = 5000 + 154; pub const SYS_setrlimit: c_long = 5000 + 155; pub const SYS_chroot: c_long = 5000 + 156; pub const SYS_sync: c_long = 5000 + 157; pub const SYS_acct: c_long = 5000 + 158; pub const SYS_settimeofday: c_long = 5000 + 159; pub const SYS_mount: c_long = 5000 + 160; pub const SYS_umount2: c_long = 5000 + 161; pub const SYS_swapon: c_long = 5000 + 162; pub const SYS_swapoff: c_long = 5000 + 163; pub const SYS_reboot: c_long = 5000 + 164; pub const SYS_sethostname: c_long = 5000 + 165; pub const SYS_setdomainname: c_long = 5000 + 166; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 5000 + 167; pub const SYS_init_module: c_long = 5000 + 168; pub const SYS_delete_module: c_long = 5000 + 169; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 5000 + 170; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 5000 + 171; pub const SYS_quotactl: c_long = 5000 + 172; pub const SYS_nfsservctl: c_long = 5000 + 173; pub const SYS_getpmsg: c_long = 5000 + 174; pub const SYS_putpmsg: c_long = 5000 + 175; pub const SYS_afs_syscall: c_long = 5000 + 176; pub const SYS_gettid: c_long = 5000 + 178; pub const SYS_readahead: c_long = 5000 + 179; pub const SYS_setxattr: c_long = 5000 + 180; pub const SYS_lsetxattr: c_long = 5000 + 181; pub const SYS_fsetxattr: c_long = 5000 + 182; pub const SYS_getxattr: c_long = 5000 + 183; pub const SYS_lgetxattr: c_long = 5000 + 184; pub const SYS_fgetxattr: c_long = 5000 + 185; pub const SYS_listxattr: c_long = 5000 + 186; pub const SYS_llistxattr: c_long = 5000 + 187; pub const SYS_flistxattr: c_long = 5000 + 188; pub const SYS_removexattr: c_long = 5000 + 189; pub const SYS_lremovexattr: c_long = 5000 + 190; pub const SYS_fremovexattr: c_long = 5000 + 191; pub const SYS_tkill: c_long = 5000 + 192; pub const SYS_futex: c_long = 5000 + 194; pub const SYS_sched_setaffinity: c_long = 5000 + 195; pub const SYS_sched_getaffinity: c_long = 5000 + 196; pub const SYS_cacheflush: c_long = 5000 + 197; pub const SYS_cachectl: c_long = 5000 + 198; pub const SYS_sysmips: c_long = 5000 + 199; pub const SYS_io_setup: c_long = 5000 + 200; pub const SYS_io_destroy: c_long = 5000 + 201; pub const SYS_io_getevents: c_long = 5000 + 202; pub const SYS_io_submit: c_long = 5000 + 203; pub const SYS_io_cancel: c_long = 5000 + 204; pub const SYS_exit_group: c_long = 5000 + 205; pub const SYS_lookup_dcookie: c_long = 5000 + 206; pub const SYS_epoll_create: c_long = 5000 + 207; pub const SYS_epoll_ctl: c_long = 5000 + 208; pub const SYS_epoll_wait: c_long = 5000 + 209; pub const SYS_remap_file_pages: c_long = 5000 + 210; pub const SYS_rt_sigreturn: c_long = 5000 + 211; pub const SYS_set_tid_address: c_long = 5000 + 212; pub const SYS_restart_syscall: c_long = 5000 + 213; pub const SYS_semtimedop: c_long = 5000 + 214; pub const SYS_fadvise64: c_long = 5000 + 215; pub const SYS_timer_create: c_long = 5000 + 216; pub const SYS_timer_settime: c_long = 5000 + 217; pub const SYS_timer_gettime: c_long = 5000 + 218; pub const SYS_timer_getoverrun: c_long = 5000 + 219; pub const SYS_timer_delete: c_long = 5000 + 220; pub const SYS_clock_settime: c_long = 5000 + 221; pub const SYS_clock_gettime: c_long = 5000 + 222; pub const SYS_clock_getres: c_long = 5000 + 223; pub const SYS_clock_nanosleep: c_long = 5000 + 224; pub const SYS_tgkill: c_long = 5000 + 225; pub const SYS_utimes: c_long = 5000 + 226; pub const SYS_mbind: c_long = 5000 + 227; pub const SYS_get_mempolicy: c_long = 5000 + 228; pub const SYS_set_mempolicy: c_long = 5000 + 229; pub const SYS_mq_open: c_long = 5000 + 230; pub const SYS_mq_unlink: c_long = 5000 + 231; pub const SYS_mq_timedsend: c_long = 5000 + 232; pub const SYS_mq_timedreceive: c_long = 5000 + 233; pub const SYS_mq_notify: c_long = 5000 + 234; pub const SYS_mq_getsetattr: c_long = 5000 + 235; pub const SYS_vserver: c_long = 5000 + 236; pub const SYS_waitid: c_long = 5000 + 237; /* pub const SYS_sys_setaltroot: c_long = 5000 + 238; */ pub const SYS_add_key: c_long = 5000 + 239; pub const SYS_request_key: c_long = 5000 + 240; pub const SYS_keyctl: c_long = 5000 + 241; pub const SYS_set_thread_area: c_long = 5000 + 242; pub const SYS_inotify_init: c_long = 5000 + 243; pub const SYS_inotify_add_watch: c_long = 5000 + 244; pub const SYS_inotify_rm_watch: c_long = 5000 + 245; pub const SYS_migrate_pages: c_long = 5000 + 246; pub const SYS_openat: c_long = 5000 + 247; pub const SYS_mkdirat: c_long = 5000 + 248; pub const SYS_mknodat: c_long = 5000 + 249; pub const SYS_fchownat: c_long = 5000 + 250; pub const SYS_futimesat: c_long = 5000 + 251; pub const SYS_newfstatat: c_long = 5000 + 252; pub const SYS_unlinkat: c_long = 5000 + 253; pub const SYS_renameat: c_long = 5000 + 254; pub const SYS_linkat: c_long = 5000 + 255; pub const SYS_symlinkat: c_long = 5000 + 256; pub const SYS_readlinkat: c_long = 5000 + 257; pub const SYS_fchmodat: c_long = 5000 + 258; pub const SYS_faccessat: c_long = 5000 + 259; pub const SYS_pselect6: c_long = 5000 + 260; pub const SYS_ppoll: c_long = 5000 + 261; pub const SYS_unshare: c_long = 5000 + 262; pub const SYS_splice: c_long = 5000 + 263; pub const SYS_sync_file_range: c_long = 5000 + 264; pub const SYS_tee: c_long = 5000 + 265; pub const SYS_vmsplice: c_long = 5000 + 266; pub const SYS_move_pages: c_long = 5000 + 267; pub const SYS_set_robust_list: c_long = 5000 + 268; pub const SYS_get_robust_list: c_long = 5000 + 269; pub const SYS_kexec_load: c_long = 5000 + 270; pub const SYS_getcpu: c_long = 5000 + 271; pub const SYS_epoll_pwait: c_long = 5000 + 272; pub const SYS_ioprio_set: c_long = 5000 + 273; pub const SYS_ioprio_get: c_long = 5000 + 274; pub const SYS_utimensat: c_long = 5000 + 275; pub const SYS_signalfd: c_long = 5000 + 276; pub const SYS_timerfd: c_long = 5000 + 277; pub const SYS_eventfd: c_long = 5000 + 278; pub const SYS_fallocate: c_long = 5000 + 279; pub const SYS_timerfd_create: c_long = 5000 + 280; pub const SYS_timerfd_gettime: c_long = 5000 + 281; pub const SYS_timerfd_settime: c_long = 5000 + 282; pub const SYS_signalfd4: c_long = 5000 + 283; pub const SYS_eventfd2: c_long = 5000 + 284; pub const SYS_epoll_create1: c_long = 5000 + 285; pub const SYS_dup3: c_long = 5000 + 286; pub const SYS_pipe2: c_long = 5000 + 287; pub const SYS_inotify_init1: c_long = 5000 + 288; pub const SYS_preadv: c_long = 5000 + 289; pub const SYS_pwritev: c_long = 5000 + 290; pub const SYS_rt_tgsigqueueinfo: c_long = 5000 + 291; pub const SYS_perf_event_open: c_long = 5000 + 292; pub const SYS_accept4: c_long = 5000 + 293; pub const SYS_recvmmsg: c_long = 5000 + 294; pub const SYS_fanotify_init: c_long = 5000 + 295; pub const SYS_fanotify_mark: c_long = 5000 + 296; pub const SYS_prlimit64: c_long = 5000 + 297; pub const SYS_name_to_handle_at: c_long = 5000 + 298; pub const SYS_open_by_handle_at: c_long = 5000 + 299; pub const SYS_clock_adjtime: c_long = 5000 + 300; pub const SYS_syncfs: c_long = 5000 + 301; pub const SYS_sendmmsg: c_long = 5000 + 302; pub const SYS_setns: c_long = 5000 + 303; pub const SYS_process_vm_readv: c_long = 5000 + 304; pub const SYS_process_vm_writev: c_long = 5000 + 305; pub const SYS_kcmp: c_long = 5000 + 306; pub const SYS_finit_module: c_long = 5000 + 307; pub const SYS_getdents64: c_long = 5000 + 308; pub const SYS_sched_setattr: c_long = 5000 + 309; pub const SYS_sched_getattr: c_long = 5000 + 310; pub const SYS_renameat2: c_long = 5000 + 311; pub const SYS_seccomp: c_long = 5000 + 312; pub const SYS_getrandom: c_long = 5000 + 313; pub const SYS_memfd_create: c_long = 5000 + 314; pub const SYS_bpf: c_long = 5000 + 315; pub const SYS_execveat: c_long = 5000 + 316; pub const SYS_userfaultfd: c_long = 5000 + 317; pub const SYS_membarrier: c_long = 5000 + 318; pub const SYS_mlock2: c_long = 5000 + 319; pub const SYS_copy_file_range: c_long = 5000 + 320; pub const SYS_preadv2: c_long = 5000 + 321; pub const SYS_pwritev2: c_long = 5000 + 322; pub const SYS_pkey_mprotect: c_long = 5000 + 323; pub const SYS_pkey_alloc: c_long = 5000 + 324; pub const SYS_pkey_free: c_long = 5000 + 325; pub const SYS_statx: c_long = 5000 + 326; pub const SYS_rseq: c_long = 5000 + 327; pub const SYS_pidfd_send_signal: c_long = 5000 + 424; pub const SYS_io_uring_setup: c_long = 5000 + 425; pub const SYS_io_uring_enter: c_long = 5000 + 426; pub const SYS_io_uring_register: c_long = 5000 + 427; pub const SYS_open_tree: c_long = 5000 + 428; pub const SYS_move_mount: c_long = 5000 + 429; pub const SYS_fsopen: c_long = 5000 + 430; pub const SYS_fsconfig: c_long = 5000 + 431; pub const SYS_fsmount: c_long = 5000 + 432; pub const SYS_fspick: c_long = 5000 + 433; pub const SYS_pidfd_open: c_long = 5000 + 434; pub const SYS_clone3: c_long = 5000 + 435; pub const SYS_close_range: c_long = 5000 + 436; pub const SYS_openat2: c_long = 5000 + 437; pub const SYS_pidfd_getfd: c_long = 5000 + 438; pub const SYS_faccessat2: c_long = 5000 + 439; pub const SYS_process_madvise: c_long = 5000 + 440; pub const SYS_epoll_pwait2: c_long = 5000 + 441; pub const SYS_mount_setattr: c_long = 5000 + 442; pub const SYS_quotactl_fd: c_long = 5000 + 443; pub const SYS_landlock_create_ruleset: c_long = 5000 + 444; pub const SYS_landlock_add_rule: c_long = 5000 + 445; pub const SYS_landlock_restrict_self: c_long = 5000 + 446; pub const SYS_memfd_secret: c_long = 5000 + 447; pub const SYS_process_mrelease: c_long = 5000 + 448; pub const SYS_futex_waitv: c_long = 5000 + 449; pub const SYS_set_mempolicy_home_node: c_long = 5000 + 450; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_NOATIME: c_int = 0o1000000; pub const O_CLOEXEC: c_int = 0x80000; pub const O_PATH: c_int = 0o10000000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const O_DIRECT: c_int = 0x8000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_APPEND: c_int = 8; pub const O_CREAT: c_int = 256; pub const O_EXCL: c_int = 1024; pub const O_NOCTTY: c_int = 2048; pub const O_NONBLOCK: c_int = 128; pub const O_SYNC: c_int = 0x4010; pub const O_RSYNC: c_int = 0x4010; pub const O_DSYNC: c_int = 0x10; pub const O_FSYNC: c_int = 0x4010; pub const O_ASYNC: c_int = 0x1000; pub const O_NDELAY: c_int = 0x80; pub const EDEADLK: c_int = 45; pub const ENAMETOOLONG: c_int = 78; pub const ENOLCK: c_int = 46; pub const ENOSYS: c_int = 89; pub const ENOTEMPTY: c_int = 93; pub const ELOOP: c_int = 90; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EBADE: c_int = 50; pub const EBADR: c_int = 51; pub const EXFULL: c_int = 52; pub const ENOANO: c_int = 53; pub const EBADRQC: c_int = 54; pub const EBADSLT: c_int = 55; pub const EDEADLOCK: c_int = 56; pub const EMULTIHOP: c_int = 74; pub const EOVERFLOW: c_int = 79; pub const ENOTUNIQ: c_int = 80; pub const EBADFD: c_int = 81; pub const EBADMSG: c_int = 77; pub const EREMCHG: c_int = 82; pub const ELIBACC: c_int = 83; pub const ELIBBAD: c_int = 84; pub const ELIBSCN: c_int = 85; pub const ELIBMAX: c_int = 86; pub const ELIBEXEC: c_int = 87; pub const EILSEQ: c_int = 88; pub const ERESTART: c_int = 91; pub const ESTRPIPE: c_int = 92; pub const EUSERS: c_int = 94; pub const ENOTSOCK: c_int = 95; pub const EDESTADDRREQ: c_int = 96; pub const EMSGSIZE: c_int = 97; pub const EPROTOTYPE: c_int = 98; pub const ENOPROTOOPT: c_int = 99; pub const EPROTONOSUPPORT: c_int = 120; pub const ESOCKTNOSUPPORT: c_int = 121; pub const EOPNOTSUPP: c_int = 122; pub const EPFNOSUPPORT: c_int = 123; pub const EAFNOSUPPORT: c_int = 124; pub const EADDRINUSE: c_int = 125; pub const EADDRNOTAVAIL: c_int = 126; pub const ENETDOWN: c_int = 127; pub const ENETUNREACH: c_int = 128; pub const ENETRESET: c_int = 129; pub const ECONNABORTED: c_int = 130; pub const ECONNRESET: c_int = 131; pub const ENOBUFS: c_int = 132; pub const EISCONN: c_int = 133; pub const ENOTCONN: c_int = 134; pub const ESHUTDOWN: c_int = 143; pub const ETOOMANYREFS: c_int = 144; pub const ETIMEDOUT: c_int = 145; pub const ECONNREFUSED: c_int = 146; pub const EHOSTDOWN: c_int = 147; pub const EHOSTUNREACH: c_int = 148; pub const EALREADY: c_int = 149; pub const EINPROGRESS: c_int = 150; pub const ESTALE: c_int = 151; pub const EUCLEAN: c_int = 135; pub const ENOTNAM: c_int = 137; pub const ENAVAIL: c_int = 138; pub const EISNAM: c_int = 139; pub const EREMOTEIO: c_int = 140; pub const EDQUOT: c_int = 1133; pub const ENOMEDIUM: c_int = 159; pub const EMEDIUMTYPE: c_int = 160; pub const ECANCELED: c_int = 158; pub const ENOKEY: c_int = 161; pub const EKEYEXPIRED: c_int = 162; pub const EKEYREVOKED: c_int = 163; pub const EKEYREJECTED: c_int = 164; pub const EOWNERDEAD: c_int = 165; pub const ENOTRECOVERABLE: c_int = 166; pub const ERFKILL: c_int = 167; pub const MAP_NORESERVE: c_int = 0x400; pub const MAP_ANON: c_int = 0x800; pub const MAP_ANONYMOUS: c_int = 0x800; pub const MAP_GROWSDOWN: c_int = 0x1000; pub const MAP_DENYWRITE: c_int = 0x2000; pub const MAP_EXECUTABLE: c_int = 0x4000; pub const MAP_LOCKED: c_int = 0x8000; pub const MAP_POPULATE: c_int = 0x10000; pub const MAP_NONBLOCK: c_int = 0x20000; pub const MAP_STACK: c_int = 0x40000; pub const MAP_HUGETLB: c_int = 0x080000; pub const SOCK_STREAM: c_int = 2; pub const SOCK_DGRAM: c_int = 1; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000008; pub const SA_NOCLDWAIT: c_int = 0x00010000; pub const SIGCHLD: c_int = 18; pub const SIGBUS: c_int = 10; pub const SIGTTIN: c_int = 26; pub const SIGTTOU: c_int = 27; pub const SIGXCPU: c_int = 30; pub const SIGXFSZ: c_int = 31; pub const SIGVTALRM: c_int = 28; pub const SIGPROF: c_int = 29; pub const SIGWINCH: c_int = 20; pub const SIGUSR1: c_int = 16; pub const SIGUSR2: c_int = 17; pub const SIGCONT: c_int = 25; pub const SIGSTOP: c_int = 23; pub const SIGTSTP: c_int = 24; pub const SIGURG: c_int = 21; pub const SIGIO: c_int = 22; pub const SIGSYS: c_int = 12; pub const SIGPOLL: c_int = 22; pub const SIGPWR: c_int = 19; pub const SIG_SETMASK: c_int = 3; pub const SIG_BLOCK: c_int = 0x1; pub const SIG_UNBLOCK: c_int = 0x2; pub const POLLWRNORM: c_short = 0x004; pub const POLLWRBAND: c_short = 0x100; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: crate::tcflag_t = 0x00000100; pub const TOSTOP: crate::tcflag_t = 0x00008000; pub const FLUSHO: crate::tcflag_t = 0x00002000; pub const EXTPROC: crate::tcflag_t = 0o200000; pub const TCSANOW: c_int = 0x540e; pub const TCSADRAIN: c_int = 0x540f; pub const TCSAFLUSH: c_int = 0x5410; pub const PTRACE_GETFPREGS: c_uint = 14; pub const PTRACE_SETFPREGS: c_uint = 15; pub const PTRACE_DETACH: c_uint = 17; pub const PTRACE_GETFPXREGS: c_uint = 18; pub const PTRACE_SETFPXREGS: c_uint = 19; pub const PTRACE_GETREGS: c_uint = 12; pub const PTRACE_SETREGS: c_uint = 13; pub const EFD_NONBLOCK: c_int = 0x80; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const F_GETLK: c_int = 14; pub const F_GETOWN: c_int = 23; pub const F_SETOWN: c_int = 24; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const SFD_NONBLOCK: c_int = 0x80; pub const RTLD_DEEPBIND: c_int = 0x10; pub const RTLD_GLOBAL: c_int = 0x4; pub const RTLD_NOLOAD: c_int = 0x8; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MCL_ONFAULT: c_int = 0x0004; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const FF1: crate::tcflag_t = 0x00008000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VT1: crate::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CIBAUD: crate::tcflag_t = 0o02003600000; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const EHWPOISON: c_int = 168; extern "C" { pub fn sysctl( name: *mut c_int, namelen: c_int, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; } libc/src/unix/linux_like/linux/gnu/b64/powerpc64/0000775000175000017500000000000015105742312021406 5ustar bdrungbdrunglibc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs0000644000175000017500000010147315105742312022537 0ustar bdrungbdrung//! PowerPC64-specific definitions for 64-bit linux-like values use crate::prelude::*; use crate::{off64_t, off_t, pthread_mutex_t}; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = i64; pub type suseconds_t = i64; pub type __u64 = c_ulong; pub type __s64 = c_long; s! { pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, #[cfg(target_arch = "sparc64")] __reserved0: c_int, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct statfs { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, f_spare: [crate::__fsword_t; 5], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_start: off64_t, pub l_len: off64_t, pub l_pid: crate::pid_t, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __unused: [c_long; 3], } pub struct stat64 { pub st_dev: crate::dev_t, pub st_ino: crate::ino64_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, __pad0: c_int, pub st_rdev: crate::dev_t, pub st_size: off64_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt64_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, __reserved: [c_long; 3], } pub struct statfs64 { pub f_type: crate::__fsword_t, pub f_bsize: crate::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_namelen: crate::__fsword_t, pub f_frsize: crate::__fsword_t, pub f_flags: crate::__fsword_t, pub f_spare: [crate::__fsword_t; 4], } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct statvfs64 { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct pthread_attr_t { __size: [u64; 7], } pub struct ipc_perm { pub __key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: u32, __pad1: u32, __unused1: u64, __unused2: c_ulong, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_segsz: size_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, __unused4: c_ulong, __unused5: c_ulong, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [i64; 4], } } pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const RTLD_DEEPBIND: c_int = 0x8; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const VEOF: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const O_FSYNC: c_int = 0x101000; pub const O_NOATIME: c_int = 0o1000000; pub const O_PATH: c_int = 0o10000000; pub const O_TMPFILE: c_int = 0o20000000 | O_DIRECTORY; pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = 0x0020; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const MAP_HUGETLB: c_int = 0x040000; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EMULTIHOP: c_int = 72; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EBADMSG: c_int = 74; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const EHWPOISON: c_int = 133; pub const ERFKILL: c_int = 132; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = 31; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const O_ASYNC: c_int = 0x2000; pub const O_NDELAY: c_int = 0x800; pub const PTRACE_DETACH: c_uint = 17; pub const EFD_NONBLOCK: c_int = 0x800; pub const F_GETLK: c_int = 5; pub const F_GETOWN: c_int = 9; pub const F_SETOWN: c_int = 8; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const F_RDLCK: c_int = 0; pub const F_WRLCK: c_int = 1; pub const F_UNLCK: c_int = 2; pub const SFD_NONBLOCK: c_int = 0x0800; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const SFD_CLOEXEC: c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_CLOEXEC: c_int = 0x80000; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EDOTDOT: c_int = 73; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EFD_CLOEXEC: c_int = 0x80000; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: crate::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const O_DIRECTORY: c_int = 0x4000; pub const O_NOFOLLOW: c_int = 0x8000; pub const O_DIRECT: c_int = 0x20000; pub const MAP_LOCKED: c_int = 0x00080; pub const MAP_NORESERVE: c_int = 0x00040; pub const MAP_SYNC: c_int = 0x080000; pub const EDEADLOCK: c_int = 58; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const MCL_CURRENT: c_int = 0x2000; pub const MCL_FUTURE: c_int = 0x4000; pub const MCL_ONFAULT: c_int = 0x8000; pub const SIGSTKSZ: size_t = 0x4000; pub const MINSIGSTKSZ: size_t = 4096; pub const CBAUD: crate::tcflag_t = 0xff; pub const TAB1: crate::tcflag_t = 0x400; pub const TAB2: crate::tcflag_t = 0x800; pub const TAB3: crate::tcflag_t = 0xc00; pub const CR1: crate::tcflag_t = 0x1000; pub const CR2: crate::tcflag_t = 0x2000; pub const CR3: crate::tcflag_t = 0x3000; pub const FF1: crate::tcflag_t = 0x4000; pub const BS1: crate::tcflag_t = 0x8000; pub const VT1: crate::tcflag_t = 0x10000; pub const VWERASE: usize = 0xa; pub const VREPRINT: usize = 0xb; pub const VSUSP: usize = 0xc; pub const VSTART: usize = 0xd; pub const VSTOP: usize = 0xe; pub const VDISCARD: usize = 0x10; pub const VTIME: usize = 0x7; pub const IXON: crate::tcflag_t = 0x200; pub const IXOFF: crate::tcflag_t = 0x400; pub const ONLCR: crate::tcflag_t = 0x2; pub const CSIZE: crate::tcflag_t = 0x300; pub const CS6: crate::tcflag_t = 0x100; pub const CS7: crate::tcflag_t = 0x200; pub const CS8: crate::tcflag_t = 0x300; pub const CSTOPB: crate::tcflag_t = 0x400; pub const CREAD: crate::tcflag_t = 0x800; pub const PARENB: crate::tcflag_t = 0x1000; pub const PARODD: crate::tcflag_t = 0x2000; pub const HUPCL: crate::tcflag_t = 0x4000; pub const CLOCAL: crate::tcflag_t = 0x8000; pub const ECHOKE: crate::tcflag_t = 0x1; pub const ECHOE: crate::tcflag_t = 0x2; pub const ECHOK: crate::tcflag_t = 0x4; pub const ECHONL: crate::tcflag_t = 0x10; pub const ECHOPRT: crate::tcflag_t = 0x20; pub const ECHOCTL: crate::tcflag_t = 0x40; pub const ISIG: crate::tcflag_t = 0x80; pub const ICANON: crate::tcflag_t = 0x100; pub const PENDIN: crate::tcflag_t = 0x20000000; pub const NOFLSH: crate::tcflag_t = 0x80000000; pub const VSWTC: usize = 9; pub const OLCUC: crate::tcflag_t = 0o000004; pub const NLDLY: crate::tcflag_t = 0o001400; pub const CRDLY: crate::tcflag_t = 0o030000; pub const TABDLY: crate::tcflag_t = 0o006000; pub const BSDLY: crate::tcflag_t = 0o100000; pub const FFDLY: crate::tcflag_t = 0o040000; pub const VTDLY: crate::tcflag_t = 0o200000; pub const XTABS: crate::tcflag_t = 0o006000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const CBAUDEX: crate::speed_t = 0o000020; pub const B57600: crate::speed_t = 0o0020; pub const B115200: crate::speed_t = 0o0021; pub const B230400: crate::speed_t = 0o0022; pub const B460800: crate::speed_t = 0o0023; pub const B500000: crate::speed_t = 0o0024; pub const B576000: crate::speed_t = 0o0025; pub const B921600: crate::speed_t = 0o0026; pub const B1000000: crate::speed_t = 0o0027; pub const B1152000: crate::speed_t = 0o0030; pub const B1500000: crate::speed_t = 0o0031; pub const B2000000: crate::speed_t = 0o0032; pub const B2500000: crate::speed_t = 0o0033; pub const B3000000: crate::speed_t = 0o0034; pub const B3500000: crate::speed_t = 0o0035; pub const B4000000: crate::speed_t = 0o0036; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; pub const VMIN: usize = 5; pub const IEXTEN: crate::tcflag_t = 0x400; pub const TOSTOP: crate::tcflag_t = 0x400000; pub const FLUSHO: crate::tcflag_t = 0x800000; pub const EXTPROC: crate::tcflag_t = 0x10000000; // Syscall table pub const SYS_restart_syscall: c_long = 0; pub const SYS_exit: c_long = 1; pub const SYS_fork: c_long = 2; pub const SYS_read: c_long = 3; pub const SYS_write: c_long = 4; pub const SYS_open: c_long = 5; pub const SYS_close: c_long = 6; pub const SYS_waitpid: c_long = 7; pub const SYS_creat: c_long = 8; pub const SYS_link: c_long = 9; pub const SYS_unlink: c_long = 10; pub const SYS_execve: c_long = 11; pub const SYS_chdir: c_long = 12; pub const SYS_time: c_long = 13; pub const SYS_mknod: c_long = 14; pub const SYS_chmod: c_long = 15; pub const SYS_lchown: c_long = 16; pub const SYS_break: c_long = 17; pub const SYS_oldstat: c_long = 18; pub const SYS_lseek: c_long = 19; pub const SYS_getpid: c_long = 20; pub const SYS_mount: c_long = 21; pub const SYS_umount: c_long = 22; pub const SYS_setuid: c_long = 23; pub const SYS_getuid: c_long = 24; pub const SYS_stime: c_long = 25; pub const SYS_ptrace: c_long = 26; pub const SYS_alarm: c_long = 27; pub const SYS_oldfstat: c_long = 28; pub const SYS_pause: c_long = 29; pub const SYS_utime: c_long = 30; pub const SYS_stty: c_long = 31; pub const SYS_gtty: c_long = 32; pub const SYS_access: c_long = 33; pub const SYS_nice: c_long = 34; pub const SYS_ftime: c_long = 35; pub const SYS_sync: c_long = 36; pub const SYS_kill: c_long = 37; pub const SYS_rename: c_long = 38; pub const SYS_mkdir: c_long = 39; pub const SYS_rmdir: c_long = 40; pub const SYS_dup: c_long = 41; pub const SYS_pipe: c_long = 42; pub const SYS_times: c_long = 43; pub const SYS_prof: c_long = 44; pub const SYS_brk: c_long = 45; pub const SYS_setgid: c_long = 46; pub const SYS_getgid: c_long = 47; pub const SYS_signal: c_long = 48; pub const SYS_geteuid: c_long = 49; pub const SYS_getegid: c_long = 50; pub const SYS_acct: c_long = 51; pub const SYS_umount2: c_long = 52; pub const SYS_lock: c_long = 53; pub const SYS_ioctl: c_long = 54; pub const SYS_fcntl: c_long = 55; pub const SYS_mpx: c_long = 56; pub const SYS_setpgid: c_long = 57; pub const SYS_ulimit: c_long = 58; pub const SYS_oldolduname: c_long = 59; pub const SYS_umask: c_long = 60; pub const SYS_chroot: c_long = 61; pub const SYS_ustat: c_long = 62; pub const SYS_dup2: c_long = 63; pub const SYS_getppid: c_long = 64; pub const SYS_getpgrp: c_long = 65; pub const SYS_setsid: c_long = 66; pub const SYS_sigaction: c_long = 67; pub const SYS_sgetmask: c_long = 68; pub const SYS_ssetmask: c_long = 69; pub const SYS_setreuid: c_long = 70; pub const SYS_setregid: c_long = 71; pub const SYS_sigsuspend: c_long = 72; pub const SYS_sigpending: c_long = 73; pub const SYS_sethostname: c_long = 74; pub const SYS_setrlimit: c_long = 75; pub const SYS_getrlimit: c_long = 76; pub const SYS_getrusage: c_long = 77; pub const SYS_gettimeofday: c_long = 78; pub const SYS_settimeofday: c_long = 79; pub const SYS_getgroups: c_long = 80; pub const SYS_setgroups: c_long = 81; pub const SYS_select: c_long = 82; pub const SYS_symlink: c_long = 83; pub const SYS_oldlstat: c_long = 84; pub const SYS_readlink: c_long = 85; pub const SYS_uselib: c_long = 86; pub const SYS_swapon: c_long = 87; pub const SYS_reboot: c_long = 88; pub const SYS_readdir: c_long = 89; pub const SYS_mmap: c_long = 90; pub const SYS_munmap: c_long = 91; pub const SYS_truncate: c_long = 92; pub const SYS_ftruncate: c_long = 93; pub const SYS_fchmod: c_long = 94; pub const SYS_fchown: c_long = 95; pub const SYS_getpriority: c_long = 96; pub const SYS_setpriority: c_long = 97; pub const SYS_profil: c_long = 98; pub const SYS_statfs: c_long = 99; pub const SYS_fstatfs: c_long = 100; pub const SYS_ioperm: c_long = 101; pub const SYS_socketcall: c_long = 102; pub const SYS_syslog: c_long = 103; pub const SYS_setitimer: c_long = 104; pub const SYS_getitimer: c_long = 105; pub const SYS_stat: c_long = 106; pub const SYS_lstat: c_long = 107; pub const SYS_fstat: c_long = 108; pub const SYS_olduname: c_long = 109; pub const SYS_iopl: c_long = 110; pub const SYS_vhangup: c_long = 111; pub const SYS_idle: c_long = 112; pub const SYS_vm86: c_long = 113; pub const SYS_wait4: c_long = 114; pub const SYS_swapoff: c_long = 115; pub const SYS_sysinfo: c_long = 116; pub const SYS_ipc: c_long = 117; pub const SYS_fsync: c_long = 118; pub const SYS_sigreturn: c_long = 119; pub const SYS_clone: c_long = 120; pub const SYS_setdomainname: c_long = 121; pub const SYS_uname: c_long = 122; pub const SYS_modify_ldt: c_long = 123; pub const SYS_adjtimex: c_long = 124; pub const SYS_mprotect: c_long = 125; pub const SYS_sigprocmask: c_long = 126; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_create_module: c_long = 127; pub const SYS_init_module: c_long = 128; pub const SYS_delete_module: c_long = 129; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_get_kernel_syms: c_long = 130; pub const SYS_quotactl: c_long = 131; pub const SYS_getpgid: c_long = 132; pub const SYS_fchdir: c_long = 133; pub const SYS_bdflush: c_long = 134; pub const SYS_sysfs: c_long = 135; pub const SYS_personality: c_long = 136; pub const SYS_afs_syscall: c_long = 137; /* Syscall for Andrew File System */ pub const SYS_setfsuid: c_long = 138; pub const SYS_setfsgid: c_long = 139; pub const SYS__llseek: c_long = 140; pub const SYS_getdents: c_long = 141; pub const SYS__newselect: c_long = 142; pub const SYS_flock: c_long = 143; pub const SYS_msync: c_long = 144; pub const SYS_readv: c_long = 145; pub const SYS_writev: c_long = 146; pub const SYS_getsid: c_long = 147; pub const SYS_fdatasync: c_long = 148; pub const SYS__sysctl: c_long = 149; pub const SYS_mlock: c_long = 150; pub const SYS_munlock: c_long = 151; pub const SYS_mlockall: c_long = 152; pub const SYS_munlockall: c_long = 153; pub const SYS_sched_setparam: c_long = 154; pub const SYS_sched_getparam: c_long = 155; pub const SYS_sched_setscheduler: c_long = 156; pub const SYS_sched_getscheduler: c_long = 157; pub const SYS_sched_yield: c_long = 158; pub const SYS_sched_get_priority_max: c_long = 159; pub const SYS_sched_get_priority_min: c_long = 160; pub const SYS_sched_rr_get_interval: c_long = 161; pub const SYS_nanosleep: c_long = 162; pub const SYS_mremap: c_long = 163; pub const SYS_setresuid: c_long = 164; pub const SYS_getresuid: c_long = 165; #[deprecated(since = "0.2.70", note = "Functional up to 2.6 kernel")] pub const SYS_query_module: c_long = 166; pub const SYS_poll: c_long = 167; pub const SYS_nfsservctl: c_long = 168; pub const SYS_setresgid: c_long = 169; pub const SYS_getresgid: c_long = 170; pub const SYS_prctl: c_long = 171; pub const SYS_rt_sigreturn: c_long = 172; pub const SYS_rt_sigaction: c_long = 173; pub const SYS_rt_sigprocmask: c_long = 174; pub const SYS_rt_sigpending: c_long = 175; pub const SYS_rt_sigtimedwait: c_long = 176; pub const SYS_rt_sigqueueinfo: c_long = 177; pub const SYS_rt_sigsuspend: c_long = 178; pub const SYS_pread64: c_long = 179; pub const SYS_pwrite64: c_long = 180; pub const SYS_chown: c_long = 181; pub const SYS_getcwd: c_long = 182; pub const SYS_capget: c_long = 183; pub const SYS_capset: c_long = 184; pub const SYS_sigaltstack: c_long = 185; pub const SYS_sendfile: c_long = 186; pub const SYS_getpmsg: c_long = 187; /* some people actually want streams */ pub const SYS_putpmsg: c_long = 188; /* some people actually want streams */ pub const SYS_vfork: c_long = 189; pub const SYS_ugetrlimit: c_long = 190; /* SuS compliant getrlimit */ pub const SYS_readahead: c_long = 191; pub const SYS_pciconfig_read: c_long = 198; pub const SYS_pciconfig_write: c_long = 199; pub const SYS_pciconfig_iobase: c_long = 200; pub const SYS_multiplexer: c_long = 201; pub const SYS_getdents64: c_long = 202; pub const SYS_pivot_root: c_long = 203; pub const SYS_madvise: c_long = 205; pub const SYS_mincore: c_long = 206; pub const SYS_gettid: c_long = 207; pub const SYS_tkill: c_long = 208; pub const SYS_setxattr: c_long = 209; pub const SYS_lsetxattr: c_long = 210; pub const SYS_fsetxattr: c_long = 211; pub const SYS_getxattr: c_long = 212; pub const SYS_lgetxattr: c_long = 213; pub const SYS_fgetxattr: c_long = 214; pub const SYS_listxattr: c_long = 215; pub const SYS_llistxattr: c_long = 216; pub const SYS_flistxattr: c_long = 217; pub const SYS_removexattr: c_long = 218; pub const SYS_lremovexattr: c_long = 219; pub const SYS_fremovexattr: c_long = 220; pub const SYS_futex: c_long = 221; pub const SYS_sched_setaffinity: c_long = 222; pub const SYS_sched_getaffinity: c_long = 223; pub const SYS_tuxcall: c_long = 225; pub const SYS_io_setup: c_long = 227; pub const SYS_io_destroy: c_long = 228; pub const SYS_io_getevents: c_long = 229; pub const SYS_io_submit: c_long = 230; pub const SYS_io_cancel: c_long = 231; pub const SYS_set_tid_address: c_long = 232; pub const SYS_exit_group: c_long = 234; pub const SYS_lookup_dcookie: c_long = 235; pub const SYS_epoll_create: c_long = 236; pub const SYS_epoll_ctl: c_long = 237; pub const SYS_epoll_wait: c_long = 238; pub const SYS_remap_file_pages: c_long = 239; pub const SYS_timer_create: c_long = 240; pub const SYS_timer_settime: c_long = 241; pub const SYS_timer_gettime: c_long = 242; pub const SYS_timer_getoverrun: c_long = 243; pub const SYS_timer_delete: c_long = 244; pub const SYS_clock_settime: c_long = 245; pub const SYS_clock_gettime: c_long = 246; pub const SYS_clock_getres: c_long = 247; pub const SYS_clock_nanosleep: c_long = 248; pub const SYS_swapcontext: c_long = 249; pub const SYS_tgkill: c_long = 250; pub const SYS_utimes: c_long = 251; pub const SYS_statfs64: c_long = 252; pub const SYS_fstatfs64: c_long = 253; pub const SYS_rtas: c_long = 255; pub const SYS_sys_debug_setcontext: c_long = 256; pub const SYS_migrate_pages: c_long = 258; pub const SYS_mbind: c_long = 259; pub const SYS_get_mempolicy: c_long = 260; pub const SYS_set_mempolicy: c_long = 261; pub const SYS_mq_open: c_long = 262; pub const SYS_mq_unlink: c_long = 263; pub const SYS_mq_timedsend: c_long = 264; pub const SYS_mq_timedreceive: c_long = 265; pub const SYS_mq_notify: c_long = 266; pub const SYS_mq_getsetattr: c_long = 267; pub const SYS_kexec_load: c_long = 268; pub const SYS_add_key: c_long = 269; pub const SYS_request_key: c_long = 270; pub const SYS_keyctl: c_long = 271; pub const SYS_waitid: c_long = 272; pub const SYS_ioprio_set: c_long = 273; pub const SYS_ioprio_get: c_long = 274; pub const SYS_inotify_init: c_long = 275; pub const SYS_inotify_add_watch: c_long = 276; pub const SYS_inotify_rm_watch: c_long = 277; pub const SYS_spu_run: c_long = 278; pub const SYS_spu_create: c_long = 279; pub const SYS_pselect6: c_long = 280; pub const SYS_ppoll: c_long = 281; pub const SYS_unshare: c_long = 282; pub const SYS_splice: c_long = 283; pub const SYS_tee: c_long = 284; pub const SYS_vmsplice: c_long = 285; pub const SYS_openat: c_long = 286; pub const SYS_mkdirat: c_long = 287; pub const SYS_mknodat: c_long = 288; pub const SYS_fchownat: c_long = 289; pub const SYS_futimesat: c_long = 290; pub const SYS_newfstatat: c_long = 291; pub const SYS_unlinkat: c_long = 292; pub const SYS_renameat: c_long = 293; pub const SYS_linkat: c_long = 294; pub const SYS_symlinkat: c_long = 295; pub const SYS_readlinkat: c_long = 296; pub const SYS_fchmodat: c_long = 297; pub const SYS_faccessat: c_long = 298; pub const SYS_get_robust_list: c_long = 299; pub const SYS_set_robust_list: c_long = 300; pub const SYS_move_pages: c_long = 301; pub const SYS_getcpu: c_long = 302; pub const SYS_epoll_pwait: c_long = 303; pub const SYS_utimensat: c_long = 304; pub const SYS_signalfd: c_long = 305; pub const SYS_timerfd_create: c_long = 306; pub const SYS_eventfd: c_long = 307; pub const SYS_sync_file_range2: c_long = 308; pub const SYS_fallocate: c_long = 309; pub const SYS_subpage_prot: c_long = 310; pub const SYS_timerfd_settime: c_long = 311; pub const SYS_timerfd_gettime: c_long = 312; pub const SYS_signalfd4: c_long = 313; pub const SYS_eventfd2: c_long = 314; pub const SYS_epoll_create1: c_long = 315; pub const SYS_dup3: c_long = 316; pub const SYS_pipe2: c_long = 317; pub const SYS_inotify_init1: c_long = 318; pub const SYS_perf_event_open: c_long = 319; pub const SYS_preadv: c_long = 320; pub const SYS_pwritev: c_long = 321; pub const SYS_rt_tgsigqueueinfo: c_long = 322; pub const SYS_fanotify_init: c_long = 323; pub const SYS_fanotify_mark: c_long = 324; pub const SYS_prlimit64: c_long = 325; pub const SYS_socket: c_long = 326; pub const SYS_bind: c_long = 327; pub const SYS_connect: c_long = 328; pub const SYS_listen: c_long = 329; pub const SYS_accept: c_long = 330; pub const SYS_getsockname: c_long = 331; pub const SYS_getpeername: c_long = 332; pub const SYS_socketpair: c_long = 333; pub const SYS_send: c_long = 334; pub const SYS_sendto: c_long = 335; pub const SYS_recv: c_long = 336; pub const SYS_recvfrom: c_long = 337; pub const SYS_shutdown: c_long = 338; pub const SYS_setsockopt: c_long = 339; pub const SYS_getsockopt: c_long = 340; pub const SYS_sendmsg: c_long = 341; pub const SYS_recvmsg: c_long = 342; pub const SYS_recvmmsg: c_long = 343; pub const SYS_accept4: c_long = 344; pub const SYS_name_to_handle_at: c_long = 345; pub const SYS_open_by_handle_at: c_long = 346; pub const SYS_clock_adjtime: c_long = 347; pub const SYS_syncfs: c_long = 348; pub const SYS_sendmmsg: c_long = 349; pub const SYS_setns: c_long = 350; pub const SYS_process_vm_readv: c_long = 351; pub const SYS_process_vm_writev: c_long = 352; pub const SYS_finit_module: c_long = 353; pub const SYS_kcmp: c_long = 354; pub const SYS_sched_setattr: c_long = 355; pub const SYS_sched_getattr: c_long = 356; pub const SYS_renameat2: c_long = 357; pub const SYS_seccomp: c_long = 358; pub const SYS_getrandom: c_long = 359; pub const SYS_memfd_create: c_long = 360; pub const SYS_bpf: c_long = 361; pub const SYS_execveat: c_long = 362; pub const SYS_switch_endian: c_long = 363; pub const SYS_userfaultfd: c_long = 364; pub const SYS_membarrier: c_long = 365; pub const SYS_mlock2: c_long = 378; pub const SYS_copy_file_range: c_long = 379; pub const SYS_preadv2: c_long = 380; pub const SYS_pwritev2: c_long = 381; pub const SYS_kexec_file_load: c_long = 382; pub const SYS_statx: c_long = 383; pub const SYS_rseq: c_long = 387; pub const SYS_pidfd_send_signal: c_long = 424; pub const SYS_io_uring_setup: c_long = 425; pub const SYS_io_uring_enter: c_long = 426; pub const SYS_io_uring_register: c_long = 427; pub const SYS_open_tree: c_long = 428; pub const SYS_move_mount: c_long = 429; pub const SYS_fsopen: c_long = 430; pub const SYS_fsconfig: c_long = 431; pub const SYS_fsmount: c_long = 432; pub const SYS_fspick: c_long = 433; pub const SYS_pidfd_open: c_long = 434; pub const SYS_clone3: c_long = 435; pub const SYS_close_range: c_long = 436; pub const SYS_openat2: c_long = 437; pub const SYS_pidfd_getfd: c_long = 438; pub const SYS_faccessat2: c_long = 439; pub const SYS_process_madvise: c_long = 440; pub const SYS_epoll_pwait2: c_long = 441; pub const SYS_mount_setattr: c_long = 442; pub const SYS_quotactl_fd: c_long = 443; pub const SYS_landlock_create_ruleset: c_long = 444; pub const SYS_landlock_add_rule: c_long = 445; pub const SYS_landlock_restrict_self: c_long = 446; pub const SYS_memfd_secret: c_long = 447; pub const SYS_process_mrelease: c_long = 448; pub const SYS_futex_waitv: c_long = 449; pub const SYS_set_mempolicy_home_node: c_long = 450; extern "C" { pub fn sysctl( name: *mut c_int, namelen: c_int, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; } libc/src/unix/linux_like/emscripten/0000775000175000017500000000000015105742312017403 5ustar bdrungbdrunglibc/src/unix/linux_like/emscripten/mod.rs0000644000175000017500000014777215105742312020550 0ustar bdrungbdrunguse crate::prelude::*; pub type wchar_t = i32; pub type useconds_t = u32; pub type dev_t = u32; pub type socklen_t = u32; pub type pthread_t = c_ulong; pub type mode_t = u32; pub type shmatt_t = c_ulong; pub type mqd_t = c_int; pub type msgqnum_t = c_ulong; pub type msglen_t = c_ulong; pub type nfds_t = c_ulong; pub type nl_item = c_int; pub type idtype_t = c_uint; pub type loff_t = i64; pub type pthread_key_t = c_uint; pub type clock_t = c_long; pub type time_t = i64; pub type suseconds_t = c_long; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i32; pub type blksize_t = c_long; pub type fsblkcnt_t = u32; pub type fsfilcnt_t = u32; pub type rlim_t = u64; pub type nlink_t = u32; pub type ino64_t = crate::ino_t; pub type off64_t = off_t; pub type blkcnt64_t = crate::blkcnt_t; pub type rlim64_t = crate::rlim_t; pub type rlimit64 = crate::rlimit; pub type flock64 = crate::flock; pub type stat64 = crate::stat; pub type statfs64 = crate::statfs; pub type statvfs64 = crate::statvfs; pub type dirent64 = crate::dirent; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos64_t {} // FIXME(emscripten): fill this out with a struct impl Copy for fpos64_t {} impl Clone for fpos64_t { fn clone(&self) -> fpos64_t { *self } } s! { pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct spwd { pub sp_namp: *mut c_char, pub sp_pwdp: *mut c_char, pub sp_lstchg: c_long, pub sp_min: c_long, pub sp_max: c_long, pub sp_warn: c_long, pub sp_inact: c_long, pub sp_expire: c_long, pub sp_flag: c_ulong, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, __f_unused: c_int, pub f_flag: c_ulong, pub f_namemax: c_ulong, __f_spare: [c_int; 6], } pub struct signalfd_siginfo { pub ssi_signo: u32, pub ssi_errno: i32, pub ssi_code: i32, pub ssi_pid: u32, pub ssi_uid: u32, pub ssi_fd: i32, pub ssi_tid: u32, pub ssi_band: u32, pub ssi_overrun: u32, pub ssi_trapno: u32, pub ssi_status: i32, pub ssi_int: i32, pub ssi_ptr: u64, pub ssi_utime: u64, pub ssi_stime: u64, pub ssi_addr: u64, pub ssi_addr_lsb: u16, _pad2: u16, pub ssi_syscall: i32, pub ssi_call_addr: u64, pub ssi_arch: u32, _pad: [u8; 28], } pub struct fsid_t { __val: [c_int; 2], } pub struct cpu_set_t { bits: [u32; 32], } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } // System V IPC pub struct msginfo { pub msgpool: c_int, pub msgmap: c_int, pub msgmax: c_int, pub msgmnb: c_int, pub msgmni: c_int, pub msgssz: c_int, pub msgtql: c_int, pub msgseg: c_ushort, } pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, pub sa_restorer: Option, } pub struct ipc_perm { pub __ipc_perm_key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub __seq: c_int, __unused1: c_long, __unused2: c_long, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], pub __c_ispeed: crate::speed_t, pub __c_ospeed: crate::speed_t, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct pthread_attr_t { __size: [u32; 11], } pub struct sigset_t { __val: [c_ulong; 32], } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct sem_t { __val: [c_int; 4], } pub struct stat { pub st_dev: crate::dev_t, #[cfg(emscripten_old_stat_abi)] __st_dev_padding: c_int, #[cfg(emscripten_old_stat_abi)] __st_ino_truncated: c_long, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, #[cfg(emscripten_old_stat_abi)] __st_rdev_padding: c_int, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_ino: crate::ino_t, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_cpid: crate::pid_t, pub shm_lpid: crate::pid_t, pub shm_nattch: c_ulong, __pad1: c_ulong, __pad2: c_ulong, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, pub __msg_cbytes: c_ulong, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, __pad1: c_ulong, __pad2: c_ulong, } pub struct statfs { pub f_type: c_ulong, pub f_bsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_fsid: crate::fsid_t, pub f_namelen: c_ulong, pub f_frsize: c_ulong, pub f_flags: c_ulong, pub f_spare: [c_ulong; 4], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, pub _pad: [c_int; 29], _align: [usize; 0], } pub struct arpd_request { pub req: c_ushort, pub ip: u32, pub dev: c_ulong, pub stamp: c_ulong, pub updated: c_ulong, pub ha: [c_uchar; crate::MAX_ADDR_LEN], } #[allow(missing_debug_implementations)] #[repr(align(4))] pub struct pthread_mutex_t { size: [u8; crate::__SIZEOF_PTHREAD_MUTEX_T], } #[repr(align(4))] pub struct pthread_rwlock_t { size: [u8; crate::__SIZEOF_PTHREAD_RWLOCK_T], } #[repr(align(4))] pub struct pthread_mutexattr_t { size: [u8; crate::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[repr(align(4))] pub struct pthread_rwlockattr_t { size: [u8; crate::__SIZEOF_PTHREAD_RWLOCKATTR_T], } #[repr(align(4))] pub struct pthread_condattr_t { size: [u8; crate::__SIZEOF_PTHREAD_CONDATTR_T], } } s_no_extra_traits! { pub struct dirent { pub d_ino: crate::ino_t, pub d_off: off_t, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } pub struct sysinfo { pub uptime: c_ulong, pub loads: [c_ulong; 3], pub totalram: c_ulong, pub freeram: c_ulong, pub sharedram: c_ulong, pub bufferram: c_ulong, pub totalswap: c_ulong, pub freeswap: c_ulong, pub procs: c_ushort, pub pad: c_ushort, pub totalhigh: c_ulong, pub freehigh: c_ulong, pub mem_unit: c_uint, pub __reserved: [c_char; 256], } pub struct mq_attr { pub mq_flags: c_long, pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_curmsgs: c_long, pad: [c_long; 4], } #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct pthread_cond_t { size: [u8; crate::__SIZEOF_PTHREAD_COND_T], } #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f64; 3], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for sysinfo { fn eq(&self, other: &sysinfo) -> bool { self.uptime == other.uptime && self.loads == other.loads && self.totalram == other.totalram && self.freeram == other.freeram && self.sharedram == other.sharedram && self.bufferram == other.bufferram && self.totalswap == other.totalswap && self.freeswap == other.freeswap && self.procs == other.procs && self.pad == other.pad && self.totalhigh == other.totalhigh && self.freehigh == other.freehigh && self.mem_unit == other.mem_unit && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a, b)| a == b) } } impl Eq for sysinfo {} impl fmt::Debug for sysinfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sysinfo") .field("uptime", &self.uptime) .field("loads", &self.loads) .field("totalram", &self.totalram) .field("freeram", &self.freeram) .field("sharedram", &self.sharedram) .field("bufferram", &self.bufferram) .field("totalswap", &self.totalswap) .field("freeswap", &self.freeswap) .field("procs", &self.procs) .field("pad", &self.pad) .field("totalhigh", &self.totalhigh) .field("freehigh", &self.freehigh) .field("mem_unit", &self.mem_unit) // FIXME(debug): .field("__reserved", &self.__reserved) .finish() } } impl hash::Hash for sysinfo { fn hash(&self, state: &mut H) { self.uptime.hash(state); self.loads.hash(state); self.totalram.hash(state); self.freeram.hash(state); self.sharedram.hash(state); self.bufferram.hash(state); self.totalswap.hash(state); self.freeswap.hash(state); self.procs.hash(state); self.pad.hash(state); self.totalhigh.hash(state); self.freehigh.hash(state); self.mem_unit.hash(state); self.__reserved.hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_flags == other.mq_flags && self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_curmsgs == other.mq_curmsgs } } impl Eq for mq_attr {} impl fmt::Debug for mq_attr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mq_attr") .field("mq_flags", &self.mq_flags) .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_curmsgs", &self.mq_curmsgs) .finish() } } impl hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_flags.hash(state); self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_curmsgs.hash(state); } } impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a, b)| a == b) } } impl Eq for pthread_cond_t {} impl fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_cond_t") // FIXME(debug): .field("size", &self.size) .finish() } } impl hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } } } pub const MADV_SOFT_OFFLINE: c_int = 101; pub const MS_NOUSER: c_ulong = 0x80000000; pub const MS_RMT_MASK: c_ulong = 0x02800051; pub const ABDAY_1: crate::nl_item = 0x20000; pub const ABDAY_2: crate::nl_item = 0x20001; pub const ABDAY_3: crate::nl_item = 0x20002; pub const ABDAY_4: crate::nl_item = 0x20003; pub const ABDAY_5: crate::nl_item = 0x20004; pub const ABDAY_6: crate::nl_item = 0x20005; pub const ABDAY_7: crate::nl_item = 0x20006; pub const DAY_1: crate::nl_item = 0x20007; pub const DAY_2: crate::nl_item = 0x20008; pub const DAY_3: crate::nl_item = 0x20009; pub const DAY_4: crate::nl_item = 0x2000A; pub const DAY_5: crate::nl_item = 0x2000B; pub const DAY_6: crate::nl_item = 0x2000C; pub const DAY_7: crate::nl_item = 0x2000D; pub const ABMON_1: crate::nl_item = 0x2000E; pub const ABMON_2: crate::nl_item = 0x2000F; pub const ABMON_3: crate::nl_item = 0x20010; pub const ABMON_4: crate::nl_item = 0x20011; pub const ABMON_5: crate::nl_item = 0x20012; pub const ABMON_6: crate::nl_item = 0x20013; pub const ABMON_7: crate::nl_item = 0x20014; pub const ABMON_8: crate::nl_item = 0x20015; pub const ABMON_9: crate::nl_item = 0x20016; pub const ABMON_10: crate::nl_item = 0x20017; pub const ABMON_11: crate::nl_item = 0x20018; pub const ABMON_12: crate::nl_item = 0x20019; pub const MON_1: crate::nl_item = 0x2001A; pub const MON_2: crate::nl_item = 0x2001B; pub const MON_3: crate::nl_item = 0x2001C; pub const MON_4: crate::nl_item = 0x2001D; pub const MON_5: crate::nl_item = 0x2001E; pub const MON_6: crate::nl_item = 0x2001F; pub const MON_7: crate::nl_item = 0x20020; pub const MON_8: crate::nl_item = 0x20021; pub const MON_9: crate::nl_item = 0x20022; pub const MON_10: crate::nl_item = 0x20023; pub const MON_11: crate::nl_item = 0x20024; pub const MON_12: crate::nl_item = 0x20025; pub const AM_STR: crate::nl_item = 0x20026; pub const PM_STR: crate::nl_item = 0x20027; pub const D_T_FMT: crate::nl_item = 0x20028; pub const D_FMT: crate::nl_item = 0x20029; pub const T_FMT: crate::nl_item = 0x2002A; pub const T_FMT_AMPM: crate::nl_item = 0x2002B; pub const ERA: crate::nl_item = 0x2002C; pub const ERA_D_FMT: crate::nl_item = 0x2002E; pub const ALT_DIGITS: crate::nl_item = 0x2002F; pub const ERA_D_T_FMT: crate::nl_item = 0x20030; pub const ERA_T_FMT: crate::nl_item = 0x20031; pub const CODESET: crate::nl_item = 14; pub const CRNCYSTR: crate::nl_item = 0x4000F; pub const RUSAGE_THREAD: c_int = 1; pub const RUSAGE_CHILDREN: c_int = -1; pub const RADIXCHAR: crate::nl_item = 0x10000; pub const THOUSEP: crate::nl_item = 0x10001; pub const YESEXPR: crate::nl_item = 0x50000; pub const NOEXPR: crate::nl_item = 0x50001; pub const YESSTR: crate::nl_item = 0x50002; pub const NOSTR: crate::nl_item = 0x50003; pub const FILENAME_MAX: c_uint = 4096; pub const L_tmpnam: c_uint = 20; pub const _PC_LINK_MAX: c_int = 0; pub const _PC_MAX_CANON: c_int = 1; pub const _PC_MAX_INPUT: c_int = 2; pub const _PC_NAME_MAX: c_int = 3; pub const _PC_PATH_MAX: c_int = 4; pub const _PC_PIPE_BUF: c_int = 5; pub const _PC_CHOWN_RESTRICTED: c_int = 6; pub const _PC_NO_TRUNC: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_SYNC_IO: c_int = 9; pub const _PC_ASYNC_IO: c_int = 10; pub const _PC_PRIO_IO: c_int = 11; pub const _PC_SOCK_MAXBUF: c_int = 12; pub const _PC_FILESIZEBITS: c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: c_int = 16; pub const _PC_REC_XFER_ALIGN: c_int = 17; pub const _PC_ALLOC_SIZE_MIN: c_int = 18; pub const _PC_SYMLINK_MAX: c_int = 19; pub const _PC_2_SYMLINKS: c_int = 20; pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_STREAM_MAX: c_int = 5; pub const _SC_TZNAME_MAX: c_int = 6; pub const _SC_JOB_CONTROL: c_int = 7; pub const _SC_SAVED_IDS: c_int = 8; pub const _SC_REALTIME_SIGNALS: c_int = 9; pub const _SC_PRIORITY_SCHEDULING: c_int = 10; pub const _SC_TIMERS: c_int = 11; pub const _SC_ASYNCHRONOUS_IO: c_int = 12; pub const _SC_PRIORITIZED_IO: c_int = 13; pub const _SC_SYNCHRONIZED_IO: c_int = 14; pub const _SC_FSYNC: c_int = 15; pub const _SC_MAPPED_FILES: c_int = 16; pub const _SC_MEMLOCK: c_int = 17; pub const _SC_MEMLOCK_RANGE: c_int = 18; pub const _SC_MEMORY_PROTECTION: c_int = 19; pub const _SC_MESSAGE_PASSING: c_int = 20; pub const _SC_SEMAPHORES: c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 22; pub const _SC_AIO_LISTIO_MAX: c_int = 23; pub const _SC_AIO_MAX: c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 25; pub const _SC_DELAYTIMER_MAX: c_int = 26; pub const _SC_MQ_OPEN_MAX: c_int = 27; pub const _SC_MQ_PRIO_MAX: c_int = 28; pub const _SC_VERSION: c_int = 29; pub const _SC_PAGESIZE: c_int = 30; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_RTSIG_MAX: c_int = 31; pub const _SC_SEM_NSEMS_MAX: c_int = 32; pub const _SC_SEM_VALUE_MAX: c_int = 33; pub const _SC_SIGQUEUE_MAX: c_int = 34; pub const _SC_TIMER_MAX: c_int = 35; pub const _SC_BC_BASE_MAX: c_int = 36; pub const _SC_BC_DIM_MAX: c_int = 37; pub const _SC_BC_SCALE_MAX: c_int = 38; pub const _SC_BC_STRING_MAX: c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: c_int = 40; pub const _SC_EXPR_NEST_MAX: c_int = 42; pub const _SC_LINE_MAX: c_int = 43; pub const _SC_RE_DUP_MAX: c_int = 44; pub const _SC_2_VERSION: c_int = 46; pub const _SC_2_C_BIND: c_int = 47; pub const _SC_2_C_DEV: c_int = 48; pub const _SC_2_FORT_DEV: c_int = 49; pub const _SC_2_FORT_RUN: c_int = 50; pub const _SC_2_SW_DEV: c_int = 51; pub const _SC_2_LOCALEDEF: c_int = 52; pub const _SC_UIO_MAXIOV: c_int = 60; pub const _SC_IOV_MAX: c_int = 60; pub const _SC_THREADS: c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: c_int = 70; pub const _SC_LOGIN_NAME_MAX: c_int = 71; pub const _SC_TTY_NAME_MAX: c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73; pub const _SC_THREAD_KEYS_MAX: c_int = 74; pub const _SC_THREAD_STACK_MIN: c_int = 75; pub const _SC_THREAD_THREADS_MAX: c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: c_int = 82; pub const _SC_NPROCESSORS_CONF: c_int = 83; pub const _SC_NPROCESSORS_ONLN: c_int = 84; pub const _SC_PHYS_PAGES: c_int = 85; pub const _SC_AVPHYS_PAGES: c_int = 86; pub const _SC_ATEXIT_MAX: c_int = 87; pub const _SC_PASS_MAX: c_int = 88; pub const _SC_XOPEN_VERSION: c_int = 89; pub const _SC_XOPEN_XCU_VERSION: c_int = 90; pub const _SC_XOPEN_UNIX: c_int = 91; pub const _SC_XOPEN_CRYPT: c_int = 92; pub const _SC_XOPEN_ENH_I18N: c_int = 93; pub const _SC_XOPEN_SHM: c_int = 94; pub const _SC_2_CHAR_TERM: c_int = 95; pub const _SC_2_UPE: c_int = 97; pub const _SC_XOPEN_XPG2: c_int = 98; pub const _SC_XOPEN_XPG3: c_int = 99; pub const _SC_XOPEN_XPG4: c_int = 100; pub const _SC_NZERO: c_int = 109; pub const _SC_XBS5_ILP32_OFF32: c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 126; pub const _SC_XBS5_LP64_OFF64: c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 128; pub const _SC_XOPEN_LEGACY: c_int = 129; pub const _SC_XOPEN_REALTIME: c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131; pub const _SC_ADVISORY_INFO: c_int = 132; pub const _SC_BARRIERS: c_int = 133; pub const _SC_CLOCK_SELECTION: c_int = 137; pub const _SC_CPUTIME: c_int = 138; pub const _SC_THREAD_CPUTIME: c_int = 139; pub const _SC_MONOTONIC_CLOCK: c_int = 149; pub const _SC_READER_WRITER_LOCKS: c_int = 153; pub const _SC_SPIN_LOCKS: c_int = 154; pub const _SC_REGEXP: c_int = 155; pub const _SC_SHELL: c_int = 157; pub const _SC_SPAWN: c_int = 159; pub const _SC_SPORADIC_SERVER: c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 161; pub const _SC_TIMEOUTS: c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 165; pub const _SC_2_PBS: c_int = 168; pub const _SC_2_PBS_ACCOUNTING: c_int = 169; pub const _SC_2_PBS_LOCATE: c_int = 170; pub const _SC_2_PBS_MESSAGE: c_int = 171; pub const _SC_2_PBS_TRACK: c_int = 172; pub const _SC_SYMLOOP_MAX: c_int = 173; pub const _SC_STREAMS: c_int = 174; pub const _SC_2_PBS_CHECKPOINT: c_int = 175; pub const _SC_V6_ILP32_OFF32: c_int = 176; pub const _SC_V6_ILP32_OFFBIG: c_int = 177; pub const _SC_V6_LP64_OFF64: c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: c_int = 179; pub const _SC_HOST_NAME_MAX: c_int = 180; pub const _SC_TRACE: c_int = 181; pub const _SC_TRACE_EVENT_FILTER: c_int = 182; pub const _SC_TRACE_INHERIT: c_int = 183; pub const _SC_TRACE_LOG: c_int = 184; pub const _SC_IPV6: c_int = 235; pub const _SC_RAW_SOCKETS: c_int = 236; pub const _SC_V7_ILP32_OFF32: c_int = 237; pub const _SC_V7_ILP32_OFFBIG: c_int = 238; pub const _SC_V7_LP64_OFF64: c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: c_int = 240; pub const _SC_SS_REPL_MAX: c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 242; pub const _SC_TRACE_NAME_MAX: c_int = 243; pub const _SC_TRACE_SYS_MAX: c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 245; pub const _SC_XOPEN_STREAMS: c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 248; pub const RLIM_SAVED_MAX: crate::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: crate::rlim_t = RLIM_INFINITY; pub const GLOB_ERR: c_int = 1 << 0; pub const GLOB_MARK: c_int = 1 << 1; pub const GLOB_NOSORT: c_int = 1 << 2; pub const GLOB_DOOFFS: c_int = 1 << 3; pub const GLOB_NOCHECK: c_int = 1 << 4; pub const GLOB_APPEND: c_int = 1 << 5; pub const GLOB_NOESCAPE: c_int = 1 << 6; pub const GLOB_NOSPACE: c_int = 1; pub const GLOB_ABORTED: c_int = 2; pub const GLOB_NOMATCH: c_int = 3; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 1; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const AT_EACCESS: c_int = 0x200; pub const S_IEXEC: mode_t = 0o0100; pub const S_IWRITE: mode_t = 0o0200; pub const S_IREAD: mode_t = 0o0400; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const ST_RDONLY: c_ulong = 1; pub const ST_NOSUID: c_ulong = 2; pub const ST_NODEV: c_ulong = 4; pub const ST_NOEXEC: c_ulong = 8; pub const ST_SYNCHRONOUS: c_ulong = 16; pub const ST_MANDLOCK: c_ulong = 64; pub const ST_WRITE: c_ulong = 128; pub const ST_APPEND: c_ulong = 256; pub const ST_IMMUTABLE: c_ulong = 512; pub const ST_NOATIME: c_ulong = 1024; pub const ST_NODIRATIME: c_ulong = 2048; pub const RTLD_NEXT: *mut c_void = -1i64 as *mut c_void; pub const RTLD_DEFAULT: *mut c_void = 0i64 as *mut c_void; pub const RTLD_NODELETE: c_int = 0x1000; pub const RTLD_NOW: c_int = 0x2; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { size: [0; __SIZEOF_PTHREAD_RWLOCK_T], }; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_PROCESS_PRIVATE: c_int = 0; pub const PTHREAD_PROCESS_SHARED: c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const SCHED_OTHER: c_int = 0; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const SCHED_BATCH: c_int = 3; pub const SCHED_IDLE: c_int = 5; pub const AF_IB: c_int = 27; pub const AF_MPLS: c_int = 28; pub const AF_NFC: c_int = 39; pub const AF_VSOCK: c_int = 40; pub const PF_IB: c_int = AF_IB; pub const PF_MPLS: c_int = AF_MPLS; pub const PF_NFC: c_int = AF_NFC; pub const PF_VSOCK: c_int = AF_VSOCK; // System V IPC pub const IPC_PRIVATE: crate::key_t = 0; pub const IPC_CREAT: c_int = 0o1000; pub const IPC_EXCL: c_int = 0o2000; pub const IPC_NOWAIT: c_int = 0o4000; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 1; pub const IPC_STAT: c_int = 2; pub const IPC_INFO: c_int = 3; pub const MSG_STAT: c_int = 11; pub const MSG_INFO: c_int = 12; pub const MSG_NOERROR: c_int = 0o10000; pub const MSG_EXCEPT: c_int = 0o20000; pub const SHM_R: c_int = 0o400; pub const SHM_W: c_int = 0o200; pub const SHM_RDONLY: c_int = 0o10000; pub const SHM_RND: c_int = 0o20000; pub const SHM_REMAP: c_int = 0o40000; pub const SHM_EXEC: c_int = 0o100000; pub const SHM_LOCK: c_int = 11; pub const SHM_UNLOCK: c_int = 12; pub const SHM_HUGETLB: c_int = 0o4000; pub const SHM_NORESERVE: c_int = 0o10000; pub const LOG_NFACILITIES: c_int = 24; pub const SEM_FAILED: *mut crate::sem_t = 0 as *mut sem_t; pub const AI_PASSIVE: c_int = 0x0001; pub const AI_CANONNAME: c_int = 0x0002; pub const AI_NUMERICHOST: c_int = 0x0004; pub const AI_V4MAPPED: c_int = 0x0008; pub const AI_ALL: c_int = 0x0010; pub const AI_ADDRCONFIG: c_int = 0x0020; pub const AI_NUMERICSERV: c_int = 0x0400; pub const EAI_BADFLAGS: c_int = -1; pub const EAI_NONAME: c_int = -2; pub const EAI_AGAIN: c_int = -3; pub const EAI_FAIL: c_int = -4; pub const EAI_FAMILY: c_int = -6; pub const EAI_SOCKTYPE: c_int = -7; pub const EAI_SERVICE: c_int = -8; pub const EAI_MEMORY: c_int = -10; pub const EAI_OVERFLOW: c_int = -12; pub const NI_NUMERICHOST: c_int = 1; pub const NI_NUMERICSERV: c_int = 2; pub const NI_NOFQDN: c_int = 4; pub const NI_NAMEREQD: c_int = 8; pub const NI_DGRAM: c_int = 16; pub const SYNC_FILE_RANGE_WAIT_BEFORE: c_uint = 1; pub const SYNC_FILE_RANGE_WRITE: c_uint = 2; pub const SYNC_FILE_RANGE_WAIT_AFTER: c_uint = 4; pub const EAI_SYSTEM: c_int = -11; pub const MREMAP_MAYMOVE: c_int = 1; pub const MREMAP_FIXED: c_int = 2; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; pub const ITIMER_PROF: c_int = 2; pub const _POSIX_VDISABLE: crate::cc_t = 0; pub const FALLOC_FL_KEEP_SIZE: c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: c_int = 0x02; pub const NCCS: usize = 32; pub const O_TRUNC: c_int = 512; pub const O_NOATIME: c_int = 0o1000000; pub const O_CLOEXEC: c_int = 0x80000; // Defined as wasi value. pub const EPERM: c_int = 63; pub const ENOENT: c_int = 44; pub const ESRCH: c_int = 71; pub const EINTR: c_int = 27; pub const EIO: c_int = 29; pub const ENXIO: c_int = 60; pub const E2BIG: c_int = 1; pub const ENOEXEC: c_int = 45; pub const EBADF: c_int = 8; pub const ECHILD: c_int = 12; pub const EAGAIN: c_int = 6; pub const ENOMEM: c_int = 48; pub const EACCES: c_int = 2; pub const EFAULT: c_int = 21; pub const ENOTBLK: c_int = 105; pub const EBUSY: c_int = 10; pub const EEXIST: c_int = 20; pub const EXDEV: c_int = 75; pub const ENODEV: c_int = 43; pub const ENOTDIR: c_int = 54; pub const EISDIR: c_int = 31; pub const EINVAL: c_int = 28; pub const ENFILE: c_int = 41; pub const EMFILE: c_int = 33; pub const ENOTTY: c_int = 59; pub const ETXTBSY: c_int = 74; pub const EFBIG: c_int = 22; pub const ENOSPC: c_int = 51; pub const ESPIPE: c_int = 70; pub const EROFS: c_int = 69; pub const EMLINK: c_int = 34; pub const EPIPE: c_int = 64; pub const EDOM: c_int = 18; pub const ERANGE: c_int = 68; pub const EWOULDBLOCK: c_int = EAGAIN; pub const ENOLINK: c_int = 47; pub const EPROTO: c_int = 65; pub const EDEADLK: c_int = 16; pub const EDEADLOCK: c_int = EDEADLK; pub const ENAMETOOLONG: c_int = 37; pub const ENOLCK: c_int = 46; pub const ENOSYS: c_int = 52; pub const ENOTEMPTY: c_int = 55; pub const ELOOP: c_int = 32; pub const ENOMSG: c_int = 49; pub const EIDRM: c_int = 24; pub const EMULTIHOP: c_int = 36; pub const EBADMSG: c_int = 9; pub const EOVERFLOW: c_int = 61; pub const EILSEQ: c_int = 25; pub const ENOTSOCK: c_int = 57; pub const EDESTADDRREQ: c_int = 17; pub const EMSGSIZE: c_int = 35; pub const EPROTOTYPE: c_int = 67; pub const ENOPROTOOPT: c_int = 50; pub const EPROTONOSUPPORT: c_int = 66; pub const EAFNOSUPPORT: c_int = 5; pub const EADDRINUSE: c_int = 3; pub const EADDRNOTAVAIL: c_int = 4; pub const ENETDOWN: c_int = 38; pub const ENETUNREACH: c_int = 40; pub const ENETRESET: c_int = 39; pub const ECONNABORTED: c_int = 13; pub const ECONNRESET: c_int = 15; pub const ENOBUFS: c_int = 42; pub const EISCONN: c_int = 30; pub const ENOTCONN: c_int = 53; pub const ETIMEDOUT: c_int = 73; pub const ECONNREFUSED: c_int = 14; pub const EHOSTUNREACH: c_int = 23; pub const EALREADY: c_int = 7; pub const EINPROGRESS: c_int = 26; pub const ESTALE: c_int = 72; pub const EDQUOT: c_int = 19; pub const ECANCELED: c_int = 11; pub const EOWNERDEAD: c_int = 62; pub const ENOTRECOVERABLE: c_int = 56; pub const ENOSTR: c_int = 100; pub const EBFONT: c_int = 101; pub const EBADSLT: c_int = 102; pub const EBADRQC: c_int = 103; pub const ENOANO: c_int = 104; pub const ECHRNG: c_int = 106; pub const EL3HLT: c_int = 107; pub const EL3RST: c_int = 108; pub const ELNRNG: c_int = 109; pub const EUNATCH: c_int = 110; pub const ENOCSI: c_int = 111; pub const EL2HLT: c_int = 112; pub const EBADE: c_int = 113; pub const EBADR: c_int = 114; pub const EXFULL: c_int = 115; pub const ENODATA: c_int = 116; pub const ETIME: c_int = 117; pub const ENOSR: c_int = 118; pub const ENONET: c_int = 119; pub const ENOPKG: c_int = 120; pub const EREMOTE: c_int = 121; pub const EADV: c_int = 122; pub const ESRMNT: c_int = 123; pub const ECOMM: c_int = 124; pub const EDOTDOT: c_int = 125; pub const ENOTUNIQ: c_int = 126; pub const EBADFD: c_int = 127; pub const EREMCHG: c_int = 128; pub const ELIBACC: c_int = 129; pub const ELIBBAD: c_int = 130; pub const ELIBSCN: c_int = 131; pub const ELIBMAX: c_int = 132; pub const ELIBEXEC: c_int = 133; pub const ERESTART: c_int = 134; pub const ESTRPIPE: c_int = 135; pub const EUSERS: c_int = 136; pub const ESOCKTNOSUPPORT: c_int = 137; pub const EOPNOTSUPP: c_int = 138; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 139; pub const ESHUTDOWN: c_int = 140; pub const ETOOMANYREFS: c_int = 141; pub const EHOSTDOWN: c_int = 142; pub const EUCLEAN: c_int = 143; pub const ENOTNAM: c_int = 144; pub const ENAVAIL: c_int = 145; pub const EISNAM: c_int = 146; pub const EREMOTEIO: c_int = 147; pub const ENOMEDIUM: c_int = 148; pub const EMEDIUMTYPE: c_int = 149; pub const ENOKEY: c_int = 150; pub const EKEYEXPIRED: c_int = 151; pub const EKEYREVOKED: c_int = 152; pub const EKEYREJECTED: c_int = 153; pub const ERFKILL: c_int = 154; pub const EHWPOISON: c_int = 155; pub const EL2NSYNC: c_int = 156; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const SA_RESTART: c_int = 0x10000000; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const BUFSIZ: c_uint = 1024; pub const TMP_MAX: c_uint = 10000; pub const FOPEN_MAX: c_uint = 1000; pub const O_PATH: c_int = 0o10000000; pub const O_EXEC: c_int = 0o10000000; pub const O_SEARCH: c_int = 0o10000000; pub const O_ACCMODE: c_int = 0o10000003; pub const O_NDELAY: c_int = O_NONBLOCK; pub const NI_MAXHOST: crate::socklen_t = 255; pub const PTHREAD_STACK_MIN: size_t = 2048; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const RLIM_INFINITY: crate::rlim_t = !0; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: c_int = 16; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = RLIMIT_NLIMITS; pub const MAP_ANONYMOUS: c_int = MAP_ANON; #[doc(hidden)] #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: c_int = crate::SIGSYS; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const CPU_SETSIZE: c_int = 1024; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const TIOCINQ: c_int = crate::FIONREAD; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_NOLOAD: c_int = 0x4; pub const CLOCK_SGI_CYCLE: crate::clockid_t = 10; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const SIGSTKSZ: size_t = 8192; pub const MINSIGSTKSZ: size_t = 2048; pub const CBAUD: crate::tcflag_t = 0o0010017; pub const TAB1: c_int = 0x00000800; pub const TAB2: c_int = 0x00001000; pub const TAB3: c_int = 0x00001800; pub const CR1: c_int = 0x00000200; pub const CR2: c_int = 0x00000400; pub const CR3: c_int = 0x00000600; pub const FF1: c_int = 0x00008000; pub const BS1: c_int = 0x00002000; pub const VT1: c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x4; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOPRT: crate::tcflag_t = 0x00000400; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const CBAUDEX: crate::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: crate::tcflag_t = 0o000002; pub const NLDLY: crate::tcflag_t = 0o000400; pub const CRDLY: crate::tcflag_t = 0o003000; pub const TABDLY: crate::tcflag_t = 0o014000; pub const BSDLY: crate::tcflag_t = 0o020000; pub const FFDLY: crate::tcflag_t = 0o100000; pub const VTDLY: crate::tcflag_t = 0o040000; pub const XTABS: crate::tcflag_t = 0o014000; pub const B0: crate::speed_t = 0o000000; pub const B50: crate::speed_t = 0o000001; pub const B75: crate::speed_t = 0o000002; pub const B110: crate::speed_t = 0o000003; pub const B134: crate::speed_t = 0o000004; pub const B150: crate::speed_t = 0o000005; pub const B200: crate::speed_t = 0o000006; pub const B300: crate::speed_t = 0o000007; pub const B600: crate::speed_t = 0o000010; pub const B1200: crate::speed_t = 0o000011; pub const B1800: crate::speed_t = 0o000012; pub const B2400: crate::speed_t = 0o000013; pub const B4800: crate::speed_t = 0o000014; pub const B9600: crate::speed_t = 0o000015; pub const B19200: crate::speed_t = 0o000016; pub const B38400: crate::speed_t = 0o000017; pub const B57600: crate::speed_t = 0o010001; pub const B115200: crate::speed_t = 0o010002; pub const B230400: crate::speed_t = 0o010003; pub const B460800: crate::speed_t = 0o010004; pub const B500000: crate::speed_t = 0o010005; pub const B576000: crate::speed_t = 0o010006; pub const B921600: crate::speed_t = 0o010007; pub const B1000000: crate::speed_t = 0o010010; pub const B1152000: crate::speed_t = 0o010011; pub const B1500000: crate::speed_t = 0o010012; pub const B2000000: crate::speed_t = 0o010013; pub const B2500000: crate::speed_t = 0o010014; pub const B3000000: crate::speed_t = 0o010015; pub const B3500000: crate::speed_t = 0o010016; pub const B4000000: crate::speed_t = 0o010017; pub const SO_BINDTODEVICE: c_int = 25; pub const SO_TIMESTAMP: c_int = 63; pub const SO_MARK: c_int = 36; pub const SO_RXQ_OVFL: c_int = 40; pub const SO_PEEK_OFF: c_int = 42; pub const SO_BUSY_POLL: c_int = 46; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const O_DIRECT: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x10000; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_ASYNC: c_int = 0x2000; pub const FIOCLEX: c_int = 0x5451; pub const FIONBIO: c_int = 0x5421; pub const RLIMIT_RSS: c_int = 5; pub const RLIMIT_NOFILE: c_int = 7; pub const RLIMIT_AS: c_int = 9; pub const RLIMIT_NPROC: c_int = 6; pub const RLIMIT_MEMLOCK: c_int = 8; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_LOCKS: c_int = 10; pub const RLIMIT_SIGPENDING: c_int = 11; pub const RLIMIT_MSGQUEUE: c_int = 12; pub const RLIMIT_NICE: c_int = 13; pub const RLIMIT_RTPRIO: c_int = 14; pub const O_APPEND: c_int = 1024; pub const O_CREAT: c_int = 64; pub const O_EXCL: c_int = 128; pub const O_NOCTTY: c_int = 256; pub const O_NONBLOCK: c_int = 2048; pub const O_SYNC: c_int = 1052672; pub const O_RSYNC: c_int = 1052672; pub const O_DSYNC: c_int = 4096; pub const SOCK_NONBLOCK: c_int = 2048; pub const MAP_ANON: c_int = 0x0020; pub const MAP_GROWSDOWN: c_int = 0x0100; pub const MAP_DENYWRITE: c_int = 0x0800; pub const MAP_EXECUTABLE: c_int = 0x01000; pub const MAP_LOCKED: c_int = 0x02000; pub const MAP_NORESERVE: c_int = 0x04000; pub const MAP_POPULATE: c_int = 0x08000; pub const MAP_NONBLOCK: c_int = 0x010000; pub const MAP_STACK: c_int = 0x020000; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_SEQPACKET: c_int = 5; pub const IPPROTO_MAX: c_int = 263; pub const SOL_SOCKET: c_int = 1; pub const SO_REUSEADDR: c_int = 2; pub const SO_TYPE: c_int = 3; pub const SO_ERROR: c_int = 4; pub const SO_DONTROUTE: c_int = 5; pub const SO_BROADCAST: c_int = 6; pub const SO_SNDBUF: c_int = 7; pub const SO_RCVBUF: c_int = 8; pub const SO_KEEPALIVE: c_int = 9; pub const SO_OOBINLINE: c_int = 10; pub const SO_LINGER: c_int = 13; pub const SO_REUSEPORT: c_int = 15; pub const SO_RCVLOWAT: c_int = 18; pub const SO_SNDLOWAT: c_int = 19; pub const SO_RCVTIMEO: c_int = 66; pub const SO_SNDTIMEO: c_int = 67; pub const SO_ACCEPTCONN: c_int = 30; pub const IPV6_RTHDR_LOOSE: c_int = 0; pub const IPV6_RTHDR_STRICT: c_int = 1; pub const SA_ONSTACK: c_int = 0x08000000; pub const SA_SIGINFO: c_int = 0x00000004; pub const SA_NOCLDWAIT: c_int = 0x00000002; pub const SIGCHLD: c_int = 17; pub const SIGBUS: c_int = 7; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGUSR1: c_int = 10; pub const SIGUSR2: c_int = 12; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGURG: c_int = 23; pub const SIGIO: c_int = 29; pub const SIGSYS: c_int = 31; pub const SIGSTKFLT: c_int = 16; pub const SIGPOLL: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0x000000; pub const SIG_UNBLOCK: c_int = 0x01; pub const EXTPROC: crate::tcflag_t = 0x00010000; pub const MAP_HUGETLB: c_int = 0x040000; pub const F_GETLK: c_int = 12; pub const F_GETOWN: c_int = 9; pub const F_SETLK: c_int = 13; pub const F_SETLKW: c_int = 14; pub const F_SETOWN: c_int = 8; pub const F_OFD_GETLK: c_int = 36; pub const F_OFD_SETLK: c_int = 37; pub const F_OFD_SETLKW: c_int = 38; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const FLUSHO: crate::tcflag_t = 0x00001000; pub const TCGETS: c_int = 0x5401; pub const TCSETS: c_int = 0x5402; pub const TCSETSW: c_int = 0x5403; pub const TCSETSF: c_int = 0x5404; pub const TCGETA: c_int = 0x5405; pub const TCSETA: c_int = 0x5406; pub const TCSETAW: c_int = 0x5407; pub const TCSETAF: c_int = 0x5408; pub const TCSBRK: c_int = 0x5409; pub const TCXONC: c_int = 0x540A; pub const TCFLSH: c_int = 0x540B; pub const TIOCGSOFTCAR: c_int = 0x5419; pub const TIOCSSOFTCAR: c_int = 0x541A; pub const TIOCLINUX: c_int = 0x541C; pub const TIOCGSERIAL: c_int = 0x541E; pub const TIOCEXCL: c_int = 0x540C; pub const TIOCNXCL: c_int = 0x540D; pub const TIOCSCTTY: c_int = 0x540E; pub const TIOCGPGRP: c_int = 0x540F; pub const TIOCSPGRP: c_int = 0x5410; pub const TIOCOUTQ: c_int = 0x5411; pub const TIOCSTI: c_int = 0x5412; pub const TIOCGWINSZ: c_int = 0x5413; pub const TIOCSWINSZ: c_int = 0x5414; pub const TIOCMGET: c_int = 0x5415; pub const TIOCMBIS: c_int = 0x5416; pub const TIOCMBIC: c_int = 0x5417; pub const TIOCMSET: c_int = 0x5418; pub const FIONREAD: c_int = 0x541B; pub const TIOCCONS: c_int = 0x541D; pub const SYS_gettid: c_long = 224; // Valid for arm (32-bit) and x86 (32-bit) pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; pub const TIOCM_LE: c_int = 0x001; pub const TIOCM_DTR: c_int = 0x002; pub const TIOCM_RTS: c_int = 0x004; pub const TIOCM_ST: c_int = 0x008; pub const TIOCM_SR: c_int = 0x010; pub const TIOCM_CTS: c_int = 0x020; pub const TIOCM_CAR: c_int = 0x040; pub const TIOCM_RNG: c_int = 0x080; pub const TIOCM_DSR: c_int = 0x100; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const O_TMPFILE: c_int = 0x410000; pub const MAX_ADDR_LEN: usize = 7; pub const ARPD_UPDATE: c_ushort = 0x01; pub const ARPD_LOOKUP: c_ushort = 0x02; pub const ARPD_FLUSH: c_ushort = 0x03; pub const ATF_MAGIC: c_int = 0x80; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; pub const SOMAXCONN: c_int = 128; f! { pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as usize) < mem::size_of::() { return 0 as *mut cmsghdr; }; let next = (cmsg as usize + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if (next.offset(1)) as usize > max { 0 as *mut cmsghdr } else { next as *mut cmsghdr } } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * mem::size_of_val(&cpuset.bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } } safe_f! { pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= (major & 0xfffff000) << 31 << 1; dev |= (major & 0x00000fff) << 8; dev |= (minor & 0xffffff00) << 12; dev |= minor & 0x000000ff; dev } pub {const} fn major(dev: crate::dev_t) -> c_uint { // see // https://github.com/emscripten-core/emscripten/blob/ // main/system/lib/libc/musl/include/sys/sysmacros.h let mut major = 0; major |= (dev >> 31 >> 1) & 0xfffff000; major |= (dev >> 8) & 0x00000fff; major as c_uint } pub {const} fn minor(dev: crate::dev_t) -> c_uint { // see // https://github.com/emscripten-core/emscripten/blob/ // main/system/lib/libc/musl/include/sys/sysmacros.h let mut minor = 0; minor |= (dev >> 12) & 0xffffff00; minor |= dev & 0x000000ff; minor as c_uint } } extern "C" { pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn __errno_location() -> *mut c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int; pub fn nl_langinfo_l(item: crate::nl_item, locale: crate::locale_t) -> *mut c_char; pub fn accept4( fd: c_int, addr: *mut crate::sockaddr, len: *mut crate::socklen_t, flg: c_int, ) -> c_int; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn mremap( addr: *mut c_void, len: size_t, new_len: size_t, flags: c_int, ... ) -> *mut c_void; pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; pub fn globfree(pglob: *mut crate::glob_t); pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn sendmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_uint, ) -> c_int; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_uint, timeout: *mut crate::timespec, ) -> c_int; pub fn sync(); pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int; pub fn getpriority(which: c_int, who: crate::id_t) -> c_int; pub fn setpriority(which: c_int, who: crate::id_t, prio: c_int) -> c_int; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; // grp.h pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; } // Alias to 64 to mimic glibc's LFS64 support mod lfs64; pub use self::lfs64::*; libc/src/unix/linux_like/emscripten/lfs64.rs0000644000175000017500000001235315105742312020711 0ustar bdrungbdrunguse crate::off64_t; use crate::prelude::*; // In-sync with ../linux/musl/lfs64.rs except for fallocate64, prlimit64 and sendfile64 #[inline] pub unsafe extern "C" fn creat64(path: *const c_char, mode: crate::mode_t) -> c_int { crate::creat(path, mode) } #[inline] pub unsafe extern "C" fn fgetpos64(stream: *mut crate::FILE, pos: *mut crate::fpos64_t) -> c_int { crate::fgetpos(stream, pos as *mut _) } #[inline] pub unsafe extern "C" fn fopen64(pathname: *const c_char, mode: *const c_char) -> *mut crate::FILE { crate::fopen(pathname, mode) } #[inline] pub unsafe extern "C" fn freopen64( pathname: *const c_char, mode: *const c_char, stream: *mut crate::FILE, ) -> *mut crate::FILE { crate::freopen(pathname, mode, stream) } #[inline] pub unsafe extern "C" fn fseeko64( stream: *mut crate::FILE, offset: off64_t, whence: c_int, ) -> c_int { crate::fseeko(stream, offset, whence) } #[inline] pub unsafe extern "C" fn fsetpos64(stream: *mut crate::FILE, pos: *const crate::fpos64_t) -> c_int { crate::fsetpos(stream, pos as *mut _) } #[inline] pub unsafe extern "C" fn fstat64(fildes: c_int, buf: *mut crate::stat64) -> c_int { crate::fstat(fildes, buf as *mut _) } #[inline] pub unsafe extern "C" fn fstatat64( fd: c_int, path: *const c_char, buf: *mut crate::stat64, flag: c_int, ) -> c_int { crate::fstatat(fd, path, buf as *mut _, flag) } #[inline] pub unsafe extern "C" fn fstatfs64(fd: c_int, buf: *mut crate::statfs64) -> c_int { crate::fstatfs(fd, buf as *mut _) } #[inline] pub unsafe extern "C" fn fstatvfs64(fd: c_int, buf: *mut crate::statvfs64) -> c_int { crate::fstatvfs(fd, buf as *mut _) } #[inline] pub unsafe extern "C" fn ftello64(stream: *mut crate::FILE) -> off64_t { crate::ftello(stream) } #[inline] pub unsafe extern "C" fn ftruncate64(fd: c_int, length: off64_t) -> c_int { crate::ftruncate(fd, length) } #[inline] pub unsafe extern "C" fn getrlimit64(resource: c_int, rlim: *mut crate::rlimit64) -> c_int { crate::getrlimit(resource, rlim as *mut _) } #[inline] pub unsafe extern "C" fn lseek64(fd: c_int, offset: off64_t, whence: c_int) -> off64_t { crate::lseek(fd, offset, whence) } #[inline] pub unsafe extern "C" fn lstat64(path: *const c_char, buf: *mut crate::stat64) -> c_int { crate::lstat(path, buf as *mut _) } #[inline] pub unsafe extern "C" fn mmap64( addr: *mut c_void, length: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off64_t, ) -> *mut c_void { crate::mmap(addr, length, prot, flags, fd, offset) } // These functions are variadic in the C ABI since the `mode` argument is "optional". Variadic // `extern "C"` functions are unstable in Rust so we cannot write a shim function for these // entrypoints. See https://github.com/rust-lang/rust/issues/44930. // // These aliases are mostly fine though, neither function takes a LFS64-namespaced type as an // argument, nor do their names clash with any declared types. pub use crate::{open as open64, openat as openat64}; #[inline] pub unsafe extern "C" fn posix_fadvise64( fd: c_int, offset: off64_t, len: off64_t, advice: c_int, ) -> c_int { crate::posix_fadvise(fd, offset, len, advice) } #[inline] pub unsafe extern "C" fn posix_fallocate64(fd: c_int, offset: off64_t, len: off64_t) -> c_int { crate::posix_fallocate(fd, offset, len) } #[inline] pub unsafe extern "C" fn pread64( fd: c_int, buf: *mut c_void, count: size_t, offset: off64_t, ) -> ssize_t { crate::pread(fd, buf, count, offset) } #[inline] pub unsafe extern "C" fn preadv64( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, ) -> ssize_t { crate::preadv(fd, iov, iovcnt, offset) } #[inline] pub unsafe extern "C" fn pwrite64( fd: c_int, buf: *const c_void, count: size_t, offset: off64_t, ) -> ssize_t { crate::pwrite(fd, buf, count, offset) } #[inline] pub unsafe extern "C" fn pwritev64( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off64_t, ) -> ssize_t { crate::pwritev(fd, iov, iovcnt, offset) } #[inline] pub unsafe extern "C" fn readdir64(dirp: *mut crate::DIR) -> *mut crate::dirent64 { crate::readdir(dirp) as *mut _ } #[inline] pub unsafe extern "C" fn readdir64_r( dirp: *mut crate::DIR, entry: *mut crate::dirent64, result: *mut *mut crate::dirent64, ) -> c_int { crate::readdir_r(dirp, entry as *mut _, result as *mut _) } #[inline] pub unsafe extern "C" fn setrlimit64(resource: c_int, rlim: *const crate::rlimit64) -> c_int { crate::setrlimit(resource, rlim as *mut _) } #[inline] pub unsafe extern "C" fn stat64(pathname: *const c_char, statbuf: *mut crate::stat64) -> c_int { crate::stat(pathname, statbuf as *mut _) } #[inline] pub unsafe extern "C" fn statfs64(pathname: *const c_char, buf: *mut crate::statfs64) -> c_int { crate::statfs(pathname, buf as *mut _) } #[inline] pub unsafe extern "C" fn statvfs64(path: *const c_char, buf: *mut crate::statvfs64) -> c_int { crate::statvfs(path, buf as *mut _) } #[inline] pub unsafe extern "C" fn tmpfile64() -> *mut crate::FILE { crate::tmpfile() } #[inline] pub unsafe extern "C" fn truncate64(path: *const c_char, length: off64_t) -> c_int { crate::truncate(path, length) } libc/src/unix/redox/0000775000175000017500000000000015105742312014210 5ustar bdrungbdrunglibc/src/unix/redox/mod.rs0000644000175000017500000013636115105742312015345 0ustar bdrungbdrunguse crate::prelude::*; pub type wchar_t = i32; pub type blkcnt_t = c_ulong; pub type blksize_t = c_long; pub type clock_t = c_long; pub type clockid_t = c_int; pub type dev_t = c_long; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type ino_t = c_ulonglong; pub type mode_t = c_int; pub type nfds_t = c_ulong; pub type nlink_t = c_ulong; pub type off_t = c_longlong; pub type pthread_t = *mut c_void; // Must be usize due to library/std/sys_common/thread_local.rs, // should technically be *mut c_void pub type pthread_key_t = usize; pub type rlim_t = c_ulonglong; pub type sa_family_t = u16; pub type sem_t = *mut c_void; pub type sigset_t = c_ulonglong; pub type socklen_t = u32; pub type speed_t = u32; pub type suseconds_t = c_int; pub type tcflag_t = u32; pub type time_t = c_longlong; pub type id_t = c_uint; pub type pid_t = usize; pub type uid_t = u32; pub type gid_t = u32; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } s_no_extra_traits! { #[repr(C)] pub struct utsname { pub sysname: [c_char; UTSLENGTH], pub nodename: [c_char; UTSLENGTH], pub release: [c_char; UTSLENGTH], pub version: [c_char; UTSLENGTH], pub machine: [c_char; UTSLENGTH], pub domainname: [c_char; UTSLENGTH], } pub struct dirent { pub d_ino: crate::ino_t, pub d_off: off_t, pub d_reclen: c_ushort, pub d_type: c_uchar, pub d_name: [c_char; 256], } pub struct sockaddr_un { pub sun_family: crate::sa_family_t, pub sun_path: [c_char; 108], } pub struct sockaddr_storage { pub ss_family: crate::sa_family_t, __ss_padding: [u8; 128 - mem::size_of::() - mem::size_of::()], __ss_align: c_ulong, } } s! { pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: size_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut crate::addrinfo, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct epoll_event { pub events: u32, pub u64: u64, pub _pad: u64, } pub struct fd_set { fds_bits: [c_ulong; crate::FD_SETSIZE as usize / ULONG_SIZE], } pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: crate::in_addr, pub imr_interface: crate::in_addr, } pub struct lconv { pub currency_symbol: *const c_char, pub decimal_point: *const c_char, pub frac_digits: c_char, pub grouping: *const c_char, pub int_curr_symbol: *const c_char, pub int_frac_digits: c_char, pub mon_decimal_point: *const c_char, pub mon_grouping: *const c_char, pub mon_thousands_sep: *const c_char, pub negative_sign: *const c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub n_sign_posn: c_char, pub positive_sign: *const c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub p_sign_posn: c_char, pub thousands_sep: *const c_char, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: size_t, pub msg_control: *mut c_void, pub msg_controllen: size_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: size_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_flags: c_ulong, pub sa_restorer: Option, pub sa_mask: crate::sigset_t, } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, _pad: [c_int; 29], _align: [usize; 0], } pub struct sockaddr { pub sa_family: crate::sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in { pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } pub struct sockaddr_in6 { pub sin6_family: crate::sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, _pad: [c_char; 24], } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *const c_char, } pub struct ucred { pub pid: pid_t, pub uid: uid_t, pub gid: gid_t, } #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] #[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] pub struct pthread_attr_t { bytes: [u8; _PTHREAD_ATTR_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_barrier_t { bytes: [u8; _PTHREAD_BARRIER_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_barrierattr_t { bytes: [u8; _PTHREAD_BARRIERATTR_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_mutex_t { bytes: [u8; _PTHREAD_MUTEX_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_rwlock_t { bytes: [u8; _PTHREAD_RWLOCK_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_mutexattr_t { bytes: [u8; _PTHREAD_MUTEXATTR_SIZE], } #[repr(C)] #[repr(align(1))] pub struct pthread_rwlockattr_t { bytes: [u8; _PTHREAD_RWLOCKATTR_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_cond_t { bytes: [u8; _PTHREAD_COND_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_condattr_t { bytes: [u8; _PTHREAD_CONDATTR_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_once_t { bytes: [u8; _PTHREAD_ONCE_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_spinlock_t { bytes: [u8; _PTHREAD_SPINLOCK_SIZE], } } const _PTHREAD_ATTR_SIZE: usize = 32; const _PTHREAD_RWLOCKATTR_SIZE: usize = 1; const _PTHREAD_RWLOCK_SIZE: usize = 4; const _PTHREAD_BARRIER_SIZE: usize = 24; const _PTHREAD_BARRIERATTR_SIZE: usize = 4; const _PTHREAD_CONDATTR_SIZE: usize = 8; const _PTHREAD_COND_SIZE: usize = 8; const _PTHREAD_MUTEX_SIZE: usize = 12; const _PTHREAD_MUTEXATTR_SIZE: usize = 20; const _PTHREAD_ONCE_SIZE: usize = 4; const _PTHREAD_SPINLOCK_SIZE: usize = 4; pub const UTSLENGTH: usize = 65; // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { const ULONG_SIZE: usize = 32; } else if #[cfg(target_pointer_width = "64")] { const ULONG_SIZE: usize = 64; } else { // Unknown target_pointer_width } } // limits.h pub const PATH_MAX: c_int = 4096; // fcntl.h pub const F_GETLK: c_int = 5; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_ULOCK: c_int = 0; pub const F_LOCK: c_int = 1; pub const F_TLOCK: c_int = 2; pub const F_TEST: c_int = 3; // FIXME(redox): relibc { pub const RTLD_DEFAULT: *mut c_void = 0i64 as *mut c_void; // } // dlfcn.h pub const RTLD_LAZY: c_int = 0x0001; pub const RTLD_NOW: c_int = 0x0002; pub const RTLD_GLOBAL: c_int = 0x0100; pub const RTLD_LOCAL: c_int = 0x0000; // errno.h pub const EPERM: c_int = 1; /* Operation not permitted */ pub const ENOENT: c_int = 2; /* No such file or directory */ pub const ESRCH: c_int = 3; /* No such process */ pub const EINTR: c_int = 4; /* Interrupted system call */ pub const EIO: c_int = 5; /* I/O error */ pub const ENXIO: c_int = 6; /* No such device or address */ pub const E2BIG: c_int = 7; /* Argument list too long */ pub const ENOEXEC: c_int = 8; /* Exec format error */ pub const EBADF: c_int = 9; /* Bad file number */ pub const ECHILD: c_int = 10; /* No child processes */ pub const EAGAIN: c_int = 11; /* Try again */ pub const ENOMEM: c_int = 12; /* Out of memory */ pub const EACCES: c_int = 13; /* Permission denied */ pub const EFAULT: c_int = 14; /* Bad address */ pub const ENOTBLK: c_int = 15; /* Block device required */ pub const EBUSY: c_int = 16; /* Device or resource busy */ pub const EEXIST: c_int = 17; /* File exists */ pub const EXDEV: c_int = 18; /* Cross-device link */ pub const ENODEV: c_int = 19; /* No such device */ pub const ENOTDIR: c_int = 20; /* Not a directory */ pub const EISDIR: c_int = 21; /* Is a directory */ pub const EINVAL: c_int = 22; /* Invalid argument */ pub const ENFILE: c_int = 23; /* File table overflow */ pub const EMFILE: c_int = 24; /* Too many open files */ pub const ENOTTY: c_int = 25; /* Not a typewriter */ pub const ETXTBSY: c_int = 26; /* Text file busy */ pub const EFBIG: c_int = 27; /* File too large */ pub const ENOSPC: c_int = 28; /* No space left on device */ pub const ESPIPE: c_int = 29; /* Illegal seek */ pub const EROFS: c_int = 30; /* Read-only file system */ pub const EMLINK: c_int = 31; /* Too many links */ pub const EPIPE: c_int = 32; /* Broken pipe */ pub const EDOM: c_int = 33; /* Math argument out of domain of func */ pub const ERANGE: c_int = 34; /* Math result not representable */ pub const EDEADLK: c_int = 35; /* Resource deadlock would occur */ pub const ENAMETOOLONG: c_int = 36; /* File name too long */ pub const ENOLCK: c_int = 37; /* No record locks available */ pub const ENOSYS: c_int = 38; /* Function not implemented */ pub const ENOTEMPTY: c_int = 39; /* Directory not empty */ pub const ELOOP: c_int = 40; /* Too many symbolic links encountered */ pub const EWOULDBLOCK: c_int = 41; /* Operation would block */ pub const ENOMSG: c_int = 42; /* No message of desired type */ pub const EIDRM: c_int = 43; /* Identifier removed */ pub const ECHRNG: c_int = 44; /* Channel number out of range */ pub const EL2NSYNC: c_int = 45; /* Level 2 not synchronized */ pub const EL3HLT: c_int = 46; /* Level 3 halted */ pub const EL3RST: c_int = 47; /* Level 3 reset */ pub const ELNRNG: c_int = 48; /* Link number out of range */ pub const EUNATCH: c_int = 49; /* Protocol driver not attached */ pub const ENOCSI: c_int = 50; /* No CSI structure available */ pub const EL2HLT: c_int = 51; /* Level 2 halted */ pub const EBADE: c_int = 52; /* Invalid exchange */ pub const EBADR: c_int = 53; /* Invalid request descriptor */ pub const EXFULL: c_int = 54; /* Exchange full */ pub const ENOANO: c_int = 55; /* No anode */ pub const EBADRQC: c_int = 56; /* Invalid request code */ pub const EBADSLT: c_int = 57; /* Invalid slot */ pub const EDEADLOCK: c_int = 58; /* Resource deadlock would occur */ pub const EBFONT: c_int = 59; /* Bad font file format */ pub const ENOSTR: c_int = 60; /* Device not a stream */ pub const ENODATA: c_int = 61; /* No data available */ pub const ETIME: c_int = 62; /* Timer expired */ pub const ENOSR: c_int = 63; /* Out of streams resources */ pub const ENONET: c_int = 64; /* Machine is not on the network */ pub const ENOPKG: c_int = 65; /* Package not installed */ pub const EREMOTE: c_int = 66; /* Object is remote */ pub const ENOLINK: c_int = 67; /* Link has been severed */ pub const EADV: c_int = 68; /* Advertise error */ pub const ESRMNT: c_int = 69; /* Srmount error */ pub const ECOMM: c_int = 70; /* Communication error on send */ pub const EPROTO: c_int = 71; /* Protocol error */ pub const EMULTIHOP: c_int = 72; /* Multihop attempted */ pub const EDOTDOT: c_int = 73; /* RFS specific error */ pub const EBADMSG: c_int = 74; /* Not a data message */ pub const EOVERFLOW: c_int = 75; /* Value too large for defined data type */ pub const ENOTUNIQ: c_int = 76; /* Name not unique on network */ pub const EBADFD: c_int = 77; /* File descriptor in bad state */ pub const EREMCHG: c_int = 78; /* Remote address changed */ pub const ELIBACC: c_int = 79; /* Can not access a needed shared library */ pub const ELIBBAD: c_int = 80; /* Accessing a corrupted shared library */ pub const ELIBSCN: c_int = 81; /* .lib section in a.out corrupted */ /* Attempting to link in too many shared libraries */ pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; /* Cannot exec a shared library directly */ pub const EILSEQ: c_int = 84; /* Illegal byte sequence */ /* Interrupted system call should be restarted */ pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; /* Streams pipe error */ pub const EUSERS: c_int = 87; /* Too many users */ pub const ENOTSOCK: c_int = 88; /* Socket operation on non-socket */ pub const EDESTADDRREQ: c_int = 89; /* Destination address required */ pub const EMSGSIZE: c_int = 90; /* Message too long */ pub const EPROTOTYPE: c_int = 91; /* Protocol wrong type for socket */ pub const ENOPROTOOPT: c_int = 92; /* Protocol not available */ pub const EPROTONOSUPPORT: c_int = 93; /* Protocol not supported */ pub const ESOCKTNOSUPPORT: c_int = 94; /* Socket type not supported */ /* Operation not supported on transport endpoint */ pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; /* Protocol family not supported */ /* Address family not supported by protocol */ pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; /* Address already in use */ pub const EADDRNOTAVAIL: c_int = 99; /* Cannot assign requested address */ pub const ENETDOWN: c_int = 100; /* Network is down */ pub const ENETUNREACH: c_int = 101; /* Network is unreachable */ /* Network dropped connection because of reset */ pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; /* Software caused connection abort */ pub const ECONNRESET: c_int = 104; /* Connection reset by peer */ pub const ENOBUFS: c_int = 105; /* No buffer space available */ pub const EISCONN: c_int = 106; /* Transport endpoint is already connected */ pub const ENOTCONN: c_int = 107; /* Transport endpoint is not connected */ /* Cannot send after transport endpoint shutdown */ pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; /* Too many references: cannot splice */ pub const ETIMEDOUT: c_int = 110; /* Connection timed out */ pub const ECONNREFUSED: c_int = 111; /* Connection refused */ pub const EHOSTDOWN: c_int = 112; /* Host is down */ pub const EHOSTUNREACH: c_int = 113; /* No route to host */ pub const EALREADY: c_int = 114; /* Operation already in progress */ pub const EINPROGRESS: c_int = 115; /* Operation now in progress */ pub const ESTALE: c_int = 116; /* Stale NFS file handle */ pub const EUCLEAN: c_int = 117; /* Structure needs cleaning */ pub const ENOTNAM: c_int = 118; /* Not a XENIX named type file */ pub const ENAVAIL: c_int = 119; /* No XENIX semaphores available */ pub const EISNAM: c_int = 120; /* Is a named type file */ pub const EREMOTEIO: c_int = 121; /* Remote I/O error */ pub const EDQUOT: c_int = 122; /* Quota exceeded */ pub const ENOMEDIUM: c_int = 123; /* No medium found */ pub const EMEDIUMTYPE: c_int = 124; /* Wrong medium type */ pub const ECANCELED: c_int = 125; /* Operation Canceled */ pub const ENOKEY: c_int = 126; /* Required key not available */ pub const EKEYEXPIRED: c_int = 127; /* Key has expired */ pub const EKEYREVOKED: c_int = 128; /* Key has been revoked */ pub const EKEYREJECTED: c_int = 129; /* Key was rejected by service */ pub const EOWNERDEAD: c_int = 130; /* Owner died */ pub const ENOTRECOVERABLE: c_int = 131; /* State not recoverable */ // fcntl.h pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; // FIXME(redox): relibc { pub const F_DUPFD_CLOEXEC: c_int = crate::F_DUPFD; // } pub const FD_CLOEXEC: c_int = 0x0100_0000; pub const O_RDONLY: c_int = 0x0001_0000; pub const O_WRONLY: c_int = 0x0002_0000; pub const O_RDWR: c_int = 0x0003_0000; pub const O_ACCMODE: c_int = 0x0003_0000; pub const O_NONBLOCK: c_int = 0x0004_0000; pub const O_APPEND: c_int = 0x0008_0000; pub const O_SHLOCK: c_int = 0x0010_0000; pub const O_EXLOCK: c_int = 0x0020_0000; pub const O_ASYNC: c_int = 0x0040_0000; pub const O_FSYNC: c_int = 0x0080_0000; pub const O_CLOEXEC: c_int = 0x0100_0000; pub const O_CREAT: c_int = 0x0200_0000; pub const O_TRUNC: c_int = 0x0400_0000; pub const O_EXCL: c_int = 0x0800_0000; pub const O_DIRECTORY: c_int = 0x1000_0000; pub const O_PATH: c_int = 0x2000_0000; pub const O_SYMLINK: c_int = 0x4000_0000; // Negative to allow it to be used as int // FIXME(redox): Fix negative values missing from includes pub const O_NOFOLLOW: c_int = -0x8000_0000; // locale.h pub const LC_ALL: c_int = 0; pub const LC_COLLATE: c_int = 1; pub const LC_CTYPE: c_int = 2; pub const LC_MESSAGES: c_int = 3; pub const LC_MONETARY: c_int = 4; pub const LC_NUMERIC: c_int = 5; pub const LC_TIME: c_int = 6; // netdb.h pub const AI_PASSIVE: c_int = 0x0001; pub const AI_CANONNAME: c_int = 0x0002; pub const AI_NUMERICHOST: c_int = 0x0004; pub const AI_V4MAPPED: c_int = 0x0008; pub const AI_ALL: c_int = 0x0010; pub const AI_ADDRCONFIG: c_int = 0x0020; pub const AI_NUMERICSERV: c_int = 0x0400; pub const EAI_BADFLAGS: c_int = -1; pub const EAI_NONAME: c_int = -2; pub const EAI_AGAIN: c_int = -3; pub const EAI_FAIL: c_int = -4; pub const EAI_NODATA: c_int = -5; pub const EAI_FAMILY: c_int = -6; pub const EAI_SOCKTYPE: c_int = -7; pub const EAI_SERVICE: c_int = -8; pub const EAI_ADDRFAMILY: c_int = -9; pub const EAI_MEMORY: c_int = -10; pub const EAI_SYSTEM: c_int = -11; pub const EAI_OVERFLOW: c_int = -12; pub const NI_MAXHOST: c_int = 1025; pub const NI_MAXSERV: c_int = 32; pub const NI_NUMERICHOST: c_int = 0x0001; pub const NI_NUMERICSERV: c_int = 0x0002; pub const NI_NOFQDN: c_int = 0x0004; pub const NI_NAMEREQD: c_int = 0x0008; pub const NI_DGRAM: c_int = 0x0010; // netinet/in.h // FIXME(redox): relibc { pub const IP_TTL: c_int = 2; pub const IPV6_UNICAST_HOPS: c_int = 16; pub const IPV6_MULTICAST_IF: c_int = 17; pub const IPV6_MULTICAST_HOPS: c_int = 18; pub const IPV6_MULTICAST_LOOP: c_int = 19; pub const IPV6_ADD_MEMBERSHIP: c_int = 20; pub const IPV6_DROP_MEMBERSHIP: c_int = 21; pub const IPV6_V6ONLY: c_int = 26; pub const IP_MULTICAST_IF: c_int = 32; pub const IP_MULTICAST_TTL: c_int = 33; pub const IP_MULTICAST_LOOP: c_int = 34; pub const IP_ADD_MEMBERSHIP: c_int = 35; pub const IP_DROP_MEMBERSHIP: c_int = 36; pub const IP_TOS: c_int = 1; pub const IP_RECVTOS: c_int = 2; pub const IPPROTO_IGMP: c_int = 2; pub const IPPROTO_PUP: c_int = 12; pub const IPPROTO_IDP: c_int = 22; pub const IPPROTO_RAW: c_int = 255; pub const IPPROTO_MAX: c_int = 255; // } // netinet/tcp.h pub const TCP_NODELAY: c_int = 1; // FIXME(redox): relibc { pub const TCP_KEEPIDLE: c_int = 1; // } // poll.h pub const POLLIN: c_short = 0x001; pub const POLLPRI: c_short = 0x002; pub const POLLOUT: c_short = 0x004; pub const POLLERR: c_short = 0x008; pub const POLLHUP: c_short = 0x010; pub const POLLNVAL: c_short = 0x020; pub const POLLRDNORM: c_short = 0x040; pub const POLLRDBAND: c_short = 0x080; pub const POLLWRNORM: c_short = 0x100; pub const POLLWRBAND: c_short = 0x200; // pthread.h pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 1; pub const PTHREAD_MUTEX_INITIALIZER: crate::pthread_mutex_t = crate::pthread_mutex_t { bytes: [0; _PTHREAD_MUTEX_SIZE], }; pub const PTHREAD_COND_INITIALIZER: crate::pthread_cond_t = crate::pthread_cond_t { bytes: [0; _PTHREAD_COND_SIZE], }; pub const PTHREAD_RWLOCK_INITIALIZER: crate::pthread_rwlock_t = crate::pthread_rwlock_t { bytes: [0; _PTHREAD_RWLOCK_SIZE], }; pub const PTHREAD_STACK_MIN: size_t = 4096; // signal.h pub const SIG_BLOCK: c_int = 0; pub const SIG_UNBLOCK: c_int = 1; pub const SIG_SETMASK: c_int = 2; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGBUS: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGUSR1: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGUSR2: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGSTKFLT: c_int = 16; pub const SIGCHLD: c_int = 17; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGURG: c_int = 23; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGIO: c_int = 29; pub const SIGPWR: c_int = 30; pub const SIGSYS: c_int = 31; pub const NSIG: c_int = 32; pub const SA_NOCLDSTOP: c_ulong = 0x00000001; pub const SA_NOCLDWAIT: c_ulong = 0x00000002; pub const SA_SIGINFO: c_ulong = 0x00000004; pub const SA_RESTORER: c_ulong = 0x04000000; pub const SA_ONSTACK: c_ulong = 0x08000000; pub const SA_RESTART: c_ulong = 0x10000000; pub const SA_NODEFER: c_ulong = 0x40000000; pub const SA_RESETHAND: c_ulong = 0x80000000; // sys/file.h pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; // sys/epoll.h pub const EPOLL_CLOEXEC: c_int = 0x0100_0000; pub const EPOLL_CTL_ADD: c_int = 1; pub const EPOLL_CTL_DEL: c_int = 2; pub const EPOLL_CTL_MOD: c_int = 3; pub const EPOLLIN: c_int = 0x001; pub const EPOLLPRI: c_int = 0x002; pub const EPOLLOUT: c_int = 0x004; pub const EPOLLERR: c_int = 0x008; pub const EPOLLHUP: c_int = 0x010; pub const EPOLLNVAL: c_int = 0x020; pub const EPOLLRDNORM: c_int = 0x040; pub const EPOLLRDBAND: c_int = 0x080; pub const EPOLLWRNORM: c_int = 0x100; pub const EPOLLWRBAND: c_int = 0x200; pub const EPOLLMSG: c_int = 0x400; pub const EPOLLRDHUP: c_int = 0x2000; pub const EPOLLEXCLUSIVE: c_int = 1 << 28; pub const EPOLLWAKEUP: c_int = 1 << 29; pub const EPOLLONESHOT: c_int = 1 << 30; pub const EPOLLET: c_int = 1 << 31; // sys/stat.h pub const S_IFMT: c_int = 0o17_0000; pub const S_IFDIR: c_int = 0o4_0000; pub const S_IFCHR: c_int = 0o2_0000; pub const S_IFBLK: c_int = 0o6_0000; pub const S_IFREG: c_int = 0o10_0000; pub const S_IFIFO: c_int = 0o1_0000; pub const S_IFLNK: c_int = 0o12_0000; pub const S_IFSOCK: c_int = 0o14_0000; pub const S_IRWXU: c_int = 0o0700; pub const S_IRUSR: c_int = 0o0400; pub const S_IWUSR: c_int = 0o0200; pub const S_IXUSR: c_int = 0o0100; pub const S_IRWXG: c_int = 0o0070; pub const S_IRGRP: c_int = 0o0040; pub const S_IWGRP: c_int = 0o0020; pub const S_IXGRP: c_int = 0o0010; pub const S_IRWXO: c_int = 0o0007; pub const S_IROTH: c_int = 0o0004; pub const S_IWOTH: c_int = 0o0002; pub const S_IXOTH: c_int = 0o0001; // stdlib.h pub const EXIT_SUCCESS: c_int = 0; pub const EXIT_FAILURE: c_int = 1; // sys/ioctl.h // FIXME(redox): relibc { pub const FIONREAD: c_ulong = 0x541B; pub const FIONBIO: c_ulong = 0x5421; pub const FIOCLEX: c_ulong = 0x5451; // } pub const TCGETS: c_ulong = 0x5401; pub const TCSETS: c_ulong = 0x5402; pub const TCFLSH: c_ulong = 0x540B; pub const TIOCSCTTY: c_ulong = 0x540E; pub const TIOCGPGRP: c_ulong = 0x540F; pub const TIOCSPGRP: c_ulong = 0x5410; pub const TIOCGWINSZ: c_ulong = 0x5413; pub const TIOCSWINSZ: c_ulong = 0x5414; // sys/mman.h pub const PROT_NONE: c_int = 0x0000; pub const PROT_READ: c_int = 0x0004; pub const PROT_WRITE: c_int = 0x0002; pub const PROT_EXEC: c_int = 0x0001; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const MAP_SHARED: c_int = 0x0001; pub const MAP_PRIVATE: c_int = 0x0002; pub const MAP_ANON: c_int = 0x0020; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const MAP_FIXED: c_int = 0x0010; pub const MAP_FAILED: *mut c_void = !0 as _; pub const MS_ASYNC: c_int = 0x0001; pub const MS_INVALIDATE: c_int = 0x0002; pub const MS_SYNC: c_int = 0x0004; // sys/select.h pub const FD_SETSIZE: usize = 1024; // sys/socket.h pub const AF_INET: c_int = 2; pub const AF_INET6: c_int = 10; pub const AF_UNIX: c_int = 1; pub const AF_UNSPEC: c_int = 0; pub const PF_INET: c_int = 2; pub const PF_INET6: c_int = 10; pub const PF_UNIX: c_int = 1; pub const PF_UNSPEC: c_int = 0; pub const MSG_CTRUNC: c_int = 8; pub const MSG_DONTROUTE: c_int = 4; pub const MSG_EOR: c_int = 128; pub const MSG_OOB: c_int = 1; pub const MSG_PEEK: c_int = 2; pub const MSG_TRUNC: c_int = 32; pub const MSG_DONTWAIT: c_int = 64; pub const MSG_WAITALL: c_int = 256; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const SO_DEBUG: c_int = 1; pub const SO_REUSEADDR: c_int = 2; pub const SO_TYPE: c_int = 3; pub const SO_ERROR: c_int = 4; pub const SO_DONTROUTE: c_int = 5; pub const SO_BROADCAST: c_int = 6; pub const SO_SNDBUF: c_int = 7; pub const SO_RCVBUF: c_int = 8; pub const SO_KEEPALIVE: c_int = 9; pub const SO_OOBINLINE: c_int = 10; pub const SO_NO_CHECK: c_int = 11; pub const SO_PRIORITY: c_int = 12; pub const SO_LINGER: c_int = 13; pub const SO_BSDCOMPAT: c_int = 14; pub const SO_REUSEPORT: c_int = 15; pub const SO_PASSCRED: c_int = 16; pub const SO_PEERCRED: c_int = 17; pub const SO_RCVLOWAT: c_int = 18; pub const SO_SNDLOWAT: c_int = 19; pub const SO_RCVTIMEO: c_int = 20; pub const SO_SNDTIMEO: c_int = 21; pub const SO_ACCEPTCONN: c_int = 30; pub const SO_PEERSEC: c_int = 31; pub const SO_SNDBUFFORCE: c_int = 32; pub const SO_RCVBUFFORCE: c_int = 33; pub const SO_PROTOCOL: c_int = 38; pub const SO_DOMAIN: c_int = 39; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_NONBLOCK: c_int = 0o4_000; pub const SOCK_CLOEXEC: c_int = 0o2_000_000; pub const SOCK_SEQPACKET: c_int = 5; pub const SOL_SOCKET: c_int = 1; pub const SOMAXCONN: c_int = 128; // sys/termios.h pub const VEOF: usize = 0; pub const VEOL: usize = 1; pub const VEOL2: usize = 2; pub const VERASE: usize = 3; pub const VWERASE: usize = 4; pub const VKILL: usize = 5; pub const VREPRINT: usize = 6; pub const VSWTC: usize = 7; pub const VINTR: usize = 8; pub const VQUIT: usize = 9; pub const VSUSP: usize = 10; pub const VSTART: usize = 12; pub const VSTOP: usize = 13; pub const VLNEXT: usize = 14; pub const VDISCARD: usize = 15; pub const VMIN: usize = 16; pub const VTIME: usize = 17; pub const NCCS: usize = 32; pub const IGNBRK: crate::tcflag_t = 0o000_001; pub const BRKINT: crate::tcflag_t = 0o000_002; pub const IGNPAR: crate::tcflag_t = 0o000_004; pub const PARMRK: crate::tcflag_t = 0o000_010; pub const INPCK: crate::tcflag_t = 0o000_020; pub const ISTRIP: crate::tcflag_t = 0o000_040; pub const INLCR: crate::tcflag_t = 0o000_100; pub const IGNCR: crate::tcflag_t = 0o000_200; pub const ICRNL: crate::tcflag_t = 0o000_400; pub const IXON: crate::tcflag_t = 0o001_000; pub const IXOFF: crate::tcflag_t = 0o002_000; pub const OPOST: crate::tcflag_t = 0o000_001; pub const ONLCR: crate::tcflag_t = 0o000_002; pub const OLCUC: crate::tcflag_t = 0o000_004; pub const OCRNL: crate::tcflag_t = 0o000_010; pub const ONOCR: crate::tcflag_t = 0o000_020; pub const ONLRET: crate::tcflag_t = 0o000_040; pub const OFILL: crate::tcflag_t = 0o0000_100; pub const OFDEL: crate::tcflag_t = 0o0000_200; pub const B0: speed_t = 0o000_000; pub const B50: speed_t = 0o000_001; pub const B75: speed_t = 0o000_002; pub const B110: speed_t = 0o000_003; pub const B134: speed_t = 0o000_004; pub const B150: speed_t = 0o000_005; pub const B200: speed_t = 0o000_006; pub const B300: speed_t = 0o000_007; pub const B600: speed_t = 0o000_010; pub const B1200: speed_t = 0o000_011; pub const B1800: speed_t = 0o000_012; pub const B2400: speed_t = 0o000_013; pub const B4800: speed_t = 0o000_014; pub const B9600: speed_t = 0o000_015; pub const B19200: speed_t = 0o000_016; pub const B38400: speed_t = 0o000_017; pub const B57600: speed_t = 0o0_020; pub const B115200: speed_t = 0o0_021; pub const B230400: speed_t = 0o0_022; pub const B460800: speed_t = 0o0_023; pub const B500000: speed_t = 0o0_024; pub const B576000: speed_t = 0o0_025; pub const B921600: speed_t = 0o0_026; pub const B1000000: speed_t = 0o0_027; pub const B1152000: speed_t = 0o0_030; pub const B1500000: speed_t = 0o0_031; pub const B2000000: speed_t = 0o0_032; pub const B2500000: speed_t = 0o0_033; pub const B3000000: speed_t = 0o0_034; pub const B3500000: speed_t = 0o0_035; pub const B4000000: speed_t = 0o0_036; pub const CSIZE: crate::tcflag_t = 0o001_400; pub const CS5: crate::tcflag_t = 0o000_000; pub const CS6: crate::tcflag_t = 0o000_400; pub const CS7: crate::tcflag_t = 0o001_000; pub const CS8: crate::tcflag_t = 0o001_400; pub const CSTOPB: crate::tcflag_t = 0o002_000; pub const CREAD: crate::tcflag_t = 0o004_000; pub const PARENB: crate::tcflag_t = 0o010_000; pub const PARODD: crate::tcflag_t = 0o020_000; pub const HUPCL: crate::tcflag_t = 0o040_000; pub const CLOCAL: crate::tcflag_t = 0o0100000; pub const ISIG: crate::tcflag_t = 0x0000_0080; pub const ICANON: crate::tcflag_t = 0x0000_0100; pub const ECHO: crate::tcflag_t = 0x0000_0008; pub const ECHOE: crate::tcflag_t = 0x0000_0002; pub const ECHOK: crate::tcflag_t = 0x0000_0004; pub const ECHONL: crate::tcflag_t = 0x0000_0010; pub const NOFLSH: crate::tcflag_t = 0x8000_0000; pub const TOSTOP: crate::tcflag_t = 0x0040_0000; pub const IEXTEN: crate::tcflag_t = 0x0000_0400; pub const TCOOFF: c_int = 0; pub const TCOON: c_int = 1; pub const TCIOFF: c_int = 2; pub const TCION: c_int = 3; pub const TCIFLUSH: c_int = 0; pub const TCOFLUSH: c_int = 1; pub const TCIOFLUSH: c_int = 2; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; // sys/wait.h pub const WNOHANG: c_int = 1; pub const WUNTRACED: c_int = 2; pub const WSTOPPED: c_int = 2; pub const WEXITED: c_int = 4; pub const WCONTINUED: c_int = 8; pub const WNOWAIT: c_int = 0x0100_0000; pub const __WNOTHREAD: c_int = 0x2000_0000; pub const __WALL: c_int = 0x4000_0000; #[allow(overflowing_literals)] pub const __WCLONE: c_int = 0x8000_0000; // time.h pub const CLOCK_REALTIME: c_int = 1; pub const CLOCK_MONOTONIC: c_int = 4; pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 2; pub const CLOCKS_PER_SEC: crate::clock_t = 1_000_000; // unistd.h // POSIX.1 { pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_STREAM_MAX: c_int = 5; pub const _SC_TZNAME_MAX: c_int = 6; // ... pub const _SC_VERSION: c_int = 29; pub const _SC_PAGESIZE: c_int = 30; pub const _SC_PAGE_SIZE: c_int = 30; // ... pub const _SC_RE_DUP_MAX: c_int = 44; // ... pub const _SC_LOGIN_NAME_MAX: c_int = 71; pub const _SC_TTY_NAME_MAX: c_int = 72; // ... pub const _SC_SYMLOOP_MAX: c_int = 173; // ... pub const _SC_HOST_NAME_MAX: c_int = 180; // } POSIX.1 pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const _PC_LINK_MAX: c_int = 0; pub const _PC_MAX_CANON: c_int = 1; pub const _PC_MAX_INPUT: c_int = 2; pub const _PC_NAME_MAX: c_int = 3; pub const _PC_PATH_MAX: c_int = 4; pub const _PC_PIPE_BUF: c_int = 5; pub const _PC_CHOWN_RESTRICTED: c_int = 6; pub const _PC_NO_TRUNC: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_SYNC_IO: c_int = 9; pub const _PC_ASYNC_IO: c_int = 10; pub const _PC_PRIO_IO: c_int = 11; pub const _PC_SOCK_MAXBUF: c_int = 12; pub const _PC_FILESIZEBITS: c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: c_int = 16; pub const _PC_REC_XFER_ALIGN: c_int = 17; pub const _PC_ALLOC_SIZE_MIN: c_int = 18; pub const _PC_SYMLINK_MAX: c_int = 19; pub const _PC_2_SYMLINKS: c_int = 20; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; // wait.h f! { pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0x7f } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: c_int) -> bool { (status & 0x80) != 0 } } extern "C" { // errno.h pub fn __errno_location() -> *mut c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; // unistd.h pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; pub fn getdtablesize() -> c_int; // grp.h pub fn getgrent() -> *mut crate::group; pub fn setgrent(); pub fn endgrent(); pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrouplist( user: *const c_char, group: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; // malloc.h pub fn memalign(align: size_t, size: size_t) -> *mut c_void; // netdb.h pub fn getnameinfo( addr: *const crate::sockaddr, addrlen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; // pthread.h pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn pthread_create( tid: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, start: extern "C" fn(*mut c_void) -> *mut c_void, arg: *mut c_void, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; //pty.h pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *const termios, winp: *const crate::winsize, ) -> c_int; // pwd.h pub fn getpwent() -> *mut passwd; pub fn setpwent(); pub fn endpwent(); pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; // signal.h pub fn pthread_sigmask( how: c_int, set: *const crate::sigset_t, oldset: *mut crate::sigset_t, ) -> c_int; pub fn pthread_cancel(thread: crate::pthread_t) -> c_int; pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sigtimedwait( set: *const sigset_t, sig: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; // stdlib.h pub fn getsubopt( optionp: *mut *mut c_char, tokens: *const *mut c_char, valuep: *mut *mut c_char, ) -> c_int; pub fn reallocarray(ptr: *mut c_void, nmemb: size_t, size: size_t) -> *mut c_void; // string.h pub fn explicit_bzero(p: *mut c_void, len: size_t); pub fn strlcat(dst: *mut c_char, src: *const c_char, siz: size_t) -> size_t; pub fn strlcpy(dst: *mut c_char, src: *const c_char, siz: size_t) -> size_t; // sys/epoll.h pub fn epoll_create(size: c_int) -> c_int; pub fn epoll_create1(flags: c_int) -> c_int; pub fn epoll_wait( epfd: c_int, events: *mut crate::epoll_event, maxevents: c_int, timeout: c_int, ) -> c_int; pub fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut crate::epoll_event) -> c_int; // sys/ioctl.h pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int; // sys/mman.h pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; // sys/resource.h pub fn getpriority(which: c_int, who: crate::id_t) -> c_int; pub fn setpriority(which: c_int, who: crate::id_t, prio: c_int) -> c_int; pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; // sys/socket.h pub fn CMSG_ALIGN(len: size_t) -> size_t; pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar; pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr; pub fn CMSG_LEN(len: c_uint) -> c_uint; pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr; pub fn CMSG_SPACE(len: c_uint) -> c_uint; pub fn bind( socket: c_int, address: *const crate::sockaddr, address_len: crate::socklen_t, ) -> c_int; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn recvmsg(socket: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t; pub fn sendmsg(socket: c_int, msg: *const msghdr, flags: c_int) -> ssize_t; pub fn sendto( socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const crate::sockaddr, addrlen: crate::socklen_t, ) -> ssize_t; // sys/stat.h pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; // sys/uio.h pub fn preadv( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t, ) -> ssize_t; pub fn pwritev( fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t, ) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; // sys/utsname.h pub fn uname(utsname: *mut utsname) -> c_int; // time.h pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut crate::timezone) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; // utmp.h pub fn login_tty(fd: c_int) -> c_int; } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME(debug): .field("sun_path", &self.sun_path) .finish() } } impl hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_family == other.ss_family && self.__ss_align == self.__ss_align && self .__ss_padding .iter() .zip(other.__ss_padding.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_family", &self.ss_family) .field("__ss_align", &self.__ss_align) // FIXME(debug): .field("__ss_padding", &self.__ss_padding) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_family.hash(state); self.__ss_padding.hash(state); self.__ss_align.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) && self .domainname .iter() .zip(other.domainname.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl fmt::Debug for utsname { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utsname") // FIXME(debug): .field("sysname", &self.sysname) // FIXME(debug): .field("nodename", &self.nodename) // FIXME(debug): .field("release", &self.release) // FIXME(debug): .field("version", &self.version) // FIXME(debug): .field("machine", &self.machine) // FIXME(debug): .field("domainname", &self.domainname) .finish() } } impl hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); self.domainname.hash(state); } } } } libc/src/unix/cygwin/0000775000175000017500000000000015105742312014367 5ustar bdrungbdrunglibc/src/unix/cygwin/mod.rs0000644000175000017500000024271515105742312015525 0ustar bdrungbdrunguse crate::prelude::*; use crate::*; pub type wchar_t = c_ushort; pub type blkcnt_t = i64; pub type blksize_t = i32; pub type dev_t = u32; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type ino_t = u64; pub type key_t = c_longlong; pub type sa_family_t = u16; pub type socklen_t = c_int; pub type off_t = c_long; pub type id_t = u32; pub type mode_t = u32; pub type _off64_t = c_longlong; pub type loff_t = _off64_t; pub type iconv_t = *mut c_void; pub type clock_t = c_ulong; pub type time_t = c_long; pub type clockid_t = c_ulong; pub type timer_t = c_ulong; pub type nl_item = c_int; pub type nlink_t = c_ushort; pub type suseconds_t = c_long; pub type useconds_t = c_ulong; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } pub type sigset_t = c_ulong; pub type fd_mask = c_ulong; pub type pthread_t = *mut c_void; pub type pthread_mutex_t = *mut c_void; // Must be usize due to libstd/sys_common/thread_local.rs, // should technically be *mut c_void pub type pthread_key_t = usize; pub type pthread_attr_t = *mut c_void; pub type pthread_mutexattr_t = *mut c_void; pub type pthread_condattr_t = *mut c_void; pub type pthread_cond_t = *mut c_void; // The following ones should be *mut c_void pub type pthread_barrierattr_t = usize; pub type pthread_barrier_t = usize; pub type pthread_spinlock_t = usize; pub type pthread_rwlock_t = *mut c_void; pub type pthread_rwlockattr_t = *mut c_void; pub type register_t = intptr_t; pub type u_char = c_uchar; pub type u_short = c_ushort; pub type u_long = c_ulong; pub type u_int = c_uint; pub type caddr_t = *mut c_char; pub type vm_size_t = c_ulong; pub type rlim_t = c_ulong; pub type nfds_t = c_uint; pub type sem_t = *mut sem; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum sem {} impl Copy for sem {} impl Clone for sem { fn clone(&self) -> sem { *self } } pub type tcflag_t = c_uint; pub type speed_t = c_uint; pub type vm_offset_t = c_ulong; pub type posix_spawn_file_actions_t = *mut c_void; pub type posix_spawnattr_t = *mut c_void; s! { pub struct itimerspec { pub it_interval: timespec, pub it_value: timespec, } pub struct cpu_set_t { bits: [u64; 16], } pub struct sigaction { pub sa_sigaction: sighandler_t, pub sa_mask: sigset_t, pub sa_flags: c_int, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: size_t, } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *const c_char, } pub struct bintime { pub sec: time_t, pub frac: u64, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: uid_t, pub pw_gid: gid_t, pub pw_comment: *mut c_char, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } pub struct ucred { pub pid: pid_t, pub uid: uid_t, pub gid: gid_t, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: size_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct Dl_info { pub dli_fname: [c_char; PATH_MAX as usize], pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct in6_pktinfo { pub ipi6_addr: in6_addr, pub ipi6_ifindex: u32, } pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_p_sign_posn: c_char, } pub struct termios { pub c_iflag: tcflag_t, pub c_oflag: tcflag_t, pub c_cflag: tcflag_t, pub c_lflag: tcflag_t, pub c_line: c_char, pub c_cc: [cc_t; NCCS], pub c_ispeed: speed_t, pub c_ospeed: speed_t, } pub struct sched_param { pub sched_priority: c_int, } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: pid_t, } pub struct hostent { pub h_name: *const c_char, pub h_aliases: *mut *mut c_char, pub h_addrtype: c_short, pub h_length: c_short, pub h_addr_list: *mut *mut c_char, } pub struct linger { pub l_onoff: c_ushort, pub l_linger: c_ushort, } pub struct fd_set { fds_bits: [fd_mask; FD_SETSIZE / core::mem::size_of::() / 8], } pub struct _uc_fpxreg { pub significand: [u16; 4], pub exponent: u16, pub padding: [u16; 3], } pub struct _uc_xmmreg { pub element: [u32; 4], } pub struct _fpstate { pub cwd: u16, pub swd: u16, pub ftw: u16, pub fop: u16, pub rip: u64, pub rdp: u64, pub mxcsr: u32, pub mxcr_mask: u32, pub st: [_uc_fpxreg; 8], pub xmm: [_uc_xmmreg; 16], pub padding: [u32; 24], } #[repr(align(16))] pub struct mcontext_t { pub p1home: u64, pub p2home: u64, pub p3home: u64, pub p4home: u64, pub p5home: u64, pub p6home: u64, pub ctxflags: u32, pub mxcsr: u32, pub cs: u16, pub ds: u16, pub es: u16, pub fs: u16, pub gs: u16, pub ss: u16, pub eflags: u32, pub dr0: u64, pub dr1: u64, pub dr2: u64, pub dr3: u64, pub dr6: u64, pub dr7: u64, pub rax: u64, pub rcx: u64, pub rdx: u64, pub rbx: u64, pub rsp: u64, pub rbp: u64, pub rsi: u64, pub rdi: u64, pub r8: u64, pub r9: u64, pub r10: u64, pub r11: u64, pub r12: u64, pub r13: u64, pub r14: u64, pub r15: u64, pub rip: u64, pub fpregs: _fpstate, pub vregs: [u64; 52], pub vcx: u64, pub dbc: u64, pub btr: u64, pub bfr: u64, pub etr: u64, pub efr: u64, pub oldmask: u64, pub cr2: u64, } pub struct sigevent { pub sigev_value: sigval, pub sigev_signo: c_int, pub sigev_notify: c_int, pub sigev_notify_function: Option, pub sigev_notify_attributes: *mut pthread_attr_t, } #[repr(align(8))] pub struct ucontext_t { pub uc_mcontext: mcontext_t, pub uc_link: *mut ucontext_t, pub uc_sigmask: sigset_t, pub uc_stack: stack_t, pub uc_flags: c_ulong, } pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_storage { pub ss_family: sa_family_t, __ss_pad1: [c_char; 6], __ss_align: i64, __ss_pad2: [c_char; 112], } pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, pub st_nlink: nlink_t, pub st_uid: uid_t, pub st_gid: gid_t, pub st_rdev: dev_t, pub st_size: off_t, pub st_atime: time_t, pub st_atime_nsec: c_long, pub st_mtime: time_t, pub st_mtime_nsec: c_long, pub st_ctime: time_t, pub st_ctime_nsec: c_long, pub st_blksize: blksize_t, pub st_blocks: blkcnt_t, pub st_birthtime: time_t, pub st_birthtime_nsec: c_long, } pub struct in_addr { pub s_addr: in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct in_pktinfo { pub ipi_addr: in_addr, pub ipi_ifindex: u32, } pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [u8; 8], } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: fsblkcnt_t, pub f_bfree: fsblkcnt_t, pub f_bavail: fsblkcnt_t, pub f_files: fsfilcnt_t, pub f_ffree: fsfilcnt_t, pub f_favail: fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, } pub struct statfs { pub f_type: c_long, pub f_bsize: c_long, pub f_blocks: c_long, pub f_bfree: c_long, pub f_bavail: c_long, pub f_files: c_long, pub f_ffree: c_long, pub f_fsid: c_long, pub f_namelen: c_long, pub f_spare: [c_long; 6], } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_pid: pid_t, pub si_uid: uid_t, pub si_errno: c_int, __pad: [u32; 32], } pub union __c_anonymous_ifr_ifru { pub ifru_addr: sockaddr, pub ifru_broadaddr: sockaddr, pub ifru_dstaddr: sockaddr, pub ifru_netmask: sockaddr, pub ifru_hwaddr: sockaddr, pub ifru_flags: c_int, pub ifru_metric: c_int, pub ifru_mtu: c_int, pub ifru_ifindex: c_int, pub ifru_data: *mut c_char, __ifru_pad: [c_char; 28], } pub struct ifreq { /// if name, e.g. "en0" pub ifr_name: [c_char; IFNAMSIZ], pub ifr_ifru: __c_anonymous_ifr_ifru, } pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: caddr_t, pub ifcu_req: *mut ifreq, } pub struct ifconf { pub ifc_len: c_int, pub ifc_ifcu: __c_anonymous_ifc_ifcu, } pub struct dirent { __d_version: u32, pub d_ino: ino_t, pub d_type: c_uchar, __d_unused1: [c_uchar; 3], __d_internal1: u32, pub d_name: [c_char; 256], } pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char; 108], } pub struct utsname { pub sysname: [c_char; 66], pub nodename: [c_char; 65], pub release: [c_char; 65], pub version: [c_char; 65], pub machine: [c_char; 65], pub domainname: [c_char; 65], } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { #[repr(C)] struct siginfo_si_addr { _si_signo: c_int, _si_code: c_int, _si_pid: pid_t, _si_uid: uid_t, _si_errno: c_int, si_addr: *mut c_void, } (*(self as *const siginfo_t as *const siginfo_si_addr)).si_addr } pub unsafe fn si_status(&self) -> c_int { #[repr(C)] struct siginfo_sigchld { _si_signo: c_int, _si_code: c_int, _si_pid: pid_t, _si_uid: uid_t, _si_errno: c_int, si_status: c_int, } (*(self as *const siginfo_t as *const siginfo_sigchld)).si_status } pub unsafe fn si_pid(&self) -> pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> uid_t { self.si_uid } pub unsafe fn si_value(&self) -> sigval { #[repr(C)] struct siginfo_si_value { _si_signo: c_int, _si_code: c_int, _si_pid: pid_t, _si_uid: uid_t, _si_errno: c_int, si_value: sigval, } (*(self as *const siginfo_t as *const siginfo_si_value)).si_value } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { self.si_signo == other.si_signo && self.si_code == other.si_code && self.si_pid == other.si_pid && self.si_uid == other.si_uid && self.si_errno == other.si_errno } } impl Eq for siginfo_t {} impl fmt::Debug for siginfo_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("siginfo_t") .field("si_signo", &self.si_signo) .field("si_code", &self.si_code) .field("si_pid", &self.si_pid) .field("si_uid", &self.si_uid) .field("si_errno", &self.si_errno) // Ignore __pad .finish() } } impl hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_code.hash(state); self.si_pid.hash(state); self.si_uid.hash(state); self.si_errno.hash(state); // Ignore __pad } } impl fmt::Debug for ifreq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } impl fmt::Debug for ifconf { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifconf") .field("ifc_len", &self.ifc_len) .field("ifc_ifcu", &self.ifc_ifcu) .finish() } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME: .field("sun_path", &self.sun_path) .finish() } } impl hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) && self .domainname .iter() .zip(other.domainname.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl fmt::Debug for utsname { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utsname") // FIXME: .field("sysname", &self.sysname) // FIXME: .field("nodename", &self.nodename) // FIXME: .field("release", &self.release) // FIXME: .field("version", &self.version) // FIXME: .field("machine", &self.machine) // FIXME: .field("domainname", &self.domainname) .finish() } } impl hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); self.domainname.hash(state); } } } } pub const FD_SETSIZE: usize = 1024; pub const CPU_SETSIZE: c_int = 0x400; // si_code values for SIGBUS signal pub const BUS_ADRALN: c_int = 25; pub const BUS_ADRERR: c_int = 26; pub const BUS_OBJERR: c_int = 27; // si_code values for SIGCHLD signal pub const CLD_EXITED: c_int = 28; pub const CLD_KILLED: c_int = 29; pub const CLD_DUMPED: c_int = 30; pub const CLD_TRAPPED: c_int = 31; pub const CLD_STOPPED: c_int = 32; pub const CLD_CONTINUED: c_int = 33; pub const SIGEV_SIGNAL: c_int = 0; pub const SIGEV_NONE: c_int = 1; pub const SIGEV_THREAD: c_int = 2; pub const SA_NOCLDSTOP: c_int = 0x00000001; pub const SA_NOCLDWAIT: c_int = 0; // FIXME: does not exist on Cygwin! pub const SA_SIGINFO: c_int = 0x00000002; pub const SA_RESTART: c_int = 0x10000000; pub const SA_ONSTACK: c_int = 0x20000000; pub const SA_NODEFER: c_int = 0x40000000; pub const SA_RESETHAND: c_int = 0x80000000; pub const MINSIGSTKSZ: size_t = 8192; pub const SIGSTKSZ: size_t = 32768; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGBUS: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGSYS: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGURG: c_int = 16; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGCONT: c_int = 19; pub const SIGCHLD: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGIO: c_int = 23; pub const SIGPOLL: c_int = 23; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGPWR: c_int = 29; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SS_ONSTACK: c_int = 0x1; pub const SS_DISABLE: c_int = 0x2; pub const SIG_SETMASK: c_int = 0; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const TIMER_ABSTIME: c_int = 4; pub const CLOCK_REALTIME_COARSE: clockid_t = 0; pub const CLOCK_REALTIME: clockid_t = 1; pub const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: clockid_t = 3; pub const CLOCK_MONOTONIC: clockid_t = 4; pub const CLOCK_MONOTONIC_RAW: clockid_t = 5; pub const CLOCK_MONOTONIC_COARSE: clockid_t = 6; pub const CLOCK_BOOTTIME: clockid_t = 7; pub const CLOCK_REALTIME_ALARM: clockid_t = 8; pub const CLOCK_BOOTTIME_ALARM: clockid_t = 9; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; pub const ITIMER_PROF: c_int = 2; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_NOFILE: c_int = 5; pub const RLIMIT_AS: c_int = 6; pub const RLIM_NLIMITS: c_int = 7; pub const RLIMIT_NLIMITS: c_int = RLIM_NLIMITS; pub const RLIM_INFINITY: rlim_t = !0; pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; pub const RUSAGE_SELF: c_int = 0; pub const RUSAGE_CHILDREN: c_int = -1; pub const IFF_UP: c_int = 0x1; // interface is up pub const IFF_BROADCAST: c_int = 0x2; // broadcast address valid pub const IFF_LOOPBACK: c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: c_int = 0x10; // interface is point-to-point link pub const IFF_NOTRAILERS: c_int = 0x20; // avoid use of trailers pub const IFF_RUNNING: c_int = 0x40; // resources allocated pub const IFF_NOARP: c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: c_int = 0x100; // receive all packets pub const IFF_MULTICAST: c_int = 0x1000; // supports multicast pub const IFF_LOWER_UP: c_int = 0x10000; // driver signals L1 up pub const IFF_DORMANT: c_int = 0x20000; // driver signals dormant pub const IF_NAMESIZE: size_t = 44; pub const IFNAMSIZ: size_t = IF_NAMESIZE; pub const FIONREAD: c_int = 0x4008667f; pub const FIONBIO: c_int = 0x8004667e; pub const FIOASYNC: c_int = 0x8008667d; pub const FIOCLEX: c_int = 0; // FIXME: does not exist on Cygwin! pub const SIOCGIFCONF: c_ulong = 0x80107364; pub const SIOCGIFFLAGS: c_ulong = 0x80507365; pub const SIOCGIFADDR: c_ulong = 0x80507366; pub const SIOCGIFBRDADDR: c_ulong = 0x80507367; pub const SIOCGIFNETMASK: c_ulong = 0x80507368; pub const SIOCGIFHWADDR: c_ulong = 0x80507369; pub const SIOCGIFMETRIC: c_ulong = 0x8050736a; pub const SIOCGIFMTU: c_ulong = 0x8050736b; pub const SIOCGIFINDEX: c_ulong = 0x8050736c; pub const SIOGIFINDEX: c_ulong = SIOCGIFINDEX; pub const SIOCGIFDSTADDR: c_ulong = 0x8050736e; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_DEBUG: c_int = 1; pub const SO_ACCEPTCONN: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_USELOOPBACK: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_PEERCRED: c_int = 0x0200; pub const SO_PASSCRED: c_int = 0x0400; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVLOWAT: c_int = 0x1004; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; pub const SO_TYPE: c_int = 0x1008; pub const SCM_RIGHTS: c_int = 0x01; pub const SCM_CREDENTIALS: c_int = 0x02; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_SEQPACKET: c_int = 5; pub const SOCK_NONBLOCK: c_int = 0x01000000; pub const SOCK_CLOEXEC: c_int = 0x02000000; pub const AF_UNSPEC: c_int = 0; pub const AF_LOCAL: c_int = 1; pub const AF_UNIX: c_int = AF_LOCAL; pub const AF_INET: c_int = 2; pub const AF_IMPLINK: c_int = 3; pub const AF_PUP: c_int = 4; pub const AF_CHAOS: c_int = 5; pub const AF_NS: c_int = 6; pub const AF_ISO: c_int = 7; pub const AF_OSI: c_int = AF_ISO; pub const AF_ECMA: c_int = 8; pub const AF_DATAKIT: c_int = 9; pub const AF_CCITT: c_int = 10; pub const AF_SNA: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_DLI: c_int = 13; pub const AF_LAT: c_int = 14; pub const AF_HYLINK: c_int = 15; pub const AF_APPLETALK: c_int = 16; pub const AF_NETBIOS: c_int = 17; pub const AF_INET6: c_int = 23; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_LOCAL: c_int = AF_LOCAL; pub const PF_UNIX: c_int = PF_LOCAL; pub const PF_INET: c_int = AF_INET; pub const PF_IMPLINK: c_int = AF_IMPLINK; pub const PF_PUP: c_int = AF_PUP; pub const PF_CHAOS: c_int = AF_CHAOS; pub const PF_NS: c_int = AF_NS; pub const PF_ISO: c_int = AF_ISO; pub const PF_OSI: c_int = AF_ISO; pub const PF_DATAKIT: c_int = AF_DATAKIT; pub const PF_CCITT: c_int = AF_CCITT; pub const PF_SNA: c_int = AF_SNA; pub const PF_DECnet: c_int = AF_DECnet; pub const PF_DLI: c_int = AF_DLI; pub const PF_LAT: c_int = AF_LAT; pub const PF_HYLINK: c_int = AF_HYLINK; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_NETBIOS: c_int = AF_NETBIOS; pub const PF_INET6: c_int = AF_INET6; pub const SOMAXCONN: c_int = 0x7fffffff; pub const MSG_OOB: c_int = 0x1; pub const MSG_PEEK: c_int = 0x2; pub const MSG_DONTROUTE: c_int = 0x4; pub const MSG_WAITALL: c_int = 0x8; pub const MSG_DONTWAIT: c_int = 0x10; pub const MSG_NOSIGNAL: c_int = 0x20; pub const MSG_TRUNC: c_int = 0x0100; pub const MSG_CTRUNC: c_int = 0x0200; pub const MSG_BCAST: c_int = 0x0400; pub const MSG_MCAST: c_int = 0x0800; pub const MSG_CMSG_CLOEXEC: c_int = 0x1000; pub const MSG_EOR: c_int = 0x8000; pub const SOL_IP: c_int = 0; pub const SOL_IPV6: c_int = 41; pub const SOL_TCP: c_int = 6; pub const SOL_UDP: c_int = 17; pub const IPTOS_LOWDELAY: u8 = 0x10; pub const IPTOS_THROUGHPUT: u8 = 0x08; pub const IPTOS_RELIABILITY: u8 = 0x04; pub const IPTOS_LOWCOST: u8 = 0x02; pub const IPTOS_MINCOST: u8 = IPTOS_LOWCOST; pub const IP_DEFAULT_MULTICAST_TTL: c_int = 1; pub const IP_DEFAULT_MULTICAST_LOOP: c_int = 1; pub const IP_OPTIONS: c_int = 1; pub const IP_HDRINCL: c_int = 2; pub const IP_TOS: c_int = 3; pub const IP_TTL: c_int = 4; pub const IP_MULTICAST_IF: c_int = 9; pub const IP_MULTICAST_TTL: c_int = 10; pub const IP_MULTICAST_LOOP: c_int = 11; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IP_ADD_SOURCE_MEMBERSHIP: c_int = 15; pub const IP_DROP_SOURCE_MEMBERSHIP: c_int = 16; pub const IP_BLOCK_SOURCE: c_int = 17; pub const IP_UNBLOCK_SOURCE: c_int = 18; pub const IP_PKTINFO: c_int = 19; pub const IP_RECVTTL: c_int = 21; pub const IP_UNICAST_IF: c_int = 31; pub const IP_RECVTOS: c_int = 40; pub const IP_MTU_DISCOVER: c_int = 71; pub const IP_MTU: c_int = 73; pub const IP_RECVERR: c_int = 75; pub const IP_PMTUDISC_WANT: c_int = 0; pub const IP_PMTUDISC_DO: c_int = 1; pub const IP_PMTUDISC_DONT: c_int = 2; pub const IP_PMTUDISC_PROBE: c_int = 3; pub const IPV6_HOPOPTS: c_int = 1; pub const IPV6_HDRINCL: c_int = 2; pub const IPV6_UNICAST_HOPS: c_int = 4; pub const IPV6_MULTICAST_IF: c_int = 9; pub const IPV6_MULTICAST_HOPS: c_int = 10; pub const IPV6_MULTICAST_LOOP: c_int = 11; pub const IPV6_ADD_MEMBERSHIP: c_int = 12; pub const IPV6_DROP_MEMBERSHIP: c_int = 13; pub const IPV6_JOIN_GROUP: c_int = 12; pub const IPV6_LEAVE_GROUP: c_int = 13; pub const IPV6_DONTFRAG: c_int = 14; pub const IPV6_PKTINFO: c_int = 19; pub const IPV6_HOPLIMIT: c_int = 21; pub const IPV6_CHECKSUM: c_int = 26; pub const IPV6_V6ONLY: c_int = 27; pub const IPV6_UNICAST_IF: c_int = 31; pub const IPV6_RTHDR: c_int = 32; pub const IPV6_RECVRTHDR: c_int = 38; pub const IPV6_TCLASS: c_int = 39; pub const IPV6_RECVTCLASS: c_int = 40; pub const IPV6_MTU_DISCOVER: c_int = 71; pub const IPV6_MTU: c_int = 72; pub const IPV6_RECVERR: c_int = 75; pub const IPV6_PMTUDISC_WANT: c_int = 0; pub const IPV6_PMTUDISC_DO: c_int = 1; pub const IPV6_PMTUDISC_DONT: c_int = 2; pub const IPV6_PMTUDISC_PROBE: c_int = 3; pub const MCAST_JOIN_GROUP: c_int = 41; pub const MCAST_LEAVE_GROUP: c_int = 42; pub const MCAST_BLOCK_SOURCE: c_int = 43; pub const MCAST_UNBLOCK_SOURCE: c_int = 44; pub const MCAST_JOIN_SOURCE_GROUP: c_int = 45; pub const MCAST_LEAVE_SOURCE_GROUP: c_int = 46; pub const MCAST_INCLUDE: c_int = 0; pub const MCAST_EXCLUDE: c_int = 1; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const S_BLKSIZE: mode_t = 1024; pub const S_IREAD: mode_t = 256; pub const S_IWRITE: mode_t = 128; pub const S_IEXEC: mode_t = 64; pub const S_ENFMT: mode_t = 1024; pub const S_IFMT: mode_t = 61440; pub const S_IFDIR: mode_t = 16384; pub const S_IFCHR: mode_t = 8192; pub const S_IFBLK: mode_t = 24576; pub const S_IFREG: mode_t = 32768; pub const S_IFLNK: mode_t = 40960; pub const S_IFSOCK: mode_t = 49152; pub const S_IFIFO: mode_t = 4096; pub const S_IRWXU: mode_t = 448; pub const S_IRUSR: mode_t = 256; pub const S_IWUSR: mode_t = 128; pub const S_IXUSR: mode_t = 64; pub const S_IRWXG: mode_t = 56; pub const S_IRGRP: mode_t = 32; pub const S_IWGRP: mode_t = 16; pub const S_IXGRP: mode_t = 8; pub const S_IRWXO: mode_t = 7; pub const S_IROTH: mode_t = 4; pub const S_IWOTH: mode_t = 2; pub const S_IXOTH: mode_t = 1; pub const UTIME_NOW: c_long = -2; pub const UTIME_OMIT: c_long = -1; pub const ARG_MAX: c_int = 32000; pub const CHILD_MAX: c_int = 256; pub const IOV_MAX: c_int = 1024; pub const PTHREAD_STACK_MIN: size_t = 65536; pub const PATH_MAX: c_int = 4096; pub const PIPE_BUF: usize = 4096; pub const NGROUPS_MAX: c_int = 1024; pub const FORK_RELOAD: c_int = 1; pub const FORK_NO_RELOAD: c_int = 0; pub const RTLD_DEFAULT: *mut c_void = 0isize as *mut c_void; pub const RTLD_LOCAL: c_int = 0; pub const RTLD_LAZY: c_int = 1; pub const RTLD_NOW: c_int = 2; pub const RTLD_GLOBAL: c_int = 4; pub const RTLD_NODELETE: c_int = 8; pub const RTLD_NOLOAD: c_int = 16; pub const RTLD_DEEPBIND: c_int = 32; /// IP6 hop-by-hop options pub const IPPROTO_HOPOPTS: c_int = 0; /// gateway mgmt protocol pub const IPPROTO_IGMP: c_int = 2; /// IPIP tunnels (older KA9Q tunnels use 94) pub const IPPROTO_IPIP: c_int = 4; /// exterior gateway protocol pub const IPPROTO_EGP: c_int = 8; /// pup pub const IPPROTO_PUP: c_int = 12; /// xns idp pub const IPPROTO_IDP: c_int = 22; /// IP6 routing header pub const IPPROTO_ROUTING: c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: c_int = 44; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: c_int = 51; /// IP6 no next header pub const IPPROTO_NONE: c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: c_int = 60; pub const IPPROTO_RAW: c_int = 255; pub const IPPROTO_MAX: c_int = 256; pub const AI_PASSIVE: c_int = 0x1; pub const AI_CANONNAME: c_int = 0x2; pub const AI_NUMERICHOST: c_int = 0x4; pub const AI_NUMERICSERV: c_int = 0x8; pub const AI_ALL: c_int = 0x100; pub const AI_ADDRCONFIG: c_int = 0x400; pub const AI_V4MAPPED: c_int = 0x800; pub const NI_NOFQDN: c_int = 0x1; pub const NI_NUMERICHOST: c_int = 0x2; pub const NI_NAMEREQD: c_int = 0x4; pub const NI_NUMERICSERV: c_int = 0x8; pub const NI_DGRAM: c_int = 0x10; pub const NI_MAXHOST: c_int = 1025; pub const NI_MAXSERV: c_int = 32; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_MEMORY: c_int = 6; pub const EAI_NODATA: c_int = 7; pub const EAI_NONAME: c_int = 8; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 14; pub const POLLIN: c_short = 0x1; pub const POLLPRI: c_short = 0x2; pub const POLLOUT: c_short = 0x4; pub const POLLERR: c_short = 0x8; pub const POLLHUP: c_short = 0x10; pub const POLLNVAL: c_short = 0x20; pub const POLLRDNORM: c_short = 0x1; pub const POLLRDBAND: c_short = 0x2; pub const POLLWRNORM: c_short = 0x4; pub const POLLWRBAND: c_short = 0x4; pub const LC_ALL: c_int = 0; pub const LC_COLLATE: c_int = 1; pub const LC_CTYPE: c_int = 2; pub const LC_MONETARY: c_int = 3; pub const LC_NUMERIC: c_int = 4; pub const LC_TIME: c_int = 5; pub const LC_MESSAGES: c_int = 6; pub const LC_ALL_MASK: c_int = 1 << 0; pub const LC_COLLATE_MASK: c_int = 1 << 1; pub const LC_CTYPE_MASK: c_int = 1 << 2; pub const LC_MONETARY_MASK: c_int = 1 << 3; pub const LC_NUMERIC_MASK: c_int = 1 << 4; pub const LC_TIME_MASK: c_int = 1 << 5; pub const LC_MESSAGES_MASK: c_int = 1 << 6; pub const LC_GLOBAL_LOCALE: locale_t = -1isize as locale_t; pub const SEM_FAILED: *mut sem_t = core::ptr::null_mut(); pub const ST_RDONLY: c_ulong = 0x80000; pub const ST_NOSUID: c_ulong = 0; pub const TIOCMGET: c_int = 0x5415; pub const TIOCMBIS: c_int = 0x5416; pub const TIOCMBIC: c_int = 0x5417; pub const TIOCMSET: c_int = 0x5418; pub const TIOCINQ: c_int = 0x541B; pub const TIOCSCTTY: c_int = 0x540E; pub const TIOCSBRK: c_int = 0x5427; pub const TIOCCBRK: c_int = 0x5428; pub const TIOCM_DTR: c_int = 0x002; pub const TIOCM_RTS: c_int = 0x004; pub const TIOCM_CTS: c_int = 0x020; pub const TIOCM_CAR: c_int = 0x040; pub const TIOCM_RNG: c_int = 0x080; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const TCOOFF: c_int = 0; pub const TCOON: c_int = 1; pub const TCIOFF: c_int = 2; pub const TCION: c_int = 3; pub const TCGETA: c_int = 5; pub const TCSETA: c_int = 6; pub const TCSETAW: c_int = 7; pub const TCSETAF: c_int = 8; pub const TCIFLUSH: c_int = 0; pub const TCOFLUSH: c_int = 1; pub const TCIOFLUSH: c_int = 2; pub const TCFLSH: c_int = 3; pub const TCSAFLUSH: c_int = 1; pub const TCSANOW: c_int = 2; pub const TCSADRAIN: c_int = 3; pub const TIOCPKT: c_int = 6; pub const TIOCPKT_DATA: c_int = 0x0; pub const TIOCPKT_FLUSHREAD: c_int = 0x1; pub const TIOCPKT_FLUSHWRITE: c_int = 0x2; pub const TIOCPKT_STOP: c_int = 0x4; pub const TIOCPKT_START: c_int = 0x8; pub const TIOCPKT_NOSTOP: c_int = 0x10; pub const TIOCPKT_DOSTOP: c_int = 0x20; pub const IGNBRK: tcflag_t = 0x00001; pub const BRKINT: tcflag_t = 0x00002; pub const IGNPAR: tcflag_t = 0x00004; pub const IMAXBEL: tcflag_t = 0x00008; pub const INPCK: tcflag_t = 0x00010; pub const ISTRIP: tcflag_t = 0x00020; pub const INLCR: tcflag_t = 0x00040; pub const IGNCR: tcflag_t = 0x00080; pub const ICRNL: tcflag_t = 0x00100; pub const IXON: tcflag_t = 0x00400; pub const IXOFF: tcflag_t = 0x01000; pub const IUCLC: tcflag_t = 0x04000; pub const IXANY: tcflag_t = 0x08000; pub const PARMRK: tcflag_t = 0x10000; pub const IUTF8: tcflag_t = 0x20000; pub const OPOST: tcflag_t = 0x00001; pub const OLCUC: tcflag_t = 0x00002; pub const OCRNL: tcflag_t = 0x00004; pub const ONLCR: tcflag_t = 0x00008; pub const ONOCR: tcflag_t = 0x00010; pub const ONLRET: tcflag_t = 0x00020; pub const OFILL: tcflag_t = 0x00040; pub const CRDLY: tcflag_t = 0x00180; pub const CR0: tcflag_t = 0x00000; pub const CR1: tcflag_t = 0x00080; pub const CR2: tcflag_t = 0x00100; pub const CR3: tcflag_t = 0x00180; pub const NLDLY: tcflag_t = 0x00200; pub const NL0: tcflag_t = 0x00000; pub const NL1: tcflag_t = 0x00200; pub const BSDLY: tcflag_t = 0x00400; pub const BS0: tcflag_t = 0x00000; pub const BS1: tcflag_t = 0x00400; pub const TABDLY: tcflag_t = 0x01800; pub const TAB0: tcflag_t = 0x00000; pub const TAB1: tcflag_t = 0x00800; pub const TAB2: tcflag_t = 0x01000; pub const TAB3: tcflag_t = 0x01800; pub const XTABS: tcflag_t = 0x01800; pub const VTDLY: tcflag_t = 0x02000; pub const VT0: tcflag_t = 0x00000; pub const VT1: tcflag_t = 0x02000; pub const FFDLY: tcflag_t = 0x04000; pub const FF0: tcflag_t = 0x00000; pub const FF1: tcflag_t = 0x04000; pub const OFDEL: tcflag_t = 0x08000; pub const CBAUD: tcflag_t = 0x0100f; pub const B0: speed_t = 0x00000; pub const B50: speed_t = 0x00001; pub const B75: speed_t = 0x00002; pub const B110: speed_t = 0x00003; pub const B134: speed_t = 0x00004; pub const B150: speed_t = 0x00005; pub const B200: speed_t = 0x00006; pub const B300: speed_t = 0x00007; pub const B600: speed_t = 0x00008; pub const B1200: speed_t = 0x00009; pub const B1800: speed_t = 0x0000a; pub const B2400: speed_t = 0x0000b; pub const B4800: speed_t = 0x0000c; pub const B9600: speed_t = 0x0000d; pub const B19200: speed_t = 0x0000e; pub const B38400: speed_t = 0x0000f; pub const CSIZE: tcflag_t = 0x00030; pub const CS5: tcflag_t = 0x00000; pub const CS6: tcflag_t = 0x00010; pub const CS7: tcflag_t = 0x00020; pub const CS8: tcflag_t = 0x00030; pub const CSTOPB: tcflag_t = 0x00040; pub const CREAD: tcflag_t = 0x00080; pub const PARENB: tcflag_t = 0x00100; pub const PARODD: tcflag_t = 0x00200; pub const HUPCL: tcflag_t = 0x00400; pub const CLOCAL: tcflag_t = 0x00800; pub const CBAUDEX: tcflag_t = 0x0100f; pub const B57600: speed_t = 0x01001; pub const B115200: speed_t = 0x01002; pub const B230400: speed_t = 0x01004; pub const B460800: speed_t = 0x01006; pub const B500000: speed_t = 0x01007; pub const B576000: speed_t = 0x01008; pub const B921600: speed_t = 0x01009; pub const B1000000: speed_t = 0x0100a; pub const B1152000: speed_t = 0x0100b; pub const B1500000: speed_t = 0x0100c; pub const B2000000: speed_t = 0x0100d; pub const B2500000: speed_t = 0x0100e; pub const B3000000: speed_t = 0x0100f; pub const CRTSCTS: tcflag_t = 0x08000; pub const CMSPAR: tcflag_t = 0x40000000; pub const ISIG: tcflag_t = 0x0001; pub const ICANON: tcflag_t = 0x0002; pub const ECHO: tcflag_t = 0x0004; pub const ECHOE: tcflag_t = 0x0008; pub const ECHOK: tcflag_t = 0x0010; pub const ECHONL: tcflag_t = 0x0020; pub const NOFLSH: tcflag_t = 0x0040; pub const TOSTOP: tcflag_t = 0x0080; pub const IEXTEN: tcflag_t = 0x0100; pub const FLUSHO: tcflag_t = 0x0200; pub const ECHOKE: tcflag_t = 0x0400; pub const ECHOCTL: tcflag_t = 0x0800; pub const VDISCARD: usize = 1; pub const VEOL: usize = 2; pub const VEOL2: usize = 3; pub const VEOF: usize = 4; pub const VERASE: usize = 5; pub const VINTR: usize = 6; pub const VKILL: usize = 7; pub const VLNEXT: usize = 8; pub const VMIN: usize = 9; pub const VQUIT: usize = 10; pub const VREPRINT: usize = 11; pub const VSTART: usize = 12; pub const VSTOP: usize = 13; pub const VSUSP: usize = 14; pub const VSWTC: usize = 15; pub const VTIME: usize = 16; pub const VWERASE: usize = 17; pub const NCCS: usize = 18; pub const TIOCGWINSZ: c_int = 0x5401; pub const TIOCSWINSZ: c_int = 0x5402; pub const TIOCLINUX: c_int = 0x5403; pub const TIOCGPGRP: c_int = 0x540f; pub const TIOCSPGRP: c_int = 0x5410; pub const WNOHANG: c_int = 1; pub const WUNTRACED: c_int = 2; pub const WCONTINUED: c_int = 8; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const MAP_FILE: c_int = 0; pub const MAP_SHARED: c_int = 1; pub const MAP_PRIVATE: c_int = 2; pub const MAP_TYPE: c_int = 0xf; pub const MAP_FIXED: c_int = 0x10; pub const MAP_ANON: c_int = 0x20; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const MAP_NORESERVE: c_int = 0x4000; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const MS_ASYNC: c_int = 1; pub const MS_SYNC: c_int = 2; pub const MS_INVALIDATE: c_int = 4; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_SEQUENTIAL: c_int = 1; pub const POSIX_MADV_RANDOM: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const MADV_NORMAL: c_int = 0; pub const MADV_SEQUENTIAL: c_int = 1; pub const MADV_RANDOM: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const F_ULOCK: c_int = 0; pub const F_LOCK: c_int = 1; pub const F_TLOCK: c_int = 2; pub const F_TEST: c_int = 3; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_JOB_CONTROL: c_int = 5; pub const _SC_SAVED_IDS: c_int = 6; pub const _SC_VERSION: c_int = 7; pub const _SC_PAGESIZE: c_int = 8; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_NPROCESSORS_CONF: c_int = 9; pub const _SC_NPROCESSORS_ONLN: c_int = 10; pub const _SC_PHYS_PAGES: c_int = 11; pub const _SC_AVPHYS_PAGES: c_int = 12; pub const _SC_MQ_OPEN_MAX: c_int = 13; pub const _SC_MQ_PRIO_MAX: c_int = 14; pub const _SC_RTSIG_MAX: c_int = 15; pub const _SC_SEM_NSEMS_MAX: c_int = 16; pub const _SC_SEM_VALUE_MAX: c_int = 17; pub const _SC_SIGQUEUE_MAX: c_int = 18; pub const _SC_TIMER_MAX: c_int = 19; pub const _SC_TZNAME_MAX: c_int = 20; pub const _SC_ASYNCHRONOUS_IO: c_int = 21; pub const _SC_FSYNC: c_int = 22; pub const _SC_MAPPED_FILES: c_int = 23; pub const _SC_MEMLOCK: c_int = 24; pub const _SC_MEMLOCK_RANGE: c_int = 25; pub const _SC_MEMORY_PROTECTION: c_int = 26; pub const _SC_MESSAGE_PASSING: c_int = 27; pub const _SC_PRIORITIZED_IO: c_int = 28; pub const _SC_REALTIME_SIGNALS: c_int = 29; pub const _SC_SEMAPHORES: c_int = 30; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 31; pub const _SC_SYNCHRONIZED_IO: c_int = 32; pub const _SC_TIMERS: c_int = 33; pub const _SC_AIO_LISTIO_MAX: c_int = 34; pub const _SC_AIO_MAX: c_int = 35; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 36; pub const _SC_DELAYTIMER_MAX: c_int = 37; pub const _SC_THREAD_KEYS_MAX: c_int = 38; pub const _SC_THREAD_STACK_MIN: c_int = 39; pub const _SC_THREAD_THREADS_MAX: c_int = 40; pub const _SC_TTY_NAME_MAX: c_int = 41; pub const _SC_THREADS: c_int = 42; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 43; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 44; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 45; pub const _SC_THREAD_PRIO_INHERIT: c_int = 46; pub const _SC_THREAD_PRIO_PROTECT: c_int = 47; pub const _SC_THREAD_PRIO_CEILING: c_int = _SC_THREAD_PRIO_PROTECT; pub const _SC_THREAD_PROCESS_SHARED: c_int = 48; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 49; pub const _SC_GETGR_R_SIZE_MAX: c_int = 50; pub const _SC_GETPW_R_SIZE_MAX: c_int = 51; pub const _SC_LOGIN_NAME_MAX: c_int = 52; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 53; pub const _SC_ADVISORY_INFO: c_int = 54; pub const _SC_ATEXIT_MAX: c_int = 55; pub const _SC_BARRIERS: c_int = 56; pub const _SC_BC_BASE_MAX: c_int = 57; pub const _SC_BC_DIM_MAX: c_int = 58; pub const _SC_BC_SCALE_MAX: c_int = 59; pub const _SC_BC_STRING_MAX: c_int = 60; pub const _SC_CLOCK_SELECTION: c_int = 61; pub const _SC_COLL_WEIGHTS_MAX: c_int = 62; pub const _SC_CPUTIME: c_int = 63; pub const _SC_EXPR_NEST_MAX: c_int = 64; pub const _SC_HOST_NAME_MAX: c_int = 65; pub const _SC_IOV_MAX: c_int = 66; pub const _SC_IPV6: c_int = 67; pub const _SC_LINE_MAX: c_int = 68; pub const _SC_MONOTONIC_CLOCK: c_int = 69; pub const _SC_RAW_SOCKETS: c_int = 70; pub const _SC_READER_WRITER_LOCKS: c_int = 71; pub const _SC_REGEXP: c_int = 72; pub const _SC_RE_DUP_MAX: c_int = 73; pub const _SC_SHELL: c_int = 74; pub const _SC_SPAWN: c_int = 75; pub const _SC_SPIN_LOCKS: c_int = 76; pub const _SC_SPORADIC_SERVER: c_int = 77; pub const _SC_SS_REPL_MAX: c_int = 78; pub const _SC_SYMLOOP_MAX: c_int = 79; pub const _SC_THREAD_CPUTIME: c_int = 80; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 81; pub const _SC_TIMEOUTS: c_int = 82; pub const _SC_TRACE: c_int = 83; pub const _SC_TRACE_EVENT_FILTER: c_int = 84; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 85; pub const _SC_TRACE_INHERIT: c_int = 86; pub const _SC_TRACE_LOG: c_int = 87; pub const _SC_TRACE_NAME_MAX: c_int = 88; pub const _SC_TRACE_SYS_MAX: c_int = 89; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 90; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 91; pub const _SC_V7_ILP32_OFF32: c_int = 92; pub const _SC_V6_ILP32_OFF32: c_int = _SC_V7_ILP32_OFF32; pub const _SC_XBS5_ILP32_OFF32: c_int = _SC_V7_ILP32_OFF32; pub const _SC_V7_ILP32_OFFBIG: c_int = 93; pub const _SC_V6_ILP32_OFFBIG: c_int = _SC_V7_ILP32_OFFBIG; pub const _SC_XBS5_ILP32_OFFBIG: c_int = _SC_V7_ILP32_OFFBIG; pub const _SC_V7_LP64_OFF64: c_int = 94; pub const _SC_V6_LP64_OFF64: c_int = _SC_V7_LP64_OFF64; pub const _SC_XBS5_LP64_OFF64: c_int = _SC_V7_LP64_OFF64; pub const _SC_V7_LPBIG_OFFBIG: c_int = 95; pub const _SC_V6_LPBIG_OFFBIG: c_int = _SC_V7_LPBIG_OFFBIG; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = _SC_V7_LPBIG_OFFBIG; pub const _SC_XOPEN_CRYPT: c_int = 96; pub const _SC_XOPEN_ENH_I18N: c_int = 97; pub const _SC_XOPEN_LEGACY: c_int = 98; pub const _SC_XOPEN_REALTIME: c_int = 99; pub const _SC_STREAM_MAX: c_int = 100; pub const _SC_PRIORITY_SCHEDULING: c_int = 101; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 102; pub const _SC_XOPEN_SHM: c_int = 103; pub const _SC_XOPEN_STREAMS: c_int = 104; pub const _SC_XOPEN_UNIX: c_int = 105; pub const _SC_XOPEN_VERSION: c_int = 106; pub const _SC_2_CHAR_TERM: c_int = 107; pub const _SC_2_C_BIND: c_int = 108; pub const _SC_2_C_DEV: c_int = 109; pub const _SC_2_FORT_DEV: c_int = 110; pub const _SC_2_FORT_RUN: c_int = 111; pub const _SC_2_LOCALEDEF: c_int = 112; pub const _SC_2_PBS: c_int = 113; pub const _SC_2_PBS_ACCOUNTING: c_int = 114; pub const _SC_2_PBS_CHECKPOINT: c_int = 115; pub const _SC_2_PBS_LOCATE: c_int = 116; pub const _SC_2_PBS_MESSAGE: c_int = 117; pub const _SC_2_PBS_TRACK: c_int = 118; pub const _SC_2_SW_DEV: c_int = 119; pub const _SC_2_UPE: c_int = 120; pub const _SC_2_VERSION: c_int = 121; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 122; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 123; pub const _SC_XOPEN_UUCP: c_int = 124; pub const _SC_LEVEL1_ICACHE_SIZE: c_int = 125; pub const _SC_LEVEL1_ICACHE_ASSOC: c_int = 126; pub const _SC_LEVEL1_ICACHE_LINESIZE: c_int = 127; pub const _SC_LEVEL1_DCACHE_SIZE: c_int = 128; pub const _SC_LEVEL1_DCACHE_ASSOC: c_int = 129; pub const _SC_LEVEL1_DCACHE_LINESIZE: c_int = 130; pub const _SC_LEVEL2_CACHE_SIZE: c_int = 131; pub const _SC_LEVEL2_CACHE_ASSOC: c_int = 132; pub const _SC_LEVEL2_CACHE_LINESIZE: c_int = 133; pub const _SC_LEVEL3_CACHE_SIZE: c_int = 134; pub const _SC_LEVEL3_CACHE_ASSOC: c_int = 135; pub const _SC_LEVEL3_CACHE_LINESIZE: c_int = 136; pub const _SC_LEVEL4_CACHE_SIZE: c_int = 137; pub const _SC_LEVEL4_CACHE_ASSOC: c_int = 138; pub const _SC_LEVEL4_CACHE_LINESIZE: c_int = 139; pub const _PC_LINK_MAX: c_int = 0; pub const _PC_MAX_CANON: c_int = 1; pub const _PC_MAX_INPUT: c_int = 2; pub const _PC_NAME_MAX: c_int = 3; pub const _PC_PATH_MAX: c_int = 4; pub const _PC_PIPE_BUF: c_int = 5; pub const _PC_CHOWN_RESTRICTED: c_int = 6; pub const _PC_NO_TRUNC: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_ASYNC_IO: c_int = 9; pub const _PC_PRIO_IO: c_int = 10; pub const _PC_SYNC_IO: c_int = 11; pub const _PC_FILESIZEBITS: c_int = 12; pub const _PC_2_SYMLINKS: c_int = 13; pub const _PC_SYMLINK_MAX: c_int = 14; pub const _PC_ALLOC_SIZE_MIN: c_int = 15; pub const _PC_REC_INCR_XFER_SIZE: c_int = 16; pub const _PC_REC_MAX_XFER_SIZE: c_int = 17; pub const _PC_REC_MIN_XFER_SIZE: c_int = 18; pub const _PC_REC_XFER_ALIGN: c_int = 19; pub const _PC_TIMESTAMP_RESOLUTION: c_int = 20; pub const _CS_PATH: c_int = 0; pub const O_ACCMODE: c_int = 0x3; pub const O_RDONLY: c_int = 0; pub const O_WRONLY: c_int = 1; pub const O_RDWR: c_int = 2; pub const O_APPEND: c_int = 0x0008; pub const O_CREAT: c_int = 0x0200; pub const O_TRUNC: c_int = 0x0400; pub const O_EXCL: c_int = 0x0800; pub const O_SYNC: c_int = 0x2000; pub const O_NONBLOCK: c_int = 0x4000; pub const O_NOCTTY: c_int = 0x8000; pub const O_CLOEXEC: c_int = 0x40000; pub const O_NOFOLLOW: c_int = 0x100000; pub const O_DIRECTORY: c_int = 0x200000; pub const O_EXEC: c_int = 0x400000; pub const O_SEARCH: c_int = 0x400000; pub const O_DIRECT: c_int = 0x80000; pub const O_DSYNC: c_int = 0x2000; pub const O_RSYNC: c_int = 0x2000; pub const O_TMPFILE: c_int = 0x800000; pub const O_NOATIME: c_int = 0x1000000; pub const O_PATH: c_int = 0x2000000; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const F_GETOWN: c_int = 5; pub const F_SETOWN: c_int = 6; pub const F_GETLK: c_int = 7; pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; pub const F_RGETLK: c_int = 10; pub const F_RSETLK: c_int = 11; pub const F_CNVT: c_int = 12; pub const F_RSETLKW: c_int = 13; pub const F_DUPFD_CLOEXEC: c_int = 14; pub const F_RDLCK: c_int = 1; pub const F_WRLCK: c_int = 2; pub const F_UNLCK: c_int = 3; pub const AT_FDCWD: c_int = -2; pub const AT_EACCESS: c_int = 1; pub const AT_SYMLINK_NOFOLLOW: c_int = 2; pub const AT_SYMLINK_FOLLOW: c_int = 4; pub const AT_REMOVEDIR: c_int = 8; pub const AT_EMPTY_PATH: c_int = 16; pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EDEADLK: c_int = 45; pub const ENOLCK: c_int = 46; pub const EBADE: c_int = 50; pub const EBADR: c_int = 51; pub const EXFULL: c_int = 52; pub const ENOANO: c_int = 53; pub const EBADRQC: c_int = 54; pub const EBADSLT: c_int = 55; pub const EDEADLOCK: c_int = 56; pub const EBFONT: c_int = 57; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EMULTIHOP: c_int = 74; pub const EDOTDOT: c_int = 76; pub const EBADMSG: c_int = 77; pub const EFTYPE: c_int = 79; pub const ENOTUNIQ: c_int = 80; pub const EBADFD: c_int = 81; pub const EREMCHG: c_int = 82; pub const ELIBACC: c_int = 83; pub const ELIBBAD: c_int = 84; pub const ELIBSCN: c_int = 85; pub const ELIBMAX: c_int = 86; pub const ELIBEXEC: c_int = 87; pub const ENOSYS: c_int = 88; pub const ENOTEMPTY: c_int = 90; pub const ENAMETOOLONG: c_int = 91; pub const ELOOP: c_int = 92; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EAFNOSUPPORT: c_int = 106; pub const EPROTOTYPE: c_int = 107; pub const ENOTSOCK: c_int = 108; pub const ENOPROTOOPT: c_int = 109; pub const ESHUTDOWN: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EADDRINUSE: c_int = 112; pub const ECONNABORTED: c_int = 113; pub const ENETUNREACH: c_int = 114; pub const ENETDOWN: c_int = 115; pub const ETIMEDOUT: c_int = 116; pub const EHOSTDOWN: c_int = 117; pub const EHOSTUNREACH: c_int = 118; pub const EINPROGRESS: c_int = 119; pub const EALREADY: c_int = 120; pub const EDESTADDRREQ: c_int = 121; pub const EMSGSIZE: c_int = 122; pub const EPROTONOSUPPORT: c_int = 123; pub const ESOCKTNOSUPPORT: c_int = 124; pub const EADDRNOTAVAIL: c_int = 125; pub const ENETRESET: c_int = 126; pub const EISCONN: c_int = 127; pub const ENOTCONN: c_int = 128; pub const ETOOMANYREFS: c_int = 129; pub const EPROCLIM: c_int = 130; pub const EUSERS: c_int = 131; pub const EDQUOT: c_int = 132; pub const ESTALE: c_int = 133; pub const ENOTSUP: c_int = 134; pub const ENOMEDIUM: c_int = 135; pub const EILSEQ: c_int = 138; pub const EOVERFLOW: c_int = 139; pub const ECANCELED: c_int = 140; pub const ENOTRECOVERABLE: c_int = 141; pub const EOWNERDEAD: c_int = 142; pub const ESTRPIPE: c_int = 143; pub const EWOULDBLOCK: c_int = EAGAIN; /* Operation would block */ pub const SCHED_OTHER: c_int = 3; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = 21 as *mut _; pub const PTHREAD_CREATE_DETACHED: c_int = 1; pub const PTHREAD_CREATE_JOINABLE: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; pub const PTHREAD_MUTEX_NORMAL: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: pthread_mutex_t = 18 as *mut _; pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: pthread_mutex_t = 20 as *mut _; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = 19 as *mut _; pub const PTHREAD_PROCESS_SHARED: c_int = 1; pub const PTHREAD_PROCESS_PRIVATE: c_int = 0; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = 22 as *mut _; pub const LITTLE_ENDIAN: c_int = 1234; pub const BIG_ENDIAN: c_int = 4321; pub const TCP_NODELAY: c_int = 1; pub const TCP_KEEPIDLE: c_int = 3; pub const TCP_MAXSEG: c_int = 4; pub const TCP_QUICKACK: c_int = 12; pub const TCP_USER_TIMEOUT: c_int = 14; pub const TCP_FASTOPEN: c_int = 15; pub const TCP_KEEPCNT: c_int = 16; pub const TCP_KEEPINTVL: c_int = 17; pub const WINDOWS_POST: c_int = 0; pub const WINDOWS_SEND: c_int = 1; pub const WINDOWS_HWND: c_int = 2; pub const MOUNT_TEXT: c_uint = 0x01; pub const MOUNT_SYSTEM: c_uint = 0x08; pub const MOUNT_EXEC: c_uint = 0x10; pub const MOUNT_CYGDRIVE: c_uint = 0x20; pub const MOUNT_CYGWIN_EXEC: c_uint = 0x40; pub const MOUNT_SPARSE: c_uint = 0x80; pub const MOUNT_NOTEXEC: c_uint = 0x100; pub const MOUNT_DEVFS: c_uint = 0x200; pub const MOUNT_PROC: c_uint = 0x400; pub const MOUNT_RO: c_uint = 0x1000; pub const MOUNT_NOACL: c_uint = 0x2000; pub const MOUNT_NOPOSIX: c_uint = 0x4000; pub const MOUNT_OVERRIDE: c_uint = 0x8000; pub const MOUNT_IMMUTABLE: c_uint = 0x10000; pub const MOUNT_AUTOMATIC: c_uint = 0x20000; pub const MOUNT_DOS: c_uint = 0x40000; pub const MOUNT_IHASH: c_uint = 0x80000; pub const MOUNT_BIND: c_uint = 0x100000; pub const MOUNT_USER_TEMP: c_uint = 0x200000; pub const MOUNT_DONT_USE: c_uint = 0x80000000; pub const _POSIX_VDISABLE: cc_t = 0; pub const GRND_NONBLOCK: c_uint = 0x1; pub const GRND_RANDOM: c_uint = 0x2; pub const _IONBF: c_int = 2; pub const BUFSIZ: c_int = 1024; pub const POSIX_SPAWN_RESETIDS: c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: c_int = 0x02; pub const POSIX_SPAWN_SETSCHEDPARAM: c_int = 0x04; pub const POSIX_SPAWN_SETSCHEDULER: c_int = 0x08; pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x10; pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x20; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_SEQUENTIAL: c_int = 1; pub const POSIX_FADV_RANDOM: c_int = 2; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const FALLOC_FL_PUNCH_HOLE: c_int = 0x0001; pub const FALLOC_FL_ZERO_RANGE: c_int = 0x0002; pub const FALLOC_FL_UNSHARE_RANGE: c_int = 0x0004; pub const FALLOC_FL_COLLAPSE_RANGE: c_int = 0x0008; pub const FALLOC_FL_INSERT_RANGE: c_int = 0x0010; pub const FALLOC_FL_KEEP_SIZE: c_int = 0x1000; f! { pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = core::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = core::mem::size_of_val(&(*set).fds_bits[0]) * 8; ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = core::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } pub fn CPU_ALLOC_SIZE(count: c_int) -> size_t { let _dummy: cpu_set_t = cpu_set_t { bits: [0; 16] }; let size_in_bits = 8 * core::mem::size_of_val(&_dummy.bits[0]); ((count as size_t + size_in_bits - 1) / 8) as size_t } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> c_int { let mut s: u32 = 0; let size_of_mask = core::mem::size_of_val(&cpuset.bits[0]); for i in cpuset.bits[..(size / size_of_mask)].iter() { s += i.count_ones(); } s as c_int } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * core::mem::size_of_val(&cpuset.bits[0]); if cpu < size_in_bits { let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; } } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * core::mem::size_of_val(&cpuset.bits[0]); if cpu < size_in_bits { let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); } } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * core::mem::size_of_val(&cpuset.bits[0]); if cpu < size_in_bits { let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } else { false } } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> c_int { CPU_COUNT_S(::core::mem::size_of::(), cpuset) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } pub fn CMSG_LEN(length: c_uint) -> c_uint { CMSG_ALIGN(::core::mem::size_of::()) as c_uint + length } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(::core::mem::size_of::())) as c_uint } pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= core::mem::size_of::() { (*mhdr).msg_control.cast() } else { core::ptr::null_mut() } } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { let next = (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next as usize + CMSG_ALIGN(::core::mem::size_of::()) as usize > max { core::ptr::null_mut() } else { next } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { cmsg.offset(1).cast_mut().cast() } } safe_f! { pub {const} fn makedev(ma: c_uint, mi: c_uint) -> dev_t { let ma = ma as dev_t; let mi = mi as dev_t; (ma << 16) | (mi & 0xffff) } pub {const} fn major(dev: dev_t) -> c_uint { ((dev >> 16) & 0xffff) as c_uint } pub {const} fn minor(dev: dev_t) -> c_uint { (dev & 0xffff) as c_uint } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0xff) == 0 } pub {const} fn WIFSIGNALED(status: c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 } pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xff) == 0o177 } pub {const} fn WIFCONTINUED(status: c_int) -> bool { (status & 0o177777) == 0o177777 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0o177 } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: c_int) -> bool { WIFSIGNALED(status) && (status & 0x80) != 0 } } const_fn! { {const} fn CMSG_ALIGN(len: usize) -> usize { len + core::mem::size_of::() - 1 & !(::core::mem::size_of::() - 1) } } extern "C" { pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sigsuspend(mask: *const sigset_t) -> c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn pthread_kill(thread: pthread_t, sig: c_int) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const timespec, ) -> c_int; pub fn strftime(s: *mut c_char, max: size_t, format: *const c_char, tm: *const tm) -> size_t; pub fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char; pub fn ctime_r(timep: *const time_t, buf: *mut c_char) -> *mut c_char; pub fn strptime(s: *const c_char, format: *const c_char, tm: *mut tm) -> *mut c_char; pub fn clock_settime(clk_id: clockid_t, tp: *const timespec) -> c_int; pub fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int; pub fn clock_getres(clk_id: clockid_t, tp: *mut timespec) -> c_int; pub fn timer_create(clockid: clockid_t, sevp: *mut sigevent, timerid: *mut timer_t) -> c_int; pub fn timer_delete(timerid: timer_t) -> c_int; pub fn timer_settime( timerid: timer_t, flags: c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> c_int; pub fn timer_gettime(timerid: timer_t, curr_value: *mut itimerspec) -> c_int; pub fn timer_getoverrun(timerid: timer_t) -> c_int; pub fn clock_nanosleep( clk_id: clockid_t, flags: c_int, rqtp: *const timespec, rmtp: *mut timespec, ) -> c_int; pub fn clock_getcpuclockid(pid: pid_t, clk_id: *mut clockid_t) -> c_int; pub fn futimes(fd: c_int, times: *const timeval) -> c_int; pub fn lutimes(file: *const c_char, times: *const timeval) -> c_int; pub fn settimeofday(tv: *const timeval, tz: *const timezone) -> c_int; pub fn getitimer(which: c_int, curr_value: *mut itimerval) -> c_int; pub fn setitimer(which: c_int, new_value: *const itimerval, old_value: *mut itimerval) -> c_int; pub fn gettimeofday(tp: *mut timeval, tz: *mut c_void) -> c_int; pub fn futimesat(fd: c_int, path: *const c_char, times: *const timeval) -> c_int; pub fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlim: *const rlimit) -> c_int; pub fn getpriority(which: c_int, who: id_t) -> c_int; pub fn setpriority(which: c_int, who: id_t, prio: c_int) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwent() -> *mut passwd; pub fn setpwent(); pub fn endpwent(); pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn readv(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t; pub fn writev(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: mode_t, dev: dev_t) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const timespec, flag: c_int, ) -> c_int; pub fn futimens(fd: c_int, times: *const timespec) -> c_int; pub fn dlfork(val: c_int); pub fn accept4(s: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t, flags: c_int) -> c_int; pub fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut sockaddr, addrlen: *mut socklen_t, ) -> ssize_t; pub fn recvmsg(fd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t; pub fn sendmsg(fd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t; pub fn getnameinfo( sa: *const sockaddr, salen: socklen_t, host: *mut c_char, hostlen: socklen_t, serv: *mut c_char, sevlen: socklen_t, flags: c_int, ) -> c_int; pub fn ppoll( fds: *mut pollfd, nfds: nfds_t, timeout: *const timespec, sigmask: *const sigset_t, ) -> c_int; pub fn newlocale(mask: c_int, locale: *const c_char, base: locale_t) -> locale_t; pub fn freelocale(loc: locale_t); pub fn duplocale(base: locale_t) -> locale_t; pub fn uselocale(loc: locale_t) -> locale_t; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const timespec) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn clearenv() -> c_int; pub fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn getpt() -> c_int; pub fn memalign(align: size_t, size: size_t) -> *mut c_void; pub fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int; pub fn abs(i: c_int) -> c_int; pub fn arc4random() -> u32; pub fn arc4random_uniform(l: u32) -> u32; pub fn arc4random_buf(buf: *mut c_void, size: size_t); pub fn labs(i: c_long) -> c_long; pub fn mkostemp(template: *mut c_char, flags: c_int) -> c_int; pub fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int; pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; pub fn rand() -> c_int; pub fn reallocarray(ptr: *mut c_void, nmemb: size_t, size: size_t) -> *mut c_void; pub fn reallocf(ptr: *mut c_void, size: size_t) -> *mut c_void; pub fn srand(seed: c_uint); pub fn drand48() -> c_double; pub fn erand48(xseed: *mut c_ushort) -> c_double; pub fn jrand48(xseed: *mut c_ushort) -> c_long; pub fn lcong48(p: *mut c_ushort); pub fn lrand48() -> c_long; pub fn mrand48() -> c_long; pub fn nrand48(xseed: *mut c_ushort) -> c_long; pub fn seed48(xseed: *mut c_ushort) -> *mut c_ushort; pub fn srand48(seed: c_long); pub fn qsort_r( base: *mut c_void, num: size_t, size: size_t, compar: Option c_int>, arg: *mut c_void, ); pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn explicit_bzero(s: *mut c_void, len: size_t); pub fn ffs(value: c_int) -> c_int; pub fn ffsl(value: c_long) -> c_int; pub fn ffsll(value: c_longlong) -> c_int; pub fn fls(value: c_int) -> c_int; pub fn flsl(value: c_long) -> c_int; pub fn flsll(value: c_longlong) -> c_int; pub fn strcasecmp_l(s1: *const c_char, s2: *const c_char, loc: locale_t) -> c_int; pub fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: size_t, loc: locale_t) -> c_int; pub fn timingsafe_bcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int; pub fn timingsafe_memcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; #[link_name = "__xpg_strerror_r"] pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn strsep(string: *mut *mut c_char, delim: *const c_char) -> *mut c_char; #[link_name = "__gnu_basename"] pub fn basename(path: *const c_char) -> *mut c_char; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn dup3(src: c_int, dst: c_int, flags: c_int) -> c_int; pub fn eaccess(pathname: *const c_char, mode: c_int) -> c_int; pub fn euidaccess(pathname: *const c_char, mode: c_int) -> c_int; pub fn execvpe( file: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn fexecve(fd: c_int, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; pub fn getdomainname(name: *mut c_char, len: size_t) -> c_int; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn gethostid() -> c_long; pub fn getpagesize() -> c_int; pub fn getpeereid(socket: c_int, euid: *mut uid_t, egid: *mut gid_t) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; pub fn sbrk(increment: intptr_t) -> *mut c_void; pub fn setgroups(ngroups: c_int, ptr: *const gid_t) -> c_int; pub fn sethostname(name: *const c_char, len: size_t) -> c_int; pub fn vhangup() -> c_int; pub fn getdtablesize() -> c_int; pub fn sync(); pub fn __errno() -> *mut c_int; pub fn sched_setparam(pid: pid_t, param: *const sched_param) -> c_int; pub fn sched_getparam(pid: pid_t, param: *mut sched_param) -> c_int; pub fn sched_setscheduler(pid: pid_t, policy: c_int, param: *const sched_param) -> c_int; pub fn sched_getscheduler(pid: pid_t) -> c_int; pub fn sched_get_priority_max(policy: c_int) -> c_int; pub fn sched_get_priority_min(policy: c_int) -> c_int; pub fn sched_rr_get_interval(pid: pid_t, t: *mut timespec) -> c_int; pub fn sched_getcpu() -> c_int; pub fn sched_getaffinity(pid: pid_t, cpusetsize: size_t, mask: *mut cpu_set_t) -> c_int; pub fn sched_setaffinity(pid: pid_t, cpusetsize: size_t, cpuset: *const cpu_set_t) -> c_int; pub fn pthread_attr_getguardsize(attr: *const pthread_attr_t, guardsize: *mut size_t) -> c_int; pub fn pthread_attr_getschedparam( attr: *const pthread_attr_t, param: *mut sched_param, ) -> c_int; pub fn pthread_attr_setschedparam( attr: *mut pthread_attr_t, param: *const sched_param, ) -> c_int; pub fn pthread_attr_getstack( attr: *const pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_cancel(thread: pthread_t) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clock_id: clockid_t) -> c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: c_int) -> c_int; pub fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, shared: c_int) -> c_int; pub fn pthread_barrierattr_getpshared( attr: *const pthread_barrierattr_t, shared: *mut c_int, ) -> c_int; pub fn pthread_barrierattr_destroy(attr: *mut pthread_barrierattr_t) -> c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const pthread_barrierattr_t, count: c_uint, ) -> c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_create( native: *mut pthread_t, attr: *const pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_getcpuclockid(thread: pthread_t, clk_id: *mut clockid_t) -> c_int; pub fn pthread_getschedparam( native: pthread_t, policy: *mut c_int, param: *mut sched_param, ) -> c_int; pub fn pthread_mutex_timedlock(lock: *mut pthread_mutex_t, abstime: *const timespec) -> c_int; pub fn pthread_mutexattr_getprotocol( attr: *const pthread_mutexattr_t, protocol: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: c_int) -> c_int; pub fn pthread_setschedparam( native: pthread_t, policy: c_int, param: *const sched_param, ) -> c_int; pub fn pthread_setschedprio(native: pthread_t, priority: c_int) -> c_int; pub fn pthread_getaffinity_np( thread: pthread_t, cpusetsize: size_t, cpuset: *mut cpu_set_t, ) -> c_int; pub fn pthread_getattr_np(native: pthread_t, attr: *mut pthread_attr_t) -> c_int; pub fn pthread_getname_np(thread: pthread_t, name: *mut c_char, len: size_t) -> c_int; pub fn pthread_setaffinity_np( thread: pthread_t, cpusetsize: size_t, cpuset: *const cpu_set_t, ) -> c_int; pub fn pthread_setname_np(thread: pthread_t, name: *const c_char) -> c_int; pub fn pthread_sigqueue(thread: pthread_t, sig: c_int, value: sigval) -> c_int; pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int; pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; pub fn mount(src: *const c_char, target: *const c_char, flags: c_uint) -> c_int; pub fn umount(target: *const c_char) -> c_int; pub fn cygwin_umount(target: *const c_char, flags: c_uint) -> c_int; pub fn dirfd(dirp: *mut DIR) -> c_int; pub fn seekdir(dirp: *mut DIR, loc: c_long); pub fn telldir(dirp: *mut DIR) -> c_long; pub fn uname(buf: *mut utsname) -> c_int; pub fn posix_spawn( pid: *mut pid_t, path: *const c_char, file_actions: *const posix_spawn_file_actions_t, attrp: *const posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut pid_t, file: *const c_char, file_actions: *const posix_spawn_file_actions_t, attrp: *const posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const sigset_t, ) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getpgroup(attr: *const posix_spawnattr_t, flags: *mut pid_t) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: pid_t) -> c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut c_int, ) -> c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: c_int) -> c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut sched_param, ) -> c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const sched_param, ) -> c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: c_int, path: *const c_char, oflag: c_int, mode: mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_addchdir( actions: *mut crate::posix_spawn_file_actions_t, path: *const c_char, ) -> c_int; pub fn posix_spawn_file_actions_addfchdir( actions: *mut crate::posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_addchdir_np( actions: *mut crate::posix_spawn_file_actions_t, path: *const c_char, ) -> c_int; pub fn posix_spawn_file_actions_addfchdir_np( actions: *mut crate::posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *const termios, winp: *const crate::winsize, ) -> crate::pid_t; pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *const termios, winp: *const crate::winsize, ) -> c_int; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrouplist( user: *const c_char, group: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn initgroups(user: *const c_char, group: crate::gid_t) -> c_int; pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn fallocate(fd: c_int, mode: c_int, offset: off_t, len: off_t) -> c_int; } libc/src/unix/newlib/0000775000175000017500000000000015105742312014347 5ustar bdrungbdrunglibc/src/unix/newlib/horizon/0000775000175000017500000000000015105742312016037 5ustar bdrungbdrunglibc/src/unix/newlib/horizon/mod.rs0000644000175000017500000001644715105742312017176 0ustar bdrungbdrung//! ARMv6K Nintendo 3DS C Newlib definitions use crate::off_t; use crate::prelude::*; pub type wchar_t = c_uint; pub type u_register_t = c_uint; pub type u_char = c_uchar; pub type u_short = c_ushort; pub type u_int = c_uint; pub type u_long = c_ulong; pub type ushort = c_ushort; pub type uint = c_uint; pub type ulong = c_ulong; pub type clock_t = c_ulong; pub type daddr_t = c_long; pub type caddr_t = *mut c_char; pub type sbintime_t = c_longlong; pub type sigset_t = c_ulong; s! { pub struct hostent { pub h_name: *mut c_char, pub h_aliases: *mut *mut c_char, pub h_addrtype: u16, pub h_length: u16, pub h_addr_list: *mut *mut c_char, } pub struct sockaddr { pub sa_family: crate::sa_family_t, pub sa_data: [c_char; 26usize], } pub struct sockaddr_storage { pub ss_family: crate::sa_family_t, pub __ss_padding: [c_char; 26usize], } pub struct sockaddr_in { pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } pub struct sockaddr_in6 { pub sin6_family: crate::sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_un { pub sun_len: c_uchar, pub sun_family: crate::sa_family_t, pub sun_path: [c_char; 104usize], } pub struct sched_param { pub sched_priority: c_int, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atim: crate::timespec, pub st_mtim: crate::timespec, pub st_ctim: crate::timespec, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_spare4: [c_long; 2usize], } } pub const SIGEV_NONE: c_int = 1; pub const SIGEV_SIGNAL: c_int = 2; pub const SIGEV_THREAD: c_int = 3; pub const SA_NOCLDSTOP: c_int = 1; pub const MINSIGSTKSZ: c_int = 2048; pub const SIGSTKSZ: c_int = 8192; pub const SS_ONSTACK: c_int = 1; pub const SS_DISABLE: c_int = 2; pub const SIG_SETMASK: c_int = 0; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGBUS: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGSYS: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGURG: c_int = 16; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGCONT: c_int = 19; pub const SIGCHLD: c_int = 20; pub const SIGCLD: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGIO: c_int = 23; pub const SIGPOLL: c_int = 23; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGLOST: c_int = 29; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const NSIG: c_int = 32; pub const CLOCK_ENABLED: c_uint = 1; pub const CLOCK_DISABLED: c_uint = 0; pub const CLOCK_ALLOWED: c_uint = 1; pub const CLOCK_DISALLOWED: c_uint = 0; pub const TIMER_ABSTIME: c_uint = 4; pub const SOL_SOCKET: c_int = 65535; pub const MSG_OOB: c_int = 1; pub const MSG_PEEK: c_int = 2; pub const MSG_DONTWAIT: c_int = 4; pub const MSG_DONTROUTE: c_int = 0; pub const MSG_WAITALL: c_int = 0; pub const MSG_MORE: c_int = 0; pub const MSG_NOSIGNAL: c_int = 0; pub const SOL_CONFIG: c_uint = 65534; pub const _SC_PAGESIZE: c_int = 8; pub const _SC_GETPW_R_SIZE_MAX: c_int = 51; pub const PTHREAD_STACK_MIN: size_t = 4096; pub const WNOHANG: c_int = 1; pub const POLLIN: c_short = 0x0001; pub const POLLPRI: c_short = 0x0002; pub const POLLOUT: c_short = 0x0004; pub const POLLRDNORM: c_short = 0x0040; pub const POLLWRNORM: c_short = POLLOUT; pub const POLLRDBAND: c_short = 0x0080; pub const POLLWRBAND: c_short = 0x0100; pub const POLLERR: c_short = 0x0008; pub const POLLHUP: c_short = 0x0010; pub const POLLNVAL: c_short = 0x0020; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_SERVICE: c_int = 9; pub const EAI_SYSTEM: c_int = 11; pub const EAI_BADHINTS: c_int = 12; pub const EAI_PROTOCOL: c_int = 13; pub const EAI_OVERFLOW: c_int = 14; pub const EAI_MAX: c_int = 15; pub const AF_UNIX: c_int = 1; pub const AF_INET6: c_int = 23; pub const FIONBIO: c_ulong = 1; pub const RTLD_DEFAULT: *mut c_void = 0 as *mut c_void; // For pthread get/setschedparam pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; // For getrandom() pub const GRND_NONBLOCK: c_uint = 0x1; pub const GRND_RANDOM: c_uint = 0x2; // Horizon OS works doesn't or can't hold any of this information safe_f! { pub {const} fn WIFSTOPPED(_status: c_int) -> bool { false } pub {const} fn WSTOPSIG(_status: c_int) -> c_int { 0 } pub {const} fn WIFCONTINUED(_status: c_int) -> bool { true } pub {const} fn WIFSIGNALED(_status: c_int) -> bool { false } pub {const} fn WTERMSIG(_status: c_int) -> c_int { 0 } pub {const} fn WIFEXITED(_status: c_int) -> bool { true } pub {const} fn WEXITSTATUS(_status: c_int) -> c_int { 0 } pub {const} fn WCOREDUMP(_status: c_int) -> bool { false } } extern "C" { pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(_: *mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_attr_getschedparam( attr: *const crate::pthread_attr_t, param: *mut sched_param, ) -> c_int; pub fn pthread_attr_setschedparam( attr: *mut crate::pthread_attr_t, param: *const sched_param, ) -> c_int; pub fn pthread_attr_getprocessorid_np( attr: *const crate::pthread_attr_t, processor_id: *mut c_int, ) -> c_int; pub fn pthread_attr_setprocessorid_np( attr: *mut crate::pthread_attr_t, processor_id: c_int, ) -> c_int; pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut crate::sched_param, ) -> c_int; pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn pthread_condattr_getclock( attr: *const crate::pthread_condattr_t, clock_id: *mut crate::clockid_t, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut crate::pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn pthread_getprocessorid_np() -> c_int; pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; pub fn gethostid() -> c_long; } pub use crate::unix::newlib::generic::dirent; libc/src/unix/newlib/mod.rs0000644000175000017500000007427515105742312015511 0ustar bdrungbdrunguse crate::prelude::*; pub type blkcnt_t = i32; pub type blksize_t = i32; pub type clockid_t = c_ulong; cfg_if! { if #[cfg(any(target_os = "espidf"))] { pub type dev_t = c_short; pub type ino_t = c_ushort; pub type off_t = c_long; } else if #[cfg(any(target_os = "vita"))] { pub type dev_t = c_short; pub type ino_t = c_ushort; pub type off_t = c_int; } else { pub type dev_t = u32; pub type ino_t = u32; pub type off_t = i64; } } pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u32; pub type id_t = u32; pub type key_t = c_int; pub type loff_t = c_longlong; pub type mode_t = c_uint; pub type nfds_t = u32; pub type nlink_t = c_ushort; pub type pthread_t = c_ulong; pub type pthread_key_t = c_uint; pub type rlim_t = u32; cfg_if! { if #[cfg(target_os = "horizon")] { pub type sa_family_t = u16; } else { pub type sa_family_t = u8; } } pub type socklen_t = u32; pub type speed_t = u32; pub type suseconds_t = i32; cfg_if! { if #[cfg(target_os = "espidf")] { pub type tcflag_t = u16; } else { pub type tcflag_t = c_uint; } } pub type useconds_t = u32; cfg_if! { if #[cfg(any( target_os = "horizon", all(target_os = "espidf", not(espidf_time32)) ))] { pub type time_t = c_longlong; } else { pub type time_t = i32; } } cfg_if! { if #[cfg(not(target_os = "horizon"))] { s! { pub struct hostent { pub h_name: *mut c_char, pub h_aliases: *mut *mut c_char, pub h_addrtype: c_int, pub h_length: c_int, pub h_addr_list: *mut *mut c_char, pub h_addr: *mut c_char, } } } } s! { // The order of the `ai_addr` field in this struct is crucial // for converting between the Rust and C types. pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, #[cfg(target_os = "espidf")] pub ai_addr: *mut sockaddr, pub ai_canonname: *mut c_char, #[cfg(not(any( target_os = "espidf", all(target_arch = "powerpc", target_vendor = "nintendo") )))] pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct linger { pub l_onoff: c_int, pub l_linger: c_int, } pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct pollfd { pub fd: c_int, pub events: c_int, pub revents: c_int, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_p_sign_posn: c_char, } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: fsblkcnt_t, pub f_bfree: fsblkcnt_t, pub f_bavail: fsblkcnt_t, pub f_files: fsfilcnt_t, pub f_ffree: fsfilcnt_t, pub f_favail: fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, } pub struct sigaction { pub sa_handler: extern "C" fn(arg1: c_int), pub sa_mask: sigset_t, pub sa_flags: c_int, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_flags: c_int, pub ss_size: usize, } pub struct fd_set { // Unverified fds_bits: [c_ulong; FD_SETSIZE as usize / ULONG_SIZE], } pub struct passwd { // Unverified pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct termios { // Unverified pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: crate::cc_t, pub c_cc: [crate::cc_t; crate::NCCS], #[cfg(target_os = "espidf")] pub c_ispeed: u32, #[cfg(target_os = "espidf")] pub c_ospeed: u32, } pub struct sem_t { // Unverified __size: [c_char; 16], } pub struct Dl_info { // Unverified pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct utsname { // Unverified pub sysname: [c_char; 65], pub nodename: [c_char; 65], pub release: [c_char; 65], pub version: [c_char; 65], pub machine: [c_char; 65], pub domainname: [c_char; 65], } pub struct cpu_set_t { // Unverified bits: [u32; 32], } pub struct pthread_attr_t { // Unverified #[cfg(not(target_os = "espidf"))] __size: [u8; __SIZEOF_PTHREAD_ATTR_T], #[cfg(target_os = "espidf")] pub is_initialized: i32, #[cfg(target_os = "espidf")] pub stackaddr: *mut c_void, #[cfg(target_os = "espidf")] pub stacksize: i32, #[cfg(target_os = "espidf")] pub contentionscope: i32, #[cfg(target_os = "espidf")] pub inheritsched: i32, #[cfg(target_os = "espidf")] pub schedpolicy: i32, #[cfg(target_os = "espidf")] pub schedparam: i32, #[cfg(target_os = "espidf")] pub detachstate: i32, } pub struct pthread_rwlockattr_t { // Unverified __size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T], } #[cfg_attr( all( target_pointer_width = "32", any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc") ), repr(align(4)) )] #[cfg_attr( any( target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc")) ), repr(align(8)) )] pub struct pthread_mutex_t { // Unverified size: [u8; crate::__SIZEOF_PTHREAD_MUTEX_T], } #[cfg_attr( all( target_pointer_width = "32", any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc") ), repr(align(4)) )] #[cfg_attr( any( target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc")) ), repr(align(8)) )] pub struct pthread_rwlock_t { // Unverified size: [u8; crate::__SIZEOF_PTHREAD_RWLOCK_T], } #[cfg_attr( any( target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64" ), repr(align(4)) )] #[cfg_attr( not(any( target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64" )), repr(align(8)) )] pub struct pthread_mutexattr_t { // Unverified size: [u8; crate::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[repr(align(8))] pub struct pthread_cond_t { // Unverified size: [u8; crate::__SIZEOF_PTHREAD_COND_T], } #[repr(align(4))] pub struct pthread_condattr_t { // Unverified size: [u8; crate::__SIZEOF_PTHREAD_CONDATTR_T], } } // unverified constants pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_RWLOCK_T], }; cfg_if! { if #[cfg(target_os = "espidf")] { pub const NCCS: usize = 11; } else { pub const NCCS: usize = 32; } } cfg_if! { if #[cfg(target_os = "espidf")] { const __PTHREAD_INITIALIZER_BYTE: u8 = 0xff; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 12; pub const __SIZEOF_PTHREAD_COND_T: usize = 4; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 12; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; } else if #[cfg(target_os = "vita")] { const __PTHREAD_INITIALIZER_BYTE: u8 = 0xff; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_COND_T: usize = 4; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 4; } else if #[cfg(target_os = "rtems")] { const __PTHREAD_INITIALIZER_BYTE: u8 = 0x00; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 96; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 64; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 24; pub const __SIZEOF_PTHREAD_COND_T: usize = 28; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 24; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; } else { const __PTHREAD_INITIALIZER_BYTE: u8 = 0; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 56; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; } } pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __PTHREAD_MUTEX_HAVE_PREV: usize = 1; pub const __PTHREAD_RWLOCK_INT_FLAGS_SHARED: usize = 1; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; cfg_if! { if #[cfg(any(target_os = "horizon", target_os = "espidf"))] { pub const FD_SETSIZE: usize = 64; } else if #[cfg(target_os = "vita")] { pub const FD_SETSIZE: usize = 256; } else { pub const FD_SETSIZE: usize = 1024; } } // intentionally not public, only used for fd_set const ULONG_SIZE: usize = 32; // Other constants pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const EDEADLK: c_int = 45; pub const ENOLCK: c_int = 46; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENOLINK: c_int = 67; pub const EPROTO: c_int = 71; pub const EMULTIHOP: c_int = 74; pub const EBADMSG: c_int = 77; pub const EFTYPE: c_int = 79; pub const ENOSYS: c_int = 88; pub const ENOTEMPTY: c_int = 90; pub const ENAMETOOLONG: c_int = 91; pub const ELOOP: c_int = 92; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EAFNOSUPPORT: c_int = 106; pub const EPROTOTYPE: c_int = 107; pub const ENOTSOCK: c_int = 108; pub const ENOPROTOOPT: c_int = 109; pub const ECONNREFUSED: c_int = 111; pub const EADDRINUSE: c_int = 112; pub const ECONNABORTED: c_int = 113; pub const ENETUNREACH: c_int = 114; pub const ENETDOWN: c_int = 115; pub const ETIMEDOUT: c_int = 116; pub const EHOSTDOWN: c_int = 117; pub const EHOSTUNREACH: c_int = 118; pub const EINPROGRESS: c_int = 119; pub const EALREADY: c_int = 120; pub const EDESTADDRREQ: c_int = 121; pub const EMSGSIZE: c_int = 122; pub const EPROTONOSUPPORT: c_int = 123; pub const EADDRNOTAVAIL: c_int = 125; pub const ENETRESET: c_int = 126; pub const EISCONN: c_int = 127; pub const ENOTCONN: c_int = 128; pub const ETOOMANYREFS: c_int = 129; pub const EDQUOT: c_int = 132; pub const ESTALE: c_int = 133; pub const ENOTSUP: c_int = 134; pub const EILSEQ: c_int = 138; pub const EOVERFLOW: c_int = 139; pub const ECANCELED: c_int = 140; pub const ENOTRECOVERABLE: c_int = 141; pub const EOWNERDEAD: c_int = 142; pub const EWOULDBLOCK: c_int = 11; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const F_GETOWN: c_int = 5; pub const F_SETOWN: c_int = 6; pub const F_GETLK: c_int = 7; pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; pub const F_RGETLK: c_int = 10; pub const F_RSETLK: c_int = 11; pub const F_CNVT: c_int = 12; pub const F_RSETLKW: c_int = 13; pub const F_DUPFD_CLOEXEC: c_int = 14; pub const O_RDONLY: c_int = 0; pub const O_WRONLY: c_int = 1; pub const O_RDWR: c_int = 2; pub const O_APPEND: c_int = 8; pub const O_CREAT: c_int = 512; pub const O_TRUNC: c_int = 1024; pub const O_EXCL: c_int = 2048; pub const O_SYNC: c_int = 8192; pub const O_NONBLOCK: c_int = 16384; pub const O_ACCMODE: c_int = 3; cfg_if! { if #[cfg(target_os = "espidf")] { pub const O_CLOEXEC: c_int = 0x40000; } else { pub const O_CLOEXEC: c_int = 0x80000; } } pub const RTLD_LAZY: c_int = 0x1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const FIOCLEX: c_ulong = 0x20006601; pub const FIONCLEX: c_ulong = 0x20006602; pub const S_BLKSIZE: crate::mode_t = 1024; pub const S_IREAD: crate::mode_t = 0o0400; pub const S_IWRITE: crate::mode_t = 0o0200; pub const S_IEXEC: crate::mode_t = 0o0100; pub const S_ENFMT: crate::mode_t = 0o2000; pub const S_IFMT: crate::mode_t = 0o17_0000; pub const S_IFDIR: crate::mode_t = 0o4_0000; pub const S_IFCHR: crate::mode_t = 0o2_0000; pub const S_IFBLK: crate::mode_t = 0o6_0000; pub const S_IFREG: crate::mode_t = 0o10_0000; pub const S_IFLNK: crate::mode_t = 0o12_0000; pub const S_IFSOCK: crate::mode_t = 0o14_0000; pub const S_IFIFO: crate::mode_t = 0o1_0000; pub const S_IRUSR: crate::mode_t = 0o0400; pub const S_IWUSR: crate::mode_t = 0o0200; pub const S_IXUSR: crate::mode_t = 0o0100; pub const S_IRGRP: crate::mode_t = 0o0040; pub const S_IWGRP: crate::mode_t = 0o0020; pub const S_IXGRP: crate::mode_t = 0o0010; pub const S_IROTH: crate::mode_t = 0o0004; pub const S_IWOTH: crate::mode_t = 0o0002; pub const S_IXOTH: crate::mode_t = 0o0001; pub const SOL_TCP: c_int = 6; pub const PF_UNSPEC: c_int = 0; pub const PF_INET: c_int = 2; cfg_if! { if #[cfg(target_os = "espidf")] { pub const PF_INET6: c_int = 10; } else { pub const PF_INET6: c_int = 23; } } pub const AF_UNSPEC: c_int = 0; pub const AF_INET: c_int = 2; pub const CLOCK_REALTIME: crate::clockid_t = 1; pub const CLOCK_MONOTONIC: crate::clockid_t = 4; pub const CLOCK_BOOTTIME: crate::clockid_t = 4; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const SO_BINTIME: c_int = 0x2000; pub const SO_NO_OFFLOAD: c_int = 0x4000; pub const SO_NO_DDP: c_int = 0x8000; pub const SO_REUSEPORT_LB: c_int = 0x10000; pub const SO_LABEL: c_int = 0x1009; pub const SO_PEERLABEL: c_int = 0x1010; pub const SO_LISTENQLIMIT: c_int = 0x1011; pub const SO_LISTENQLEN: c_int = 0x1012; pub const SO_LISTENINCQLEN: c_int = 0x1013; pub const SO_SETFIB: c_int = 0x1014; pub const SO_USER_COOKIE: c_int = 0x1015; pub const SO_PROTOCOL: c_int = 0x1016; pub const SO_PROTOTYPE: c_int = SO_PROTOCOL; pub const SO_VENDOR: c_int = 0x80000000; pub const SO_DEBUG: c_int = 0x01; pub const SO_ACCEPTCONN: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_USELOOPBACK: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_TIMESTAMP: c_int = 0x0400; pub const SO_NOSIGPIPE: c_int = 0x0800; pub const SO_ACCEPTFILTER: c_int = 0x1000; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVLOWAT: c_int = 0x1004; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_RCVTIMEO: c_int = 0x1006; cfg_if! { if #[cfg(target_os = "horizon")] { pub const SO_ERROR: c_int = 0x1009; } else { pub const SO_ERROR: c_int = 0x1007; } } pub const SO_TYPE: c_int = 0x1008; pub const SOCK_CLOEXEC: c_int = O_CLOEXEC; pub const INET_ADDRSTRLEN: c_int = 16; // https://github.com/bminor/newlib/blob/HEAD/newlib/libc/sys/linux/include/net/if.h#L121 pub const IFF_UP: c_int = 0x1; // interface is up pub const IFF_BROADCAST: c_int = 0x2; // broadcast address valid pub const IFF_DEBUG: c_int = 0x4; // turn on debugging pub const IFF_LOOPBACK: c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: c_int = 0x10; // interface is point-to-point link pub const IFF_NOTRAILERS: c_int = 0x20; // avoid use of trailers pub const IFF_RUNNING: c_int = 0x40; // resources allocated pub const IFF_NOARP: c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: c_int = 0x100; // receive all packets pub const IFF_ALLMULTI: c_int = 0x200; // receive all multicast packets pub const IFF_OACTIVE: c_int = 0x400; // transmission in progress pub const IFF_SIMPLEX: c_int = 0x800; // can't hear own transmissions pub const IFF_LINK0: c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: c_int = 0x4000; // per link layer defined bit pub const IFF_ALTPHYS: c_int = IFF_LINK2; // use alternate physical connection pub const IFF_MULTICAST: c_int = 0x8000; // supports multicast cfg_if! { if #[cfg(target_os = "vita")] { pub const TCP_NODELAY: c_int = 1; pub const TCP_MAXSEG: c_int = 2; } else if #[cfg(target_os = "espidf")] { pub const TCP_NODELAY: c_int = 1; pub const TCP_MAXSEG: c_int = 8194; } else { pub const TCP_NODELAY: c_int = 8193; pub const TCP_MAXSEG: c_int = 8194; } } pub const TCP_NOPUSH: c_int = 4; pub const TCP_NOOPT: c_int = 8; cfg_if! { if #[cfg(target_os = "espidf")] { pub const TCP_KEEPIDLE: c_int = 3; pub const TCP_KEEPINTVL: c_int = 4; pub const TCP_KEEPCNT: c_int = 5; } else { pub const TCP_KEEPIDLE: c_int = 256; pub const TCP_KEEPINTVL: c_int = 512; pub const TCP_KEEPCNT: c_int = 1024; } } cfg_if! { if #[cfg(target_os = "horizon")] { pub const IP_TOS: c_int = 7; } else if #[cfg(target_os = "espidf")] { pub const IP_TOS: c_int = 1; } else { pub const IP_TOS: c_int = 3; } } cfg_if! { if #[cfg(target_os = "vita")] { pub const IP_TTL: c_int = 4; } else if #[cfg(target_os = "espidf")] { pub const IP_TTL: c_int = 2; } else { pub const IP_TTL: c_int = 8; } } cfg_if! { if #[cfg(target_os = "espidf")] { pub const IP_MULTICAST_IF: c_int = 6; pub const IP_MULTICAST_TTL: c_int = 5; pub const IP_MULTICAST_LOOP: c_int = 7; } else { pub const IP_MULTICAST_IF: c_int = 9; pub const IP_MULTICAST_TTL: c_int = 10; pub const IP_MULTICAST_LOOP: c_int = 11; } } cfg_if! { if #[cfg(target_os = "vita")] { pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; } else if #[cfg(target_os = "espidf")] { pub const IP_ADD_MEMBERSHIP: c_int = 3; pub const IP_DROP_MEMBERSHIP: c_int = 4; } else { pub const IP_ADD_MEMBERSHIP: c_int = 11; pub const IP_DROP_MEMBERSHIP: c_int = 12; } } pub const IPV6_UNICAST_HOPS: c_int = 4; cfg_if! { if #[cfg(target_os = "espidf")] { pub const IPV6_MULTICAST_IF: c_int = 768; pub const IPV6_MULTICAST_HOPS: c_int = 769; pub const IPV6_MULTICAST_LOOP: c_int = 770; } else { pub const IPV6_MULTICAST_IF: c_int = 9; pub const IPV6_MULTICAST_HOPS: c_int = 10; pub const IPV6_MULTICAST_LOOP: c_int = 11; } } pub const IPV6_V6ONLY: c_int = 27; pub const IPV6_JOIN_GROUP: c_int = 12; pub const IPV6_LEAVE_GROUP: c_int = 13; pub const IPV6_ADD_MEMBERSHIP: c_int = 12; pub const IPV6_DROP_MEMBERSHIP: c_int = 13; cfg_if! { if #[cfg(target_os = "espidf")] { pub const HOST_NOT_FOUND: c_int = 210; pub const NO_DATA: c_int = 211; pub const NO_RECOVERY: c_int = 212; pub const TRY_AGAIN: c_int = 213; } else { pub const HOST_NOT_FOUND: c_int = 1; pub const NO_DATA: c_int = 2; pub const NO_RECOVERY: c_int = 3; pub const TRY_AGAIN: c_int = 4; } } pub const NO_ADDRESS: c_int = 2; pub const AI_PASSIVE: c_int = 1; pub const AI_CANONNAME: c_int = 2; pub const AI_NUMERICHOST: c_int = 4; cfg_if! { if #[cfg(target_os = "espidf")] { pub const AI_NUMERICSERV: c_int = 8; pub const AI_ADDRCONFIG: c_int = 64; } else { pub const AI_NUMERICSERV: c_int = 0; pub const AI_ADDRCONFIG: c_int = 0; } } pub const NI_MAXHOST: c_int = 1025; pub const NI_MAXSERV: c_int = 32; pub const NI_NOFQDN: c_int = 1; pub const NI_NUMERICHOST: c_int = 2; pub const NI_NAMEREQD: c_int = 4; cfg_if! { if #[cfg(target_os = "espidf")] { pub const NI_NUMERICSERV: c_int = 8; pub const NI_DGRAM: c_int = 16; } else { pub const NI_NUMERICSERV: c_int = 0; pub const NI_DGRAM: c_int = 0; } } cfg_if! { // Defined in vita/mod.rs for "vita" if #[cfg(target_os = "espidf")] { pub const EAI_FAMILY: c_int = 204; pub const EAI_MEMORY: c_int = 203; pub const EAI_NONAME: c_int = 200; pub const EAI_SOCKTYPE: c_int = 10; } else if #[cfg(not(target_os = "vita"))] { pub const EAI_FAMILY: c_int = -303; pub const EAI_MEMORY: c_int = -304; pub const EAI_NONAME: c_int = -305; pub const EAI_SOCKTYPE: c_int = -307; } } pub const EXIT_SUCCESS: c_int = 0; pub const EXIT_FAILURE: c_int = 1; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; f! { pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] |= 1 << (fd % bits); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } extern "C" { pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; #[cfg_attr(target_os = "linux", link_name = "__xpg_strerror_r")] pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr(target_os = "espidf", link_name = "lwip_bind")] pub fn bind(fd: c_int, addr: *const sockaddr, len: socklen_t) -> c_int; pub fn clock_settime(clock_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn clock_gettime(clock_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_getres(clock_id: crate::clockid_t, res: *mut crate::timespec) -> c_int; #[cfg_attr(target_os = "espidf", link_name = "lwip_close")] pub fn closesocket(sockfd: c_int) -> c_int; pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] #[cfg_attr(target_os = "espidf", link_name = "lwip_recvfrom")] pub fn recvfrom( fd: c_int, buf: *mut c_void, n: usize, flags: c_int, addr: *mut sockaddr, addr_len: *mut socklen_t, ) -> isize; #[cfg(not(all(target_arch = "powerpc", target_vendor = "nintendo")))] pub fn getnameinfo( sa: *const sockaddr, salen: socklen_t, host: *mut c_char, hostlen: socklen_t, serv: *mut c_char, servlen: socklen_t, flags: c_int, ) -> c_int; pub fn memalign(align: size_t, size: size_t) -> *mut c_void; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn fexecve(fd: c_int, argv: *const *const c_char, envp: *const *const c_char) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn getdtablesize() -> c_int; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn uname(buf: *mut crate::utsname) -> c_int; } mod generic; cfg_if! { if #[cfg(target_os = "espidf")] { mod espidf; pub use self::espidf::*; } else if #[cfg(target_os = "horizon")] { mod horizon; pub use self::horizon::*; } else if #[cfg(target_os = "vita")] { mod vita; pub use self::vita::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else { // Only tested on ARM so far. Other platforms might have different // definitions for types and constants. pub use target_arch_not_implemented; } } cfg_if! { if #[cfg(target_os = "rtems")] { mod rtems; pub use self::rtems::*; } } libc/src/unix/newlib/aarch64/0000775000175000017500000000000015105742312015577 5ustar bdrungbdrunglibc/src/unix/newlib/aarch64/mod.rs0000644000175000017500000000242115105742312016721 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = c_long; pub type wchar_t = u32; s! { pub struct sockaddr { pub sa_len: u8, pub sa_family: crate::sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: crate::sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } } pub const AF_INET6: c_int = 23; pub const FIONBIO: c_ulong = 1; pub const POLLIN: c_short = 0x1; pub const POLLPRI: c_short = 0x2; pub const POLLOUT: c_short = 0x4; pub const POLLERR: c_short = 0x8; pub const POLLHUP: c_short = 0x10; pub const POLLNVAL: c_short = 0x20; pub const SOL_SOCKET: c_int = 65535; pub const MSG_OOB: c_int = 1; pub const MSG_PEEK: c_int = 2; pub const MSG_DONTWAIT: c_int = 4; pub const MSG_DONTROUTE: c_int = 0; pub const MSG_WAITALL: c_int = 0; pub const MSG_MORE: c_int = 0; pub const MSG_NOSIGNAL: c_int = 0; pub use crate::unix::newlib::generic::{dirent, sigset_t, stat}; libc/src/unix/newlib/espidf/0000775000175000017500000000000015105742312015621 5ustar bdrungbdrunglibc/src/unix/newlib/espidf/mod.rs0000644000175000017500000000640315105742312016747 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = c_ulong; pub type wchar_t = u32; s! { pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct sockaddr_un { pub sun_family: crate::sa_family_t, pub sun_path: [c_char; 108], } pub struct sockaddr { pub sa_len: u8, pub sa_family: crate::sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: crate::sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } pub struct sockaddr_storage { pub s2_len: u8, pub ss_family: crate::sa_family_t, pub s2_data1: [c_char; 2], pub s2_data2: [u32; 3], pub s2_data3: [u32; 3], } } pub const AF_UNIX: c_int = 1; pub const AF_INET6: c_int = 10; pub const FIONBIO: c_ulong = 2147772030; pub const POLLIN: c_short = 1 << 0; pub const POLLRDNORM: c_short = 1 << 1; pub const POLLRDBAND: c_short = 1 << 2; pub const POLLPRI: c_short = POLLRDBAND; pub const POLLOUT: c_short = 1 << 3; pub const POLLWRNORM: c_short = POLLOUT; pub const POLLWRBAND: c_short = 1 << 4; pub const POLLERR: c_short = 1 << 5; pub const POLLHUP: c_short = 1 << 6; pub const SOL_SOCKET: c_int = 0xfff; pub const MSG_OOB: c_int = 0x04; pub const MSG_PEEK: c_int = 0x01; pub const MSG_DONTWAIT: c_int = 0x08; pub const MSG_DONTROUTE: c_int = 0x4; pub const MSG_WAITALL: c_int = 0x02; pub const MSG_MORE: c_int = 0x10; pub const MSG_NOSIGNAL: c_int = 0x20; pub const MSG_TRUNC: c_int = 0x04; pub const MSG_CTRUNC: c_int = 0x08; pub const MSG_EOR: c_int = 0x08; pub const PTHREAD_STACK_MIN: size_t = 768; pub const SIGABRT: c_int = 6; pub const SIGFPE: c_int = 8; pub const SIGILL: c_int = 4; pub const SIGINT: c_int = 2; pub const SIGSEGV: c_int = 11; pub const SIGTERM: c_int = 15; pub const SIGHUP: c_int = 1; pub const SIGQUIT: c_int = 3; pub const NSIG: size_t = 32; extern "C" { pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(_: *mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; pub fn gethostname(name: *mut c_char, namelen: ssize_t); #[link_name = "lwip_sendmsg"] pub fn sendmsg(s: c_int, msg: *const crate::msghdr, flags: c_int) -> ssize_t; #[link_name = "lwip_recvmsg"] pub fn recvmsg(s: c_int, msg: *mut crate::msghdr, flags: c_int) -> ssize_t; pub fn eventfd(initval: c_uint, flags: c_int) -> c_int; } pub use crate::unix::newlib::generic::{dirent, sigset_t, stat}; libc/src/unix/newlib/powerpc/0000775000175000017500000000000015105742312016026 5ustar bdrungbdrunglibc/src/unix/newlib/powerpc/mod.rs0000644000175000017500000000045715105742312017157 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = c_ulong; pub type wchar_t = c_int; pub use crate::unix::newlib::generic::{dirent, sigset_t, stat}; // the newlib shipped with devkitPPC does not support the following components: // - sockaddr // - AF_INET6 // - FIONBIO // - POLL* // - SOL_SOCKET // - MSG_* libc/src/unix/newlib/arm/0000775000175000017500000000000015105742312015126 5ustar bdrungbdrunglibc/src/unix/newlib/arm/mod.rs0000644000175000017500000000247215105742312016256 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = c_long; pub type wchar_t = u32; s! { pub struct sockaddr { pub sa_family: crate::sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in6 { pub sin6_family: crate::sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_in { pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_storage { pub ss_family: crate::sa_family_t, pub __ss_padding: [u8; 26], } } pub const AF_INET6: c_int = 23; pub const FIONBIO: c_ulong = 1; pub const POLLIN: c_short = 0x1; pub const POLLPRI: c_short = 0x2; pub const POLLHUP: c_short = 0x4; pub const POLLERR: c_short = 0x8; pub const POLLOUT: c_short = 0x10; pub const POLLNVAL: c_short = 0x20; pub const SOL_SOCKET: c_int = 65535; pub const MSG_OOB: c_int = 1; pub const MSG_PEEK: c_int = 2; pub const MSG_DONTWAIT: c_int = 4; pub const MSG_DONTROUTE: c_int = 0; pub const MSG_WAITALL: c_int = 0; pub const MSG_MORE: c_int = 0; pub const MSG_NOSIGNAL: c_int = 0; pub use crate::unix::newlib::generic::{dirent, sigset_t, stat}; libc/src/unix/newlib/generic.rs0000644000175000017500000000177615105742312016342 0ustar bdrungbdrung//! Common types used by most newlib platforms use crate::off_t; use crate::prelude::*; s! { pub struct sigset_t { #[cfg(target_os = "horizon")] __val: [c_ulong; 16], #[cfg(not(target_os = "horizon"))] __val: u32, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atime: crate::time_t, pub st_spare1: c_long, pub st_mtime: crate::time_t, pub st_spare2: c_long, pub st_ctime: crate::time_t, pub st_spare3: c_long, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_spare4: [c_long; 2usize], } pub struct dirent { pub d_ino: crate::ino_t, pub d_type: c_uchar, pub d_name: [c_char; 256usize], } } libc/src/unix/newlib/rtems/0000775000175000017500000000000015105742312015501 5ustar bdrungbdrunglibc/src/unix/newlib/rtems/mod.rs0000644000175000017500000000761215105742312016632 0ustar bdrungbdrung// defined in architecture specific module use crate::prelude::*; s! { pub struct sockaddr_un { pub sun_family: crate::sa_family_t, pub sun_path: [c_char; 108usize], } } pub const AF_UNIX: c_int = 1; pub const RTLD_DEFAULT: *mut c_void = -2isize as *mut c_void; pub const UTIME_OMIT: c_long = -1; pub const AT_FDCWD: c_int = -2; pub const O_DIRECTORY: c_int = 0x200000; pub const O_NOFOLLOW: c_int = 0x100000; pub const AT_EACCESS: c_int = 1; pub const AT_SYMLINK_NOFOLLOW: c_int = 2; pub const AT_SYMLINK_FOLLOW: c_int = 4; pub const AT_REMOVEDIR: c_int = 8; // signal.h pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const SIG_SETMASK: c_int = 0; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGBUS: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGSYS: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGURG: c_int = 16; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGCONT: c_int = 19; pub const SIGCHLD: c_int = 20; pub const SIGCLD: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGIO: c_int = 23; pub const SIGWINCH: c_int = 24; pub const SIGUSR1: c_int = 25; pub const SIGUSR2: c_int = 26; pub const SIGRTMIN: c_int = 27; pub const SIGRTMAX: c_int = 31; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SA_NOCLDSTOP: c_ulong = 0x00000001; pub const SA_SIGINFO: c_ulong = 0x00000002; pub const SA_ONSTACK: c_ulong = 0x00000004; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_SERVICE: c_int = 9; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 14; pub const _SC_PAGESIZE: c_int = 8; pub const _SC_GETPW_R_SIZE_MAX: c_int = 51; pub const PTHREAD_STACK_MIN: size_t = 0; // sys/wait.h pub const WNOHANG: c_int = 1; pub const WUNTRACED: c_int = 2; // sys/socket.h pub const SOMAXCONN: c_int = 128; safe_f! { pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: c_int) -> c_int { // (status >> 8) & 0xff WEXITSTATUS(status) } pub {const} fn WIFSIGNALED(status: c_int) -> bool { ((status & 0x7f) > 0) && ((status & 0x7f) < 0x7f) } pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0x7f } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0xff) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0xff } // RTEMS doesn't have native WIFCONTINUED. pub {const} fn WIFCONTINUED(_status: c_int) -> bool { true } // RTEMS doesn't have native WCOREDUMP. pub {const} fn WCOREDUMP(_status: c_int) -> bool { false } } extern "C" { pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(_: *mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut crate::pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn arc4random_buf(buf: *mut core::ffi::c_void, nbytes: size_t); pub fn setgroups(ngroups: c_int, grouplist: *const crate::gid_t) -> c_int; } libc/src/unix/newlib/vita/0000775000175000017500000000000015105742312015312 5ustar bdrungbdrunglibc/src/unix/newlib/vita/mod.rs0000644000175000017500000001465315105742312016446 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type clock_t = c_long; pub type wchar_t = u32; pub type sigset_t = c_ulong; s! { pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct sockaddr { pub sa_len: u8, pub sa_family: crate::sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: crate::sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_vport: crate::in_port_t, pub sin6_scope_id: u32, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_vport: crate::in_port_t, pub sin_zero: [u8; 6], } pub struct sockaddr_un { pub ss_len: u8, pub sun_family: crate::sa_family_t, pub sun_path: [c_char; 108usize], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: crate::sa_family_t, pub __ss_pad1: [u8; 2], pub __ss_align: i64, pub __ss_pad2: [u8; 116], } pub struct sched_param { pub sched_priority: c_int, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atime: crate::time_t, pub st_mtime: crate::time_t, pub st_ctime: crate::time_t, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_spare4: [c_long; 2usize], } #[repr(align(8))] pub struct dirent { __offset: [u8; 88], pub d_name: [c_char; 256usize], __pad: [u8; 8], } } pub const AF_UNIX: c_int = 1; pub const AF_INET6: c_int = 24; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_SEQPACKET: c_int = 5; pub const SOMAXCONN: c_int = 128; pub const FIONBIO: c_ulong = 1; pub const POLLIN: c_short = 0x0001; pub const POLLPRI: c_short = POLLIN; pub const POLLOUT: c_short = 0x0004; pub const POLLRDNORM: c_short = POLLIN; pub const POLLRDBAND: c_short = POLLIN; pub const POLLWRNORM: c_short = POLLOUT; pub const POLLWRBAND: c_short = POLLOUT; pub const POLLERR: c_short = 0x0008; pub const POLLHUP: c_short = 0x0010; pub const POLLNVAL: c_short = 0x0020; pub const RTLD_DEFAULT: *mut c_void = 0 as *mut c_void; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_NONBLOCK: c_int = 0x1100; pub const MSG_OOB: c_int = 0x1; pub const MSG_PEEK: c_int = 0x2; pub const MSG_DONTROUTE: c_int = 0x4; pub const MSG_EOR: c_int = 0x8; pub const MSG_TRUNC: c_int = 0x10; pub const MSG_CTRUNC: c_int = 0x20; pub const MSG_WAITALL: c_int = 0x40; pub const MSG_DONTWAIT: c_int = 0x80; pub const MSG_BCAST: c_int = 0x100; pub const MSG_MCAST: c_int = 0x200; pub const UTIME_OMIT: c_long = -1; pub const AT_FDCWD: c_int = -2; pub const O_DIRECTORY: c_int = 0x200000; pub const O_NOFOLLOW: c_int = 0x100000; pub const AT_EACCESS: c_int = 1; pub const AT_SYMLINK_NOFOLLOW: c_int = 2; pub const AT_SYMLINK_FOLLOW: c_int = 4; pub const AT_REMOVEDIR: c_int = 8; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGBUS: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGSYS: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const EAI_BADFLAGS: c_int = -1; pub const EAI_NONAME: c_int = -2; pub const EAI_AGAIN: c_int = -3; pub const EAI_FAIL: c_int = -4; pub const EAI_NODATA: c_int = -5; pub const EAI_FAMILY: c_int = -6; pub const EAI_SOCKTYPE: c_int = -7; pub const EAI_SERVICE: c_int = -8; pub const EAI_ADDRFAMILY: c_int = -9; pub const EAI_MEMORY: c_int = -10; pub const EAI_SYSTEM: c_int = -11; pub const EAI_OVERFLOW: c_int = -12; pub const _SC_PAGESIZE: c_int = 8; pub const _SC_GETPW_R_SIZE_MAX: c_int = 51; pub const PTHREAD_STACK_MIN: size_t = 32 * 1024; pub const IP_HDRINCL: c_int = 2; extern "C" { pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn sendmsg(s: c_int, msg: *const crate::msghdr, flags: c_int) -> ssize_t; pub fn recvmsg(s: c_int, msg: *mut crate::msghdr, flags: c_int) -> ssize_t; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(_: *mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_attr_getschedparam( attr: *const crate::pthread_attr_t, param: *mut sched_param, ) -> c_int; pub fn pthread_attr_setschedparam( attr: *mut crate::pthread_attr_t, param: *const sched_param, ) -> c_int; pub fn pthread_attr_getprocessorid_np( attr: *const crate::pthread_attr_t, processor_id: *mut c_int, ) -> c_int; pub fn pthread_attr_setprocessorid_np( attr: *mut crate::pthread_attr_t, processor_id: c_int, ) -> c_int; pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut crate::sched_param, ) -> c_int; pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn pthread_condattr_getclock( attr: *const crate::pthread_condattr_t, clock_id: *mut crate::clockid_t, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut crate::pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn pthread_getprocessorid_np() -> c_int; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; } libc/src/unix/solarish/0000775000175000017500000000000015105742312014713 5ustar bdrungbdrunglibc/src/unix/solarish/mod.rs0000644000175000017500000033114615105742312016046 0ustar bdrungbdrunguse core::mem::size_of; use crate::prelude::*; pub type caddr_t = *mut c_char; pub type clockid_t = c_int; pub type blkcnt_t = c_long; pub type clock_t = c_long; pub type daddr_t = c_long; pub type dev_t = c_ulong; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type ino_t = c_ulong; pub type key_t = c_int; pub type major_t = c_uint; pub type minor_t = c_uint; pub type mode_t = c_uint; pub type nlink_t = c_uint; pub type rlim_t = c_ulong; pub type speed_t = c_uint; pub type tcflag_t = c_uint; pub type time_t = c_long; pub type timer_t = c_int; pub type wchar_t = c_int; pub type nfds_t = c_ulong; pub type projid_t = c_int; pub type zoneid_t = c_int; pub type psetid_t = c_int; pub type processorid_t = c_int; pub type chipid_t = c_int; pub type ctid_t = crate::id_t; pub type suseconds_t = c_long; pub type off_t = c_long; pub type useconds_t = c_uint; pub type socklen_t = c_uint; pub type sa_family_t = u16; pub type pthread_t = c_uint; pub type pthread_key_t = c_uint; pub type thread_t = c_uint; pub type blksize_t = c_int; pub type nl_item = c_int; pub type mqd_t = *mut c_void; pub type id_t = c_int; pub type idtype_t = c_uint; pub type shmatt_t = c_ulong; pub type lgrp_id_t = crate::id_t; pub type lgrp_mem_size_t = c_longlong; pub type lgrp_cookie_t = crate::uintptr_t; pub type lgrp_content_t = c_uint; pub type lgrp_lat_between_t = c_uint; pub type lgrp_mem_size_flag_t = c_uint; pub type lgrp_view_t = c_uint; pub type posix_spawnattr_t = *mut c_void; pub type posix_spawn_file_actions_t = *mut c_void; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum ucred_t {} impl Copy for ucred_t {} impl Clone for ucred_t { fn clone(&self) -> ucred_t { *self } } s! { pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct ipc_perm { pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub seq: c_uint, pub key: crate::key_t, } pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, pub __sin6_src_id: u32, } pub struct in_pktinfo { pub ipi_ifindex: c_uint, pub ipi_spec_dst: crate::in_addr, pub ipi_addr: crate::in_addr, } pub struct in6_pktinfo { pub ipi6_addr: crate::in6_addr, pub ipi6_ifindex: c_uint, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_age: *mut c_char, pub pw_comment: *mut c_char, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: u64, pub ifa_addr: *mut crate::sockaddr, pub ifa_netmask: *mut crate::sockaddr, pub ifa_dstaddr: *mut crate::sockaddr, pub ifa_data: *mut c_void, } pub struct itimerspec { pub it_interval: crate::timespec, pub it_value: crate::timespec, } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct pthread_attr_t { __pthread_attrp: *mut c_void, } pub struct pthread_mutex_t { __pthread_mutex_flag1: u16, __pthread_mutex_flag2: u8, __pthread_mutex_ceiling: u8, __pthread_mutex_type: u16, __pthread_mutex_magic: u16, __pthread_mutex_lock: u64, __pthread_mutex_data: u64, } pub struct pthread_mutexattr_t { __pthread_mutexattrp: *mut c_void, } pub struct pthread_cond_t { __pthread_cond_flag: [u8; 4], __pthread_cond_type: u16, __pthread_cond_magic: u16, __pthread_cond_data: u64, } pub struct pthread_condattr_t { __pthread_condattrp: *mut c_void, } pub struct pthread_rwlock_t { __pthread_rwlock_readers: i32, __pthread_rwlock_type: u16, __pthread_rwlock_magic: u16, __pthread_rwlock_mutex: crate::pthread_mutex_t, __pthread_rwlock_readercv: crate::pthread_cond_t, __pthread_rwlock_writercv: crate::pthread_cond_t, } pub struct pthread_rwlockattr_t { __pthread_rwlockattrp: *mut c_void, } pub struct dirent { pub d_ino: crate::ino_t, pub d_off: off_t, pub d_reclen: u16, pub d_name: [c_char; 3], } pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, __unused1: *mut c_void, __unused2: c_int, #[cfg(target_os = "illumos")] __unused3: c_int, #[cfg(target_os = "illumos")] __unused4: c_int, #[cfg(target_os = "illumos")] __unused5: *mut c_void, #[cfg(target_os = "illumos")] __unused6: *mut c_void, #[cfg(target_os = "illumos")] __unused7: *mut c_void, #[cfg(target_os = "illumos")] __unused8: *mut c_void, #[cfg(target_os = "illumos")] __unused9: *mut c_void, #[cfg(target_os = "illumos")] __unused10: *mut c_void, } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, #[cfg(target_arch = "sparc64")] __sparcv9_pad: c_int, pub ai_addrlen: crate::socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut addrinfo, } pub struct sigset_t { bits: [u32; 4], } pub struct sigaction { pub sa_flags: c_int, pub sa_sigaction: crate::sighandler_t, pub sa_mask: sigset_t, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_basetype: [c_char; 16], pub f_flag: c_ulong, pub f_namemax: c_ulong, pub f_fstr: [c_char; 32], } pub struct sendfilevec_t { pub sfv_fd: c_int, pub sfv_flag: c_uint, pub sfv_off: off_t, pub sfv_len: size_t, } pub struct sched_param { pub sched_priority: c_int, sched_pad: [c_int; 8], } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_size: off_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_fstype: [c_char; _ST_FSTYPSZ as usize], } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_cc: [crate::cc_t; crate::NCCS], } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct sem_t { pub sem_count: u32, pub sem_type: u16, pub sem_magic: u16, pub sem_pad1: [u64; 3], pub sem_pad2: [u64; 2], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_sysid: c_int, pub l_pid: crate::pid_t, pub l_pad: [c_long; 4], } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } pub struct mq_attr { pub mq_flags: c_long, pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_curmsgs: c_long, _pad: [c_int; 12], } pub struct port_event { pub portev_events: c_int, pub portev_source: c_ushort, pub portev_pad: c_ushort, pub portev_object: crate::uintptr_t, pub portev_user: *mut c_void, } pub struct port_notify { pub portnfy_port: c_int, pub portnfy_user: *mut c_void, } pub struct aio_result_t { pub aio_return: ssize_t, pub aio_errno: c_int, } pub struct exit_status { e_termination: c_short, e_exit: c_short, } pub struct utmp { pub ut_user: [c_char; 8], pub ut_id: [c_char; 4], pub ut_line: [c_char; 12], pub ut_pid: c_short, pub ut_type: c_short, pub ut_exit: exit_status, pub ut_time: crate::time_t, } pub struct timex { pub modes: u32, pub offset: i32, pub freq: i32, pub maxerror: i32, pub esterror: i32, pub status: i32, pub constant: i32, pub precision: i32, pub tolerance: i32, pub ppsfreq: i32, pub jitter: i32, pub shift: i32, pub stabil: i32, pub jitcnt: i32, pub calcnt: i32, pub errcnt: i32, pub stbcnt: i32, } pub struct ntptimeval { pub time: crate::timeval, pub maxerror: i32, pub esterror: i32, } pub struct mmapobj_result_t { pub mr_addr: crate::caddr_t, pub mr_msize: size_t, pub mr_fsize: size_t, pub mr_offset: size_t, pub mr_prot: c_uint, pub mr_flags: c_uint, } pub struct lgrp_affinity_args_t { pub idtype: crate::idtype_t, pub id: crate::id_t, pub lgrp: crate::lgrp_id_t, pub aff: crate::lgrp_affinity_t, } pub struct processor_info_t { pub pi_state: c_int, pub pi_processor_type: [c_char; PI_TYPELEN as usize], pub pi_fputypes: [c_char; PI_FPUTYPE as usize], pub pi_clock: c_int, } pub struct option { pub name: *const c_char, pub has_arg: c_int, pub flag: *mut c_int, pub val: c_int, } } s_no_extra_traits! { pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char; 108], } pub struct utsname { pub sysname: [c_char; 257], pub nodename: [c_char; 257], pub release: [c_char; 257], pub version: [c_char; 257], pub machine: [c_char; 257], } pub struct fd_set { #[cfg(target_pointer_width = "64")] fds_bits: [i64; FD_SETSIZE as usize / 64], #[cfg(target_pointer_width = "32")] fds_bits: [i32; FD_SETSIZE as usize / 32], } pub struct sockaddr_storage { pub ss_family: crate::sa_family_t, __ss_pad1: [u8; 6], __ss_align: i64, __ss_pad2: [u8; 240], } #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, #[cfg(target_pointer_width = "64")] pub si_pad: c_int, __data_pad: [c_int; SIGINFO_DATA_SIZE], } pub struct sockaddr_dl { pub sdl_family: c_ushort, pub sdl_index: c_ushort, pub sdl_type: c_uchar, pub sdl_nlen: c_uchar, pub sdl_alen: c_uchar, pub sdl_slen: c_uchar, pub sdl_data: [c_char; 244], } pub struct sigevent { pub sigev_notify: c_int, pub sigev_signo: c_int, pub sigev_value: crate::sigval, pub ss_sp: *mut c_void, pub sigev_notify_attributes: *const crate::pthread_attr_t, __sigev_pad2: c_int, } #[repr(align(16))] pub union pad128_t { // pub _q in this structure would be a "long double", of 16 bytes pub _l: [i32; 4], } #[repr(align(16))] pub union upad128_t { // pub _q in this structure would be a "long double", of 16 bytes pub _l: [u32; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME(debug): .field("sun_path", &self.sun_path) .finish() } } impl hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl fmt::Debug for utsname { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utsname") // FIXME(debug): .field("sysname", &self.sysname) // FIXME(debug): .field("nodename", &self.nodename) // FIXME(debug): .field("release", &self.release) // FIXME(debug): .field("version", &self.version) // FIXME(debug): .field("machine", &self.machine) .finish() } } impl hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); } } impl PartialEq for fd_set { fn eq(&self, other: &fd_set) -> bool { self.fds_bits .iter() .zip(other.fds_bits.iter()) .all(|(a, b)| a == b) } } impl Eq for fd_set {} impl fmt::Debug for fd_set { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fd_set") // FIXME(debug): .field("fds_bits", &self.fds_bits) .finish() } } impl hash::Hash for fd_set { fn hash(&self, state: &mut H) { self.fds_bits.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_family == other.ss_family && self.__ss_pad1 == other.__ss_pad1 && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_align", &self.__ss_align) // FIXME(debug): .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } impl siginfo_t { /// The siginfo_t will have differing contents based on the delivered signal. Based on /// `si_signo`, this determines how many of the `c_int` pad fields contain valid data /// exposed by the C unions. /// /// It is not yet exhausitive for the OS-defined types, and defaults to assuming the /// entire data pad area is "valid" for otherwise unrecognized signal numbers. fn data_field_count(&self) -> usize { match self.si_signo { SIGSEGV | SIGBUS | SIGILL | SIGTRAP | SIGFPE => { size_of::() / size_of::() } SIGCLD => size_of::() / size_of::(), SIGHUP | SIGINT | SIGQUIT | SIGABRT | SIGSYS | SIGPIPE | SIGALRM | SIGTERM | crate::SIGUSR1 | crate::SIGUSR2 | SIGPWR | SIGWINCH | SIGURG => size_of::() / size_of::(), _ => SIGINFO_DATA_SIZE, } } } impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { if self.si_signo == other.si_signo && self.si_code == other.si_code && self.si_errno == other.si_errno { // FIXME(solarish): The `si_pad` field in the 64-bit version of the struct is ignored // (for now) when doing comparisons. let field_count = self.data_field_count(); self.__data_pad[..field_count] .iter() .zip(other.__data_pad[..field_count].iter()) .all(|(a, b)| a == b) } else { false } } } impl Eq for siginfo_t {} impl fmt::Debug for siginfo_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("siginfo_t") .field("si_signo", &self.si_signo) .field("si_code", &self.si_code) .field("si_errno", &self.si_errno) // FIXME(debug): .field("__pad", &self.__pad) .finish() } } impl hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_code.hash(state); self.si_errno.hash(state); // FIXME(solarish): The `si_pad` field in the 64-bit version of the struct is ignored // (for now) when doing hashing. let field_count = self.data_field_count(); self.__data_pad[..field_count].hash(state) } } impl PartialEq for sockaddr_dl { fn eq(&self, other: &sockaddr_dl) -> bool { self.sdl_family == other.sdl_family && self.sdl_index == other.sdl_index && self.sdl_type == other.sdl_type && self.sdl_nlen == other.sdl_nlen && self.sdl_alen == other.sdl_alen && self.sdl_slen == other.sdl_slen && self .sdl_data .iter() .zip(other.sdl_data.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_dl {} impl fmt::Debug for sockaddr_dl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_dl") .field("sdl_family", &self.sdl_family) .field("sdl_index", &self.sdl_index) .field("sdl_type", &self.sdl_type) .field("sdl_nlen", &self.sdl_nlen) .field("sdl_alen", &self.sdl_alen) .field("sdl_slen", &self.sdl_slen) // FIXME(debug): .field("sdl_data", &self.sdl_data) .finish() } } impl hash::Hash for sockaddr_dl { fn hash(&self, state: &mut H) { self.sdl_family.hash(state); self.sdl_index.hash(state); self.sdl_type.hash(state); self.sdl_nlen.hash(state); self.sdl_alen.hash(state); self.sdl_slen.hash(state); self.sdl_data.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.ss_sp == other.ss_sp && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("ss_sp", &self.ss_sp) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.ss_sp.hash(state); self.sigev_notify_attributes.hash(state); } } impl PartialEq for pad128_t { fn eq(&self, other: &pad128_t) -> bool { unsafe { // FIXME(solarish): self._q == other._q || self._l == other._l } } } impl Eq for pad128_t {} impl hash::Hash for pad128_t { fn hash(&self, state: &mut H) { unsafe { // FIXME(solarish): state.write_i64(self._q as i64); self._l.hash(state); } } } impl PartialEq for upad128_t { fn eq(&self, other: &upad128_t) -> bool { unsafe { // FIXME(solarish): self._q == other._q || self._l == other._l } } } impl Eq for upad128_t {} impl hash::Hash for upad128_t { fn hash(&self, state: &mut H) { unsafe { // FIXME(solarish): state.write_i64(self._q as i64); self._l.hash(state); } } } } } cfg_if! { if #[cfg(target_pointer_width = "64")] { const SIGINFO_DATA_SIZE: usize = 60; } else { const SIGINFO_DATA_SIZE: usize = 29; } } #[repr(C)] struct siginfo_fault { addr: *mut c_void, trapno: c_int, pc: *mut crate::caddr_t, } impl Copy for siginfo_fault {} impl Clone for siginfo_fault { fn clone(&self) -> Self { *self } } #[repr(C)] struct siginfo_cldval { utime: crate::clock_t, status: c_int, stime: crate::clock_t, } impl Copy for siginfo_cldval {} impl Clone for siginfo_cldval { fn clone(&self) -> Self { *self } } #[repr(C)] struct siginfo_killval { uid: crate::uid_t, value: crate::sigval, // Pad out to match the SIGCLD value size _pad: *mut c_void, } impl Copy for siginfo_killval {} impl Clone for siginfo_killval { fn clone(&self) -> Self { *self } } #[repr(C)] struct siginfo_sigcld { pid: crate::pid_t, val: siginfo_cldval, ctid: crate::ctid_t, zoneid: crate::zoneid_t, } impl Copy for siginfo_sigcld {} impl Clone for siginfo_sigcld { fn clone(&self) -> Self { *self } } #[repr(C)] struct siginfo_kill { pid: crate::pid_t, val: siginfo_killval, ctid: crate::ctid_t, zoneid: crate::zoneid_t, } impl Copy for siginfo_kill {} impl Clone for siginfo_kill { fn clone(&self) -> Self { *self } } impl siginfo_t { unsafe fn sidata(&self) -> T { *((&self.__data_pad) as *const c_int as *const T) } pub unsafe fn si_addr(&self) -> *mut c_void { let sifault: siginfo_fault = self.sidata(); sifault.addr } pub unsafe fn si_uid(&self) -> crate::uid_t { let kill: siginfo_kill = self.sidata(); kill.val.uid } pub unsafe fn si_value(&self) -> crate::sigval { let kill: siginfo_kill = self.sidata(); kill.val.value } pub unsafe fn si_pid(&self) -> crate::pid_t { let sigcld: siginfo_sigcld = self.sidata(); sigcld.pid } pub unsafe fn si_status(&self) -> c_int { let sigcld: siginfo_sigcld = self.sidata(); sigcld.val.status } pub unsafe fn si_utime(&self) -> c_long { let sigcld: siginfo_sigcld = self.sidata(); sigcld.val.utime } pub unsafe fn si_stime(&self) -> c_long { let sigcld: siginfo_sigcld = self.sidata(); sigcld.val.stime } } pub const LC_CTYPE: c_int = 0; pub const LC_NUMERIC: c_int = 1; pub const LC_TIME: c_int = 2; pub const LC_COLLATE: c_int = 3; pub const LC_MONETARY: c_int = 4; pub const LC_MESSAGES: c_int = 5; pub const LC_ALL: c_int = 6; pub const LC_CTYPE_MASK: c_int = 1 << LC_CTYPE; pub const LC_NUMERIC_MASK: c_int = 1 << LC_NUMERIC; pub const LC_TIME_MASK: c_int = 1 << LC_TIME; pub const LC_COLLATE_MASK: c_int = 1 << LC_COLLATE; pub const LC_MONETARY_MASK: c_int = 1 << LC_MONETARY; pub const LC_MESSAGES_MASK: c_int = 1 << LC_MESSAGES; pub const LC_ALL_MASK: c_int = LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK | LC_MONETARY_MASK | LC_MESSAGES_MASK; pub const DAY_1: crate::nl_item = 1; pub const DAY_2: crate::nl_item = 2; pub const DAY_3: crate::nl_item = 3; pub const DAY_4: crate::nl_item = 4; pub const DAY_5: crate::nl_item = 5; pub const DAY_6: crate::nl_item = 6; pub const DAY_7: crate::nl_item = 7; pub const ABDAY_1: crate::nl_item = 8; pub const ABDAY_2: crate::nl_item = 9; pub const ABDAY_3: crate::nl_item = 10; pub const ABDAY_4: crate::nl_item = 11; pub const ABDAY_5: crate::nl_item = 12; pub const ABDAY_6: crate::nl_item = 13; pub const ABDAY_7: crate::nl_item = 14; pub const MON_1: crate::nl_item = 15; pub const MON_2: crate::nl_item = 16; pub const MON_3: crate::nl_item = 17; pub const MON_4: crate::nl_item = 18; pub const MON_5: crate::nl_item = 19; pub const MON_6: crate::nl_item = 20; pub const MON_7: crate::nl_item = 21; pub const MON_8: crate::nl_item = 22; pub const MON_9: crate::nl_item = 23; pub const MON_10: crate::nl_item = 24; pub const MON_11: crate::nl_item = 25; pub const MON_12: crate::nl_item = 26; pub const ABMON_1: crate::nl_item = 27; pub const ABMON_2: crate::nl_item = 28; pub const ABMON_3: crate::nl_item = 29; pub const ABMON_4: crate::nl_item = 30; pub const ABMON_5: crate::nl_item = 31; pub const ABMON_6: crate::nl_item = 32; pub const ABMON_7: crate::nl_item = 33; pub const ABMON_8: crate::nl_item = 34; pub const ABMON_9: crate::nl_item = 35; pub const ABMON_10: crate::nl_item = 36; pub const ABMON_11: crate::nl_item = 37; pub const ABMON_12: crate::nl_item = 38; pub const RADIXCHAR: crate::nl_item = 39; pub const THOUSEP: crate::nl_item = 40; pub const YESSTR: crate::nl_item = 41; pub const NOSTR: crate::nl_item = 42; pub const CRNCYSTR: crate::nl_item = 43; pub const D_T_FMT: crate::nl_item = 44; pub const D_FMT: crate::nl_item = 45; pub const T_FMT: crate::nl_item = 46; pub const AM_STR: crate::nl_item = 47; pub const PM_STR: crate::nl_item = 48; pub const CODESET: crate::nl_item = 49; pub const T_FMT_AMPM: crate::nl_item = 50; pub const ERA: crate::nl_item = 51; pub const ERA_D_FMT: crate::nl_item = 52; pub const ERA_D_T_FMT: crate::nl_item = 53; pub const ERA_T_FMT: crate::nl_item = 54; pub const ALT_DIGITS: crate::nl_item = 55; pub const YESEXPR: crate::nl_item = 56; pub const NOEXPR: crate::nl_item = 57; pub const _DATE_FMT: crate::nl_item = 58; pub const MAXSTRMSG: crate::nl_item = 58; pub const PATH_MAX: c_int = 1024; pub const SA_ONSTACK: c_int = 0x00000001; pub const SA_RESETHAND: c_int = 0x00000002; pub const SA_RESTART: c_int = 0x00000004; pub const SA_SIGINFO: c_int = 0x00000008; pub const SA_NODEFER: c_int = 0x00000010; pub const SA_NOCLDWAIT: c_int = 0x00010000; pub const SA_NOCLDSTOP: c_int = 0x00020000; pub const SS_ONSTACK: c_int = 1; pub const SS_DISABLE: c_int = 2; pub const FIOCLEX: c_int = 0x20006601; pub const FIONCLEX: c_int = 0x20006602; pub const FIONREAD: c_int = 0x4004667f; pub const FIONBIO: c_int = 0x8004667e; pub const FIOASYNC: c_int = 0x8004667d; pub const FIOSETOWN: c_int = 0x8004667c; pub const FIOGETOWN: c_int = 0x4004667b; pub const SIGCHLD: c_int = 18; pub const SIGCLD: c_int = SIGCHLD; pub const SIGBUS: c_int = 10; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const SIG_SETMASK: c_int = 3; pub const AIO_CANCELED: c_int = 0; pub const AIO_ALLDONE: c_int = 1; pub const AIO_NOTCANCELED: c_int = 2; pub const LIO_NOP: c_int = 0; pub const LIO_READ: c_int = 1; pub const LIO_WRITE: c_int = 2; pub const LIO_NOWAIT: c_int = 0; pub const LIO_WAIT: c_int = 1; pub const SIGEV_NONE: c_int = 1; pub const SIGEV_SIGNAL: c_int = 2; pub const SIGEV_THREAD: c_int = 3; pub const SIGEV_PORT: c_int = 4; pub const CLD_EXITED: c_int = 1; pub const CLD_KILLED: c_int = 2; pub const CLD_DUMPED: c_int = 3; pub const CLD_TRAPPED: c_int = 4; pub const CLD_STOPPED: c_int = 5; pub const CLD_CONTINUED: c_int = 6; pub const IP_RECVDSTADDR: c_int = 0x7; pub const IP_PKTINFO: c_int = 0x1a; pub const IP_DONTFRAG: c_int = 0x1b; pub const IP_SEC_OPT: c_int = 0x22; pub const IPV6_UNICAST_HOPS: c_int = 0x5; pub const IPV6_MULTICAST_IF: c_int = 0x6; pub const IPV6_MULTICAST_HOPS: c_int = 0x7; pub const IPV6_MULTICAST_LOOP: c_int = 0x8; pub const IPV6_PKTINFO: c_int = 0xb; pub const IPV6_RECVPKTINFO: c_int = 0x12; pub const IPV6_RECVTCLASS: c_int = 0x19; pub const IPV6_DONTFRAG: c_int = 0x21; pub const IPV6_SEC_OPT: c_int = 0x22; pub const IPV6_TCLASS: c_int = 0x26; pub const IPV6_V6ONLY: c_int = 0x27; pub const IPV6_BOUND_IF: c_int = 0x41; cfg_if! { if #[cfg(target_pointer_width = "64")] { pub const FD_SETSIZE: usize = 65536; } else { pub const FD_SETSIZE: usize = 1024; } } pub const ST_RDONLY: c_ulong = 1; pub const ST_NOSUID: c_ulong = 2; pub const NI_MAXHOST: crate::socklen_t = 1025; pub const NI_MAXSERV: crate::socklen_t = 32; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 32767; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const SEEK_DATA: c_int = 3; pub const SEEK_HOLE: c_int = 4; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 4; pub const _IOLBF: c_int = 64; pub const BUFSIZ: c_uint = 1024; pub const FOPEN_MAX: c_uint = 20; pub const FILENAME_MAX: c_uint = 1024; pub const L_tmpnam: c_uint = 25; pub const TMP_MAX: c_uint = 17576; pub const PIPE_BUF: c_int = 5120; pub const GRND_NONBLOCK: c_uint = 0x0001; pub const GRND_RANDOM: c_uint = 0x0002; pub const O_RDONLY: c_int = 0; pub const O_WRONLY: c_int = 1; pub const O_RDWR: c_int = 2; pub const O_NDELAY: c_int = 0x04; pub const O_APPEND: c_int = 8; pub const O_DSYNC: c_int = 0x40; pub const O_RSYNC: c_int = 0x8000; pub const O_CREAT: c_int = 256; pub const O_EXCL: c_int = 1024; pub const O_NOCTTY: c_int = 2048; pub const O_TRUNC: c_int = 512; pub const O_NOFOLLOW: c_int = 0x20000; pub const O_SEARCH: c_int = 0x200000; pub const O_EXEC: c_int = 0x400000; pub const O_CLOEXEC: c_int = 0x800000; pub const O_ACCMODE: c_int = 0x600003; pub const O_XATTR: c_int = 0x4000; pub const O_DIRECTORY: c_int = 0x1000000; pub const S_IFIFO: mode_t = 0o1_0000; pub const S_IFCHR: mode_t = 0o2_0000; pub const S_IFBLK: mode_t = 0o6_0000; pub const S_IFDIR: mode_t = 0o4_0000; pub const S_IFREG: mode_t = 0o10_0000; pub const S_IFLNK: mode_t = 0o12_0000; pub const S_IFSOCK: mode_t = 0o14_0000; pub const S_IFMT: mode_t = 0o17_0000; pub const S_IEXEC: mode_t = 0o0100; pub const S_IWRITE: mode_t = 0o0200; pub const S_IREAD: mode_t = 0o0400; pub const S_IRWXU: mode_t = 0o0700; pub const S_IXUSR: mode_t = 0o0100; pub const S_IWUSR: mode_t = 0o0200; pub const S_IRUSR: mode_t = 0o0400; pub const S_IRWXG: mode_t = 0o0070; pub const S_IXGRP: mode_t = 0o0010; pub const S_IWGRP: mode_t = 0o0020; pub const S_IRGRP: mode_t = 0o0040; pub const S_IRWXO: mode_t = 0o0007; pub const S_IXOTH: mode_t = 0o0001; pub const S_IWOTH: mode_t = 0o0002; pub const S_IROTH: mode_t = 0o0004; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const F_SETLK: c_int = 6; pub const F_SETLKW: c_int = 7; pub const F_GETLK: c_int = 14; pub const F_ALLOCSP: c_int = 10; pub const F_FREESP: c_int = 11; pub const F_BLOCKS: c_int = 18; pub const F_BLKSIZE: c_int = 19; pub const F_SHARE: c_int = 40; pub const F_UNSHARE: c_int = 41; pub const F_ISSTREAM: c_int = 13; pub const F_PRIV: c_int = 15; pub const F_NPRIV: c_int = 16; pub const F_QUOTACTL: c_int = 17; pub const F_GETOWN: c_int = 23; pub const F_SETOWN: c_int = 24; pub const F_REVOKE: c_int = 25; pub const F_HASREMOTELOCKS: c_int = 26; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSEGV: c_int = 11; pub const SIGSYS: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGUSR1: c_int = 16; pub const SIGUSR2: c_int = 17; pub const SIGPWR: c_int = 19; pub const SIGWINCH: c_int = 20; pub const SIGURG: c_int = 21; pub const SIGPOLL: c_int = 22; pub const SIGIO: c_int = SIGPOLL; pub const SIGSTOP: c_int = 23; pub const SIGTSTP: c_int = 24; pub const SIGCONT: c_int = 25; pub const SIGTTIN: c_int = 26; pub const SIGTTOU: c_int = 27; pub const SIGVTALRM: c_int = 28; pub const SIGPROF: c_int = 29; pub const SIGXCPU: c_int = 30; pub const SIGXFSZ: c_int = 31; pub const WNOHANG: c_int = 0x40; pub const WUNTRACED: c_int = 0x04; pub const WEXITED: c_int = 0x01; pub const WTRAPPED: c_int = 0x02; pub const WSTOPPED: c_int = WUNTRACED; pub const WCONTINUED: c_int = 0x08; pub const WNOWAIT: c_int = 0x80; pub const AT_FDCWD: c_int = 0xffd19553; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x1000; pub const AT_SYMLINK_FOLLOW: c_int = 0x2000; pub const AT_REMOVEDIR: c_int = 0x1; pub const _AT_TRIGGER: c_int = 0x2; pub const AT_EACCESS: c_int = 0x4; pub const P_PID: idtype_t = 0; pub const P_PPID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const P_SID: idtype_t = 3; pub const P_CID: idtype_t = 4; pub const P_UID: idtype_t = 5; pub const P_GID: idtype_t = 6; pub const P_ALL: idtype_t = 7; pub const P_LWPID: idtype_t = 8; pub const P_TASKID: idtype_t = 9; pub const P_PROJID: idtype_t = 10; pub const P_POOLID: idtype_t = 11; pub const P_ZONEID: idtype_t = 12; pub const P_CTID: idtype_t = 13; pub const P_CPUID: idtype_t = 14; pub const P_PSETID: idtype_t = 15; pub const PBIND_NONE: crate::processorid_t = -1; pub const PBIND_QUERY: crate::processorid_t = -2; pub const PS_NONE: c_int = -1; pub const PS_QUERY: c_int = -2; pub const PS_MYID: c_int = -3; pub const PS_SOFT: c_int = -4; pub const PS_HARD: c_int = -5; pub const PS_QUERY_TYPE: c_int = -6; pub const PS_PRIVATE: c_int = 2; pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const MAP_SHARED: c_int = 0x0001; pub const MAP_PRIVATE: c_int = 0x0002; pub const MAP_FIXED: c_int = 0x0010; pub const MAP_NORESERVE: c_int = 0x40; pub const MAP_ANON: c_int = 0x0100; pub const MAP_ANONYMOUS: c_int = 0x0100; pub const MAP_RENAME: c_int = 0x20; pub const MAP_ALIGN: c_int = 0x200; pub const MAP_TEXT: c_int = 0x400; pub const MAP_INITDATA: c_int = 0x800; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MS_SYNC: c_int = 0x0004; pub const MS_ASYNC: c_int = 0x0001; pub const MS_INVALIDATE: c_int = 0x0002; pub const MMOBJ_PADDING: c_uint = 0x10000; pub const MMOBJ_INTERPRET: c_uint = 0x20000; pub const MR_PADDING: c_uint = 0x1; pub const MR_HDR_ELF: c_uint = 0x2; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EDEADLK: c_int = 45; pub const ENOLCK: c_int = 46; pub const ECANCELED: c_int = 47; pub const ENOTSUP: c_int = 48; pub const EDQUOT: c_int = 49; pub const EBADE: c_int = 50; pub const EBADR: c_int = 51; pub const EXFULL: c_int = 52; pub const ENOANO: c_int = 53; pub const EBADRQC: c_int = 54; pub const EBADSLT: c_int = 55; pub const EDEADLOCK: c_int = 56; pub const EBFONT: c_int = 57; pub const EOWNERDEAD: c_int = 58; pub const ENOTRECOVERABLE: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const ELOCKUNMAPPED: c_int = 72; pub const ENOTACTIVE: c_int = 73; pub const EMULTIHOP: c_int = 74; pub const EADI: c_int = 75; pub const EBADMSG: c_int = 77; pub const ENAMETOOLONG: c_int = 78; pub const EOVERFLOW: c_int = 79; pub const ENOTUNIQ: c_int = 80; pub const EBADFD: c_int = 81; pub const EREMCHG: c_int = 82; pub const ELIBACC: c_int = 83; pub const ELIBBAD: c_int = 84; pub const ELIBSCN: c_int = 85; pub const ELIBMAX: c_int = 86; pub const ELIBEXEC: c_int = 87; pub const EILSEQ: c_int = 88; pub const ENOSYS: c_int = 89; pub const ELOOP: c_int = 90; pub const ERESTART: c_int = 91; pub const ESTRPIPE: c_int = 92; pub const ENOTEMPTY: c_int = 93; pub const EUSERS: c_int = 94; pub const ENOTSOCK: c_int = 95; pub const EDESTADDRREQ: c_int = 96; pub const EMSGSIZE: c_int = 97; pub const EPROTOTYPE: c_int = 98; pub const ENOPROTOOPT: c_int = 99; pub const EPROTONOSUPPORT: c_int = 120; pub const ESOCKTNOSUPPORT: c_int = 121; pub const EOPNOTSUPP: c_int = 122; pub const EPFNOSUPPORT: c_int = 123; pub const EAFNOSUPPORT: c_int = 124; pub const EADDRINUSE: c_int = 125; pub const EADDRNOTAVAIL: c_int = 126; pub const ENETDOWN: c_int = 127; pub const ENETUNREACH: c_int = 128; pub const ENETRESET: c_int = 129; pub const ECONNABORTED: c_int = 130; pub const ECONNRESET: c_int = 131; pub const ENOBUFS: c_int = 132; pub const EISCONN: c_int = 133; pub const ENOTCONN: c_int = 134; pub const ESHUTDOWN: c_int = 143; pub const ETOOMANYREFS: c_int = 144; pub const ETIMEDOUT: c_int = 145; pub const ECONNREFUSED: c_int = 146; pub const EHOSTDOWN: c_int = 147; pub const EHOSTUNREACH: c_int = 148; pub const EWOULDBLOCK: c_int = EAGAIN; pub const EALREADY: c_int = 149; pub const EINPROGRESS: c_int = 150; pub const ESTALE: c_int = 151; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_MEMORY: c_int = 6; pub const EAI_NODATA: c_int = 7; pub const EAI_NONAME: c_int = 8; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 12; pub const NI_NOFQDN: c_uint = 0x0001; pub const NI_NUMERICHOST: c_uint = 0x0002; pub const NI_NAMEREQD: c_uint = 0x0004; pub const NI_NUMERICSERV: c_uint = 0x0008; pub const NI_DGRAM: c_uint = 0x0010; pub const NI_WITHSCOPEID: c_uint = 0x0020; pub const NI_NUMERICSCOPE: c_uint = 0x0040; pub const F_DUPFD: c_int = 0; pub const F_DUP2FD: c_int = 9; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const F_GETXFL: c_int = 45; pub const SIGTRAP: c_int = 5; pub const GLOB_APPEND: c_int = 32; pub const GLOB_DOOFFS: c_int = 16; pub const GLOB_ERR: c_int = 1; pub const GLOB_MARK: c_int = 2; pub const GLOB_NOCHECK: c_int = 8; pub const GLOB_NOSORT: c_int = 4; pub const GLOB_NOESCAPE: c_int = 64; pub const GLOB_NOSPACE: c_int = -2; pub const GLOB_ABORTED: c_int = -1; pub const GLOB_NOMATCH: c_int = -3; pub const POLLIN: c_short = 0x1; pub const POLLPRI: c_short = 0x2; pub const POLLOUT: c_short = 0x4; pub const POLLERR: c_short = 0x8; pub const POLLHUP: c_short = 0x10; pub const POLLNVAL: c_short = 0x20; pub const POLLNORM: c_short = 0x0040; pub const POLLRDNORM: c_short = 0x0040; pub const POLLWRNORM: c_short = 0x4; /* POLLOUT */ pub const POLLRDBAND: c_short = 0x0080; pub const POLLWRBAND: c_short = 0x0100; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 1; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const POSIX_SPAWN_RESETIDS: c_short = 0x1; pub const POSIX_SPAWN_SETPGROUP: c_short = 0x2; pub const POSIX_SPAWN_SETSIGDEF: c_short = 0x4; pub const POSIX_SPAWN_SETSIGMASK: c_short = 0x8; pub const POSIX_SPAWN_SETSCHEDPARAM: c_short = 0x10; pub const POSIX_SPAWN_SETSCHEDULER: c_short = 0x20; pub const POSIX_SPAWN_SETSIGIGN_NP: c_short = 0x800; pub const POSIX_SPAWN_NOSIGCHLD_NP: c_short = 0x1000; pub const POSIX_SPAWN_WAITPID_NP: c_short = 0x2000; pub const POSIX_SPAWN_NOEXECERR_NP: c_short = 0x4000; pub const PTHREAD_CREATE_JOINABLE: c_int = 0; pub const PTHREAD_CREATE_DETACHED: c_int = 0x40; pub const PTHREAD_PROCESS_SHARED: c_int = 1; pub const PTHREAD_PROCESS_PRIVATE: c_ushort = 0; pub const PTHREAD_STACK_MIN: size_t = 4096; pub const SIGSTKSZ: size_t = 8192; // https://illumos.org/man/3c/clock_gettime // https://github.com/illumos/illumos-gate/ // blob/HEAD/usr/src/lib/libc/amd64/sys/__clock_gettime.s // clock_gettime(3c) doesn't seem to accept anything other than CLOCK_REALTIME // or __CLOCK_REALTIME0 // // https://github.com/illumos/illumos-gate/ // blob/HEAD/usr/src/uts/common/sys/time_impl.h // Confusing! CLOCK_HIGHRES==CLOCK_MONOTONIC==4 // __CLOCK_REALTIME0==0 is an obsoleted version of CLOCK_REALTIME==3 pub const CLOCK_REALTIME: crate::clockid_t = 3; pub const CLOCK_MONOTONIC: crate::clockid_t = 4; pub const TIMER_RELTIME: c_int = 0; pub const TIMER_ABSTIME: c_int = 1; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_NOFILE: c_int = 5; pub const RLIMIT_VMEM: c_int = 6; pub const RLIMIT_AS: c_int = RLIMIT_VMEM; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: rlim_t = 7; pub const RLIM_INFINITY: rlim_t = 0xfffffffffffffffd; pub const RUSAGE_SELF: c_int = 0; pub const RUSAGE_CHILDREN: c_int = -1; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const MADV_FREE: c_int = 5; pub const MADV_ACCESS_DEFAULT: c_int = 6; pub const MADV_ACCESS_LWP: c_int = 7; pub const MADV_ACCESS_MANY: c_int = 8; pub const AF_UNSPEC: c_int = 0; pub const AF_UNIX: c_int = 1; pub const AF_INET: c_int = 2; pub const AF_IMPLINK: c_int = 3; pub const AF_PUP: c_int = 4; pub const AF_CHAOS: c_int = 5; pub const AF_NS: c_int = 6; pub const AF_NBS: c_int = 7; pub const AF_ECMA: c_int = 8; pub const AF_DATAKIT: c_int = 9; pub const AF_CCITT: c_int = 10; pub const AF_SNA: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_DLI: c_int = 13; pub const AF_LAT: c_int = 14; pub const AF_HYLINK: c_int = 15; pub const AF_APPLETALK: c_int = 16; pub const AF_NIT: c_int = 17; pub const AF_802: c_int = 18; pub const AF_OSI: c_int = 19; pub const AF_X25: c_int = 20; pub const AF_OSINET: c_int = 21; pub const AF_GOSIP: c_int = 22; pub const AF_IPX: c_int = 23; pub const AF_ROUTE: c_int = 24; pub const AF_LINK: c_int = 25; pub const AF_INET6: c_int = 26; pub const AF_KEY: c_int = 27; pub const AF_POLICY: c_int = 29; pub const AF_INET_OFFLOAD: c_int = 30; pub const AF_TRILL: c_int = 31; pub const AF_PACKET: c_int = 32; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_UNIX: c_int = AF_UNIX; pub const PF_LOCAL: c_int = PF_UNIX; pub const PF_FILE: c_int = PF_UNIX; pub const PF_INET: c_int = AF_INET; pub const PF_IMPLINK: c_int = AF_IMPLINK; pub const PF_PUP: c_int = AF_PUP; pub const PF_CHAOS: c_int = AF_CHAOS; pub const PF_NS: c_int = AF_NS; pub const PF_NBS: c_int = AF_NBS; pub const PF_ECMA: c_int = AF_ECMA; pub const PF_DATAKIT: c_int = AF_DATAKIT; pub const PF_CCITT: c_int = AF_CCITT; pub const PF_SNA: c_int = AF_SNA; pub const PF_DECnet: c_int = AF_DECnet; pub const PF_DLI: c_int = AF_DLI; pub const PF_LAT: c_int = AF_LAT; pub const PF_HYLINK: c_int = AF_HYLINK; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_NIT: c_int = AF_NIT; pub const PF_802: c_int = AF_802; pub const PF_OSI: c_int = AF_OSI; pub const PF_X25: c_int = AF_X25; pub const PF_OSINET: c_int = AF_OSINET; pub const PF_GOSIP: c_int = AF_GOSIP; pub const PF_IPX: c_int = AF_IPX; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_LINK: c_int = AF_LINK; pub const PF_INET6: c_int = AF_INET6; pub const PF_KEY: c_int = AF_KEY; pub const PF_POLICY: c_int = AF_POLICY; pub const PF_INET_OFFLOAD: c_int = AF_INET_OFFLOAD; pub const PF_TRILL: c_int = AF_TRILL; pub const PF_PACKET: c_int = AF_PACKET; pub const SOCK_DGRAM: c_int = 1; pub const SOCK_STREAM: c_int = 2; pub const SOCK_RAW: c_int = 4; pub const SOCK_RDM: c_int = 5; pub const SOCK_SEQPACKET: c_int = 6; pub const IP_MULTICAST_IF: c_int = 16; pub const IP_MULTICAST_TTL: c_int = 17; pub const IP_MULTICAST_LOOP: c_int = 18; pub const IP_HDRINCL: c_int = 2; pub const IP_TOS: c_int = 3; pub const IP_TTL: c_int = 4; pub const IP_ADD_MEMBERSHIP: c_int = 19; pub const IP_DROP_MEMBERSHIP: c_int = 20; pub const IPV6_JOIN_GROUP: c_int = 9; pub const IPV6_LEAVE_GROUP: c_int = 10; pub const IP_ADD_SOURCE_MEMBERSHIP: c_int = 23; pub const IP_DROP_SOURCE_MEMBERSHIP: c_int = 24; pub const IP_BLOCK_SOURCE: c_int = 21; pub const IP_UNBLOCK_SOURCE: c_int = 22; pub const IP_BOUND_IF: c_int = 0x41; // These TCP socket options are common between illumos and Solaris, while higher // numbers have generally diverged: pub const TCP_NODELAY: c_int = 0x1; pub const TCP_MAXSEG: c_int = 0x2; pub const TCP_KEEPALIVE: c_int = 0x8; pub const TCP_NOTIFY_THRESHOLD: c_int = 0x10; pub const TCP_ABORT_THRESHOLD: c_int = 0x11; pub const TCP_CONN_NOTIFY_THRESHOLD: c_int = 0x12; pub const TCP_CONN_ABORT_THRESHOLD: c_int = 0x13; pub const TCP_RECVDSTADDR: c_int = 0x14; pub const TCP_INIT_CWND: c_int = 0x15; pub const TCP_KEEPALIVE_THRESHOLD: c_int = 0x16; pub const TCP_KEEPALIVE_ABORT_THRESHOLD: c_int = 0x17; pub const TCP_CORK: c_int = 0x18; pub const TCP_RTO_INITIAL: c_int = 0x19; pub const TCP_RTO_MIN: c_int = 0x1a; pub const TCP_RTO_MAX: c_int = 0x1b; pub const TCP_LINGER2: c_int = 0x1c; pub const UDP_NAT_T_ENDPOINT: c_int = 0x0103; pub const SOMAXCONN: c_int = 128; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_DEBUG: c_int = 0x01; pub const SO_ACCEPTCONN: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_USELOOPBACK: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVLOWAT: c_int = 0x1004; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; pub const SO_TYPE: c_int = 0x1008; pub const SO_PROTOTYPE: c_int = 0x1009; pub const SO_DOMAIN: c_int = 0x100c; pub const SO_TIMESTAMP: c_int = 0x1013; pub const SO_EXCLBIND: c_int = 0x1015; pub const SCM_RIGHTS: c_int = 0x1010; pub const SCM_UCRED: c_int = 0x1012; pub const SCM_TIMESTAMP: c_int = SO_TIMESTAMP; pub const MSG_OOB: c_int = 0x1; pub const MSG_PEEK: c_int = 0x2; pub const MSG_DONTROUTE: c_int = 0x4; pub const MSG_EOR: c_int = 0x8; pub const MSG_CTRUNC: c_int = 0x10; pub const MSG_TRUNC: c_int = 0x20; pub const MSG_WAITALL: c_int = 0x40; pub const MSG_DONTWAIT: c_int = 0x80; pub const MSG_NOTIFICATION: c_int = 0x100; pub const MSG_NOSIGNAL: c_int = 0x200; pub const MSG_DUPCTRL: c_int = 0x800; pub const MSG_XPG4_2: c_int = 0x8000; pub const MSG_MAXIOVLEN: c_int = 16; pub const IF_NAMESIZE: size_t = 32; pub const IFNAMSIZ: size_t = 16; // https://docs.oracle.com/cd/E23824_01/html/821-1475/if-7p.html pub const IFF_UP: c_int = 0x0000000001; // Address is up pub const IFF_BROADCAST: c_int = 0x0000000002; // Broadcast address valid pub const IFF_DEBUG: c_int = 0x0000000004; // Turn on debugging pub const IFF_LOOPBACK: c_int = 0x0000000008; // Loopback net pub const IFF_POINTOPOINT: c_int = 0x0000000010; // Interface is p-to-p pub const IFF_NOTRAILERS: c_int = 0x0000000020; // Avoid use of trailers pub const IFF_RUNNING: c_int = 0x0000000040; // Resources allocated pub const IFF_NOARP: c_int = 0x0000000080; // No address res. protocol pub const IFF_PROMISC: c_int = 0x0000000100; // Receive all packets pub const IFF_ALLMULTI: c_int = 0x0000000200; // Receive all multicast pkts pub const IFF_INTELLIGENT: c_int = 0x0000000400; // Protocol code on board pub const IFF_MULTICAST: c_int = 0x0000000800; // Supports multicast // Multicast using broadcst. add. pub const IFF_MULTI_BCAST: c_int = 0x0000001000; pub const IFF_UNNUMBERED: c_int = 0x0000002000; // Non-unique address pub const IFF_DHCPRUNNING: c_int = 0x0000004000; // DHCP controls interface pub const IFF_PRIVATE: c_int = 0x0000008000; // Do not advertise pub const IFF_NOXMIT: c_int = 0x0000010000; // Do not transmit pkts // No address - just on-link subnet pub const IFF_NOLOCAL: c_int = 0x0000020000; pub const IFF_DEPRECATED: c_int = 0x0000040000; // Address is deprecated pub const IFF_ADDRCONF: c_int = 0x0000080000; // Addr. from stateless addrconf pub const IFF_ROUTER: c_int = 0x0000100000; // Router on interface pub const IFF_NONUD: c_int = 0x0000200000; // No NUD on interface pub const IFF_ANYCAST: c_int = 0x0000400000; // Anycast address pub const IFF_NORTEXCH: c_int = 0x0000800000; // Don't xchange rout. info pub const IFF_IPV4: c_int = 0x0001000000; // IPv4 interface pub const IFF_IPV6: c_int = 0x0002000000; // IPv6 interface pub const IFF_NOFAILOVER: c_int = 0x0008000000; // in.mpathd test address pub const IFF_FAILED: c_int = 0x0010000000; // Interface has failed pub const IFF_STANDBY: c_int = 0x0020000000; // Interface is a hot-spare pub const IFF_INACTIVE: c_int = 0x0040000000; // Functioning but not used pub const IFF_OFFLINE: c_int = 0x0080000000; // Interface is offline // If CoS marking is supported pub const IFF_COS_ENABLED: c_longlong = 0x0200000000; pub const IFF_PREFERRED: c_longlong = 0x0400000000; // Prefer as source addr. pub const IFF_TEMPORARY: c_longlong = 0x0800000000; // RFC3041 pub const IFF_FIXEDMTU: c_longlong = 0x1000000000; // MTU set with SIOCSLIFMTU pub const IFF_VIRTUAL: c_longlong = 0x2000000000; // Cannot send/receive pkts pub const IFF_DUPLICATE: c_longlong = 0x4000000000; // Local address in use pub const IFF_IPMP: c_longlong = 0x8000000000; // IPMP IP interface // sys/ipc.h: pub const IPC_ALLOC: c_int = 0x8000; pub const IPC_CREAT: c_int = 0x200; pub const IPC_EXCL: c_int = 0x400; pub const IPC_NOWAIT: c_int = 0x800; pub const IPC_PRIVATE: key_t = 0; pub const IPC_RMID: c_int = 10; pub const IPC_SET: c_int = 11; pub const IPC_SEAT: c_int = 12; // sys/shm.h pub const SHM_R: c_int = 0o400; pub const SHM_W: c_int = 0o200; pub const SHM_RDONLY: c_int = 0o10000; pub const SHM_RND: c_int = 0o20000; pub const SHM_SHARE_MMU: c_int = 0o40000; pub const SHM_PAGEABLE: c_int = 0o100000; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const F_RDLCK: c_short = 1; pub const F_WRLCK: c_short = 2; pub const F_UNLCK: c_short = 3; pub const O_SYNC: c_int = 16; pub const O_NONBLOCK: c_int = 128; pub const IPPROTO_RAW: c_int = 255; pub const _PC_LINK_MAX: c_int = 1; pub const _PC_MAX_CANON: c_int = 2; pub const _PC_MAX_INPUT: c_int = 3; pub const _PC_NAME_MAX: c_int = 4; pub const _PC_PATH_MAX: c_int = 5; pub const _PC_PIPE_BUF: c_int = 6; pub const _PC_NO_TRUNC: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_CHOWN_RESTRICTED: c_int = 9; pub const _PC_ASYNC_IO: c_int = 10; pub const _PC_PRIO_IO: c_int = 11; pub const _PC_SYNC_IO: c_int = 12; pub const _PC_ALLOC_SIZE_MIN: c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: c_int = 16; pub const _PC_REC_XFER_ALIGN: c_int = 17; pub const _PC_SYMLINK_MAX: c_int = 18; pub const _PC_2_SYMLINKS: c_int = 19; pub const _PC_ACL_ENABLED: c_int = 20; pub const _PC_MIN_HOLE_SIZE: c_int = 21; pub const _PC_CASE_BEHAVIOR: c_int = 22; pub const _PC_SATTR_ENABLED: c_int = 23; pub const _PC_SATTR_EXISTS: c_int = 24; pub const _PC_ACCESS_FILTERING: c_int = 25; pub const _PC_TIMESTAMP_RESOLUTION: c_int = 26; pub const _PC_FILESIZEBITS: c_int = 67; pub const _PC_XATTR_ENABLED: c_int = 100; pub const _PC_XATTR_EXISTS: c_int = 101; pub const _POSIX_VDISABLE: crate::cc_t = 0; pub const _SC_ARG_MAX: c_int = 1; pub const _SC_CHILD_MAX: c_int = 2; pub const _SC_CLK_TCK: c_int = 3; pub const _SC_NGROUPS_MAX: c_int = 4; pub const _SC_OPEN_MAX: c_int = 5; pub const _SC_JOB_CONTROL: c_int = 6; pub const _SC_SAVED_IDS: c_int = 7; pub const _SC_VERSION: c_int = 8; pub const _SC_PASS_MAX: c_int = 9; pub const _SC_LOGNAME_MAX: c_int = 10; pub const _SC_PAGESIZE: c_int = 11; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_XOPEN_VERSION: c_int = 12; pub const _SC_NPROCESSORS_CONF: c_int = 14; pub const _SC_NPROCESSORS_ONLN: c_int = 15; pub const _SC_STREAM_MAX: c_int = 16; pub const _SC_TZNAME_MAX: c_int = 17; pub const _SC_AIO_LISTIO_MAX: c_int = 18; pub const _SC_AIO_MAX: c_int = 19; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 20; pub const _SC_ASYNCHRONOUS_IO: c_int = 21; pub const _SC_DELAYTIMER_MAX: c_int = 22; pub const _SC_FSYNC: c_int = 23; pub const _SC_MAPPED_FILES: c_int = 24; pub const _SC_MEMLOCK: c_int = 25; pub const _SC_MEMLOCK_RANGE: c_int = 26; pub const _SC_MEMORY_PROTECTION: c_int = 27; pub const _SC_MESSAGE_PASSING: c_int = 28; pub const _SC_MQ_OPEN_MAX: c_int = 29; pub const _SC_MQ_PRIO_MAX: c_int = 30; pub const _SC_PRIORITIZED_IO: c_int = 31; pub const _SC_PRIORITY_SCHEDULING: c_int = 32; pub const _SC_REALTIME_SIGNALS: c_int = 33; pub const _SC_RTSIG_MAX: c_int = 34; pub const _SC_SEMAPHORES: c_int = 35; pub const _SC_SEM_NSEMS_MAX: c_int = 36; pub const _SC_SEM_VALUE_MAX: c_int = 37; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 38; pub const _SC_SIGQUEUE_MAX: c_int = 39; pub const _SC_SIGRT_MIN: c_int = 40; pub const _SC_SIGRT_MAX: c_int = 41; pub const _SC_SYNCHRONIZED_IO: c_int = 42; pub const _SC_TIMERS: c_int = 43; pub const _SC_TIMER_MAX: c_int = 44; pub const _SC_2_C_BIND: c_int = 45; pub const _SC_2_C_DEV: c_int = 46; pub const _SC_2_C_VERSION: c_int = 47; pub const _SC_2_FORT_DEV: c_int = 48; pub const _SC_2_FORT_RUN: c_int = 49; pub const _SC_2_LOCALEDEF: c_int = 50; pub const _SC_2_SW_DEV: c_int = 51; pub const _SC_2_UPE: c_int = 52; pub const _SC_2_VERSION: c_int = 53; pub const _SC_BC_BASE_MAX: c_int = 54; pub const _SC_BC_DIM_MAX: c_int = 55; pub const _SC_BC_SCALE_MAX: c_int = 56; pub const _SC_BC_STRING_MAX: c_int = 57; pub const _SC_COLL_WEIGHTS_MAX: c_int = 58; pub const _SC_EXPR_NEST_MAX: c_int = 59; pub const _SC_LINE_MAX: c_int = 60; pub const _SC_RE_DUP_MAX: c_int = 61; pub const _SC_XOPEN_CRYPT: c_int = 62; pub const _SC_XOPEN_ENH_I18N: c_int = 63; pub const _SC_XOPEN_SHM: c_int = 64; pub const _SC_2_CHAR_TERM: c_int = 66; pub const _SC_XOPEN_XCU_VERSION: c_int = 67; pub const _SC_ATEXIT_MAX: c_int = 76; pub const _SC_IOV_MAX: c_int = 77; pub const _SC_XOPEN_UNIX: c_int = 78; pub const _SC_T_IOV_MAX: c_int = 79; pub const _SC_PHYS_PAGES: c_int = 500; pub const _SC_AVPHYS_PAGES: c_int = 501; pub const _SC_COHER_BLKSZ: c_int = 503; pub const _SC_SPLIT_CACHE: c_int = 504; pub const _SC_ICACHE_SZ: c_int = 505; pub const _SC_DCACHE_SZ: c_int = 506; pub const _SC_ICACHE_LINESZ: c_int = 507; pub const _SC_DCACHE_LINESZ: c_int = 508; pub const _SC_ICACHE_BLKSZ: c_int = 509; pub const _SC_DCACHE_BLKSZ: c_int = 510; pub const _SC_DCACHE_TBLKSZ: c_int = 511; pub const _SC_ICACHE_ASSOC: c_int = 512; pub const _SC_DCACHE_ASSOC: c_int = 513; pub const _SC_MAXPID: c_int = 514; pub const _SC_STACK_PROT: c_int = 515; pub const _SC_NPROCESSORS_MAX: c_int = 516; pub const _SC_CPUID_MAX: c_int = 517; pub const _SC_EPHID_MAX: c_int = 518; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 568; pub const _SC_GETGR_R_SIZE_MAX: c_int = 569; pub const _SC_GETPW_R_SIZE_MAX: c_int = 570; pub const _SC_LOGIN_NAME_MAX: c_int = 571; pub const _SC_THREAD_KEYS_MAX: c_int = 572; pub const _SC_THREAD_STACK_MIN: c_int = 573; pub const _SC_THREAD_THREADS_MAX: c_int = 574; pub const _SC_TTY_NAME_MAX: c_int = 575; pub const _SC_THREADS: c_int = 576; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 577; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 578; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 579; pub const _SC_THREAD_PRIO_INHERIT: c_int = 580; pub const _SC_THREAD_PRIO_PROTECT: c_int = 581; pub const _SC_THREAD_PROCESS_SHARED: c_int = 582; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 583; pub const _SC_XOPEN_LEGACY: c_int = 717; pub const _SC_XOPEN_REALTIME: c_int = 718; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 719; pub const _SC_XBS5_ILP32_OFF32: c_int = 720; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 721; pub const _SC_XBS5_LP64_OFF64: c_int = 722; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 723; pub const _SC_2_PBS: c_int = 724; pub const _SC_2_PBS_ACCOUNTING: c_int = 725; pub const _SC_2_PBS_CHECKPOINT: c_int = 726; pub const _SC_2_PBS_LOCATE: c_int = 728; pub const _SC_2_PBS_MESSAGE: c_int = 729; pub const _SC_2_PBS_TRACK: c_int = 730; pub const _SC_ADVISORY_INFO: c_int = 731; pub const _SC_BARRIERS: c_int = 732; pub const _SC_CLOCK_SELECTION: c_int = 733; pub const _SC_CPUTIME: c_int = 734; pub const _SC_HOST_NAME_MAX: c_int = 735; pub const _SC_MONOTONIC_CLOCK: c_int = 736; pub const _SC_READER_WRITER_LOCKS: c_int = 737; pub const _SC_REGEXP: c_int = 738; pub const _SC_SHELL: c_int = 739; pub const _SC_SPAWN: c_int = 740; pub const _SC_SPIN_LOCKS: c_int = 741; pub const _SC_SPORADIC_SERVER: c_int = 742; pub const _SC_SS_REPL_MAX: c_int = 743; pub const _SC_SYMLOOP_MAX: c_int = 744; pub const _SC_THREAD_CPUTIME: c_int = 745; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 746; pub const _SC_TIMEOUTS: c_int = 747; pub const _SC_TRACE: c_int = 748; pub const _SC_TRACE_EVENT_FILTER: c_int = 749; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 750; pub const _SC_TRACE_INHERIT: c_int = 751; pub const _SC_TRACE_LOG: c_int = 752; pub const _SC_TRACE_NAME_MAX: c_int = 753; pub const _SC_TRACE_SYS_MAX: c_int = 754; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 755; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 756; pub const _SC_V6_ILP32_OFF32: c_int = 757; pub const _SC_V6_ILP32_OFFBIG: c_int = 758; pub const _SC_V6_LP64_OFF64: c_int = 759; pub const _SC_V6_LPBIG_OFFBIG: c_int = 760; pub const _SC_XOPEN_STREAMS: c_int = 761; pub const _SC_IPV6: c_int = 762; pub const _SC_RAW_SOCKETS: c_int = 763; pub const _ST_FSTYPSZ: c_int = 16; pub const _MUTEX_MAGIC: u16 = 0x4d58; // MX pub const _COND_MAGIC: u16 = 0x4356; // CV pub const _RWL_MAGIC: u16 = 0x5257; // RW pub const NCCS: usize = 19; pub const LOG_CRON: c_int = 15 << 3; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __pthread_mutex_flag1: 0, __pthread_mutex_flag2: 0, __pthread_mutex_ceiling: 0, __pthread_mutex_type: PTHREAD_PROCESS_PRIVATE, __pthread_mutex_magic: _MUTEX_MAGIC, __pthread_mutex_lock: 0, __pthread_mutex_data: 0, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __pthread_cond_flag: [0; 4], __pthread_cond_type: PTHREAD_PROCESS_PRIVATE, __pthread_cond_magic: _COND_MAGIC, __pthread_cond_data: 0, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __pthread_rwlock_readers: 0, __pthread_rwlock_type: PTHREAD_PROCESS_PRIVATE, __pthread_rwlock_magic: _RWL_MAGIC, __pthread_rwlock_mutex: PTHREAD_MUTEX_INITIALIZER, __pthread_rwlock_readercv: PTHREAD_COND_INITIALIZER, __pthread_rwlock_writercv: PTHREAD_COND_INITIALIZER, }; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 4; pub const PTHREAD_MUTEX_DEFAULT: c_int = crate::PTHREAD_MUTEX_NORMAL; pub const RTLD_NEXT: *mut c_void = -1isize as *mut c_void; pub const RTLD_DEFAULT: *mut c_void = -2isize as *mut c_void; pub const RTLD_SELF: *mut c_void = -3isize as *mut c_void; pub const RTLD_PROBE: *mut c_void = -4isize as *mut c_void; pub const RTLD_LAZY: c_int = 0x1; pub const RTLD_NOW: c_int = 0x2; pub const RTLD_NOLOAD: c_int = 0x4; pub const RTLD_GLOBAL: c_int = 0x100; pub const RTLD_LOCAL: c_int = 0x0; pub const RTLD_PARENT: c_int = 0x200; pub const RTLD_GROUP: c_int = 0x400; pub const RTLD_WORLD: c_int = 0x800; pub const RTLD_NODELETE: c_int = 0x1000; pub const RTLD_FIRST: c_int = 0x2000; pub const RTLD_CONFGEN: c_int = 0x10000; pub const PORT_SOURCE_AIO: c_int = 1; pub const PORT_SOURCE_TIMER: c_int = 2; pub const PORT_SOURCE_USER: c_int = 3; pub const PORT_SOURCE_FD: c_int = 4; pub const PORT_SOURCE_ALERT: c_int = 5; pub const PORT_SOURCE_MQ: c_int = 6; pub const PORT_SOURCE_FILE: c_int = 7; pub const NONROOT_USR: c_short = 2; pub const EMPTY: c_short = 0; pub const RUN_LVL: c_short = 1; pub const BOOT_TIME: c_short = 2; pub const OLD_TIME: c_short = 3; pub const NEW_TIME: c_short = 4; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const USER_PROCESS: c_short = 7; pub const DEAD_PROCESS: c_short = 8; pub const ACCOUNTING: c_short = 9; pub const DOWN_TIME: c_short = 10; const _TIOC: c_int = ('T' as i32) << 8; const tIOC: c_int = ('t' as i32) << 8; pub const TCGETA: c_int = _TIOC | 1; pub const TCSETA: c_int = _TIOC | 2; pub const TCSETAW: c_int = _TIOC | 3; pub const TCSETAF: c_int = _TIOC | 4; pub const TCSBRK: c_int = _TIOC | 5; pub const TCXONC: c_int = _TIOC | 6; pub const TCFLSH: c_int = _TIOC | 7; pub const TCDSET: c_int = _TIOC | 32; pub const TCGETS: c_int = _TIOC | 13; pub const TCSETS: c_int = _TIOC | 14; pub const TCSANOW: c_int = _TIOC | 14; pub const TCSETSW: c_int = _TIOC | 15; pub const TCSADRAIN: c_int = _TIOC | 15; pub const TCSETSF: c_int = _TIOC | 16; pub const TCSAFLUSH: c_int = _TIOC | 16; pub const TCIFLUSH: c_int = 0; pub const TCOFLUSH: c_int = 1; pub const TCIOFLUSH: c_int = 2; pub const TCOOFF: c_int = 0; pub const TCOON: c_int = 1; pub const TCIOFF: c_int = 2; pub const TCION: c_int = 3; pub const TIOC: c_int = _TIOC; pub const TIOCKBON: c_int = _TIOC | 8; pub const TIOCKBOF: c_int = _TIOC | 9; pub const TIOCGWINSZ: c_int = _TIOC | 104; pub const TIOCSWINSZ: c_int = _TIOC | 103; pub const TIOCGSOFTCAR: c_int = _TIOC | 105; pub const TIOCSSOFTCAR: c_int = _TIOC | 106; pub const TIOCGPPS: c_int = _TIOC | 125; pub const TIOCSPPS: c_int = _TIOC | 126; pub const TIOCGPPSEV: c_int = _TIOC | 127; pub const TIOCGETD: c_int = tIOC | 0; pub const TIOCSETD: c_int = tIOC | 1; pub const TIOCHPCL: c_int = tIOC | 2; pub const TIOCGETP: c_int = tIOC | 8; pub const TIOCSETP: c_int = tIOC | 9; pub const TIOCSETN: c_int = tIOC | 10; pub const TIOCEXCL: c_int = tIOC | 13; pub const TIOCNXCL: c_int = tIOC | 14; pub const TIOCFLUSH: c_int = tIOC | 16; pub const TIOCSETC: c_int = tIOC | 17; pub const TIOCGETC: c_int = tIOC | 18; pub const TIOCLBIS: c_int = tIOC | 127; pub const TIOCLBIC: c_int = tIOC | 126; pub const TIOCLSET: c_int = tIOC | 125; pub const TIOCLGET: c_int = tIOC | 124; pub const TIOCSBRK: c_int = tIOC | 123; pub const TIOCCBRK: c_int = tIOC | 122; pub const TIOCSDTR: c_int = tIOC | 121; pub const TIOCCDTR: c_int = tIOC | 120; pub const TIOCSLTC: c_int = tIOC | 117; pub const TIOCGLTC: c_int = tIOC | 116; pub const TIOCOUTQ: c_int = tIOC | 115; pub const TIOCNOTTY: c_int = tIOC | 113; pub const TIOCSCTTY: c_int = tIOC | 132; pub const TIOCSTOP: c_int = tIOC | 111; pub const TIOCSTART: c_int = tIOC | 110; pub const TIOCSILOOP: c_int = tIOC | 109; pub const TIOCCILOOP: c_int = tIOC | 108; pub const TIOCGPGRP: c_int = tIOC | 20; pub const TIOCSPGRP: c_int = tIOC | 21; pub const TIOCGSID: c_int = tIOC | 22; pub const TIOCSTI: c_int = tIOC | 23; pub const TIOCMSET: c_int = tIOC | 26; pub const TIOCMBIS: c_int = tIOC | 27; pub const TIOCMBIC: c_int = tIOC | 28; pub const TIOCMGET: c_int = tIOC | 29; pub const TIOCREMOTE: c_int = tIOC | 30; pub const TIOCSIGNAL: c_int = tIOC | 31; pub const TIOCM_LE: c_int = 0o0001; pub const TIOCM_DTR: c_int = 0o0002; pub const TIOCM_RTS: c_int = 0o0004; pub const TIOCM_ST: c_int = 0o0010; pub const TIOCM_SR: c_int = 0o0020; pub const TIOCM_CTS: c_int = 0o0040; pub const TIOCM_CAR: c_int = 0o0100; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RNG: c_int = 0o0200; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const TIOCM_DSR: c_int = 0o0400; /* termios */ pub const B0: speed_t = 0; pub const B50: speed_t = 1; pub const B75: speed_t = 2; pub const B110: speed_t = 3; pub const B134: speed_t = 4; pub const B150: speed_t = 5; pub const B200: speed_t = 6; pub const B300: speed_t = 7; pub const B600: speed_t = 8; pub const B1200: speed_t = 9; pub const B1800: speed_t = 10; pub const B2400: speed_t = 11; pub const B4800: speed_t = 12; pub const B9600: speed_t = 13; pub const B19200: speed_t = 14; pub const B38400: speed_t = 15; pub const B57600: speed_t = 16; pub const B76800: speed_t = 17; pub const B115200: speed_t = 18; pub const B153600: speed_t = 19; pub const B230400: speed_t = 20; pub const B307200: speed_t = 21; pub const B460800: speed_t = 22; pub const B921600: speed_t = 23; pub const CSTART: crate::tcflag_t = 0o21; pub const CSTOP: crate::tcflag_t = 0o23; pub const CSWTCH: crate::tcflag_t = 0o32; pub const CBAUD: crate::tcflag_t = 0o17; pub const CIBAUD: crate::tcflag_t = 0o3600000; pub const CBAUDEXT: crate::tcflag_t = 0o10000000; pub const CIBAUDEXT: crate::tcflag_t = 0o20000000; pub const CSIZE: crate::tcflag_t = 0o000060; pub const CS5: crate::tcflag_t = 0; pub const CS6: crate::tcflag_t = 0o000020; pub const CS7: crate::tcflag_t = 0o000040; pub const CS8: crate::tcflag_t = 0o000060; pub const CSTOPB: crate::tcflag_t = 0o000100; pub const ECHO: crate::tcflag_t = 0o000010; pub const ECHOE: crate::tcflag_t = 0o000020; pub const ECHOK: crate::tcflag_t = 0o000040; pub const ECHONL: crate::tcflag_t = 0o000100; pub const ECHOCTL: crate::tcflag_t = 0o001000; pub const ECHOPRT: crate::tcflag_t = 0o002000; pub const ECHOKE: crate::tcflag_t = 0o004000; pub const EXTPROC: crate::tcflag_t = 0o200000; pub const IGNBRK: crate::tcflag_t = 0o000001; pub const BRKINT: crate::tcflag_t = 0o000002; pub const IGNPAR: crate::tcflag_t = 0o000004; pub const PARMRK: crate::tcflag_t = 0o000010; pub const INPCK: crate::tcflag_t = 0o000020; pub const ISTRIP: crate::tcflag_t = 0o000040; pub const INLCR: crate::tcflag_t = 0o000100; pub const IGNCR: crate::tcflag_t = 0o000200; pub const ICRNL: crate::tcflag_t = 0o000400; pub const IUCLC: crate::tcflag_t = 0o001000; pub const IXON: crate::tcflag_t = 0o002000; pub const IXOFF: crate::tcflag_t = 0o010000; pub const IXANY: crate::tcflag_t = 0o004000; pub const IMAXBEL: crate::tcflag_t = 0o020000; pub const DOSMODE: crate::tcflag_t = 0o100000; pub const OPOST: crate::tcflag_t = 0o000001; pub const OLCUC: crate::tcflag_t = 0o000002; pub const ONLCR: crate::tcflag_t = 0o000004; pub const OCRNL: crate::tcflag_t = 0o000010; pub const ONOCR: crate::tcflag_t = 0o000020; pub const ONLRET: crate::tcflag_t = 0o000040; pub const OFILL: crate::tcflag_t = 0o0000100; pub const OFDEL: crate::tcflag_t = 0o0000200; pub const CREAD: crate::tcflag_t = 0o000200; pub const PARENB: crate::tcflag_t = 0o000400; pub const PARODD: crate::tcflag_t = 0o001000; pub const HUPCL: crate::tcflag_t = 0o002000; pub const CLOCAL: crate::tcflag_t = 0o004000; pub const CRTSXOFF: crate::tcflag_t = 0o10000000000; pub const CRTSCTS: crate::tcflag_t = 0o20000000000; pub const ISIG: crate::tcflag_t = 0o000001; pub const ICANON: crate::tcflag_t = 0o000002; pub const IEXTEN: crate::tcflag_t = 0o100000; pub const TOSTOP: crate::tcflag_t = 0o000400; pub const FLUSHO: crate::tcflag_t = 0o020000; pub const PENDIN: crate::tcflag_t = 0o040000; pub const NOFLSH: crate::tcflag_t = 0o000200; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VEOF: usize = 4; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const VTIME: usize = 5; pub const VSWTCH: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const VDSUSP: usize = 11; pub const VREPRINT: usize = 12; pub const VDISCARD: usize = 13; pub const VWERASE: usize = 14; pub const VLNEXT: usize = 15; // const STR: c_int = (b'S' as c_int) << 8; pub const I_NREAD: c_int = STR | 0o1; pub const I_PUSH: c_int = STR | 0o2; pub const I_POP: c_int = STR | 0o3; pub const I_LOOK: c_int = STR | 0o4; pub const I_FLUSH: c_int = STR | 0o5; pub const I_SRDOPT: c_int = STR | 0o6; pub const I_GRDOPT: c_int = STR | 0o7; pub const I_STR: c_int = STR | 0o10; pub const I_SETSIG: c_int = STR | 0o11; pub const I_GETSIG: c_int = STR | 0o12; pub const I_FIND: c_int = STR | 0o13; pub const I_LINK: c_int = STR | 0o14; pub const I_UNLINK: c_int = STR | 0o15; pub const I_PEEK: c_int = STR | 0o17; pub const I_FDINSERT: c_int = STR | 0o20; pub const I_SENDFD: c_int = STR | 0o21; pub const I_RECVFD: c_int = STR | 0o16; pub const I_SWROPT: c_int = STR | 0o23; pub const I_GWROPT: c_int = STR | 0o24; pub const I_LIST: c_int = STR | 0o25; pub const I_PLINK: c_int = STR | 0o26; pub const I_PUNLINK: c_int = STR | 0o27; pub const I_ANCHOR: c_int = STR | 0o30; pub const I_FLUSHBAND: c_int = STR | 0o34; pub const I_CKBAND: c_int = STR | 0o35; pub const I_GETBAND: c_int = STR | 0o36; pub const I_ATMARK: c_int = STR | 0o37; pub const I_SETCLTIME: c_int = STR | 0o40; pub const I_GETCLTIME: c_int = STR | 0o41; pub const I_CANPUT: c_int = STR | 0o42; pub const I_SERROPT: c_int = STR | 0o43; pub const I_GERROPT: c_int = STR | 0o44; pub const I_ESETSIG: c_int = STR | 0o45; pub const I_EGETSIG: c_int = STR | 0o46; pub const __I_PUSH_NOCTTY: c_int = STR | 0o47; // 3SOCKET flags pub const SOCK_CLOEXEC: c_int = 0x080000; pub const SOCK_NONBLOCK: c_int = 0x100000; pub const SOCK_NDELAY: c_int = 0x200000; // pub const SCALE_KG: c_int = 1 << 6; pub const SCALE_KF: c_int = 1 << 16; pub const SCALE_KH: c_int = 1 << 2; pub const MAXTC: c_int = 1 << 6; pub const SCALE_PHASE: c_int = 1 << 22; pub const SCALE_USEC: c_int = 1 << 16; pub const SCALE_UPDATE: c_int = SCALE_KG * MAXTC; pub const FINEUSEC: c_int = 1 << 22; pub const MAXPHASE: c_int = 512000; pub const MAXFREQ: c_int = 512 * SCALE_USEC; pub const MAXTIME: c_int = 200 << PPS_AVG; pub const MINSEC: c_int = 16; pub const MAXSEC: c_int = 1200; pub const PPS_AVG: c_int = 2; pub const PPS_SHIFT: c_int = 2; pub const PPS_SHIFTMAX: c_int = 8; pub const PPS_VALID: c_int = 120; pub const MAXGLITCH: c_int = 30; pub const MOD_OFFSET: u32 = 0x0001; pub const MOD_FREQUENCY: u32 = 0x0002; pub const MOD_MAXERROR: u32 = 0x0004; pub const MOD_ESTERROR: u32 = 0x0008; pub const MOD_STATUS: u32 = 0x0010; pub const MOD_TIMECONST: u32 = 0x0020; pub const MOD_CLKB: u32 = 0x4000; pub const MOD_CLKA: u32 = 0x8000; pub const STA_PLL: u32 = 0x0001; pub const STA_PPSFREQ: i32 = 0x0002; pub const STA_PPSTIME: i32 = 0x0004; pub const STA_FLL: i32 = 0x0008; pub const STA_INS: i32 = 0x0010; pub const STA_DEL: i32 = 0x0020; pub const STA_UNSYNC: i32 = 0x0040; pub const STA_FREQHOLD: i32 = 0x0080; pub const STA_PPSSIGNAL: i32 = 0x0100; pub const STA_PPSJITTER: i32 = 0x0200; pub const STA_PPSWANDER: i32 = 0x0400; pub const STA_PPSERROR: i32 = 0x0800; pub const STA_CLOCKERR: i32 = 0x1000; pub const STA_RONLY: i32 = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR; pub const TIME_OK: i32 = 0; pub const TIME_INS: i32 = 1; pub const TIME_DEL: i32 = 2; pub const TIME_OOP: i32 = 3; pub const TIME_WAIT: i32 = 4; pub const TIME_ERROR: i32 = 5; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; pub const SCHED_OTHER: c_int = 0; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const SCHED_SYS: c_int = 3; pub const SCHED_IA: c_int = 4; pub const SCHED_FSS: c_int = 5; pub const SCHED_FX: c_int = 6; // sys/priv.h pub const PRIV_DEBUG: c_uint = 0x0001; pub const PRIV_AWARE: c_uint = 0x0002; pub const PRIV_AWARE_INHERIT: c_uint = 0x0004; pub const __PROC_PROTECT: c_uint = 0x0008; pub const NET_MAC_AWARE: c_uint = 0x0010; pub const NET_MAC_AWARE_INHERIT: c_uint = 0x0020; pub const PRIV_AWARE_RESET: c_uint = 0x0040; pub const PRIV_XPOLICY: c_uint = 0x0080; pub const PRIV_PFEXEC: c_uint = 0x0100; // sys/systeminfo.h pub const SI_SYSNAME: c_int = 1; pub const SI_HOSTNAME: c_int = 2; pub const SI_RELEASE: c_int = 3; pub const SI_VERSION: c_int = 4; pub const SI_MACHINE: c_int = 5; pub const SI_ARCHITECTURE: c_int = 6; pub const SI_HW_SERIAL: c_int = 7; pub const SI_HW_PROVIDER: c_int = 8; pub const SI_SET_HOSTNAME: c_int = 258; pub const SI_SET_SRPC_DOMAIN: c_int = 265; pub const SI_PLATFORM: c_int = 513; pub const SI_ISALIST: c_int = 514; pub const SI_DHCP_CACHE: c_int = 515; pub const SI_ARCHITECTURE_32: c_int = 516; pub const SI_ARCHITECTURE_64: c_int = 517; pub const SI_ARCHITECTURE_K: c_int = 518; pub const SI_ARCHITECTURE_NATIVE: c_int = 519; // sys/lgrp_user.h pub const LGRP_COOKIE_NONE: crate::lgrp_cookie_t = 0; pub const LGRP_AFF_NONE: crate::lgrp_affinity_t = 0x0; pub const LGRP_AFF_WEAK: crate::lgrp_affinity_t = 0x10; pub const LGRP_AFF_STRONG: crate::lgrp_affinity_t = 0x100; pub const LGRP_CONTENT_ALL: crate::lgrp_content_t = 0; pub const LGRP_CONTENT_HIERARCHY: crate::lgrp_content_t = LGRP_CONTENT_ALL; pub const LGRP_CONTENT_DIRECT: crate::lgrp_content_t = 1; pub const LGRP_LAT_CPU_TO_MEM: crate::lgrp_lat_between_t = 0; pub const LGRP_MEM_SZ_FREE: crate::lgrp_mem_size_flag_t = 0; pub const LGRP_MEM_SZ_INSTALLED: crate::lgrp_mem_size_flag_t = 1; pub const LGRP_VIEW_CALLER: crate::lgrp_view_t = 0; pub const LGRP_VIEW_OS: crate::lgrp_view_t = 1; // sys/processor.h pub const P_OFFLINE: c_int = 0x001; pub const P_ONLINE: c_int = 0x002; pub const P_STATUS: c_int = 0x003; pub const P_FAULTED: c_int = 0x004; pub const P_POWEROFF: c_int = 0x005; pub const P_NOINTR: c_int = 0x006; pub const P_SPARE: c_int = 0x007; pub const P_FORCED: c_int = 0x10000000; pub const PI_TYPELEN: c_int = 16; pub const PI_FPUTYPE: c_int = 32; // sys/auxv.h pub const AT_SUN_HWCAP: c_uint = 2009; // As per sys/socket.h, header alignment must be 8 bytes on SPARC // and 4 bytes everywhere else: #[cfg(target_arch = "sparc64")] const _CMSG_HDR_ALIGNMENT: usize = 8; #[cfg(not(target_arch = "sparc64"))] const _CMSG_HDR_ALIGNMENT: usize = 4; const _CMSG_DATA_ALIGNMENT: usize = size_of::(); const NEWDEV: c_int = 1; // sys/sendfile.h pub const SFV_FD_SELF: c_int = -2; const_fn! { {const} fn _CMSG_HDR_ALIGN(p: usize) -> usize { (p + _CMSG_HDR_ALIGNMENT - 1) & !(_CMSG_HDR_ALIGNMENT - 1) } {const} fn _CMSG_DATA_ALIGN(p: usize) -> usize { (p + _CMSG_DATA_ALIGNMENT - 1) & !(_CMSG_DATA_ALIGNMENT - 1) } } f! { pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { _CMSG_DATA_ALIGN(cmsg.offset(1) as usize) as *mut c_uchar } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { _CMSG_DATA_ALIGN(mem::size_of::()) as c_uint + length } pub fn CMSG_FIRSTHDR(mhdr: *const crate::msghdr) -> *mut cmsghdr { if ((*mhdr).msg_controllen as usize) < size_of::() { 0 as *mut cmsghdr } else { (*mhdr).msg_control as *mut cmsghdr } } pub fn CMSG_NXTHDR(mhdr: *const crate::msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { return crate::CMSG_FIRSTHDR(mhdr); }; let next = _CMSG_HDR_ALIGN(cmsg as usize + (*cmsg).cmsg_len as usize + size_of::()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut cmsghdr } else { _CMSG_HDR_ALIGN(cmsg as usize + (*cmsg).cmsg_len as usize) as *mut cmsghdr } } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { _CMSG_HDR_ALIGN(size_of::() as usize + length as usize) as c_uint } pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] |= 1 << (fd % bits); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub fn SIGRTMAX() -> c_int { unsafe { crate::sysconf(_SC_SIGRT_MAX) as c_int } } pub fn SIGRTMIN() -> c_int { unsafe { crate::sysconf(_SC_SIGRT_MIN) as c_int } } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0xFF) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0xFF } pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0x7F } pub {const} fn WIFCONTINUED(status: c_int) -> bool { (status & 0xffff) == 0xffff } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status & 0xff00) >> 8 } pub {const} fn WIFSIGNALED(status: c_int) -> bool { ((status & 0xff) > 0) && (status & 0xff00 == 0) } pub {const} fn WIFSTOPPED(status: c_int) -> bool { ((status & 0xff) == 0x7f) && ((status & 0xff00) != 0) } pub {const} fn WCOREDUMP(status: c_int) -> bool { (status & 0x80) != 0 } pub {const} fn MR_GET_TYPE(flags: c_uint) -> c_uint { flags & 0x0000ffff } } extern "C" { pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn abs(i: c_int) -> c_int; pub fn acct(filename: *const c_char) -> c_int; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn getrandom(bbuf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn settimeofday(tp: *const crate::timeval, tz: *const c_void) -> c_int; pub fn getifaddrs(ifap: *mut *mut crate::ifaddrs) -> c_int; pub fn freeifaddrs(ifa: *mut crate::ifaddrs); pub fn stack_getbounds(sp: *mut crate::stack_t) -> c_int; pub fn getgrouplist( name: *const c_char, basegid: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn initgroups(name: *const c_char, basegid: crate::gid_t) -> c_int; pub fn setgroups(ngroups: c_int, ptr: *const crate::gid_t) -> c_int; pub fn ioctl(fildes: c_int, request: c_int, ...) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn ___errno() -> *mut c_int; pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn clock_settime(clk_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn fdatasync(fd: c_int) -> c_int; pub fn nl_langinfo_l(item: crate::nl_item, locale: crate::locale_t) -> *mut c_char; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; pub fn freelocale(loc: crate::locale_t); pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn getprogname() -> *const c_char; pub fn setprogname(name: *const c_char); pub fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int; pub fn getpriority(which: c_int, who: c_int) -> c_int; pub fn setpriority(which: c_int, who: c_int, prio: c_int) -> c_int; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn sethostname(name: *const c_char, len: c_int) -> c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_getname_np(tid: crate::pthread_t, name: *mut c_char, len: size_t) -> c_int; pub fn pthread_setname_np(tid: crate::pthread_t, name: *const c_char) -> c_int; pub fn waitid( idtype: idtype_t, id: id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; #[cfg_attr(target_os = "illumos", link_name = "_glob_ext")] pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; #[cfg_attr(target_os = "illumos", link_name = "_globfree_ext")] pub fn globfree(pglob: *mut crate::glob_t); pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const posix_spawn_file_actions_t, attrp: *const posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const posix_spawn_file_actions_t, attrp: *const posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawn_file_actions_init(file_actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(file_actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( file_actions: *mut posix_spawn_file_actions_t, fildes: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( file_actions: *mut posix_spawn_file_actions_t, fildes: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( file_actions: *mut posix_spawn_file_actions_t, fildes: c_int, newfildes: c_int, ) -> c_int; pub fn posix_spawn_file_actions_addclosefrom_np( file_actions: *mut posix_spawn_file_actions_t, lowfiledes: c_int, ) -> c_int; pub fn posix_spawn_file_actions_addchdir( file_actions: *mut posix_spawn_file_actions_t, path: *const c_char, ) -> c_int; pub fn posix_spawn_file_actions_addchdir_np( file_actions: *mut posix_spawn_file_actions_t, path: *const c_char, ) -> c_int; pub fn posix_spawn_file_actions_addfchdir( file_actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, pgroup: crate::pid_t) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, _pgroup: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const crate::sched_param, ) -> c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut crate::sched_param, ) -> c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, policy: c_int) -> c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, _policy: *mut c_int, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, sigdefault: *const sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, sigdefault: *mut sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigignore_np( attr: *mut posix_spawnattr_t, sigignore: *const sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigignore_np( attr: *const posix_spawnattr_t, sigignore: *mut sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, sigmask: *const sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, sigmask: *mut sigset_t, ) -> c_int; pub fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void; pub fn shmctl(shmid: c_int, cmd: c_int, buf: *mut crate::shmid_ds) -> c_int; pub fn shmdt(shmaddr: *const c_void) -> c_int; pub fn shmget(key: key_t, size: size_t, shmflg: c_int) -> c_int; pub fn shm_open(name: *const c_char, oflag: c_int, mode: crate::mode_t) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn memalign(align: size_t, size: size_t) -> *mut c_void; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; pub fn futimesat(fd: c_int, path: *const c_char, times: *const crate::timeval) -> c_int; pub fn futimens(dirfd: c_int, times: *const crate::timespec) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; #[link_name = "__xnet_bind"] pub fn bind( socket: c_int, address: *const crate::sockaddr, address_len: crate::socklen_t, ) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; #[link_name = "__xnet_sendmsg"] pub fn sendmsg(fd: c_int, msg: *const crate::msghdr, flags: c_int) -> ssize_t; #[link_name = "__xnet_recvmsg"] pub fn recvmsg(fd: c_int, msg: *mut crate::msghdr, flags: c_int) -> ssize_t; pub fn accept4( fd: c_int, address: *mut sockaddr, address_len: *mut socklen_t, flags: c_int, ) -> c_int; pub fn mq_open(name: *const c_char, oflag: c_int, ...) -> crate::mqd_t; pub fn mq_close(mqd: crate::mqd_t) -> c_int; pub fn mq_unlink(name: *const c_char) -> c_int; pub fn mq_receive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, ) -> ssize_t; pub fn mq_timedreceive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, abs_timeout: *const crate::timespec, ) -> ssize_t; pub fn mq_send( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, ) -> c_int; pub fn mq_timedsend( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, abs_timeout: *const crate::timespec, ) -> c_int; pub fn mq_getattr(mqd: crate::mqd_t, attr: *mut crate::mq_attr) -> c_int; pub fn mq_setattr( mqd: crate::mqd_t, newattr: *const crate::mq_attr, oldattr: *mut crate::mq_attr, ) -> c_int; pub fn port_create() -> c_int; pub fn port_associate( port: c_int, source: c_int, object: crate::uintptr_t, events: c_int, user: *mut c_void, ) -> c_int; pub fn port_dissociate(port: c_int, source: c_int, object: crate::uintptr_t) -> c_int; pub fn port_get(port: c_int, pe: *mut port_event, timeout: *mut crate::timespec) -> c_int; pub fn port_getn( port: c_int, pe_list: *mut port_event, max: c_uint, nget: *mut c_uint, timeout: *mut crate::timespec, ) -> c_int; pub fn port_send(port: c_int, events: c_int, user: *mut c_void) -> c_int; pub fn port_sendn( port_list: *mut c_int, error_list: *mut c_int, nent: c_uint, events: c_int, user: *mut c_void, ) -> c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getgrgid_r" )] pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn getdtablesize() -> c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getgrnam_r" )] pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn thr_self() -> crate::thread_t; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const c_char) -> *mut crate::group; #[cfg_attr(target_os = "solaris", link_name = "__pthread_kill_xpg7")] pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sched_get_priority_min(policy: c_int) -> c_int; pub fn sched_get_priority_max(policy: c_int) -> c_int; pub fn sched_getparam(pid: crate::pid_t, param: *mut sched_param) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const sched_param) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getpwnam_r" )] pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getpwuid_r" )] pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "getpwent_r" )] fn native_getpwent_r(pwd: *mut passwd, buf: *mut c_char, buflen: c_int) -> *mut passwd; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "getgrent_r" )] fn native_getgrent_r( grp: *mut crate::group, buf: *mut c_char, buflen: c_int, ) -> *mut crate::group; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_sigwait" )] pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut crate::group; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn dup3(src: c_int, dst: c_int, flags: c_int) -> c_int; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; pub fn makeutx(ux: *const utmpx) -> *mut utmpx; pub fn modutx(ux: *const utmpx) -> *mut utmpx; pub fn updwtmpx(file: *const c_char, ut: *mut utmpx); pub fn utmpxname(file: *const c_char) -> c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn endutent(); pub fn getutent() -> *mut utmp; pub fn getutid(u: *const utmp) -> *mut utmp; pub fn getutline(u: *const utmp) -> *mut utmp; pub fn pututline(u: *const utmp) -> *mut utmp; pub fn setutent(); pub fn utmpname(file: *const c_char) -> c_int; pub fn getutmp(ux: *const utmpx, u: *mut utmp); pub fn getutmpx(u: *const utmp, ux: *mut utmpx); pub fn updwtmp(file: *const c_char, u: *mut utmp); pub fn ntp_adjtime(buf: *mut timex) -> c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> c_int; pub fn timer_create(clock_id: clockid_t, evp: *mut sigevent, timerid: *mut timer_t) -> c_int; pub fn timer_delete(timerid: timer_t) -> c_int; pub fn timer_getoverrun(timerid: timer_t) -> c_int; pub fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> c_int; pub fn timer_settime( timerid: timer_t, flags: c_int, value: *const itimerspec, ovalue: *mut itimerspec, ) -> c_int; pub fn ucred_get(pid: crate::pid_t) -> *mut ucred_t; pub fn getpeerucred(fd: c_int, ucred: *mut *mut ucred_t) -> c_int; pub fn ucred_free(ucred: *mut ucred_t); pub fn ucred_geteuid(ucred: *const ucred_t) -> crate::uid_t; pub fn ucred_getruid(ucred: *const ucred_t) -> crate::uid_t; pub fn ucred_getsuid(ucred: *const ucred_t) -> crate::uid_t; pub fn ucred_getegid(ucred: *const ucred_t) -> crate::gid_t; pub fn ucred_getrgid(ucred: *const ucred_t) -> crate::gid_t; pub fn ucred_getsgid(ucred: *const ucred_t) -> crate::gid_t; pub fn ucred_getgroups(ucred: *const ucred_t, groups: *mut *const crate::gid_t) -> c_int; pub fn ucred_getpid(ucred: *const ucred_t) -> crate::pid_t; pub fn ucred_getprojid(ucred: *const ucred_t) -> projid_t; pub fn ucred_getzoneid(ucred: *const ucred_t) -> zoneid_t; pub fn ucred_getpflags(ucred: *const ucred_t, flags: c_uint) -> c_uint; pub fn ucred_size() -> size_t; pub fn pset_create(newpset: *mut crate::psetid_t) -> c_int; pub fn pset_destroy(pset: crate::psetid_t) -> c_int; pub fn pset_assign( pset: crate::psetid_t, cpu: crate::processorid_t, opset: *mut psetid_t, ) -> c_int; pub fn pset_info( pset: crate::psetid_t, tpe: *mut c_int, numcpus: *mut c_uint, cpulist: *mut processorid_t, ) -> c_int; pub fn pset_bind( pset: crate::psetid_t, idtype: crate::idtype_t, id: crate::id_t, opset: *mut psetid_t, ) -> c_int; pub fn pset_list(pset: *mut psetid_t, numpsets: *mut c_uint) -> c_int; pub fn pset_setattr(pset: psetid_t, attr: c_uint) -> c_int; pub fn pset_getattr(pset: psetid_t, attr: *mut c_uint) -> c_int; pub fn processor_bind( idtype: crate::idtype_t, id: crate::id_t, new_binding: crate::processorid_t, old_binding: *mut processorid_t, ) -> c_int; pub fn p_online(processorid: crate::processorid_t, flag: c_int) -> c_int; pub fn processor_info(processorid: crate::processorid_t, infop: *mut processor_info_t) -> c_int; pub fn getexecname() -> *const c_char; pub fn gethostid() -> c_long; pub fn getpflags(flags: c_uint) -> c_uint; pub fn setpflags(flags: c_uint, value: c_uint) -> c_int; pub fn sysinfo(command: c_int, buf: *mut c_char, count: c_long) -> c_int; pub fn faccessat(fd: c_int, path: *const c_char, amode: c_int, flag: c_int) -> c_int; // #include #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn(info: *mut dl_phdr_info, size: usize, data: *mut c_void) -> c_int, >, data: *mut c_void, ) -> c_int; pub fn getpagesize() -> c_int; pub fn getpagesizes(pagesize: *mut size_t, nelem: c_int) -> c_int; pub fn mmapobj( fd: c_int, flags: c_uint, storage: *mut mmapobj_result_t, elements: *mut c_uint, arg: *mut c_void, ) -> c_int; pub fn meminfo( inaddr: *const u64, addr_count: c_int, info_req: *const c_uint, info_count: c_int, outdata: *mut u64, validity: *mut c_uint, ) -> c_int; pub fn strsep(string: *mut *mut c_char, delim: *const c_char) -> *mut c_char; pub fn getisax(array: *mut u32, n: c_uint) -> c_uint; pub fn backtrace(buffer: *mut *mut c_void, size: c_int) -> c_int; pub fn backtrace_symbols(buffer: *const *mut c_void, size: c_int) -> *mut *mut c_char; pub fn backtrace_symbols_fd(buffer: *const *mut c_void, size: c_int, fd: c_int); pub fn getopt_long( argc: c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut c_int, ) -> c_int; pub fn sync(); pub fn aio_cancel(fd: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_error(aiocbp: *const aiocb) -> c_int; pub fn aio_fsync(op: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_read(aiocbp: *mut aiocb) -> c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn aio_waitn( aiocb_list: *mut *mut aiocb, nent: c_uint, nwait: *mut c_uint, timeout: *const crate::timespec, ) -> c_int; pub fn aio_write(aiocbp: *mut aiocb) -> c_int; pub fn lio_listio( mode: c_int, aiocb_list: *const *mut aiocb, nitems: c_int, sevp: *mut sigevent, ) -> c_int; pub fn __major(version: c_int, devnum: crate::dev_t) -> crate::major_t; pub fn __minor(version: c_int, devnum: crate::dev_t) -> crate::minor_t; pub fn __makedev( version: c_int, majdev: crate::major_t, mindev: crate::minor_t, ) -> crate::dev_t; pub fn arc4random() -> u32; pub fn arc4random_buf(buf: *mut c_void, nbytes: size_t); pub fn arc4random_uniform(upper_bound: u32) -> u32; pub fn secure_getenv(name: *const c_char) -> *mut c_char; } #[link(name = "sendfile")] extern "C" { pub fn sendfile(out_fd: c_int, in_fd: c_int, off: *mut off_t, len: size_t) -> ssize_t; pub fn sendfilev( fildes: c_int, vec: *const sendfilevec_t, sfvcnt: c_int, xferred: *mut size_t, ) -> ssize_t; } #[link(name = "lgrp")] extern "C" { pub fn lgrp_init(view: lgrp_view_t) -> lgrp_cookie_t; pub fn lgrp_fini(cookie: lgrp_cookie_t) -> c_int; pub fn lgrp_affinity_get( idtype: crate::idtype_t, id: crate::id_t, lgrp: crate::lgrp_id_t, ) -> crate::lgrp_affinity_t; pub fn lgrp_affinity_set( idtype: crate::idtype_t, id: crate::id_t, lgrp: crate::lgrp_id_t, aff: lgrp_affinity_t, ) -> c_int; pub fn lgrp_cpus( cookie: crate::lgrp_cookie_t, lgrp: crate::lgrp_id_t, cpuids: *mut crate::processorid_t, count: c_uint, content: crate::lgrp_content_t, ) -> c_int; pub fn lgrp_mem_size( cookie: crate::lgrp_cookie_t, lgrp: crate::lgrp_id_t, tpe: crate::lgrp_mem_size_flag_t, content: crate::lgrp_content_t, ) -> crate::lgrp_mem_size_t; pub fn lgrp_nlgrps(cookie: crate::lgrp_cookie_t) -> c_int; pub fn lgrp_view(cookie: crate::lgrp_cookie_t) -> crate::lgrp_view_t; pub fn lgrp_home(idtype: crate::idtype_t, id: crate::id_t) -> crate::lgrp_id_t; pub fn lgrp_version(version: c_int) -> c_int; pub fn lgrp_resources( cookie: crate::lgrp_cookie_t, lgrp: crate::lgrp_id_t, lgrps: *mut crate::lgrp_id_t, count: c_uint, tpe: crate::lgrp_rsrc_t, ) -> c_int; pub fn lgrp_root(cookie: crate::lgrp_cookie_t) -> crate::lgrp_id_t; } pub unsafe fn major(device: crate::dev_t) -> crate::major_t { __major(NEWDEV, device) } pub unsafe fn minor(device: crate::dev_t) -> crate::minor_t { __minor(NEWDEV, device) } pub unsafe fn makedev(maj: crate::major_t, min: crate::minor_t) -> crate::dev_t { __makedev(NEWDEV, maj, min) } mod compat; pub use self::compat::*; cfg_if! { if #[cfg(target_os = "illumos")] { mod illumos; pub use self::illumos::*; } else if #[cfg(target_os = "solaris")] { mod solaris; pub use self::solaris::*; } else { // Unknown target_os } } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; mod x86_common; pub use self::x86_64::*; pub use self::x86_common::*; } else if #[cfg(target_arch = "x86")] { mod x86; mod x86_common; pub use self::x86::*; pub use self::x86_common::*; } } libc/src/unix/solarish/solaris.rs0000644000175000017500000001765415105742312016750 0ustar bdrungbdrunguse crate::prelude::*; use crate::{ exit_status, off_t, termios, NET_MAC_AWARE, NET_MAC_AWARE_INHERIT, PRIV_AWARE_RESET, PRIV_DEBUG, PRIV_PFEXEC, PRIV_XPOLICY, }; pub type door_attr_t = c_uint; pub type door_id_t = c_ulonglong; pub type lgrp_affinity_t = c_uint; e! { #[repr(u32)] pub enum lgrp_rsrc_t { LGRP_RSRC_CPU = 0, LGRP_RSRC_MEM = 1, LGRP_RSRC_TYPES = 2, } } s! { pub struct aiocb { pub aio_fildes: c_int, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_offset: off_t, pub aio_reqprio: c_int, pub aio_sigevent: crate::sigevent, pub aio_lio_opcode: c_int, pub aio_resultp: crate::aio_result_t, pub aio_state: c_char, pub aio_returned: c_char, pub aio__pad1: [c_char; 2], pub aio_flags: c_int, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_flags: crate::uintptr_t, pub shm_lkcnt: c_ushort, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_cnattch: c_ulong, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_amp: *mut c_void, pub shm_gransize: u64, pub shm_allocated: u64, pub shm_pad4: [i64; 1], } pub struct xrs_t { pub xrs_id: c_ulong, pub xrs_ptr: *mut c_char, } } s_no_extra_traits! { #[repr(packed)] #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] pub struct door_desc_t__d_data__d_desc { pub d_descriptor: c_int, pub d_id: crate::door_id_t, } pub union door_desc_t__d_data { pub d_desc: door_desc_t__d_data__d_desc, d_resv: [c_int; 5], /* Check out /usr/include/sys/door.h */ } #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] pub struct door_desc_t { pub d_attributes: door_attr_t, pub d_data: door_desc_t__d_data, } #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] pub struct door_arg_t { pub data_ptr: *const c_char, pub data_size: size_t, pub desc_ptr: *const door_desc_t, pub dec_num: c_uint, pub rbuf: *const c_char, pub rsize: size_t, } pub struct utmpx { pub ut_user: [c_char; _UTMP_USER_LEN], pub ut_id: [c_char; _UTMP_ID_LEN], pub ut_line: [c_char; _UTMP_LINE_LEN], pub ut_pid: crate::pid_t, pub ut_type: c_short, pub ut_exit: exit_status, pub ut_tv: crate::timeval, pub ut_session: c_int, pub pad: [c_int; 5], pub ut_syslen: c_short, pub ut_host: [c_char; 257], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_user == other.ut_user && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_syslen == other.ut_syslen && self.pad == other.pad && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_user", &self.ut_user) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) .field("ut_pid", &self.ut_pid) .field("ut_type", &self.ut_type) .field("ut_exit", &self.ut_exit) .field("ut_tv", &self.ut_tv) .field("ut_session", &self.ut_session) .field("pad", &self.pad) .field("ut_syslen", &self.ut_syslen) .field("ut_host", &&self.ut_host[..]) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_user.hash(state); self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_syslen.hash(state); self.pad.hash(state); } } } } // FIXME(solaris): O_DIRECT and SIGINFO are NOT available on Solaris. // But in past they were defined here and thus other crates expected them. // Latest version v0.29.0 of Nix crate still expects this. Since last // version of Nix crate is almost one year ago let's define these two // temporarily before new Nix version is released. pub const O_DIRECT: c_int = 0x2000000; pub const SIGINFO: c_int = 41; pub const _UTMP_USER_LEN: usize = 32; pub const _UTMP_LINE_LEN: usize = 32; pub const _UTMP_ID_LEN: usize = 4; pub const PORT_SOURCE_POSTWAIT: c_int = 8; pub const PORT_SOURCE_SIGNAL: c_int = 9; pub const AF_LOCAL: c_int = 1; // AF_UNIX pub const AF_FILE: c_int = 1; // AF_UNIX pub const TCP_KEEPIDLE: c_int = 0x1d; pub const TCP_KEEPINTVL: c_int = 0x1e; pub const TCP_KEEPCNT: c_int = 0x1f; pub const F_DUPFD_CLOEXEC: c_int = 47; pub const F_DUPFD_CLOFORK: c_int = 49; pub const F_DUP2FD_CLOEXEC: c_int = 48; pub const F_DUP2FD_CLOFORK: c_int = 50; pub const _PC_LAST: c_int = 102; pub const PRIV_PROC_SENSITIVE: c_uint = 0x0008; pub const PRIV_PFEXEC_AUTH: c_uint = 0x0200; pub const PRIV_PROC_TPD: c_uint = 0x0400; pub const PRIV_TPD_UNSAFE: c_uint = 0x0800; pub const PRIV_PROC_TPD_RESET: c_uint = 0x1000; pub const PRIV_TPD_KILLABLE: c_uint = 0x2000; pub const POSIX_SPAWN_SETSID: c_short = 0x400; pub const PRIV_USER: c_uint = PRIV_DEBUG | PRIV_PROC_SENSITIVE | NET_MAC_AWARE | NET_MAC_AWARE_INHERIT | PRIV_XPOLICY | PRIV_AWARE_RESET | PRIV_PFEXEC | PRIV_PFEXEC_AUTH | PRIV_PROC_TPD | PRIV_TPD_UNSAFE | PRIV_TPD_KILLABLE | PRIV_PROC_TPD_RESET; extern "C" { // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn fexecve(fd: c_int, argv: *const *const c_char, envp: *const *const c_char) -> c_int; pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_char) -> c_int; pub fn door_call(d: c_int, params: *mut door_arg_t) -> c_int; pub fn door_return( data_ptr: *mut c_char, data_size: size_t, desc_ptr: *mut door_desc_t, num_desc: c_uint, ) -> c_int; pub fn door_create( server_procedure: extern "C" fn( cookie: *mut c_void, argp: *mut c_char, arg_size: size_t, dp: *mut door_desc_t, n_desc: c_uint, ), cookie: *mut c_void, attributes: door_attr_t, ) -> c_int; pub fn fattach(fildes: c_int, path: *const c_char) -> c_int; pub fn pthread_getattr_np(thread: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn euidaccess(path: *const c_char, amode: c_int) -> c_int; pub fn openpty( amain: *mut c_int, asubord: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> c_int; pub fn forkpty( amain: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> crate::pid_t; } libc/src/unix/solarish/x86.rs0000644000175000017500000000151315105742312015704 0ustar bdrungbdrunguse crate::prelude::*; pub type Elf32_Addr = c_ulong; pub type Elf32_Half = c_ushort; pub type Elf32_Off = c_ulong; pub type Elf32_Sword = c_long; pub type Elf32_Word = c_ulong; pub type Elf32_Lword = c_ulonglong; pub type Elf32_Phdr = __c_anonymous_Elf32_Phdr; s! { pub struct __c_anonymous_Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct dl_phdr_info { pub dlpi_addr: Elf32_Addr, pub dlpi_name: *const c_char, pub dlpi_phdr: *const Elf32_Phdr, pub dlpi_phnum: Elf32_Half, pub dlpi_adds: c_ulonglong, pub dlpi_subs: c_ulonglong, } } libc/src/unix/solarish/compat.rs0000644000175000017500000001507215105742312016547 0ustar bdrungbdrung// Common functions that are unfortunately missing on illumos and // Solaris, but often needed by other crates. use core::cmp::min; use crate::unix::solarish::*; use crate::{c_char, c_int, size_t}; const PTEM: &[u8] = b"ptem\0"; const LDTERM: &[u8] = b"ldterm\0"; pub unsafe fn cfmakeraw(termios: *mut crate::termios) { (*termios).c_iflag &= !(IMAXBEL | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); (*termios).c_oflag &= !OPOST; (*termios).c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN); (*termios).c_cflag &= !(CSIZE | PARENB); (*termios).c_cflag |= CS8; // By default, most software expects a pending read to block until at // least one byte becomes available. As per termio(7I), this requires // setting the MIN and TIME parameters appropriately. // // As a somewhat unfortunate artefact of history, the MIN and TIME slots // in the control character array overlap with the EOF and EOL slots used // for canonical mode processing. Because the EOF character needs to be // the ASCII EOT value (aka Control-D), it has the byte value 4. When // switching to raw mode, this is interpreted as a MIN value of 4; i.e., // reads will block until at least four bytes have been input. // // Other platforms with a distinct MIN slot like Linux and FreeBSD appear // to default to a MIN value of 1, so we'll force that value here: (*termios).c_cc[VMIN] = 1; (*termios).c_cc[VTIME] = 0; } pub unsafe fn cfsetspeed(termios: *mut crate::termios, speed: crate::speed_t) -> c_int { // Neither of these functions on illumos or Solaris actually ever // return an error crate::cfsetispeed(termios, speed); crate::cfsetospeed(termios, speed); 0 } unsafe fn bail(fdm: c_int, fds: c_int) -> c_int { let e = *___errno(); if fds >= 0 { crate::close(fds); } if fdm >= 0 { crate::close(fdm); } *___errno() = e; return -1; } #[cfg(target_os = "illumos")] pub unsafe fn openpty( amain: *mut c_int, asubord: *mut c_int, name: *mut c_char, termp: *const termios, winp: *const crate::winsize, ) -> c_int { // Open the main pseudo-terminal device, making sure not to set it as the // controlling terminal for this process: let fdm = crate::posix_openpt(O_RDWR | O_NOCTTY); if fdm < 0 { return -1; } // Set permissions and ownership on the subordinate device and unlock it: if crate::grantpt(fdm) < 0 || crate::unlockpt(fdm) < 0 { return bail(fdm, -1); } // Get the path name of the subordinate device: let subordpath = crate::ptsname(fdm); if subordpath.is_null() { return bail(fdm, -1); } // Open the subordinate device without setting it as the controlling // terminal for this process: let fds = crate::open(subordpath, O_RDWR | O_NOCTTY); if fds < 0 { return bail(fdm, -1); } // Check if the STREAMS modules are already pushed: let setup = crate::ioctl(fds, I_FIND, LDTERM.as_ptr()); if setup < 0 { return bail(fdm, fds); } else if setup == 0 { // The line discipline is not present, so push the appropriate STREAMS // modules for the subordinate device: if crate::ioctl(fds, I_PUSH, PTEM.as_ptr()) < 0 || crate::ioctl(fds, I_PUSH, LDTERM.as_ptr()) < 0 { return bail(fdm, fds); } } // If provided, set the terminal parameters: if !termp.is_null() && crate::tcsetattr(fds, TCSAFLUSH, termp) != 0 { return bail(fdm, fds); } // If provided, set the window size: if !winp.is_null() && crate::ioctl(fds, TIOCSWINSZ, winp) < 0 { return bail(fdm, fds); } // If the caller wants the name of the subordinate device, copy it out. // // Note that this is a terrible interface: there appears to be no standard // upper bound on the copy length for this pointer. Nobody should pass // anything but NULL here, preferring instead to use ptsname(3C) directly. if !name.is_null() { crate::strcpy(name, subordpath); } *amain = fdm; *asubord = fds; 0 } #[cfg(target_os = "illumos")] pub unsafe fn forkpty( amain: *mut c_int, name: *mut c_char, termp: *const termios, winp: *const crate::winsize, ) -> crate::pid_t { let mut fds = -1; if openpty(amain, &mut fds, name, termp, winp) != 0 { return -1; } let pid = crate::fork(); if pid < 0 { return bail(*amain, fds); } else if pid > 0 { // In the parent process, we close the subordinate device and return the // process ID of the new child: crate::close(fds); return pid; } // The rest of this function executes in the child process. // Close the main side of the pseudo-terminal pair: crate::close(*amain); // Use TIOCSCTTY to set the subordinate device as our controlling // terminal. This will fail (with ENOTTY) if we are not the leader in // our own session, so we call setsid() first. Finally, arrange for // the pseudo-terminal to occupy the standard I/O descriptors. if crate::setsid() < 0 || crate::ioctl(fds, TIOCSCTTY, 0) < 0 || crate::dup2(fds, 0) < 0 || crate::dup2(fds, 1) < 0 || crate::dup2(fds, 2) < 0 { // At this stage there are no particularly good ways to handle failure. // Exit as abruptly as possible, using _exit() to avoid messing with any // state still shared with the parent process. crate::_exit(EXIT_FAILURE); } // Close the inherited descriptor, taking care to avoid closing the standard // descriptors by mistake: if fds > 2 { crate::close(fds); } 0 } pub unsafe fn getpwent_r( pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int { let old_errno = *crate::___errno(); *crate::___errno() = 0; *result = native_getpwent_r(pwd, buf, min(buflen, c_int::max_value() as size_t) as c_int); let ret = if (*result).is_null() { *crate::___errno() } else { 0 }; *crate::___errno() = old_errno; ret } pub unsafe fn getgrent_r( grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int { let old_errno = *crate::___errno(); *crate::___errno() = 0; *result = native_getgrent_r(grp, buf, min(buflen, c_int::max_value() as size_t) as c_int); let ret = if (*result).is_null() { *crate::___errno() } else { 0 }; *crate::___errno() = old_errno; ret } libc/src/unix/solarish/x86_64.rs0000644000175000017500000001376115105742312016225 0ustar bdrungbdrunguse crate::prelude::*; cfg_if! { if #[cfg(target_os = "solaris")] { use crate::unix::solarish::solaris; } } pub type greg_t = c_long; pub type Elf64_Addr = c_ulong; pub type Elf64_Half = c_ushort; pub type Elf64_Off = c_ulong; pub type Elf64_Sword = c_int; pub type Elf64_Sxword = c_long; pub type Elf64_Word = c_uint; pub type Elf64_Xword = c_ulong; pub type Elf64_Lword = c_ulong; pub type Elf64_Phdr = __c_anonymous_Elf64_Phdr; s! { pub struct __c_anonymous_fpchip_state { pub cw: u16, pub sw: u16, pub fctw: u8, pub __fx_rsvd: u8, pub fop: u16, pub rip: u64, pub rdp: u64, pub mxcsr: u32, pub mxcsr_mask: u32, pub st: [crate::upad128_t; 8], pub xmm: [crate::upad128_t; 16], pub __fx_ign: [crate::upad128_t; 6], pub status: u32, pub xstatus: u32, } pub struct __c_anonymous_Elf64_Phdr { pub p_type: crate::Elf64_Word, pub p_flags: crate::Elf64_Word, pub p_offset: crate::Elf64_Off, pub p_vaddr: crate::Elf64_Addr, pub p_paddr: crate::Elf64_Addr, pub p_filesz: crate::Elf64_Xword, pub p_memsz: crate::Elf64_Xword, pub p_align: crate::Elf64_Xword, } pub struct dl_phdr_info { pub dlpi_addr: crate::Elf64_Addr, pub dlpi_name: *const c_char, pub dlpi_phdr: *const crate::Elf64_Phdr, pub dlpi_phnum: crate::Elf64_Half, pub dlpi_adds: c_ulonglong, pub dlpi_subs: c_ulonglong, #[cfg(target_os = "solaris")] pub dlpi_tls_modid: c_ulong, #[cfg(target_os = "solaris")] pub dlpi_tls_data: *mut c_void, } } s_no_extra_traits! { pub union __c_anonymous_fp_reg_set { pub fpchip_state: __c_anonymous_fpchip_state, pub f_fpregs: [[u32; 13]; 10], } pub struct fpregset_t { pub fp_reg_set: __c_anonymous_fp_reg_set, } pub struct mcontext_t { pub gregs: [crate::greg_t; 28], pub fpregs: fpregset_t, } pub struct ucontext_t { pub uc_flags: c_ulong, pub uc_link: *mut ucontext_t, pub uc_sigmask: crate::sigset_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, #[cfg(target_os = "illumos")] pub uc_brand_data: [*mut c_void; 3], #[cfg(target_os = "illumos")] pub uc_xsave: c_long, #[cfg(target_os = "illumos")] pub uc_filler: c_long, #[cfg(target_os = "solaris")] pub uc_xrs: solaris::xrs_t, #[cfg(target_os = "solaris")] pub uc_filler: [c_long; 3], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __c_anonymous_fp_reg_set { fn eq(&self, other: &__c_anonymous_fp_reg_set) -> bool { unsafe { self.fpchip_state == other.fpchip_state || self .f_fpregs .iter() .zip(other.f_fpregs.iter()) .all(|(a, b)| a == b) } } } impl Eq for __c_anonymous_fp_reg_set {} impl PartialEq for fpregset_t { fn eq(&self, other: &fpregset_t) -> bool { self.fp_reg_set == other.fp_reg_set } } impl Eq for fpregset_t {} impl fmt::Debug for fpregset_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fpregset_t") .field("fp_reg_set", &self.fp_reg_set) .finish() } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.gregs == other.gregs && self.fpregs == other.fpregs } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("gregs", &self.gregs) .field("fpregs", &self.fpregs) .finish() } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_sigmask == other.uc_sigmask && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_filler == other.uc_filler } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_sigmask", &self.uc_sigmask) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_filler", &self.uc_filler) .finish() } } } } // sys/regset.h pub const REG_GSBASE: c_int = 27; pub const REG_FSBASE: c_int = 26; pub const REG_DS: c_int = 25; pub const REG_ES: c_int = 24; pub const REG_GS: c_int = 23; pub const REG_FS: c_int = 22; pub const REG_SS: c_int = 21; pub const REG_RSP: c_int = 20; pub const REG_RFL: c_int = 19; pub const REG_CS: c_int = 18; pub const REG_RIP: c_int = 17; pub const REG_ERR: c_int = 16; pub const REG_TRAPNO: c_int = 15; pub const REG_RAX: c_int = 14; pub const REG_RCX: c_int = 13; pub const REG_RDX: c_int = 12; pub const REG_RBX: c_int = 11; pub const REG_RBP: c_int = 10; pub const REG_RSI: c_int = 9; pub const REG_RDI: c_int = 8; pub const REG_R8: c_int = 7; pub const REG_R9: c_int = 6; pub const REG_R10: c_int = 5; pub const REG_R11: c_int = 4; pub const REG_R12: c_int = 3; pub const REG_R13: c_int = 2; pub const REG_R14: c_int = 1; pub const REG_R15: c_int = 0; libc/src/unix/solarish/x86_common.rs0000644000175000017500000000577615105742312017273 0ustar bdrungbdrung// AT_SUN_HWCAP pub const AV_386_FPU: u32 = 0x00001; pub const AV_386_TSC: u32 = 0x00002; pub const AV_386_CX8: u32 = 0x00004; pub const AV_386_SEP: u32 = 0x00008; pub const AV_386_AMD_SYSC: u32 = 0x00010; pub const AV_386_CMOV: u32 = 0x00020; pub const AV_386_MMX: u32 = 0x00040; pub const AV_386_AMD_MMX: u32 = 0x00080; pub const AV_386_AMD_3DNow: u32 = 0x00100; pub const AV_386_AMD_3DNowx: u32 = 0x00200; pub const AV_386_FXSR: u32 = 0x00400; pub const AV_386_SSE: u32 = 0x00800; pub const AV_386_SSE2: u32 = 0x01000; pub const AV_386_CX16: u32 = 0x10000; pub const AV_386_AHF: u32 = 0x20000; pub const AV_386_TSCP: u32 = 0x40000; pub const AV_386_AMD_SSE4A: u32 = 0x80000; pub const AV_386_POPCNT: u32 = 0x100000; pub const AV_386_AMD_LZCNT: u32 = 0x200000; pub const AV_386_SSSE3: u32 = 0x400000; pub const AV_386_SSE4_1: u32 = 0x800000; pub const AV_386_SSE4_2: u32 = 0x1000000; pub const AV_386_MOVBE: u32 = 0x2000000; pub const AV_386_AES: u32 = 0x4000000; pub const AV_386_PCLMULQDQ: u32 = 0x8000000; pub const AV_386_XSAVE: u32 = 0x10000000; pub const AV_386_AVX: u32 = 0x20000000; cfg_if! { if #[cfg(target_os = "illumos")] { pub const AV_386_VMX: u32 = 0x40000000; pub const AV_386_AMD_SVM: u32 = 0x80000000; // AT_SUN_HWCAP2 pub const AV_386_2_F16C: u32 = 0x00000001; pub const AV_386_2_RDRAND: u32 = 0x00000002; pub const AV_386_2_BMI1: u32 = 0x00000004; pub const AV_386_2_BMI2: u32 = 0x00000008; pub const AV_386_2_FMA: u32 = 0x00000010; pub const AV_386_2_AVX2: u32 = 0x00000020; pub const AV_386_2_ADX: u32 = 0x00000040; pub const AV_386_2_RDSEED: u32 = 0x00000080; pub const AV_386_2_AVX512F: u32 = 0x00000100; pub const AV_386_2_AVX512DQ: u32 = 0x00000200; pub const AV_386_2_AVX512IFMA: u32 = 0x00000400; pub const AV_386_2_AVX512PF: u32 = 0x00000800; pub const AV_386_2_AVX512ER: u32 = 0x00001000; pub const AV_386_2_AVX512CD: u32 = 0x00002000; pub const AV_386_2_AVX512BW: u32 = 0x00004000; pub const AV_386_2_AVX512VL: u32 = 0x00008000; pub const AV_386_2_AVX512VBMI: u32 = 0x00010000; pub const AV_386_2_AVX512VPOPCDQ: u32 = 0x00020000; pub const AV_386_2_AVX512_4NNIW: u32 = 0x00040000; pub const AV_386_2_AVX512_4FMAPS: u32 = 0x00080000; pub const AV_386_2_SHA: u32 = 0x00100000; pub const AV_386_2_FSGSBASE: u32 = 0x00200000; pub const AV_386_2_CLFLUSHOPT: u32 = 0x00400000; pub const AV_386_2_CLWB: u32 = 0x00800000; pub const AV_386_2_MONITORX: u32 = 0x01000000; pub const AV_386_2_CLZERO: u32 = 0x02000000; pub const AV_386_2_AVX512_VNNI: u32 = 0x04000000; pub const AV_386_2_VPCLMULQDQ: u32 = 0x08000000; pub const AV_386_2_VAES: u32 = 0x10000000; // AT_SUN_FPTYPE pub const AT_386_FPINFO_NONE: u32 = 0; pub const AT_386_FPINFO_FXSAVE: u32 = 1; pub const AT_386_FPINFO_XSAVE: u32 = 2; pub const AT_386_FPINFO_XSAVE_AMD: u32 = 3; } } libc/src/unix/solarish/illumos.rs0000644000175000017500000002713315105742312016751 0ustar bdrungbdrunguse crate::prelude::*; use crate::{ exit_status, off_t, NET_MAC_AWARE, NET_MAC_AWARE_INHERIT, PRIV_AWARE_RESET, PRIV_DEBUG, PRIV_PFEXEC, PRIV_XPOLICY, }; pub type lgrp_rsrc_t = c_int; pub type lgrp_affinity_t = c_int; s! { pub struct aiocb { pub aio_fildes: c_int, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_offset: off_t, pub aio_reqprio: c_int, pub aio_sigevent: crate::sigevent, pub aio_lio_opcode: c_int, pub aio_resultp: crate::aio_result_t, pub aio_state: c_int, pub aio__pad: [c_int; 1], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_amp: *mut c_void, pub shm_lkcnt: c_ushort, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_cnattch: c_ulong, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, pub shm_pad4: [i64; 4], } pub struct fil_info { pub fi_flags: c_int, pub fi_pos: c_int, pub fi_name: [c_char; crate::FILNAME_MAX as usize], } } s_no_extra_traits! { #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), repr(packed(4)))] pub struct epoll_event { pub events: u32, pub u64: u64, } pub struct utmpx { pub ut_user: [c_char; _UTX_USERSIZE], pub ut_id: [c_char; _UTX_IDSIZE], pub ut_line: [c_char; _UTX_LINESIZE], pub ut_pid: crate::pid_t, pub ut_type: c_short, pub ut_exit: exit_status, pub ut_tv: crate::timeval, pub ut_session: c_int, pub ut_pad: [c_int; _UTX_PADSIZE], pub ut_syslen: c_short, pub ut_host: [c_char; _UTX_HOSTSIZE], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_user == other.ut_user && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_syslen == other.ut_syslen && self.ut_pad == other.ut_pad && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_user", &self.ut_user) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) .field("ut_pid", &self.ut_pid) .field("ut_type", &self.ut_type) .field("ut_exit", &self.ut_exit) .field("ut_tv", &self.ut_tv) .field("ut_session", &self.ut_session) .field("ut_pad", &self.ut_pad) .field("ut_syslen", &self.ut_syslen) .field("ut_host", &&self.ut_host[..]) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_user.hash(state); self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_syslen.hash(state); self.ut_pad.hash(state); } } impl PartialEq for epoll_event { fn eq(&self, other: &epoll_event) -> bool { self.events == other.events && self.u64 == other.u64 } } impl Eq for epoll_event {} impl fmt::Debug for epoll_event { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let events = self.events; let u64 = self.u64; f.debug_struct("epoll_event") .field("events", &events) .field("u64", &u64) .finish() } } impl hash::Hash for epoll_event { fn hash(&self, state: &mut H) { let events = self.events; let u64 = self.u64; events.hash(state); u64.hash(state); } } } } pub const _UTX_USERSIZE: usize = 32; pub const _UTX_LINESIZE: usize = 32; pub const _UTX_PADSIZE: usize = 5; pub const _UTX_IDSIZE: usize = 4; pub const _UTX_HOSTSIZE: usize = 257; pub const AF_LOCAL: c_int = 1; // AF_UNIX pub const AF_FILE: c_int = 1; // AF_UNIX pub const EFD_SEMAPHORE: c_int = 0x1; pub const EFD_NONBLOCK: c_int = 0x800; pub const EFD_CLOEXEC: c_int = 0x80000; pub const POLLRDHUP: c_short = 0x4000; pub const TCP_KEEPIDLE: c_int = 34; pub const TCP_KEEPCNT: c_int = 35; pub const TCP_KEEPINTVL: c_int = 36; pub const TCP_CONGESTION: c_int = 37; // These constants are correct for 64-bit programs or 32-bit programs that are // not using large-file mode. If Rust ever supports anything other than 64-bit // compilation on illumos, this may require adjustment: pub const F_OFD_GETLK: c_int = 47; pub const F_OFD_SETLK: c_int = 48; pub const F_OFD_SETLKW: c_int = 49; pub const F_FLOCK: c_int = 53; pub const F_FLOCKW: c_int = 54; pub const F_DUPFD_CLOEXEC: c_int = 37; pub const F_DUPFD_CLOFORK: c_int = 58; pub const F_DUP2FD_CLOEXEC: c_int = 36; pub const F_DUP2FD_CLOFORK: c_int = 57; pub const F_DUP3FD: c_int = 59; pub const FD_CLOFORK: c_int = 2; pub const FIL_ATTACH: c_int = 0x1; pub const FIL_DETACH: c_int = 0x2; pub const FIL_LIST: c_int = 0x3; pub const FILNAME_MAX: c_int = 32; pub const FILF_PROG: c_int = 0x1; pub const FILF_AUTO: c_int = 0x2; pub const FILF_BYPASS: c_int = 0x4; pub const SOL_FILTER: c_int = 0xfffc; pub const MADV_PURGE: c_int = 9; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_RANDOM: c_int = 1; pub const POSIX_FADV_SEQUENTIAL: c_int = 2; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const POSIX_SPAWN_SETSID: c_short = 0x40; pub const SIGINFO: c_int = 41; pub const O_DIRECT: c_int = 0x2000000; pub const O_CLOFORK: c_int = 0x4000000; pub const MSG_CMSG_CLOEXEC: c_int = 0x1000; pub const MSG_CMSG_CLOFORK: c_int = 0x2000; pub const PBIND_HARD: crate::processorid_t = -3; pub const PBIND_SOFT: crate::processorid_t = -4; pub const PS_SYSTEM: c_int = 1; pub const MAP_FILE: c_int = 0; pub const MAP_32BIT: c_int = 0x80; pub const AF_NCA: c_int = 28; pub const PF_NCA: c_int = AF_NCA; pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; pub const _PC_LAST: c_int = 101; pub const VSTATUS: usize = 16; pub const VERASE2: usize = 17; pub const EPOLLIN: c_int = 0x1; pub const EPOLLPRI: c_int = 0x2; pub const EPOLLOUT: c_int = 0x4; pub const EPOLLRDNORM: c_int = 0x40; pub const EPOLLRDBAND: c_int = 0x80; pub const EPOLLWRNORM: c_int = 0x100; pub const EPOLLWRBAND: c_int = 0x200; pub const EPOLLMSG: c_int = 0x400; pub const EPOLLERR: c_int = 0x8; pub const EPOLLHUP: c_int = 0x10; pub const EPOLLET: c_int = 0x80000000; pub const EPOLLRDHUP: c_int = 0x2000; pub const EPOLLONESHOT: c_int = 0x40000000; pub const EPOLLWAKEUP: c_int = 0x20000000; pub const EPOLLEXCLUSIVE: c_int = 0x10000000; pub const EPOLL_CLOEXEC: c_int = 0x80000; pub const EPOLL_CTL_ADD: c_int = 1; pub const EPOLL_CTL_MOD: c_int = 3; pub const EPOLL_CTL_DEL: c_int = 2; pub const PRIV_USER: c_uint = PRIV_DEBUG | NET_MAC_AWARE | NET_MAC_AWARE_INHERIT | PRIV_XPOLICY | PRIV_AWARE_RESET | PRIV_PFEXEC; pub const LGRP_RSRC_COUNT: crate::lgrp_rsrc_t = 2; pub const LGRP_RSRC_CPU: crate::lgrp_rsrc_t = 0; pub const LGRP_RSRC_MEM: crate::lgrp_rsrc_t = 1; pub const P_DISABLED: c_int = 0x008; pub const AT_SUN_HWCAP2: c_uint = 2023; pub const AT_SUN_FPTYPE: c_uint = 2027; pub const B1000000: crate::speed_t = 24; pub const B1152000: crate::speed_t = 25; pub const B1500000: crate::speed_t = 26; pub const B2000000: crate::speed_t = 27; pub const B2500000: crate::speed_t = 28; pub const B3000000: crate::speed_t = 29; pub const B3500000: crate::speed_t = 30; pub const B4000000: crate::speed_t = 31; // sys/systeminfo.h pub const SI_ADDRESS_WIDTH: c_int = 520; // sys/timerfd.h pub const TFD_CLOEXEC: i32 = 0o2000000; pub const TFD_NONBLOCK: i32 = 0o4000; pub const TFD_TIMER_ABSTIME: i32 = 1 << 0; pub const TFD_TIMER_CANCEL_ON_SET: i32 = 1 << 1; extern "C" { pub fn eventfd(init: c_uint, flags: c_int) -> c_int; pub fn epoll_pwait( epfd: c_int, events: *mut crate::epoll_event, maxevents: c_int, timeout: c_int, sigmask: *const crate::sigset_t, ) -> c_int; pub fn epoll_create(size: c_int) -> c_int; pub fn epoll_create1(flags: c_int) -> c_int; pub fn epoll_wait( epfd: c_int, events: *mut crate::epoll_event, maxevents: c_int, timeout: c_int, ) -> c_int; pub fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int, event: *mut crate::epoll_event) -> c_int; pub fn mincore(addr: crate::caddr_t, len: size_t, vec: *mut c_char) -> c_int; pub fn pset_bind_lwp( pset: crate::psetid_t, id: crate::id_t, pid: crate::pid_t, opset: *mut crate::psetid_t, ) -> c_int; pub fn pset_getloadavg(pset: crate::psetid_t, load: *mut c_double, num: c_int) -> c_int; pub fn pthread_attr_get_np(thread: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_getstackaddr( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, ) -> c_int; pub fn pthread_attr_setstack( attr: *mut crate::pthread_attr_t, stackaddr: *mut c_void, stacksize: size_t, ) -> c_int; pub fn pthread_attr_setstackaddr( attr: *mut crate::pthread_attr_t, stackaddr: *mut c_void, ) -> c_int; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advice: c_int) -> c_int; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn getpagesizes2(pagesize: *mut size_t, nelem: c_int) -> c_int; pub fn posix_spawn_file_actions_addfchdir_np( file_actions: *mut crate::posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn ptsname_r(fildes: c_int, name: *mut c_char, namelen: size_t) -> c_int; pub fn syncfs(fd: c_int) -> c_int; pub fn strcasecmp_l(s1: *const c_char, s2: *const c_char, loc: crate::locale_t) -> c_int; pub fn strncasecmp_l( s1: *const c_char, s2: *const c_char, n: size_t, loc: crate::locale_t, ) -> c_int; pub fn timerfd_create(clockid: c_int, flags: c_int) -> c_int; pub fn timerfd_gettime(fd: c_int, curr_value: *mut crate::itimerspec) -> c_int; pub fn timerfd_settime( fd: c_int, flags: c_int, new_value: *const crate::itimerspec, old_value: *mut crate::itimerspec, ) -> c_int; } libc/src/unix/nto/0000775000175000017500000000000015105742312013667 5ustar bdrungbdrunglibc/src/unix/nto/mod.rs0000644000175000017500000035331615105742312015025 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = u32; pub type sa_family_t = u8; pub type speed_t = c_uint; pub type tcflag_t = c_uint; pub type clockid_t = c_int; pub type timer_t = c_int; pub type key_t = c_uint; pub type id_t = c_int; pub type useconds_t = u32; pub type dev_t = u32; pub type socklen_t = u32; pub type mode_t = u32; pub type rlim64_t = u64; pub type mqd_t = c_int; pub type nfds_t = c_uint; pub type idtype_t = c_uint; pub type errno_t = c_int; pub type rsize_t = c_ulong; pub type Elf32_Half = u16; pub type Elf32_Word = u32; pub type Elf32_Off = u32; pub type Elf32_Addr = u32; pub type Elf32_Lword = u64; pub type Elf32_Sword = i32; pub type Elf64_Half = u16; pub type Elf64_Word = u32; pub type Elf64_Off = u64; pub type Elf64_Addr = u64; pub type Elf64_Xword = u64; pub type Elf64_Sxword = i64; pub type Elf64_Lword = u64; pub type Elf64_Sword = i32; pub type Elf32_Section = u16; pub type Elf64_Section = u16; pub type _Time32t = u32; pub type pthread_t = c_int; pub type regoff_t = ssize_t; pub type nlink_t = u32; pub type blksize_t = u32; pub type suseconds_t = i32; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = u64; pub type msgqnum_t = u64; pub type msglen_t = u64; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type rlim_t = u64; pub type posix_spawn_file_actions_t = *mut c_void; pub type posix_spawnattr_t = crate::uintptr_t; pub type pthread_mutex_t = crate::sync_t; pub type pthread_mutexattr_t = crate::_sync_attr; pub type pthread_cond_t = crate::sync_t; pub type pthread_condattr_t = crate::_sync_attr; pub type pthread_rwlockattr_t = crate::_sync_attr; pub type pthread_key_t = c_int; pub type pthread_spinlock_t = sync_t; pub type pthread_barrierattr_t = _sync_attr; pub type sem_t = sync_t; pub type nl_item = c_int; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } s! { pub struct dirent_extra { pub d_datalen: u16, pub d_type: u16, pub d_reserved: u32, } pub struct stat { pub st_ino: crate::ino_t, pub st_size: off_t, pub st_dev: crate::dev_t, pub st_rdev: crate::dev_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub __old_st_mtime: crate::_Time32t, pub __old_st_atime: crate::_Time32t, pub __old_st_ctime: crate::_Time32t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_blocksize: crate::blksize_t, pub st_nblocks: i32, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_mtim: crate::timespec, pub st_atim: crate::timespec, pub st_ctim: crate::timespec, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[cfg_attr(any(target_env = "nto71", target_env = "nto70"), repr(packed))] pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } #[cfg(not(target_env = "nto71_iosock"))] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [i8; 8], } #[cfg(target_env = "nto71_iosock")] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } // The order of the `ai_addr` field in this struct is crucial // for converting between the Rust and C types. pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut addrinfo, } pub struct fd_set { fds_bits: [c_uint; 2 * FD_SETSIZE as usize / ULONG_SIZE], } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *const c_char, } #[repr(align(8))] pub struct sched_param { pub sched_priority: c_int, pub sched_curpriority: c_int, pub reserved: [c_int; 10], } #[repr(align(8))] pub struct __sched_param { pub __sched_priority: c_int, pub __sched_curpriority: c_int, pub reserved: [c_int; 10], } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct lconv { pub currency_symbol: *mut c_char, pub int_curr_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_grouping: *mut c_char, pub mon_thousands_sep: *mut c_char, pub negative_sign: *mut c_char, pub positive_sign: *mut c_char, pub frac_digits: c_char, pub int_frac_digits: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub n_sign_posn: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub p_sign_posn: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub decimal_point: *mut c_char, pub grouping: *mut c_char, pub thousands_sep: *mut c_char, pub _Frac_grouping: *mut c_char, pub _Frac_sep: *mut c_char, pub _False: *mut c_char, pub _True: *mut c_char, pub _No: *mut c_char, pub _Yes: *mut c_char, pub _Nostr: *mut c_char, pub _Yesstr: *mut c_char, pub _Reserved: [*mut c_char; 8], } // Does not exist in io-sock #[cfg(not(target_env = "nto71_iosock"))] pub struct in_pktinfo { pub ipi_addr: crate::in_addr, pub ipi_ifindex: c_uint, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, pub ifa_addr: *mut crate::sockaddr, pub ifa_netmask: *mut crate::sockaddr, pub ifa_dstaddr: *mut crate::sockaddr, pub ifa_data: *mut c_void, } pub struct arpreq { pub arp_pa: crate::sockaddr, pub arp_ha: crate::sockaddr, pub arp_flags: c_int, } #[cfg_attr(any(target_env = "nto71", target_env = "nto70"), repr(packed))] pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } #[cfg(not(target_env = "nto71_iosock"))] pub struct mmsghdr { pub msg_hdr: crate::msghdr, pub msg_len: c_uint, } #[cfg(target_env = "nto71_iosock")] pub struct mmsghdr { pub msg_hdr: crate::msghdr, pub msg_len: ssize_t, } #[repr(align(8))] pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, __data: [u8; 36], // union } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_flags: c_int, pub sa_mask: crate::sigset_t, } pub struct _sync { _union: c_uint, __owner: c_uint, } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } pub struct glob_t { pub gl_pathc: size_t, pub gl_matchc: c_int, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_flags: c_int, pub gl_errfunc: extern "C" fn(*const c_char, c_int) -> c_int, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_age: *mut c_char, pub pw_comment: *mut c_char, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } pub struct Elf32_Ehdr { pub e_ident: [c_uchar; 16], pub e_type: Elf32_Half, pub e_machine: Elf32_Half, pub e_version: Elf32_Word, pub e_entry: Elf32_Addr, pub e_phoff: Elf32_Off, pub e_shoff: Elf32_Off, pub e_flags: Elf32_Word, pub e_ehsize: Elf32_Half, pub e_phentsize: Elf32_Half, pub e_phnum: Elf32_Half, pub e_shentsize: Elf32_Half, pub e_shnum: Elf32_Half, pub e_shstrndx: Elf32_Half, } pub struct Elf64_Ehdr { pub e_ident: [c_uchar; 16], pub e_type: Elf64_Half, pub e_machine: Elf64_Half, pub e_version: Elf64_Word, pub e_entry: Elf64_Addr, pub e_phoff: Elf64_Off, pub e_shoff: Elf64_Off, pub e_flags: Elf64_Word, pub e_ehsize: Elf64_Half, pub e_phentsize: Elf64_Half, pub e_phnum: Elf64_Half, pub e_shentsize: Elf64_Half, pub e_shnum: Elf64_Half, pub e_shstrndx: Elf64_Half, } pub struct Elf32_Sym { pub st_name: Elf32_Word, pub st_value: Elf32_Addr, pub st_size: Elf32_Word, pub st_info: c_uchar, pub st_other: c_uchar, pub st_shndx: Elf32_Section, } pub struct Elf64_Sym { pub st_name: Elf64_Word, pub st_info: c_uchar, pub st_other: c_uchar, pub st_shndx: Elf64_Section, pub st_value: Elf64_Addr, pub st_size: Elf64_Xword, } pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } pub struct Elf32_Shdr { pub sh_name: Elf32_Word, pub sh_type: Elf32_Word, pub sh_flags: Elf32_Word, pub sh_addr: Elf32_Addr, pub sh_offset: Elf32_Off, pub sh_size: Elf32_Word, pub sh_link: Elf32_Word, pub sh_info: Elf32_Word, pub sh_addralign: Elf32_Word, pub sh_entsize: Elf32_Word, } pub struct Elf64_Shdr { pub sh_name: Elf64_Word, pub sh_type: Elf64_Word, pub sh_flags: Elf64_Xword, pub sh_addr: Elf64_Addr, pub sh_offset: Elf64_Off, pub sh_size: Elf64_Xword, pub sh_link: Elf64_Word, pub sh_info: Elf64_Word, pub sh_addralign: Elf64_Xword, pub sh_entsize: Elf64_Xword, } pub struct in6_pktinfo { pub ipi6_addr: crate::in6_addr, pub ipi6_ifindex: c_uint, } pub struct inotify_event { pub wd: c_int, pub mask: u32, pub cookie: u32, pub len: u32, } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_cc: [crate::cc_t; crate::NCCS], __reserved: [c_uint; 3], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } pub struct mallinfo { pub arena: c_int, pub ordblks: c_int, pub smblks: c_int, pub hblks: c_int, pub hblkhd: c_int, pub usmblks: c_int, pub fsmblks: c_int, pub uordblks: c_int, pub fordblks: c_int, pub keepcost: c_int, } pub struct flock { pub l_type: i16, pub l_whence: i16, pub l_zero1: i32, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, pub l_sysid: u32, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_basetype: [c_char; 16], pub f_flag: c_ulong, pub f_namemax: c_ulong, f_filler: [c_uint; 21], } pub struct aiocb { pub aio_fildes: c_int, pub aio_reqprio: c_int, pub aio_offset: off_t, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_sigevent: crate::sigevent, pub aio_lio_opcode: c_int, pub _aio_lio_state: *mut c_void, _aio_pad: [c_int; 3], pub _aio_next: *mut crate::aiocb, pub _aio_flag: c_uint, pub _aio_iotype: c_uint, pub _aio_result: ssize_t, pub _aio_error: c_uint, pub _aio_suspend: *mut c_void, pub _aio_plist: *mut c_void, pub _aio_policy: c_int, pub _aio_param: crate::__sched_param, } pub struct pthread_attr_t { __data1: c_long, __data2: [u8; 96], } pub struct ipc_perm { pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub seq: c_uint, pub key: crate::key_t, _reserved: [c_int; 4], } pub struct regex_t { re_magic: c_int, re_nsub: size_t, re_endp: *const c_char, re_g: *mut c_void, } pub struct _thread_attr { pub __flags: c_int, pub __stacksize: size_t, pub __stackaddr: *mut c_void, pub __exitfunc: Option, pub __policy: c_int, pub __param: crate::__sched_param, pub __guardsize: c_uint, pub __prealloc: c_uint, __spare: [c_int; 2], } pub struct _sync_attr { pub __protocol: c_int, pub __flags: c_int, pub __prioceiling: c_int, pub __clockid: c_int, pub __count: c_int, __reserved: [c_int; 3], } pub struct sockcred { pub sc_uid: crate::uid_t, pub sc_euid: crate::uid_t, pub sc_gid: crate::gid_t, pub sc_egid: crate::gid_t, pub sc_ngroups: c_int, pub sc_groups: [crate::gid_t; 1], } pub struct bpf_program { pub bf_len: c_uint, pub bf_insns: *mut crate::bpf_insn, } #[cfg(not(target_env = "nto71_iosock"))] pub struct bpf_stat { pub bs_recv: u64, pub bs_drop: u64, pub bs_capt: u64, bs_padding: [u64; 13], } #[cfg(target_env = "nto71_iosock")] pub struct bpf_stat { pub bs_recv: c_uint, pub bs_drop: c_uint, } pub struct bpf_version { pub bv_major: c_ushort, pub bv_minor: c_ushort, } pub struct bpf_hdr { pub bh_tstamp: crate::timeval, pub bh_caplen: u32, pub bh_datalen: u32, pub bh_hdrlen: u16, } pub struct bpf_insn { pub code: u16, pub jt: c_uchar, pub jf: c_uchar, pub k: u32, } pub struct bpf_dltlist { pub bfl_len: c_uint, pub bfl_list: *mut c_uint, } // Does not exist in io-sock #[cfg(not(target_env = "nto71_iosock"))] pub struct unpcbid { pub unp_pid: crate::pid_t, pub unp_euid: crate::uid_t, pub unp_egid: crate::gid_t, } pub struct dl_phdr_info { pub dlpi_addr: crate::Elf64_Addr, pub dlpi_name: *const c_char, pub dlpi_phdr: *const crate::Elf64_Phdr, pub dlpi_phnum: crate::Elf64_Half, } #[repr(align(8))] pub struct ucontext_t { pub uc_link: *mut ucontext_t, pub uc_sigmask: crate::sigset_t, pub uc_stack: stack_t, pub uc_mcontext: mcontext_t, } } s_no_extra_traits! { pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char; 104], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, __ss_pad1: [c_char; 6], __ss_align: i64, __ss_pad2: [c_char; 112], } pub struct utsname { pub sysname: [c_char; _SYSNAME_SIZE], pub nodename: [c_char; _SYSNAME_SIZE], pub release: [c_char; _SYSNAME_SIZE], pub version: [c_char; _SYSNAME_SIZE], pub machine: [c_char; _SYSNAME_SIZE], } pub struct sigevent { pub sigev_notify: c_int, pub __padding1: c_int, pub sigev_signo: c_int, // union pub __padding2: c_int, pub sigev_value: crate::sigval, __sigev_un2: usize, // union } pub struct dirent { pub d_ino: crate::ino_t, pub d_offset: off_t, pub d_reclen: c_short, pub d_namelen: c_short, pub d_name: [c_char; 1], // flex array } pub struct sigset_t { __val: [u32; 2], } pub struct mq_attr { pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_flags: c_long, pub mq_curmsgs: c_long, pub mq_sendwait: c_long, pub mq_recvwait: c_long, } pub struct msg { pub msg_next: *mut crate::msg, pub msg_type: c_long, pub msg_ts: c_ushort, pub msg_spot: c_short, _pad: [u8; 4], } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_first: *mut crate::msg, pub msg_last: *mut crate::msg, pub msg_cbytes: crate::msglen_t, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, pub msg_stime: crate::time_t, msg_pad1: c_long, pub msg_rtime: crate::time_t, msg_pad2: c_long, pub msg_ctime: crate::time_t, msg_pad3: c_long, msg_pad4: [c_long; 4], } #[cfg(not(target_env = "nto71_iosock"))] pub struct sockaddr_dl { pub sdl_len: c_uchar, pub sdl_family: crate::sa_family_t, pub sdl_index: u16, pub sdl_type: c_uchar, pub sdl_nlen: c_uchar, pub sdl_alen: c_uchar, pub sdl_slen: c_uchar, pub sdl_data: [c_char; 12], } #[cfg(target_env = "nto71_iosock")] pub struct sockaddr_dl { pub sdl_len: c_uchar, pub sdl_family: c_uchar, pub sdl_index: c_ushort, pub sdl_type: c_uchar, pub sdl_nlen: c_uchar, pub sdl_alen: c_uchar, pub sdl_slen: c_uchar, pub sdl_data: [c_char; 46], } pub struct sync_t { __u: c_uint, // union pub __owner: c_uint, } #[repr(align(4))] pub struct pthread_barrier_t { // union __pad: [u8; 28], // union } pub struct pthread_rwlock_t { pub __active: c_int, pub __blockedwriters: c_int, pub __blockedreaders: c_int, pub __heavy: c_int, pub __lock: crate::pthread_mutex_t, // union pub __rcond: crate::pthread_cond_t, // union pub __wcond: crate::pthread_cond_t, // union pub __owner: c_uint, pub __spare: c_uint, } } cfg_if! { if #[cfg(feature = "extra_traits")] { // sigevent impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.__sigev_un2 == other.__sigev_un2 } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("__sigev_un2", &self.__sigev_un2) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.__sigev_un2.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_len == other.sun_len && self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_len", &self.sun_len) .field("sun_family", &self.sun_family) // FIXME(debug): .field("sun_path", &self.sun_path) .finish() } } impl hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_len.hash(state); self.sun_family.hash(state); self.sun_path.hash(state); } } // sigset_t impl PartialEq for sigset_t { fn eq(&self, other: &sigset_t) -> bool { self.__val == other.__val } } impl Eq for sigset_t {} impl fmt::Debug for sigset_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigset_t") .field("__val", &self.__val) .finish() } } impl hash::Hash for sigset_t { fn hash(&self, state: &mut H) { self.__val.hash(state); } } // msg impl fmt::Debug for msg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("msg") .field("msg_next", &self.msg_next) .field("msg_type", &self.msg_type) .field("msg_ts", &self.msg_ts) .field("msg_spot", &self.msg_spot) .finish() } } // msqid_ds impl fmt::Debug for msqid_ds { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("msqid_ds") .field("msg_perm", &self.msg_perm) .field("msg_first", &self.msg_first) .field("msg_cbytes", &self.msg_cbytes) .field("msg_qnum", &self.msg_qnum) .field("msg_qbytes", &self.msg_qbytes) .field("msg_lspid", &self.msg_lspid) .field("msg_lrpid", &self.msg_lrpid) .field("msg_stime", &self.msg_stime) .field("msg_rtime", &self.msg_rtime) .field("msg_ctime", &self.msg_ctime) .finish() } } // sockaddr_dl impl fmt::Debug for sockaddr_dl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_dl") .field("sdl_len", &self.sdl_len) .field("sdl_family", &self.sdl_family) .field("sdl_index", &self.sdl_index) .field("sdl_type", &self.sdl_type) .field("sdl_nlen", &self.sdl_nlen) .field("sdl_alen", &self.sdl_alen) .field("sdl_slen", &self.sdl_slen) .field("sdl_data", &self.sdl_data) .finish() } } impl PartialEq for sockaddr_dl { fn eq(&self, other: &sockaddr_dl) -> bool { self.sdl_len == other.sdl_len && self.sdl_family == other.sdl_family && self.sdl_index == other.sdl_index && self.sdl_type == other.sdl_type && self.sdl_nlen == other.sdl_nlen && self.sdl_alen == other.sdl_alen && self.sdl_slen == other.sdl_slen && self .sdl_data .iter() .zip(other.sdl_data.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_dl {} impl hash::Hash for sockaddr_dl { fn hash(&self, state: &mut H) { self.sdl_len.hash(state); self.sdl_family.hash(state); self.sdl_index.hash(state); self.sdl_type.hash(state); self.sdl_nlen.hash(state); self.sdl_alen.hash(state); self.sdl_slen.hash(state); self.sdl_data.hash(state); } } // sync_t impl fmt::Debug for sync_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sync_t") .field("__owner", &self.__owner) .field("__u", &self.__u) .finish() } } // pthread_barrier_t impl fmt::Debug for pthread_barrier_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_barrier_t") .field("__pad", &self.__pad) .finish() } } // pthread_rwlock_t impl fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_rwlock_t") .field("__active", &self.__active) .field("__blockedwriters", &self.__blockedwriters) .field("__blockedreaders", &self.__blockedreaders) .field("__heavy", &self.__heavy) .field("__lock", &self.__lock) .field("__rcond", &self.__rcond) .field("__wcond", &self.__wcond) .field("__owner", &self.__owner) .field("__spare", &self.__spare) .finish() } } // syspage_entry impl fmt::Debug for syspage_entry { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("syspage_entry") .field("size", &self.size) .field("total_size", &self.total_size) .field("type_", &self.type_) .field("num_cpu", &self.num_cpu) .field("system_private", &self.system_private) .field("old_asinfo", &self.old_asinfo) .field("hwinfo", &self.hwinfo) .field("old_cpuinfo", &self.old_cpuinfo) .field("old_cacheattr", &self.old_cacheattr) .field("qtime", &self.qtime) .field("callout", &self.callout) .field("callin", &self.callin) .field("typed_strings", &self.typed_strings) .field("strings", &self.strings) .field("old_intrinfo", &self.old_intrinfo) .field("smp", &self.smp) .field("pminfo", &self.pminfo) .field("old_mdriver", &self.old_mdriver) .field("new_asinfo", &self.new_asinfo) .field("new_cpuinfo", &self.new_cpuinfo) .field("new_cacheattr", &self.new_cacheattr) .field("new_intrinfo", &self.new_intrinfo) .field("new_mdriver", &self.new_mdriver) .finish() } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl fmt::Debug for utsname { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utsname") // FIXME(debug): .field("sysname", &self.sysname) // FIXME(debug): .field("nodename", &self.nodename) // FIXME(debug): .field("release", &self.release) // FIXME(debug): .field("version", &self.version) // FIXME(debug): .field("machine", &self.machine) .finish() } } impl hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_flags == other.mq_flags && self.mq_curmsgs == other.mq_curmsgs && self.mq_msgsize == other.mq_msgsize && self.mq_sendwait == other.mq_sendwait && self.mq_recvwait == other.mq_recvwait } } impl Eq for mq_attr {} impl fmt::Debug for mq_attr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mq_attr") .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_flags", &self.mq_flags) .field("mq_curmsgs", &self.mq_curmsgs) .field("mq_msgsize", &self.mq_msgsize) .field("mq_sendwait", &self.mq_sendwait) .field("mq_recvwait", &self.mq_recvwait) .finish() } } impl hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_flags.hash(state); self.mq_curmsgs.hash(state); self.mq_sendwait.hash(state); self.mq_recvwait.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self.__ss_pad1 == other.__ss_pad1 && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_align", &self.__ss_align) // FIXME(debug): .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_offset == other.d_offset && self.d_reclen == other.d_reclen && self.d_namelen == other.d_namelen && self.d_name[..self.d_namelen as _] .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_offset", &self.d_offset) .field("d_reclen", &self.d_reclen) .field("d_namelen", &self.d_namelen) .field("d_name", &&self.d_name[..self.d_namelen as _]) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_offset.hash(state); self.d_reclen.hash(state); self.d_namelen.hash(state); self.d_name[..self.d_namelen as _].hash(state); } } } } pub const _SYSNAME_SIZE: usize = 256 + 1; pub const RLIM_INFINITY: crate::rlim_t = 0xfffffffffffffffd; pub const O_LARGEFILE: c_int = 0o0100000; // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { const ULONG_SIZE: usize = 32; } else if #[cfg(target_pointer_width = "64")] { const ULONG_SIZE: usize = 64; } else { // Unknown target_pointer_width } } pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 32767; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const F_DUPFD_CLOEXEC: c_int = 5; pub const SIGTRAP: c_int = 5; pub const CLOCK_REALTIME: crate::clockid_t = 0; pub const CLOCK_MONOTONIC: crate::clockid_t = 2; pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 3; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 4; pub const TIMER_ABSTIME: c_uint = 0x80000000; pub const RUSAGE_SELF: c_int = 0; pub const F_OK: c_int = 0; pub const X_OK: c_int = 1; pub const W_OK: c_int = 2; pub const R_OK: c_int = 4; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSEGV: c_int = 11; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const PROT_NONE: c_int = 0x00000000; pub const PROT_READ: c_int = 0x00000100; pub const PROT_WRITE: c_int = 0x00000200; pub const PROT_EXEC: c_int = 0x00000400; pub const MAP_FILE: c_int = 0; pub const MAP_SHARED: c_int = 1; pub const MAP_PRIVATE: c_int = 2; pub const MAP_FIXED: c_int = 0x10; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const MS_ASYNC: c_int = 1; pub const MS_INVALIDATE: c_int = 4; pub const MS_SYNC: c_int = 2; pub const SCM_RIGHTS: c_int = 0x01; pub const SCM_TIMESTAMP: c_int = 0x02; cfg_if! { if #[cfg(not(target_env = "nto71_iosock"))] { pub const SCM_CREDS: c_int = 0x04; pub const IFF_NOTRAILERS: c_int = 0x00000020; pub const AF_INET6: c_int = 24; pub const AF_BLUETOOTH: c_int = 31; pub const pseudo_AF_KEY: c_int = 29; pub const MSG_NOSIGNAL: c_int = 0x0800; pub const MSG_WAITFORONE: c_int = 0x2000; pub const IP_IPSEC_POLICY_COMPAT: c_int = 22; pub const IP_PKTINFO: c_int = 25; pub const IPPROTO_DIVERT: c_int = 259; pub const IPV6_IPSEC_POLICY_COMPAT: c_int = 28; pub const TCP_KEEPALIVE: c_int = 0x04; pub const ARPHRD_ARCNET: u16 = 7; pub const SO_BINDTODEVICE: c_int = 0x0800; pub const EAI_NODATA: c_int = 7; pub const IPTOS_ECN_NOT_ECT: u8 = 0x00; pub const RTF_BROADCAST: u32 = 0x80000; pub const UDP_ENCAP: c_int = 100; pub const HW_IOSTATS: c_int = 9; pub const HW_MACHINE_ARCH: c_int = 10; pub const HW_ALIGNBYTES: c_int = 11; pub const HW_CNMAGIC: c_int = 12; pub const HW_PHYSMEM64: c_int = 13; pub const HW_USERMEM64: c_int = 14; pub const HW_IOSTATNAMES: c_int = 15; pub const HW_MAXID: c_int = 15; pub const CTL_UNSPEC: c_int = 0; pub const CTL_QNX: c_int = 9; pub const CTL_PROC: c_int = 10; pub const CTL_VENDOR: c_int = 11; pub const CTL_EMUL: c_int = 12; pub const CTL_SECURITY: c_int = 13; pub const CTL_MAXID: c_int = 14; pub const AF_ARP: c_int = 28; pub const AF_IEEE80211: c_int = 32; pub const AF_NATM: c_int = 27; pub const AF_NS: c_int = 6; pub const BIOCGDLTLIST: c_int = -1072676233; pub const BIOCGETIF: c_int = 1083196011; pub const BIOCGSEESENT: c_int = 1074020984; pub const BIOCGSTATS: c_int = 1082147439; pub const BIOCSDLT: c_int = -2147204490; pub const BIOCSETIF: c_int = -2138029460; pub const BIOCSSEESENT: c_int = -2147204487; pub const FIONSPACE: c_int = 1074030200; pub const FIONWRITE: c_int = 1074030201; pub const IFF_ACCEPTRTADV: c_int = 0x40000000; pub const IFF_IP6FORWARDING: c_int = 0x20000000; pub const IFF_SHIM: c_int = 0x80000000; pub const KERN_ARND: c_int = 81; pub const KERN_IOV_MAX: c_int = 38; pub const KERN_LOGSIGEXIT: c_int = 46; pub const KERN_MAXID: c_int = 83; pub const KERN_PROC_ARGS: c_int = 48; pub const KERN_PROC_ENV: c_int = 3; pub const KERN_PROC_GID: c_int = 7; pub const KERN_PROC_RGID: c_int = 8; pub const LOCAL_CONNWAIT: c_int = 0x0002; pub const LOCAL_CREDS: c_int = 0x0001; pub const LOCAL_PEEREID: c_int = 0x0003; pub const MSG_NOTIFICATION: c_int = 0x0400; pub const NET_RT_IFLIST: c_int = 4; pub const NI_NUMERICSCOPE: c_int = 0x00000040; pub const PF_ARP: c_int = 28; pub const PF_NATM: c_int = 27; pub const pseudo_AF_HDRCMPLT: c_int = 30; pub const SIOCGIFADDR: c_int = -1064277727; pub const SO_FIB: c_int = 0x100a; pub const SO_TXPRIO: c_int = 0x100b; pub const SO_SETFIB: c_int = 0x100a; pub const SO_VLANPRIO: c_int = 0x100c; pub const USER_ATEXIT_MAX: c_int = 21; pub const USER_MAXID: c_int = 22; pub const SO_OVERFLOWED: c_int = 0x1009; } else { pub const SCM_CREDS: c_int = 0x03; pub const AF_INET6: c_int = 28; pub const AF_BLUETOOTH: c_int = 36; pub const pseudo_AF_KEY: c_int = 27; pub const MSG_NOSIGNAL: c_int = 0x20000; pub const MSG_WAITFORONE: c_int = 0x00080000; pub const IPPROTO_DIVERT: c_int = 258; pub const RTF_BROADCAST: u32 = 0x400000; pub const UDP_ENCAP: c_int = 1; pub const HW_MACHINE_ARCH: c_int = 11; pub const AF_ARP: c_int = 35; pub const AF_IEEE80211: c_int = 37; pub const AF_NATM: c_int = 29; pub const BIOCGDLTLIST: c_ulong = 0xffffffffc0104279; pub const BIOCGETIF: c_int = 0x4020426b; pub const BIOCGSEESENT: c_int = 0x40044276; pub const BIOCGSTATS: c_int = 0x4008426f; pub const BIOCSDLT: c_int = 0x80044278; pub const BIOCSETIF: c_int = 0x8020426c; pub const BIOCSSEESENT: c_int = 0x80044277; pub const KERN_ARND: c_int = 37; pub const KERN_IOV_MAX: c_int = 35; pub const KERN_LOGSIGEXIT: c_int = 34; pub const KERN_PROC_ARGS: c_int = 7; pub const KERN_PROC_ENV: c_int = 35; pub const KERN_PROC_GID: c_int = 11; pub const KERN_PROC_RGID: c_int = 10; pub const LOCAL_CONNWAIT: c_int = 4; pub const LOCAL_CREDS: c_int = 2; pub const MSG_NOTIFICATION: c_int = 0x00002000; pub const NET_RT_IFLIST: c_int = 3; pub const NI_NUMERICSCOPE: c_int = 0x00000020; pub const PF_ARP: c_int = AF_ARP; pub const PF_NATM: c_int = AF_NATM; pub const pseudo_AF_HDRCMPLT: c_int = 31; pub const SIOCGIFADDR: c_int = 0xc0206921; pub const SO_SETFIB: c_int = 0x1014; } } pub const MAP_TYPE: c_int = 0x3; pub const IFF_UP: c_int = 0x00000001; pub const IFF_BROADCAST: c_int = 0x00000002; pub const IFF_DEBUG: c_int = 0x00000004; pub const IFF_LOOPBACK: c_int = 0x00000008; pub const IFF_POINTOPOINT: c_int = 0x00000010; pub const IFF_RUNNING: c_int = 0x00000040; pub const IFF_NOARP: c_int = 0x00000080; pub const IFF_PROMISC: c_int = 0x00000100; pub const IFF_ALLMULTI: c_int = 0x00000200; pub const IFF_MULTICAST: c_int = 0x00008000; pub const AF_UNSPEC: c_int = 0; pub const AF_UNIX: c_int = AF_LOCAL; pub const AF_LOCAL: c_int = 1; pub const AF_INET: c_int = 2; pub const AF_IPX: c_int = 23; pub const AF_APPLETALK: c_int = 16; pub const AF_ROUTE: c_int = 17; pub const AF_SNA: c_int = 11; pub const AF_ISDN: c_int = 26; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_UNIX: c_int = PF_LOCAL; pub const PF_LOCAL: c_int = AF_LOCAL; pub const PF_INET: c_int = AF_INET; pub const PF_IPX: c_int = AF_IPX; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_INET6: c_int = AF_INET6; pub const PF_KEY: c_int = pseudo_AF_KEY; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_SNA: c_int = AF_SNA; pub const PF_BLUETOOTH: c_int = AF_BLUETOOTH; pub const PF_ISDN: c_int = AF_ISDN; pub const SOMAXCONN: c_int = 128; pub const MSG_OOB: c_int = 0x0001; pub const MSG_PEEK: c_int = 0x0002; pub const MSG_DONTROUTE: c_int = 0x0004; pub const MSG_CTRUNC: c_int = 0x0020; pub const MSG_TRUNC: c_int = 0x0010; pub const MSG_DONTWAIT: c_int = 0x0080; pub const MSG_EOR: c_int = 0x0008; pub const MSG_WAITALL: c_int = 0x0040; pub const IP_TOS: c_int = 3; pub const IP_TTL: c_int = 4; pub const IP_HDRINCL: c_int = 2; pub const IP_OPTIONS: c_int = 1; pub const IP_RECVOPTS: c_int = 5; pub const IP_RETOPTS: c_int = 8; pub const IP_MULTICAST_IF: c_int = 9; pub const IP_MULTICAST_TTL: c_int = 10; pub const IP_MULTICAST_LOOP: c_int = 11; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IP_DEFAULT_MULTICAST_TTL: c_int = 1; pub const IP_DEFAULT_MULTICAST_LOOP: c_int = 1; pub const IPPROTO_HOPOPTS: c_int = 0; pub const IPPROTO_IGMP: c_int = 2; pub const IPPROTO_IPIP: c_int = 4; pub const IPPROTO_EGP: c_int = 8; pub const IPPROTO_PUP: c_int = 12; pub const IPPROTO_IDP: c_int = 22; pub const IPPROTO_TP: c_int = 29; pub const IPPROTO_ROUTING: c_int = 43; pub const IPPROTO_FRAGMENT: c_int = 44; pub const IPPROTO_RSVP: c_int = 46; pub const IPPROTO_GRE: c_int = 47; pub const IPPROTO_ESP: c_int = 50; pub const IPPROTO_AH: c_int = 51; pub const IPPROTO_NONE: c_int = 59; pub const IPPROTO_DSTOPTS: c_int = 60; pub const IPPROTO_ENCAP: c_int = 98; pub const IPPROTO_PIM: c_int = 103; pub const IPPROTO_SCTP: c_int = 132; pub const IPPROTO_RAW: c_int = 255; pub const IPPROTO_MAX: c_int = 256; pub const IPPROTO_CARP: c_int = 112; pub const IPPROTO_DONE: c_int = 257; pub const IPPROTO_EON: c_int = 80; pub const IPPROTO_ETHERIP: c_int = 97; pub const IPPROTO_GGP: c_int = 3; pub const IPPROTO_IPCOMP: c_int = 108; pub const IPPROTO_MOBILE: c_int = 55; pub const IPV6_RTHDR_LOOSE: c_int = 0; pub const IPV6_RTHDR_STRICT: c_int = 1; pub const IPV6_UNICAST_HOPS: c_int = 4; pub const IPV6_MULTICAST_IF: c_int = 9; pub const IPV6_MULTICAST_HOPS: c_int = 10; pub const IPV6_MULTICAST_LOOP: c_int = 11; pub const IPV6_JOIN_GROUP: c_int = 12; pub const IPV6_LEAVE_GROUP: c_int = 13; pub const IPV6_CHECKSUM: c_int = 26; pub const IPV6_V6ONLY: c_int = 27; pub const IPV6_RTHDRDSTOPTS: c_int = 35; pub const IPV6_RECVPKTINFO: c_int = 36; pub const IPV6_RECVHOPLIMIT: c_int = 37; pub const IPV6_RECVRTHDR: c_int = 38; pub const IPV6_RECVHOPOPTS: c_int = 39; pub const IPV6_RECVDSTOPTS: c_int = 40; pub const IPV6_RECVPATHMTU: c_int = 43; pub const IPV6_PATHMTU: c_int = 44; pub const IPV6_PKTINFO: c_int = 46; pub const IPV6_HOPLIMIT: c_int = 47; pub const IPV6_NEXTHOP: c_int = 48; pub const IPV6_HOPOPTS: c_int = 49; pub const IPV6_DSTOPTS: c_int = 50; pub const IPV6_RECVTCLASS: c_int = 57; pub const IPV6_TCLASS: c_int = 61; pub const IPV6_DONTFRAG: c_int = 62; pub const TCP_NODELAY: c_int = 0x01; pub const TCP_MAXSEG: c_int = 0x02; pub const TCP_MD5SIG: c_int = 0x10; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const LOCK_SH: c_int = 0x1; pub const LOCK_EX: c_int = 0x2; pub const LOCK_NB: c_int = 0x4; pub const LOCK_UN: c_int = 0x8; pub const SS_ONSTACK: c_int = 1; pub const SS_DISABLE: c_int = 2; pub const PATH_MAX: c_int = 1024; pub const UIO_MAXIOV: c_int = 1024; pub const FD_SETSIZE: usize = 256; pub const TCIOFF: c_int = 0x0002; pub const TCION: c_int = 0x0003; pub const TCOOFF: c_int = 0x0000; pub const TCOON: c_int = 0x0001; pub const TCIFLUSH: c_int = 0; pub const TCOFLUSH: c_int = 1; pub const TCIOFLUSH: c_int = 2; pub const NL0: crate::tcflag_t = 0x000; pub const NL1: crate::tcflag_t = 0x100; pub const TAB0: crate::tcflag_t = 0x0000; pub const CR0: crate::tcflag_t = 0x000; pub const FF0: crate::tcflag_t = 0x0000; pub const BS0: crate::tcflag_t = 0x0000; pub const VT0: crate::tcflag_t = 0x0000; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VLNEXT: usize = 15; pub const IGNBRK: crate::tcflag_t = 0x00000001; pub const BRKINT: crate::tcflag_t = 0x00000002; pub const IGNPAR: crate::tcflag_t = 0x00000004; pub const PARMRK: crate::tcflag_t = 0x00000008; pub const INPCK: crate::tcflag_t = 0x00000010; pub const ISTRIP: crate::tcflag_t = 0x00000020; pub const INLCR: crate::tcflag_t = 0x00000040; pub const IGNCR: crate::tcflag_t = 0x00000080; pub const ICRNL: crate::tcflag_t = 0x00000100; pub const IXANY: crate::tcflag_t = 0x00000800; pub const IMAXBEL: crate::tcflag_t = 0x00002000; pub const OPOST: crate::tcflag_t = 0x00000001; pub const CS5: crate::tcflag_t = 0x00; pub const ECHO: crate::tcflag_t = 0x00000008; pub const OCRNL: crate::tcflag_t = 0x00000008; pub const ONOCR: crate::tcflag_t = 0x00000010; pub const ONLRET: crate::tcflag_t = 0x00000020; pub const OFILL: crate::tcflag_t = 0x00000040; pub const OFDEL: crate::tcflag_t = 0x00000080; pub const WNOHANG: c_int = 0x0040; pub const WUNTRACED: c_int = 0x0004; pub const WSTOPPED: c_int = WUNTRACED; pub const WEXITED: c_int = 0x0001; pub const WCONTINUED: c_int = 0x0008; pub const WNOWAIT: c_int = 0x0080; pub const WTRAPPED: c_int = 0x0002; pub const RTLD_LOCAL: c_int = 0x0200; pub const RTLD_LAZY: c_int = 0x0001; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_RANDOM: c_int = 2; pub const POSIX_FADV_SEQUENTIAL: c_int = 1; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const AT_FDCWD: c_int = -100; pub const AT_EACCESS: c_int = 0x0001; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x0002; pub const AT_SYMLINK_FOLLOW: c_int = 0x0004; pub const AT_REMOVEDIR: c_int = 0x0008; pub const LOG_CRON: c_int = 9 << 3; pub const LOG_AUTHPRIV: c_int = 10 << 3; pub const LOG_FTP: c_int = 11 << 3; pub const LOG_PERROR: c_int = 0x20; pub const PIPE_BUF: usize = 5120; pub const CLD_EXITED: c_int = 1; pub const CLD_KILLED: c_int = 2; pub const CLD_DUMPED: c_int = 3; pub const CLD_TRAPPED: c_int = 4; pub const CLD_STOPPED: c_int = 5; pub const CLD_CONTINUED: c_int = 6; pub const UTIME_OMIT: c_long = 0x40000002; pub const UTIME_NOW: c_long = 0x40000001; pub const POLLIN: c_short = POLLRDNORM | POLLRDBAND; pub const POLLPRI: c_short = 0x0008; pub const POLLOUT: c_short = 0x0002; pub const POLLERR: c_short = 0x0020; pub const POLLHUP: c_short = 0x0040; pub const POLLNVAL: c_short = 0x1000; pub const POLLRDNORM: c_short = 0x0001; pub const POLLRDBAND: c_short = 0x0004; pub const IPTOS_LOWDELAY: u8 = 0x10; pub const IPTOS_THROUGHPUT: u8 = 0x08; pub const IPTOS_RELIABILITY: u8 = 0x04; pub const IPTOS_MINCOST: u8 = 0x02; pub const IPTOS_PREC_NETCONTROL: u8 = 0xe0; pub const IPTOS_PREC_INTERNETCONTROL: u8 = 0xc0; pub const IPTOS_PREC_CRITIC_ECP: u8 = 0xa0; pub const IPTOS_PREC_FLASHOVERRIDE: u8 = 0x80; pub const IPTOS_PREC_FLASH: u8 = 0x60; pub const IPTOS_PREC_IMMEDIATE: u8 = 0x40; pub const IPTOS_PREC_PRIORITY: u8 = 0x20; pub const IPTOS_PREC_ROUTINE: u8 = 0x00; pub const IPTOS_ECN_MASK: u8 = 0x03; pub const IPTOS_ECN_ECT1: u8 = 0x01; pub const IPTOS_ECN_ECT0: u8 = 0x02; pub const IPTOS_ECN_CE: u8 = 0x03; pub const IPOPT_CONTROL: u8 = 0x00; pub const IPOPT_RESERVED1: u8 = 0x20; pub const IPOPT_RESERVED2: u8 = 0x60; pub const IPOPT_LSRR: u8 = 131; pub const IPOPT_RR: u8 = 7; pub const IPOPT_SSRR: u8 = 137; pub const IPDEFTTL: u8 = 64; pub const IPOPT_OPTVAL: u8 = 0; pub const IPOPT_OLEN: u8 = 1; pub const IPOPT_OFFSET: u8 = 2; pub const IPOPT_MINOFF: u8 = 4; pub const IPOPT_NOP: u8 = 1; pub const IPOPT_EOL: u8 = 0; pub const IPOPT_TS: u8 = 68; pub const IPOPT_TS_TSONLY: u8 = 0; pub const IPOPT_TS_TSANDADDR: u8 = 1; pub const IPOPT_TS_PRESPEC: u8 = 3; pub const MAX_IPOPTLEN: u8 = 40; pub const IPVERSION: u8 = 4; pub const MAXTTL: u8 = 255; pub const ARPHRD_ETHER: u16 = 1; pub const ARPHRD_IEEE802: u16 = 6; pub const ARPHRD_IEEE1394: u16 = 24; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_DEBUG: c_int = 0x0001; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_TYPE: c_int = 0x1008; pub const SO_ERROR: c_int = 0x1007; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_LINGER: c_int = 0x0080; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_RCVLOWAT: c_int = 0x1004; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_TIMESTAMP: c_int = 0x0400; pub const SO_ACCEPTCONN: c_int = 0x0002; pub const TIOCM_LE: c_int = 0x0100; pub const TIOCM_DTR: c_int = 0x0001; pub const TIOCM_RTS: c_int = 0x0002; pub const TIOCM_ST: c_int = 0x0200; pub const TIOCM_SR: c_int = 0x0400; pub const TIOCM_CTS: c_int = 0x1000; pub const TIOCM_CAR: c_int = TIOCM_CD; pub const TIOCM_CD: c_int = 0x8000; pub const TIOCM_RNG: c_int = TIOCM_RI; pub const TIOCM_RI: c_int = 0x4000; pub const TIOCM_DSR: c_int = 0x2000; pub const SCHED_OTHER: c_int = 3; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const IPC_PRIVATE: crate::key_t = 0; pub const IPC_CREAT: c_int = 0o001000; pub const IPC_EXCL: c_int = 0o002000; pub const IPC_NOWAIT: c_int = 0o004000; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 1; pub const IPC_STAT: c_int = 2; pub const MSG_NOERROR: c_int = 0o010000; pub const LOG_NFACILITIES: c_int = 24; pub const SEM_FAILED: *mut crate::sem_t = 0xFFFFFFFFFFFFFFFF as *mut sem_t; pub const AI_PASSIVE: c_int = 0x00000001; pub const AI_CANONNAME: c_int = 0x00000002; pub const AI_NUMERICHOST: c_int = 0x00000004; pub const AI_NUMERICSERV: c_int = 0x00000008; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_NONAME: c_int = 8; pub const EAI_AGAIN: c_int = 2; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SERVICE: c_int = 9; pub const EAI_MEMORY: c_int = 6; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 14; pub const NI_NUMERICHOST: c_int = 0x00000002; pub const NI_NUMERICSERV: c_int = 0x00000008; pub const NI_NOFQDN: c_int = 0x00000001; pub const NI_NAMEREQD: c_int = 0x00000004; pub const NI_DGRAM: c_int = 0x00000010; pub const AIO_CANCELED: c_int = 0; pub const AIO_NOTCANCELED: c_int = 2; pub const AIO_ALLDONE: c_int = 1; pub const LIO_READ: c_int = 1; pub const LIO_WRITE: c_int = 2; pub const LIO_NOP: c_int = 0; pub const LIO_WAIT: c_int = 1; pub const LIO_NOWAIT: c_int = 0; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; pub const ITIMER_PROF: c_int = 2; // DIFF(main): changed to `c_short` in f62eb023ab pub const POSIX_SPAWN_RESETIDS: c_int = 0x00000010; pub const POSIX_SPAWN_SETPGROUP: c_int = 0x00000001; pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x00000004; pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x00000002; pub const POSIX_SPAWN_SETSCHEDPARAM: c_int = 0x00000400; pub const POSIX_SPAWN_SETSCHEDULER: c_int = 0x00000040; pub const RTF_UP: c_ushort = 0x0001; pub const RTF_GATEWAY: c_ushort = 0x0002; pub const RTF_HOST: c_ushort = 0x0004; pub const RTF_DYNAMIC: c_ushort = 0x0010; pub const RTF_MODIFIED: c_ushort = 0x0020; pub const RTF_REJECT: c_ushort = 0x0008; pub const RTF_STATIC: c_ushort = 0x0800; pub const RTF_XRESOLVE: c_ushort = 0x0200; pub const RTM_NEWADDR: u16 = 0xc; pub const RTM_DELADDR: u16 = 0xd; pub const RTA_DST: c_ushort = 0x1; pub const RTA_GATEWAY: c_ushort = 0x2; pub const IN_ACCESS: u32 = 0x00000001; pub const IN_MODIFY: u32 = 0x00000002; pub const IN_ATTRIB: u32 = 0x00000004; pub const IN_CLOSE_WRITE: u32 = 0x00000008; pub const IN_CLOSE_NOWRITE: u32 = 0x00000010; pub const IN_CLOSE: u32 = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE; pub const IN_OPEN: u32 = 0x00000020; pub const IN_MOVED_FROM: u32 = 0x00000040; pub const IN_MOVED_TO: u32 = 0x00000080; pub const IN_MOVE: u32 = IN_MOVED_FROM | IN_MOVED_TO; pub const IN_CREATE: u32 = 0x00000100; pub const IN_DELETE: u32 = 0x00000200; pub const IN_DELETE_SELF: u32 = 0x00000400; pub const IN_MOVE_SELF: u32 = 0x00000800; pub const IN_UNMOUNT: u32 = 0x00002000; pub const IN_Q_OVERFLOW: u32 = 0x00004000; pub const IN_IGNORED: u32 = 0x00008000; pub const IN_ONLYDIR: u32 = 0x01000000; pub const IN_DONT_FOLLOW: u32 = 0x02000000; pub const IN_ISDIR: u32 = 0x40000000; pub const IN_ONESHOT: u32 = 0x80000000; pub const REG_EXTENDED: c_int = 0o0001; pub const REG_ICASE: c_int = 0o0002; pub const REG_NEWLINE: c_int = 0o0010; pub const REG_NOSUB: c_int = 0o0004; pub const REG_NOTBOL: c_int = 0o00001; pub const REG_NOTEOL: c_int = 0o00002; pub const REG_ENOSYS: c_int = 17; pub const REG_NOMATCH: c_int = 1; pub const REG_BADPAT: c_int = 2; pub const REG_ECOLLATE: c_int = 3; pub const REG_ECTYPE: c_int = 4; pub const REG_EESCAPE: c_int = 5; pub const REG_ESUBREG: c_int = 6; pub const REG_EBRACK: c_int = 7; pub const REG_EPAREN: c_int = 8; pub const REG_EBRACE: c_int = 9; pub const REG_BADBR: c_int = 10; pub const REG_ERANGE: c_int = 11; pub const REG_ESPACE: c_int = 12; pub const REG_BADRPT: c_int = 13; // errno.h pub const EOK: c_int = 0; pub const EWOULDBLOCK: c_int = EAGAIN; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EDEADLK: c_int = 45; pub const ENOLCK: c_int = 46; pub const ECANCELED: c_int = 47; pub const EDQUOT: c_int = 49; pub const EBADE: c_int = 50; pub const EBADR: c_int = 51; pub const EXFULL: c_int = 52; pub const ENOANO: c_int = 53; pub const EBADRQC: c_int = 54; pub const EBADSLT: c_int = 55; pub const EDEADLOCK: c_int = 56; pub const EBFONT: c_int = 57; pub const EOWNERDEAD: c_int = 58; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EMULTIHOP: c_int = 74; pub const EBADMSG: c_int = 77; pub const ENAMETOOLONG: c_int = 78; pub const EOVERFLOW: c_int = 79; pub const ENOTUNIQ: c_int = 80; pub const EBADFD: c_int = 81; pub const EREMCHG: c_int = 82; pub const ELIBACC: c_int = 83; pub const ELIBBAD: c_int = 84; pub const ELIBSCN: c_int = 85; pub const ELIBMAX: c_int = 86; pub const ELIBEXEC: c_int = 87; pub const EILSEQ: c_int = 88; pub const ENOSYS: c_int = 89; pub const ELOOP: c_int = 90; pub const ERESTART: c_int = 91; pub const ESTRPIPE: c_int = 92; pub const ENOTEMPTY: c_int = 93; pub const EUSERS: c_int = 94; pub const ENOTRECOVERABLE: c_int = 95; pub const EOPNOTSUPP: c_int = 103; pub const EFPOS: c_int = 110; pub const ESTALE: c_int = 122; pub const EINPROGRESS: c_int = 236; pub const EALREADY: c_int = 237; pub const ENOTSOCK: c_int = 238; pub const EDESTADDRREQ: c_int = 239; pub const EMSGSIZE: c_int = 240; pub const EPROTOTYPE: c_int = 241; pub const ENOPROTOOPT: c_int = 242; pub const EPROTONOSUPPORT: c_int = 243; pub const ESOCKTNOSUPPORT: c_int = 244; pub const EPFNOSUPPORT: c_int = 246; pub const EAFNOSUPPORT: c_int = 247; pub const EADDRINUSE: c_int = 248; pub const EADDRNOTAVAIL: c_int = 249; pub const ENETDOWN: c_int = 250; pub const ENETUNREACH: c_int = 251; pub const ENETRESET: c_int = 252; pub const ECONNABORTED: c_int = 253; pub const ECONNRESET: c_int = 254; pub const ENOBUFS: c_int = 255; pub const EISCONN: c_int = 256; pub const ENOTCONN: c_int = 257; pub const ESHUTDOWN: c_int = 258; pub const ETOOMANYREFS: c_int = 259; pub const ETIMEDOUT: c_int = 260; pub const ECONNREFUSED: c_int = 261; pub const EHOSTDOWN: c_int = 264; pub const EHOSTUNREACH: c_int = 265; pub const EBADRPC: c_int = 272; pub const ERPCMISMATCH: c_int = 273; pub const EPROGUNAVAIL: c_int = 274; pub const EPROGMISMATCH: c_int = 275; pub const EPROCUNAVAIL: c_int = 276; pub const ENOREMOTE: c_int = 300; pub const ENONDP: c_int = 301; pub const EBADFSYS: c_int = 302; pub const EMORE: c_int = 309; pub const ECTRLTERM: c_int = 310; pub const ENOLIC: c_int = 311; pub const ESRVRFAULT: c_int = 312; pub const EENDIAN: c_int = 313; pub const ESECTYPEINVAL: c_int = 314; pub const RUSAGE_CHILDREN: c_int = -1; pub const L_tmpnam: c_uint = 255; pub const _PC_LINK_MAX: c_int = 1; pub const _PC_MAX_CANON: c_int = 2; pub const _PC_MAX_INPUT: c_int = 3; pub const _PC_NAME_MAX: c_int = 4; pub const _PC_PATH_MAX: c_int = 5; pub const _PC_PIPE_BUF: c_int = 6; pub const _PC_CHOWN_RESTRICTED: c_int = 9; pub const _PC_NO_TRUNC: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_SYNC_IO: c_int = 14; pub const _PC_ASYNC_IO: c_int = 12; pub const _PC_PRIO_IO: c_int = 13; pub const _PC_SOCK_MAXBUF: c_int = 15; pub const _PC_FILESIZEBITS: c_int = 16; pub const _PC_REC_INCR_XFER_SIZE: c_int = 22; pub const _PC_REC_MAX_XFER_SIZE: c_int = 23; pub const _PC_REC_MIN_XFER_SIZE: c_int = 24; pub const _PC_REC_XFER_ALIGN: c_int = 25; pub const _PC_ALLOC_SIZE_MIN: c_int = 21; pub const _PC_SYMLINK_MAX: c_int = 17; pub const _PC_2_SYMLINKS: c_int = 20; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_ARG_MAX: c_int = 1; pub const _SC_CHILD_MAX: c_int = 2; pub const _SC_CLK_TCK: c_int = 3; pub const _SC_NGROUPS_MAX: c_int = 4; pub const _SC_OPEN_MAX: c_int = 5; pub const _SC_JOB_CONTROL: c_int = 6; pub const _SC_SAVED_IDS: c_int = 7; pub const _SC_VERSION: c_int = 8; pub const _SC_PASS_MAX: c_int = 9; pub const _SC_PAGESIZE: c_int = 11; pub const _SC_XOPEN_VERSION: c_int = 12; pub const _SC_STREAM_MAX: c_int = 13; pub const _SC_TZNAME_MAX: c_int = 14; pub const _SC_AIO_LISTIO_MAX: c_int = 15; pub const _SC_AIO_MAX: c_int = 16; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 17; pub const _SC_DELAYTIMER_MAX: c_int = 18; pub const _SC_MQ_OPEN_MAX: c_int = 19; pub const _SC_MQ_PRIO_MAX: c_int = 20; pub const _SC_RTSIG_MAX: c_int = 21; pub const _SC_SEM_NSEMS_MAX: c_int = 22; pub const _SC_SEM_VALUE_MAX: c_int = 23; pub const _SC_SIGQUEUE_MAX: c_int = 24; pub const _SC_TIMER_MAX: c_int = 25; pub const _SC_ASYNCHRONOUS_IO: c_int = 26; pub const _SC_FSYNC: c_int = 27; pub const _SC_MAPPED_FILES: c_int = 28; pub const _SC_MEMLOCK: c_int = 29; pub const _SC_MEMLOCK_RANGE: c_int = 30; pub const _SC_MEMORY_PROTECTION: c_int = 31; pub const _SC_MESSAGE_PASSING: c_int = 32; pub const _SC_PRIORITIZED_IO: c_int = 33; pub const _SC_PRIORITY_SCHEDULING: c_int = 34; pub const _SC_REALTIME_SIGNALS: c_int = 35; pub const _SC_SEMAPHORES: c_int = 36; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 37; pub const _SC_SYNCHRONIZED_IO: c_int = 38; pub const _SC_TIMERS: c_int = 39; pub const _SC_GETGR_R_SIZE_MAX: c_int = 40; pub const _SC_GETPW_R_SIZE_MAX: c_int = 41; pub const _SC_LOGIN_NAME_MAX: c_int = 42; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 43; pub const _SC_THREAD_KEYS_MAX: c_int = 44; pub const _SC_THREAD_STACK_MIN: c_int = 45; pub const _SC_THREAD_THREADS_MAX: c_int = 46; pub const _SC_TTY_NAME_MAX: c_int = 47; pub const _SC_THREADS: c_int = 48; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 49; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 50; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 51; pub const _SC_THREAD_PRIO_INHERIT: c_int = 52; pub const _SC_THREAD_PRIO_PROTECT: c_int = 53; pub const _SC_THREAD_PROCESS_SHARED: c_int = 54; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 55; pub const _SC_2_CHAR_TERM: c_int = 56; pub const _SC_2_C_BIND: c_int = 57; pub const _SC_2_C_DEV: c_int = 58; pub const _SC_2_C_VERSION: c_int = 59; pub const _SC_2_FORT_DEV: c_int = 60; pub const _SC_2_FORT_RUN: c_int = 61; pub const _SC_2_LOCALEDEF: c_int = 62; pub const _SC_2_SW_DEV: c_int = 63; pub const _SC_2_UPE: c_int = 64; pub const _SC_2_VERSION: c_int = 65; pub const _SC_ATEXIT_MAX: c_int = 66; pub const _SC_AVPHYS_PAGES: c_int = 67; pub const _SC_BC_BASE_MAX: c_int = 68; pub const _SC_BC_DIM_MAX: c_int = 69; pub const _SC_BC_SCALE_MAX: c_int = 70; pub const _SC_BC_STRING_MAX: c_int = 71; pub const _SC_CHARCLASS_NAME_MAX: c_int = 72; pub const _SC_CHAR_BIT: c_int = 73; pub const _SC_CHAR_MAX: c_int = 74; pub const _SC_CHAR_MIN: c_int = 75; pub const _SC_COLL_WEIGHTS_MAX: c_int = 76; pub const _SC_EQUIV_CLASS_MAX: c_int = 77; pub const _SC_EXPR_NEST_MAX: c_int = 78; pub const _SC_INT_MAX: c_int = 79; pub const _SC_INT_MIN: c_int = 80; pub const _SC_LINE_MAX: c_int = 81; pub const _SC_LONG_BIT: c_int = 82; pub const _SC_MB_LEN_MAX: c_int = 83; pub const _SC_NL_ARGMAX: c_int = 84; pub const _SC_NL_LANGMAX: c_int = 85; pub const _SC_NL_MSGMAX: c_int = 86; pub const _SC_NL_NMAX: c_int = 87; pub const _SC_NL_SETMAX: c_int = 88; pub const _SC_NL_TEXTMAX: c_int = 89; pub const _SC_NPROCESSORS_CONF: c_int = 90; pub const _SC_NPROCESSORS_ONLN: c_int = 91; pub const _SC_NZERO: c_int = 92; pub const _SC_PHYS_PAGES: c_int = 93; pub const _SC_PII: c_int = 94; pub const _SC_PII_INTERNET: c_int = 95; pub const _SC_PII_INTERNET_DGRAM: c_int = 96; pub const _SC_PII_INTERNET_STREAM: c_int = 97; pub const _SC_PII_OSI: c_int = 98; pub const _SC_PII_OSI_CLTS: c_int = 99; pub const _SC_PII_OSI_COTS: c_int = 100; pub const _SC_PII_OSI_M: c_int = 101; pub const _SC_PII_SOCKET: c_int = 102; pub const _SC_PII_XTI: c_int = 103; pub const _SC_POLL: c_int = 104; pub const _SC_RE_DUP_MAX: c_int = 105; pub const _SC_SCHAR_MAX: c_int = 106; pub const _SC_SCHAR_MIN: c_int = 107; pub const _SC_SELECT: c_int = 108; pub const _SC_SHRT_MAX: c_int = 109; pub const _SC_SHRT_MIN: c_int = 110; pub const _SC_SSIZE_MAX: c_int = 111; pub const _SC_T_IOV_MAX: c_int = 112; pub const _SC_UCHAR_MAX: c_int = 113; pub const _SC_UINT_MAX: c_int = 114; pub const _SC_UIO_MAXIOV: c_int = 115; pub const _SC_ULONG_MAX: c_int = 116; pub const _SC_USHRT_MAX: c_int = 117; pub const _SC_WORD_BIT: c_int = 118; pub const _SC_XOPEN_CRYPT: c_int = 119; pub const _SC_XOPEN_ENH_I18N: c_int = 120; pub const _SC_XOPEN_SHM: c_int = 121; pub const _SC_XOPEN_UNIX: c_int = 122; pub const _SC_XOPEN_XCU_VERSION: c_int = 123; pub const _SC_XOPEN_XPG2: c_int = 124; pub const _SC_XOPEN_XPG3: c_int = 125; pub const _SC_XOPEN_XPG4: c_int = 126; pub const _SC_XBS5_ILP32_OFF32: c_int = 127; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 128; pub const _SC_XBS5_LP64_OFF64: c_int = 129; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 130; pub const _SC_ADVISORY_INFO: c_int = 131; pub const _SC_CPUTIME: c_int = 132; pub const _SC_SPAWN: c_int = 133; pub const _SC_SPORADIC_SERVER: c_int = 134; pub const _SC_THREAD_CPUTIME: c_int = 135; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 136; pub const _SC_TIMEOUTS: c_int = 137; pub const _SC_BARRIERS: c_int = 138; pub const _SC_CLOCK_SELECTION: c_int = 139; pub const _SC_MONOTONIC_CLOCK: c_int = 140; pub const _SC_READER_WRITER_LOCKS: c_int = 141; pub const _SC_SPIN_LOCKS: c_int = 142; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 143; pub const _SC_TRACE_EVENT_FILTER: c_int = 144; pub const _SC_TRACE: c_int = 145; pub const _SC_TRACE_INHERIT: c_int = 146; pub const _SC_TRACE_LOG: c_int = 147; pub const _SC_2_PBS: c_int = 148; pub const _SC_2_PBS_ACCOUNTING: c_int = 149; pub const _SC_2_PBS_CHECKPOINT: c_int = 150; pub const _SC_2_PBS_LOCATE: c_int = 151; pub const _SC_2_PBS_MESSAGE: c_int = 152; pub const _SC_2_PBS_TRACK: c_int = 153; pub const _SC_HOST_NAME_MAX: c_int = 154; pub const _SC_IOV_MAX: c_int = 155; pub const _SC_IPV6: c_int = 156; pub const _SC_RAW_SOCKETS: c_int = 157; pub const _SC_REGEXP: c_int = 158; pub const _SC_SHELL: c_int = 159; pub const _SC_SS_REPL_MAX: c_int = 160; pub const _SC_SYMLOOP_MAX: c_int = 161; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 162; pub const _SC_TRACE_NAME_MAX: c_int = 163; pub const _SC_TRACE_SYS_MAX: c_int = 164; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 165; pub const _SC_V6_ILP32_OFF32: c_int = 166; pub const _SC_V6_ILP32_OFFBIG: c_int = 167; pub const _SC_V6_LP64_OFF64: c_int = 168; pub const _SC_V6_LPBIG_OFFBIG: c_int = 169; pub const _SC_XOPEN_REALTIME: c_int = 170; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 171; pub const _SC_XOPEN_LEGACY: c_int = 172; pub const _SC_XOPEN_STREAMS: c_int = 173; pub const _SC_V7_ILP32_OFF32: c_int = 176; pub const _SC_V7_ILP32_OFFBIG: c_int = 177; pub const _SC_V7_LP64_OFF64: c_int = 178; pub const _SC_V7_LPBIG_OFFBIG: c_int = 179; pub const GLOB_ERR: c_int = 0x0001; pub const GLOB_MARK: c_int = 0x0002; pub const GLOB_NOSORT: c_int = 0x0004; pub const GLOB_DOOFFS: c_int = 0x0008; pub const GLOB_NOCHECK: c_int = 0x0010; pub const GLOB_APPEND: c_int = 0x0020; pub const GLOB_NOESCAPE: c_int = 0x0040; pub const GLOB_NOSPACE: c_int = 1; pub const GLOB_ABORTED: c_int = 2; pub const GLOB_NOMATCH: c_int = 3; pub const S_IEXEC: mode_t = crate::S_IXUSR; pub const S_IWRITE: mode_t = crate::S_IWUSR; pub const S_IREAD: mode_t = crate::S_IRUSR; pub const S_IFIFO: crate::mode_t = 0o1_0000; pub const S_IFCHR: crate::mode_t = 0o2_0000; pub const S_IFDIR: crate::mode_t = 0o4_0000; pub const S_IFBLK: crate::mode_t = 0o6_0000; pub const S_IFREG: crate::mode_t = 0o10_0000; pub const S_IFLNK: crate::mode_t = 0o12_0000; pub const S_IFSOCK: crate::mode_t = 0o14_0000; pub const S_IFMT: crate::mode_t = 0o17_0000; pub const S_IXOTH: crate::mode_t = 0o0001; pub const S_IWOTH: crate::mode_t = 0o0002; pub const S_IROTH: crate::mode_t = 0o0004; pub const S_IRWXO: crate::mode_t = 0o0007; pub const S_IXGRP: crate::mode_t = 0o0010; pub const S_IWGRP: crate::mode_t = 0o0020; pub const S_IRGRP: crate::mode_t = 0o0040; pub const S_IRWXG: crate::mode_t = 0o0070; pub const S_IXUSR: crate::mode_t = 0o0100; pub const S_IWUSR: crate::mode_t = 0o0200; pub const S_IRUSR: crate::mode_t = 0o0400; pub const S_IRWXU: crate::mode_t = 0o0700; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const ST_RDONLY: c_ulong = 0x01; pub const ST_NOSUID: c_ulong = 0x04; pub const ST_NOEXEC: c_ulong = 0x02; pub const ST_NOATIME: c_ulong = 0x20; pub const RTLD_NEXT: *mut c_void = -3i64 as *mut c_void; pub const RTLD_DEFAULT: *mut c_void = -2i64 as *mut c_void; pub const RTLD_NODELETE: c_int = 0x1000; pub const RTLD_NOW: c_int = 0x0002; pub const EMPTY: c_short = 0; pub const RUN_LVL: c_short = 1; pub const BOOT_TIME: c_short = 2; pub const NEW_TIME: c_short = 4; pub const OLD_TIME: c_short = 3; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const USER_PROCESS: c_short = 7; pub const DEAD_PROCESS: c_short = 8; pub const ACCOUNTING: c_short = 9; pub const ENOTSUP: c_int = 48; pub const BUFSIZ: c_uint = 1024; pub const TMP_MAX: c_uint = 26 * 26 * 26; pub const FOPEN_MAX: c_uint = 16; pub const FILENAME_MAX: c_uint = 255; pub const NI_MAXHOST: crate::socklen_t = 1025; pub const M_KEEP: c_int = 4; pub const REG_STARTEND: c_int = 0o00004; pub const VEOF: usize = 4; pub const RTLD_GLOBAL: c_int = 0x0100; pub const RTLD_NOLOAD: c_int = 0x0004; pub const O_RDONLY: c_int = 0o000000; pub const O_WRONLY: c_int = 0o000001; pub const O_RDWR: c_int = 0o000002; pub const O_EXEC: c_int = 0o00003; pub const O_ASYNC: c_int = 0o0200000; pub const O_NDELAY: c_int = O_NONBLOCK; pub const O_TRUNC: c_int = 0o001000; pub const O_CLOEXEC: c_int = 0o020000; pub const O_DIRECTORY: c_int = 0o4000000; pub const O_ACCMODE: c_int = 0o000007; pub const O_APPEND: c_int = 0o000010; pub const O_CREAT: c_int = 0o000400; pub const O_EXCL: c_int = 0o002000; pub const O_NOCTTY: c_int = 0o004000; pub const O_NONBLOCK: c_int = 0o000200; pub const O_SYNC: c_int = 0o000040; pub const O_RSYNC: c_int = 0o000100; pub const O_DSYNC: c_int = 0o000020; pub const O_NOFOLLOW: c_int = 0o010000; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const SOCK_SEQPACKET: c_int = 5; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_CLOEXEC: c_int = 0x10000000; pub const SA_SIGINFO: c_int = 0x0002; pub const SA_NOCLDWAIT: c_int = 0x0020; pub const SA_NODEFER: c_int = 0x0010; pub const SA_RESETHAND: c_int = 0x0004; pub const SA_NOCLDSTOP: c_int = 0x0001; pub const SIGTTIN: c_int = 26; pub const SIGTTOU: c_int = 27; pub const SIGXCPU: c_int = 30; pub const SIGXFSZ: c_int = 31; pub const SIGVTALRM: c_int = 28; pub const SIGPROF: c_int = 29; pub const SIGWINCH: c_int = 20; pub const SIGCHLD: c_int = 18; pub const SIGBUS: c_int = 10; pub const SIGUSR1: c_int = 16; pub const SIGUSR2: c_int = 17; pub const SIGCONT: c_int = 25; pub const SIGSTOP: c_int = 23; pub const SIGTSTP: c_int = 24; pub const SIGURG: c_int = 21; pub const SIGIO: c_int = SIGPOLL; pub const SIGSYS: c_int = 12; pub const SIGPOLL: c_int = 22; pub const SIGPWR: c_int = 19; pub const SIG_SETMASK: c_int = 2; pub const SIG_BLOCK: c_int = 0; pub const SIG_UNBLOCK: c_int = 1; pub const POLLWRNORM: c_short = crate::POLLOUT; pub const POLLWRBAND: c_short = 0x0010; pub const F_SETLK: c_int = 106; pub const F_SETLKW: c_int = 107; pub const F_ALLOCSP: c_int = 110; pub const F_FREESP: c_int = 111; pub const F_GETLK: c_int = 114; pub const F_RDLCK: c_int = 1; pub const F_WRLCK: c_int = 2; pub const F_UNLCK: c_int = 3; pub const NCCS: usize = 40; pub const MAP_ANON: c_int = MAP_ANONYMOUS; pub const MAP_ANONYMOUS: c_int = 0x00080000; pub const MCL_CURRENT: c_int = 0x000000001; pub const MCL_FUTURE: c_int = 0x000000002; pub const _TIO_CBAUD: crate::tcflag_t = 15; pub const CBAUD: crate::tcflag_t = _TIO_CBAUD; pub const TAB1: crate::tcflag_t = 0x0800; pub const TAB2: crate::tcflag_t = 0x1000; pub const TAB3: crate::tcflag_t = 0x1800; pub const CR1: crate::tcflag_t = 0x200; pub const CR2: crate::tcflag_t = 0x400; pub const CR3: crate::tcflag_t = 0x600; pub const FF1: crate::tcflag_t = 0x8000; pub const BS1: crate::tcflag_t = 0x2000; pub const VT1: crate::tcflag_t = 0x4000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 17; pub const IXON: crate::tcflag_t = 0x00000400; pub const IXOFF: crate::tcflag_t = 0x00001000; pub const ONLCR: crate::tcflag_t = 0x00000004; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS6: crate::tcflag_t = 0x10; pub const CS7: crate::tcflag_t = 0x20; pub const CS8: crate::tcflag_t = 0x30; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00000800; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOCTL: crate::tcflag_t = 0x00000200; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const OLCUC: crate::tcflag_t = 0x00000002; pub const NLDLY: crate::tcflag_t = 0x00000100; pub const CRDLY: crate::tcflag_t = 0x00000600; pub const TABDLY: crate::tcflag_t = 0x00001800; pub const BSDLY: crate::tcflag_t = 0x00002000; pub const FFDLY: crate::tcflag_t = 0x00008000; pub const VTDLY: crate::tcflag_t = 0x00004000; pub const XTABS: crate::tcflag_t = 0x1800; pub const B0: crate::speed_t = 0; pub const B50: crate::speed_t = 1; pub const B75: crate::speed_t = 2; pub const B110: crate::speed_t = 3; pub const B134: crate::speed_t = 4; pub const B150: crate::speed_t = 5; pub const B200: crate::speed_t = 6; pub const B300: crate::speed_t = 7; pub const B600: crate::speed_t = 8; pub const B1200: crate::speed_t = 9; pub const B1800: crate::speed_t = 10; pub const B2400: crate::speed_t = 11; pub const B4800: crate::speed_t = 12; pub const B9600: crate::speed_t = 13; pub const B19200: crate::speed_t = 14; pub const B38400: crate::speed_t = 15; pub const EXTA: crate::speed_t = 14; pub const EXTB: crate::speed_t = 15; pub const B57600: crate::speed_t = 57600; pub const B115200: crate::speed_t = 115200; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; pub const VMIN: usize = 16; pub const IEXTEN: crate::tcflag_t = 0x00008000; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const TCSANOW: c_int = 0x0001; pub const TCSADRAIN: c_int = 0x0002; pub const TCSAFLUSH: c_int = 0x0004; pub const HW_MACHINE: c_int = 1; pub const HW_MODEL: c_int = 2; pub const HW_NCPU: c_int = 3; pub const HW_BYTEORDER: c_int = 4; pub const HW_PHYSMEM: c_int = 5; pub const HW_USERMEM: c_int = 6; pub const HW_PAGESIZE: c_int = 7; pub const HW_DISKNAMES: c_int = 8; pub const CTL_KERN: c_int = 1; pub const CTL_VM: c_int = 2; pub const CTL_VFS: c_int = 3; pub const CTL_NET: c_int = 4; pub const CTL_DEBUG: c_int = 5; pub const CTL_HW: c_int = 6; pub const CTL_MACHDEP: c_int = 7; pub const CTL_USER: c_int = 8; pub const DAY_1: crate::nl_item = 8; pub const DAY_2: crate::nl_item = 9; pub const DAY_3: crate::nl_item = 10; pub const DAY_4: crate::nl_item = 11; pub const DAY_5: crate::nl_item = 12; pub const DAY_6: crate::nl_item = 13; pub const DAY_7: crate::nl_item = 14; pub const MON_1: crate::nl_item = 22; pub const MON_2: crate::nl_item = 23; pub const MON_3: crate::nl_item = 24; pub const MON_4: crate::nl_item = 25; pub const MON_5: crate::nl_item = 26; pub const MON_6: crate::nl_item = 27; pub const MON_7: crate::nl_item = 28; pub const MON_8: crate::nl_item = 29; pub const MON_9: crate::nl_item = 30; pub const MON_10: crate::nl_item = 31; pub const MON_11: crate::nl_item = 32; pub const MON_12: crate::nl_item = 33; pub const ABDAY_1: crate::nl_item = 15; pub const ABDAY_2: crate::nl_item = 16; pub const ABDAY_3: crate::nl_item = 17; pub const ABDAY_4: crate::nl_item = 18; pub const ABDAY_5: crate::nl_item = 19; pub const ABDAY_6: crate::nl_item = 20; pub const ABDAY_7: crate::nl_item = 21; pub const ABMON_1: crate::nl_item = 34; pub const ABMON_2: crate::nl_item = 35; pub const ABMON_3: crate::nl_item = 36; pub const ABMON_4: crate::nl_item = 37; pub const ABMON_5: crate::nl_item = 38; pub const ABMON_6: crate::nl_item = 39; pub const ABMON_7: crate::nl_item = 40; pub const ABMON_8: crate::nl_item = 41; pub const ABMON_9: crate::nl_item = 42; pub const ABMON_10: crate::nl_item = 43; pub const ABMON_11: crate::nl_item = 44; pub const ABMON_12: crate::nl_item = 45; pub const AF_CCITT: c_int = 10; pub const AF_CHAOS: c_int = 5; pub const AF_CNT: c_int = 21; pub const AF_COIP: c_int = 20; pub const AF_DATAKIT: c_int = 9; pub const AF_DECnet: c_int = 12; pub const AF_DLI: c_int = 13; pub const AF_E164: c_int = 26; pub const AF_ECMA: c_int = 8; pub const AF_HYLINK: c_int = 15; pub const AF_IMPLINK: c_int = 3; pub const AF_ISO: c_int = 7; pub const AF_LAT: c_int = 14; pub const AF_LINK: c_int = 18; pub const AF_OSI: c_int = 7; pub const AF_PUP: c_int = 4; pub const ALT_DIGITS: crate::nl_item = 50; pub const AM_STR: crate::nl_item = 6; pub const B76800: crate::speed_t = 76800; pub const BIOCFLUSH: c_int = 17000; pub const BIOCGBLEN: c_int = 1074020966; pub const BIOCGDLT: c_int = 1074020970; pub const BIOCGHDRCMPLT: c_int = 1074020980; pub const BIOCGRTIMEOUT: c_int = 1074807406; pub const BIOCIMMEDIATE: c_int = -2147204496; pub const BIOCPROMISC: c_int = 17001; pub const BIOCSBLEN: c_int = -1073462682; pub const BIOCSETF: c_int = -2146418073; pub const BIOCSHDRCMPLT: c_int = -2147204491; pub const BIOCSRTIMEOUT: c_int = -2146418067; pub const BIOCVERSION: c_int = 1074020977; pub const BPF_ALIGNMENT: usize = mem::size_of::(); pub const CHAR_BIT: usize = 8; pub const CODESET: crate::nl_item = 1; pub const CRNCYSTR: crate::nl_item = 55; pub const D_FLAG_FILTER: c_int = 0x00000001; pub const D_FLAG_STAT: c_int = 0x00000002; pub const D_FLAG_STAT_FORM_MASK: c_int = 0x000000f0; pub const D_FLAG_STAT_FORM_T32_2001: c_int = 0x00000010; pub const D_FLAG_STAT_FORM_T32_2008: c_int = 0x00000020; pub const D_FLAG_STAT_FORM_T64_2008: c_int = 0x00000030; pub const D_FLAG_STAT_FORM_UNSET: c_int = 0x00000000; pub const D_FMT: crate::nl_item = 3; pub const D_GETFLAG: c_int = 1; pub const D_SETFLAG: c_int = 2; pub const D_T_FMT: crate::nl_item = 2; pub const ERA: crate::nl_item = 46; pub const ERA_D_FMT: crate::nl_item = 47; pub const ERA_D_T_FMT: crate::nl_item = 48; pub const ERA_T_FMT: crate::nl_item = 49; pub const RADIXCHAR: crate::nl_item = 51; pub const THOUSEP: crate::nl_item = 52; pub const YESEXPR: crate::nl_item = 53; pub const NOEXPR: crate::nl_item = 54; pub const F_GETOWN: c_int = 35; pub const FIONBIO: c_int = -2147195266; pub const FIOASYNC: c_int = -2147195267; pub const FIOCLEX: c_int = 26113; pub const FIOGETOWN: c_int = 1074030203; pub const FIONCLEX: c_int = 26114; pub const FIONREAD: c_int = 1074030207; pub const FIOSETOWN: c_int = -2147195268; pub const F_SETOWN: c_int = 36; pub const IFF_LINK0: c_int = 0x00001000; pub const IFF_LINK1: c_int = 0x00002000; pub const IFF_LINK2: c_int = 0x00004000; pub const IFF_OACTIVE: c_int = 0x00000400; pub const IFF_SIMPLEX: c_int = 0x00000800; pub const IHFLOW: tcflag_t = 0x00000001; pub const IIDLE: tcflag_t = 0x00000008; pub const IP_RECVDSTADDR: c_int = 7; pub const IP_RECVIF: c_int = 20; pub const IPTOS_ECN_NOTECT: u8 = 0x00; pub const IUCLC: tcflag_t = 0x00000200; pub const IUTF8: tcflag_t = 0x0004000; pub const KERN_ARGMAX: c_int = 8; pub const KERN_BOOTTIME: c_int = 21; pub const KERN_CLOCKRATE: c_int = 12; pub const KERN_FILE: c_int = 15; pub const KERN_HOSTID: c_int = 11; pub const KERN_HOSTNAME: c_int = 10; pub const KERN_JOB_CONTROL: c_int = 19; pub const KERN_MAXFILES: c_int = 7; pub const KERN_MAXPROC: c_int = 6; pub const KERN_MAXVNODES: c_int = 5; pub const KERN_NGROUPS: c_int = 18; pub const KERN_OSRELEASE: c_int = 2; pub const KERN_OSREV: c_int = 3; pub const KERN_OSTYPE: c_int = 1; pub const KERN_POSIX1: c_int = 17; pub const KERN_PROC: c_int = 14; pub const KERN_PROC_ALL: c_int = 0; pub const KERN_PROC_PGRP: c_int = 2; pub const KERN_PROC_PID: c_int = 1; pub const KERN_PROC_RUID: c_int = 6; pub const KERN_PROC_SESSION: c_int = 3; pub const KERN_PROC_TTY: c_int = 4; pub const KERN_PROC_UID: c_int = 5; pub const KERN_PROF: c_int = 16; pub const KERN_SAVED_IDS: c_int = 20; pub const KERN_SECURELVL: c_int = 9; pub const KERN_VERSION: c_int = 4; pub const KERN_VNODE: c_int = 13; pub const LC_ALL: c_int = 63; pub const LC_COLLATE: c_int = 1; pub const LC_CTYPE: c_int = 2; pub const LC_MESSAGES: c_int = 32; pub const LC_MONETARY: c_int = 4; pub const LC_NUMERIC: c_int = 8; pub const LC_TIME: c_int = 16; pub const MAP_STACK: c_int = 0x00001000; pub const MNT_NOEXEC: c_int = 0x02; pub const MNT_NOSUID: c_int = 0x04; pub const MNT_RDONLY: c_int = 0x01; pub const NET_RT_DUMP: c_int = 1; pub const NET_RT_FLAGS: c_int = 2; pub const OHFLOW: tcflag_t = 0x00000002; pub const P_ALL: idtype_t = 0; pub const PARSTK: tcflag_t = 0x00000004; pub const PF_CCITT: c_int = 10; pub const PF_CHAOS: c_int = 5; pub const PF_CNT: c_int = 21; pub const PF_COIP: c_int = 20; pub const PF_DATAKIT: c_int = 9; pub const PF_DECnet: c_int = 12; pub const PF_DLI: c_int = 13; pub const PF_ECMA: c_int = 8; pub const PF_HYLINK: c_int = 15; pub const PF_IMPLINK: c_int = 3; pub const PF_ISO: c_int = 7; pub const PF_LAT: c_int = 14; pub const PF_LINK: c_int = 18; pub const PF_OSI: c_int = 7; pub const PF_PIP: c_int = 25; pub const PF_PUP: c_int = 4; pub const PF_RTIP: c_int = 22; pub const PF_XTP: c_int = 19; pub const PM_STR: crate::nl_item = 7; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 2; pub const POSIX_MADV_SEQUENTIAL: c_int = 1; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const _POSIX_VDISABLE: c_int = 0; pub const P_PGID: idtype_t = 2; pub const P_PID: idtype_t = 1; pub const PRIO_PGRP: c_int = 1; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_USER: c_int = 2; pub const pseudo_AF_PIP: c_int = 25; pub const pseudo_AF_RTIP: c_int = 22; pub const pseudo_AF_XTP: c_int = 19; pub const REG_ASSERT: c_int = 15; pub const REG_ATOI: c_int = 255; pub const REG_BACKR: c_int = 0x400; pub const REG_BASIC: c_int = 0x00; pub const REG_DUMP: c_int = 0x80; pub const REG_EMPTY: c_int = 14; pub const REG_INVARG: c_int = 16; pub const REG_ITOA: c_int = 0o400; pub const REG_LARGE: c_int = 0x200; pub const REG_NOSPEC: c_int = 0x10; pub const REG_OK: c_int = 0; pub const REG_PEND: c_int = 0x20; pub const REG_TRACE: c_int = 0x100; pub const RLIMIT_AS: c_int = 6; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_MEMLOCK: c_int = 7; pub const RLIMIT_NOFILE: c_int = 5; pub const RLIMIT_NPROC: c_int = 8; pub const RLIMIT_RSS: c_int = 6; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_VMEM: c_int = 6; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 14; pub const SCHED_ADJTOHEAD: c_int = 5; pub const SCHED_ADJTOTAIL: c_int = 6; pub const SCHED_MAXPOLICY: c_int = 7; pub const SCHED_SETPRIO: c_int = 7; pub const SCHED_SPORADIC: c_int = 4; pub const SHM_ANON: *mut c_char = -1isize as *mut c_char; pub const SIGCLD: c_int = SIGCHLD; pub const SIGDEADLK: c_int = 7; pub const SIGEMT: c_int = 7; pub const SIGEV_NONE: c_int = 0; pub const SIGEV_SIGNAL: c_int = 129; pub const SIGEV_THREAD: c_int = 135; pub const SO_USELOOPBACK: c_int = 0x0040; pub const _SS_ALIGNSIZE: usize = mem::size_of::(); pub const _SS_MAXSIZE: usize = 128; pub const _SS_PAD1SIZE: usize = _SS_ALIGNSIZE - 2; pub const _SS_PAD2SIZE: usize = _SS_MAXSIZE - 2 - _SS_PAD1SIZE - _SS_ALIGNSIZE; pub const TC_CPOSIX: tcflag_t = CLOCAL | CREAD | CSIZE | CSTOPB | HUPCL | PARENB | PARODD; pub const TCGETS: c_int = 0x404c540d; pub const TC_IPOSIX: tcflag_t = BRKINT | ICRNL | IGNBRK | IGNPAR | INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK; pub const TC_LPOSIX: tcflag_t = ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG | NOFLSH | TOSTOP; pub const TC_OPOSIX: tcflag_t = OPOST; pub const T_FMT_AMPM: crate::nl_item = 5; pub const TIOCCBRK: c_int = 29818; pub const TIOCCDTR: c_int = 29816; pub const TIOCDRAIN: c_int = 29790; pub const TIOCEXCL: c_int = 29709; pub const TIOCFLUSH: c_int = -2147191792; pub const TIOCGETA: c_int = 1078752275; pub const TIOCGPGRP: c_int = 1074033783; pub const TIOCGWINSZ: c_int = 1074295912; pub const TIOCMBIC: c_int = -2147191701; pub const TIOCMBIS: c_int = -2147191700; pub const TIOCMGET: c_int = 1074033770; pub const TIOCMSET: c_int = -2147191699; pub const TIOCNOTTY: c_int = 29809; pub const TIOCNXCL: c_int = 29710; pub const TIOCOUTQ: c_int = 1074033779; pub const TIOCPKT: c_int = -2147191696; pub const TIOCPKT_DATA: c_int = 0x00; pub const TIOCPKT_DOSTOP: c_int = 0x20; pub const TIOCPKT_FLUSHREAD: c_int = 0x01; pub const TIOCPKT_FLUSHWRITE: c_int = 0x02; pub const TIOCPKT_IOCTL: c_int = 0x40; pub const TIOCPKT_NOSTOP: c_int = 0x10; pub const TIOCPKT_START: c_int = 0x08; pub const TIOCPKT_STOP: c_int = 0x04; pub const TIOCSBRK: c_int = 29819; pub const TIOCSCTTY: c_int = 29793; pub const TIOCSDTR: c_int = 29817; pub const TIOCSETA: c_int = -2142473196; pub const TIOCSETAF: c_int = -2142473194; pub const TIOCSETAW: c_int = -2142473195; pub const TIOCSPGRP: c_int = -2147191690; pub const TIOCSTART: c_int = 29806; pub const TIOCSTI: c_int = -2147388302; pub const TIOCSTOP: c_int = 29807; pub const TIOCSWINSZ: c_int = -2146929561; pub const USER_CS_PATH: c_int = 1; pub const USER_BC_BASE_MAX: c_int = 2; pub const USER_BC_DIM_MAX: c_int = 3; pub const USER_BC_SCALE_MAX: c_int = 4; pub const USER_BC_STRING_MAX: c_int = 5; pub const USER_COLL_WEIGHTS_MAX: c_int = 6; pub const USER_EXPR_NEST_MAX: c_int = 7; pub const USER_LINE_MAX: c_int = 8; pub const USER_RE_DUP_MAX: c_int = 9; pub const USER_POSIX2_VERSION: c_int = 10; pub const USER_POSIX2_C_BIND: c_int = 11; pub const USER_POSIX2_C_DEV: c_int = 12; pub const USER_POSIX2_CHAR_TERM: c_int = 13; pub const USER_POSIX2_FORT_DEV: c_int = 14; pub const USER_POSIX2_FORT_RUN: c_int = 15; pub const USER_POSIX2_LOCALEDEF: c_int = 16; pub const USER_POSIX2_SW_DEV: c_int = 17; pub const USER_POSIX2_UPE: c_int = 18; pub const USER_STREAM_MAX: c_int = 19; pub const USER_TZNAME_MAX: c_int = 20; pub const VDOWN: usize = 31; pub const VINS: usize = 32; pub const VDEL: usize = 33; pub const VRUB: usize = 34; pub const VCAN: usize = 35; pub const VHOME: usize = 36; pub const VEND: usize = 37; pub const VSPARE3: usize = 38; pub const VSPARE4: usize = 39; pub const VSWTCH: usize = 7; pub const VDSUSP: usize = 11; pub const VFWD: usize = 18; pub const VLOGIN: usize = 19; pub const VPREFIX: usize = 20; pub const VSUFFIX: usize = 24; pub const VLEFT: usize = 28; pub const VRIGHT: usize = 29; pub const VUP: usize = 30; pub const XCASE: tcflag_t = 0x00000004; pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1; pub const PTHREAD_CREATE_JOINABLE: c_int = 0x00; pub const PTHREAD_CREATE_DETACHED: c_int = 0x01; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 2; pub const PTHREAD_MUTEX_NORMAL: c_int = 3; pub const PTHREAD_STACK_MIN: size_t = 256; pub const PTHREAD_MUTEX_DEFAULT: c_int = 0; pub const PTHREAD_MUTEX_STALLED: c_int = 0x00; pub const PTHREAD_MUTEX_ROBUST: c_int = 0x10; pub const PTHREAD_PROCESS_PRIVATE: c_int = 0x00; pub const PTHREAD_PROCESS_SHARED: c_int = 0x01; pub const PTHREAD_KEYS_MAX: usize = 128; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __u: 0x80000000, __owner: 0xffffffff, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __u: CLOCK_REALTIME as u32, __owner: 0xfffffffb, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __active: 0, __blockedwriters: 0, __blockedreaders: 0, __heavy: 0, __lock: PTHREAD_MUTEX_INITIALIZER, __rcond: PTHREAD_COND_INITIALIZER, __wcond: PTHREAD_COND_INITIALIZER, __owner: -2i32 as c_uint, __spare: 0, }; const_fn! { {const} fn _CMSG_ALIGN(len: usize) -> usize { len + mem::size_of::() - 1 & !(mem::size_of::() - 1) } {const} fn _ALIGN(p: usize, b: usize) -> usize { (p + b - 1) & !(b - 1) } } f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_NXTHDR(mhdr: *const crate::msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { let msg = _CMSG_ALIGN((*cmsg).cmsg_len as usize); let next = cmsg as usize + msg + _CMSG_ALIGN(mem::size_of::()); if next > (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize { 0 as *mut cmsghdr } else { (cmsg as usize + msg) as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(_CMSG_ALIGN(mem::size_of::()) as isize) } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { _CMSG_ALIGN(mem::size_of::()) as c_uint + length } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (_CMSG_ALIGN(mem::size_of::()) + _CMSG_ALIGN(length as usize)) as c_uint } pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } pub fn _DEXTRA_FIRST(_d: *const dirent) -> *mut crate::dirent_extra { let _f = &((*(_d)).d_name) as *const _; let _s = _d as usize; _ALIGN(_s + _f as usize - _s + (*_d).d_namelen as usize + 1, 8) as *mut crate::dirent_extra } pub fn _DEXTRA_VALID(_x: *const crate::dirent_extra, _d: *const dirent) -> bool { let sz = _x as usize - _d as usize + mem::size_of::(); let rsz = (*_d).d_reclen as usize; if sz > rsz || sz + (*_x).d_datalen as usize > rsz { false } else { true } } pub fn _DEXTRA_NEXT(_x: *const crate::dirent_extra) -> *mut crate::dirent_extra { _ALIGN( _x as usize + mem::size_of::() + (*_x).d_datalen as usize, 8, ) as *mut crate::dirent_extra } pub fn SOCKCREDSIZE(ngrps: usize) -> usize { let ngrps = if ngrps > 0 { ngrps - 1 } else { 0 }; mem::size_of::() + mem::size_of::() * ngrps } } safe_f! { pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0x7f } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: c_int) -> bool { (status & 0x80) != 0 } pub {const} fn IPTOS_ECN(x: u8) -> u8 { x & crate::IPTOS_ECN_MASK } pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { ((major << 10) | (minor)) as crate::dev_t } pub {const} fn major(dev: crate::dev_t) -> c_uint { ((dev as c_uint) >> 10) & 0x3f } pub {const} fn minor(dev: crate::dev_t) -> c_uint { (dev as c_uint) & 0x3ff } } cfg_if! { if #[cfg(not(target_env = "nto71_iosock"))] { extern "C" { pub fn sendmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_uint, ) -> c_int; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_uint, timeout: *mut crate::timespec, ) -> c_int; } } else { extern "C" { pub fn sendmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: size_t, flags: c_int, ) -> ssize_t; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: size_t, flags: c_int, timeout: *const crate::timespec, ) -> ssize_t; } } } // Network related functions are provided by libsocket and regex // functions are provided by libregex. // In QNX <=7.0, libregex functions were included in libc itself. #[link(name = "socket")] #[cfg_attr(not(target_env = "nto70"), link(name = "regex"))] extern "C" { pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; pub fn getpriority(which: c_int, who: crate::id_t) -> c_int; pub fn setpriority(which: c_int, who: crate::id_t, prio: c_int) -> c_int; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn mknodat( __fd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: crate::dev_t, ) -> c_int; pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_settime(clk_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn clock_getcpuclockid(pid: crate::pid_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn memalign(align: size_t, size: size_t) -> *mut c_void; pub fn setgroups(ngroups: c_int, ptr: *const crate::gid_t) -> c_int; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: c_int) -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: c_int) -> c_int; pub fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> *mut c_char; pub fn clearenv() -> c_int; pub fn waitid( idtype: idtype_t, id: id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn wait4( pid: crate::pid_t, status: *mut c_int, options: c_int, rusage: *mut crate::rusage, ) -> crate::pid_t; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn execvpe( file: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; pub fn getifaddrs(ifap: *mut *mut crate::ifaddrs) -> c_int; pub fn freeifaddrs(ifa: *mut crate::ifaddrs); pub fn bind( socket: c_int, address: *const crate::sockaddr, address_len: crate::socklen_t, ) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn sendmsg(fd: c_int, msg: *const crate::msghdr, flags: c_int) -> ssize_t; pub fn recvmsg(fd: c_int, msg: *mut crate::msghdr, flags: c_int) -> ssize_t; pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> c_int; pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> crate::pid_t; pub fn login_tty(fd: c_int) -> c_int; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn getpeereid(socket: c_int, euid: *mut crate::uid_t, egid: *mut crate::gid_t) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut crate::group; pub fn setspent(); pub fn endspent(); pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int; pub fn ftok(pathname: *const c_char, proj_id: c_int) -> crate::key_t; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn mkostemp(template: *mut c_char, flags: c_int) -> c_int; pub fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn pthread_setschedprio(native: crate::pthread_t, priority: c_int) -> c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; pub fn globfree(pglob: *mut crate::glob_t); pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; pub fn getdomainname(name: *mut c_char, len: size_t) -> c_int; pub fn setdomainname(name: *const c_char, len: size_t) -> c_int; pub fn sync(); pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut crate::sched_param, ) -> c_int; pub fn umount(target: *const c_char, flags: c_int) -> c_int; pub fn sched_get_priority_max(policy: c_int) -> c_int; pub fn settimeofday(tv: *const crate::timeval, tz: *const c_void) -> c_int; pub fn sched_rr_get_interval(pid: crate::pid_t, tp: *mut crate::timespec) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const crate::sched_param) -> c_int; pub fn mount( special_device: *const c_char, mount_directory: *const c_char, flags: c_int, mount_type: *const c_char, mount_data: *const c_void, mount_datalen: c_int, ) -> c_int; pub fn sched_getparam(pid: crate::pid_t, param: *mut crate::sched_param) -> c_int; pub fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_spin_init(lock: *mut crate::pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_barrierattr_init(__attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_destroy(__attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_getpshared( __attr: *const crate::pthread_barrierattr_t, __pshared: *mut c_int, ) -> c_int; pub fn pthread_barrierattr_setpshared( __attr: *mut crate::pthread_barrierattr_t, __pshared: c_int, ) -> c_int; pub fn pthread_barrier_init( __barrier: *mut crate::pthread_barrier_t, __attr: *const crate::pthread_barrierattr_t, __count: c_uint, ) -> c_int; pub fn pthread_barrier_destroy(__barrier: *mut crate::pthread_barrier_t) -> c_int; pub fn pthread_barrier_wait(__barrier: *mut crate::pthread_barrier_t) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn sethostname(name: *const c_char, len: size_t) -> c_int; pub fn sched_get_priority_min(policy: c_int) -> c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn getdtablesize() -> c_int; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn initgroups(user: *const c_char, group: crate::gid_t) -> c_int; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn pthread_cancel(thread: crate::pthread_t) -> c_int; pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn getgrouplist( user: *const c_char, group: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_getrobust( attr: *const pthread_mutexattr_t, robustness: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robustness: c_int) -> c_int; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn getitimer(which: c_int, curr_value: *mut crate::itimerval) -> c_int; pub fn setitimer( which: c_int, value: *const crate::itimerval, ovalue: *mut crate::itimerval, ) -> c_int; pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: crate::pid_t) -> c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut c_int, ) -> c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: c_int) -> c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut crate::sched_param, ) -> c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const crate::sched_param, ) -> c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int, ) -> c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn inotify_rm_watch(fd: c_int, wd: c_int) -> c_int; pub fn inotify_init() -> c_int; pub fn inotify_add_watch(fd: c_int, path: *const c_char, mask: u32) -> c_int; pub fn gettid() -> crate::pid_t; pub fn pthread_getcpuclockid(thread: crate::pthread_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn mallopt(param: c_int, value: i64) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn ctermid(s: *mut c_char) -> *mut c_char; pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int; pub fn mallinfo() -> crate::mallinfo; pub fn getpwent_r( pwd: *mut crate::passwd, buf: *mut c_char, __bufsize: c_int, __result: *mut *mut crate::passwd, ) -> c_int; pub fn pthread_getname_np(thread: crate::pthread_t, name: *mut c_char, len: c_int) -> c_int; pub fn pthread_setname_np(thread: crate::pthread_t, name: *const c_char) -> c_int; pub fn sysctl( _: *const c_int, _: c_uint, _: *mut c_void, _: *mut size_t, _: *const c_void, _: size_t, ) -> c_int; pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlp: *const crate::rlimit) -> c_int; pub fn lio_listio( __mode: c_int, __list: *const *mut aiocb, __nent: c_int, __sig: *mut sigevent, ) -> c_int; pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn( // The original .h file declares this as *const, but for consistency with other platforms, // changing this to *mut to make it easier to use. // Maybe in v0.3 all platforms should use this as a *const. info: *mut dl_phdr_info, size: size_t, data: *mut c_void, ) -> c_int, >, data: *mut c_void, ) -> c_int; pub fn memset_s(s: *mut c_void, smax: size_t, c: c_int, n: size_t) -> c_int; pub fn regcomp(__preg: *mut crate::regex_t, __pattern: *const c_char, __cflags: c_int) -> c_int; pub fn regexec( __preg: *const crate::regex_t, __str: *const c_char, __nmatch: size_t, __pmatch: *mut crate::regmatch_t, __eflags: c_int, ) -> c_int; pub fn regerror( __errcode: c_int, __preg: *const crate::regex_t, __errbuf: *mut c_char, __errbuf_size: size_t, ) -> size_t; pub fn regfree(__preg: *mut crate::regex_t); pub fn dirfd(__dirp: *mut crate::DIR) -> c_int; pub fn dircntl(dir: *mut crate::DIR, cmd: c_int, ...) -> c_int; pub fn aio_cancel(__fd: c_int, __aiocbp: *mut crate::aiocb) -> c_int; pub fn aio_error(__aiocbp: *const crate::aiocb) -> c_int; pub fn aio_fsync(__operation: c_int, __aiocbp: *mut crate::aiocb) -> c_int; pub fn aio_read(__aiocbp: *mut crate::aiocb) -> c_int; pub fn aio_return(__aiocpb: *mut crate::aiocb) -> ssize_t; pub fn aio_suspend( __list: *const *const crate::aiocb, __nent: c_int, __timeout: *const crate::timespec, ) -> c_int; pub fn aio_write(__aiocpb: *mut crate::aiocb) -> c_int; pub fn mq_close(__mqdes: crate::mqd_t) -> c_int; pub fn mq_getattr(__mqdes: crate::mqd_t, __mqstat: *mut crate::mq_attr) -> c_int; pub fn mq_notify(__mqdes: crate::mqd_t, __notification: *const crate::sigevent) -> c_int; pub fn mq_open(__name: *const c_char, __oflag: c_int, ...) -> crate::mqd_t; pub fn mq_receive( __mqdes: crate::mqd_t, __msg_ptr: *mut c_char, __msg_len: size_t, __msg_prio: *mut c_uint, ) -> ssize_t; pub fn mq_send( __mqdes: crate::mqd_t, __msg_ptr: *const c_char, __msg_len: size_t, __msg_prio: c_uint, ) -> c_int; pub fn mq_setattr( __mqdes: crate::mqd_t, __mqstat: *const mq_attr, __omqstat: *mut mq_attr, ) -> c_int; pub fn mq_timedreceive( __mqdes: crate::mqd_t, __msg_ptr: *mut c_char, __msg_len: size_t, __msg_prio: *mut c_uint, __abs_timeout: *const crate::timespec, ) -> ssize_t; pub fn mq_timedsend( __mqdes: crate::mqd_t, __msg_ptr: *const c_char, __msg_len: size_t, __msg_prio: c_uint, __abs_timeout: *const crate::timespec, ) -> c_int; pub fn mq_unlink(__name: *const c_char) -> c_int; pub fn __get_errno_ptr() -> *mut c_int; // System page, see https://www.qnx.com/developers/docs/7.1#com.qnx.doc.neutrino.building/topic/syspage/syspage_about.html pub static mut _syspage_ptr: *mut syspage_entry; // Function on the stack after a call to pthread_create(). This is used // as a sentinel to work around an infitnite loop in the unwinding code. pub fn __my_thread_exit(value_ptr: *mut *const c_void); } // Models the implementation in stdlib.h. Ctest will fail if trying to use the // default symbol from libc pub unsafe fn atexit(cb: extern "C" fn()) -> c_int { extern "C" { static __dso_handle: *mut c_void; pub fn __cxa_atexit(cb: extern "C" fn(), __arg: *mut c_void, __dso: *mut c_void) -> c_int; } __cxa_atexit(cb, 0 as *mut c_void, __dso_handle) } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { #[repr(C)] struct siginfo_si_addr { _pad: [u8; 32], si_addr: *mut c_void, } (*(self as *const siginfo_t as *const siginfo_si_addr)).si_addr } pub unsafe fn si_value(&self) -> crate::sigval { #[repr(C)] struct siginfo_si_value { _pad: [u8; 32], si_value: crate::sigval, } (*(self as *const siginfo_t as *const siginfo_si_value)).si_value } pub unsafe fn si_pid(&self) -> crate::pid_t { #[repr(C)] struct siginfo_si_pid { _pad: [u8; 16], si_pid: crate::pid_t, } (*(self as *const siginfo_t as *const siginfo_si_pid)).si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { #[repr(C)] struct siginfo_si_uid { _pad: [u8; 24], si_uid: crate::uid_t, } (*(self as *const siginfo_t as *const siginfo_si_uid)).si_uid } pub unsafe fn si_status(&self) -> c_int { #[repr(C)] struct siginfo_si_status { _pad: [u8; 28], si_status: c_int, } (*(self as *const siginfo_t as *const siginfo_si_status)).si_status } } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else { panic!("Unsupported arch"); } } mod neutrino; pub use self::neutrino::*; libc/src/unix/nto/neutrino.rs0000644000175000017500000012173415105742312016106 0ustar bdrungbdrunguse crate::prelude::*; pub type nto_job_t = crate::sync_t; s! { pub struct syspage_entry_info { pub entry_off: u16, pub entry_size: u16, } pub struct syspage_array_info { entry_off: u16, entry_size: u16, element_size: u16, } pub struct intrspin { pub value: c_uint, // volatile } pub struct iov_t { pub iov_base: *mut c_void, // union pub iov_len: size_t, } pub struct _itimer { pub nsec: u64, pub interval_nsec: u64, } pub struct _msg_info64 { pub nd: u32, pub srcnd: u32, pub pid: crate::pid_t, pub tid: i32, pub chid: i32, pub scoid: i32, pub coid: i32, pub priority: i16, pub flags: i16, pub msglen: isize, pub srcmsglen: isize, pub dstmsglen: isize, pub type_id: u32, reserved: u32, } pub struct _cred_info { pub ruid: crate::uid_t, pub euid: crate::uid_t, pub suid: crate::uid_t, pub rgid: crate::gid_t, pub egid: crate::gid_t, pub sgid: crate::gid_t, pub ngroups: u32, pub grouplist: [crate::gid_t; 8], } pub struct _client_info { pub nd: u32, pub pid: crate::pid_t, pub sid: crate::pid_t, pub flags: u32, pub cred: crate::_cred_info, } pub struct _client_able { pub ability: u32, pub flags: u32, pub range_lo: u64, pub range_hi: u64, } pub struct nto_channel_config { pub event: crate::sigevent, pub num_pulses: c_uint, pub rearm_threshold: c_uint, pub options: c_uint, reserved: [c_uint; 3], } // TODO: The following structures are defined in a header file which doesn't // appear as part of the default headers found in a standard installation // of Neutrino 7.1 SDP. Commented out for now. //pub struct _asyncmsg_put_header { // pub err: c_int, // pub iov: *mut crate::iov_t, // pub parts: c_int, // pub handle: c_uint, // pub cb: Option< // unsafe extern "C" fn( // err: c_int, // buf: *mut c_void, // handle: c_uint, // ) -> c_int>, // pub put_hdr_flags: c_uint, //} //pub struct _asyncmsg_connection_attr { // pub call_back: Option< // unsafe extern "C" fn( // err: c_int, // buff: *mut c_void, // handle: c_uint, // ) -> c_int>, // pub buffer_size: size_t, // pub max_num_buffer: c_uint, // pub trigger_num_msg: c_uint, // pub trigger_time: crate::_itimer, // reserve: c_uint, //} //pub struct _asyncmsg_connection_descriptor { // pub flags: c_uint, // pub sendq_size: c_uint, // pub sendq_head: c_uint, // pub sendq_tail: c_uint, // pub sendq_free: c_uint, // pub err: c_int, // pub ev: crate::sigevent, // pub num_curmsg: c_uint, // pub ttimer: crate::timer_t, // pub block_con: crate::pthread_cond_t, // pub mu: crate::pthread_mutex_t, // reserved: c_uint, // pub attr: crate::_asyncmsg_connection_attr, // pub reserves: [c_uint; 3], // pub sendq: [crate::_asyncmsg_put_header; 1], // flexarray //} pub struct __c_anonymous_struct_ev { pub event: crate::sigevent, pub coid: c_int, } pub struct _channel_connect_attr { // union pub ev: crate::__c_anonymous_struct_ev, } pub struct _sighandler_info { pub siginfo: crate::siginfo_t, pub handler: Option, pub context: *mut c_void, } pub struct __c_anonymous_struct_time { pub length: c_uint, pub scale: c_uint, } pub struct _idle_hook { pub hook_size: c_uint, pub cmd: c_uint, pub mode: c_uint, pub latency: c_uint, pub next_fire: u64, pub curr_time: u64, pub tod_adjust: u64, pub resp: c_uint, pub time: __c_anonymous_struct_time, pub trigger: crate::sigevent, pub intrs: *mut c_uint, pub block_stack_size: c_uint, } pub struct _clockadjust { pub tick_count: u32, pub tick_nsec_inc: i32, } pub struct qtime_entry { pub cycles_per_sec: u64, pub nsec_tod_adjust: u64, // volatile pub nsec: u64, // volatile pub nsec_inc: u32, pub boot_time: u32, pub adjust: _clockadjust, pub timer_rate: u32, pub timer_scale: i32, pub timer_load: u32, pub intr: i32, pub epoch: u32, pub flags: u32, pub rr_interval_mul: u32, pub timer_load_hi: u32, pub nsec_stable: u64, // volatile pub timer_load_max: u64, pub timer_prog_time: u32, spare: [u32; 7], } pub struct _sched_info { pub priority_min: c_int, pub priority_max: c_int, pub interval: u64, pub priority_priv: c_int, reserved: [c_int; 11], } pub struct _timer_info { pub itime: crate::_itimer, pub otime: crate::_itimer, pub flags: u32, pub tid: i32, pub notify: i32, pub clockid: crate::clockid_t, pub overruns: u32, pub event: crate::sigevent, // union } pub struct _clockperiod { pub nsec: u32, pub fract: i32, } } s_no_extra_traits! { #[repr(align(8))] pub struct syspage_entry { pub size: u16, pub total_size: u16, pub type_: u16, pub num_cpu: u16, pub system_private: syspage_entry_info, pub old_asinfo: syspage_entry_info, pub __mangle_name_to_cause_compilation_errs_meminfo: syspage_entry_info, pub hwinfo: syspage_entry_info, pub old_cpuinfo: syspage_entry_info, pub old_cacheattr: syspage_entry_info, pub qtime: syspage_entry_info, pub callout: syspage_entry_info, pub callin: syspage_entry_info, pub typed_strings: syspage_entry_info, pub strings: syspage_entry_info, pub old_intrinfo: syspage_entry_info, pub smp: syspage_entry_info, pub pminfo: syspage_entry_info, pub old_mdriver: syspage_entry_info, spare0: [u32; 1], __reserved: [u8; 160], // anonymous union with architecture dependent structs pub new_asinfo: syspage_array_info, pub new_cpuinfo: syspage_array_info, pub new_cacheattr: syspage_array_info, pub new_intrinfo: syspage_array_info, pub new_mdriver: syspage_array_info, } } pub const SYSMGR_PID: u32 = 1; pub const SYSMGR_CHID: u32 = 1; pub const SYSMGR_COID: u32 = _NTO_SIDE_CHANNEL; pub const SYSMGR_HANDLE: u32 = 0; pub const STATE_DEAD: c_int = 0x00; pub const STATE_RUNNING: c_int = 0x01; pub const STATE_READY: c_int = 0x02; pub const STATE_STOPPED: c_int = 0x03; pub const STATE_SEND: c_int = 0x04; pub const STATE_RECEIVE: c_int = 0x05; pub const STATE_REPLY: c_int = 0x06; pub const STATE_STACK: c_int = 0x07; pub const STATE_WAITTHREAD: c_int = 0x08; pub const STATE_WAITPAGE: c_int = 0x09; pub const STATE_SIGSUSPEND: c_int = 0x0a; pub const STATE_SIGWAITINFO: c_int = 0x0b; pub const STATE_NANOSLEEP: c_int = 0x0c; pub const STATE_MUTEX: c_int = 0x0d; pub const STATE_CONDVAR: c_int = 0x0e; pub const STATE_JOIN: c_int = 0x0f; pub const STATE_INTR: c_int = 0x10; pub const STATE_SEM: c_int = 0x11; pub const STATE_WAITCTX: c_int = 0x12; pub const STATE_NET_SEND: c_int = 0x13; pub const STATE_NET_REPLY: c_int = 0x14; pub const STATE_MAX: c_int = 0x18; pub const _NTO_TIMEOUT_RECEIVE: i32 = 1 << STATE_RECEIVE; pub const _NTO_TIMEOUT_SEND: i32 = 1 << STATE_SEND; pub const _NTO_TIMEOUT_REPLY: i32 = 1 << STATE_REPLY; pub const _NTO_TIMEOUT_SIGSUSPEND: i32 = 1 << STATE_SIGSUSPEND; pub const _NTO_TIMEOUT_SIGWAITINFO: i32 = 1 << STATE_SIGWAITINFO; pub const _NTO_TIMEOUT_NANOSLEEP: i32 = 1 << STATE_NANOSLEEP; pub const _NTO_TIMEOUT_MUTEX: i32 = 1 << STATE_MUTEX; pub const _NTO_TIMEOUT_CONDVAR: i32 = 1 << STATE_CONDVAR; pub const _NTO_TIMEOUT_JOIN: i32 = 1 << STATE_JOIN; pub const _NTO_TIMEOUT_INTR: i32 = 1 << STATE_INTR; pub const _NTO_TIMEOUT_SEM: i32 = 1 << STATE_SEM; pub const _NTO_MI_ENDIAN_BIG: u32 = 1; pub const _NTO_MI_ENDIAN_DIFF: u32 = 2; pub const _NTO_MI_UNBLOCK_REQ: u32 = 256; pub const _NTO_MI_NET_CRED_DIRTY: u32 = 512; pub const _NTO_MI_CONSTRAINED: u32 = 1024; pub const _NTO_MI_CHROOT: u32 = 2048; pub const _NTO_MI_BITS_64: u32 = 4096; pub const _NTO_MI_BITS_DIFF: u32 = 8192; pub const _NTO_MI_SANDBOX: u32 = 16384; pub const _NTO_CI_ENDIAN_BIG: u32 = 1; pub const _NTO_CI_BKGND_PGRP: u32 = 4; pub const _NTO_CI_ORPHAN_PGRP: u32 = 8; pub const _NTO_CI_STOPPED: u32 = 128; pub const _NTO_CI_UNABLE: u32 = 256; pub const _NTO_CI_TYPE_ID: u32 = 512; pub const _NTO_CI_CHROOT: u32 = 2048; pub const _NTO_CI_BITS_64: u32 = 4096; pub const _NTO_CI_SANDBOX: u32 = 16384; pub const _NTO_CI_LOADER: u32 = 32768; pub const _NTO_CI_FULL_GROUPS: u32 = 2147483648; pub const _NTO_TI_ACTIVE: u32 = 1; pub const _NTO_TI_ABSOLUTE: u32 = 2; pub const _NTO_TI_EXPIRED: u32 = 4; pub const _NTO_TI_TOD_BASED: u32 = 8; pub const _NTO_TI_TARGET_PROCESS: u32 = 16; pub const _NTO_TI_REPORT_TOLERANCE: u32 = 32; pub const _NTO_TI_PRECISE: u32 = 64; pub const _NTO_TI_TOLERANT: u32 = 128; pub const _NTO_TI_WAKEUP: u32 = 256; pub const _NTO_TI_PROCESS_TOLERANT: u32 = 512; pub const _NTO_TI_HIGH_RESOLUTION: u32 = 1024; pub const _PULSE_TYPE: u32 = 0; pub const _PULSE_SUBTYPE: u32 = 0; pub const _PULSE_CODE_UNBLOCK: i32 = -32; pub const _PULSE_CODE_DISCONNECT: i32 = -33; pub const _PULSE_CODE_THREADDEATH: i32 = -34; pub const _PULSE_CODE_COIDDEATH: i32 = -35; pub const _PULSE_CODE_NET_ACK: i32 = -36; pub const _PULSE_CODE_NET_UNBLOCK: i32 = -37; pub const _PULSE_CODE_NET_DETACH: i32 = -38; pub const _PULSE_CODE_RESTART: i32 = -39; pub const _PULSE_CODE_NORESTART: i32 = -40; pub const _PULSE_CODE_UNBLOCK_RESTART: i32 = -41; pub const _PULSE_CODE_UNBLOCK_TIMER: i32 = -42; pub const _PULSE_CODE_MINAVAIL: u32 = 0; pub const _PULSE_CODE_MAXAVAIL: u32 = 127; pub const _NTO_HARD_FLAGS_END: u32 = 1; pub const _NTO_PULSE_IF_UNIQUE: u32 = 4096; pub const _NTO_PULSE_REPLACE: u32 = 8192; pub const _NTO_PF_NOCLDSTOP: u32 = 1; pub const _NTO_PF_LOADING: u32 = 2; pub const _NTO_PF_TERMING: u32 = 4; pub const _NTO_PF_ZOMBIE: u32 = 8; pub const _NTO_PF_NOZOMBIE: u32 = 16; pub const _NTO_PF_FORKED: u32 = 32; pub const _NTO_PF_ORPHAN_PGRP: u32 = 64; pub const _NTO_PF_STOPPED: u32 = 128; pub const _NTO_PF_DEBUG_STOPPED: u32 = 256; pub const _NTO_PF_BKGND_PGRP: u32 = 512; pub const _NTO_PF_NOISYNC: u32 = 1024; pub const _NTO_PF_CONTINUED: u32 = 2048; pub const _NTO_PF_CHECK_INTR: u32 = 4096; pub const _NTO_PF_COREDUMP: u32 = 8192; pub const _NTO_PF_RING0: u32 = 32768; pub const _NTO_PF_SLEADER: u32 = 65536; pub const _NTO_PF_WAITINFO: u32 = 131072; pub const _NTO_PF_DESTROYALL: u32 = 524288; pub const _NTO_PF_NOCOREDUMP: u32 = 1048576; pub const _NTO_PF_WAITDONE: u32 = 4194304; pub const _NTO_PF_TERM_WAITING: u32 = 8388608; pub const _NTO_PF_ASLR: u32 = 16777216; pub const _NTO_PF_EXECED: u32 = 33554432; pub const _NTO_PF_APP_STOPPED: u32 = 67108864; pub const _NTO_PF_64BIT: u32 = 134217728; pub const _NTO_PF_NET: u32 = 268435456; pub const _NTO_PF_NOLAZYSTACK: u32 = 536870912; pub const _NTO_PF_NOEXEC_STACK: u32 = 1073741824; pub const _NTO_PF_LOADER_PERMS: u32 = 2147483648; pub const _NTO_TF_INTR_PENDING: u32 = 65536; pub const _NTO_TF_DETACHED: u32 = 131072; pub const _NTO_TF_SHR_MUTEX: u32 = 262144; pub const _NTO_TF_SHR_MUTEX_EUID: u32 = 524288; pub const _NTO_TF_THREADS_HOLD: u32 = 1048576; pub const _NTO_TF_UNBLOCK_REQ: u32 = 4194304; pub const _NTO_TF_ALIGN_FAULT: u32 = 16777216; pub const _NTO_TF_SSTEP: u32 = 33554432; pub const _NTO_TF_ALLOCED_STACK: u32 = 67108864; pub const _NTO_TF_NOMULTISIG: u32 = 134217728; pub const _NTO_TF_LOW_LATENCY: u32 = 268435456; pub const _NTO_TF_IOPRIV: u32 = 2147483648; pub const _NTO_TCTL_IO_PRIV: u32 = 1; pub const _NTO_TCTL_THREADS_HOLD: u32 = 2; pub const _NTO_TCTL_THREADS_CONT: u32 = 3; pub const _NTO_TCTL_RUNMASK: u32 = 4; pub const _NTO_TCTL_ALIGN_FAULT: u32 = 5; pub const _NTO_TCTL_RUNMASK_GET_AND_SET: u32 = 6; pub const _NTO_TCTL_PERFCOUNT: u32 = 7; pub const _NTO_TCTL_ONE_THREAD_HOLD: u32 = 8; pub const _NTO_TCTL_ONE_THREAD_CONT: u32 = 9; pub const _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT: u32 = 10; pub const _NTO_TCTL_NAME: u32 = 11; pub const _NTO_TCTL_RCM_GET_AND_SET: u32 = 12; pub const _NTO_TCTL_SHR_MUTEX: u32 = 13; pub const _NTO_TCTL_IO: u32 = 14; pub const _NTO_TCTL_NET_KIF_GET_AND_SET: u32 = 15; pub const _NTO_TCTL_LOW_LATENCY: u32 = 16; pub const _NTO_TCTL_ADD_EXIT_EVENT: u32 = 17; pub const _NTO_TCTL_DEL_EXIT_EVENT: u32 = 18; pub const _NTO_TCTL_IO_LEVEL: u32 = 19; pub const _NTO_TCTL_RESERVED: u32 = 2147483648; pub const _NTO_TCTL_IO_LEVEL_INHERIT: u32 = 1073741824; pub const _NTO_IO_LEVEL_NONE: u32 = 1; pub const _NTO_IO_LEVEL_1: u32 = 2; pub const _NTO_IO_LEVEL_2: u32 = 3; pub const _NTO_THREAD_NAME_MAX: u32 = 100; pub const _NTO_CHF_FIXED_PRIORITY: u32 = 1; pub const _NTO_CHF_UNBLOCK: u32 = 2; pub const _NTO_CHF_THREAD_DEATH: u32 = 4; pub const _NTO_CHF_DISCONNECT: u32 = 8; pub const _NTO_CHF_NET_MSG: u32 = 16; pub const _NTO_CHF_SENDER_LEN: u32 = 32; pub const _NTO_CHF_COID_DISCONNECT: u32 = 64; pub const _NTO_CHF_REPLY_LEN: u32 = 128; pub const _NTO_CHF_PULSE_POOL: u32 = 256; pub const _NTO_CHF_ASYNC_NONBLOCK: u32 = 512; pub const _NTO_CHF_ASYNC: u32 = 1024; pub const _NTO_CHF_GLOBAL: u32 = 2048; pub const _NTO_CHF_PRIVATE: u32 = 4096; pub const _NTO_CHF_MSG_PAUSING: u32 = 8192; pub const _NTO_CHF_INHERIT_RUNMASK: u32 = 16384; pub const _NTO_CHF_UNBLOCK_TIMER: u32 = 32768; pub const _NTO_CHO_CUSTOM_EVENT: u32 = 1; pub const _NTO_COF_CLOEXEC: u32 = 1; pub const _NTO_COF_DEAD: u32 = 2; pub const _NTO_COF_NOSHARE: u32 = 64; pub const _NTO_COF_NETCON: u32 = 128; pub const _NTO_COF_NONBLOCK: u32 = 256; pub const _NTO_COF_ASYNC: u32 = 512; pub const _NTO_COF_GLOBAL: u32 = 1024; pub const _NTO_COF_NOEVENT: u32 = 2048; pub const _NTO_COF_INSECURE: u32 = 4096; pub const _NTO_COF_REG_EVENTS: u32 = 8192; pub const _NTO_COF_UNREG_EVENTS: u32 = 16384; pub const _NTO_COF_MASK: u32 = 65535; pub const _NTO_SIDE_CHANNEL: u32 = 1073741824; pub const _NTO_CONNECTION_SCOID: u32 = 65536; pub const _NTO_GLOBAL_CHANNEL: u32 = 1073741824; pub const _NTO_TIMEOUT_MASK: u32 = (1 << STATE_MAX) - 1; pub const _NTO_TIMEOUT_ACTIVE: u32 = 1 << STATE_MAX; pub const _NTO_TIMEOUT_IMMEDIATE: u32 = 1 << (STATE_MAX + 1); pub const _NTO_IC_LATENCY: u32 = 0; pub const _NTO_INTR_FLAGS_END: u32 = 1; pub const _NTO_INTR_FLAGS_NO_UNMASK: u32 = 2; pub const _NTO_INTR_FLAGS_PROCESS: u32 = 4; pub const _NTO_INTR_FLAGS_TRK_MSK: u32 = 8; pub const _NTO_INTR_FLAGS_ARRAY: u32 = 16; pub const _NTO_INTR_FLAGS_EXCLUSIVE: u32 = 32; pub const _NTO_INTR_FLAGS_FPU: u32 = 64; pub const _NTO_INTR_CLASS_EXTERNAL: u32 = 0; pub const _NTO_INTR_CLASS_SYNTHETIC: u32 = 2147418112; pub const _NTO_INTR_SPARE: u32 = 2147483647; pub const _NTO_HOOK_IDLE: u32 = 2147418113; pub const _NTO_HOOK_OVERDRIVE: u32 = 2147418114; pub const _NTO_HOOK_LAST: u32 = 2147418114; pub const _NTO_HOOK_IDLE2_FLAG: u32 = 32768; pub const _NTO_IH_CMD_SLEEP_SETUP: u32 = 1; pub const _NTO_IH_CMD_SLEEP_BLOCK: u32 = 2; pub const _NTO_IH_CMD_SLEEP_WAKEUP: u32 = 4; pub const _NTO_IH_CMD_SLEEP_ONLINE: u32 = 8; pub const _NTO_IH_RESP_NEEDS_BLOCK: u32 = 1; pub const _NTO_IH_RESP_NEEDS_WAKEUP: u32 = 2; pub const _NTO_IH_RESP_NEEDS_ONLINE: u32 = 4; pub const _NTO_IH_RESP_SYNC_TIME: u32 = 16; pub const _NTO_IH_RESP_SYNC_TLB: u32 = 32; pub const _NTO_IH_RESP_SUGGEST_OFFLINE: u32 = 256; pub const _NTO_IH_RESP_SLEEP_MODE_REACHED: u32 = 512; pub const _NTO_IH_RESP_DELIVER_INTRS: u32 = 1024; pub const _NTO_READIOV_SEND: u32 = 0; pub const _NTO_READIOV_REPLY: u32 = 1; pub const _NTO_KEYDATA_VTID: u32 = 2147483648; pub const _NTO_KEYDATA_PATHSIGN: u32 = 32768; pub const _NTO_KEYDATA_OP_MASK: u32 = 255; pub const _NTO_KEYDATA_VERIFY: u32 = 0; pub const _NTO_KEYDATA_CALCULATE: u32 = 1; pub const _NTO_KEYDATA_CALCULATE_REUSE: u32 = 2; pub const _NTO_KEYDATA_PATHSIGN_VERIFY: u32 = 32768; pub const _NTO_KEYDATA_PATHSIGN_CALCULATE: u32 = 32769; pub const _NTO_KEYDATA_PATHSIGN_CALCULATE_REUSE: u32 = 32770; pub const _NTO_SCTL_SETPRIOCEILING: u32 = 1; pub const _NTO_SCTL_GETPRIOCEILING: u32 = 2; pub const _NTO_SCTL_SETEVENT: u32 = 3; pub const _NTO_SCTL_MUTEX_WAKEUP: u32 = 4; pub const _NTO_SCTL_MUTEX_CONSISTENT: u32 = 5; pub const _NTO_SCTL_SEM_VALUE: u32 = 6; pub const _NTO_CLIENTINFO_GETGROUPS: u32 = 1; pub const _NTO_CLIENTINFO_GETTYPEID: u32 = 2; extern "C" { pub fn ChannelCreate(__flags: c_uint) -> c_int; pub fn ChannelCreate_r(__flags: c_uint) -> c_int; pub fn ChannelCreatePulsePool(__flags: c_uint, __config: *const nto_channel_config) -> c_int; pub fn ChannelCreateExt( __flags: c_uint, __mode: crate::mode_t, __bufsize: usize, __maxnumbuf: c_uint, __ev: *const crate::sigevent, __cred: *mut _cred_info, ) -> c_int; pub fn ChannelDestroy(__chid: c_int) -> c_int; pub fn ChannelDestroy_r(__chid: c_int) -> c_int; pub fn ConnectAttach( __nd: u32, __pid: crate::pid_t, __chid: c_int, __index: c_uint, __flags: c_int, ) -> c_int; pub fn ConnectAttach_r( __nd: u32, __pid: crate::pid_t, __chid: c_int, __index: c_uint, __flags: c_int, ) -> c_int; // TODO: The following function uses a structure defined in a header file // which doesn't appear as part of the default headers found in a // standard installation of Neutrino 7.1 SDP. Commented out for now. //pub fn ConnectAttachExt( // __nd: u32, // __pid: crate::pid_t, // __chid: c_int, // __index: c_uint, // __flags: c_int, // __cd: *mut _asyncmsg_connection_descriptor, //) -> c_int; pub fn ConnectDetach(__coid: c_int) -> c_int; pub fn ConnectDetach_r(__coid: c_int) -> c_int; pub fn ConnectServerInfo(__pid: crate::pid_t, __coid: c_int, __info: *mut _msg_info64) -> c_int; pub fn ConnectServerInfo_r( __pid: crate::pid_t, __coid: c_int, __info: *mut _msg_info64, ) -> c_int; pub fn ConnectClientInfoExtraArgs( __scoid: c_int, __info_pp: *mut _client_info, __ngroups: c_int, __abilities: *mut _client_able, __nable: c_int, __type_id: *mut c_uint, ) -> c_int; pub fn ConnectClientInfoExtraArgs_r( __scoid: c_int, __info_pp: *mut _client_info, __ngroups: c_int, __abilities: *mut _client_able, __nable: c_int, __type_id: *mut c_uint, ) -> c_int; pub fn ConnectClientInfo(__scoid: c_int, __info: *mut _client_info, __ngroups: c_int) -> c_int; pub fn ConnectClientInfo_r( __scoid: c_int, __info: *mut _client_info, __ngroups: c_int, ) -> c_int; pub fn ConnectClientInfoExt( __scoid: c_int, __info_pp: *mut *mut _client_info, flags: c_int, ) -> c_int; pub fn ClientInfoExtFree(__info_pp: *mut *mut _client_info) -> c_int; pub fn ConnectClientInfoAble( __scoid: c_int, __info_pp: *mut *mut _client_info, flags: c_int, abilities: *mut _client_able, nable: c_int, ) -> c_int; pub fn ConnectFlags( __pid: crate::pid_t, __coid: c_int, __mask: c_uint, __bits: c_uint, ) -> c_int; pub fn ConnectFlags_r( __pid: crate::pid_t, __coid: c_int, __mask: c_uint, __bits: c_uint, ) -> c_int; pub fn ChannelConnectAttr( __id: c_uint, __old_attr: *mut _channel_connect_attr, __new_attr: *mut _channel_connect_attr, __flags: c_uint, ) -> c_int; pub fn MsgSend( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __rmsg: *mut c_void, __rbytes: usize, ) -> c_long; pub fn MsgSend_r( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __rmsg: *mut c_void, __rbytes: usize, ) -> c_long; pub fn MsgSendnc( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __rmsg: *mut c_void, __rbytes: usize, ) -> c_long; pub fn MsgSendnc_r( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __rmsg: *mut c_void, __rbytes: usize, ) -> c_long; pub fn MsgSendsv( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __riov: *const crate::iovec, __rparts: usize, ) -> c_long; pub fn MsgSendsv_r( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __riov: *const crate::iovec, __rparts: usize, ) -> c_long; pub fn MsgSendsvnc( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __riov: *const crate::iovec, __rparts: usize, ) -> c_long; pub fn MsgSendsvnc_r( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __riov: *const crate::iovec, __rparts: usize, ) -> c_long; pub fn MsgSendvs( __coid: c_int, __siov: *const crate::iovec, __sparts: usize, __rmsg: *mut c_void, __rbytes: usize, ) -> c_long; pub fn MsgSendvs_r( __coid: c_int, __siov: *const crate::iovec, __sparts: usize, __rmsg: *mut c_void, __rbytes: usize, ) -> c_long; pub fn MsgSendvsnc( __coid: c_int, __siov: *const crate::iovec, __sparts: usize, __rmsg: *mut c_void, __rbytes: usize, ) -> c_long; pub fn MsgSendvsnc_r( __coid: c_int, __siov: *const crate::iovec, __sparts: usize, __rmsg: *mut c_void, __rbytes: usize, ) -> c_long; pub fn MsgSendv( __coid: c_int, __siov: *const crate::iovec, __sparts: usize, __riov: *const crate::iovec, __rparts: usize, ) -> c_long; pub fn MsgSendv_r( __coid: c_int, __siov: *const crate::iovec, __sparts: usize, __riov: *const crate::iovec, __rparts: usize, ) -> c_long; pub fn MsgSendvnc( __coid: c_int, __siov: *const crate::iovec, __sparts: usize, __riov: *const crate::iovec, __rparts: usize, ) -> c_long; pub fn MsgSendvnc_r( __coid: c_int, __siov: *const crate::iovec, __sparts: usize, __riov: *const crate::iovec, __rparts: usize, ) -> c_long; pub fn MsgReceive( __chid: c_int, __msg: *mut c_void, __bytes: usize, __info: *mut _msg_info64, ) -> c_int; pub fn MsgReceive_r( __chid: c_int, __msg: *mut c_void, __bytes: usize, __info: *mut _msg_info64, ) -> c_int; pub fn MsgReceivev( __chid: c_int, __iov: *const crate::iovec, __parts: usize, __info: *mut _msg_info64, ) -> c_int; pub fn MsgReceivev_r( __chid: c_int, __iov: *const crate::iovec, __parts: usize, __info: *mut _msg_info64, ) -> c_int; pub fn MsgReceivePulse( __chid: c_int, __pulse: *mut c_void, __bytes: usize, __info: *mut _msg_info64, ) -> c_int; pub fn MsgReceivePulse_r( __chid: c_int, __pulse: *mut c_void, __bytes: usize, __info: *mut _msg_info64, ) -> c_int; pub fn MsgReceivePulsev( __chid: c_int, __iov: *const crate::iovec, __parts: usize, __info: *mut _msg_info64, ) -> c_int; pub fn MsgReceivePulsev_r( __chid: c_int, __iov: *const crate::iovec, __parts: usize, __info: *mut _msg_info64, ) -> c_int; pub fn MsgReply( __rcvid: c_int, __status: c_long, __msg: *const c_void, __bytes: usize, ) -> c_int; pub fn MsgReply_r( __rcvid: c_int, __status: c_long, __msg: *const c_void, __bytes: usize, ) -> c_int; pub fn MsgReplyv( __rcvid: c_int, __status: c_long, __iov: *const crate::iovec, __parts: usize, ) -> c_int; pub fn MsgReplyv_r( __rcvid: c_int, __status: c_long, __iov: *const crate::iovec, __parts: usize, ) -> c_int; pub fn MsgReadiov( __rcvid: c_int, __iov: *const crate::iovec, __parts: usize, __offset: usize, __flags: c_int, ) -> isize; pub fn MsgReadiov_r( __rcvid: c_int, __iov: *const crate::iovec, __parts: usize, __offset: usize, __flags: c_int, ) -> isize; pub fn MsgRead(__rcvid: c_int, __msg: *mut c_void, __bytes: usize, __offset: usize) -> isize; pub fn MsgRead_r(__rcvid: c_int, __msg: *mut c_void, __bytes: usize, __offset: usize) -> isize; pub fn MsgReadv( __rcvid: c_int, __iov: *const crate::iovec, __parts: usize, __offset: usize, ) -> isize; pub fn MsgReadv_r( __rcvid: c_int, __iov: *const crate::iovec, __parts: usize, __offset: usize, ) -> isize; pub fn MsgWrite(__rcvid: c_int, __msg: *const c_void, __bytes: usize, __offset: usize) -> isize; pub fn MsgWrite_r( __rcvid: c_int, __msg: *const c_void, __bytes: usize, __offset: usize, ) -> isize; pub fn MsgWritev( __rcvid: c_int, __iov: *const crate::iovec, __parts: usize, __offset: usize, ) -> isize; pub fn MsgWritev_r( __rcvid: c_int, __iov: *const crate::iovec, __parts: usize, __offset: usize, ) -> isize; pub fn MsgSendPulse(__coid: c_int, __priority: c_int, __code: c_int, __value: c_int) -> c_int; pub fn MsgSendPulse_r(__coid: c_int, __priority: c_int, __code: c_int, __value: c_int) -> c_int; pub fn MsgSendPulsePtr( __coid: c_int, __priority: c_int, __code: c_int, __value: *mut c_void, ) -> c_int; pub fn MsgSendPulsePtr_r( __coid: c_int, __priority: c_int, __code: c_int, __value: *mut c_void, ) -> c_int; pub fn MsgDeliverEvent(__rcvid: c_int, __event: *const crate::sigevent) -> c_int; pub fn MsgDeliverEvent_r(__rcvid: c_int, __event: *const crate::sigevent) -> c_int; pub fn MsgVerifyEvent(__rcvid: c_int, __event: *const crate::sigevent) -> c_int; pub fn MsgVerifyEvent_r(__rcvid: c_int, __event: *const crate::sigevent) -> c_int; pub fn MsgRegisterEvent(__event: *mut crate::sigevent, __coid: c_int) -> c_int; pub fn MsgRegisterEvent_r(__event: *mut crate::sigevent, __coid: c_int) -> c_int; pub fn MsgUnregisterEvent(__event: *const crate::sigevent) -> c_int; pub fn MsgUnregisterEvent_r(__event: *const crate::sigevent) -> c_int; pub fn MsgInfo(__rcvid: c_int, __info: *mut _msg_info64) -> c_int; pub fn MsgInfo_r(__rcvid: c_int, __info: *mut _msg_info64) -> c_int; pub fn MsgKeyData( __rcvid: c_int, __oper: c_int, __key: u32, __newkey: *mut u32, __iov: *const crate::iovec, __parts: c_int, ) -> c_int; pub fn MsgKeyData_r( __rcvid: c_int, __oper: c_int, __key: u32, __newkey: *mut u32, __iov: *const crate::iovec, __parts: c_int, ) -> c_int; pub fn MsgError(__rcvid: c_int, __err: c_int) -> c_int; pub fn MsgError_r(__rcvid: c_int, __err: c_int) -> c_int; pub fn MsgCurrent(__rcvid: c_int) -> c_int; pub fn MsgCurrent_r(__rcvid: c_int) -> c_int; pub fn MsgSendAsyncGbl( __coid: c_int, __smsg: *const c_void, __sbytes: usize, __msg_prio: c_uint, ) -> c_int; pub fn MsgSendAsync(__coid: c_int) -> c_int; pub fn MsgReceiveAsyncGbl( __chid: c_int, __rmsg: *mut c_void, __rbytes: usize, __info: *mut _msg_info64, __coid: c_int, ) -> c_int; pub fn MsgReceiveAsync(__chid: c_int, __iov: *const crate::iovec, __parts: c_uint) -> c_int; pub fn MsgPause(__rcvid: c_int, __cookie: c_uint) -> c_int; pub fn MsgPause_r(__rcvid: c_int, __cookie: c_uint) -> c_int; pub fn SignalKill( __nd: u32, __pid: crate::pid_t, __tid: c_int, __signo: c_int, __code: c_int, __value: c_int, ) -> c_int; pub fn SignalKill_r( __nd: u32, __pid: crate::pid_t, __tid: c_int, __signo: c_int, __code: c_int, __value: c_int, ) -> c_int; pub fn SignalKillSigval( __nd: u32, __pid: crate::pid_t, __tid: c_int, __signo: c_int, __code: c_int, __value: *const crate::sigval, ) -> c_int; pub fn SignalKillSigval_r( __nd: u32, __pid: crate::pid_t, __tid: c_int, __signo: c_int, __code: c_int, __value: *const crate::sigval, ) -> c_int; pub fn SignalReturn(__info: *mut _sighandler_info) -> c_int; pub fn SignalFault(__sigcode: c_uint, __regs: *mut c_void, __refaddr: usize) -> c_int; pub fn SignalAction( __pid: crate::pid_t, __sigstub: unsafe extern "C" fn(), __signo: c_int, __act: *const crate::sigaction, __oact: *mut crate::sigaction, ) -> c_int; pub fn SignalAction_r( __pid: crate::pid_t, __sigstub: unsafe extern "C" fn(), __signo: c_int, __act: *const crate::sigaction, __oact: *mut crate::sigaction, ) -> c_int; pub fn SignalProcmask( __pid: crate::pid_t, __tid: c_int, __how: c_int, __set: *const crate::sigset_t, __oldset: *mut crate::sigset_t, ) -> c_int; pub fn SignalProcmask_r( __pid: crate::pid_t, __tid: c_int, __how: c_int, __set: *const crate::sigset_t, __oldset: *mut crate::sigset_t, ) -> c_int; pub fn SignalSuspend(__set: *const crate::sigset_t) -> c_int; pub fn SignalSuspend_r(__set: *const crate::sigset_t) -> c_int; pub fn SignalWaitinfo(__set: *const crate::sigset_t, __info: *mut crate::siginfo_t) -> c_int; pub fn SignalWaitinfo_r(__set: *const crate::sigset_t, __info: *mut crate::siginfo_t) -> c_int; pub fn SignalWaitinfoMask( __set: *const crate::sigset_t, __info: *mut crate::siginfo_t, __mask: *const crate::sigset_t, ) -> c_int; pub fn SignalWaitinfoMask_r( __set: *const crate::sigset_t, __info: *mut crate::siginfo_t, __mask: *const crate::sigset_t, ) -> c_int; pub fn ThreadCreate( __pid: crate::pid_t, __func: unsafe extern "C" fn(__arg: *mut c_void) -> *mut c_void, __arg: *mut c_void, __attr: *const crate::_thread_attr, ) -> c_int; pub fn ThreadCreate_r( __pid: crate::pid_t, __func: unsafe extern "C" fn(__arg: *mut c_void) -> *mut c_void, __arg: *mut c_void, __attr: *const crate::_thread_attr, ) -> c_int; pub fn ThreadDestroy(__tid: c_int, __priority: c_int, __status: *mut c_void) -> c_int; pub fn ThreadDestroy_r(__tid: c_int, __priority: c_int, __status: *mut c_void) -> c_int; pub fn ThreadDetach(__tid: c_int) -> c_int; pub fn ThreadDetach_r(__tid: c_int) -> c_int; pub fn ThreadJoin(__tid: c_int, __status: *mut *mut c_void) -> c_int; pub fn ThreadJoin_r(__tid: c_int, __status: *mut *mut c_void) -> c_int; pub fn ThreadCancel(__tid: c_int, __canstub: unsafe extern "C" fn()) -> c_int; pub fn ThreadCancel_r(__tid: c_int, __canstub: unsafe extern "C" fn()) -> c_int; pub fn ThreadCtl(__cmd: c_int, __data: *mut c_void) -> c_int; pub fn ThreadCtl_r(__cmd: c_int, __data: *mut c_void) -> c_int; pub fn ThreadCtlExt( __pid: crate::pid_t, __tid: c_int, __cmd: c_int, __data: *mut c_void, ) -> c_int; pub fn ThreadCtlExt_r( __pid: crate::pid_t, __tid: c_int, __cmd: c_int, __data: *mut c_void, ) -> c_int; pub fn InterruptHookTrace( __handler: Option *const crate::sigevent>, __flags: c_uint, ) -> c_int; pub fn InterruptHookIdle( __handler: Option, __flags: c_uint, ) -> c_int; pub fn InterruptHookIdle2( __handler: Option< unsafe extern "C" fn(arg1: c_uint, arg2: *mut syspage_entry, arg3: *mut _idle_hook), >, __flags: c_uint, ) -> c_int; pub fn InterruptHookOverdriveEvent(__event: *const crate::sigevent, __flags: c_uint) -> c_int; pub fn InterruptAttachEvent( __intr: c_int, __event: *const crate::sigevent, __flags: c_uint, ) -> c_int; pub fn InterruptAttachEvent_r( __intr: c_int, __event: *const crate::sigevent, __flags: c_uint, ) -> c_int; pub fn InterruptAttach( __intr: c_int, __handler: Option< unsafe extern "C" fn(__area: *mut c_void, __id: c_int) -> *const crate::sigevent, >, __area: *const c_void, __size: c_int, __flags: c_uint, ) -> c_int; pub fn InterruptAttach_r( __intr: c_int, __handler: Option< unsafe extern "C" fn(__area: *mut c_void, __id: c_int) -> *const crate::sigevent, >, __area: *const c_void, __size: c_int, __flags: c_uint, ) -> c_int; pub fn InterruptAttachArray( __intr: c_int, __handler: Option< unsafe extern "C" fn(__area: *mut c_void, __id: c_int) -> *const *const crate::sigevent, >, __area: *const c_void, __size: c_int, __flags: c_uint, ) -> c_int; pub fn InterruptAttachArray_r( __intr: c_int, __handler: Option< unsafe extern "C" fn(__area: *mut c_void, __id: c_int) -> *const *const crate::sigevent, >, __area: *const c_void, __size: c_int, __flags: c_uint, ) -> c_int; pub fn InterruptDetach(__id: c_int) -> c_int; pub fn InterruptDetach_r(__id: c_int) -> c_int; pub fn InterruptWait(__flags: c_int, __timeout: *const u64) -> c_int; pub fn InterruptWait_r(__flags: c_int, __timeout: *const u64) -> c_int; pub fn InterruptCharacteristic( __type: c_int, __id: c_int, __new: *mut c_uint, __old: *mut c_uint, ) -> c_int; pub fn InterruptCharacteristic_r( __type: c_int, __id: c_int, __new: *mut c_uint, __old: *mut c_uint, ) -> c_int; pub fn SchedGet(__pid: crate::pid_t, __tid: c_int, __param: *mut crate::sched_param) -> c_int; pub fn SchedGet_r(__pid: crate::pid_t, __tid: c_int, __param: *mut crate::sched_param) -> c_int; pub fn SchedGetCpuNum() -> c_uint; pub fn SchedSet( __pid: crate::pid_t, __tid: c_int, __algorithm: c_int, __param: *const crate::sched_param, ) -> c_int; pub fn SchedSet_r( __pid: crate::pid_t, __tid: c_int, __algorithm: c_int, __param: *const crate::sched_param, ) -> c_int; pub fn SchedInfo( __pid: crate::pid_t, __algorithm: c_int, __info: *mut crate::_sched_info, ) -> c_int; pub fn SchedInfo_r( __pid: crate::pid_t, __algorithm: c_int, __info: *mut crate::_sched_info, ) -> c_int; pub fn SchedYield() -> c_int; pub fn SchedYield_r() -> c_int; pub fn SchedCtl(__cmd: c_int, __data: *mut c_void, __length: usize) -> c_int; pub fn SchedCtl_r(__cmd: c_int, __data: *mut c_void, __length: usize) -> c_int; pub fn SchedJobCreate(__job: *mut nto_job_t) -> c_int; pub fn SchedJobCreate_r(__job: *mut nto_job_t) -> c_int; pub fn SchedJobDestroy(__job: *mut nto_job_t) -> c_int; pub fn SchedJobDestroy_r(__job: *mut nto_job_t) -> c_int; pub fn SchedWaypoint( __job: *mut nto_job_t, __new: *const i64, __max: *const i64, __old: *mut i64, ) -> c_int; pub fn SchedWaypoint_r( __job: *mut nto_job_t, __new: *const i64, __max: *const i64, __old: *mut i64, ) -> c_int; pub fn TimerCreate(__id: crate::clockid_t, __notify: *const crate::sigevent) -> c_int; pub fn TimerCreate_r(__id: crate::clockid_t, __notify: *const crate::sigevent) -> c_int; pub fn TimerDestroy(__id: crate::timer_t) -> c_int; pub fn TimerDestroy_r(__id: crate::timer_t) -> c_int; pub fn TimerSettime( __id: crate::timer_t, __flags: c_int, __itime: *const crate::_itimer, __oitime: *mut crate::_itimer, ) -> c_int; pub fn TimerSettime_r( __id: crate::timer_t, __flags: c_int, __itime: *const crate::_itimer, __oitime: *mut crate::_itimer, ) -> c_int; pub fn TimerInfo( __pid: crate::pid_t, __id: crate::timer_t, __flags: c_int, __info: *mut crate::_timer_info, ) -> c_int; pub fn TimerInfo_r( __pid: crate::pid_t, __id: crate::timer_t, __flags: c_int, __info: *mut crate::_timer_info, ) -> c_int; pub fn TimerAlarm( __id: crate::clockid_t, __itime: *const crate::_itimer, __otime: *mut crate::_itimer, ) -> c_int; pub fn TimerAlarm_r( __id: crate::clockid_t, __itime: *const crate::_itimer, __otime: *mut crate::_itimer, ) -> c_int; pub fn TimerTimeout( __id: crate::clockid_t, __flags: c_int, __notify: *const crate::sigevent, __ntime: *const u64, __otime: *mut u64, ) -> c_int; pub fn TimerTimeout_r( __id: crate::clockid_t, __flags: c_int, __notify: *const crate::sigevent, __ntime: *const u64, __otime: *mut u64, ) -> c_int; pub fn SyncTypeCreate( __type: c_uint, __sync: *mut crate::sync_t, __attr: *const crate::_sync_attr, ) -> c_int; pub fn SyncTypeCreate_r( __type: c_uint, __sync: *mut crate::sync_t, __attr: *const crate::_sync_attr, ) -> c_int; pub fn SyncDestroy(__sync: *mut crate::sync_t) -> c_int; pub fn SyncDestroy_r(__sync: *mut crate::sync_t) -> c_int; pub fn SyncCtl(__cmd: c_int, __sync: *mut crate::sync_t, __data: *mut c_void) -> c_int; pub fn SyncCtl_r(__cmd: c_int, __sync: *mut crate::sync_t, __data: *mut c_void) -> c_int; pub fn SyncMutexEvent(__sync: *mut crate::sync_t, event: *const crate::sigevent) -> c_int; pub fn SyncMutexEvent_r(__sync: *mut crate::sync_t, event: *const crate::sigevent) -> c_int; pub fn SyncMutexLock(__sync: *mut crate::sync_t) -> c_int; pub fn SyncMutexLock_r(__sync: *mut crate::sync_t) -> c_int; pub fn SyncMutexUnlock(__sync: *mut crate::sync_t) -> c_int; pub fn SyncMutexUnlock_r(__sync: *mut crate::sync_t) -> c_int; pub fn SyncMutexRevive(__sync: *mut crate::sync_t) -> c_int; pub fn SyncMutexRevive_r(__sync: *mut crate::sync_t) -> c_int; pub fn SyncCondvarWait(__sync: *mut crate::sync_t, __mutex: *mut crate::sync_t) -> c_int; pub fn SyncCondvarWait_r(__sync: *mut crate::sync_t, __mutex: *mut crate::sync_t) -> c_int; pub fn SyncCondvarSignal(__sync: *mut crate::sync_t, __all: c_int) -> c_int; pub fn SyncCondvarSignal_r(__sync: *mut crate::sync_t, __all: c_int) -> c_int; pub fn SyncSemPost(__sync: *mut crate::sync_t) -> c_int; pub fn SyncSemPost_r(__sync: *mut crate::sync_t) -> c_int; pub fn SyncSemWait(__sync: *mut crate::sync_t, __tryto: c_int) -> c_int; pub fn SyncSemWait_r(__sync: *mut crate::sync_t, __tryto: c_int) -> c_int; pub fn ClockTime(__id: crate::clockid_t, _new: *const u64, __old: *mut u64) -> c_int; pub fn ClockTime_r(__id: crate::clockid_t, _new: *const u64, __old: *mut u64) -> c_int; pub fn ClockAdjust( __id: crate::clockid_t, _new: *const crate::_clockadjust, __old: *mut crate::_clockadjust, ) -> c_int; pub fn ClockAdjust_r( __id: crate::clockid_t, _new: *const crate::_clockadjust, __old: *mut crate::_clockadjust, ) -> c_int; pub fn ClockPeriod( __id: crate::clockid_t, _new: *const crate::_clockperiod, __old: *mut crate::_clockperiod, __reserved: c_int, ) -> c_int; pub fn ClockPeriod_r( __id: crate::clockid_t, _new: *const crate::_clockperiod, __old: *mut crate::_clockperiod, __reserved: c_int, ) -> c_int; pub fn ClockId(__pid: crate::pid_t, __tid: c_int) -> c_int; pub fn ClockId_r(__pid: crate::pid_t, __tid: c_int) -> c_int; // //TODO: The following commented out functions are implemented in assembly. // We can implmement them either via a C stub or rust's inline assembly. // //pub fn InterruptEnable(); //pub fn InterruptDisable(); pub fn InterruptMask(__intr: c_int, __id: c_int) -> c_int; pub fn InterruptUnmask(__intr: c_int, __id: c_int) -> c_int; //pub fn InterruptLock(__spin: *mut intrspin); //pub fn InterruptUnlock(__spin: *mut intrspin); //pub fn InterruptStatus() -> c_uint; } libc/src/unix/nto/x86_64.rs0000644000175000017500000000524715105742312015201 0ustar bdrungbdrunguse crate::prelude::*; pub type wchar_t = u32; pub type time_t = i64; s! { #[repr(align(8))] pub struct x86_64_cpu_registers { pub rdi: u64, pub rsi: u64, pub rdx: u64, pub r10: u64, pub r8: u64, pub r9: u64, pub rax: u64, pub rbx: u64, pub rbp: u64, pub rcx: u64, pub r11: u64, pub r12: u64, pub r13: u64, pub r14: u64, pub r15: u64, pub rip: u64, pub cs: u32, rsvd1: u32, pub rflags: u64, pub rsp: u64, pub ss: u32, rsvd2: u32, } #[repr(align(8))] pub struct mcontext_t { pub cpu: x86_64_cpu_registers, pub fpu: x86_64_fpu_registers, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct fsave_area_64 { pub fpu_control_word: u32, pub fpu_status_word: u32, pub fpu_tag_word: u32, pub fpu_ip: u32, pub fpu_cs: u32, pub fpu_op: u32, pub fpu_ds: u32, pub st_regs: [u8; 80], } pub struct fxsave_area_64 { pub fpu_control_word: u16, pub fpu_status_word: u16, pub fpu_tag_word: u16, pub fpu_operand: u16, pub fpu_rip: u64, pub fpu_rdp: u64, pub mxcsr: u32, pub mxcsr_mask: u32, pub st_regs: [u8; 128], pub xmm_regs: [u8; 128], reserved2: [u8; 224], } pub struct fpu_extention_savearea_64 { pub other: [u8; 512], pub xstate_bv: u64, pub xstate_undef: [u64; 7], pub xstate_info: [u8; 224], } } s_no_extra_traits! { pub union x86_64_fpu_registers { pub fsave_area: fsave_area_64, pub fxsave_area: fxsave_area_64, pub xsave_area: fpu_extention_savearea_64, pub data: [u8; 1024], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl Eq for x86_64_fpu_registers {} impl PartialEq for x86_64_fpu_registers { fn eq(&self, other: &x86_64_fpu_registers) -> bool { unsafe { self.fsave_area == other.fsave_area || self.fxsave_area == other.fxsave_area || self.xsave_area == other.xsave_area } } } impl hash::Hash for x86_64_fpu_registers { fn hash(&self, state: &mut H) { unsafe { self.fsave_area.hash(state); self.fxsave_area.hash(state); self.xsave_area.hash(state); } } } } } libc/src/unix/nto/aarch64.rs0000644000175000017500000000126615105742312015470 0ustar bdrungbdrunguse crate::prelude::*; pub type wchar_t = u32; pub type time_t = i64; s! { pub struct aarch64_qreg_t { pub qlo: u64, pub qhi: u64, } pub struct aarch64_fpu_registers { pub reg: [crate::aarch64_qreg_t; 32], pub fpsr: u32, pub fpcr: u32, } pub struct aarch64_cpu_registers { pub gpr: [u64; 32], pub elr: u64, pub pstate: u64, } #[repr(align(16))] pub struct mcontext_t { pub cpu: crate::aarch64_cpu_registers, pub fpu: crate::aarch64_fpu_registers, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } } libc/src/unix/haiku/0000775000175000017500000000000015105742312014170 5ustar bdrungbdrunglibc/src/unix/haiku/mod.rs0000644000175000017500000021446415105742312015326 0ustar bdrungbdrunguse crate::prelude::*; pub type rlim_t = crate::uintptr_t; pub type sa_family_t = u8; pub type pthread_key_t = c_int; pub type nfds_t = c_ulong; pub type tcflag_t = c_uint; pub type speed_t = c_uchar; pub type clock_t = i32; pub type clockid_t = i32; pub type suseconds_t = i32; pub type wchar_t = i32; pub type off_t = i64; pub type ino_t = i64; pub type blkcnt_t = i64; pub type blksize_t = i32; pub type dev_t = i32; pub type mode_t = u32; pub type nlink_t = i32; pub type useconds_t = u32; pub type socklen_t = u32; pub type pthread_t = crate::uintptr_t; pub type pthread_condattr_t = crate::uintptr_t; pub type pthread_mutexattr_t = crate::uintptr_t; pub type pthread_rwlockattr_t = crate::uintptr_t; pub type sigset_t = u64; pub type fsblkcnt_t = i64; pub type fsfilcnt_t = i64; pub type pthread_attr_t = *mut c_void; pub type nl_item = c_int; pub type id_t = i32; pub type idtype_t = c_int; pub type fd_mask = u32; pub type regoff_t = c_int; pub type key_t = i32; pub type msgqnum_t = u32; pub type msglen_t = u32; pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Off = u32; pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Off = u64; pub type Elf64_Sword = i32; pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; pub type ENTRY = entry; pub type ACTION = c_int; pub type posix_spawnattr_t = *mut c_void; pub type posix_spawn_file_actions_t = *mut c_void; pub type StringList = _stringlist; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { self.si_addr } pub unsafe fn si_pid(&self) -> crate::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> c_int { self.si_status } } s! { pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8; 30], } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [i8; 24], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: u8, pub sin6_port: u16, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut addrinfo, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *const c_char, pub ifa_flags: c_uint, pub ifa_addr: *mut crate::sockaddr, pub ifa_netmask: *mut crate::sockaddr, pub ifa_dstaddr: *mut crate::sockaddr, pub ifa_data: *mut c_void, } pub struct fd_set { // size for 1024 bits, and a fd_mask with size u32 fds_bits: [fd_mask; 32], } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_int, pub tm_zone: *mut c_char, } pub struct utsname { pub sysname: [c_char; 32], pub nodename: [c_char; 32], pub release: [c_char; 32], pub version: [c_char; 32], pub machine: [c_char; 32], } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_line: c_char, pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, pub c_cc: [crate::cc_t; crate::NCCS], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, } pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, pub st_nlink: nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_size: off_t, pub st_rdev: dev_t, pub st_blksize: blksize_t, pub st_atime: time_t, pub st_atime_nsec: c_long, pub st_mtime: time_t, pub st_mtime_nsec: c_long, pub st_ctime: time_t, pub st_ctime_nsec: c_long, pub st_crtime: time_t, pub st_crtime_nsec: c_long, pub st_type: u32, pub st_blocks: blkcnt_t, } pub struct glob_t { pub gl_pathc: size_t, __unused1: size_t, pub gl_offs: size_t, __unused2: size_t, pub gl_pathv: *mut *mut c_char, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, __unused6: *mut c_void, __unused7: *mut c_void, __unused8: *mut c_void, } pub struct pthread_mutex_t { flags: u32, lock: i32, unused: i32, owner: i32, owner_count: i32, } pub struct pthread_cond_t { flags: u32, unused: i32, mutex: *mut c_void, waiter_count: i32, lock: i32, } pub struct pthread_rwlock_t { flags: u32, owner: i32, lock_sem: i32, // this is actually a union lock_count: i32, reader_count: i32, writer_count: i32, waiters: [*mut c_void; 2], } pub struct pthread_spinlock_t { lock: u32, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, pub pw_gecos: *mut c_char, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, pub si_pid: crate::pid_t, pub si_uid: crate::uid_t, pub si_addr: *mut c_void, pub si_status: c_int, pub si_band: c_long, pub sigval: *mut c_void, } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, //actually a union with sa_handler pub sa_mask: crate::sigset_t, pub sa_flags: c_int, sa_userdata: *mut c_void, } pub struct sem_t { pub type_: i32, pub named_sem_id: i32, // actually a union with unnamed_sem (i32) pub padding: [i32; 2], } pub struct ucred { pub pid: crate::pid_t, pub uid: crate::uid_t, pub gid: crate::gid_t, } pub struct sockaddr_dl { pub sdl_len: u8, pub sdl_family: u8, pub sdl_e_type: u16, pub sdl_index: u32, pub sdl_type: u8, pub sdl_nlen: u8, pub sdl_alen: u8, pub sdl_slen: u8, pub sdl_data: [u8; 46], } pub struct spwd { pub sp_namp: *mut c_char, pub sp_pwdp: *mut c_char, pub sp_lstchg: c_int, pub sp_min: c_int, pub sp_max: c_int, pub sp_warn: c_int, pub sp_inact: c_int, pub sp_expire: c_int, pub sp_flag: c_int, } pub struct regex_t { __buffer: *mut c_void, __allocated: size_t, __used: size_t, __syntax: c_ulong, __fastmap: *mut c_char, __translate: *mut c_char, __re_nsub: size_t, __bitfield: u8, } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, } pub struct ipc_perm { pub key: crate::key_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, } pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } pub struct entry { pub key: *mut c_char, pub data: *mut c_void, } pub struct option { pub name: *const c_char, pub has_arg: c_int, pub flag: *mut c_int, pub val: c_int, } pub struct _stringlist { pub sl_str: *mut *mut c_char, pub sl_max: size_t, pub sl_cur: size_t, } pub struct dl_phdr_info { pub dlpi_addr: crate::Elf_Addr, pub dlpi_name: *const c_char, pub dlpi_phdr: *const crate::Elf_Phdr, pub dlpi_phnum: crate::Elf_Half, } } s_no_extra_traits! { pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char; 126], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, __ss_pad1: [u8; 6], __ss_pad2: u64, __ss_pad3: [u8; 112], } pub struct dirent { pub d_dev: dev_t, pub d_pdev: dev_t, pub d_ino: ino_t, pub d_pino: i64, pub d_reclen: c_ushort, pub d_name: [c_char; 1024], // Max length is _POSIX_PATH_MAX } pub struct sigevent { pub sigev_notify: c_int, pub sigev_signo: c_int, pub sigev_value: crate::sigval, __unused1: *mut c_void, // actually a function pointer pub sigev_notify_attributes: *mut crate::pthread_attr_t, } pub struct utmpx { pub ut_type: c_short, pub ut_tv: crate::timeval, pub ut_id: [c_char; 8], pub ut_pid: crate::pid_t, pub ut_user: [c_char; 32], pub ut_line: [c_char; 16], pub ut_host: [c_char; 128], __ut_reserved: [c_char; 64], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_tv == other.ut_tv && self.ut_id == other.ut_id && self.ut_pid == other.ut_pid && self.ut_user == other.ut_user && self.ut_line == other.ut_line && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) && self.__ut_reserved == other.__ut_reserved } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) .field("ut_tv", &self.ut_tv) .field("ut_id", &self.ut_id) .field("ut_pid", &self.ut_pid) .field("ut_user", &self.ut_user) .field("ut_line", &self.ut_line) .field("ut_host", &self.ut_host) .field("__ut_reserved", &self.__ut_reserved) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_tv.hash(state); self.ut_id.hash(state); self.ut_pid.hash(state); self.ut_user.hash(state); self.ut_line.hash(state); self.ut_host.hash(state); self.__ut_reserved.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_len == other.sun_len && self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_len", &self.sun_len) .field("sun_family", &self.sun_family) // FIXME(debug): .field("sun_path", &self.sun_path) .finish() } } impl hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_len.hash(state); self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self .__ss_pad1 .iter() .zip(other.__ss_pad1.iter()) .all(|(a, b)| a == b) && self.__ss_pad2 == other.__ss_pad2 && self .__ss_pad3 .iter() .zip(other.__ss_pad3.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_pad2", &self.__ss_pad2) // FIXME(debug): .field("__ss_pad3", &self.__ss_pad3) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_pad2.hash(state); self.__ss_pad3.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_dev == other.d_dev && self.d_pdev == other.d_pdev && self.d_ino == other.d_ino && self.d_pino == other.d_pino && self.d_reclen == other.d_reclen && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_dev", &self.d_dev) .field("d_pdev", &self.d_pdev) .field("d_ino", &self.d_ino) .field("d_pino", &self.d_pino) .field("d_reclen", &self.d_reclen) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_dev.hash(state); self.d_pdev.hash(state); self.d_ino.hash(state); self.d_pino.hash(state); self.d_reclen.hash(state); self.d_name.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.sigev_notify_attributes.hash(state); } } } } pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 2147483647; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const L_SET: c_int = SEEK_SET; pub const L_INCR: c_int = SEEK_CUR; pub const L_XTND: c_int = SEEK_END; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const F_DUPFD: c_int = 0x0001; pub const F_GETFD: c_int = 0x0002; pub const F_SETFD: c_int = 0x0004; pub const F_GETFL: c_int = 0x0008; pub const F_SETFL: c_int = 0x0010; pub const F_GETLK: c_int = 0x0020; pub const F_SETLK: c_int = 0x0080; pub const F_SETLKW: c_int = 0x0100; pub const F_DUPFD_CLOEXEC: c_int = 0x0200; pub const F_RDLCK: c_int = 0x0040; pub const F_UNLCK: c_int = 0x0200; pub const F_WRLCK: c_int = 0x0400; pub const AT_FDCWD: c_int = -100; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x01; pub const AT_SYMLINK_FOLLOW: c_int = 0x02; pub const AT_REMOVEDIR: c_int = 0x04; pub const AT_EACCESS: c_int = 0x08; pub const POLLIN: c_short = 0x0001; pub const POLLOUT: c_short = 0x0002; pub const POLLRDNORM: c_short = POLLIN; pub const POLLWRNORM: c_short = POLLOUT; pub const POLLRDBAND: c_short = 0x0008; pub const POLLWRBAND: c_short = 0x0010; pub const POLLPRI: c_short = 0x0020; pub const POLLERR: c_short = 0x0004; pub const POLLHUP: c_short = 0x0080; pub const POLLNVAL: c_short = 0x1000; pub const PTHREAD_CREATE_JOINABLE: c_int = 0; pub const PTHREAD_CREATE_DETACHED: c_int = 1; pub const CLOCK_REALTIME: c_int = -1; pub const CLOCK_MONOTONIC: c_int = 0; pub const CLOCK_PROCESS_CPUTIME_ID: c_int = -2; pub const CLOCK_THREAD_CPUTIME_ID: c_int = -3; pub const RLIMIT_CORE: c_int = 0; pub const RLIMIT_CPU: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_FSIZE: c_int = 3; pub const RLIMIT_NOFILE: c_int = 4; pub const RLIMIT_STACK: c_int = 5; pub const RLIMIT_AS: c_int = 6; pub const RLIM_INFINITY: crate::rlim_t = 0xffffffff; // Haiku specific pub const RLIMIT_NOVMON: c_int = 7; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 8; pub const RUSAGE_SELF: c_int = 0; pub const RTLD_LAZY: c_int = 0; pub const NCCS: usize = 11; pub const O_RDONLY: c_int = 0x0000; pub const O_WRONLY: c_int = 0x0001; pub const O_RDWR: c_int = 0x0002; pub const O_ACCMODE: c_int = 0x0003; pub const O_EXCL: c_int = 0x0100; pub const O_CREAT: c_int = 0x0200; pub const O_TRUNC: c_int = 0x0400; pub const O_NOCTTY: c_int = 0x1000; pub const O_NOTRAVERSE: c_int = 0x2000; pub const O_CLOEXEC: c_int = 0x00000040; pub const O_NONBLOCK: c_int = 0x00000080; pub const O_APPEND: c_int = 0x00000800; pub const O_SYNC: c_int = 0x00010000; pub const O_RSYNC: c_int = 0x00020000; pub const O_DSYNC: c_int = 0x00040000; pub const O_NOFOLLOW: c_int = 0x00080000; pub const O_NOCACHE: c_int = 0x00100000; pub const O_DIRECTORY: c_int = 0x00200000; pub const S_IFIFO: crate::mode_t = 0o1_0000; pub const S_IFCHR: crate::mode_t = 0o2_0000; pub const S_IFBLK: crate::mode_t = 0o6_0000; pub const S_IFDIR: crate::mode_t = 0o4_0000; pub const S_IFREG: crate::mode_t = 0o10_0000; pub const S_IFLNK: crate::mode_t = 0o12_0000; pub const S_IFSOCK: crate::mode_t = 0o14_0000; pub const S_IFMT: crate::mode_t = 0o17_0000; pub const S_IRWXU: crate::mode_t = 0o0700; pub const S_IRUSR: crate::mode_t = 0o0400; pub const S_IWUSR: crate::mode_t = 0o0200; pub const S_IXUSR: crate::mode_t = 0o0100; pub const S_IRWXG: crate::mode_t = 0o0070; pub const S_IRGRP: crate::mode_t = 0o0040; pub const S_IWGRP: crate::mode_t = 0o0020; pub const S_IXGRP: crate::mode_t = 0o0010; pub const S_IRWXO: crate::mode_t = 0o0007; pub const S_IROTH: crate::mode_t = 0o0004; pub const S_IWOTH: crate::mode_t = 0o0002; pub const S_IXOTH: crate::mode_t = 0o0001; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGCHLD: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGPIPE: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSTOP: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGCONT: c_int = 12; pub const SIGTSTP: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGTTIN: c_int = 16; pub const SIGTTOU: c_int = 17; pub const SIGUSR1: c_int = 18; pub const SIGUSR2: c_int = 19; pub const SIGWINCH: c_int = 20; pub const SIGKILLTHR: c_int = 21; pub const SIGTRAP: c_int = 22; pub const SIGPOLL: c_int = 23; pub const SIGPROF: c_int = 24; pub const SIGSYS: c_int = 25; pub const SIGURG: c_int = 26; pub const SIGVTALRM: c_int = 27; pub const SIGXCPU: c_int = 28; pub const SIGXFSZ: c_int = 29; pub const SIGBUS: c_int = 30; pub const SIG_BLOCK: c_int = 1; pub const SIG_UNBLOCK: c_int = 2; pub const SIG_SETMASK: c_int = 3; pub const SIGEV_NONE: c_int = 0; pub const SIGEV_SIGNAL: c_int = 1; pub const SIGEV_THREAD: c_int = 2; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_MEMORY: c_int = 6; pub const EAI_NODATA: c_int = 7; pub const EAI_NONAME: c_int = 8; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 14; pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const LC_ALL: c_int = 0; pub const LC_COLLATE: c_int = 1; pub const LC_CTYPE: c_int = 2; pub const LC_MONETARY: c_int = 3; pub const LC_NUMERIC: c_int = 4; pub const LC_TIME: c_int = 5; pub const LC_MESSAGES: c_int = 6; // FIXME(haiku): Haiku does not have MAP_FILE, but library/std/os.rs requires it pub const MAP_FILE: c_int = 0x00; pub const MAP_SHARED: c_int = 0x01; pub const MAP_PRIVATE: c_int = 0x02; pub const MAP_FIXED: c_int = 0x04; pub const MAP_ANONYMOUS: c_int = 0x08; pub const MAP_NORESERVE: c_int = 0x10; pub const MAP_ANON: c_int = MAP_ANONYMOUS; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const MS_ASYNC: c_int = 0x01; pub const MS_INVALIDATE: c_int = 0x04; pub const MS_SYNC: c_int = 0x02; pub const E2BIG: c_int = -2147454975; pub const ECHILD: c_int = -2147454974; pub const EDEADLK: c_int = -2147454973; pub const EFBIG: c_int = -2147454972; pub const EMLINK: c_int = -2147454971; pub const ENFILE: c_int = -2147454970; pub const ENODEV: c_int = -2147454969; pub const ENOLCK: c_int = -2147454968; pub const ENOSYS: c_int = -2147454967; pub const ENOTTY: c_int = -2147454966; pub const ENXIO: c_int = -2147454965; pub const ESPIPE: c_int = -2147454964; pub const ESRCH: c_int = -2147454963; pub const EFPOS: c_int = -2147454962; pub const ESIGPARM: c_int = -2147454961; pub const EDOM: c_int = -2147454960; pub const ERANGE: c_int = -2147454959; pub const EPROTOTYPE: c_int = -2147454958; pub const EPROTONOSUPPORT: c_int = -2147454957; pub const EPFNOSUPPORT: c_int = -2147454956; pub const EAFNOSUPPORT: c_int = -2147454955; pub const EADDRINUSE: c_int = -2147454954; pub const EADDRNOTAVAIL: c_int = -2147454953; pub const ENETDOWN: c_int = -2147454952; pub const ENETUNREACH: c_int = -2147454951; pub const ENETRESET: c_int = -2147454950; pub const ECONNABORTED: c_int = -2147454949; pub const ECONNRESET: c_int = -2147454948; pub const EISCONN: c_int = -2147454947; pub const ENOTCONN: c_int = -2147454946; pub const ESHUTDOWN: c_int = -2147454945; pub const ECONNREFUSED: c_int = -2147454944; pub const EHOSTUNREACH: c_int = -2147454943; pub const ENOPROTOOPT: c_int = -2147454942; pub const ENOBUFS: c_int = -2147454941; pub const EINPROGRESS: c_int = -2147454940; pub const EALREADY: c_int = -2147454939; pub const EILSEQ: c_int = -2147454938; pub const ENOMSG: c_int = -2147454937; pub const ESTALE: c_int = -2147454936; pub const EOVERFLOW: c_int = -2147454935; pub const EMSGSIZE: c_int = -2147454934; pub const EOPNOTSUPP: c_int = -2147454933; pub const ENOTSOCK: c_int = -2147454932; pub const EHOSTDOWN: c_int = -2147454931; pub const EBADMSG: c_int = -2147454930; pub const ECANCELED: c_int = -2147454929; pub const EDESTADDRREQ: c_int = -2147454928; pub const EDQUOT: c_int = -2147454927; pub const EIDRM: c_int = -2147454926; pub const EMULTIHOP: c_int = -2147454925; pub const ENODATA: c_int = -2147454924; pub const ENOLINK: c_int = -2147454923; pub const ENOSR: c_int = -2147454922; pub const ENOSTR: c_int = -2147454921; pub const ENOTSUP: c_int = -2147454920; pub const EPROTO: c_int = -2147454919; pub const ETIME: c_int = -2147454918; pub const ETXTBSY: c_int = -2147454917; pub const ENOATTR: c_int = -2147454916; // INT_MIN pub const ENOMEM: c_int = -2147483648; // POSIX errors that can be mapped to BeOS error codes pub const EACCES: c_int = -2147483646; pub const EINTR: c_int = -2147483638; pub const EIO: c_int = -2147483647; pub const EBUSY: c_int = -2147483634; pub const EFAULT: c_int = -2147478783; pub const ETIMEDOUT: c_int = -2147483639; pub const EAGAIN: c_int = -2147483637; pub const EWOULDBLOCK: c_int = -2147483637; pub const EBADF: c_int = -2147459072; pub const EEXIST: c_int = -2147459070; pub const EINVAL: c_int = -2147483643; pub const ENAMETOOLONG: c_int = -2147459068; pub const ENOENT: c_int = -2147459069; pub const EPERM: c_int = -2147483633; pub const ENOTDIR: c_int = -2147459067; pub const EISDIR: c_int = -2147459063; pub const ENOTEMPTY: c_int = -2147459066; pub const ENOSPC: c_int = -2147459065; pub const EROFS: c_int = -2147459064; pub const EMFILE: c_int = -2147459062; pub const EXDEV: c_int = -2147459061; pub const ELOOP: c_int = -2147459060; pub const ENOEXEC: c_int = -2147478782; pub const EPIPE: c_int = -2147459059; pub const IPPROTO_RAW: c_int = 255; // These are prefixed with POSIX_ on Haiku pub const MADV_NORMAL: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_RANDOM: c_int = 3; pub const MADV_WILLNEED: c_int = 4; pub const MADV_DONTNEED: c_int = 5; pub const MADV_FREE: c_int = 6; // https://github.com/haiku/haiku/blob/HEAD/headers/posix/net/if.h#L80 pub const IFF_UP: c_int = 0x0001; pub const IFF_BROADCAST: c_int = 0x0002; // valid broadcast address pub const IFF_LOOPBACK: c_int = 0x0008; pub const IFF_POINTOPOINT: c_int = 0x0010; // point-to-point link pub const IFF_NOARP: c_int = 0x0040; // no address resolution pub const IFF_AUTOUP: c_int = 0x0080; // auto dial pub const IFF_PROMISC: c_int = 0x0100; // receive all packets pub const IFF_ALLMULTI: c_int = 0x0200; // receive all multicast packets pub const IFF_SIMPLEX: c_int = 0x0800; // doesn't receive own transmissions pub const IFF_LINK: c_int = 0x1000; // has link pub const IFF_AUTO_CONFIGURED: c_int = 0x2000; pub const IFF_CONFIGURING: c_int = 0x4000; pub const IFF_MULTICAST: c_int = 0x8000; // supports multicast pub const AF_UNSPEC: c_int = 0; pub const AF_INET: c_int = 1; pub const AF_APPLETALK: c_int = 2; pub const AF_ROUTE: c_int = 3; pub const AF_LINK: c_int = 4; pub const AF_INET6: c_int = 5; pub const AF_DLI: c_int = 6; pub const AF_IPX: c_int = 7; pub const AF_NOTIFY: c_int = 8; pub const AF_LOCAL: c_int = 9; pub const AF_UNIX: c_int = AF_LOCAL; pub const AF_BLUETOOTH: c_int = 10; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_INET: c_int = AF_INET; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_LINK: c_int = AF_LINK; pub const PF_INET6: c_int = AF_INET6; pub const PF_LOCAL: c_int = AF_LOCAL; pub const PF_UNIX: c_int = AF_UNIX; pub const PF_BLUETOOTH: c_int = AF_BLUETOOTH; pub const IP_OPTIONS: c_int = 1; pub const IP_HDRINCL: c_int = 2; pub const IP_TOS: c_int = 3; pub const IP_TTL: c_int = 4; pub const IP_RECVOPTS: c_int = 5; pub const IP_RECVRETOPTS: c_int = 6; pub const IP_RECVDSTADDR: c_int = 7; pub const IP_RETOPTS: c_int = 8; pub const IP_MULTICAST_IF: c_int = 9; pub const IP_MULTICAST_TTL: c_int = 10; pub const IP_MULTICAST_LOOP: c_int = 11; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IP_BLOCK_SOURCE: c_int = 14; pub const IP_UNBLOCK_SOURCE: c_int = 15; pub const IP_ADD_SOURCE_MEMBERSHIP: c_int = 16; pub const IP_DROP_SOURCE_MEMBERSHIP: c_int = 17; pub const TCP_NODELAY: c_int = 0x01; pub const TCP_MAXSEG: c_int = 0x02; pub const TCP_NOPUSH: c_int = 0x04; pub const TCP_NOOPT: c_int = 0x08; pub const IF_NAMESIZE: size_t = 32; pub const IFNAMSIZ: size_t = IF_NAMESIZE; pub const IPV6_MULTICAST_IF: c_int = 24; pub const IPV6_MULTICAST_HOPS: c_int = 25; pub const IPV6_MULTICAST_LOOP: c_int = 26; pub const IPV6_UNICAST_HOPS: c_int = 27; pub const IPV6_JOIN_GROUP: c_int = 28; pub const IPV6_LEAVE_GROUP: c_int = 29; pub const IPV6_V6ONLY: c_int = 30; pub const IPV6_PKTINFO: c_int = 31; pub const IPV6_RECVPKTINFO: c_int = 32; pub const IPV6_HOPLIMIT: c_int = 33; pub const IPV6_RECVHOPLIMIT: c_int = 34; pub const IPV6_HOPOPTS: c_int = 35; pub const IPV6_DSTOPTS: c_int = 36; pub const IPV6_RTHDR: c_int = 37; pub const MSG_OOB: c_int = 0x0001; pub const MSG_PEEK: c_int = 0x0002; pub const MSG_DONTROUTE: c_int = 0x0004; pub const MSG_EOR: c_int = 0x0008; pub const MSG_TRUNC: c_int = 0x0010; pub const MSG_CTRUNC: c_int = 0x0020; pub const MSG_WAITALL: c_int = 0x0040; pub const MSG_DONTWAIT: c_int = 0x0080; pub const MSG_BCAST: c_int = 0x0100; pub const MSG_MCAST: c_int = 0x0200; pub const MSG_EOF: c_int = 0x0400; pub const MSG_NOSIGNAL: c_int = 0x0800; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const LOCK_SH: c_int = 0x01; pub const LOCK_EX: c_int = 0x02; pub const LOCK_NB: c_int = 0x04; pub const LOCK_UN: c_int = 0x08; pub const MINSIGSTKSZ: size_t = 8192; pub const SIGSTKSZ: size_t = 16384; pub const IOV_MAX: c_int = 1024; pub const PATH_MAX: c_int = 1024; pub const SA_NOCLDSTOP: c_int = 0x01; pub const SA_NOCLDWAIT: c_int = 0x02; pub const SA_RESETHAND: c_int = 0x04; pub const SA_NODEFER: c_int = 0x08; pub const SA_RESTART: c_int = 0x10; pub const SA_ONSTACK: c_int = 0x20; pub const SA_SIGINFO: c_int = 0x40; pub const SA_NOMASK: c_int = SA_NODEFER; pub const SA_STACK: c_int = SA_ONSTACK; pub const SA_ONESHOT: c_int = SA_RESETHAND; pub const SS_ONSTACK: c_int = 0x1; pub const SS_DISABLE: c_int = 0x2; // DIFF(main): changed to `c_int` in 500365e1 pub const FD_SETSIZE: usize = 1024; pub const RTLD_LOCAL: c_int = 0x0; pub const RTLD_NOW: c_int = 0x1; pub const RTLD_GLOBAL: c_int = 0x2; pub const RTLD_DEFAULT: *mut c_void = 0isize as *mut c_void; pub const BUFSIZ: c_uint = 8192; pub const FILENAME_MAX: c_uint = 256; pub const FOPEN_MAX: c_uint = 128; pub const L_tmpnam: c_uint = 512; pub const TMP_MAX: c_uint = 32768; pub const _PC_CHOWN_RESTRICTED: c_int = 1; pub const _PC_MAX_CANON: c_int = 2; pub const _PC_MAX_INPUT: c_int = 3; pub const _PC_NAME_MAX: c_int = 4; pub const _PC_NO_TRUNC: c_int = 5; pub const _PC_PATH_MAX: c_int = 6; pub const _PC_PIPE_BUF: c_int = 7; pub const _PC_VDISABLE: c_int = 8; pub const _PC_LINK_MAX: c_int = 25; pub const _PC_SYNC_IO: c_int = 26; pub const _PC_ASYNC_IO: c_int = 27; pub const _PC_PRIO_IO: c_int = 28; pub const _PC_SOCK_MAXBUF: c_int = 29; pub const _PC_FILESIZEBITS: c_int = 30; pub const _PC_REC_INCR_XFER_SIZE: c_int = 31; pub const _PC_REC_MAX_XFER_SIZE: c_int = 32; pub const _PC_REC_MIN_XFER_SIZE: c_int = 33; pub const _PC_REC_XFER_ALIGN: c_int = 34; pub const _PC_ALLOC_SIZE_MIN: c_int = 35; pub const _PC_SYMLINK_MAX: c_int = 36; pub const _PC_2_SYMLINKS: c_int = 37; pub const _PC_XATTR_EXISTS: c_int = 38; pub const _PC_XATTR_ENABLED: c_int = 39; pub const FIONBIO: c_ulong = 0xbe000000; pub const FIONREAD: c_ulong = 0xbe000001; pub const FIOSEEKDATA: c_ulong = 0xbe000002; pub const FIOSEEKHOLE: c_ulong = 0xbe000003; pub const _SC_ARG_MAX: c_int = 15; pub const _SC_CHILD_MAX: c_int = 16; pub const _SC_CLK_TCK: c_int = 17; pub const _SC_JOB_CONTROL: c_int = 18; pub const _SC_NGROUPS_MAX: c_int = 19; pub const _SC_OPEN_MAX: c_int = 20; pub const _SC_SAVED_IDS: c_int = 21; pub const _SC_STREAM_MAX: c_int = 22; pub const _SC_TZNAME_MAX: c_int = 23; pub const _SC_VERSION: c_int = 24; pub const _SC_GETGR_R_SIZE_MAX: c_int = 25; pub const _SC_GETPW_R_SIZE_MAX: c_int = 26; pub const _SC_PAGESIZE: c_int = 27; pub const _SC_PAGE_SIZE: c_int = 27; pub const _SC_SEM_NSEMS_MAX: c_int = 28; pub const _SC_SEM_VALUE_MAX: c_int = 29; pub const _SC_SEMAPHORES: c_int = 30; pub const _SC_THREADS: c_int = 31; pub const _SC_IOV_MAX: c_int = 32; pub const _SC_UIO_MAXIOV: c_int = 32; pub const _SC_NPROCESSORS_CONF: c_int = 34; pub const _SC_NPROCESSORS_ONLN: c_int = 35; pub const _SC_ATEXIT_MAX: c_int = 37; pub const _SC_PASS_MAX: c_int = 39; pub const _SC_PHYS_PAGES: c_int = 40; pub const _SC_AVPHYS_PAGES: c_int = 41; pub const _SC_PIPE: c_int = 42; pub const _SC_SELECT: c_int = 43; pub const _SC_POLL: c_int = 44; pub const _SC_MAPPED_FILES: c_int = 45; pub const _SC_THREAD_PROCESS_SHARED: c_int = 46; pub const _SC_THREAD_STACK_MIN: c_int = 47; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 48; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 49; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 50; pub const _SC_REALTIME_SIGNALS: c_int = 51; pub const _SC_MEMORY_PROTECTION: c_int = 52; pub const _SC_SIGQUEUE_MAX: c_int = 53; pub const _SC_RTSIG_MAX: c_int = 54; pub const _SC_MONOTONIC_CLOCK: c_int = 55; pub const _SC_DELAYTIMER_MAX: c_int = 56; pub const _SC_TIMER_MAX: c_int = 57; pub const _SC_TIMERS: c_int = 58; pub const _SC_CPUTIME: c_int = 59; pub const _SC_THREAD_CPUTIME: c_int = 60; pub const _SC_HOST_NAME_MAX: c_int = 61; pub const _SC_REGEXP: c_int = 62; pub const _SC_SYMLOOP_MAX: c_int = 63; pub const _SC_SHELL: c_int = 64; pub const _SC_TTY_NAME_MAX: c_int = 65; pub const _SC_ADVISORY_INFO: c_int = 66; pub const _SC_BARRIERS: c_int = 67; pub const _SC_CLOCK_SELECTION: c_int = 68; pub const _SC_FSYNC: c_int = 69; pub const _SC_IPV6: c_int = 70; pub const _SC_MEMLOCK: c_int = 71; pub const _SC_MEMLOCK_RANGE: c_int = 72; pub const _SC_MESSAGE_PASSING: c_int = 73; pub const _SC_PRIORITIZED_IO: c_int = 74; pub const _SC_PRIORITY_SCHEDULING: c_int = 75; pub const _SC_READER_WRITER_LOCKS: c_int = 76; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 77; pub const _SC_SPAWN: c_int = 78; pub const _SC_SPIN_LOCKS: c_int = 79; pub const _SC_SPORADIC_SERVER: c_int = 80; pub const _SC_SYNCHRONIZED_IO: c_int = 81; pub const _SC_THREAD_PRIO_INHERIT: c_int = 82; pub const _SC_THREAD_PRIO_PROTECT: c_int = 83; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 84; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 85; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 86; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 87; pub const _SC_TIMEOUTS: c_int = 88; pub const _SC_TRACE: c_int = 89; pub const _SC_TRACE_EVENT_FILTER: c_int = 90; pub const _SC_TRACE_INHERIT: c_int = 91; pub const _SC_TRACE_LOG: c_int = 92; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 93; pub const _SC_V6_ILP32_OFF32: c_int = 94; pub const _SC_V6_ILP32_OFFBIG: c_int = 95; pub const _SC_V6_LP64_OFF64: c_int = 96; pub const _SC_V6_LPBIG_OFFBIG: c_int = 97; pub const _SC_V7_ILP32_OFF32: c_int = 98; pub const _SC_V7_ILP32_OFFBIG: c_int = 99; pub const _SC_V7_LP64_OFF64: c_int = 100; pub const _SC_V7_LPBIG_OFFBIG: c_int = 101; pub const _SC_2_C_BIND: c_int = 102; pub const _SC_2_C_DEV: c_int = 103; pub const _SC_2_CHAR_TERM: c_int = 104; pub const _SC_2_FORT_DEV: c_int = 105; pub const _SC_2_FORT_RUN: c_int = 106; pub const _SC_2_LOCALEDEF: c_int = 107; pub const _SC_2_PBS: c_int = 108; pub const _SC_2_PBS_ACCOUNTING: c_int = 109; pub const _SC_2_PBS_CHECKPOINT: c_int = 110; pub const _SC_2_PBS_LOCATE: c_int = 111; pub const _SC_2_PBS_MESSAGE: c_int = 112; pub const _SC_2_PBS_TRACK: c_int = 113; pub const _SC_2_SW_DEV: c_int = 114; pub const _SC_2_UPE: c_int = 115; pub const _SC_2_VERSION: c_int = 116; pub const _SC_XOPEN_CRYPT: c_int = 117; pub const _SC_XOPEN_ENH_I18N: c_int = 118; pub const _SC_XOPEN_REALTIME: c_int = 119; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 120; pub const _SC_XOPEN_SHM: c_int = 121; pub const _SC_XOPEN_STREAMS: c_int = 122; pub const _SC_XOPEN_UNIX: c_int = 123; pub const _SC_XOPEN_UUCP: c_int = 124; pub const _SC_XOPEN_VERSION: c_int = 125; pub const _SC_BC_BASE_MAX: c_int = 129; pub const _SC_BC_DIM_MAX: c_int = 130; pub const _SC_BC_SCALE_MAX: c_int = 131; pub const _SC_BC_STRING_MAX: c_int = 132; pub const _SC_COLL_WEIGHTS_MAX: c_int = 133; pub const _SC_EXPR_NEST_MAX: c_int = 134; pub const _SC_LINE_MAX: c_int = 135; pub const _SC_LOGIN_NAME_MAX: c_int = 136; pub const _SC_MQ_OPEN_MAX: c_int = 137; pub const _SC_MQ_PRIO_MAX: c_int = 138; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 139; pub const _SC_THREAD_KEYS_MAX: c_int = 140; pub const _SC_THREAD_THREADS_MAX: c_int = 141; pub const _SC_RE_DUP_MAX: c_int = 142; pub const PTHREAD_STACK_MIN: size_t = 8192; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { flags: 0, lock: 0, unused: -42, owner: -1, owner_count: 0, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { flags: 0, unused: -42, mutex: 0 as *mut _, waiter_count: 0, lock: 0, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { flags: 0, owner: -1, lock_sem: 0, lock_count: 0, reader_count: 0, writer_count: 0, waiters: [0 as *mut _; 2], }; pub const PTHREAD_MUTEX_DEFAULT: c_int = 0; pub const PTHREAD_MUTEX_NORMAL: c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 3; pub const FIOCLEX: c_ulong = 0; // FIXME(haiku): does not exist on Haiku! pub const RUSAGE_CHILDREN: c_int = -1; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_SEQPACKET: c_int = 5; pub const SOL_SOCKET: c_int = -1; pub const SO_ACCEPTCONN: c_int = 0x00000001; pub const SO_BROADCAST: c_int = 0x00000002; pub const SO_DEBUG: c_int = 0x00000004; pub const SO_DONTROUTE: c_int = 0x00000008; pub const SO_KEEPALIVE: c_int = 0x00000010; pub const SO_OOBINLINE: c_int = 0x00000020; pub const SO_REUSEADDR: c_int = 0x00000040; pub const SO_REUSEPORT: c_int = 0x00000080; pub const SO_USELOOPBACK: c_int = 0x00000100; pub const SO_LINGER: c_int = 0x00000200; pub const SO_SNDBUF: c_int = 0x40000001; pub const SO_SNDLOWAT: c_int = 0x40000002; pub const SO_SNDTIMEO: c_int = 0x40000003; pub const SO_RCVBUF: c_int = 0x40000004; pub const SO_RCVLOWAT: c_int = 0x40000005; pub const SO_RCVTIMEO: c_int = 0x40000006; pub const SO_ERROR: c_int = 0x40000007; pub const SO_TYPE: c_int = 0x40000008; pub const SO_NONBLOCK: c_int = 0x40000009; pub const SO_BINDTODEVICE: c_int = 0x4000000a; pub const SO_PEERCRED: c_int = 0x4000000b; pub const SCM_RIGHTS: c_int = 0x01; pub const SOMAXCONN: c_int = 32; pub const NI_MAXHOST: size_t = 1025; pub const WNOHANG: c_int = 0x01; pub const WUNTRACED: c_int = 0x02; pub const WCONTINUED: c_int = 0x04; pub const WEXITED: c_int = 0x08; pub const WSTOPPED: c_int = 0x10; pub const WNOWAIT: c_int = 0x20; // si_code values for SIGBUS signal pub const BUS_ADRALN: c_int = 40; pub const BUS_ADRERR: c_int = 41; pub const BUS_OBJERR: c_int = 42; // si_code values for SIGCHLD signal pub const CLD_EXITED: c_int = 60; pub const CLD_KILLED: c_int = 61; pub const CLD_DUMPED: c_int = 62; pub const CLD_TRAPPED: c_int = 63; pub const CLD_STOPPED: c_int = 64; pub const CLD_CONTINUED: c_int = 65; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const UTIME_OMIT: c_long = 1000000001; pub const UTIME_NOW: c_long = 1000000000; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VEOF: usize = 4; pub const VEOL: usize = 5; pub const VMIN: usize = 4; pub const VTIME: usize = 5; pub const VEOL2: usize = 6; pub const VSWTCH: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const IGNBRK: crate::tcflag_t = 0x01; pub const BRKINT: crate::tcflag_t = 0x02; pub const IGNPAR: crate::tcflag_t = 0x04; pub const PARMRK: crate::tcflag_t = 0x08; pub const INPCK: crate::tcflag_t = 0x10; pub const ISTRIP: crate::tcflag_t = 0x20; pub const INLCR: crate::tcflag_t = 0x40; pub const IGNCR: crate::tcflag_t = 0x80; pub const ICRNL: crate::tcflag_t = 0x100; pub const IUCLC: crate::tcflag_t = 0x200; pub const IXON: crate::tcflag_t = 0x400; pub const IXANY: crate::tcflag_t = 0x800; pub const IXOFF: crate::tcflag_t = 0x1000; pub const OPOST: crate::tcflag_t = 0x00000001; pub const OLCUC: crate::tcflag_t = 0x00000002; pub const ONLCR: crate::tcflag_t = 0x00000004; pub const OCRNL: crate::tcflag_t = 0x00000008; pub const ONOCR: crate::tcflag_t = 0x00000010; pub const ONLRET: crate::tcflag_t = 0x00000020; pub const OFILL: crate::tcflag_t = 0x00000040; pub const OFDEL: crate::tcflag_t = 0x00000080; pub const NLDLY: crate::tcflag_t = 0x00000100; pub const NL0: crate::tcflag_t = 0x00000000; pub const NL1: crate::tcflag_t = 0x00000100; pub const CRDLY: crate::tcflag_t = 0x00000600; pub const CR0: crate::tcflag_t = 0x00000000; pub const CR1: crate::tcflag_t = 0x00000200; pub const CR2: crate::tcflag_t = 0x00000400; pub const CR3: crate::tcflag_t = 0x00000600; pub const TABDLY: crate::tcflag_t = 0x00001800; pub const TAB0: crate::tcflag_t = 0x00000000; pub const TAB1: crate::tcflag_t = 0x00000800; pub const TAB2: crate::tcflag_t = 0x00001000; pub const TAB3: crate::tcflag_t = 0x00001800; pub const BSDLY: crate::tcflag_t = 0x00002000; pub const BS0: crate::tcflag_t = 0x00000000; pub const BS1: crate::tcflag_t = 0x00002000; pub const VTDLY: crate::tcflag_t = 0x00004000; pub const VT0: crate::tcflag_t = 0x00000000; pub const VT1: crate::tcflag_t = 0x00004000; pub const FFDLY: crate::tcflag_t = 0x00008000; pub const FF0: crate::tcflag_t = 0x00000000; pub const FF1: crate::tcflag_t = 0x00008000; pub const CSIZE: crate::tcflag_t = 0x00000020; pub const CS5: crate::tcflag_t = 0x00000000; pub const CS6: crate::tcflag_t = 0x00000000; pub const CS7: crate::tcflag_t = 0x00000000; pub const CS8: crate::tcflag_t = 0x00000020; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const CREAD: crate::tcflag_t = 0x00000080; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const XLOBLK: crate::tcflag_t = 0x00001000; pub const CTSFLOW: crate::tcflag_t = 0x00002000; pub const RTSFLOW: crate::tcflag_t = 0x00004000; pub const CRTSCTS: crate::tcflag_t = RTSFLOW | CTSFLOW; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const XCASE: crate::tcflag_t = 0x00000004; pub const ECHO: crate::tcflag_t = 0x00000008; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const TOSTOP: crate::tcflag_t = 0x00000100; pub const IEXTEN: crate::tcflag_t = 0x00000200; pub const ECHOCTL: crate::tcflag_t = 0x00000400; pub const ECHOPRT: crate::tcflag_t = 0x00000800; pub const ECHOKE: crate::tcflag_t = 0x00001000; pub const FLUSHO: crate::tcflag_t = 0x00002000; pub const PENDIN: crate::tcflag_t = 0x00004000; pub const TCGB_CTS: c_int = 0x01; pub const TCGB_DSR: c_int = 0x02; pub const TCGB_RI: c_int = 0x04; pub const TCGB_DCD: c_int = 0x08; pub const TIOCM_CTS: c_int = TCGB_CTS; pub const TIOCM_CD: c_int = TCGB_DCD; pub const TIOCM_CAR: c_int = TCGB_DCD; pub const TIOCM_RI: c_int = TCGB_RI; pub const TIOCM_RNG: c_int = TCGB_RI; pub const TIOCM_DSR: c_int = TCGB_DSR; pub const TIOCM_DTR: c_int = 0x10; pub const TIOCM_RTS: c_int = 0x20; pub const B0: speed_t = 0x00; pub const B50: speed_t = 0x01; pub const B75: speed_t = 0x02; pub const B110: speed_t = 0x03; pub const B134: speed_t = 0x04; pub const B150: speed_t = 0x05; pub const B200: speed_t = 0x06; pub const B300: speed_t = 0x07; pub const B600: speed_t = 0x08; pub const B1200: speed_t = 0x09; pub const B1800: speed_t = 0x0A; pub const B2400: speed_t = 0x0B; pub const B4800: speed_t = 0x0C; pub const B9600: speed_t = 0x0D; pub const B19200: speed_t = 0x0E; pub const B38400: speed_t = 0x0F; pub const B57600: speed_t = 0x10; pub const B115200: speed_t = 0x11; pub const B230400: speed_t = 0x12; pub const B31250: speed_t = 0x13; pub const TCSANOW: c_int = 0x01; pub const TCSADRAIN: c_int = 0x02; pub const TCSAFLUSH: c_int = 0x04; pub const TCOOFF: c_int = 0x01; pub const TCOON: c_int = 0x02; pub const TCIOFF: c_int = 0x04; pub const TCION: c_int = 0x08; pub const TCIFLUSH: c_int = 0x01; pub const TCOFLUSH: c_int = 0x02; pub const TCIOFLUSH: c_int = 0x03; pub const TCGETA: c_ulong = 0x8000; pub const TCSETA: c_ulong = TCGETA + 1; pub const TCSETAF: c_ulong = TCGETA + 2; pub const TCSETAW: c_ulong = TCGETA + 3; pub const TCSBRK: c_ulong = TCGETA + 5; pub const TCFLSH: c_ulong = TCGETA + 6; pub const TCXONC: c_ulong = TCGETA + 7; pub const TCGETBITS: c_ulong = TCGETA + 9; pub const TCSETDTR: c_ulong = TCGETA + 10; pub const TCSETRTS: c_ulong = TCGETA + 11; pub const TIOCGWINSZ: c_ulong = TCGETA + 12; pub const TIOCSWINSZ: c_ulong = TCGETA + 13; pub const TIOCGPGRP: c_ulong = TCGETA + 15; pub const TIOCSPGRP: c_ulong = TCGETA + 16; pub const TIOCSCTTY: c_ulong = TCGETA + 17; pub const TIOCMGET: c_ulong = TCGETA + 18; pub const TIOCMSET: c_ulong = TCGETA + 19; pub const TIOCSBRK: c_ulong = TCGETA + 20; pub const TIOCCBRK: c_ulong = TCGETA + 21; pub const TIOCMBIS: c_ulong = TCGETA + 22; pub const TIOCMBIC: c_ulong = TCGETA + 23; pub const TIOCGSID: c_ulong = TCGETA + 24; pub const TIOCOUTQ: c_ulong = TCGETA + 25; pub const TIOCEXCL: c_ulong = TCGETA + 26; pub const TIOCNXCL: c_ulong = TCGETA + 27; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; // utmpx entry types pub const EMPTY: c_short = 0; pub const BOOT_TIME: c_short = 1; pub const OLD_TIME: c_short = 2; pub const NEW_TIME: c_short = 3; pub const USER_PROCESS: c_short = 4; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const DEAD_PROCESS: c_short = 7; pub const LOG_PID: c_int = 1 << 12; pub const LOG_CONS: c_int = 2 << 12; pub const LOG_ODELAY: c_int = 4 << 12; pub const LOG_NDELAY: c_int = 8 << 12; pub const LOG_SERIAL: c_int = 16 << 12; pub const LOG_PERROR: c_int = 32 << 12; pub const LOG_NOWAIT: c_int = 64 << 12; // spawn.h // DIFF(main): changed to `c_short` in f62eb023ab pub const POSIX_SPAWN_RESETIDS: c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: c_int = 0x02; pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x10; pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x20; pub const POSIX_SPAWN_SETSID: c_int = 0x40; const_fn! { {const} fn CMSG_ALIGN(len: usize) -> usize { len + mem::size_of::() - 1 & !(mem::size_of::() - 1) } } f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(CMSG_ALIGN(mem::size_of::()) as isize) } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(mem::size_of::())) as c_uint } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { CMSG_ALIGN(mem::size_of::()) as c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { return crate::CMSG_FIRSTHDR(mhdr); }; let next = cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize) + CMSG_ALIGN(mem::size_of::()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut cmsghdr } else { (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr } } pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub {const} fn WIFEXITED(status: c_int) -> bool { (status & !0xff) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { status & 0xff } pub {const} fn WIFSIGNALED(status: c_int) -> bool { ((status >> 8) & 0xff) != 0 } pub {const} fn WTERMSIG(status: c_int) -> c_int { (status >> 8) & 0xff } pub {const} fn WIFSTOPPED(status: c_int) -> bool { ((status >> 16) & 0xff) != 0 } pub {const} fn WSTOPSIG(status: c_int) -> c_int { (status >> 16) & 0xff } // actually WIFCORED, but this is used everywhere else pub {const} fn WCOREDUMP(status: c_int) -> bool { (status & 0x10000) != 0 } pub {const} fn WIFCONTINUED(status: c_int) -> bool { (status & 0x20000) != 0 } } extern "C" { pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; pub fn getpriority(which: c_int, who: id_t) -> c_int; pub fn setpriority(which: c_int, who: id_t, priority: c_int) -> c_int; pub fn endusershell(); pub fn getpass(prompt: *const c_char) -> *mut c_char; pub fn getusershell() -> *mut c_char; pub fn issetugid() -> c_int; pub fn setusershell(); pub fn utimensat( fd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn _errnop() -> *mut c_int; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn getifaddrs(ifap: *mut *mut crate::ifaddrs) -> c_int; pub fn freeifaddrs(ifa: *mut crate::ifaddrs); pub fn ppoll( fds: *mut crate::pollfd, numfds: crate::nfds_t, timeout: *const crate::timespec, sigMask: *const sigset_t, ) -> c_int; pub fn getspent() -> *mut spwd; pub fn getspent_r( pwd: *mut spwd, buf: *mut c_char, bufferSize: size_t, res: *mut *mut spwd, ) -> c_int; pub fn setspent(); pub fn endspent(); pub fn getspnam(name: *const c_char) -> *mut spwd; pub fn getspnam_r( name: *const c_char, spwd: *mut spwd, buffer: *mut c_char, bufferSize: size_t, res: *mut *mut spwd, ) -> c_int; pub fn sgetspent(line: *const c_char) -> *mut spwd; pub fn sgetspent_r( line: *const c_char, spwd: *mut spwd, buffer: *mut c_char, bufferSize: size_t, res: *mut *mut spwd, ) -> c_int; pub fn fgetspent(file: *mut crate::FILE) -> *mut spwd; pub fn fgetspent_r( file: *mut crate::FILE, spwd: *mut spwd, buffer: *mut c_char, bufferSize: size_t, res: *mut *mut spwd, ) -> c_int; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_settime(clk_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn clock_getcpuclockid(pid: crate::pid_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn pthread_create( thread: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn valloc(numBytes: size_t) -> *mut c_void; pub fn malloc_usable_size(ptr: *mut c_void) -> size_t; pub fn memalign(align: size_t, size: size_t) -> *mut c_void; pub fn setgroups(ngroups: c_int, ptr: *const crate::gid_t) -> c_int; pub fn initgroups(name: *const c_char, basegid: crate::gid_t) -> c_int; pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_sigqueue(thread: crate::pthread_t, sig: c_int, value: crate::sigval) -> c_int; pub fn pthread_spin_init(lock: *mut crate::pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut crate::pthread_spinlock_t) -> c_int; pub fn waitid( idtype: idtype_t, id: id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; pub fn globfree(pglob: *mut crate::glob_t); pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advice: c_int) -> c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn shm_open(name: *const c_char, oflag: c_int, mode: crate::mode_t) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn bind( socket: c_int, address: *const crate::sockaddr, address_len: crate::socklen_t, ) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, count: c_int) -> ssize_t; pub fn readv(fd: c_int, iov: *const crate::iovec, count: c_int) -> ssize_t; pub fn sendmsg(fd: c_int, msg: *const crate::msghdr, flags: c_int) -> ssize_t; pub fn recvmsg(fd: c_int, msg: *mut crate::msghdr, flags: c_int) -> ssize_t; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn execvpe( file: *const c_char, argv: *const *const c_char, environment: *const *const c_char, ) -> c_int; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrouplist( user: *const c_char, basegroup: crate::gid_t, grouplist: *mut crate::gid_t, groupcount: *mut c_int, ) -> c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn getdtablesize() -> c_int; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwent() -> *mut passwd; pub fn setpwent(); pub fn endpwent(); pub fn endgrent(); pub fn getgrent() -> *mut crate::group; pub fn setgrent(); pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn sethostname(name: *const c_char, len: size_t) -> c_int; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn getitimer(which: c_int, curr_value: *mut crate::itimerval) -> c_int; pub fn setitimer( which: c_int, new_value: *const crate::itimerval, old_value: *mut crate::itimerval, ) -> c_int; pub fn regcomp(preg: *mut regex_t, pattern: *const c_char, cflags: c_int) -> c_int; pub fn regexec( preg: *const regex_t, input: *const c_char, nmatch: size_t, pmatch: *mut regmatch_t, eflags: c_int, ) -> c_int; pub fn regerror( errcode: c_int, preg: *const regex_t, errbuf: *mut c_char, errbuf_size: size_t, ) -> size_t; pub fn regfree(preg: *mut regex_t); pub fn msgctl(msqid: c_int, cmd: c_int, buf: *mut msqid_ds) -> c_int; pub fn msgget(key: crate::key_t, msgflg: c_int) -> c_int; pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtype: c_long, msgflg: c_int, ) -> ssize_t; pub fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: size_t, msgflg: c_int) -> c_int; pub fn semget(key: crate::key_t, nsems: c_int, semflg: c_int) -> c_int; pub fn semctl(semid: c_int, semnum: c_int, cmd: c_int, ...) -> c_int; pub fn semop(semid: c_int, sops: *mut sembuf, nsops: size_t) -> c_int; pub fn ftok(pathname: *const c_char, proj_id: c_int) -> crate::key_t; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn lsearch( key: *const c_void, base: *mut c_void, nelp: *mut size_t, width: size_t, compar: Option c_int>, ) -> *mut c_void; pub fn lfind( key: *const c_void, base: *const c_void, nelp: *mut size_t, width: size_t, compar: Option c_int>, ) -> *mut c_void; pub fn hcreate(nelt: size_t) -> c_int; pub fn hdestroy(); pub fn hsearch(entry: crate::ENTRY, action: crate::ACTION) -> *mut crate::ENTRY; pub fn drand48() -> c_double; pub fn erand48(xseed: *mut c_ushort) -> c_double; pub fn lrand48() -> c_long; pub fn nrand48(xseed: *mut c_ushort) -> c_long; pub fn mrand48() -> c_long; pub fn jrand48(xseed: *mut c_ushort) -> c_long; pub fn srand48(seed: c_long); pub fn seed48(xseed: *mut c_ushort) -> *mut c_ushort; pub fn lcong48(p: *mut c_ushort); pub fn clearenv() -> c_int; pub fn ctermid(s: *mut c_char) -> *mut c_char; pub fn sync(); pub fn getpagesize() -> c_int; pub fn brk(addr: *mut c_void) -> c_int; pub fn sbrk(increment: intptr_t) -> *mut c_void; pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawn_file_actions_init(file_actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(file_actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( file_actions: *mut posix_spawn_file_actions_t, fildes: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( file_actions: *mut posix_spawn_file_actions_t, fildes: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( file_actions: *mut posix_spawn_file_actions_t, fildes: c_int, newfildes: c_int, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, _flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, _pgroup: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, pgroup: crate::pid_t) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, sigdefault: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, sigdefault: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, _sigmask: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, sigmask: *const crate::sigset_t, ) -> c_int; pub fn getopt_long( argc: c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut c_int, ) -> c_int; pub fn strcasecmp_l( string1: *const c_char, string2: *const c_char, locale: crate::locale_t, ) -> c_int; pub fn strncasecmp_l( string1: *const c_char, string2: *const c_char, length: size_t, locale: crate::locale_t, ) -> c_int; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; } #[link(name = "bsd")] extern "C" { pub fn lutimes(file: *const c_char, times: *const crate::timeval) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> crate::pid_t; pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> c_int; pub fn strsep(string: *mut *mut c_char, delimiters: *const c_char) -> *mut c_char; pub fn explicit_bzero(buf: *mut c_void, len: size_t); pub fn login_tty(_fd: c_int) -> c_int; pub fn sl_init() -> *mut StringList; pub fn sl_add(sl: *mut StringList, n: *mut c_char) -> c_int; pub fn sl_free(sl: *mut StringList, i: c_int); pub fn sl_find(sl: *mut StringList, n: *mut c_char) -> *mut c_char; pub fn getprogname() -> *const c_char; pub fn setprogname(progname: *const c_char); pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn(info: *mut dl_phdr_info, size: usize, data: *mut c_void) -> c_int, >, data: *mut c_void, ) -> c_int; pub fn arc4random() -> u32; pub fn arc4random_uniform(upper_bound: u32) -> u32; pub fn arc4random_buf(buf: *mut c_void, n: size_t); } #[link(name = "gnu")] extern "C" { pub fn memmem( source: *const c_void, sourceLength: size_t, search: *const c_void, searchLength: size_t, ) -> *mut c_void; pub fn pthread_getattr_np(thread: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_getname_np( thread: crate::pthread_t, buffer: *mut c_char, length: size_t, ) -> c_int; pub fn pthread_setname_np(thread: crate::pthread_t, name: *const c_char) -> c_int; } cfg_if! { if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { mod b32; pub use self::b32::*; } } cfg_if! { if #[cfg(target_arch = "x86")] { // TODO // mod x86; // pub use self::x86::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { // TODO // mod aarch64; // pub use self::aarch64::*; } } mod native; pub use self::native::*; libc/src/unix/haiku/b32.rs0000644000175000017500000000076715105742312015134 0ustar bdrungbdrungpub type time_t = i32; pub type Elf_Addr = crate::Elf32_Addr; pub type Elf_Half = crate::Elf32_Half; pub type Elf_Phdr = crate::Elf32_Phdr; s! { pub struct Elf32_Phdr { pub p_type: crate::Elf32_Word, pub p_offset: crate::Elf32_Off, pub p_vaddr: crate::Elf32_Addr, pub p_paddr: crate::Elf32_Addr, pub p_filesz: crate::Elf32_Word, pub p_memsz: crate::Elf32_Word, pub p_flags: crate::Elf32_Word, pub p_align: crate::Elf32_Word, } } libc/src/unix/haiku/x86_64.rs0000644000175000017500000002355515105742312015504 0ustar bdrungbdrunguse crate::prelude::*; s_no_extra_traits! { pub struct fpu_state { pub control: c_ushort, pub status: c_ushort, pub tag: c_ushort, pub opcode: c_ushort, pub rip: c_ulong, pub rdp: c_ulong, pub mxcsr: c_uint, pub mscsr_mask: c_uint, pub _fpreg: [[c_uchar; 8]; 16], pub _xmm: [[c_uchar; 16]; 16], pub _reserved_416_511: [c_uchar; 96], } pub struct xstate_hdr { pub bv: c_ulong, pub xcomp_bv: c_ulong, pub _reserved: [c_uchar; 48], } pub struct savefpu { pub fp_fxsave: fpu_state, pub fp_xstate: xstate_hdr, pub _fp_ymm: [[c_uchar; 16]; 16], } pub struct mcontext_t { pub rax: c_ulong, pub rbx: c_ulong, pub rcx: c_ulong, pub rdx: c_ulong, pub rdi: c_ulong, pub rsi: c_ulong, pub rbp: c_ulong, pub r8: c_ulong, pub r9: c_ulong, pub r10: c_ulong, pub r11: c_ulong, pub r12: c_ulong, pub r13: c_ulong, pub r14: c_ulong, pub r15: c_ulong, pub rsp: c_ulong, pub rip: c_ulong, pub rflags: c_ulong, pub fpu: savefpu, } pub struct ucontext_t { pub uc_link: *mut ucontext_t, pub uc_sigmask: crate::sigset_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for fpu_state { fn eq(&self, other: &fpu_state) -> bool { self.control == other.control && self.status == other.status && self.tag == other.tag && self.opcode == other.opcode && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mscsr_mask == other.mscsr_mask && self ._fpreg .iter() .zip(other._fpreg.iter()) .all(|(a, b)| a == b) && self._xmm.iter().zip(other._xmm.iter()).all(|(a, b)| a == b) && self ._reserved_416_511 .iter() .zip(other._reserved_416_511.iter()) .all(|(a, b)| a == b) } } impl Eq for fpu_state {} impl fmt::Debug for fpu_state { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fpu_state") .field("control", &self.control) .field("status", &self.status) .field("tag", &self.tag) .field("opcode", &self.opcode) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mscsr_mask", &self.mscsr_mask) // FIXME(debug): .field("_fpreg", &self._fpreg) // FIXME(debug): .field("_xmm", &self._xmm) // FIXME(debug): .field("_reserved_416_511", &self._reserved_416_511) .finish() } } impl hash::Hash for fpu_state { fn hash(&self, state: &mut H) { self.control.hash(state); self.status.hash(state); self.tag.hash(state); self.opcode.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mscsr_mask.hash(state); self._fpreg.hash(state); self._xmm.hash(state); self._reserved_416_511.hash(state); } } impl PartialEq for xstate_hdr { fn eq(&self, other: &xstate_hdr) -> bool { self.bv == other.bv && self.xcomp_bv == other.xcomp_bv && self ._reserved .iter() .zip(other._reserved.iter()) .all(|(a, b)| a == b) } } impl Eq for xstate_hdr {} impl fmt::Debug for xstate_hdr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("xstate_hdr") .field("bv", &self.bv) .field("xcomp_bv", &self.xcomp_bv) // FIXME(debug): .field("_reserved", &field._reserved) .finish() } } impl hash::Hash for xstate_hdr { fn hash(&self, state: &mut H) { self.bv.hash(state); self.xcomp_bv.hash(state); self._reserved.hash(state); } } impl PartialEq for savefpu { fn eq(&self, other: &savefpu) -> bool { self.fp_fxsave == other.fp_fxsave && self.fp_xstate == other.fp_xstate && self ._fp_ymm .iter() .zip(other._fp_ymm.iter()) .all(|(a, b)| a == b) } } impl Eq for savefpu {} impl fmt::Debug for savefpu { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("savefpu") .field("fp_fxsave", &self.fp_fxsave) .field("fp_xstate", &self.fp_xstate) // FIXME(debug): .field("_fp_ymm", &field._fp_ymm) .finish() } } impl hash::Hash for savefpu { fn hash(&self, state: &mut H) { self.fp_fxsave.hash(state); self.fp_xstate.hash(state); self._fp_ymm.hash(state); } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.rax == other.rax && self.rbx == other.rbx && self.rbx == other.rbx && self.rcx == other.rcx && self.rdx == other.rdx && self.rdi == other.rdi && self.rsi == other.rsi && self.r8 == other.r8 && self.r9 == other.r9 && self.r10 == other.r10 && self.r11 == other.r11 && self.r12 == other.r12 && self.r13 == other.r13 && self.r14 == other.r14 && self.r15 == other.r15 && self.rsp == other.rsp && self.rip == other.rip && self.rflags == other.rflags && self.fpu == other.fpu } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("rax", &self.rax) .field("rbx", &self.rbx) .field("rcx", &self.rcx) .field("rdx", &self.rdx) .field("rdi", &self.rdi) .field("rsi", &self.rsi) .field("rbp", &self.rbp) .field("r8", &self.r8) .field("r9", &self.r9) .field("r10", &self.r10) .field("r11", &self.r11) .field("r12", &self.r12) .field("r13", &self.r13) .field("r14", &self.r14) .field("r15", &self.r15) .field("rsp", &self.rsp) .field("rip", &self.rip) .field("rflags", &self.rflags) .field("fpu", &self.fpu) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.rax.hash(state); self.rbx.hash(state); self.rcx.hash(state); self.rdx.hash(state); self.rdi.hash(state); self.rsi.hash(state); self.rbp.hash(state); self.r8.hash(state); self.r9.hash(state); self.r10.hash(state); self.r11.hash(state); self.r12.hash(state); self.r13.hash(state); self.r14.hash(state); self.r15.hash(state); self.rsp.hash(state); self.rip.hash(state); self.rflags.hash(state); self.fpu.hash(state); } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_link == other.uc_link && self.uc_sigmask == other.uc_sigmask && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_link", &self.uc_link) .field("uc_sigmask", &self.uc_sigmask) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_link.hash(state); self.uc_sigmask.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); } } } } libc/src/unix/haiku/b64.rs0000644000175000017500000000077215105742312015135 0ustar bdrungbdrungpub type time_t = i64; pub type Elf_Addr = crate::Elf64_Addr; pub type Elf_Half = crate::Elf64_Half; pub type Elf_Phdr = crate::Elf64_Phdr; s! { pub struct Elf64_Phdr { pub p_type: crate::Elf64_Word, pub p_flags: crate::Elf64_Word, pub p_offset: crate::Elf64_Off, pub p_vaddr: crate::Elf64_Addr, pub p_paddr: crate::Elf64_Addr, pub p_filesz: crate::Elf64_Xword, pub p_memsz: crate::Elf64_Xword, pub p_align: crate::Elf64_Xword, } } libc/src/unix/haiku/native.rs0000644000175000017500000014611115105742312016026 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; // This module contains bindings to the native Haiku API. The Haiku API // originates from BeOS, and it was the original way to perform low level // system and IO operations. The POSIX API was in that era was like a // compatibility layer. In current Haiku development, both the POSIX API and // the Haiku API are considered to be co-equal status. However, they are not // integrated like they are on other UNIX platforms, which means that for many // low level concepts there are two versions, like processes (POSIX) and // teams (Haiku), or pthreads and native threads. // // Both the POSIX API and the Haiku API live in libroot.so, the library that is // linked to any binary by default. // // This file follows the Haiku API for Haiku R1 beta 2. It is organized by the // C/C++ header files in which the concepts can be found, while adhering to the // style guide for this crate. // Helper macro to generate u32 constants. The Haiku API uses (non-standard) // multi-character constants (like 'UPDA' or 'MSGM') to represent 32 bit // integer constants. macro_rules! haiku_constant { ($a:tt, $b:tt, $c:tt, $d:tt) => { (($a as u32) << 24) + (($b as u32) << 16) + (($c as u32) << 8) + ($d as u32) }; } // support/SupportDefs.h pub type status_t = i32; pub type bigtime_t = i64; pub type nanotime_t = i64; pub type type_code = u32; pub type perform_code = u32; // kernel/OS.h pub type area_id = i32; pub type port_id = i32; pub type sem_id = i32; pub type team_id = i32; pub type thread_id = i32; pub type thread_func = extern "C" fn(*mut c_void) -> status_t; // kernel/image.h pub type image_id = i32; e! { // kernel/OS.h pub enum thread_state { B_THREAD_RUNNING = 1, B_THREAD_READY, B_THREAD_RECEIVING, B_THREAD_ASLEEP, B_THREAD_SUSPENDED, B_THREAD_WAITING, } // kernel/image.h pub enum image_type { B_APP_IMAGE = 1, B_LIBRARY_IMAGE, B_ADD_ON_IMAGE, B_SYSTEM_IMAGE, } // kernel/scheduler.h pub enum be_task_flags { B_DEFAULT_MEDIA_PRIORITY = 0x000, B_OFFLINE_PROCESSING = 0x001, B_STATUS_RENDERING = 0x002, B_USER_INPUT_HANDLING = 0x004, B_LIVE_VIDEO_MANIPULATION = 0x008, B_VIDEO_PLAYBACK = 0x010, B_VIDEO_RECORDING = 0x020, B_LIVE_AUDIO_MANIPULATION = 0x040, B_AUDIO_PLAYBACK = 0x080, B_AUDIO_RECORDING = 0x100, B_LIVE_3D_RENDERING = 0x200, B_NUMBER_CRUNCHING = 0x400, B_MIDI_PROCESSING = 0x800, } pub enum schduler_mode { SCHEDULER_MODE_LOW_LATENCY, SCHEDULER_MODE_POWER_SAVING, } // FindDirectory.h pub enum path_base_directory { B_FIND_PATH_INSTALLATION_LOCATION_DIRECTORY, B_FIND_PATH_ADD_ONS_DIRECTORY, B_FIND_PATH_APPS_DIRECTORY, B_FIND_PATH_BIN_DIRECTORY, B_FIND_PATH_BOOT_DIRECTORY, B_FIND_PATH_CACHE_DIRECTORY, B_FIND_PATH_DATA_DIRECTORY, B_FIND_PATH_DEVELOP_DIRECTORY, B_FIND_PATH_DEVELOP_LIB_DIRECTORY, B_FIND_PATH_DOCUMENTATION_DIRECTORY, B_FIND_PATH_ETC_DIRECTORY, B_FIND_PATH_FONTS_DIRECTORY, B_FIND_PATH_HEADERS_DIRECTORY, B_FIND_PATH_LIB_DIRECTORY, B_FIND_PATH_LOG_DIRECTORY, B_FIND_PATH_MEDIA_NODES_DIRECTORY, B_FIND_PATH_PACKAGES_DIRECTORY, B_FIND_PATH_PREFERENCES_DIRECTORY, B_FIND_PATH_SERVERS_DIRECTORY, B_FIND_PATH_SETTINGS_DIRECTORY, B_FIND_PATH_SOUNDS_DIRECTORY, B_FIND_PATH_SPOOL_DIRECTORY, B_FIND_PATH_TRANSLATORS_DIRECTORY, B_FIND_PATH_VAR_DIRECTORY, B_FIND_PATH_IMAGE_PATH = 1000, B_FIND_PATH_PACKAGE_PATH, } pub enum directory_which { B_DESKTOP_DIRECTORY = 0, B_TRASH_DIRECTORY, B_SYSTEM_DIRECTORY = 1000, B_SYSTEM_ADDONS_DIRECTORY = 1002, B_SYSTEM_BOOT_DIRECTORY, B_SYSTEM_FONTS_DIRECTORY, B_SYSTEM_LIB_DIRECTORY, B_SYSTEM_SERVERS_DIRECTORY, B_SYSTEM_APPS_DIRECTORY, B_SYSTEM_BIN_DIRECTORY, B_SYSTEM_DOCUMENTATION_DIRECTORY = 1010, B_SYSTEM_PREFERENCES_DIRECTORY, B_SYSTEM_TRANSLATORS_DIRECTORY, B_SYSTEM_MEDIA_NODES_DIRECTORY, B_SYSTEM_SOUNDS_DIRECTORY, B_SYSTEM_DATA_DIRECTORY, B_SYSTEM_DEVELOP_DIRECTORY, B_SYSTEM_PACKAGES_DIRECTORY, B_SYSTEM_HEADERS_DIRECTORY, B_SYSTEM_ETC_DIRECTORY = 2008, B_SYSTEM_SETTINGS_DIRECTORY = 2010, B_SYSTEM_LOG_DIRECTORY = 2012, B_SYSTEM_SPOOL_DIRECTORY, B_SYSTEM_TEMP_DIRECTORY, B_SYSTEM_VAR_DIRECTORY, B_SYSTEM_CACHE_DIRECTORY = 2020, B_SYSTEM_NONPACKAGED_DIRECTORY = 2023, B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY, B_SYSTEM_NONPACKAGED_TRANSLATORS_DIRECTORY, B_SYSTEM_NONPACKAGED_MEDIA_NODES_DIRECTORY, B_SYSTEM_NONPACKAGED_BIN_DIRECTORY, B_SYSTEM_NONPACKAGED_DATA_DIRECTORY, B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY, B_SYSTEM_NONPACKAGED_SOUNDS_DIRECTORY, B_SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY, B_SYSTEM_NONPACKAGED_LIB_DIRECTORY, B_SYSTEM_NONPACKAGED_HEADERS_DIRECTORY, B_SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY, B_USER_DIRECTORY = 3000, B_USER_CONFIG_DIRECTORY, B_USER_ADDONS_DIRECTORY, B_USER_BOOT_DIRECTORY, B_USER_FONTS_DIRECTORY, B_USER_LIB_DIRECTORY, B_USER_SETTINGS_DIRECTORY, B_USER_DESKBAR_DIRECTORY, B_USER_PRINTERS_DIRECTORY, B_USER_TRANSLATORS_DIRECTORY, B_USER_MEDIA_NODES_DIRECTORY, B_USER_SOUNDS_DIRECTORY, B_USER_DATA_DIRECTORY, B_USER_CACHE_DIRECTORY, B_USER_PACKAGES_DIRECTORY, B_USER_HEADERS_DIRECTORY, B_USER_NONPACKAGED_DIRECTORY, B_USER_NONPACKAGED_ADDONS_DIRECTORY, B_USER_NONPACKAGED_TRANSLATORS_DIRECTORY, B_USER_NONPACKAGED_MEDIA_NODES_DIRECTORY, B_USER_NONPACKAGED_BIN_DIRECTORY, B_USER_NONPACKAGED_DATA_DIRECTORY, B_USER_NONPACKAGED_FONTS_DIRECTORY, B_USER_NONPACKAGED_SOUNDS_DIRECTORY, B_USER_NONPACKAGED_DOCUMENTATION_DIRECTORY, B_USER_NONPACKAGED_LIB_DIRECTORY, B_USER_NONPACKAGED_HEADERS_DIRECTORY, B_USER_NONPACKAGED_DEVELOP_DIRECTORY, B_USER_DEVELOP_DIRECTORY, B_USER_DOCUMENTATION_DIRECTORY, B_USER_SERVERS_DIRECTORY, B_USER_APPS_DIRECTORY, B_USER_BIN_DIRECTORY, B_USER_PREFERENCES_DIRECTORY, B_USER_ETC_DIRECTORY, B_USER_LOG_DIRECTORY, B_USER_SPOOL_DIRECTORY, B_USER_VAR_DIRECTORY, B_APPS_DIRECTORY = 4000, B_PREFERENCES_DIRECTORY, B_UTILITIES_DIRECTORY, B_PACKAGE_LINKS_DIRECTORY, } // kernel/OS.h pub enum topology_level_type { B_TOPOLOGY_UNKNOWN, B_TOPOLOGY_ROOT, B_TOPOLOGY_SMT, B_TOPOLOGY_CORE, B_TOPOLOGY_PACKAGE, } pub enum cpu_platform { B_CPU_UNKNOWN, B_CPU_x86, B_CPU_x86_64, B_CPU_PPC, B_CPU_PPC_64, B_CPU_M68K, B_CPU_ARM, B_CPU_ARM_64, B_CPU_ALPHA, B_CPU_MIPS, B_CPU_SH, B_CPU_SPARC, B_CPU_RISC_V, } pub enum cpu_vendor { B_CPU_VENDOR_UNKNOWN, B_CPU_VENDOR_AMD, B_CPU_VENDOR_CYRIX, B_CPU_VENDOR_IDT, B_CPU_VENDOR_INTEL, B_CPU_VENDOR_NATIONAL_SEMICONDUCTOR, B_CPU_VENDOR_RISE, B_CPU_VENDOR_TRANSMETA, B_CPU_VENDOR_VIA, B_CPU_VENDOR_IBM, B_CPU_VENDOR_MOTOROLA, B_CPU_VENDOR_NEC, B_CPU_VENDOR_HYGON, B_CPU_VENDOR_SUN, B_CPU_VENDOR_FUJITSU, } } s! { // kernel/OS.h pub struct area_info { pub area: area_id, pub name: [c_char; B_OS_NAME_LENGTH], pub size: usize, pub lock: u32, pub protection: u32, pub team: team_id, pub ram_size: u32, pub copy_count: u32, pub in_count: u32, pub out_count: u32, pub address: *mut c_void, } pub struct port_info { pub port: port_id, pub team: team_id, pub name: [c_char; B_OS_NAME_LENGTH], pub capacity: i32, pub queue_count: i32, pub total_count: i32, } pub struct port_message_info { pub size: size_t, pub sender: crate::uid_t, pub sender_group: crate::gid_t, pub sender_team: crate::team_id, } pub struct team_info { pub team: team_id, pub thread_count: i32, pub image_count: i32, pub area_count: i32, pub debugger_nub_thread: thread_id, pub debugger_nub_port: port_id, pub argc: i32, pub args: [c_char; 64], pub uid: crate::uid_t, pub gid: crate::gid_t, } pub struct sem_info { pub sem: sem_id, pub team: team_id, pub name: [c_char; B_OS_NAME_LENGTH], pub count: i32, pub latest_holder: thread_id, } pub struct team_usage_info { pub user_time: bigtime_t, pub kernel_time: bigtime_t, } pub struct thread_info { pub thread: thread_id, pub team: team_id, pub name: [c_char; B_OS_NAME_LENGTH], pub state: thread_state, pub priority: i32, pub sem: sem_id, pub user_time: bigtime_t, pub kernel_time: bigtime_t, pub stack_base: *mut c_void, pub stack_end: *mut c_void, } pub struct cpu_info { pub active_time: bigtime_t, pub enabled: bool, pub current_frequency: u64, } pub struct system_info { pub boot_time: bigtime_t, pub cpu_count: u32, pub max_pages: u64, pub used_pages: u64, pub cached_pages: u64, pub block_cache_pages: u64, pub ignored_pages: u64, pub needed_memory: u64, pub free_memory: u64, pub max_swap_pages: u64, pub free_swap_pages: u64, pub page_faults: u32, pub max_sems: u32, pub used_sems: u32, pub max_ports: u32, pub used_ports: u32, pub max_threads: u32, pub used_threads: u32, pub max_teams: u32, pub used_teams: u32, pub kernel_name: [c_char; B_FILE_NAME_LENGTH], pub kernel_build_date: [c_char; B_OS_NAME_LENGTH], pub kernel_build_time: [c_char; B_OS_NAME_LENGTH], pub kernel_version: i64, pub abi: u32, } pub struct object_wait_info { pub object: i32, pub type_: u16, pub events: u16, } pub struct cpu_topology_root_info { pub platform: cpu_platform, } pub struct cpu_topology_package_info { pub vendor: cpu_vendor, pub cache_line_size: u32, } pub struct cpu_topology_core_info { pub model: u32, pub default_frequency: u64, } // kernel/fs_attr.h pub struct attr_info { pub type_: u32, pub size: off_t, } // kernel/fs_index.h pub struct index_info { pub type_: u32, pub size: off_t, pub modification_time: crate::time_t, pub creation_time: crate::time_t, pub uid: crate::uid_t, pub gid: crate::gid_t, } //kernel/fs_info.h pub struct fs_info { pub dev: crate::dev_t, pub root: crate::ino_t, pub flags: u32, pub block_size: off_t, pub io_size: off_t, pub total_blocks: off_t, pub free_blocks: off_t, pub total_nodes: off_t, pub free_nodes: off_t, pub device_name: [c_char; 128], pub volume_name: [c_char; B_FILE_NAME_LENGTH], pub fsh_name: [c_char; B_OS_NAME_LENGTH], } // kernel/image.h pub struct image_info { pub id: image_id, pub image_type: c_int, pub sequence: i32, pub init_order: i32, pub init_routine: extern "C" fn(), pub term_routine: extern "C" fn(), pub device: crate::dev_t, pub node: crate::ino_t, pub name: [c_char; crate::PATH_MAX as usize], pub text: *mut c_void, pub data: *mut c_void, pub text_size: i32, pub data_size: i32, pub api_version: i32, pub abi: i32, } pub struct __c_anonymous_eax_0 { pub max_eax: u32, pub vendor_id: [c_char; 12], } pub struct __c_anonymous_eax_1 { pub stepping: u32, pub model: u32, pub family: u32, pub tpe: u32, __reserved_0: u32, pub extended_model: u32, pub extended_family: u32, __reserved_1: u32, pub brand_index: u32, pub clflush: u32, pub logical_cpus: u32, pub apic_id: u32, pub features: u32, pub extended_features: u32, } pub struct __c_anonymous_eax_2 { pub call_num: u8, pub cache_descriptors: [u8; 15], } pub struct __c_anonymous_eax_3 { __reserved: [u32; 2], pub serial_number_high: u32, pub serial_number_low: u32, } pub struct __c_anonymous_regs { pub eax: u32, pub ebx: u32, pub edx: u32, pub ecx: u32, } } s_no_extra_traits! { pub union cpuid_info { pub eax_0: __c_anonymous_eax_0, pub eax_1: __c_anonymous_eax_1, pub eax_2: __c_anonymous_eax_2, pub eax_3: __c_anonymous_eax_3, pub as_chars: [c_char; 16], pub regs: __c_anonymous_regs, } pub union __c_anonymous_cpu_topology_info_data { pub root: cpu_topology_root_info, pub package: cpu_topology_package_info, pub core: cpu_topology_core_info, } pub struct cpu_topology_node_info { pub id: u32, pub type_: topology_level_type, pub level: u32, pub data: __c_anonymous_cpu_topology_info_data, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for cpuid_info { fn eq(&self, other: &cpuid_info) -> bool { unsafe { self.eax_0 == other.eax_0 || self.eax_1 == other.eax_1 || self.eax_2 == other.eax_2 || self.eax_3 == other.eax_3 || self.as_chars == other.as_chars || self.regs == other.regs } } } impl Eq for cpuid_info {} impl PartialEq for __c_anonymous_cpu_topology_info_data { fn eq(&self, other: &__c_anonymous_cpu_topology_info_data) -> bool { unsafe { self.root == other.root || self.package == other.package || self.core == other.core } } } impl Eq for __c_anonymous_cpu_topology_info_data {} impl PartialEq for cpu_topology_node_info { fn eq(&self, other: &cpu_topology_node_info) -> bool { self.id == other.id && self.type_ == other.type_ && self.level == other.level } } impl Eq for cpu_topology_node_info {} impl fmt::Debug for cpu_topology_node_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("cpu_topology_node_info") .field("id", &self.id) .field("type", &self.type_) .field("level", &self.level) .finish() } } } } // kernel/OS.h pub const B_OS_NAME_LENGTH: usize = 32; pub const B_PAGE_SIZE: usize = 4096; pub const B_INFINITE_TIMEOUT: usize = 9223372036854775807; pub const B_RELATIVE_TIMEOUT: u32 = 0x8; pub const B_ABSOLUTE_TIMEOUT: u32 = 0x10; pub const B_TIMEOUT_REAL_TIME_BASE: u32 = 0x40; pub const B_ABSOLUTE_REAL_TIME_TIMEOUT: u32 = B_ABSOLUTE_TIMEOUT | B_TIMEOUT_REAL_TIME_BASE; pub const B_NO_LOCK: u32 = 0; pub const B_LAZY_LOCK: u32 = 1; pub const B_FULL_LOCK: u32 = 2; pub const B_CONTIGUOUS: u32 = 3; pub const B_LOMEM: u32 = 4; pub const B_32_BIT_FULL_LOCK: u32 = 5; pub const B_32_BIT_CONTIGUOUS: u32 = 6; pub const B_ANY_ADDRESS: u32 = 0; pub const B_EXACT_ADDRESS: u32 = 1; pub const B_BASE_ADDRESS: u32 = 2; pub const B_CLONE_ADDRESS: u32 = 3; pub const B_ANY_KERNEL_ADDRESS: u32 = 4; pub const B_RANDOMIZED_ANY_ADDRESS: u32 = 6; pub const B_RANDOMIZED_BASE_ADDRESS: u32 = 7; pub const B_READ_AREA: u32 = 1 << 0; pub const B_WRITE_AREA: u32 = 1 << 1; pub const B_EXECUTE_AREA: u32 = 1 << 2; pub const B_STACK_AREA: u32 = 1 << 3; pub const B_CLONEABLE_AREA: u32 = 1 << 8; pub const B_CAN_INTERRUPT: u32 = 0x01; pub const B_CHECK_PERMISSION: u32 = 0x04; pub const B_KILL_CAN_INTERRUPT: u32 = 0x20; pub const B_DO_NOT_RESCHEDULE: u32 = 0x02; pub const B_RELEASE_ALL: u32 = 0x08; pub const B_RELEASE_IF_WAITING_ONLY: u32 = 0x10; pub const B_CURRENT_TEAM: team_id = 0; pub const B_SYSTEM_TEAM: team_id = 1; pub const B_TEAM_USAGE_SELF: i32 = 0; pub const B_TEAM_USAGE_CHILDREN: i32 = -1; pub const B_IDLE_PRIORITY: i32 = 0; pub const B_LOWEST_ACTIVE_PRIORITY: i32 = 1; pub const B_LOW_PRIORITY: i32 = 5; pub const B_NORMAL_PRIORITY: i32 = 10; pub const B_DISPLAY_PRIORITY: i32 = 15; pub const B_URGENT_DISPLAY_PRIORITY: i32 = 20; pub const B_REAL_TIME_DISPLAY_PRIORITY: i32 = 100; pub const B_URGENT_PRIORITY: i32 = 110; pub const B_REAL_TIME_PRIORITY: i32 = 120; pub const B_SYSTEM_TIMEBASE: i32 = 0; pub const B_FIRST_REAL_TIME_PRIORITY: i32 = B_REAL_TIME_DISPLAY_PRIORITY; pub const B_ONE_SHOT_ABSOLUTE_ALARM: u32 = 1; pub const B_ONE_SHOT_RELATIVE_ALARM: u32 = 2; pub const B_PERIODIC_ALARM: u32 = 3; pub const B_OBJECT_TYPE_FD: u16 = 0; pub const B_OBJECT_TYPE_SEMAPHORE: u16 = 1; pub const B_OBJECT_TYPE_PORT: u16 = 2; pub const B_OBJECT_TYPE_THREAD: u16 = 3; pub const B_EVENT_READ: u16 = 0x0001; pub const B_EVENT_WRITE: u16 = 0x0002; pub const B_EVENT_ERROR: u16 = 0x0004; pub const B_EVENT_PRIORITY_READ: u16 = 0x0008; pub const B_EVENT_PRIORITY_WRITE: u16 = 0x0010; pub const B_EVENT_HIGH_PRIORITY_READ: u16 = 0x0020; pub const B_EVENT_HIGH_PRIORITY_WRITE: u16 = 0x0040; pub const B_EVENT_DISCONNECTED: u16 = 0x0080; pub const B_EVENT_ACQUIRE_SEMAPHORE: u16 = 0x0001; pub const B_EVENT_INVALID: u16 = 0x1000; // kernel/fs_info.h pub const B_FS_IS_READONLY: u32 = 0x00000001; pub const B_FS_IS_REMOVABLE: u32 = 0x00000002; pub const B_FS_IS_PERSISTENT: u32 = 0x00000004; pub const B_FS_IS_SHARED: u32 = 0x00000008; pub const B_FS_HAS_MIME: u32 = 0x00010000; pub const B_FS_HAS_ATTR: u32 = 0x00020000; pub const B_FS_HAS_QUERY: u32 = 0x00040000; pub const B_FS_HAS_SELF_HEALING_LINKS: u32 = 0x00080000; pub const B_FS_HAS_ALIASES: u32 = 0x00100000; pub const B_FS_SUPPORTS_NODE_MONITORING: u32 = 0x00200000; pub const B_FS_SUPPORTS_MONITOR_CHILDREN: u32 = 0x00400000; // kernel/fs_query.h pub const B_LIVE_QUERY: u32 = 0x00000001; pub const B_QUERY_NON_INDEXED: u32 = 0x00000002; // kernel/fs_volume.h pub const B_MOUNT_READ_ONLY: u32 = 1; pub const B_MOUNT_VIRTUAL_DEVICE: u32 = 2; pub const B_FORCE_UNMOUNT: u32 = 1; // kernel/image.h pub const B_FLUSH_DCACHE: u32 = 0x0001; pub const B_FLUSH_ICACHE: u32 = 0x0004; pub const B_INVALIDATE_DCACHE: u32 = 0x0002; pub const B_INVALIDATE_ICACHE: u32 = 0x0008; pub const B_SYMBOL_TYPE_DATA: i32 = 0x1; pub const B_SYMBOL_TYPE_TEXT: i32 = 0x2; pub const B_SYMBOL_TYPE_ANY: i32 = 0x5; // storage/StorageDefs.h pub const B_DEV_NAME_LENGTH: usize = 128; pub const B_FILE_NAME_LENGTH: usize = crate::FILENAME_MAX as usize; pub const B_PATH_NAME_LENGTH: usize = crate::PATH_MAX as usize; pub const B_ATTR_NAME_LENGTH: usize = B_FILE_NAME_LENGTH - 1; pub const B_MIME_TYPE_LENGTH: usize = B_ATTR_NAME_LENGTH - 15; pub const B_MAX_SYMLINKS: usize = 16; // Haiku open modes in BFile are passed as u32 pub const B_READ_ONLY: u32 = crate::O_RDONLY as u32; pub const B_WRITE_ONLY: u32 = crate::O_WRONLY as u32; pub const B_READ_WRITE: u32 = crate::O_RDWR as u32; pub const B_FAIL_IF_EXISTS: u32 = crate::O_EXCL as u32; pub const B_CREATE_FILE: u32 = crate::O_CREAT as u32; pub const B_ERASE_FILE: u32 = crate::O_TRUNC as u32; pub const B_OPEN_AT_END: u32 = crate::O_APPEND as u32; pub const B_FILE_NODE: u32 = 0x01; pub const B_SYMLINK_NODE: u32 = 0x02; pub const B_DIRECTORY_NODE: u32 = 0x04; pub const B_ANY_NODE: u32 = 0x07; // support/Errors.h pub const B_GENERAL_ERROR_BASE: status_t = core::i32::MIN; pub const B_OS_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x1000; pub const B_APP_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x2000; pub const B_INTERFACE_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x3000; pub const B_MEDIA_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x4000; pub const B_TRANSLATION_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x4800; pub const B_MIDI_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x5000; pub const B_STORAGE_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x6000; pub const B_POSIX_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x7000; pub const B_MAIL_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x8000; pub const B_PRINT_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x9000; pub const B_DEVICE_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0xa000; pub const B_ERRORS_END: status_t = B_GENERAL_ERROR_BASE + 0xffff; // General errors pub const B_NO_MEMORY: status_t = B_GENERAL_ERROR_BASE + 0; pub const B_IO_ERROR: status_t = B_GENERAL_ERROR_BASE + 1; pub const B_PERMISSION_DENIED: status_t = B_GENERAL_ERROR_BASE + 2; pub const B_BAD_INDEX: status_t = B_GENERAL_ERROR_BASE + 3; pub const B_BAD_TYPE: status_t = B_GENERAL_ERROR_BASE + 4; pub const B_BAD_VALUE: status_t = B_GENERAL_ERROR_BASE + 5; pub const B_MISMATCHED_VALUES: status_t = B_GENERAL_ERROR_BASE + 6; pub const B_NAME_NOT_FOUND: status_t = B_GENERAL_ERROR_BASE + 7; pub const B_NAME_IN_USE: status_t = B_GENERAL_ERROR_BASE + 8; pub const B_TIMED_OUT: status_t = B_GENERAL_ERROR_BASE + 9; pub const B_INTERRUPTED: status_t = B_GENERAL_ERROR_BASE + 10; pub const B_WOULD_BLOCK: status_t = B_GENERAL_ERROR_BASE + 11; pub const B_CANCELED: status_t = B_GENERAL_ERROR_BASE + 12; pub const B_NO_INIT: status_t = B_GENERAL_ERROR_BASE + 13; pub const B_NOT_INITIALIZED: status_t = B_GENERAL_ERROR_BASE + 13; pub const B_BUSY: status_t = B_GENERAL_ERROR_BASE + 14; pub const B_NOT_ALLOWED: status_t = B_GENERAL_ERROR_BASE + 15; pub const B_BAD_DATA: status_t = B_GENERAL_ERROR_BASE + 16; pub const B_DONT_DO_THAT: status_t = B_GENERAL_ERROR_BASE + 17; pub const B_ERROR: status_t = -1; pub const B_OK: status_t = 0; pub const B_NO_ERROR: status_t = 0; // Kernel kit errors pub const B_BAD_SEM_ID: status_t = B_OS_ERROR_BASE + 0; pub const B_NO_MORE_SEMS: status_t = B_OS_ERROR_BASE + 1; pub const B_BAD_THREAD_ID: status_t = B_OS_ERROR_BASE + 0x100; pub const B_NO_MORE_THREADS: status_t = B_OS_ERROR_BASE + 0x101; pub const B_BAD_THREAD_STATE: status_t = B_OS_ERROR_BASE + 0x102; pub const B_BAD_TEAM_ID: status_t = B_OS_ERROR_BASE + 0x103; pub const B_NO_MORE_TEAMS: status_t = B_OS_ERROR_BASE + 0x104; pub const B_BAD_PORT_ID: status_t = B_OS_ERROR_BASE + 0x200; pub const B_NO_MORE_PORTS: status_t = B_OS_ERROR_BASE + 0x201; pub const B_BAD_IMAGE_ID: status_t = B_OS_ERROR_BASE + 0x300; pub const B_BAD_ADDRESS: status_t = B_OS_ERROR_BASE + 0x301; pub const B_NOT_AN_EXECUTABLE: status_t = B_OS_ERROR_BASE + 0x302; pub const B_MISSING_LIBRARY: status_t = B_OS_ERROR_BASE + 0x303; pub const B_MISSING_SYMBOL: status_t = B_OS_ERROR_BASE + 0x304; pub const B_UNKNOWN_EXECUTABLE: status_t = B_OS_ERROR_BASE + 0x305; pub const B_LEGACY_EXECUTABLE: status_t = B_OS_ERROR_BASE + 0x306; pub const B_DEBUGGER_ALREADY_INSTALLED: status_t = B_OS_ERROR_BASE + 0x400; // Application kit errors pub const B_BAD_REPLY: status_t = B_APP_ERROR_BASE + 0; pub const B_DUPLICATE_REPLY: status_t = B_APP_ERROR_BASE + 1; pub const B_MESSAGE_TO_SELF: status_t = B_APP_ERROR_BASE + 2; pub const B_BAD_HANDLER: status_t = B_APP_ERROR_BASE + 3; pub const B_ALREADY_RUNNING: status_t = B_APP_ERROR_BASE + 4; pub const B_LAUNCH_FAILED: status_t = B_APP_ERROR_BASE + 5; pub const B_AMBIGUOUS_APP_LAUNCH: status_t = B_APP_ERROR_BASE + 6; pub const B_UNKNOWN_MIME_TYPE: status_t = B_APP_ERROR_BASE + 7; pub const B_BAD_SCRIPT_SYNTAX: status_t = B_APP_ERROR_BASE + 8; pub const B_LAUNCH_FAILED_NO_RESOLVE_LINK: status_t = B_APP_ERROR_BASE + 9; pub const B_LAUNCH_FAILED_EXECUTABLE: status_t = B_APP_ERROR_BASE + 10; pub const B_LAUNCH_FAILED_APP_NOT_FOUND: status_t = B_APP_ERROR_BASE + 11; pub const B_LAUNCH_FAILED_APP_IN_TRASH: status_t = B_APP_ERROR_BASE + 12; pub const B_LAUNCH_FAILED_NO_PREFERRED_APP: status_t = B_APP_ERROR_BASE + 13; pub const B_LAUNCH_FAILED_FILES_APP_NOT_FOUND: status_t = B_APP_ERROR_BASE + 14; pub const B_BAD_MIME_SNIFFER_RULE: status_t = B_APP_ERROR_BASE + 15; pub const B_NOT_A_MESSAGE: status_t = B_APP_ERROR_BASE + 16; pub const B_SHUTDOWN_CANCELLED: status_t = B_APP_ERROR_BASE + 17; pub const B_SHUTTING_DOWN: status_t = B_APP_ERROR_BASE + 18; // Storage kit errors pub const B_FILE_ERROR: status_t = B_STORAGE_ERROR_BASE + 0; pub const B_FILE_EXISTS: status_t = B_STORAGE_ERROR_BASE + 2; pub const B_ENTRY_NOT_FOUND: status_t = B_STORAGE_ERROR_BASE + 3; pub const B_NAME_TOO_LONG: status_t = B_STORAGE_ERROR_BASE + 4; pub const B_NOT_A_DIRECTORY: status_t = B_STORAGE_ERROR_BASE + 5; pub const B_DIRECTORY_NOT_EMPTY: status_t = B_STORAGE_ERROR_BASE + 6; pub const B_DEVICE_FULL: status_t = B_STORAGE_ERROR_BASE + 7; pub const B_READ_ONLY_DEVICE: status_t = B_STORAGE_ERROR_BASE + 8; pub const B_IS_A_DIRECTORY: status_t = B_STORAGE_ERROR_BASE + 9; pub const B_NO_MORE_FDS: status_t = B_STORAGE_ERROR_BASE + 10; pub const B_CROSS_DEVICE_LINK: status_t = B_STORAGE_ERROR_BASE + 11; pub const B_LINK_LIMIT: status_t = B_STORAGE_ERROR_BASE + 12; pub const B_BUSTED_PIPE: status_t = B_STORAGE_ERROR_BASE + 13; pub const B_UNSUPPORTED: status_t = B_STORAGE_ERROR_BASE + 14; pub const B_PARTITION_TOO_SMALL: status_t = B_STORAGE_ERROR_BASE + 15; pub const B_PARTIAL_READ: status_t = B_STORAGE_ERROR_BASE + 16; pub const B_PARTIAL_WRITE: status_t = B_STORAGE_ERROR_BASE + 17; // Mapped posix errors pub const B_BUFFER_OVERFLOW: status_t = crate::EOVERFLOW; pub const B_TOO_MANY_ARGS: status_t = crate::E2BIG; pub const B_FILE_TOO_LARGE: status_t = crate::EFBIG; pub const B_RESULT_NOT_REPRESENTABLE: status_t = crate::ERANGE; pub const B_DEVICE_NOT_FOUND: status_t = crate::ENODEV; pub const B_NOT_SUPPORTED: status_t = crate::EOPNOTSUPP; // Media kit errors pub const B_STREAM_NOT_FOUND: status_t = B_MEDIA_ERROR_BASE + 0; pub const B_SERVER_NOT_FOUND: status_t = B_MEDIA_ERROR_BASE + 1; pub const B_RESOURCE_NOT_FOUND: status_t = B_MEDIA_ERROR_BASE + 2; pub const B_RESOURCE_UNAVAILABLE: status_t = B_MEDIA_ERROR_BASE + 3; pub const B_BAD_SUBSCRIBER: status_t = B_MEDIA_ERROR_BASE + 4; pub const B_SUBSCRIBER_NOT_ENTERED: status_t = B_MEDIA_ERROR_BASE + 5; pub const B_BUFFER_NOT_AVAILABLE: status_t = B_MEDIA_ERROR_BASE + 6; pub const B_LAST_BUFFER_ERROR: status_t = B_MEDIA_ERROR_BASE + 7; pub const B_MEDIA_SYSTEM_FAILURE: status_t = B_MEDIA_ERROR_BASE + 100; pub const B_MEDIA_BAD_NODE: status_t = B_MEDIA_ERROR_BASE + 101; pub const B_MEDIA_NODE_BUSY: status_t = B_MEDIA_ERROR_BASE + 102; pub const B_MEDIA_BAD_FORMAT: status_t = B_MEDIA_ERROR_BASE + 103; pub const B_MEDIA_BAD_BUFFER: status_t = B_MEDIA_ERROR_BASE + 104; pub const B_MEDIA_TOO_MANY_NODES: status_t = B_MEDIA_ERROR_BASE + 105; pub const B_MEDIA_TOO_MANY_BUFFERS: status_t = B_MEDIA_ERROR_BASE + 106; pub const B_MEDIA_NODE_ALREADY_EXISTS: status_t = B_MEDIA_ERROR_BASE + 107; pub const B_MEDIA_BUFFER_ALREADY_EXISTS: status_t = B_MEDIA_ERROR_BASE + 108; pub const B_MEDIA_CANNOT_SEEK: status_t = B_MEDIA_ERROR_BASE + 109; pub const B_MEDIA_CANNOT_CHANGE_RUN_MODE: status_t = B_MEDIA_ERROR_BASE + 110; pub const B_MEDIA_APP_ALREADY_REGISTERED: status_t = B_MEDIA_ERROR_BASE + 111; pub const B_MEDIA_APP_NOT_REGISTERED: status_t = B_MEDIA_ERROR_BASE + 112; pub const B_MEDIA_CANNOT_RECLAIM_BUFFERS: status_t = B_MEDIA_ERROR_BASE + 113; pub const B_MEDIA_BUFFERS_NOT_RECLAIMED: status_t = B_MEDIA_ERROR_BASE + 114; pub const B_MEDIA_TIME_SOURCE_STOPPED: status_t = B_MEDIA_ERROR_BASE + 115; pub const B_MEDIA_TIME_SOURCE_BUSY: status_t = B_MEDIA_ERROR_BASE + 116; pub const B_MEDIA_BAD_SOURCE: status_t = B_MEDIA_ERROR_BASE + 117; pub const B_MEDIA_BAD_DESTINATION: status_t = B_MEDIA_ERROR_BASE + 118; pub const B_MEDIA_ALREADY_CONNECTED: status_t = B_MEDIA_ERROR_BASE + 119; pub const B_MEDIA_NOT_CONNECTED: status_t = B_MEDIA_ERROR_BASE + 120; pub const B_MEDIA_BAD_CLIP_FORMAT: status_t = B_MEDIA_ERROR_BASE + 121; pub const B_MEDIA_ADDON_FAILED: status_t = B_MEDIA_ERROR_BASE + 122; pub const B_MEDIA_ADDON_DISABLED: status_t = B_MEDIA_ERROR_BASE + 123; pub const B_MEDIA_CHANGE_IN_PROGRESS: status_t = B_MEDIA_ERROR_BASE + 124; pub const B_MEDIA_STALE_CHANGE_COUNT: status_t = B_MEDIA_ERROR_BASE + 125; pub const B_MEDIA_ADDON_RESTRICTED: status_t = B_MEDIA_ERROR_BASE + 126; pub const B_MEDIA_NO_HANDLER: status_t = B_MEDIA_ERROR_BASE + 127; pub const B_MEDIA_DUPLICATE_FORMAT: status_t = B_MEDIA_ERROR_BASE + 128; pub const B_MEDIA_REALTIME_DISABLED: status_t = B_MEDIA_ERROR_BASE + 129; pub const B_MEDIA_REALTIME_UNAVAILABLE: status_t = B_MEDIA_ERROR_BASE + 130; // Mail kit errors pub const B_MAIL_NO_DAEMON: status_t = B_MAIL_ERROR_BASE + 0; pub const B_MAIL_UNKNOWN_USER: status_t = B_MAIL_ERROR_BASE + 1; pub const B_MAIL_WRONG_PASSWORD: status_t = B_MAIL_ERROR_BASE + 2; pub const B_MAIL_UNKNOWN_HOST: status_t = B_MAIL_ERROR_BASE + 3; pub const B_MAIL_ACCESS_ERROR: status_t = B_MAIL_ERROR_BASE + 4; pub const B_MAIL_UNKNOWN_FIELD: status_t = B_MAIL_ERROR_BASE + 5; pub const B_MAIL_NO_RECIPIENT: status_t = B_MAIL_ERROR_BASE + 6; pub const B_MAIL_INVALID_MAIL: status_t = B_MAIL_ERROR_BASE + 7; // Print kit errors pub const B_NO_PRINT_SERVER: status_t = B_PRINT_ERROR_BASE + 0; // Device kit errors pub const B_DEV_INVALID_IOCTL: status_t = B_DEVICE_ERROR_BASE + 0; pub const B_DEV_NO_MEMORY: status_t = B_DEVICE_ERROR_BASE + 1; pub const B_DEV_BAD_DRIVE_NUM: status_t = B_DEVICE_ERROR_BASE + 2; pub const B_DEV_NO_MEDIA: status_t = B_DEVICE_ERROR_BASE + 3; pub const B_DEV_UNREADABLE: status_t = B_DEVICE_ERROR_BASE + 4; pub const B_DEV_FORMAT_ERROR: status_t = B_DEVICE_ERROR_BASE + 5; pub const B_DEV_TIMEOUT: status_t = B_DEVICE_ERROR_BASE + 6; pub const B_DEV_RECALIBRATE_ERROR: status_t = B_DEVICE_ERROR_BASE + 7; pub const B_DEV_SEEK_ERROR: status_t = B_DEVICE_ERROR_BASE + 8; pub const B_DEV_ID_ERROR: status_t = B_DEVICE_ERROR_BASE + 9; pub const B_DEV_READ_ERROR: status_t = B_DEVICE_ERROR_BASE + 10; pub const B_DEV_WRITE_ERROR: status_t = B_DEVICE_ERROR_BASE + 11; pub const B_DEV_NOT_READY: status_t = B_DEVICE_ERROR_BASE + 12; pub const B_DEV_MEDIA_CHANGED: status_t = B_DEVICE_ERROR_BASE + 13; pub const B_DEV_MEDIA_CHANGE_REQUESTED: status_t = B_DEVICE_ERROR_BASE + 14; pub const B_DEV_RESOURCE_CONFLICT: status_t = B_DEVICE_ERROR_BASE + 15; pub const B_DEV_CONFIGURATION_ERROR: status_t = B_DEVICE_ERROR_BASE + 16; pub const B_DEV_DISABLED_BY_USER: status_t = B_DEVICE_ERROR_BASE + 17; pub const B_DEV_DOOR_OPEN: status_t = B_DEVICE_ERROR_BASE + 18; pub const B_DEV_INVALID_PIPE: status_t = B_DEVICE_ERROR_BASE + 19; pub const B_DEV_CRC_ERROR: status_t = B_DEVICE_ERROR_BASE + 20; pub const B_DEV_STALLED: status_t = B_DEVICE_ERROR_BASE + 21; pub const B_DEV_BAD_PID: status_t = B_DEVICE_ERROR_BASE + 22; pub const B_DEV_UNEXPECTED_PID: status_t = B_DEVICE_ERROR_BASE + 23; pub const B_DEV_DATA_OVERRUN: status_t = B_DEVICE_ERROR_BASE + 24; pub const B_DEV_DATA_UNDERRUN: status_t = B_DEVICE_ERROR_BASE + 25; pub const B_DEV_FIFO_OVERRUN: status_t = B_DEVICE_ERROR_BASE + 26; pub const B_DEV_FIFO_UNDERRUN: status_t = B_DEVICE_ERROR_BASE + 27; pub const B_DEV_PENDING: status_t = B_DEVICE_ERROR_BASE + 28; pub const B_DEV_MULTIPLE_ERRORS: status_t = B_DEVICE_ERROR_BASE + 29; pub const B_DEV_TOO_LATE: status_t = B_DEVICE_ERROR_BASE + 30; // translation kit errors pub const B_TRANSLATION_BASE_ERROR: status_t = B_TRANSLATION_ERROR_BASE + 0; pub const B_NO_TRANSLATOR: status_t = B_TRANSLATION_ERROR_BASE + 1; pub const B_ILLEGAL_DATA: status_t = B_TRANSLATION_ERROR_BASE + 2; // support/TypeConstants.h pub const B_AFFINE_TRANSFORM_TYPE: u32 = haiku_constant!('A', 'M', 'T', 'X'); pub const B_ALIGNMENT_TYPE: u32 = haiku_constant!('A', 'L', 'G', 'N'); pub const B_ANY_TYPE: u32 = haiku_constant!('A', 'N', 'Y', 'T'); pub const B_ATOM_TYPE: u32 = haiku_constant!('A', 'T', 'O', 'M'); pub const B_ATOMREF_TYPE: u32 = haiku_constant!('A', 'T', 'M', 'R'); pub const B_BOOL_TYPE: u32 = haiku_constant!('B', 'O', 'O', 'L'); pub const B_CHAR_TYPE: u32 = haiku_constant!('C', 'H', 'A', 'R'); pub const B_COLOR_8_BIT_TYPE: u32 = haiku_constant!('C', 'L', 'R', 'B'); pub const B_DOUBLE_TYPE: u32 = haiku_constant!('D', 'B', 'L', 'E'); pub const B_FLOAT_TYPE: u32 = haiku_constant!('F', 'L', 'O', 'T'); pub const B_GRAYSCALE_8_BIT_TYPE: u32 = haiku_constant!('G', 'R', 'Y', 'B'); pub const B_INT16_TYPE: u32 = haiku_constant!('S', 'H', 'R', 'T'); pub const B_INT32_TYPE: u32 = haiku_constant!('L', 'O', 'N', 'G'); pub const B_INT64_TYPE: u32 = haiku_constant!('L', 'L', 'N', 'G'); pub const B_INT8_TYPE: u32 = haiku_constant!('B', 'Y', 'T', 'E'); pub const B_LARGE_ICON_TYPE: u32 = haiku_constant!('I', 'C', 'O', 'N'); pub const B_MEDIA_PARAMETER_GROUP_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'G'); pub const B_MEDIA_PARAMETER_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'T'); pub const B_MEDIA_PARAMETER_WEB_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'W'); pub const B_MESSAGE_TYPE: u32 = haiku_constant!('M', 'S', 'G', 'G'); pub const B_MESSENGER_TYPE: u32 = haiku_constant!('M', 'S', 'N', 'G'); pub const B_MIME_TYPE: u32 = haiku_constant!('M', 'I', 'M', 'E'); pub const B_MINI_ICON_TYPE: u32 = haiku_constant!('M', 'I', 'C', 'N'); pub const B_MONOCHROME_1_BIT_TYPE: u32 = haiku_constant!('M', 'N', 'O', 'B'); pub const B_OBJECT_TYPE: u32 = haiku_constant!('O', 'P', 'T', 'R'); pub const B_OFF_T_TYPE: u32 = haiku_constant!('O', 'F', 'F', 'T'); pub const B_PATTERN_TYPE: u32 = haiku_constant!('P', 'A', 'T', 'N'); pub const B_POINTER_TYPE: u32 = haiku_constant!('P', 'N', 'T', 'R'); pub const B_POINT_TYPE: u32 = haiku_constant!('B', 'P', 'N', 'T'); pub const B_PROPERTY_INFO_TYPE: u32 = haiku_constant!('S', 'C', 'T', 'D'); pub const B_RAW_TYPE: u32 = haiku_constant!('R', 'A', 'W', 'T'); pub const B_RECT_TYPE: u32 = haiku_constant!('R', 'E', 'C', 'T'); pub const B_REF_TYPE: u32 = haiku_constant!('R', 'R', 'E', 'F'); pub const B_RGB_32_BIT_TYPE: u32 = haiku_constant!('R', 'G', 'B', 'B'); pub const B_RGB_COLOR_TYPE: u32 = haiku_constant!('R', 'G', 'B', 'C'); pub const B_SIZE_TYPE: u32 = haiku_constant!('S', 'I', 'Z', 'E'); pub const B_SIZE_T_TYPE: u32 = haiku_constant!('S', 'I', 'Z', 'T'); pub const B_SSIZE_T_TYPE: u32 = haiku_constant!('S', 'S', 'Z', 'T'); pub const B_STRING_TYPE: u32 = haiku_constant!('C', 'S', 'T', 'R'); pub const B_STRING_LIST_TYPE: u32 = haiku_constant!('S', 'T', 'R', 'L'); pub const B_TIME_TYPE: u32 = haiku_constant!('T', 'I', 'M', 'E'); pub const B_UINT16_TYPE: u32 = haiku_constant!('U', 'S', 'H', 'T'); pub const B_UINT32_TYPE: u32 = haiku_constant!('U', 'L', 'N', 'G'); pub const B_UINT64_TYPE: u32 = haiku_constant!('U', 'L', 'L', 'G'); pub const B_UINT8_TYPE: u32 = haiku_constant!('U', 'B', 'Y', 'T'); pub const B_VECTOR_ICON_TYPE: u32 = haiku_constant!('V', 'I', 'C', 'N'); pub const B_XATTR_TYPE: u32 = haiku_constant!('X', 'A', 'T', 'R'); pub const B_NETWORK_ADDRESS_TYPE: u32 = haiku_constant!('N', 'W', 'A', 'D'); pub const B_MIME_STRING_TYPE: u32 = haiku_constant!('M', 'I', 'M', 'S'); pub const B_ASCII_TYPE: u32 = haiku_constant!('T', 'E', 'X', 'T'); pub const B_APP_IMAGE_SYMBOL: *const c_void = core::ptr::null(); extern "C" { // kernel/OS.h pub fn create_area( name: *const c_char, startAddress: *mut *mut c_void, addressSpec: u32, size: usize, lock: u32, protection: u32, ) -> area_id; pub fn clone_area( name: *const c_char, destAddress: *mut *mut c_void, addressSpec: u32, protection: u32, source: area_id, ) -> area_id; pub fn find_area(name: *const c_char) -> area_id; pub fn area_for(address: *mut c_void) -> area_id; pub fn delete_area(id: area_id) -> status_t; pub fn resize_area(id: area_id, newSize: usize) -> status_t; pub fn set_area_protection(id: area_id, newProtection: u32) -> status_t; pub fn _get_area_info(id: area_id, areaInfo: *mut area_info, size: usize) -> status_t; pub fn _get_next_area_info( team: team_id, cookie: *mut isize, areaInfo: *mut area_info, size: usize, ) -> status_t; pub fn create_port(capacity: i32, name: *const c_char) -> port_id; pub fn find_port(name: *const c_char) -> port_id; pub fn read_port( port: port_id, code: *mut i32, buffer: *mut c_void, bufferSize: size_t, ) -> ssize_t; pub fn read_port_etc( port: port_id, code: *mut i32, buffer: *mut c_void, bufferSize: size_t, flags: u32, timeout: bigtime_t, ) -> ssize_t; pub fn write_port( port: port_id, code: i32, buffer: *const c_void, bufferSize: size_t, ) -> status_t; pub fn write_port_etc( port: port_id, code: i32, buffer: *const c_void, bufferSize: size_t, flags: u32, timeout: bigtime_t, ) -> status_t; pub fn close_port(port: port_id) -> status_t; pub fn delete_port(port: port_id) -> status_t; pub fn port_buffer_size(port: port_id) -> ssize_t; pub fn port_buffer_size_etc(port: port_id, flags: u32, timeout: bigtime_t) -> ssize_t; pub fn port_count(port: port_id) -> ssize_t; pub fn set_port_owner(port: port_id, team: team_id) -> status_t; pub fn _get_port_info(port: port_id, buf: *mut port_info, portInfoSize: size_t) -> status_t; pub fn _get_next_port_info( port: port_id, cookie: *mut i32, portInfo: *mut port_info, portInfoSize: size_t, ) -> status_t; pub fn _get_port_message_info_etc( port: port_id, info: *mut port_message_info, infoSize: size_t, flags: u32, timeout: bigtime_t, ) -> status_t; pub fn create_sem(count: i32, name: *const c_char) -> sem_id; pub fn delete_sem(id: sem_id) -> status_t; pub fn acquire_sem(id: sem_id) -> status_t; pub fn acquire_sem_etc(id: sem_id, count: i32, flags: u32, timeout: bigtime_t) -> status_t; pub fn release_sem(id: sem_id) -> status_t; pub fn release_sem_etc(id: sem_id, count: i32, flags: u32) -> status_t; pub fn switch_sem(semToBeReleased: sem_id, id: sem_id) -> status_t; pub fn switch_sem_etc( semToBeReleased: sem_id, id: sem_id, count: i32, flags: u32, timeout: bigtime_t, ) -> status_t; pub fn get_sem_count(id: sem_id, threadCount: *mut i32) -> status_t; pub fn set_sem_owner(id: sem_id, team: team_id) -> status_t; pub fn _get_sem_info(id: sem_id, info: *mut sem_info, infoSize: size_t) -> status_t; pub fn _get_next_sem_info( team: team_id, cookie: *mut i32, info: *mut sem_info, infoSize: size_t, ) -> status_t; pub fn kill_team(team: team_id) -> status_t; pub fn _get_team_info(team: team_id, info: *mut team_info, size: size_t) -> status_t; pub fn _get_next_team_info(cookie: *mut i32, info: *mut team_info, size: size_t) -> status_t; pub fn spawn_thread( func: thread_func, name: *const c_char, priority: i32, data: *mut c_void, ) -> thread_id; pub fn kill_thread(thread: thread_id) -> status_t; pub fn resume_thread(thread: thread_id) -> status_t; pub fn suspend_thread(thread: thread_id) -> status_t; pub fn rename_thread(thread: thread_id, newName: *const c_char) -> status_t; pub fn set_thread_priority(thread: thread_id, newPriority: i32) -> status_t; pub fn suggest_thread_priority( what: u32, period: i32, jitter: crate::bigtime_t, length: crate::bigtime_t, ) -> i32; pub fn estimate_max_scheduling_latency(th: crate::thread_id) -> crate::bigtime_t; pub fn exit_thread(status: status_t); pub fn wait_for_thread(thread: thread_id, returnValue: *mut status_t) -> status_t; pub fn on_exit_thread(callback: extern "C" fn(*mut c_void), data: *mut c_void) -> status_t; pub fn find_thread(name: *const c_char) -> thread_id; pub fn get_scheduler_mode() -> i32; pub fn set_scheduler_mode(mode: i32) -> status_t; pub fn send_data( thread: thread_id, code: i32, buffer: *const c_void, bufferSize: size_t, ) -> status_t; pub fn receive_data(sender: *mut thread_id, buffer: *mut c_void, bufferSize: size_t) -> i32; pub fn has_data(thread: thread_id) -> bool; pub fn snooze(amount: bigtime_t) -> status_t; pub fn snooze_etc(amount: bigtime_t, timeBase: c_int, flags: u32) -> status_t; pub fn snooze_until(time: bigtime_t, timeBase: c_int) -> status_t; pub fn _get_thread_info(id: thread_id, info: *mut thread_info, size: size_t) -> status_t; pub fn _get_next_thread_info( team: team_id, cookie: *mut i32, info: *mut thread_info, size: size_t, ) -> status_t; pub fn get_pthread_thread_id(thread: crate::pthread_t) -> thread_id; pub fn _get_team_usage_info( team: team_id, who: i32, info: *mut team_usage_info, size: size_t, ) -> status_t; pub fn real_time_clock() -> c_ulong; pub fn set_real_time_clock(secsSinceJan1st1970: c_ulong); pub fn real_time_clock_usecs() -> bigtime_t; pub fn system_time() -> bigtime_t; pub fn system_time_nsecs() -> nanotime_t; // set_timezone() is deprecated and a no-op pub fn set_alarm(when: bigtime_t, flags: u32) -> bigtime_t; pub fn debugger(message: *const c_char); pub fn disable_debugger(state: c_int) -> c_int; pub fn get_system_info(info: *mut system_info) -> status_t; pub fn _get_cpu_info_etc( firstCPU: u32, cpuCount: u32, info: *mut cpu_info, size: size_t, ) -> status_t; pub fn get_cpu_topology_info( topologyInfos: *mut cpu_topology_node_info, topologyInfoCount: *mut u32, ) -> status_t; pub fn is_computer_on() -> i32; pub fn is_computer_on_fire() -> c_double; pub fn send_signal(threadID: thread_id, signal: c_uint) -> c_int; pub fn set_signal_stack(base: *mut c_void, size: size_t); pub fn wait_for_objects(infos: *mut object_wait_info, numInfos: c_int) -> ssize_t; pub fn wait_for_objects_etc( infos: *mut object_wait_info, numInfos: c_int, flags: u32, timeout: bigtime_t, ) -> ssize_t; // kernel/fs_attr.h pub fn fs_read_attr( fd: c_int, attribute: *const c_char, type_: u32, pos: off_t, buffer: *mut c_void, readBytes: size_t, ) -> ssize_t; pub fn fs_write_attr( fd: c_int, attribute: *const c_char, type_: u32, pos: off_t, buffer: *const c_void, writeBytes: size_t, ) -> ssize_t; pub fn fs_remove_attr(fd: c_int, attribute: *const c_char) -> c_int; pub fn fs_stat_attr(fd: c_int, attribute: *const c_char, attrInfo: *mut attr_info) -> c_int; pub fn fs_open_attr( path: *const c_char, attribute: *const c_char, type_: u32, openMode: c_int, ) -> c_int; pub fn fs_fopen_attr(fd: c_int, attribute: *const c_char, type_: u32, openMode: c_int) -> c_int; pub fn fs_close_attr(fd: c_int) -> c_int; pub fn fs_open_attr_dir(path: *const c_char) -> *mut crate::DIR; pub fn fs_lopen_attr_dir(path: *const c_char) -> *mut crate::DIR; pub fn fs_fopen_attr_dir(fd: c_int) -> *mut crate::DIR; pub fn fs_close_attr_dir(dir: *mut crate::DIR) -> c_int; pub fn fs_read_attr_dir(dir: *mut crate::DIR) -> *mut crate::dirent; pub fn fs_rewind_attr_dir(dir: *mut crate::DIR); // kernel/fs_image.h pub fn fs_create_index( device: crate::dev_t, name: *const c_char, type_: u32, flags: u32, ) -> c_int; pub fn fs_remove_index(device: crate::dev_t, name: *const c_char) -> c_int; pub fn fs_stat_index( device: crate::dev_t, name: *const c_char, indexInfo: *mut index_info, ) -> c_int; pub fn fs_open_index_dir(device: crate::dev_t) -> *mut crate::DIR; pub fn fs_close_index_dir(indexDirectory: *mut crate::DIR) -> c_int; pub fn fs_read_index_dir(indexDirectory: *mut crate::DIR) -> *mut crate::dirent; pub fn fs_rewind_index_dir(indexDirectory: *mut crate::DIR); // kernel/fs_info.h pub fn dev_for_path(path: *const c_char) -> crate::dev_t; pub fn next_dev(pos: *mut i32) -> crate::dev_t; pub fn fs_stat_dev(dev: crate::dev_t, info: *mut fs_info) -> c_int; // kernel/fs_query.h pub fn fs_open_query(device: crate::dev_t, query: *const c_char, flags: u32) -> *mut crate::DIR; pub fn fs_open_live_query( device: crate::dev_t, query: *const c_char, flags: u32, port: port_id, token: i32, ) -> *mut crate::DIR; pub fn fs_close_query(d: *mut crate::DIR) -> c_int; pub fn fs_read_query(d: *mut crate::DIR) -> *mut crate::dirent; pub fn get_path_for_dirent(dent: *mut crate::dirent, buf: *mut c_char, len: size_t) -> status_t; // kernel/fs_volume.h pub fn fs_mount_volume( where_: *const c_char, device: *const c_char, filesystem: *const c_char, flags: u32, parameters: *const c_char, ) -> crate::dev_t; pub fn fs_unmount_volume(path: *const c_char, flags: u32) -> status_t; // kernel/image.h pub fn load_image( argc: i32, argv: *mut *const c_char, environ: *mut *const c_char, ) -> thread_id; pub fn load_add_on(path: *const c_char) -> image_id; pub fn unload_add_on(image: image_id) -> status_t; pub fn get_image_symbol( image: image_id, name: *const c_char, symbolType: i32, symbolLocation: *mut *mut c_void, ) -> status_t; pub fn get_nth_image_symbol( image: image_id, n: i32, nameBuffer: *mut c_char, nameLength: *mut i32, symbolType: *mut i32, symbolLocation: *mut *mut c_void, ) -> status_t; pub fn clear_caches(address: *mut c_void, length: size_t, flags: u32); pub fn _get_image_info(image: image_id, info: *mut image_info, size: size_t) -> status_t; pub fn _get_next_image_info( team: team_id, cookie: *mut i32, info: *mut image_info, size: size_t, ) -> status_t; pub fn find_path( codePointer: *const c_void, baseDirectory: path_base_directory, subPath: *const c_char, pathBuffer: *mut c_char, bufferSize: usize, ) -> status_t; pub fn find_path_etc( codePointer: *const c_void, dependency: *const c_char, architecture: *const c_char, baseDirectory: path_base_directory, subPath: *const c_char, flags: u32, pathBuffer: *mut c_char, bufferSize: size_t, ) -> status_t; pub fn find_path_for_path( path: *const c_char, baseDirectory: path_base_directory, subPath: *const c_char, pathBuffer: *mut c_char, bufferSize: size_t, ) -> status_t; pub fn find_path_for_path_etc( path: *const c_char, dependency: *const c_char, architecture: *const c_char, baseDirectory: path_base_directory, subPath: *const c_char, flags: u32, pathBuffer: *mut c_char, bufferSize: size_t, ) -> status_t; pub fn find_paths( baseDirectory: path_base_directory, subPath: *const c_char, _paths: *mut *mut *mut c_char, pathCount: *mut size_t, ) -> status_t; pub fn find_paths_etc( architecture: *const c_char, baseDirectory: path_base_directory, subPath: *const c_char, flags: u32, _paths: *mut *mut *mut c_char, pathCount: *mut size_t, ) -> status_t; pub fn find_directory( which: directory_which, volume: crate::dev_t, createIt: bool, pathString: *mut c_char, length: i32, ) -> status_t; pub fn get_cpuid(info: *mut cpuid_info, eaxRegister: u32, cpuNum: u32) -> status_t; } // The following functions are defined as macros in C/C++ #[inline] pub unsafe fn get_cpu_info(firstCPU: u32, cpuCount: u32, info: *mut cpu_info) -> status_t { _get_cpu_info_etc( firstCPU, cpuCount, info, core::mem::size_of::() as size_t, ) } #[inline] pub unsafe fn get_area_info(id: area_id, info: *mut area_info) -> status_t { _get_area_info(id, info, core::mem::size_of::() as usize) } #[inline] pub unsafe fn get_next_area_info( team: team_id, cookie: *mut isize, info: *mut area_info, ) -> status_t { _get_next_area_info( team, cookie, info, core::mem::size_of::() as usize, ) } #[inline] pub unsafe fn get_port_info(port: port_id, buf: *mut port_info) -> status_t { _get_port_info(port, buf, core::mem::size_of::() as size_t) } #[inline] pub unsafe fn get_next_port_info( port: port_id, cookie: *mut i32, portInfo: *mut port_info, ) -> status_t { _get_next_port_info( port, cookie, portInfo, core::mem::size_of::() as size_t, ) } #[inline] pub unsafe fn get_port_message_info_etc( port: port_id, info: *mut port_message_info, flags: u32, timeout: bigtime_t, ) -> status_t { _get_port_message_info_etc( port, info, core::mem::size_of::() as size_t, flags, timeout, ) } #[inline] pub unsafe fn get_sem_info(id: sem_id, info: *mut sem_info) -> status_t { _get_sem_info(id, info, core::mem::size_of::() as size_t) } #[inline] pub unsafe fn get_next_sem_info(team: team_id, cookie: *mut i32, info: *mut sem_info) -> status_t { _get_next_sem_info( team, cookie, info, core::mem::size_of::() as size_t, ) } #[inline] pub unsafe fn get_team_info(team: team_id, info: *mut team_info) -> status_t { _get_team_info(team, info, core::mem::size_of::() as size_t) } #[inline] pub unsafe fn get_next_team_info(cookie: *mut i32, info: *mut team_info) -> status_t { _get_next_team_info(cookie, info, core::mem::size_of::() as size_t) } #[inline] pub unsafe fn get_team_usage_info(team: team_id, who: i32, info: *mut team_usage_info) -> status_t { _get_team_usage_info( team, who, info, core::mem::size_of::() as size_t, ) } #[inline] pub unsafe fn get_thread_info(id: thread_id, info: *mut thread_info) -> status_t { _get_thread_info(id, info, core::mem::size_of::() as size_t) } #[inline] pub unsafe fn get_next_thread_info( team: team_id, cookie: *mut i32, info: *mut thread_info, ) -> status_t { _get_next_thread_info( team, cookie, info, core::mem::size_of::() as size_t, ) } // kernel/image.h #[inline] pub unsafe fn get_image_info(image: image_id, info: *mut image_info) -> status_t { _get_image_info(image, info, core::mem::size_of::() as size_t) } #[inline] pub unsafe fn get_next_image_info( team: team_id, cookie: *mut i32, info: *mut image_info, ) -> status_t { _get_next_image_info( team, cookie, info, core::mem::size_of::() as size_t, ) } libc/src/unix/aix/0000775000175000017500000000000015105742312013650 5ustar bdrungbdrunglibc/src/unix/aix/mod.rs0000644000175000017500000033352315105742312015004 0ustar bdrungbdrunguse crate::prelude::*; pub type caddr_t = *mut c_char; pub type clockid_t = c_longlong; pub type blkcnt_t = c_long; pub type clock_t = c_int; pub type daddr_t = c_long; pub type dev_t = c_ulong; pub type fpos64_t = c_longlong; pub type fsblkcnt_t = c_ulong; pub type fsfilcnt_t = c_ulong; pub type idtype_t = c_int; pub type ino_t = c_ulong; pub type key_t = c_int; pub type mode_t = c_uint; pub type nlink_t = c_short; pub type rlim_t = c_ulong; pub type speed_t = c_uint; pub type tcflag_t = c_uint; pub type time_t = c_long; pub type time64_t = crate::int64_t; pub type timer_t = c_long; pub type wchar_t = c_uint; pub type nfds_t = c_int; pub type projid_t = c_int; pub type id_t = c_uint; pub type blksize64_t = c_ulonglong; pub type blkcnt64_t = c_ulonglong; pub type sctp_assoc_t = crate::uint32_t; pub type suseconds_t = c_int; pub type useconds_t = c_uint; pub type off_t = c_long; pub type off64_t = c_longlong; pub type socklen_t = c_uint; pub type sa_family_t = c_uchar; pub type in_port_t = c_ushort; pub type in_addr_t = c_uint; pub type signal_t = c_int; pub type pthread_t = c_uint; pub type pthread_key_t = c_uint; pub type thread_t = pthread_t; pub type blksize_t = c_long; pub type nl_item = c_int; pub type mqd_t = c_int; pub type shmatt_t = c_ulong; pub type regoff_t = c_long; pub type rlim64_t = c_ulonglong; pub type sem_t = c_int; pub type pollset_t = c_int; pub type pthread_rwlockattr_t = *mut c_void; pub type pthread_condattr_t = *mut c_void; pub type pthread_mutexattr_t = *mut c_void; pub type pthread_attr_t = *mut c_void; pub type pthread_barrierattr_t = *mut c_void; pub type posix_spawn_file_actions_t = *mut c_char; pub type iconv_t = *mut c_void; e! { #[repr(u32)] pub enum uio_rw { UIO_READ = 0, UIO_WRITE, UIO_READ_NO_MOVE, UIO_WRITE_NO_MOVE, UIO_PWRITE, } } s! { pub struct fsid_t { pub val: [c_uint; 2], } pub struct fsid64_t { pub val: [crate::uint64_t; 2], } pub struct timezone { pub tz_minuteswest: c_int, pub tz_dsttime: c_int, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct dirent { pub d_offset: c_ulong, pub d_ino: crate::ino_t, pub d_reclen: c_ushort, pub d_namlen: c_ushort, pub d_name: [c_char; 256], } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_cc: [crate::cc_t; crate::NCCS], } pub struct flock64 { pub l_type: c_short, pub l_whence: c_short, pub l_sysid: c_uint, pub l_pid: crate::pid_t, pub l_vfs: c_int, pub l_start: off64_t, pub l_len: off64_t, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: socklen_t, pub msg_flags: c_int, } pub struct statvfs64 { pub f_bsize: crate::blksize64_t, pub f_frsize: crate::blksize64_t, pub f_blocks: crate::blkcnt64_t, pub f_bfree: crate::blkcnt64_t, pub f_bavail: crate::blkcnt64_t, pub f_files: crate::blkcnt64_t, pub f_ffree: crate::blkcnt64_t, pub f_favail: crate::blkcnt64_t, pub f_fsid: fsid64_t, pub f_basetype: [c_char; 16], pub f_flag: c_ulong, pub f_namemax: c_ulong, pub f_fstr: [c_char; 32], pub f_filler: [c_ulong; 16], } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub left_parenthesis: *mut c_char, pub right_parenthesis: *mut c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: c_ulong, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut addrinfo, pub ai_eflags: c_int, } pub struct in_addr { pub s_addr: in_addr_t, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct sockaddr { pub sa_len: c_uchar, pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_dl { pub sdl_len: c_uchar, pub sdl_family: c_uchar, pub sdl_index: c_ushort, pub sdl_type: c_uchar, pub sdl_nlen: c_uchar, pub sdl_alen: c_uchar, pub sdl_slen: c_uchar, pub sdl_data: [c_char; 120], } pub struct sockaddr_in { pub sin_len: c_uchar, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [c_char; 8], } pub struct sockaddr_in6 { pub sin6_len: c_uchar, pub sin6_family: c_uchar, pub sin6_port: crate::uint16_t, pub sin6_flowinfo: crate::uint32_t, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: crate::uint32_t, } pub struct sockaddr_storage { pub __ss_len: c_uchar, pub ss_family: sa_family_t, __ss_pad1: [c_char; 6], __ss_align: crate::int64_t, __ss_pad2: [c_char; 1265], } pub struct sockaddr_un { pub sun_len: c_uchar, pub sun_family: sa_family_t, pub sun_path: [c_char; 1023], } pub struct st_timespec { pub tv_sec: crate::time_t, pub tv_nsec: c_int, } pub struct statfs64 { pub f_version: c_int, pub f_type: c_int, pub f_bsize: blksize64_t, pub f_blocks: blkcnt64_t, pub f_bfree: blkcnt64_t, pub f_bavail: blkcnt64_t, pub f_files: crate::uint64_t, pub f_ffree: crate::uint64_t, pub f_fsid: fsid64_t, pub f_vfstype: c_int, pub f_fsize: blksize64_t, pub f_vfsnumber: c_int, pub f_vfsoff: c_int, pub f_vfslen: c_int, pub f_vfsvers: c_int, pub f_fname: [c_char; 32], pub f_fpack: [c_char; 32], pub f_name_max: c_int, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, } pub struct utsname { pub sysname: [c_char; 32], pub nodename: [c_char; 32], pub release: [c_char; 32], pub version: [c_char; 32], pub machine: [c_char; 32], } pub struct xutsname { pub nid: c_uint, pub reserved: c_int, pub longnid: c_ulonglong, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct sigevent { pub sigev_value: crate::sigval, pub sigev_signo: c_int, pub sigev_notify: c_int, pub sigev_notify_function: extern "C" fn(val: crate::sigval), pub sigev_notify_attributes: *mut pthread_attr_t, } // Should be union with another 'sival_int' pub struct sigval64 { pub sival_ptr: c_ulonglong, } pub struct sigevent64 { pub sigev_value: sigval64, pub sigev_signo: c_int, pub sigev_notify: c_int, pub sigev_notify_function: c_ulonglong, pub sigev_notify_attributes: c_ulonglong, } pub struct osigevent { pub sevt_value: *mut c_void, pub sevt_signo: signal_t, } pub struct poll_ctl { pub cmd: c_short, pub events: c_short, pub fd: c_int, } pub struct sf_parms { pub header_data: *mut c_void, pub header_length: c_uint, pub file_descriptor: c_int, pub file_size: crate::uint64_t, pub file_offset: crate::uint64_t, pub file_bytes: crate::int64_t, pub trailer_data: *mut c_void, pub trailer_length: c_uint, pub bytes_sent: crate::uint64_t, } pub struct mmsghdr { pub msg_hdr: crate::msghdr, pub msg_len: c_uint, } pub struct sched_param { pub sched_priority: c_int, pub sched_policy: c_int, pub sched_reserved: [c_int; 6], } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, pub __pad: [c_int; 4], } pub struct posix_spawnattr_t { pub posix_attr_flags: c_short, pub posix_attr_pgroup: crate::pid_t, pub posix_attr_sigmask: crate::sigset_t, pub posix_attr_sigdefault: crate::sigset_t, pub posix_attr_schedpolicy: c_int, pub posix_attr_schedparam: sched_param, } pub struct glob_t { pub gl_pathc: size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: size_t, pub gl_padr: *mut c_void, pub gl_ptx: *mut c_void, } pub struct mallinfo { pub arena: c_ulong, pub ordblks: c_int, pub smblks: c_int, pub hblks: c_int, pub hblkhd: c_int, pub usmblks: c_ulong, pub fsmblks: c_ulong, pub uordblks: c_ulong, pub fordblks: c_ulong, pub keepcost: c_int, } pub struct utmp_exit_status { pub e_termination: c_short, pub e_exit: c_short, } pub struct utmp { pub ut_user: [c_char; 256], pub ut_id: [c_char; 14], pub ut_line: [c_char; 64], pub ut_pid: crate::pid_t, pub ut_type: c_short, pub ut_time: time64_t, pub ut_exit: utmp_exit_status, pub ut_host: [c_char; 256], pub __dbl_word_pad: c_int, pub __reservedA: [c_int; 2], pub __reservedV: [c_int; 6], } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct regex_t { pub re_nsub: size_t, pub re_comp: *mut c_void, pub re_cflags: c_int, pub re_erroff: size_t, pub re_len: size_t, pub re_ucoll: [crate::wchar_t; 2], pub re_lsub: [*mut c_void; 24], pub re_esub: [*mut c_void; 24], pub re_map: *mut c_uchar, pub __maxsub: c_int, pub __unused: [*mut c_void; 34], } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } pub struct shmid_ds { pub shm_perm: ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: shmatt_t, pub shm_cnattch: shmatt_t, pub shm_atime: time_t, pub shm_dtime: time_t, pub shm_ctime: time_t, pub shm_handle: crate::uint32_t, pub shm_extshm: c_int, pub shm_pagesize: crate::int64_t, pub shm_lba: crate::uint64_t, pub shm_reserved: crate::int64_t, pub shm_reserved1: crate::int64_t, } pub struct stat64 { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, pub st_nlink: nlink_t, pub st_flag: c_ushort, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: dev_t, pub st_ssize: c_int, pub st_atim: st_timespec, pub st_mtim: st_timespec, pub st_ctim: st_timespec, pub st_blksize: blksize_t, pub st_blocks: blkcnt_t, pub st_vfstype: c_int, pub st_vfs: c_uint, pub st_type: c_uint, pub st_gen: c_uint, pub st_reserved: [c_uint; 10], pub st_size: off64_t, } pub struct mntent { pub mnt_fsname: *mut c_char, pub mnt_dir: *mut c_char, pub mnt_type: *mut c_char, pub mnt_opts: *mut c_char, pub mnt_freq: c_int, pub mnt_passno: c_int, } pub struct ipc_perm { pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: mode_t, pub seq: c_ushort, pub __reserved: c_ushort, pub key: key_t, } pub struct entry { pub key: *mut c_char, pub data: *mut c_void, } pub struct mq_attr { pub mq_flags: c_long, pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_curmsgs: c_long, } pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } pub struct itimerspec { pub it_interval: crate::timespec, pub it_value: crate::timespec, } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, // FIXME(union): this field is actually a union pub sa_mask: sigset_t, pub sa_flags: c_int, } } s_no_extra_traits! { pub union __poll_ctl_ext_u { pub addr: *mut c_void, pub data32: u32, pub data: u64, } pub struct poll_ctl_ext { pub version: u8, pub command: u8, pub events: c_short, pub fd: c_int, pub u: __poll_ctl_ext_u, pub reversed64: [u64; 6], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __poll_ctl_ext_u { fn eq(&self, other: &__poll_ctl_ext_u) -> bool { unsafe { self.addr == other.addr && self.data32 == other.data32 && self.data == other.data } } } impl Eq for __poll_ctl_ext_u {} impl hash::Hash for __poll_ctl_ext_u { fn hash(&self, state: &mut H) { unsafe { self.addr.hash(state); self.data32.hash(state); self.data.hash(state); } } } impl PartialEq for poll_ctl_ext { fn eq(&self, other: &poll_ctl_ext) -> bool { self.version == other.version && self.command == other.command && self.events == other.events && self.fd == other.fd && self.reversed64 == other.reversed64 && self.u == other.u } } impl Eq for poll_ctl_ext {} impl fmt::Debug for poll_ctl_ext { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("poll_ctl_ext") .field("version", &self.version) .field("command", &self.command) .field("events", &self.events) .field("fd", &self.fd) .field("u", &self.u) .field("reversed64", &self.reversed64) .finish() } } impl hash::Hash for poll_ctl_ext { fn hash(&self, state: &mut H) { self.version.hash(state); self.command.hash(state); self.events.hash(state); self.fd.hash(state); self.u.hash(state); self.reversed64.hash(state); } } } } // dlfcn.h pub const RTLD_LAZY: c_int = 0x4; pub const RTLD_NOW: c_int = 0x2; pub const RTLD_GLOBAL: c_int = 0x10000; pub const RTLD_LOCAL: c_int = 0x80000; pub const RTLD_MEMBER: c_int = 0x40000; pub const RTLD_NOAUTODEFER: c_int = 0x20000; pub const RTLD_DEFAULT: *mut c_void = -1isize as *mut c_void; pub const RTLD_MYSELF: *mut c_void = -2isize as *mut c_void; pub const RTLD_NEXT: *mut c_void = -3isize as *mut c_void; // fcntl.h pub const O_RDONLY: c_int = 0x0; pub const O_WRONLY: c_int = 0x1; pub const O_RDWR: c_int = 0x2; pub const O_NDELAY: c_int = 0x8000; pub const O_APPEND: c_int = 0x8; pub const O_DSYNC: c_int = 0x400000; pub const O_CREAT: c_int = 0x100; pub const O_EXCL: c_int = 0x400; pub const O_NOCTTY: c_int = 0x800; pub const O_TRUNC: c_int = 0x200; pub const O_NOFOLLOW: c_int = 0x1000000; pub const O_DIRECTORY: c_int = 0x80000; pub const O_SEARCH: c_int = 0x20; pub const O_EXEC: c_int = 0x20; pub const O_CLOEXEC: c_int = 0x800000; pub const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR; pub const O_DIRECT: c_int = 0x8000000; pub const O_TTY_INIT: c_int = 0; pub const O_RSYNC: c_int = 0x200000; pub const O_LARGEFILE: c_int = 0x4000000; pub const F_CLOSEM: c_int = 10; pub const F_DUPFD_CLOEXEC: c_int = 16; pub const F_GETLK64: c_int = 11; pub const F_SETLK64: c_int = 12; pub const F_SETLKW64: c_int = 13; pub const F_DUP2FD: c_int = 14; pub const F_TSTLK: c_int = 15; pub const F_GETLK: c_int = F_GETLK64; pub const F_SETLK: c_int = F_SETLK64; pub const F_SETLKW: c_int = F_SETLKW64; pub const F_GETOWN: c_int = 8; pub const F_SETOWN: c_int = 9; pub const AT_FDCWD: c_int = -2; pub const AT_SYMLINK_NOFOLLOW: c_int = 1; pub const AT_SYMLINK_FOLLOW: c_int = 2; pub const AT_REMOVEDIR: c_int = 1; pub const AT_EACCESS: c_int = 1; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const O_SYNC: c_int = 16; pub const O_NONBLOCK: c_int = 4; pub const FASYNC: c_int = 0x20000; pub const POSIX_FADV_NORMAL: c_int = 1; pub const POSIX_FADV_SEQUENTIAL: c_int = 2; pub const POSIX_FADV_RANDOM: c_int = 3; pub const POSIX_FADV_WILLNEED: c_int = 4; pub const POSIX_FADV_DONTNEED: c_int = 5; pub const POSIX_FADV_NOREUSE: c_int = 6; // glob.h pub const GLOB_APPEND: c_int = 0x1; pub const GLOB_DOOFFS: c_int = 0x2; pub const GLOB_ERR: c_int = 0x4; pub const GLOB_MARK: c_int = 0x8; pub const GLOB_NOCHECK: c_int = 0x10; pub const GLOB_NOSORT: c_int = 0x20; pub const GLOB_NOESCAPE: c_int = 0x80; pub const GLOB_NOSPACE: c_int = 0x2000; pub const GLOB_ABORTED: c_int = 0x1000; pub const GLOB_NOMATCH: c_int = 0x4000; pub const GLOB_NOSYS: c_int = 0x8000; // langinfo.h pub const DAY_1: crate::nl_item = 13; pub const DAY_2: crate::nl_item = 14; pub const DAY_3: crate::nl_item = 15; pub const DAY_4: crate::nl_item = 16; pub const DAY_5: crate::nl_item = 17; pub const DAY_6: crate::nl_item = 18; pub const DAY_7: crate::nl_item = 19; pub const ABDAY_1: crate::nl_item = 6; pub const ABDAY_2: crate::nl_item = 7; pub const ABDAY_3: crate::nl_item = 8; pub const ABDAY_4: crate::nl_item = 9; pub const ABDAY_5: crate::nl_item = 10; pub const ABDAY_6: crate::nl_item = 11; pub const ABDAY_7: crate::nl_item = 12; pub const MON_1: crate::nl_item = 32; pub const MON_2: crate::nl_item = 33; pub const MON_3: crate::nl_item = 34; pub const MON_4: crate::nl_item = 35; pub const MON_5: crate::nl_item = 36; pub const MON_6: crate::nl_item = 37; pub const MON_7: crate::nl_item = 38; pub const MON_8: crate::nl_item = 39; pub const MON_9: crate::nl_item = 40; pub const MON_10: crate::nl_item = 41; pub const MON_11: crate::nl_item = 42; pub const MON_12: crate::nl_item = 43; pub const ABMON_1: crate::nl_item = 20; pub const ABMON_2: crate::nl_item = 21; pub const ABMON_3: crate::nl_item = 22; pub const ABMON_4: crate::nl_item = 23; pub const ABMON_5: crate::nl_item = 24; pub const ABMON_6: crate::nl_item = 25; pub const ABMON_7: crate::nl_item = 26; pub const ABMON_8: crate::nl_item = 27; pub const ABMON_9: crate::nl_item = 28; pub const ABMON_10: crate::nl_item = 29; pub const ABMON_11: crate::nl_item = 30; pub const ABMON_12: crate::nl_item = 31; pub const RADIXCHAR: crate::nl_item = 44; pub const THOUSEP: crate::nl_item = 45; pub const YESSTR: crate::nl_item = 46; pub const NOSTR: crate::nl_item = 47; pub const CRNCYSTR: crate::nl_item = 48; pub const D_T_FMT: crate::nl_item = 1; pub const D_FMT: crate::nl_item = 2; pub const T_FMT: crate::nl_item = 3; pub const AM_STR: crate::nl_item = 4; pub const PM_STR: crate::nl_item = 5; pub const CODESET: crate::nl_item = 49; pub const T_FMT_AMPM: crate::nl_item = 55; pub const ERA: crate::nl_item = 56; pub const ERA_D_FMT: crate::nl_item = 57; pub const ERA_D_T_FMT: crate::nl_item = 58; pub const ERA_T_FMT: crate::nl_item = 59; pub const ALT_DIGITS: crate::nl_item = 60; pub const YESEXPR: crate::nl_item = 61; pub const NOEXPR: crate::nl_item = 62; // locale.h pub const LC_GLOBAL_LOCALE: crate::locale_t = -1isize as crate::locale_t; pub const LC_CTYPE: c_int = 1; pub const LC_NUMERIC: c_int = 3; pub const LC_TIME: c_int = 4; pub const LC_COLLATE: c_int = 0; pub const LC_MONETARY: c_int = 2; pub const LC_MESSAGES: c_int = 4; pub const LC_ALL: c_int = -1; pub const LC_CTYPE_MASK: c_int = 2; pub const LC_NUMERIC_MASK: c_int = 16; pub const LC_TIME_MASK: c_int = 32; pub const LC_COLLATE_MASK: c_int = 1; pub const LC_MONETARY_MASK: c_int = 8; pub const LC_MESSAGES_MASK: c_int = 4; pub const LC_ALL_MASK: c_int = LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK | LC_MONETARY_MASK | LC_MESSAGES_MASK; // netdb.h pub const NI_MAXHOST: crate::socklen_t = 1025; pub const NI_MAXSERV: crate::socklen_t = 32; pub const NI_NOFQDN: crate::socklen_t = 0x1; pub const NI_NUMERICHOST: crate::socklen_t = 0x2; pub const NI_NAMEREQD: crate::socklen_t = 0x4; pub const NI_NUMERICSERV: crate::socklen_t = 0x8; pub const NI_DGRAM: crate::socklen_t = 0x10; pub const NI_NUMERICSCOPE: crate::socklen_t = 0x40; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_MEMORY: c_int = 6; pub const EAI_NODATA: c_int = 7; pub const EAI_NONAME: c_int = 8; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 13; pub const AI_CANONNAME: c_int = 0x01; pub const AI_PASSIVE: c_int = 0x02; pub const AI_NUMERICHOST: c_int = 0x04; pub const AI_ADDRCONFIG: c_int = 0x08; pub const AI_V4MAPPED: c_int = 0x10; pub const AI_ALL: c_int = 0x20; pub const AI_NUMERICSERV: c_int = 0x40; pub const AI_EXTFLAGS: c_int = 0x80; pub const AI_DEFAULT: c_int = AI_V4MAPPED | AI_ADDRCONFIG; pub const IPV6_ADDRFORM: c_int = 22; pub const IPV6_ADDR_PREFERENCES: c_int = 74; pub const IPV6_CHECKSUM: c_int = 39; pub const IPV6_DONTFRAG: c_int = 45; pub const IPV6_DSTOPTS: c_int = 54; pub const IPV6_FLOWINFO_FLOWLABEL: c_int = 16777215; pub const IPV6_FLOWINFO_PRIORITY: c_int = 251658240; pub const IPV6_HOPLIMIT: c_int = 40; pub const IPV6_HOPOPTS: c_int = 52; pub const IPV6_NEXTHOP: c_int = 48; pub const IPV6_PATHMTU: c_int = 46; pub const IPV6_PKTINFO: c_int = 33; pub const IPV6_PREFER_SRC_CGA: c_int = 16; pub const IPV6_PREFER_SRC_COA: c_int = 2; pub const IPV6_PREFER_SRC_HOME: c_int = 1; pub const IPV6_PREFER_SRC_NONCGA: c_int = 32; pub const IPV6_PREFER_SRC_PUBLIC: c_int = 4; pub const IPV6_PREFER_SRC_TMP: c_int = 8; pub const IPV6_RECVDSTOPTS: c_int = 56; pub const IPV6_RECVHOPLIMIT: c_int = 41; pub const IPV6_RECVHOPOPTS: c_int = 53; pub const IPV6_RECVPATHMTU: c_int = 47; pub const IPV6_RECVRTHDR: c_int = 51; pub const IPV6_RECVTCLASS: c_int = 42; pub const IPV6_RTHDR: c_int = 50; pub const IPV6_RTHDRDSTOPTS: c_int = 55; pub const IPV6_TCLASS: c_int = 43; // net/bpf.h pub const DLT_NULL: c_int = 0x18; pub const DLT_EN10MB: c_int = 0x6; pub const DLT_EN3MB: c_int = 0x1a; pub const DLT_AX25: c_int = 0x5; pub const DLT_PRONET: c_int = 0xd; pub const DLT_IEEE802: c_int = 0x7; pub const DLT_ARCNET: c_int = 0x23; pub const DLT_SLIP: c_int = 0x1c; pub const DLT_PPP: c_int = 0x17; pub const DLT_FDDI: c_int = 0xf; pub const DLT_ATM: c_int = 0x25; pub const DLT_IPOIB: c_int = 0xc7; pub const BIOCSETF: c_ulong = 0x80104267; pub const BIOCGRTIMEOUT: c_ulong = 0x4010426e; pub const BIOCGBLEN: c_int = 0x40044266; pub const BIOCSBLEN: c_int = 0xc0044266; pub const BIOCFLUSH: c_int = 0x20004268; pub const BIOCPROMISC: c_int = 0x20004269; pub const BIOCGDLT: c_int = 0x4004426a; pub const BIOCSRTIMEOUT: c_int = 0x8010426d; pub const BIOCGSTATS: c_int = 0x4008426f; pub const BIOCIMMEDIATE: c_int = 0x80044270; pub const BIOCVERSION: c_int = 0x40044271; pub const BIOCSDEVNO: c_int = 0x20004272; pub const BIOCGETIF: c_ulong = 0x4020426b; pub const BIOCSETIF: c_ulong = 0xffffffff8020426c; pub const BPF_ABS: c_int = 32; pub const BPF_ADD: c_int = 0; pub const BPF_ALIGNMENT: c_ulong = 4; pub const BPF_ALU: c_int = 4; pub const BPF_AND: c_int = 80; pub const BPF_B: c_int = 16; pub const BPF_DIV: c_int = 48; pub const BPF_H: c_int = 8; pub const BPF_IMM: c_int = 0; pub const BPF_IND: c_int = 64; pub const BPF_JA: c_int = 0; pub const BPF_JEQ: c_int = 16; pub const BPF_JGE: c_int = 48; pub const BPF_JGT: c_int = 32; pub const BPF_JMP: c_int = 5; pub const BPF_JSET: c_int = 64; pub const BPF_K: c_int = 0; pub const BPF_LD: c_int = 0; pub const BPF_LDX: c_int = 1; pub const BPF_LEN: c_int = 128; pub const BPF_LSH: c_int = 96; pub const BPF_MAXINSNS: c_int = 512; pub const BPF_MEM: c_int = 96; pub const BPF_MEMWORDS: c_int = 16; pub const BPF_MISC: c_int = 7; pub const BPF_MSH: c_int = 160; pub const BPF_MUL: c_int = 32; pub const BPF_NEG: c_int = 128; pub const BPF_OR: c_int = 64; pub const BPF_RET: c_int = 6; pub const BPF_RSH: c_int = 112; pub const BPF_ST: c_int = 2; pub const BPF_STX: c_int = 3; pub const BPF_SUB: c_int = 16; pub const BPF_W: c_int = 0; pub const BPF_X: c_int = 8; // net/if.h pub const IFNET_SLOWHZ: c_int = 1; pub const IFQ_MAXLEN: c_int = 50; pub const IFF_UP: c_int = 0x1; pub const IFF_BROADCAST: c_int = 0x2; pub const IFF_DEBUG: c_int = 0x4; pub const IFF_LOOPBACK: c_int = 0x8; pub const IFF_POINTOPOINT: c_int = 0x10; pub const IFF_NOTRAILERS: c_int = 0x20; pub const IFF_RUNNING: c_int = 0x40; pub const IFF_NOARP: c_int = 0x80; pub const IFF_PROMISC: c_int = 0x100; pub const IFF_ALLMULTI: c_int = 0x200; pub const IFF_MULTICAST: c_int = 0x80000; pub const IFF_LINK0: c_int = 0x100000; pub const IFF_LINK1: c_int = 0x200000; pub const IFF_LINK2: c_int = 0x400000; pub const IFF_OACTIVE: c_int = 0x400; pub const IFF_SIMPLEX: c_int = 0x800; // net/if_arp.h pub const ARPHRD_ETHER: c_int = 1; pub const ARPHRD_802_5: c_int = 6; pub const ARPHRD_802_3: c_int = 6; pub const ARPHRD_FDDI: c_int = 1; // net/route.h pub const RTM_ADD: c_int = 0x1; pub const RTM_DELETE: c_int = 0x2; pub const RTM_CHANGE: c_int = 0x3; pub const RTM_GET: c_int = 0x4; pub const RTM_LOSING: c_int = 0x5; pub const RTM_REDIRECT: c_int = 0x6; pub const RTM_MISS: c_int = 0x7; pub const RTM_LOCK: c_int = 0x8; pub const RTM_OLDADD: c_int = 0x9; pub const RTM_OLDDEL: c_int = 0xa; pub const RTM_RESOLVE: c_int = 0xb; pub const RTM_NEWADDR: c_int = 0xc; pub const RTM_DELADDR: c_int = 0xd; pub const RTM_IFINFO: c_int = 0xe; pub const RTM_EXPIRE: c_int = 0xf; pub const RTM_RTLOST: c_int = 0x10; pub const RTM_GETNEXT: c_int = 0x11; pub const RTM_SAMEADDR: c_int = 0x12; pub const RTM_SET: c_int = 0x13; pub const RTV_MTU: c_int = 0x1; pub const RTV_HOPCOUNT: c_int = 0x2; pub const RTV_EXPIRE: c_int = 0x4; pub const RTV_RPIPE: c_int = 0x8; pub const RTV_SPIPE: c_int = 0x10; pub const RTV_SSTHRESH: c_int = 0x20; pub const RTV_RTT: c_int = 0x40; pub const RTV_RTTVAR: c_int = 0x80; pub const RTA_DST: c_int = 0x1; pub const RTA_GATEWAY: c_int = 0x2; pub const RTA_NETMASK: c_int = 0x4; pub const RTA_GENMASK: c_int = 0x8; pub const RTA_IFP: c_int = 0x10; pub const RTA_IFA: c_int = 0x20; pub const RTA_AUTHOR: c_int = 0x40; pub const RTA_BRD: c_int = 0x80; pub const RTA_DOWNSTREAM: c_int = 0x100; pub const RTAX_DST: c_int = 0; pub const RTAX_GATEWAY: c_int = 1; pub const RTAX_NETMASK: c_int = 2; pub const RTAX_GENMASK: c_int = 3; pub const RTAX_IFP: c_int = 4; pub const RTAX_IFA: c_int = 5; pub const RTAX_AUTHOR: c_int = 6; pub const RTAX_BRD: c_int = 7; pub const RTAX_MAX: c_int = 8; pub const RTF_UP: c_int = 0x1; pub const RTF_GATEWAY: c_int = 0x2; pub const RTF_HOST: c_int = 0x4; pub const RTF_REJECT: c_int = 0x8; pub const RTF_DYNAMIC: c_int = 0x10; pub const RTF_MODIFIED: c_int = 0x20; pub const RTF_DONE: c_int = 0x40; pub const RTF_MASK: c_int = 0x80; pub const RTF_CLONING: c_int = 0x100; pub const RTF_XRESOLVE: c_int = 0x200; pub const RTF_LLINFO: c_int = 0x400; pub const RTF_STATIC: c_int = 0x800; pub const RTF_BLACKHOLE: c_int = 0x1000; pub const RTF_BUL: c_int = 0x2000; pub const RTF_PROTO2: c_int = 0x4000; pub const RTF_PROTO1: c_int = 0x8000; pub const RTF_CLONE: c_int = 0x10000; pub const RTF_CLONED: c_int = 0x20000; pub const RTF_PROTO3: c_int = 0x40000; pub const RTF_BCE: c_int = 0x80000; pub const RTF_PINNED: c_int = 0x100000; pub const RTF_LOCAL: c_int = 0x200000; pub const RTF_BROADCAST: c_int = 0x400000; pub const RTF_MULTICAST: c_int = 0x800000; pub const RTF_ACTIVE_DGD: c_int = 0x1000000; pub const RTF_STOPSRCH: c_int = 0x2000000; pub const RTF_FREE_IN_PROG: c_int = 0x4000000; pub const RTF_PERMANENT6: c_int = 0x8000000; pub const RTF_UNREACHABLE: c_int = 0x10000000; pub const RTF_CACHED: c_int = 0x20000000; pub const RTF_SMALLMTU: c_int = 0x40000; // netinet/in.h pub const IPPROTO_HOPOPTS: c_int = 0; pub const IPPROTO_IGMP: c_int = 2; pub const IPPROTO_GGP: c_int = 3; pub const IPPROTO_IPIP: c_int = 4; pub const IPPROTO_EGP: c_int = 8; pub const IPPROTO_PUP: c_int = 12; pub const IPPROTO_IDP: c_int = 22; pub const IPPROTO_TP: c_int = 29; pub const IPPROTO_ROUTING: c_int = 43; pub const IPPROTO_FRAGMENT: c_int = 44; pub const IPPROTO_QOS: c_int = 45; pub const IPPROTO_RSVP: c_int = 46; pub const IPPROTO_GRE: c_int = 47; pub const IPPROTO_ESP: c_int = 50; pub const IPPROTO_AH: c_int = 51; pub const IPPROTO_NONE: c_int = 59; pub const IPPROTO_DSTOPTS: c_int = 60; pub const IPPROTO_LOCAL: c_int = 63; pub const IPPROTO_EON: c_int = 80; pub const IPPROTO_BIP: c_int = 0x53; pub const IPPROTO_SCTP: c_int = 132; pub const IPPROTO_MH: c_int = 135; pub const IPPROTO_GIF: c_int = 140; pub const IPPROTO_RAW: c_int = 255; pub const IPPROTO_MAX: c_int = 256; pub const IP_OPTIONS: c_int = 1; pub const IP_HDRINCL: c_int = 2; pub const IP_TOS: c_int = 3; pub const IP_TTL: c_int = 4; pub const IP_UNICAST_HOPS: c_int = 4; pub const IP_RECVOPTS: c_int = 5; pub const IP_RECVRETOPTS: c_int = 6; pub const IP_RECVDSTADDR: c_int = 7; pub const IP_RETOPTS: c_int = 8; pub const IP_MULTICAST_IF: c_int = 9; pub const IP_MULTICAST_TTL: c_int = 10; pub const IP_MULTICAST_HOPS: c_int = 10; pub const IP_MULTICAST_LOOP: c_int = 11; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IP_RECVMACHDR: c_int = 14; pub const IP_RECVIFINFO: c_int = 15; pub const IP_BROADCAST_IF: c_int = 16; pub const IP_DHCPMODE: c_int = 17; pub const IP_RECVIF: c_int = 20; pub const IP_ADDRFORM: c_int = 22; pub const IP_DONTFRAG: c_int = 25; pub const IP_FINDPMTU: c_int = 26; pub const IP_PMTUAGE: c_int = 27; pub const IP_RECVINTERFACE: c_int = 32; pub const IP_RECVTTL: c_int = 34; pub const IP_BLOCK_SOURCE: c_int = 58; pub const IP_UNBLOCK_SOURCE: c_int = 59; pub const IP_ADD_SOURCE_MEMBERSHIP: c_int = 60; pub const IP_DROP_SOURCE_MEMBERSHIP: c_int = 61; pub const IP_DEFAULT_MULTICAST_TTL: c_int = 1; pub const IP_DEFAULT_MULTICAST_LOOP: c_int = 1; pub const IP_INC_MEMBERSHIPS: c_int = 20; pub const IP_INIT_MEMBERSHIP: c_int = 20; pub const IPV6_UNICAST_HOPS: c_int = IP_TTL; pub const IPV6_MULTICAST_IF: c_int = IP_MULTICAST_IF; pub const IPV6_MULTICAST_HOPS: c_int = IP_MULTICAST_TTL; pub const IPV6_MULTICAST_LOOP: c_int = IP_MULTICAST_LOOP; pub const IPV6_RECVPKTINFO: c_int = 35; pub const IPV6_V6ONLY: c_int = 37; pub const IPV6_ADD_MEMBERSHIP: c_int = IP_ADD_MEMBERSHIP; pub const IPV6_DROP_MEMBERSHIP: c_int = IP_DROP_MEMBERSHIP; pub const IPV6_JOIN_GROUP: c_int = IP_ADD_MEMBERSHIP; pub const IPV6_LEAVE_GROUP: c_int = IP_DROP_MEMBERSHIP; pub const MCAST_BLOCK_SOURCE: c_int = 64; pub const MCAST_EXCLUDE: c_int = 2; pub const MCAST_INCLUDE: c_int = 1; pub const MCAST_JOIN_GROUP: c_int = 62; pub const MCAST_JOIN_SOURCE_GROUP: c_int = 66; pub const MCAST_LEAVE_GROUP: c_int = 63; pub const MCAST_LEAVE_SOURCE_GROUP: c_int = 67; pub const MCAST_UNBLOCK_SOURCE: c_int = 65; // netinet/ip.h pub const MAXTTL: c_int = 255; pub const IPDEFTTL: c_int = 64; pub const IPOPT_CONTROL: c_int = 0; pub const IPOPT_EOL: c_int = 0; pub const IPOPT_LSRR: c_int = 131; pub const IPOPT_MINOFF: c_int = 4; pub const IPOPT_NOP: c_int = 1; pub const IPOPT_OFFSET: c_int = 2; pub const IPOPT_OLEN: c_int = 1; pub const IPOPT_OPTVAL: c_int = 0; pub const IPOPT_RESERVED1: c_int = 0x20; pub const IPOPT_RESERVED2: c_int = 0x60; pub const IPOPT_RR: c_int = 7; pub const IPOPT_SSRR: c_int = 137; pub const IPOPT_TS: c_int = 68; pub const IPOPT_TS_PRESPEC: c_int = 3; pub const IPOPT_TS_TSANDADDR: c_int = 1; pub const IPOPT_TS_TSONLY: c_int = 0; pub const IPTOS_LOWDELAY: c_int = 16; pub const IPTOS_PREC_CRITIC_ECP: c_int = 160; pub const IPTOS_PREC_FLASH: c_int = 96; pub const IPTOS_PREC_FLASHOVERRIDE: c_int = 128; pub const IPTOS_PREC_IMMEDIATE: c_int = 64; pub const IPTOS_PREC_INTERNETCONTROL: c_int = 192; pub const IPTOS_PREC_NETCONTROL: c_int = 224; pub const IPTOS_PREC_PRIORITY: c_int = 32; pub const IPTOS_PREC_ROUTINE: c_int = 16; pub const IPTOS_RELIABILITY: c_int = 4; pub const IPTOS_THROUGHPUT: c_int = 8; pub const IPVERSION: c_int = 4; // netinet/tcp.h pub const TCP_NODELAY: c_int = 0x1; pub const TCP_MAXSEG: c_int = 0x2; pub const TCP_RFC1323: c_int = 0x4; pub const TCP_KEEPALIVE: c_int = 0x8; pub const TCP_KEEPIDLE: c_int = 0x11; pub const TCP_KEEPINTVL: c_int = 0x12; pub const TCP_KEEPCNT: c_int = 0x13; pub const TCP_NODELAYACK: c_int = 0x14; // pthread.h pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1; pub const PTHREAD_CREATE_JOINABLE: c_int = 0; pub const PTHREAD_CREATE_DETACHED: c_int = 1; pub const PTHREAD_PROCESS_SHARED: c_int = 0; pub const PTHREAD_PROCESS_PRIVATE: c_ushort = 1; pub const PTHREAD_STACK_MIN: size_t = PAGESIZE as size_t * 4; pub const PTHREAD_MUTEX_NORMAL: c_int = 5; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 3; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 4; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_MUTEX_ROBUST: c_int = 1; pub const PTHREAD_MUTEX_STALLED: c_int = 0; pub const PTHREAD_PRIO_INHERIT: c_int = 3; pub const PTHREAD_PRIO_NONE: c_int = 1; pub const PTHREAD_PRIO_PROTECT: c_int = 2; // regex.h pub const REG_EXTENDED: c_int = 1; pub const REG_ICASE: c_int = 2; pub const REG_NEWLINE: c_int = 4; pub const REG_NOSUB: c_int = 8; pub const REG_NOTBOL: c_int = 0x100; pub const REG_NOTEOL: c_int = 0x200; pub const REG_NOMATCH: c_int = 1; pub const REG_BADPAT: c_int = 2; pub const REG_ECOLLATE: c_int = 3; pub const REG_ECTYPE: c_int = 4; pub const REG_EESCAPE: c_int = 5; pub const REG_ESUBREG: c_int = 6; pub const REG_EBRACK: c_int = 7; pub const REG_EPAREN: c_int = 8; pub const REG_EBRACE: c_int = 9; pub const REG_BADBR: c_int = 10; pub const REG_ERANGE: c_int = 11; pub const REG_ESPACE: c_int = 12; pub const REG_BADRPT: c_int = 13; pub const REG_ECHAR: c_int = 14; pub const REG_EBOL: c_int = 15; pub const REG_EEOL: c_int = 16; pub const REG_ENOSYS: c_int = 17; // rpcsvc/mount.h pub const NFSMNT_ACDIRMAX: c_int = 2048; pub const NFSMNT_ACDIRMIN: c_int = 1024; pub const NFSMNT_ACREGMAX: c_int = 512; pub const NFSMNT_ACREGMIN: c_int = 256; pub const NFSMNT_INT: c_int = 64; pub const NFSMNT_NOAC: c_int = 128; pub const NFSMNT_RETRANS: c_int = 16; pub const NFSMNT_RSIZE: c_int = 4; pub const NFSMNT_SOFT: c_int = 1; pub const NFSMNT_TIMEO: c_int = 8; pub const NFSMNT_WSIZE: c_int = 2; // rpcsvc/rstat.h pub const CPUSTATES: c_int = 4; // search.h pub const FIND: c_int = 0; pub const ENTER: c_int = 1; // semaphore.h pub const SEM_FAILED: *mut sem_t = -1isize as *mut crate::sem_t; // spawn.h // DIFF(main): changed to `c_short` in f62eb023ab pub const POSIX_SPAWN_SETPGROUP: c_int = 0x1; pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x2; pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x4; pub const POSIX_SPAWN_SETSCHEDULER: c_int = 0x8; pub const POSIX_SPAWN_SETSCHEDPARAM: c_int = 0x10; pub const POSIX_SPAWN_RESETIDS: c_int = 0x20; pub const POSIX_SPAWN_FORK_HANDLERS: c_int = 0x1000; // stdio.h pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0o000; pub const _IONBF: c_int = 0o004; pub const _IOLBF: c_int = 0o100; pub const BUFSIZ: c_uint = 4096; pub const FOPEN_MAX: c_uint = 32767; pub const FILENAME_MAX: c_uint = 255; pub const L_tmpnam: c_uint = 21; pub const TMP_MAX: c_uint = 16384; // stdlib.h pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 32767; // sys/access.h pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; // sys/aio.h pub const LIO_NOP: c_int = 0; pub const LIO_READ: c_int = 1; pub const LIO_WRITE: c_int = 2; pub const LIO_NOWAIT: c_int = 0; pub const LIO_WAIT: c_int = 1; pub const AIO_ALLDONE: c_int = 2; pub const AIO_CANCELED: c_int = 0; pub const AIO_NOTCANCELED: c_int = 1; // sys/errno.h pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const ENOMSG: c_int = 35; pub const EIDRM: c_int = 36; pub const ECHRNG: c_int = 37; pub const EL2NSYNC: c_int = 38; pub const EL3HLT: c_int = 39; pub const EL3RST: c_int = 40; pub const ELNRNG: c_int = 41; pub const EUNATCH: c_int = 42; pub const ENOCSI: c_int = 43; pub const EL2HLT: c_int = 44; pub const EDEADLK: c_int = 45; pub const ENOLCK: c_int = 49; pub const ECANCELED: c_int = 117; pub const ENOTSUP: c_int = 124; pub const EPROCLIM: c_int = 83; pub const EDQUOT: c_int = 88; pub const EOWNERDEAD: c_int = 95; pub const ENOTRECOVERABLE: c_int = 94; pub const ENOSTR: c_int = 123; pub const ENODATA: c_int = 122; pub const ETIME: c_int = 119; pub const ENOSR: c_int = 118; pub const EREMOTE: c_int = 93; pub const ENOATTR: c_int = 112; pub const ESAD: c_int = 113; pub const ENOTRUST: c_int = 114; pub const ENOLINK: c_int = 126; pub const EPROTO: c_int = 121; pub const EMULTIHOP: c_int = 125; pub const EBADMSG: c_int = 120; pub const ENAMETOOLONG: c_int = 86; pub const EOVERFLOW: c_int = 127; pub const EILSEQ: c_int = 116; pub const ENOSYS: c_int = 109; pub const ELOOP: c_int = 85; pub const ERESTART: c_int = 82; pub const ENOTEMPTY: c_int = 87; pub const EUSERS: c_int = 84; pub const ENOTSOCK: c_int = 57; pub const EDESTADDRREQ: c_int = 58; pub const EMSGSIZE: c_int = 59; pub const EPROTOTYPE: c_int = 60; pub const ENOPROTOOPT: c_int = 61; pub const EPROTONOSUPPORT: c_int = 62; pub const ESOCKTNOSUPPORT: c_int = 63; pub const EOPNOTSUPP: c_int = 64; pub const EPFNOSUPPORT: c_int = 65; pub const EAFNOSUPPORT: c_int = 66; pub const EADDRINUSE: c_int = 67; pub const EADDRNOTAVAIL: c_int = 68; pub const ENETDOWN: c_int = 69; pub const ENETUNREACH: c_int = 70; pub const ENETRESET: c_int = 71; pub const ECONNABORTED: c_int = 72; pub const ECONNRESET: c_int = 73; pub const ENOBUFS: c_int = 74; pub const EISCONN: c_int = 75; pub const ENOTCONN: c_int = 76; pub const ESHUTDOWN: c_int = 77; pub const ETOOMANYREFS: c_int = 115; pub const ETIMEDOUT: c_int = 78; pub const ECONNREFUSED: c_int = 79; pub const EHOSTDOWN: c_int = 80; pub const EHOSTUNREACH: c_int = 81; pub const EWOULDBLOCK: c_int = EAGAIN; pub const EALREADY: c_int = 56; pub const EINPROGRESS: c_int = 55; pub const ESTALE: c_int = 52; // sys/dr.h pub const LPAR_INFO_FORMAT1: c_int = 1; pub const LPAR_INFO_FORMAT2: c_int = 2; pub const WPAR_INFO_FORMAT: c_int = 3; pub const PROC_MODULE_INFO: c_int = 4; pub const NUM_PROC_MODULE_TYPES: c_int = 5; pub const LPAR_INFO_VRME_NUM_POOLS: c_int = 6; pub const LPAR_INFO_VRME_POOLS: c_int = 7; pub const LPAR_INFO_VRME_LPAR: c_int = 8; pub const LPAR_INFO_VRME_RESET_HWMARKS: c_int = 9; pub const LPAR_INFO_VRME_ALLOW_DESIRED: c_int = 10; pub const EMTP_INFO_FORMAT: c_int = 11; pub const LPAR_INFO_LPM_CAPABILITY: c_int = 12; pub const ENERGYSCALE_INFO: c_int = 13; // sys/file.h pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; // sys/flock.h pub const F_RDLCK: c_short = 0o01; pub const F_WRLCK: c_short = 0o02; pub const F_UNLCK: c_short = 0o03; // sys/fs/quota_common.h pub const Q_QUOTAON: c_int = 0x100; pub const Q_QUOTAOFF: c_int = 0x200; pub const Q_SETUSE: c_int = 0x500; pub const Q_SYNC: c_int = 0x600; pub const Q_GETQUOTA: c_int = 0x300; pub const Q_SETQLIM: c_int = 0x400; pub const Q_SETQUOTA: c_int = 0x400; // sys/ioctl.h pub const IOCPARM_MASK: c_int = 0x7f; pub const IOC_VOID: c_int = 0x20000000; pub const IOC_OUT: c_int = 0x40000000; pub const IOC_IN: c_int = 0x40000000 << 1; pub const IOC_INOUT: c_int = IOC_IN | IOC_OUT; pub const FIOCLEX: c_int = 536897025; pub const FIONCLEX: c_int = 536897026; pub const FIONREAD: c_int = 1074030207; pub const FIONBIO: c_int = -2147195266; pub const FIOASYNC: c_int = -2147195267; pub const FIOSETOWN: c_int = -2147195268; pub const FIOGETOWN: c_int = 1074030203; pub const TIOCGETD: c_int = 0x40047400; pub const TIOCSETD: c_int = 0x80047401; pub const TIOCHPCL: c_int = 0x20007402; pub const TIOCMODG: c_int = 0x40047403; pub const TIOCMODS: c_int = 0x80047404; pub const TIOCM_LE: c_int = 0x1; pub const TIOCM_DTR: c_int = 0x2; pub const TIOCM_RTS: c_int = 0x4; pub const TIOCM_ST: c_int = 0x8; pub const TIOCM_SR: c_int = 0x10; pub const TIOCM_CTS: c_int = 0x20; pub const TIOCM_CAR: c_int = 0x40; pub const TIOCM_CD: c_int = 0x40; pub const TIOCM_RNG: c_int = 0x80; pub const TIOCM_RI: c_int = 0x80; pub const TIOCM_DSR: c_int = 0x100; pub const TIOCGETP: c_int = 0x40067408; pub const TIOCSETP: c_int = 0x80067409; pub const TIOCSETN: c_int = 0x8006740a; pub const TIOCEXCL: c_int = 0x2000740d; pub const TIOCNXCL: c_int = 0x2000740e; pub const TIOCFLUSH: c_int = 0x80047410; pub const TIOCSETC: c_int = 0x80067411; pub const TIOCGETC: c_int = 0x40067412; pub const TANDEM: c_int = 0x1; pub const CBREAK: c_int = 0x2; pub const LCASE: c_int = 0x4; pub const MDMBUF: c_int = 0x800000; pub const XTABS: c_int = 0xc00; pub const SIOCADDMULTI: c_int = -2145359567; pub const SIOCADDRT: c_int = -2143784438; pub const SIOCDARP: c_int = -2142476000; pub const SIOCDELMULTI: c_int = -2145359566; pub const SIOCDELRT: c_int = -2143784437; pub const SIOCDIFADDR: c_int = -2144835303; pub const SIOCGARP: c_int = -1068734170; pub const SIOCGIFADDR: c_int = -1071093471; pub const SIOCGIFBRDADDR: c_int = -1071093469; pub const SIOCGIFCONF: c_int = -1072666299; pub const SIOCGIFDSTADDR: c_int = -1071093470; pub const SIOCGIFFLAGS: c_int = -1071093487; pub const SIOCGIFHWADDR: c_int = -1068209771; pub const SIOCGIFMETRIC: c_int = -1071093481; pub const SIOCGIFMTU: c_int = -1071093418; pub const SIOCGIFNETMASK: c_int = -1071093467; pub const SIOCSARP: c_int = -2142476002; pub const SIOCSIFADDR: c_int = -2144835316; pub const SIOCSIFBRDADDR: c_int = -2144835309; pub const SIOCSIFDSTADDR: c_int = -2144835314; pub const SIOCSIFFLAGS: c_int = -2144835312; pub const SIOCSIFMETRIC: c_int = -2144835304; pub const SIOCSIFMTU: c_int = -2144835240; pub const SIOCSIFNETMASK: c_int = -2144835306; pub const TIOCUCNTL: c_int = -2147191706; pub const TIOCCONS: c_int = -2147191710; pub const TIOCPKT: c_int = -2147191696; pub const TIOCPKT_DATA: c_int = 0; pub const TIOCPKT_FLUSHREAD: c_int = 1; pub const TIOCPKT_FLUSHWRITE: c_int = 2; pub const TIOCPKT_NOSTOP: c_int = 0x10; pub const TIOCPKT_DOSTOP: c_int = 0x20; pub const TIOCPKT_START: c_int = 8; pub const TIOCPKT_STOP: c_int = 4; // sys/ipc.h pub const IPC_ALLOC: c_int = 0o100000; pub const IPC_CREAT: c_int = 0o020000; pub const IPC_EXCL: c_int = 0o002000; pub const IPC_NOWAIT: c_int = 0o004000; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 101; pub const IPC_R: c_int = 0o0400; pub const IPC_W: c_int = 0o0200; pub const IPC_O: c_int = 0o1000; pub const IPC_NOERROR: c_int = 0o10000; pub const IPC_STAT: c_int = 102; pub const IPC_PRIVATE: crate::key_t = -1; pub const SHM_LOCK: c_int = 201; pub const SHM_UNLOCK: c_int = 202; // sys/ldr.h pub const L_GETINFO: c_int = 2; pub const L_GETMESSAGE: c_int = 1; pub const L_GETLIBPATH: c_int = 3; pub const L_GETXINFO: c_int = 8; // sys/limits.h pub const PATH_MAX: c_int = 1023; pub const PAGESIZE: c_int = 4096; pub const IOV_MAX: c_int = 16; pub const AIO_LISTIO_MAX: c_int = 4096; pub const PIPE_BUF: usize = 32768; pub const OPEN_MAX: c_int = 65534; pub const MAX_INPUT: c_int = 512; pub const MAX_CANON: c_int = 256; pub const ARG_MAX: c_int = 1048576; pub const BC_BASE_MAX: c_int = 99; pub const BC_DIM_MAX: c_int = 0x800; pub const BC_SCALE_MAX: c_int = 99; pub const BC_STRING_MAX: c_int = 0x800; pub const CHARCLASS_NAME_MAX: c_int = 14; pub const CHILD_MAX: c_int = 128; pub const COLL_WEIGHTS_MAX: c_int = 4; pub const EXPR_NEST_MAX: c_int = 32; pub const NZERO: c_int = 20; // sys/lockf.h pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; // sys/machine.h pub const BIG_ENDIAN: c_int = 4321; pub const LITTLE_ENDIAN: c_int = 1234; pub const PDP_ENDIAN: c_int = 3412; // sys/mman.h pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const MAP_FILE: c_int = 0; pub const MAP_SHARED: c_int = 1; pub const MAP_PRIVATE: c_int = 2; pub const MAP_FIXED: c_int = 0x100; pub const MAP_ANON: c_int = 0x10; pub const MAP_ANONYMOUS: c_int = 0x10; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const MAP_TYPE: c_int = 0xf0; pub const MCL_CURRENT: c_int = 0x100; pub const MCL_FUTURE: c_int = 0x200; pub const MS_SYNC: c_int = 0x20; pub const MS_ASYNC: c_int = 0x10; pub const MS_INVALIDATE: c_int = 0x40; pub const POSIX_MADV_NORMAL: c_int = 1; pub const POSIX_MADV_RANDOM: c_int = 3; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 4; pub const POSIX_MADV_DONTNEED: c_int = 5; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; // sys/mode.h pub const S_IFMT: mode_t = 0o17_0000; pub const S_IFREG: mode_t = 0o10_0000; pub const S_IFDIR: mode_t = 0o4_0000; pub const S_IFBLK: mode_t = 0o6_0000; pub const S_IFCHR: mode_t = 0o2_0000; pub const S_IFIFO: mode_t = 0o1_0000; pub const S_IRWXU: mode_t = 0o0700; pub const S_IRUSR: mode_t = 0o0400; pub const S_IWUSR: mode_t = 0o0200; pub const S_IXUSR: mode_t = 0o0100; pub const S_IRWXG: mode_t = 0o0070; pub const S_IRGRP: mode_t = 0o0040; pub const S_IWGRP: mode_t = 0o0020; pub const S_IXGRP: mode_t = 0o0010; pub const S_IRWXO: mode_t = 0o0007; pub const S_IROTH: mode_t = 0o0004; pub const S_IWOTH: mode_t = 0o0002; pub const S_IXOTH: mode_t = 0o0001; pub const S_IFLNK: mode_t = 0o12_0000; pub const S_IFSOCK: mode_t = 0o14_0000; pub const S_IEXEC: mode_t = 0o0100; pub const S_IWRITE: mode_t = 0o0200; pub const S_IREAD: mode_t = 0o0400; // sys/msg.h pub const MSG_NOERROR: c_int = 0o10000; // sys/m_signal.h pub const SIGSTKSZ: size_t = 4096; pub const MINSIGSTKSZ: size_t = 1200; // sys/params.h pub const MAXPATHLEN: c_int = PATH_MAX + 1; pub const MAXSYMLINKS: c_int = 20; pub const MAXHOSTNAMELEN: c_int = 256; pub const MAXUPRC: c_int = 128; pub const NGROUPS_MAX: c_ulong = 2048; pub const NGROUPS: c_ulong = NGROUPS_MAX; pub const NOFILE: c_int = OPEN_MAX; // sys/poll.h pub const POLLIN: c_short = 0x0001; pub const POLLPRI: c_short = 0x0004; pub const POLLOUT: c_short = 0x0002; pub const POLLERR: c_short = 0x4000; pub const POLLHUP: c_short = 0x2000; pub const POLLMSG: c_short = 0x0080; pub const POLLSYNC: c_short = 0x8000; pub const POLLNVAL: c_short = POLLSYNC; pub const POLLNORM: c_short = POLLIN; pub const POLLRDNORM: c_short = 0x0010; pub const POLLWRNORM: c_short = POLLOUT; pub const POLLRDBAND: c_short = 0x0020; pub const POLLWRBAND: c_short = 0x0040; // sys/pollset.h pub const PS_ADD: c_uchar = 0; pub const PS_MOD: c_uchar = 1; pub const PS_DELETE: c_uchar = 2; pub const PS_REPLACE: c_uchar = 3; // sys/ptrace.h pub const PT_TRACE_ME: c_int = 0; pub const PT_READ_I: c_int = 1; pub const PT_READ_D: c_int = 2; pub const PT_WRITE_I: c_int = 4; pub const PT_WRITE_D: c_int = 5; pub const PT_CONTINUE: c_int = 7; pub const PT_KILL: c_int = 8; pub const PT_STEP: c_int = 9; pub const PT_READ_GPR: c_int = 11; pub const PT_READ_FPR: c_int = 12; pub const PT_WRITE_GPR: c_int = 14; pub const PT_WRITE_FPR: c_int = 15; pub const PT_READ_BLOCK: c_int = 17; pub const PT_WRITE_BLOCK: c_int = 19; pub const PT_ATTACH: c_int = 30; pub const PT_DETACH: c_int = 31; pub const PT_REGSET: c_int = 32; pub const PT_REATT: c_int = 33; pub const PT_LDINFO: c_int = 34; pub const PT_MULTI: c_int = 35; pub const PT_NEXT: c_int = 36; pub const PT_SET: c_int = 37; pub const PT_CLEAR: c_int = 38; pub const PT_LDXINFO: c_int = 39; pub const PT_QUERY: c_int = 40; pub const PT_WATCH: c_int = 41; pub const PTT_CONTINUE: c_int = 50; pub const PTT_STEP: c_int = 51; pub const PTT_READ_SPRS: c_int = 52; pub const PTT_WRITE_SPRS: c_int = 53; pub const PTT_READ_GPRS: c_int = 54; pub const PTT_WRITE_GPRS: c_int = 55; pub const PTT_READ_FPRS: c_int = 56; pub const PTT_WRITE_FPRS: c_int = 57; pub const PTT_READ_VEC: c_int = 58; pub const PTT_WRITE_VEC: c_int = 59; pub const PTT_WATCH: c_int = 60; pub const PTT_SET_TRAP: c_int = 61; pub const PTT_CLEAR_TRAP: c_int = 62; pub const PTT_READ_UKEYSET: c_int = 63; pub const PT_GET_UKEY: c_int = 64; pub const PTT_READ_FPSCR_HI: c_int = 65; pub const PTT_WRITE_FPSCR_HI: c_int = 66; pub const PTT_READ_VSX: c_int = 67; pub const PTT_WRITE_VSX: c_int = 68; pub const PTT_READ_TM: c_int = 69; pub const PTRACE_ATTACH: c_int = 14; pub const PTRACE_CONT: c_int = 7; pub const PTRACE_DETACH: c_int = 15; pub const PTRACE_GETFPREGS: c_int = 12; pub const PTRACE_GETREGS: c_int = 10; pub const PTRACE_KILL: c_int = 8; pub const PTRACE_PEEKDATA: c_int = 2; pub const PTRACE_PEEKTEXT: c_int = 1; pub const PTRACE_PEEKUSER: c_int = 3; pub const PTRACE_POKEDATA: c_int = 5; pub const PTRACE_POKETEXT: c_int = 4; pub const PTRACE_POKEUSER: c_int = 6; pub const PTRACE_SETFPREGS: c_int = 13; pub const PTRACE_SETREGS: c_int = 11; pub const PTRACE_SINGLESTEP: c_int = 9; pub const PTRACE_SYSCALL: c_int = 16; pub const PTRACE_TRACEME: c_int = 0; // sys/resource.h pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_RSS: c_int = 5; pub const RLIMIT_AS: c_int = 6; pub const RLIMIT_NOFILE: c_int = 7; pub const RLIMIT_THREADS: c_int = 8; pub const RLIMIT_NPROC: c_int = 9; pub const RUSAGE_SELF: c_int = 0; pub const RUSAGE_CHILDREN: c_int = -1; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; pub const RUSAGE_THREAD: c_int = 1; pub const RLIM_SAVED_MAX: c_ulong = RLIM_INFINITY - 1; pub const RLIM_SAVED_CUR: c_ulong = RLIM_INFINITY - 2; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 10; // sys/sched.h pub const SCHED_OTHER: c_int = 0; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const SCHED_LOCAL: c_int = 3; pub const SCHED_GLOBAL: c_int = 4; pub const SCHED_FIFO2: c_int = 5; pub const SCHED_FIFO3: c_int = 6; pub const SCHED_FIFO4: c_int = 7; // sys/sem.h pub const SEM_UNDO: c_int = 0o10000; pub const GETNCNT: c_int = 3; pub const GETPID: c_int = 4; pub const GETVAL: c_int = 5; pub const GETALL: c_int = 6; pub const GETZCNT: c_int = 7; pub const SETVAL: c_int = 8; pub const SETALL: c_int = 9; // sys/shm.h pub const SHMLBA: c_int = 0x10000000; pub const SHMLBA_EXTSHM: c_int = 0x1000; pub const SHM_SHMAT: c_int = 0x80000000; pub const SHM_RDONLY: c_int = 0o10000; pub const SHM_RND: c_int = 0o20000; pub const SHM_PIN: c_int = 0o4000; pub const SHM_LGPAGE: c_int = 0o20000000000; pub const SHM_MAP: c_int = 0o4000; pub const SHM_FMAP: c_int = 0o2000; pub const SHM_COPY: c_int = 0o40000; pub const SHM_CLEAR: c_int = 0; pub const SHM_HGSEG: c_int = 0o10000000000; pub const SHM_R: c_int = IPC_R; pub const SHM_W: c_int = IPC_W; pub const SHM_DEST: c_int = 0o2000; // sys/signal.h pub const SA_ONSTACK: c_int = 0x00000001; pub const SA_RESETHAND: c_int = 0x00000002; pub const SA_RESTART: c_int = 0x00000008; pub const SA_SIGINFO: c_int = 0x00000100; pub const SA_NODEFER: c_int = 0x00000200; pub const SA_NOCLDWAIT: c_int = 0x00000400; pub const SA_NOCLDSTOP: c_int = 0x00000004; pub const SS_ONSTACK: c_int = 0x00000001; pub const SS_DISABLE: c_int = 0x00000002; pub const SIGCHLD: c_int = 20; pub const SIGBUS: c_int = 10; pub const SIG_BLOCK: c_int = 0; pub const SIG_UNBLOCK: c_int = 1; pub const SIG_SETMASK: c_int = 2; pub const SIGEV_NONE: c_int = 1; pub const SIGEV_SIGNAL: c_int = 2; pub const SIGEV_THREAD: c_int = 3; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSEGV: c_int = 11; pub const SIGSYS: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGPWR: c_int = 29; pub const SIGWINCH: c_int = 28; pub const SIGURG: c_int = 16; pub const SIGPOLL: c_int = SIGIO; pub const SIGIO: c_int = 23; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGCONT: c_int = 19; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGVTALRM: c_int = 34; pub const SIGPROF: c_int = 32; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGTRAP: c_int = 5; pub const SIGCLD: c_int = 20; pub const SIGRTMAX: c_int = 57; pub const SIGRTMIN: c_int = 50; pub const SI_USER: c_int = 0; pub const SI_UNDEFINED: c_int = 8; pub const SI_EMPTY: c_int = 9; pub const BUS_ADRALN: c_int = 1; pub const BUS_ADRERR: c_int = 2; pub const BUS_OBJERR: c_int = 3; pub const BUS_UEGARD: c_int = 4; pub const CLD_EXITED: c_int = 10; pub const CLD_KILLED: c_int = 11; pub const CLD_DUMPED: c_int = 12; pub const CLD_TRAPPED: c_int = 13; pub const CLD_STOPPED: c_int = 14; pub const CLD_CONTINUED: c_int = 15; pub const FPE_INTDIV: c_int = 20; pub const FPE_INTOVF: c_int = 21; pub const FPE_FLTDIV: c_int = 22; pub const FPE_FLTOVF: c_int = 23; pub const FPE_FLTUND: c_int = 24; pub const FPE_FLTRES: c_int = 25; pub const FPE_FLTINV: c_int = 26; pub const FPE_FLTSUB: c_int = 27; pub const ILL_ILLOPC: c_int = 30; pub const ILL_ILLOPN: c_int = 31; pub const ILL_ILLADR: c_int = 32; pub const ILL_ILLTRP: c_int = 33; pub const ILL_PRVOPC: c_int = 34; pub const ILL_PRVREG: c_int = 35; pub const ILL_COPROC: c_int = 36; pub const ILL_BADSTK: c_int = 37; pub const ILL_TMBADTHING: c_int = 38; pub const POLL_IN: c_int = 40; pub const POLL_OUT: c_int = 41; pub const POLL_MSG: c_int = -3; pub const POLL_ERR: c_int = 43; pub const POLL_PRI: c_int = 44; pub const POLL_HUP: c_int = 45; pub const SEGV_MAPERR: c_int = 50; pub const SEGV_ACCERR: c_int = 51; pub const SEGV_KEYERR: c_int = 52; pub const TRAP_BRKPT: c_int = 60; pub const TRAP_TRACE: c_int = 61; pub const SI_QUEUE: c_int = 71; pub const SI_TIMER: c_int = 72; pub const SI_ASYNCIO: c_int = 73; pub const SI_MESGQ: c_int = 74; // sys/socket.h pub const AF_UNSPEC: c_int = 0; pub const AF_UNIX: c_int = 1; pub const AF_INET: c_int = 2; pub const AF_IMPLINK: c_int = 3; pub const AF_PUP: c_int = 4; pub const AF_CHAOS: c_int = 5; pub const AF_NS: c_int = 6; pub const AF_ECMA: c_int = 8; pub const AF_DATAKIT: c_int = 9; pub const AF_CCITT: c_int = 10; pub const AF_SNA: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_DLI: c_int = 13; pub const AF_LAT: c_int = 14; pub const SO_TIMESTAMPNS: c_int = 0x100a; pub const SOMAXCONN: c_int = 1024; pub const AF_LOCAL: c_int = AF_UNIX; pub const UIO_MAXIOV: c_int = 1024; pub const pseudo_AF_XTP: c_int = 19; pub const AF_HYLINK: c_int = 15; pub const AF_APPLETALK: c_int = 16; pub const AF_ISO: c_int = 7; pub const AF_OSI: c_int = AF_ISO; pub const AF_ROUTE: c_int = 17; pub const AF_LINK: c_int = 18; pub const AF_INET6: c_int = 24; pub const AF_INTF: c_int = 20; pub const AF_RIF: c_int = 21; pub const AF_NDD: c_int = 23; pub const AF_MAX: c_int = 30; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_UNIX: c_int = AF_UNIX; pub const PF_INET: c_int = AF_INET; pub const PF_IMPLINK: c_int = AF_IMPLINK; pub const PF_PUP: c_int = AF_PUP; pub const PF_CHAOS: c_int = AF_CHAOS; pub const PF_NS: c_int = AF_NS; pub const PF_ISO: c_int = AF_ISO; pub const PF_OSI: c_int = AF_ISO; pub const PF_ECMA: c_int = AF_ECMA; pub const PF_DATAKIT: c_int = AF_DATAKIT; pub const PF_CCITT: c_int = AF_CCITT; pub const PF_SNA: c_int = AF_SNA; pub const PF_DECnet: c_int = AF_DECnet; pub const PF_DLI: c_int = AF_DLI; pub const PF_LAT: c_int = AF_LAT; pub const PF_HYLINK: c_int = AF_HYLINK; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_LINK: c_int = AF_LINK; pub const PF_XTP: c_int = 19; pub const PF_RIF: c_int = AF_RIF; pub const PF_INTF: c_int = AF_INTF; pub const PF_NDD: c_int = AF_NDD; pub const PF_INET6: c_int = AF_INET6; pub const PF_MAX: c_int = AF_MAX; pub const SF_CLOSE: c_int = 1; pub const SF_REUSE: c_int = 2; pub const SF_DONT_CACHE: c_int = 4; pub const SF_SYNC_CACHE: c_int = 8; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_STREAM: c_int = 1; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_SEQPACKET: c_int = 5; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_DEBUG: c_int = 0x0001; pub const SO_ACCEPTCONN: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_USELOOPBACK: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_USE_IFBUFS: c_int = 0x0400; pub const SO_CKSUMRECV: c_int = 0x0800; pub const SO_NOREUSEADDR: c_int = 0x1000; pub const SO_KERNACCEPT: c_int = 0x2000; pub const SO_NOMULTIPATH: c_int = 0x4000; pub const SO_AUDIT: c_int = 0x8000; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVLOWAT: c_int = 0x1004; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; pub const SO_TYPE: c_int = 0x1008; pub const SCM_RIGHTS: c_int = 0x01; pub const MSG_OOB: c_int = 0x1; pub const MSG_PEEK: c_int = 0x2; pub const MSG_DONTROUTE: c_int = 0x4; pub const MSG_EOR: c_int = 0x8; pub const MSG_TRUNC: c_int = 0x10; pub const MSG_CTRUNC: c_int = 0x20; pub const MSG_WAITALL: c_int = 0x40; pub const MSG_MPEG2: c_int = 0x80; pub const MSG_NOSIGNAL: c_int = 0x100; pub const MSG_WAITFORONE: c_int = 0x200; pub const MSG_ARGEXT: c_int = 0x400; pub const MSG_NONBLOCK: c_int = 0x4000; pub const MSG_COMPAT: c_int = 0x8000; pub const MSG_MAXIOVLEN: c_int = 16; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; // sys/stat.h pub const UTIME_NOW: c_int = -2; pub const UTIME_OMIT: c_int = -3; // sys/statvfs.h pub const ST_RDONLY: c_ulong = 0x0001; pub const ST_NOSUID: c_ulong = 0x0040; pub const ST_NODEV: c_ulong = 0x0080; // sys/stropts.h pub const I_NREAD: c_int = 0x20005301; pub const I_PUSH: c_int = 0x20005302; pub const I_POP: c_int = 0x20005303; pub const I_LOOK: c_int = 0x20005304; pub const I_FLUSH: c_int = 0x20005305; pub const I_SRDOPT: c_int = 0x20005306; pub const I_GRDOPT: c_int = 0x20005307; pub const I_STR: c_int = 0x20005308; pub const I_SETSIG: c_int = 0x20005309; pub const I_GETSIG: c_int = 0x2000530a; pub const I_FIND: c_int = 0x2000530b; pub const I_LINK: c_int = 0x2000530c; pub const I_UNLINK: c_int = 0x2000530d; pub const I_PEEK: c_int = 0x2000530f; pub const I_FDINSERT: c_int = 0x20005310; pub const I_SENDFD: c_int = 0x20005311; pub const I_RECVFD: c_int = 0x20005312; pub const I_SWROPT: c_int = 0x20005314; pub const I_GWROPT: c_int = 0x20005315; pub const I_LIST: c_int = 0x20005316; pub const I_PLINK: c_int = 0x2000531d; pub const I_PUNLINK: c_int = 0x2000531e; pub const I_FLUSHBAND: c_int = 0x20005313; pub const I_CKBAND: c_int = 0x20005318; pub const I_GETBAND: c_int = 0x20005319; pub const I_ATMARK: c_int = 0x20005317; pub const I_SETCLTIME: c_int = 0x2000531b; pub const I_GETCLTIME: c_int = 0x2000531c; pub const I_CANPUT: c_int = 0x2000531a; // sys/syslog.h pub const LOG_CRON: c_int = 9 << 3; pub const LOG_AUTHPRIV: c_int = 10 << 3; pub const LOG_NFACILITIES: c_int = 24; pub const LOG_PERROR: c_int = 0x20; // sys/systemcfg.h pub const SC_ARCH: c_int = 1; pub const SC_IMPL: c_int = 2; pub const SC_VERS: c_int = 3; pub const SC_WIDTH: c_int = 4; pub const SC_NCPUS: c_int = 5; pub const SC_L1C_ATTR: c_int = 6; pub const SC_L1C_ISZ: c_int = 7; pub const SC_L1C_DSZ: c_int = 8; pub const SC_L1C_ICA: c_int = 9; pub const SC_L1C_DCA: c_int = 10; pub const SC_L1C_IBS: c_int = 11; pub const SC_L1C_DBS: c_int = 12; pub const SC_L1C_ILS: c_int = 13; pub const SC_L1C_DLS: c_int = 14; pub const SC_L2C_SZ: c_int = 15; pub const SC_L2C_AS: c_int = 16; pub const SC_TLB_ATTR: c_int = 17; pub const SC_ITLB_SZ: c_int = 18; pub const SC_DTLB_SZ: c_int = 19; pub const SC_ITLB_ATT: c_int = 20; pub const SC_DTLB_ATT: c_int = 21; pub const SC_RESRV_SZ: c_int = 22; pub const SC_PRI_LC: c_int = 23; pub const SC_PRO_LC: c_int = 24; pub const SC_RTC_TYPE: c_int = 25; pub const SC_VIRT_AL: c_int = 26; pub const SC_CAC_CONG: c_int = 27; pub const SC_MOD_ARCH: c_int = 28; pub const SC_MOD_IMPL: c_int = 29; pub const SC_XINT: c_int = 30; pub const SC_XFRAC: c_int = 31; pub const SC_KRN_ATTR: c_int = 32; pub const SC_PHYSMEM: c_int = 33; pub const SC_SLB_ATTR: c_int = 34; pub const SC_SLB_SZ: c_int = 35; pub const SC_MAX_NCPUS: c_int = 37; pub const SC_MAX_REALADDR: c_int = 38; pub const SC_ORIG_ENT_CAP: c_int = 39; pub const SC_ENT_CAP: c_int = 40; pub const SC_DISP_WHE: c_int = 41; pub const SC_CAPINC: c_int = 42; pub const SC_VCAPW: c_int = 43; pub const SC_SPLP_STAT: c_int = 44; pub const SC_SMT_STAT: c_int = 45; pub const SC_SMT_TC: c_int = 46; pub const SC_VMX_VER: c_int = 47; pub const SC_LMB_SZ: c_int = 48; pub const SC_MAX_XCPU: c_int = 49; pub const SC_EC_LVL: c_int = 50; pub const SC_AME_STAT: c_int = 51; pub const SC_ECO_STAT: c_int = 52; pub const SC_DFP_VER: c_int = 53; pub const SC_VRM_STAT: c_int = 54; pub const SC_PHYS_IMP: c_int = 55; pub const SC_PHYS_VER: c_int = 56; pub const SC_SPCM_STATUS: c_int = 57; pub const SC_SPCM_MAX: c_int = 58; pub const SC_TM_VER: c_int = 59; pub const SC_NX_CAP: c_int = 60; pub const SC_PKS_STATE: c_int = 61; pub const SC_MMA_VER: c_int = 62; pub const POWER_RS: c_int = 1; pub const POWER_PC: c_int = 2; pub const IA64: c_int = 3; pub const POWER_RS1: c_int = 0x1; pub const POWER_RSC: c_int = 0x2; pub const POWER_RS2: c_int = 0x4; pub const POWER_601: c_int = 0x8; pub const POWER_604: c_int = 0x10; pub const POWER_603: c_int = 0x20; pub const POWER_620: c_int = 0x40; pub const POWER_630: c_int = 0x80; pub const POWER_A35: c_int = 0x100; pub const POWER_RS64II: c_int = 0x200; pub const POWER_RS64III: c_int = 0x400; pub const POWER_4: c_int = 0x800; pub const POWER_RS64IV: c_int = POWER_4; pub const POWER_MPC7450: c_int = 0x1000; pub const POWER_5: c_int = 0x2000; pub const POWER_6: c_int = 0x4000; pub const POWER_7: c_int = 0x8000; pub const POWER_8: c_int = 0x10000; pub const POWER_9: c_int = 0x20000; // sys/time.h pub const FD_SETSIZE: usize = 65534; pub const TIMEOFDAY: c_int = 9; pub const CLOCK_REALTIME: crate::clockid_t = TIMEOFDAY as clockid_t; pub const CLOCK_MONOTONIC: crate::clockid_t = 10; pub const TIMER_ABSTIME: c_int = 999; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; pub const ITIMER_PROF: c_int = 2; pub const ITIMER_VIRT: c_int = 3; pub const ITIMER_REAL1: c_int = 20; pub const ITIMER_REAL_TH: c_int = ITIMER_REAL1; pub const DST_AUST: c_int = 2; pub const DST_CAN: c_int = 6; pub const DST_EET: c_int = 5; pub const DST_MET: c_int = 4; pub const DST_NONE: c_int = 0; pub const DST_USA: c_int = 1; pub const DST_WET: c_int = 3; // sys/termio.h pub const CSTART: crate::tcflag_t = 0o21; pub const CSTOP: crate::tcflag_t = 0o23; pub const TCGETA: c_int = TIOC | 5; pub const TCSETA: c_int = TIOC | 6; pub const TCSETAW: c_int = TIOC | 7; pub const TCSETAF: c_int = TIOC | 8; pub const TCSBRK: c_int = TIOC | 9; pub const TCXONC: c_int = TIOC | 11; pub const TCFLSH: c_int = TIOC | 12; pub const TCGETS: c_int = TIOC | 1; pub const TCSETS: c_int = TIOC | 2; pub const TCSANOW: c_int = 0; pub const TCSETSW: c_int = TIOC | 3; pub const TCSADRAIN: c_int = 1; pub const TCSETSF: c_int = TIOC | 4; pub const TCSAFLUSH: c_int = 2; pub const TCIFLUSH: c_int = 0; pub const TCOFLUSH: c_int = 1; pub const TCIOFLUSH: c_int = 2; pub const TCOOFF: c_int = 0; pub const TCOON: c_int = 1; pub const TCIOFF: c_int = 2; pub const TCION: c_int = 3; pub const TIOC: c_int = 0x5400; pub const TIOCGWINSZ: c_int = 0x40087468; pub const TIOCSWINSZ: c_int = 0x80087467; pub const TIOCLBIS: c_int = 0x8004747f; pub const TIOCLBIC: c_int = 0x8004747e; pub const TIOCLSET: c_int = 0x8004747d; pub const TIOCLGET: c_int = 0x4004747c; pub const TIOCSBRK: c_int = 0x2000747b; pub const TIOCCBRK: c_int = 0x2000747a; pub const TIOCSDTR: c_int = 0x20007479; pub const TIOCCDTR: c_int = 0x20007478; pub const TIOCSLTC: c_int = 0x80067475; pub const TIOCGLTC: c_int = 0x40067474; pub const TIOCOUTQ: c_int = 0x40047473; pub const TIOCNOTTY: c_int = 0x20007471; pub const TIOCSTOP: c_int = 0x2000746f; pub const TIOCSTART: c_int = 0x2000746e; pub const TIOCGPGRP: c_int = 0x40047477; pub const TIOCSPGRP: c_int = 0x80047476; pub const TIOCGSID: c_int = 0x40047448; pub const TIOCSTI: c_int = 0x80017472; pub const TIOCMSET: c_int = 0x8004746d; pub const TIOCMBIS: c_int = 0x8004746c; pub const TIOCMBIC: c_int = 0x8004746b; pub const TIOCMGET: c_int = 0x4004746a; pub const TIOCREMOTE: c_int = 0x80047469; // sys/user.h pub const MAXCOMLEN: c_int = 32; pub const UF_SYSTEM: c_int = 0x1000; // sys/vattr.h pub const AT_FLAGS: c_int = 0x80; pub const AT_GID: c_int = 8; pub const AT_UID: c_int = 4; // sys/wait.h pub const P_ALL: c_int = 0; pub const P_PID: c_int = 1; pub const P_PGID: c_int = 2; pub const WNOHANG: c_int = 0x1; pub const WUNTRACED: c_int = 0x2; pub const WEXITED: c_int = 0x04; pub const WCONTINUED: c_int = 0x01000000; pub const WNOWAIT: c_int = 0x10; pub const WSTOPPED: c_int = _W_STOPPED; pub const _W_STOPPED: c_int = 0x00000040; pub const _W_SLWTED: c_int = 0x0000007c; pub const _W_SEWTED: c_int = 0x0000007d; pub const _W_SFWTED: c_int = 0x0000007e; pub const _W_STRC: c_int = 0x0000007f; // termios.h pub const NCCS: usize = 16; pub const OLCUC: crate::tcflag_t = 2; pub const CSIZE: crate::tcflag_t = 0x00000030; pub const CS5: crate::tcflag_t = 0x00000000; pub const CS6: crate::tcflag_t = 0x00000010; pub const CS7: crate::tcflag_t = 0x00000020; pub const CS8: crate::tcflag_t = 0x00000030; pub const CSTOPB: crate::tcflag_t = 0x00000040; pub const ECHO: crate::tcflag_t = 0x20000; pub const ECHOE: crate::tcflag_t = 0x00000010; pub const ECHOK: crate::tcflag_t = 0x00000020; pub const ECHONL: crate::tcflag_t = 0x00000040; pub const ECHOCTL: crate::tcflag_t = 0x00020000; pub const ECHOPRT: crate::tcflag_t = 0x00040000; pub const ECHOKE: crate::tcflag_t = 0x00080000; pub const IGNBRK: crate::tcflag_t = 0x00000001; pub const BRKINT: crate::tcflag_t = 0x00000002; pub const IGNPAR: crate::tcflag_t = 0x00000004; pub const PARMRK: crate::tcflag_t = 0x00000008; pub const INPCK: crate::tcflag_t = 0x00000010; pub const ISTRIP: crate::tcflag_t = 0x00000020; pub const INLCR: crate::tcflag_t = 0x00000040; pub const IGNCR: crate::tcflag_t = 0x00000080; pub const ICRNL: crate::tcflag_t = 0x00000100; pub const IXON: crate::tcflag_t = 0x0001; pub const IXOFF: crate::tcflag_t = 0x00000400; pub const IXANY: crate::tcflag_t = 0x00001000; pub const IMAXBEL: crate::tcflag_t = 0x00010000; pub const OPOST: crate::tcflag_t = 0x00000001; pub const ONLCR: crate::tcflag_t = 0x00000004; pub const OCRNL: crate::tcflag_t = 0x00000008; pub const ONOCR: crate::tcflag_t = 0x00000010; pub const ONLRET: crate::tcflag_t = 0x00000020; pub const CREAD: crate::tcflag_t = 0x00000080; pub const IEXTEN: crate::tcflag_t = 0x00200000; pub const TOSTOP: crate::tcflag_t = 0x00010000; pub const FLUSHO: crate::tcflag_t = 0x00100000; pub const PENDIN: crate::tcflag_t = 0x20000000; pub const NOFLSH: crate::tcflag_t = 0x00000080; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VEOF: usize = 4; pub const VEOL: usize = 5; pub const VSTART: usize = 7; pub const VSTOP: usize = 8; pub const VSUSP: usize = 9; pub const VMIN: usize = 4; pub const VTIME: usize = 5; pub const VEOL2: usize = 6; pub const VDSUSP: usize = 10; pub const VREPRINT: usize = 11; pub const VDISCRD: usize = 12; pub const VWERSE: usize = 13; pub const VLNEXT: usize = 14; pub const B0: crate::speed_t = 0x0; pub const B50: crate::speed_t = 0x1; pub const B75: crate::speed_t = 0x2; pub const B110: crate::speed_t = 0x3; pub const B134: crate::speed_t = 0x4; pub const B150: crate::speed_t = 0x5; pub const B200: crate::speed_t = 0x6; pub const B300: crate::speed_t = 0x7; pub const B600: crate::speed_t = 0x8; pub const B1200: crate::speed_t = 0x9; pub const B1800: crate::speed_t = 0xa; pub const B2400: crate::speed_t = 0xb; pub const B4800: crate::speed_t = 0xc; pub const B9600: crate::speed_t = 0xd; pub const B19200: crate::speed_t = 0xe; pub const B38400: crate::speed_t = 0xf; pub const EXTA: crate::speed_t = B19200; pub const EXTB: crate::speed_t = B38400; pub const IUCLC: crate::tcflag_t = 0x00000800; pub const OFILL: crate::tcflag_t = 0x00000040; pub const OFDEL: crate::tcflag_t = 0x00000080; pub const CRDLY: crate::tcflag_t = 0x00000300; pub const CR0: crate::tcflag_t = 0x00000000; pub const CR1: crate::tcflag_t = 0x00000100; pub const CR2: crate::tcflag_t = 0x00000200; pub const CR3: crate::tcflag_t = 0x00000300; pub const TABDLY: crate::tcflag_t = 0x00000c00; pub const TAB0: crate::tcflag_t = 0x00000000; pub const TAB1: crate::tcflag_t = 0x00000400; pub const TAB2: crate::tcflag_t = 0x00000800; pub const TAB3: crate::tcflag_t = 0x00000c00; pub const BSDLY: crate::tcflag_t = 0x00001000; pub const BS0: crate::tcflag_t = 0x00000000; pub const BS1: crate::tcflag_t = 0x00001000; pub const FFDLY: crate::tcflag_t = 0x00002000; pub const FF0: crate::tcflag_t = 0x00000000; pub const FF1: crate::tcflag_t = 0x00002000; pub const NLDLY: crate::tcflag_t = 0x00004000; pub const NL0: crate::tcflag_t = 0x00000000; pub const NL1: crate::tcflag_t = 0x00004000; pub const VTDLY: crate::tcflag_t = 0x00008000; pub const VT0: crate::tcflag_t = 0x00000000; pub const VT1: crate::tcflag_t = 0x00008000; pub const OXTABS: crate::tcflag_t = 0x00040000; pub const ONOEOT: crate::tcflag_t = 0x00080000; pub const CBAUD: crate::tcflag_t = 0x0000000f; pub const PARENB: crate::tcflag_t = 0x00000100; pub const PARODD: crate::tcflag_t = 0x00000200; pub const HUPCL: crate::tcflag_t = 0x00000400; pub const CLOCAL: crate::tcflag_t = 0x00000800; pub const CIBAUD: crate::tcflag_t = 0x000f0000; pub const IBSHIFT: crate::tcflag_t = 16; pub const PAREXT: crate::tcflag_t = 0x00100000; pub const ISIG: crate::tcflag_t = 0x00000001; pub const ICANON: crate::tcflag_t = 0x00000002; pub const XCASE: crate::tcflag_t = 0x00000004; pub const ALTWERASE: crate::tcflag_t = 0x00400000; // time.h pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 11; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 12; // unistd.h pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const _POSIX_VDISABLE: c_int = 0xff; pub const _PC_LINK_MAX: c_int = 11; pub const _PC_MAX_CANON: c_int = 12; pub const _PC_MAX_INPUT: c_int = 13; pub const _PC_NAME_MAX: c_int = 14; pub const _PC_PATH_MAX: c_int = 16; pub const _PC_PIPE_BUF: c_int = 17; pub const _PC_NO_TRUNC: c_int = 15; pub const _PC_VDISABLE: c_int = 18; pub const _PC_CHOWN_RESTRICTED: c_int = 10; pub const _PC_ASYNC_IO: c_int = 19; pub const _PC_PRIO_IO: c_int = 21; pub const _PC_SYNC_IO: c_int = 20; pub const _PC_ALLOC_SIZE_MIN: c_int = 26; pub const _PC_REC_INCR_XFER_SIZE: c_int = 27; pub const _PC_REC_MAX_XFER_SIZE: c_int = 28; pub const _PC_REC_MIN_XFER_SIZE: c_int = 29; pub const _PC_REC_XFER_ALIGN: c_int = 30; pub const _PC_SYMLINK_MAX: c_int = 25; pub const _PC_2_SYMLINKS: c_int = 31; pub const _PC_TIMESTAMP_RESOLUTION: c_int = 32; pub const _PC_FILESIZEBITS: c_int = 22; pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_JOB_CONTROL: c_int = 7; pub const _SC_SAVED_IDS: c_int = 8; pub const _SC_VERSION: c_int = 9; pub const _SC_PASS_MAX: c_int = 45; pub const _SC_PAGESIZE: c_int = _SC_PAGE_SIZE; pub const _SC_PAGE_SIZE: c_int = 48; pub const _SC_XOPEN_VERSION: c_int = 46; pub const _SC_NPROCESSORS_CONF: c_int = 71; pub const _SC_NPROCESSORS_ONLN: c_int = 72; pub const _SC_STREAM_MAX: c_int = 5; pub const _SC_TZNAME_MAX: c_int = 6; pub const _SC_AIO_LISTIO_MAX: c_int = 75; pub const _SC_AIO_MAX: c_int = 76; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 77; pub const _SC_ASYNCHRONOUS_IO: c_int = 78; pub const _SC_DELAYTIMER_MAX: c_int = 79; pub const _SC_FSYNC: c_int = 80; pub const _SC_MAPPED_FILES: c_int = 84; pub const _SC_MEMLOCK: c_int = 85; pub const _SC_MEMLOCK_RANGE: c_int = 86; pub const _SC_MEMORY_PROTECTION: c_int = 87; pub const _SC_MESSAGE_PASSING: c_int = 88; pub const _SC_MQ_OPEN_MAX: c_int = 89; pub const _SC_MQ_PRIO_MAX: c_int = 90; pub const _SC_PRIORITIZED_IO: c_int = 91; pub const _SC_PRIORITY_SCHEDULING: c_int = 92; pub const _SC_REALTIME_SIGNALS: c_int = 93; pub const _SC_RTSIG_MAX: c_int = 94; pub const _SC_SEMAPHORES: c_int = 95; pub const _SC_SEM_NSEMS_MAX: c_int = 96; pub const _SC_SEM_VALUE_MAX: c_int = 97; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 98; pub const _SC_SIGQUEUE_MAX: c_int = 99; pub const _SC_SYNCHRONIZED_IO: c_int = 100; pub const _SC_TIMERS: c_int = 102; pub const _SC_TIMER_MAX: c_int = 103; pub const _SC_2_C_BIND: c_int = 51; pub const _SC_2_C_DEV: c_int = 32; pub const _SC_2_C_VERSION: c_int = 52; pub const _SC_2_FORT_DEV: c_int = 33; pub const _SC_2_FORT_RUN: c_int = 34; pub const _SC_2_LOCALEDEF: c_int = 35; pub const _SC_2_SW_DEV: c_int = 36; pub const _SC_2_UPE: c_int = 53; pub const _SC_2_VERSION: c_int = 31; pub const _SC_BC_BASE_MAX: c_int = 23; pub const _SC_BC_DIM_MAX: c_int = 24; pub const _SC_BC_SCALE_MAX: c_int = 25; pub const _SC_BC_STRING_MAX: c_int = 26; pub const _SC_COLL_WEIGHTS_MAX: c_int = 50; pub const _SC_EXPR_NEST_MAX: c_int = 28; pub const _SC_LINE_MAX: c_int = 29; pub const _SC_RE_DUP_MAX: c_int = 30; pub const _SC_XOPEN_CRYPT: c_int = 56; pub const _SC_XOPEN_ENH_I18N: c_int = 57; pub const _SC_XOPEN_SHM: c_int = 55; pub const _SC_2_CHAR_TERM: c_int = 54; pub const _SC_XOPEN_XCU_VERSION: c_int = 109; pub const _SC_ATEXIT_MAX: c_int = 47; pub const _SC_IOV_MAX: c_int = 58; pub const _SC_XOPEN_UNIX: c_int = 73; pub const _SC_T_IOV_MAX: c_int = 0; pub const _SC_PHYS_PAGES: c_int = 113; pub const _SC_AVPHYS_PAGES: c_int = 114; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 101; pub const _SC_GETGR_R_SIZE_MAX: c_int = 81; pub const _SC_GETPW_R_SIZE_MAX: c_int = 82; pub const _SC_LOGIN_NAME_MAX: c_int = 83; pub const _SC_THREAD_KEYS_MAX: c_int = 68; pub const _SC_THREAD_STACK_MIN: c_int = 69; pub const _SC_THREAD_THREADS_MAX: c_int = 70; pub const _SC_TTY_NAME_MAX: c_int = 104; pub const _SC_THREADS: c_int = 60; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 61; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 62; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 64; pub const _SC_THREAD_PRIO_INHERIT: c_int = 65; pub const _SC_THREAD_PRIO_PROTECT: c_int = 66; pub const _SC_THREAD_PROCESS_SHARED: c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 59; pub const _SC_XOPEN_LEGACY: c_int = 112; pub const _SC_XOPEN_REALTIME: c_int = 110; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 111; pub const _SC_XBS5_ILP32_OFF32: c_int = 105; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 106; pub const _SC_XBS5_LP64_OFF64: c_int = 107; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 108; pub const _SC_2_PBS: c_int = 132; pub const _SC_2_PBS_ACCOUNTING: c_int = 133; pub const _SC_2_PBS_CHECKPOINT: c_int = 134; pub const _SC_2_PBS_LOCATE: c_int = 135; pub const _SC_2_PBS_MESSAGE: c_int = 136; pub const _SC_2_PBS_TRACK: c_int = 137; pub const _SC_ADVISORY_INFO: c_int = 130; pub const _SC_BARRIERS: c_int = 138; pub const _SC_CLOCK_SELECTION: c_int = 139; pub const _SC_CPUTIME: c_int = 140; pub const _SC_HOST_NAME_MAX: c_int = 126; pub const _SC_MONOTONIC_CLOCK: c_int = 141; pub const _SC_READER_WRITER_LOCKS: c_int = 142; pub const _SC_REGEXP: c_int = 127; pub const _SC_SHELL: c_int = 128; pub const _SC_SPAWN: c_int = 143; pub const _SC_SPIN_LOCKS: c_int = 144; pub const _SC_SPORADIC_SERVER: c_int = 145; pub const _SC_SS_REPL_MAX: c_int = 156; pub const _SC_SYMLOOP_MAX: c_int = 129; pub const _SC_THREAD_CPUTIME: c_int = 146; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 147; pub const _SC_TIMEOUTS: c_int = 148; pub const _SC_TRACE: c_int = 149; pub const _SC_TRACE_EVENT_FILTER: c_int = 150; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 157; pub const _SC_TRACE_INHERIT: c_int = 151; pub const _SC_TRACE_LOG: c_int = 152; pub const _SC_TRACE_NAME_MAX: c_int = 158; pub const _SC_TRACE_SYS_MAX: c_int = 159; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 160; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 153; pub const _SC_V6_ILP32_OFF32: c_int = 121; pub const _SC_V6_ILP32_OFFBIG: c_int = 122; pub const _SC_V6_LP64_OFF64: c_int = 123; pub const _SC_V6_LPBIG_OFFBIG: c_int = 124; pub const _SC_XOPEN_STREAMS: c_int = 125; pub const _SC_IPV6: c_int = 154; pub const _SC_RAW_SOCKETS: c_int = 155; // utmp.h pub const EMPTY: c_short = -1; pub const RUN_LVL: c_short = 1; pub const BOOT_TIME: c_short = 2; pub const OLD_TIME: c_short = 3; pub const NEW_TIME: c_short = 4; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const USER_PROCESS: c_short = 7; pub const DEAD_PROCESS: c_short = 8; pub const ACCOUNTING: c_short = 9; f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { CMSG_FIRSTHDR(mhdr) } else { if (cmsg as usize + (*cmsg).cmsg_len as usize + mem::size_of::()) > ((*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize) { 0 as *mut cmsghdr } else { // AIX does not have any alignment/padding for ancillary data, so we don't need _CMSG_ALIGN here. (cmsg as usize + (*cmsg).cmsg_len as usize) as *mut cmsghdr } } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(mem::size_of::() as isize) } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { mem::size_of::() as c_uint + length } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { mem::size_of::() as c_uint + length } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let bits = mem::size_of::() * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] |= 1 << (fd % bits); return; } pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let bits = mem::size_of::() * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let bits = mem::size_of::() * 8; let fd = fd as usize; return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0; } } safe_f! { pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & _W_STOPPED) != 0 } pub {const} fn WSTOPSIG(status: c_int) -> c_int { if WIFSTOPPED(status) { (((status as c_uint) >> 8) & 0xff) as c_int } else { -1 } } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0xFF) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { if WIFEXITED(status) { (((status as c_uint) >> 8) & 0xff) as c_int } else { -1 } } pub {const} fn WIFSIGNALED(status: c_int) -> bool { !WIFEXITED(status) && !WIFSTOPPED(status) } pub {const} fn WTERMSIG(status: c_int) -> c_int { if WIFSIGNALED(status) { (((status as c_uint) >> 16) & 0xff) as c_int } else { -1 } } pub {const} fn WIFCONTINUED(status: c_int) -> bool { (status & WCONTINUED) != 0 } // AIX doesn't have native WCOREDUMP. pub {const} fn WCOREDUMP(_status: c_int) -> bool { false } pub {const} fn major(dev: crate::dev_t) -> c_uint { let x = dev >> 16; x as c_uint } pub {const} fn minor(dev: crate::dev_t) -> c_uint { let y = dev & 0xFFFF; y as c_uint } pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= major << 16; dev |= minor; dev } } #[link(name = "thread")] extern "C" { pub fn thr_kill(id: thread_t, sig: c_int) -> c_int; pub fn thr_self() -> thread_t; } #[link(name = "pthread")] extern "C" { pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn pthread_attr_getschedparam( attr: *const crate::pthread_attr_t, param: *mut sched_param, ) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_attr_setschedparam( attr: *mut crate::pthread_attr_t, param: *const sched_param, ) -> c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const crate::pthread_barrierattr_t, count: c_uint, ) -> c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_barrierattr_destroy(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_getpshared( attr: *const crate::pthread_barrierattr_t, shared: *mut c_int, ) -> c_int; pub fn pthread_barrierattr_init(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_setpshared( attr: *mut crate::pthread_barrierattr_t, shared: c_int, ) -> c_int; pub fn pthread_cancel(thread: crate::pthread_t) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: c_int) -> c_int; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_getattr_np(native: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_getcpuclockid(thread: crate::pthread_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn pthread_getschedparam( thread: crate::pthread_t, policy: *mut c_int, param: *mut sched_param, ) -> c_int; pub fn pthread_kill(thread: crate::pthread_t, signal: c_int) -> c_int; pub fn pthread_mutex_consistent(mutex: *mut crate::pthread_mutex_t) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_mutexattr_getprotocol( attr: *const pthread_mutexattr_t, protocol: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_getrobust( attr: *mut crate::pthread_mutexattr_t, robust: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_mutexattr_setrobust( attr: *mut crate::pthread_mutexattr_t, robust: c_int, ) -> c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: c_int) -> c_int; pub fn pthread_setschedparam( thread: crate::pthread_t, policy: c_int, param: *const sched_param, ) -> c_int; pub fn pthread_setschedprio(native: crate::pthread_t, priority: c_int) -> c_int; pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int; } #[link(name = "iconv")] extern "C" { pub fn iconv( cd: iconv_t, inbuf: *mut *mut c_char, inbytesleft: *mut size_t, outbuf: *mut *mut c_char, outbytesleft: *mut size_t, ) -> size_t; pub fn iconv_close(cd: iconv_t) -> c_int; pub fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> iconv_t; } extern "C" { pub fn acct(filename: *const c_char) -> c_int; pub fn aio_cancel(fildes: c_int, aiocbp: *mut crate::aiocb) -> c_int; pub fn aio_error(aiocbp: *mut crate::aiocb) -> c_int; #[link_name = "_posix_aio_fsync"] pub fn aio_fsync(op: c_int, aiocbp: *mut crate::aiocb) -> c_int; pub fn aio_read(aiocbp: *mut crate::aiocb) -> c_int; // pub fn aio_suspend // pub fn aio_write pub fn basename(path: *mut c_char) -> *mut c_char; pub fn bind( socket: c_int, address: *const crate::sockaddr, address_len: crate::socklen_t, ) -> c_int; pub fn brk(addr: *mut c_void) -> c_int; pub fn clearenv() -> c_int; pub fn clock_getcpuclockid(pid: crate::pid_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn clock_settime(clock_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn creat64(path: *const c_char, mode: mode_t) -> c_int; pub fn ctermid(s: *mut c_char) -> *mut c_char; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn drand48() -> c_double; pub fn duplocale(arg1: crate::locale_t) -> crate::locale_t; pub fn endgrent(); pub fn endmntent(streamp: *mut crate::FILE) -> c_int; pub fn endpwent(); pub fn endutent(); pub fn endutxent(); pub fn erand48(xseed: *mut c_ushort) -> c_double; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn fattach(fildes: c_int, path: *const c_char) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn fexecve(fd: c_int, argv: *const *const c_char, envp: *const *const c_char) -> c_int; pub fn ffs(value: c_int) -> c_int; pub fn ffsl(value: c_long) -> c_int; pub fn ffsll(value: c_longlong) -> c_int; pub fn fgetgrent(file: *mut crate::FILE) -> *mut crate::group; pub fn fgetpos64(stream: *mut crate::FILE, ptr: *mut fpos64_t) -> c_int; pub fn fgetpwent(file: *mut crate::FILE) -> *mut crate::passwd; pub fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn freelocale(loc: crate::locale_t); pub fn freopen64( filename: *const c_char, mode: *const c_char, file: *mut crate::FILE, ) -> *mut crate::FILE; pub fn fseeko64(stream: *mut crate::FILE, offset: off64_t, whence: c_int) -> c_int; pub fn fsetpos64(stream: *mut crate::FILE, ptr: *const fpos64_t) -> c_int; pub fn fstat64(fildes: c_int, buf: *mut stat64) -> c_int; pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn fstatfs64(fd: c_int, buf: *mut statfs64) -> c_int; pub fn fstatvfs64(fd: c_int, buf: *mut statvfs64) -> c_int; pub fn ftello64(stream: *mut crate::FILE) -> off64_t; pub fn ftok(path: *const c_char, id: c_int) -> crate::key_t; pub fn ftruncate64(fd: c_int, length: off64_t) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn getcontext(ucp: *mut ucontext_t) -> c_int; pub fn getdomainname(name: *mut c_char, len: c_int) -> c_int; pub fn getdtablesize() -> c_int; pub fn getgrent() -> *mut crate::group; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrnam(name: *const c_char) -> *mut crate::group; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getgrset(user: *mut c_char) -> *mut c_char; pub fn gethostid() -> c_long; pub fn getmntent(stream: *mut crate::FILE) -> *mut crate::mntent; pub fn getnameinfo( sa: *const crate::sockaddr, salen: size_t, host: *mut c_char, hostlen: size_t, serv: *mut c_char, servlen: size_t, flags: c_int, ) -> c_int; pub fn getpagesize() -> c_int; pub fn getpeereid(socket: c_int, euid: *mut crate::uid_t, egid: *mut crate::gid_t) -> c_int; pub fn getpriority(which: c_int, who: crate::id_t) -> c_int; pub fn getpwent() -> *mut crate::passwd; pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; pub fn getrlimit64(resource: c_int, rlim: *mut rlimit64) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn getitimer(which: c_int, curr_value: *mut crate::itimerval) -> c_int; pub fn getutent() -> *mut utmp; pub fn getutid(u: *const utmp) -> *mut utmp; pub fn getutline(u: *const utmp) -> *mut utmp; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; pub fn globfree(pglob: *mut crate::glob_t); pub fn hasmntopt(mnt: *const crate::mntent, opt: *const c_char) -> *mut c_char; pub fn hcreate(nelt: size_t) -> c_int; pub fn hdestroy(); pub fn hsearch(entry: entry, action: c_int) -> *mut entry; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn if_nameindex() -> *mut if_nameindex; pub fn initgroups(name: *const c_char, basegid: crate::gid_t) -> c_int; pub fn ioctl(fildes: c_int, request: c_int, ...) -> c_int; pub fn jrand48(xseed: *mut c_ushort) -> c_long; pub fn lcong48(p: *mut c_ushort); pub fn lfind( key: *const c_void, base: *const c_void, nelp: *mut size_t, width: size_t, compar: Option c_int>, ) -> *mut c_void; pub fn lio_listio( mode: c_int, aiocb_list: *const *mut aiocb, nitems: c_int, sevp: *mut sigevent, ) -> c_int; pub fn loadquery(flags: c_int, buf: *mut c_char, buflen: c_uint) -> c_int; pub fn lpar_get_info(command: c_int, buf: *mut c_void, bufsize: size_t) -> c_int; pub fn lpar_set_resources(id: c_int, resource: *mut c_void) -> c_int; pub fn lrand48() -> c_long; pub fn lsearch( key: *const c_void, base: *mut c_void, nelp: *mut size_t, width: size_t, compar: Option c_int>, ) -> *mut c_void; pub fn lseek64(fd: c_int, offset: off64_t, whence: c_int) -> off64_t; pub fn lstat64(path: *const c_char, buf: *mut stat64) -> c_int; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn makecontext(ucp: *mut crate::ucontext_t, func: extern "C" fn(), argc: c_int, ...); pub fn mallinfo() -> crate::mallinfo; pub fn mallopt(param: c_int, value: c_int) -> c_int; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; pub fn memset_s(s: *mut c_void, smax: size_t, c: c_int, n: size_t) -> c_int; pub fn mincore(addr: *const c_void, len: size_t, vec: *mut c_char) -> c_int; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn mount(device: *const c_char, path: *const c_char, flags: c_int) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn mq_close(mqd: crate::mqd_t) -> c_int; pub fn mq_getattr(mqd: crate::mqd_t, attr: *mut crate::mq_attr) -> c_int; pub fn mq_notify(mqd: crate::mqd_t, notification: *const crate::sigevent) -> c_int; pub fn mq_open(name: *const c_char, oflag: c_int, ...) -> crate::mqd_t; pub fn mq_receive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, ) -> ssize_t; pub fn mq_send( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, ) -> c_int; pub fn mq_setattr( mqd: crate::mqd_t, newattr: *const crate::mq_attr, oldattr: *mut crate::mq_attr, ) -> c_int; pub fn mq_timedreceive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, abs_timeout: *const crate::timespec, ) -> ssize_t; pub fn mq_timedsend( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, abs_timeout: *const crate::timespec, ) -> c_int; pub fn mq_unlink(name: *const c_char) -> c_int; pub fn mrand48() -> c_long; pub fn msgctl(msqid: c_int, cmd: c_int, buf: *mut msqid_ds) -> c_int; pub fn msgget(key: crate::key_t, msgflg: c_int) -> c_int; pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtyp: c_long, msgflg: c_int, ) -> ssize_t; pub fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: size_t, msgflg: c_int) -> c_int; pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; pub fn nl_langinfo_l(item: crate::nl_item, loc: crate::locale_t) -> *mut c_char; pub fn nrand48(xseed: *mut c_ushort) -> c_long; pub fn open64(path: *const c_char, oflag: c_int, ...) -> c_int; pub fn pollset_create(maxfd: c_int) -> pollset_t; pub fn pollset_ctl(ps: pollset_t, pollctl_array: *mut poll_ctl, array_length: c_int) -> c_int; pub fn pollset_destroy(ps: pollset_t) -> c_int; pub fn pollset_poll( ps: pollset_t, polldata_array: *mut crate::pollfd, array_length: c_int, timeout: c_int, ) -> c_int; pub fn pollset_query(ps: pollset_t, pollfd_query: *mut crate::pollfd) -> c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int; pub fn posix_fadvise64(fd: c_int, offset: off64_t, len: off64_t, advise: c_int) -> c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn posix_fallocate64(fd: c_int, offset: off64_t, len: off64_t) -> c_int; pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut crate::sched_param, ) -> c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut c_int, ) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut sigset_t, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: crate::pid_t) -> c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const crate::sched_param, ) -> c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: c_int) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: off64_t) -> ssize_t; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn ptrace64( request: c_int, id: c_longlong, addr: c_longlong, data: c_int, buff: *mut c_int, ) -> c_int; pub fn pututline(u: *const utmp) -> *mut utmp; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: off64_t) -> ssize_t; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; #[link_name = "__linux_quotactl"] pub fn quotactl(cmd: c_int, special: *const c_char, id: c_int, data: *mut c_char) -> c_int; pub fn rand() -> c_int; pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: c_uint, flags: c_int, timeout: *mut crate::timespec, ) -> c_int; pub fn recvmsg(sockfd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t; pub fn regcomp(preg: *mut regex_t, pattern: *const c_char, cflags: c_int) -> c_int; pub fn regerror( errcode: c_int, preg: *const crate::regex_t, errbuf: *mut c_char, errbuf_size: size_t, ) -> size_t; pub fn regexec( preg: *const regex_t, input: *const c_char, nmatch: size_t, pmatch: *mut regmatch_t, eflags: c_int, ) -> c_int; pub fn regfree(preg: *mut regex_t); pub fn sbrk(increment: intptr_t) -> *mut c_void; pub fn sched_getparam(pid: crate::pid_t, param: *mut sched_param) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn sched_get_priority_max(policy: c_int) -> c_int; pub fn sched_get_priority_min(policy: c_int) -> c_int; pub fn sched_rr_get_interval(pid: crate::pid_t, tp: *mut crate::timespec) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const crate::sched_param) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn sctp_opt_info( sd: c_int, id: crate::sctp_assoc_t, opt: c_int, arg_size: *mut c_void, size: *mut size_t, ) -> c_int; pub fn sctp_peeloff(s: c_int, id: crate::sctp_assoc_t) -> c_int; pub fn seed48(xseed: *mut c_ushort) -> *mut c_ushort; pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn semctl(semid: c_int, semnum: c_int, cmd: c_int, ...) -> c_int; pub fn semget(key: crate::key_t, nsems: c_int, semflag: c_int) -> c_int; pub fn semop(semid: c_int, sops: *mut sembuf, nsops: size_t) -> c_int; pub fn send_file(socket: *mut c_int, iobuf: *mut sf_parms, flags: c_uint) -> ssize_t; pub fn sendmmsg(sockfd: c_int, msgvec: *mut mmsghdr, vlen: c_uint, flags: c_int) -> c_int; pub fn sendmsg(sockfd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t; pub fn setcontext(ucp: *const ucontext_t) -> c_int; pub fn setdomainname(name: *const c_char, len: c_int) -> c_int; pub fn setgroups(ngroups: c_int, ptr: *const crate::gid_t) -> c_int; pub fn setgrent(); pub fn sethostid(hostid: c_int) -> c_int; pub fn sethostname(name: *const c_char, len: c_int) -> c_int; pub fn setmntent(filename: *const c_char, ty: *const c_char) -> *mut crate::FILE; pub fn setpriority(which: c_int, who: id_t, priority: c_int) -> c_int; pub fn setpwent(); pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; pub fn setrlimit64(resource: c_int, rlim: *const rlimit64) -> c_int; pub fn settimeofday(tv: *const crate::timeval, tz: *const crate::timezone) -> c_int; pub fn setitimer( which: c_int, new_value: *const crate::itimerval, old_value: *mut crate::itimerval, ) -> c_int; pub fn setutent(); pub fn setutxent(); pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void; pub fn shmdt(shmaddr: *const c_void) -> c_int; pub fn shmctl(shmid: c_int, cmd: c_int, buf: *mut crate::shmid_ds) -> c_int; pub fn shmget(key: key_t, size: size_t, shmflg: c_int) -> c_int; pub fn shm_open(name: *const c_char, oflag: c_int, mode: crate::mode_t) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; pub fn splice(socket1: c_int, socket2: c_int, flags: c_int) -> c_int; pub fn srand(seed: c_uint); pub fn srand48(seed: c_long); pub fn stat64(path: *const c_char, buf: *mut stat64) -> c_int; pub fn stat64at(dirfd: c_int, path: *const c_char, buf: *mut stat64, flags: c_int) -> c_int; pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; pub fn statfs64(path: *const c_char, buf: *mut statfs64) -> c_int; pub fn statvfs64(path: *const c_char, buf: *mut statvfs64) -> c_int; pub fn statx(path: *const c_char, buf: *mut stat, length: c_int, command: c_int) -> c_int; pub fn strcasecmp_l( string1: *const c_char, string2: *const c_char, locale: crate::locale_t, ) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn strftime( arg1: *mut c_char, arg2: size_t, arg3: *const c_char, arg4: *const tm, ) -> size_t; pub fn strncasecmp_l( string1: *const c_char, string2: *const c_char, length: size_t, locale: crate::locale_t, ) -> c_int; pub fn strptime(s: *const c_char, format: *const c_char, tm: *mut crate::tm) -> *mut c_char; pub fn strsep(string: *mut *mut c_char, delim: *const c_char) -> *mut c_char; pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> c_int; pub fn swapoff(puath: *const c_char) -> c_int; pub fn swapon(path: *const c_char) -> c_int; pub fn sync(); pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn timer_create( clockid: crate::clockid_t, sevp: *mut crate::sigevent, timerid: *mut crate::timer_t, ) -> c_int; pub fn timer_delete(timerid: timer_t) -> c_int; pub fn timer_getoverrun(timerid: timer_t) -> c_int; pub fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> c_int; pub fn timer_settime( timerid: crate::timer_t, flags: c_int, new_value: *const crate::itimerspec, old_value: *mut crate::itimerspec, ) -> c_int; pub fn truncate64(path: *const c_char, length: off64_t) -> c_int; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn updwtmp(file: *const c_char, u: *mut utmp); pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn utmpname(file: *const c_char) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn wait4( pid: crate::pid_t, status: *mut c_int, options: c_int, rusage: *mut crate::rusage, ) -> crate::pid_t; pub fn waitid( idtype: idtype_t, id: id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; // Use AIX thread-safe version errno. pub fn _Errno() -> *mut c_int; } cfg_if! { if #[cfg(target_arch = "powerpc64")] { mod powerpc64; pub use self::powerpc64::*; } } libc/src/unix/aix/powerpc64.rs0000644000175000017500000004574415105742312016063 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; s! { pub struct sigset_t { pub ss_set: [c_ulong; 4], } pub struct fd_set { pub fds_bits: [c_long; 1024], } pub struct flock { pub l_type: c_short, pub l_whence: c_short, pub l_sysid: c_uint, pub l_pid: crate::pid_t, pub l_vfs: c_int, pub l_start: off_t, pub l_len: off_t, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_basetype: [c_char; 16], pub f_flag: c_ulong, pub f_namemax: c_ulong, pub f_fstr: [c_char; 32], pub f_filler: [c_ulong; 16], } pub struct pthread_rwlock_t { __rw_word: [c_long; 10], } pub struct pthread_cond_t { __cv_word: [c_long; 6], } pub struct pthread_mutex_t { __mt_word: [c_long; 8], } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_flag: c_ushort, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_ssize: c_int, pub st_atime: crate::st_timespec, pub st_mtime: crate::st_timespec, pub st_ctime: crate::st_timespec, pub st_blksize: crate::blksize_t, pub st_blocks: crate::blkcnt_t, pub st_vfstype: c_int, pub st_vfs: c_uint, pub st_type: c_uint, pub st_gen: c_uint, pub st_reserved: [c_uint; 9], pub st_padto_ll: c_uint, pub st_size: off_t, } pub struct statfs { pub f_version: c_int, pub f_type: c_int, pub f_bsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsblkcnt_t, pub f_ffree: crate::fsblkcnt_t, pub f_fsid: crate::fsid64_t, pub f_vfstype: c_int, pub f_fsize: c_ulong, pub f_vfsnumber: c_int, pub f_vfsoff: c_int, pub f_vfslen: c_int, pub f_vfsvers: c_int, pub f_fname: [c_char; 32], pub f_fpack: [c_char; 32], pub f_name_max: c_int, } pub struct aiocb { pub aio_lio_opcode: c_int, pub aio_fildes: c_int, pub aio_word1: c_int, pub aio_offset: off_t, pub aio_buf: *mut c_void, pub aio_return: ssize_t, pub aio_errno: c_int, pub aio_nbytes: size_t, pub aio_reqprio: c_int, pub aio_sigevent: crate::sigevent, pub aio_word2: c_int, pub aio_fp: c_int, pub aio_handle: *mut aiocb, pub aio_reserved: [c_uint; 2], pub aio_sigev_tid: c_long, } pub struct ucontext_t { pub __sc_onstack: c_int, pub uc_sigmask: crate::sigset_t, pub __sc_uerror: c_int, pub uc_mcontext: crate::mcontext_t, pub uc_link: *mut ucontext_t, pub uc_stack: crate::stack_t, // Should be pointer to __extctx_t pub __extctx: *mut c_void, pub __extctx_magic: c_int, pub __pad: [c_int; 1], } pub struct mcontext_t { pub gpr: [c_ulonglong; 32], pub msr: c_ulonglong, pub iar: c_ulonglong, pub lr: c_ulonglong, pub ctr: c_ulonglong, pub cr: c_uint, pub xer: c_uint, pub fpscr: c_uint, pub fpscrx: c_uint, pub except: [c_ulonglong; 1], // Should be array of double type pub fpr: [crate::uint64_t; 32], pub fpeu: c_char, pub fpinfo: c_char, pub fpscr24_31: c_char, pub pad: [c_char; 1], pub excp_type: c_int, } pub struct utmpx { pub ut_user: [c_char; 256], pub ut_id: [c_char; 14], pub ut_line: [c_char; 64], pub ut_pid: crate::pid_t, pub ut_type: c_short, pub ut_tv: crate::timeval, pub ut_host: [c_char; 256], pub __dbl_word_pad: c_int, pub __reservedA: [c_int; 2], pub __reservedV: [c_int; 6], } pub struct pthread_spinlock_t { pub __sp_word: [c_long; 3], } pub struct pthread_barrier_t { pub __br_word: [c_long; 5], } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, pub msg_first: c_uint, pub msg_last: c_uint, pub msg_cbytes: c_uint, pub msg_qnum: c_uint, pub msg_qbytes: c_ulong, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, pub msg_rwait: c_int, pub msg_wwait: c_int, pub msg_reqevents: c_ushort, } } s_no_extra_traits! { pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, pub si_pid: crate::pid_t, pub si_uid: crate::uid_t, pub si_status: c_int, pub si_addr: *mut c_void, pub si_band: c_long, pub si_value: crate::sigval, pub __si_flags: c_int, pub __pad: [c_int; 3], } pub union _kernel_simple_lock { pub _slock: c_long, // Should be pointer to 'lock_data_instrumented' pub _slockp: *mut c_void, } pub struct fileops_t { pub fo_rw: extern "C" fn( file: *mut file, rw: crate::uio_rw, io: *mut c_void, ext: c_long, secattr: *mut c_void, ) -> c_int, pub fo_ioctl: extern "C" fn( file: *mut file, a: c_long, b: crate::caddr_t, c: c_long, d: c_long, ) -> c_int, pub fo_select: extern "C" fn(file: *mut file, a: c_int, b: *mut c_ushort, c: extern "C" fn()) -> c_int, pub fo_close: extern "C" fn(file: *mut file) -> c_int, pub fo_fstat: extern "C" fn(file: *mut file, sstat: *mut crate::stat) -> c_int, } pub struct file { pub f_flag: c_long, pub f_count: c_int, pub f_options: c_short, pub f_type: c_short, // Should be pointer to 'vnode' pub f_data: *mut c_void, pub f_offset: c_longlong, pub f_dir_off: c_long, // Should be pointer to 'cred' pub f_cred: *mut c_void, pub f_lock: _kernel_simple_lock, pub f_offset_lock: _kernel_simple_lock, pub f_vinfo: crate::caddr_t, pub f_ops: *mut fileops_t, pub f_parentp: crate::caddr_t, pub f_fnamep: crate::caddr_t, pub f_fdata: [c_char; 160], } pub union __ld_info_file { pub _ldinfo_fd: c_int, pub _ldinfo_fp: *mut file, pub _core_offset: c_long, } pub struct ld_info { pub ldinfo_next: c_uint, pub ldinfo_flags: c_uint, pub _file: __ld_info_file, pub ldinfo_textorg: *mut c_void, pub ldinfo_textsize: c_ulong, pub ldinfo_dataorg: *mut c_void, pub ldinfo_datasize: c_ulong, pub ldinfo_filename: [c_char; 2], } pub union __pollfd_ext_u { pub addr: *mut c_void, pub data32: u32, pub data: u64, } pub struct pollfd_ext { pub fd: c_int, pub events: c_ushort, pub revents: c_ushort, pub data: __pollfd_ext_u, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { self.si_addr } pub unsafe fn si_value(&self) -> crate::sigval { self.si_value } pub unsafe fn si_pid(&self) -> crate::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> c_int { self.si_status } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { self.si_signo == other.si_signo && self.si_errno == other.si_errno && self.si_code == other.si_code && self.si_pid == other.si_pid && self.si_uid == other.si_uid && self.si_status == other.si_status && self.si_addr == other.si_addr && self.si_band == other.si_band && self.__si_flags == other.__si_flags && self.si_value == other.si_value } } impl Eq for siginfo_t {} impl fmt::Debug for siginfo_t { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("siginfo_t") .field("si_signo", &self.si_signo) .field("si_errno", &self.si_errno) .field("si_code", &self.si_code) .field("si_pid", &self.si_pid) .field("si_uid", &self.si_uid) .field("si_status", &self.si_status) .field("si_addr", &self.si_addr) .field("si_band", &self.si_band) .field("si_value", &self.si_value) .field("__si_flags", &self.__si_flags) .finish() } } impl hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_errno.hash(state); self.si_code.hash(state); self.si_pid.hash(state); self.si_uid.hash(state); self.si_status.hash(state); self.si_addr.hash(state); self.si_band.hash(state); self.si_value.hash(state); self.__si_flags.hash(state); } } impl PartialEq for _kernel_simple_lock { fn eq(&self, other: &_kernel_simple_lock) -> bool { unsafe { self._slock == other._slock && self._slockp == other._slockp } } } impl Eq for _kernel_simple_lock {} impl hash::Hash for _kernel_simple_lock { fn hash(&self, state: &mut H) { unsafe { self._slock.hash(state); self._slockp.hash(state); } } } impl PartialEq for fileops_t { fn eq(&self, other: &fileops_t) -> bool { self.fo_rw == other.fo_rw && self.fo_ioctl == other.fo_ioctl && self.fo_select == other.fo_select && self.fo_close == other.fo_close && self.fo_fstat == other.fo_fstat } } impl Eq for fileops_t {} impl fmt::Debug for fileops_t { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("fileops_t") .field("fo_rw", &self.fo_rw) .field("fo_ioctl", &self.fo_ioctl) .field("fo_select", &self.fo_select) .field("fo_close", &self.fo_close) .field("fo_fstat", &self.fo_fstat) .finish() } } impl hash::Hash for fileops_t { fn hash(&self, state: &mut H) { self.fo_rw.hash(state); self.fo_ioctl.hash(state); self.fo_select.hash(state); self.fo_close.hash(state); self.fo_fstat.hash(state); } } impl PartialEq for file { fn eq(&self, other: &file) -> bool { self.f_flag == other.f_flag && self.f_count == other.f_count && self.f_options == other.f_options && self.f_type == other.f_type && self.f_data == other.f_data && self.f_offset == other.f_offset && self.f_dir_off == other.f_dir_off && self.f_cred == other.f_cred && self.f_vinfo == other.f_vinfo && self.f_ops == other.f_ops && self.f_parentp == other.f_parentp && self.f_fnamep == other.f_fnamep && self.f_fdata == other.f_fdata && self.f_lock == other.f_lock && self.f_offset_lock == other.f_offset_lock } } impl Eq for file {} impl fmt::Debug for file { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("file") .field("f_flag", &self.f_flag) .field("f_count", &self.f_count) .field("f_options", &self.f_options) .field("f_type", &self.f_type) .field("f_data", &self.f_data) .field("f_offset", &self.f_offset) .field("f_dir_off", &self.f_dir_off) .field("f_cred", &self.f_cred) .field("f_lock", &self.f_lock) .field("f_offset_lock", &self.f_offset_lock) .field("f_vinfo", &self.f_vinfo) .field("f_ops", &self.f_ops) .field("f_parentp", &self.f_parentp) .field("f_fnamep", &self.f_fnamep) .field("f_fdata", &self.f_fdata) .finish() } } impl hash::Hash for file { fn hash(&self, state: &mut H) { self.f_flag.hash(state); self.f_count.hash(state); self.f_options.hash(state); self.f_type.hash(state); self.f_data.hash(state); self.f_offset.hash(state); self.f_dir_off.hash(state); self.f_cred.hash(state); self.f_lock.hash(state); self.f_offset_lock.hash(state); self.f_vinfo.hash(state); self.f_ops.hash(state); self.f_parentp.hash(state); self.f_fnamep.hash(state); self.f_fdata.hash(state); } } impl PartialEq for __ld_info_file { fn eq(&self, other: &__ld_info_file) -> bool { unsafe { self._ldinfo_fd == other._ldinfo_fd && self._ldinfo_fp == other._ldinfo_fp && self._core_offset == other._core_offset } } } impl Eq for __ld_info_file {} impl hash::Hash for __ld_info_file { fn hash(&self, state: &mut H) { unsafe { self._ldinfo_fd.hash(state); self._ldinfo_fp.hash(state); self._core_offset.hash(state); } } } impl PartialEq for ld_info { fn eq(&self, other: &ld_info) -> bool { self.ldinfo_next == other.ldinfo_next && self.ldinfo_flags == other.ldinfo_flags && self.ldinfo_textorg == other.ldinfo_textorg && self.ldinfo_textsize == other.ldinfo_textsize && self.ldinfo_dataorg == other.ldinfo_dataorg && self.ldinfo_datasize == other.ldinfo_datasize && self.ldinfo_filename == other.ldinfo_filename && self._file == other._file } } impl Eq for ld_info {} impl fmt::Debug for ld_info { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ld_info") .field("ldinfo_next", &self.ldinfo_next) .field("ldinfo_flags", &self.ldinfo_flags) .field("ldinfo_textorg", &self.ldinfo_textorg) .field("ldinfo_textsize", &self.ldinfo_textsize) .field("ldinfo_dataorg", &self.ldinfo_dataorg) .field("ldinfo_datasize", &self.ldinfo_datasize) .field("ldinfo_filename", &self.ldinfo_filename) .field("_file", &self._file) .finish() } } impl hash::Hash for ld_info { fn hash(&self, state: &mut H) { self.ldinfo_next.hash(state); self.ldinfo_flags.hash(state); self.ldinfo_textorg.hash(state); self.ldinfo_textsize.hash(state); self.ldinfo_dataorg.hash(state); self.ldinfo_datasize.hash(state); self.ldinfo_filename.hash(state); self._file.hash(state); } } impl PartialEq for __pollfd_ext_u { fn eq(&self, other: &__pollfd_ext_u) -> bool { unsafe { self.addr == other.addr && self.data32 == other.data32 && self.data == other.data } } } impl Eq for __pollfd_ext_u {} impl hash::Hash for __pollfd_ext_u { fn hash(&self, state: &mut H) { unsafe { self.addr.hash(state); self.data.hash(state); self.data32.hash(state); } } } impl PartialEq for pollfd_ext { fn eq(&self, other: &pollfd_ext) -> bool { self.fd == other.fd && self.events == other.events && self.revents == other.revents && self.data == other.data } } impl Eq for pollfd_ext {} impl fmt::Debug for pollfd_ext { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("pollfd_ext") .field("fd", &self.fd) .field("events", &self.events) .field("revents", &self.revents) .field("data", &self.data) .finish() } } impl hash::Hash for pollfd_ext { fn hash(&self, state: &mut H) { self.fd.hash(state); self.events.hash(state); self.revents.hash(state); self.data.hash(state); } } } } pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __mt_word: [0, 2, 0, 0, 0, 0, 0, 0], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __cv_word: [0, 0, 0, 0, 2, 0], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __rw_word: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; pub const RLIM_INFINITY: c_ulong = 0x7fffffffffffffff; extern "C" { pub fn getsystemcfg(label: c_int) -> c_ulong; } libc/src/unix/nuttx/0000775000175000017500000000000015105742312014251 5ustar bdrungbdrunglibc/src/unix/nuttx/mod.rs0000644000175000017500000004114015105742312015374 0ustar bdrungbdrunguse crate::prelude::*; use crate::{in6_addr, in_addr_t, timespec, DIR}; pub type nlink_t = u16; pub type ino_t = u16; pub type blkcnt_t = u64; pub type blksize_t = i16; pub type cc_t = u8; pub type clock_t = i64; pub type dev_t = i32; pub type fsblkcnt_t = u64; pub type locale_t = *mut i8; pub type mode_t = u32; pub type nfds_t = u32; pub type off_t = i64; pub type pthread_key_t = i32; pub type pthread_mutexattr_t = u8; pub type pthread_rwlockattr_t = i32; pub type pthread_t = i32; pub type rlim_t = i64; pub type sa_family_t = u16; pub type socklen_t = u32; pub type speed_t = usize; pub type suseconds_t = i32; pub type tcflag_t = u32; pub type clockid_t = i32; pub type time_t = i64; pub type wchar_t = i32; s! { pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, pub st_nlink: u64, pub st_uid: u32, pub st_gid: u32, pub st_rdev: dev_t, pub st_size: off_t, pub st_atim: timespec, pub st_mtim: timespec, pub st_ctim: timespec, pub st_blksize: blksize_t, pub st_blocks: i64, __reserved: [usize; __DEFAULT_RESERVED_SIZE__], } pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [u8; 14], } pub struct passwd { pub pw_name: *const c_char, pub pw_passwd: *const c_char, pub pw_uid: u32, pub pw_gid: u32, pub pw_gecos: *const c_char, pub pw_dir: *const c_char, pub pw_shell: *const c_char, __reserved: [usize; __DEFAULT_RESERVED_SIZE__], } pub struct sem_t { __val: [usize; __SEM_SIZE__], } pub struct pthread_attr_t { __val: [usize; __PTHREAD_ATTR_SIZE__], } pub struct pthread_mutex_t { __val: [usize; __PTHREAD_MUTEX_SIZE__], } pub struct pthread_cond_t { __val: [usize; __PTHREAD_COND_SIZE__], } pub struct pthread_condattr_t { __val: [usize; __PTHREAD_CONDATTR_SIZE__], } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct lconv { pub decimal_point: *const c_char, pub thousands_sep: *const c_char, pub grouping: *const c_char, pub int_curr_symbol: *const c_char, pub currency_symbol: *const c_char, pub mon_decimal_point: *const c_char, pub mon_thousands_sep: *const c_char, pub mon_grouping: *const c_char, pub positive_sign: *const c_char, pub negative_sign: *const c_char, pub int_frac_digits: i8, pub frac_digits: i8, pub p_cs_precedes: i8, pub p_sep_by_space: i8, pub n_cs_precedes: i8, pub n_sep_by_space: i8, pub p_sign_posn: i8, pub n_sign_posn: i8, pub int_n_cs_precedes: i8, pub int_n_sep_by_space: i8, pub int_n_sign_posn: i8, pub int_p_cs_precedes: i8, pub int_p_sep_by_space: i8, pub int_p_sign_posn: i8, __reserved: [usize; __DEFAULT_RESERVED_SIZE__], } pub struct tm { pub tm_sec: i32, pub tm_min: i32, pub tm_hour: i32, pub tm_mday: i32, pub tm_mon: i32, pub tm_year: i32, pub tm_wday: i32, pub tm_yday: i32, pub tm_isdst: i32, pub tm_gmtoff: isize, pub tm_zone: *const c_char, __reserved: [usize; __DEFAULT_RESERVED_SIZE__], } pub struct addrinfo { pub ai_flags: i32, pub ai_family: i32, pub ai_socktype: i32, pub ai_protocol: i32, pub ai_addrlen: socklen_t, pub ai_addr: *mut sockaddr, pub ai_canonname: *mut c_char, pub ai_next: *mut addrinfo, __reserved: [usize; __DEFAULT_RESERVED_SIZE__], } pub struct pthread_rwlock_t { __val: [usize; __PTHREAD_RWLOCK_SIZE__], } pub struct statvfs { pub f_bsize: usize, pub f_frsize: usize, pub f_blocks: fsblkcnt_t, pub f_bfree: fsblkcnt_t, pub f_bavail: fsblkcnt_t, pub f_files: fsblkcnt_t, pub f_ffree: fsblkcnt_t, pub f_favail: fsblkcnt_t, pub f_fsid: usize, pub f_flag: usize, pub f_namemax: usize, __reserved: [usize; __DEFAULT_RESERVED_SIZE__], } pub struct dirent { pub d_type: u8, pub d_name: [c_char; __NAME_MAX__ + 1], } pub struct fd_set { __val: [u32; __FDSET_SIZE__], } pub struct sigset_t { __val: [u32; __SIGSET_SIZE__], } pub struct sigaction { pub sa_handler: usize, pub sa_mask: sigset_t, pub sa_flags: i32, pub sa_user: usize, __reserved: [usize; __DEFAULT_RESERVED_SIZE__], } pub struct termios { pub c_iflag: tcflag_t, pub c_oflag: tcflag_t, pub c_cflag: tcflag_t, pub c_lflag: tcflag_t, pub c_cc: [cc_t; 12], pub c_speed: speed_t, __reserved: [usize; __DEFAULT_RESERVED_SIZE__], } pub struct in_addr { pub s_addr: in_addr_t, } pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char; 108], } pub struct sockaddr_storage { pub ss_family: sa_family_t, ss_data: [u32; __SOCKADDR_STORAGE_SIZE__], } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: u32, } pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } } // Reserved two pointer size for reserved area for some structures. // This ensures that the size of these structures is large enough // if more fields are added in the NuttX side. // // These structures are that defined by POSIX but only necessary fields are included, // for example, struct passwd, https://pubs.opengroup.org/onlinepubs/009695399/basedefs/pwd.h.html, // POSIX only defines following fields in struct passwd: // char *pw_name User's login name. // char *pw_passwd Encrypted password. // uid_t pw_uid Numerical user ID. // gid_t pw_gid Numerical group ID. // char *pw_dir Initial working directory. // char *pw_shell Program to use as shell. // Other fields can be different depending on the implementation. const __DEFAULT_RESERVED_SIZE__: usize = 2; const __SOCKADDR_STORAGE_SIZE__: usize = 36; const __PTHREAD_ATTR_SIZE__: usize = 5; const __PTHREAD_MUTEX_SIZE__: usize = 9; const __PTHREAD_COND_SIZE__: usize = 7; const __PTHREAD_CONDATTR_SIZE__: usize = 5; const __PTHREAD_RWLOCK_SIZE__: usize = 17; const __SEM_SIZE__: usize = 6; const __NAME_MAX__: usize = 64; const __FDSET_SIZE__: usize = 10; const __SIGSET_SIZE__: usize = 8; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __val: [0; __PTHREAD_COND_SIZE__], }; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __val: [0; __PTHREAD_MUTEX_SIZE__], }; // dlfcn.h pub const RTLD_DEFAULT: *mut c_void = 0 as *mut c_void; // stdlib.h pub const EXIT_SUCCESS: i32 = 0; pub const EXIT_FAILURE: i32 = 1; // time.h pub const CLOCK_REALTIME: i32 = 0; pub const CLOCK_MONOTONIC: i32 = 1; // errno.h pub const EPERM: i32 = 1; pub const ENOENT: i32 = 2; pub const ESRCH: i32 = 3; pub const EINTR: i32 = 4; pub const EIO: i32 = 5; pub const ENXIO: i32 = 6; pub const E2BIG: i32 = 7; pub const ENOEXEC: i32 = 8; pub const EBADF: i32 = 9; pub const ECHILD: i32 = 10; pub const EAGAIN: i32 = 11; pub const ENOMEM: i32 = 12; pub const EACCES: i32 = 13; pub const EFAULT: i32 = 14; pub const ENOTBLK: i32 = 15; pub const EBUSY: i32 = 16; pub const EEXIST: i32 = 17; pub const EXDEV: i32 = 18; pub const ENODEV: i32 = 19; pub const ENOTDIR: i32 = 20; pub const EISDIR: i32 = 21; pub const EINVAL: i32 = 22; pub const ENFILE: i32 = 23; pub const EMFILE: i32 = 24; pub const ENOTTY: i32 = 25; pub const ETXTBSY: i32 = 26; pub const EFBIG: i32 = 27; pub const ENOSPC: i32 = 28; pub const ESPIPE: i32 = 29; pub const EROFS: i32 = 30; pub const EMLINK: i32 = 31; pub const EPIPE: i32 = 32; pub const EDOM: i32 = 33; pub const ERANGE: i32 = 34; pub const EDEADLK: i32 = 35; pub const ENAMETOOLONG: i32 = 36; pub const ENOLCK: i32 = 37; pub const ENOSYS: i32 = 38; pub const ENOTEMPTY: i32 = 39; pub const ELOOP: i32 = 40; pub const EWOULDBLOCK: i32 = EAGAIN; pub const ENOMSG: i32 = 42; pub const EIDRM: i32 = 43; pub const ECHRNG: i32 = 44; pub const EL2NSYNC: i32 = 45; pub const EL3HLT: i32 = 46; pub const EL3RST: i32 = 47; pub const ELNRNG: i32 = 48; pub const EUNATCH: i32 = 49; pub const ENOCSI: i32 = 50; pub const EL2HLT: i32 = 51; pub const EBADE: i32 = 52; pub const EBADR: i32 = 53; pub const EXFULL: i32 = 54; pub const ENOANO: i32 = 55; pub const EBADRQC: i32 = 56; pub const EBADSLT: i32 = 57; pub const EDEADLOCK: i32 = EDEADLK; pub const EBFONT: i32 = 59; pub const ENOSTR: i32 = 60; pub const ENODATA: i32 = 61; pub const ETIME: i32 = 62; pub const ENOSR: i32 = 63; pub const ENONET: i32 = 64; pub const ENOPKG: i32 = 65; pub const EREMOTE: i32 = 66; pub const ENOLINK: i32 = 67; pub const EADV: i32 = 68; pub const ESRMNT: i32 = 69; pub const ECOMM: i32 = 70; pub const EPROTO: i32 = 71; pub const EMULTIHOP: i32 = 72; pub const EDOTDOT: i32 = 73; pub const EBADMSG: i32 = 74; pub const EOVERFLOW: i32 = 75; pub const ENOTUNIQ: i32 = 76; pub const EBADFD: i32 = 77; pub const EREMCHG: i32 = 78; pub const ELIBACC: i32 = 79; pub const ELIBBAD: i32 = 80; pub const ELIBSCN: i32 = 81; pub const ELIBMAX: i32 = 82; pub const ELIBEXEC: i32 = 83; pub const EILSEQ: i32 = 84; pub const ERESTART: i32 = 85; pub const ESTRPIPE: i32 = 86; pub const EUSERS: i32 = 87; pub const ENOTSOCK: i32 = 88; pub const EDESTADDRREQ: i32 = 89; pub const EMSGSIZE: i32 = 90; pub const EPROTOTYPE: i32 = 91; pub const ENOPROTOOPT: i32 = 92; pub const EPROTONOSUPPORT: i32 = 93; pub const ESOCKTNOSUPPORT: i32 = 94; pub const EOPNOTSUPP: i32 = 95; pub const EPFNOSUPPORT: i32 = 96; pub const EAFNOSUPPORT: i32 = 97; pub const EADDRINUSE: i32 = 98; pub const EADDRNOTAVAIL: i32 = 99; pub const ENETDOWN: i32 = 100; pub const ENETUNREACH: i32 = 101; pub const ENETRESET: i32 = 102; pub const ECONNABORTED: i32 = 103; pub const ECONNRESET: i32 = 104; pub const ENOBUFS: i32 = 105; pub const EISCONN: i32 = 106; pub const ENOTCONN: i32 = 107; pub const ESHUTDOWN: i32 = 108; pub const ETOOMANYREFS: i32 = 109; pub const ETIMEDOUT: i32 = 110; pub const ECONNREFUSED: i32 = 111; pub const EHOSTDOWN: i32 = 112; pub const EHOSTUNREACH: i32 = 113; pub const EALREADY: i32 = 114; pub const EINPROGRESS: i32 = 115; pub const ESTALE: i32 = 116; pub const EUCLEAN: i32 = 117; pub const ENOTNAM: i32 = 118; pub const ENAVAIL: i32 = 119; pub const EISNAM: i32 = 120; pub const EREMOTEIO: i32 = 121; pub const EDQUOT: i32 = 122; pub const ENOMEDIUM: i32 = 123; pub const EMEDIUMTYPE: i32 = 124; pub const ECANCELED: i32 = 125; pub const ENOKEY: i32 = 126; pub const EKEYEXPIRED: i32 = 127; pub const EKEYREVOKED: i32 = 128; pub const EKEYREJECTED: i32 = 129; pub const EOWNERDEAD: i32 = 130; pub const ENOTRECOVERABLE: i32 = 131; pub const ERFKILL: i32 = 132; pub const EHWPOISON: i32 = 133; pub const ELBIN: i32 = 134; pub const EFTYPE: i32 = 135; pub const ENMFILE: i32 = 136; pub const EPROCLIM: i32 = 137; pub const ENOTSUP: i32 = 138; pub const ENOSHARE: i32 = 139; pub const ECASECLASH: i32 = 140; // fcntl.h pub const FIOCLEX: i32 = 0x30b; pub const F_SETFL: i32 = 0x9; pub const F_DUPFD_CLOEXEC: i32 = 0x12; pub const F_GETFD: i32 = 0x1; pub const F_GETFL: i32 = 0x2; pub const O_RDONLY: i32 = 0x1; pub const O_WRONLY: i32 = 0x2; pub const O_RDWR: i32 = 0x3; pub const O_CREAT: i32 = 0x4; pub const O_EXCL: i32 = 0x8; pub const O_NOCTTY: i32 = 0x0; pub const O_TRUNC: i32 = 0x20; pub const O_APPEND: i32 = 0x10; pub const O_NONBLOCK: i32 = 0x40; pub const O_DSYNC: i32 = 0x80; pub const O_DIRECT: i32 = 0x200; pub const O_LARGEFILE: i32 = 0x2000; pub const O_DIRECTORY: i32 = 0x800; pub const O_NOFOLLOW: i32 = 0x1000; pub const O_NOATIME: i32 = 0x40000; pub const O_CLOEXEC: i32 = 0x400; pub const O_ACCMODE: i32 = 0x0003; pub const AT_FDCWD: i32 = -100; pub const AT_REMOVEDIR: i32 = 0x200; // sys/types.h pub const SEEK_SET: i32 = 0; pub const SEEK_CUR: i32 = 1; pub const SEEK_END: i32 = 2; // sys/stat.h pub const S_IFDIR: u32 = 0x4000; pub const S_IFLNK: u32 = 0xA000; pub const S_IFREG: u32 = 0x8000; pub const S_IFMT: u32 = 0xF000; pub const S_IFIFO: u32 = 0x1000; pub const S_IFSOCK: u32 = 0xc000; pub const S_IFBLK: u32 = 0x6000; pub const S_IFCHR: u32 = 0x2000; pub const S_IRUSR: u32 = 0x100; pub const S_IWUSR: u32 = 0x80; pub const S_IXUSR: u32 = 0x40; pub const S_IRGRP: u32 = 0x20; pub const S_IWGRP: u32 = 0x10; pub const S_IXGRP: u32 = 0x8; pub const S_IROTH: u32 = 0x004; pub const S_IWOTH: u32 = 0x002; pub const S_IXOTH: u32 = 0x001; // sys/poll.h pub const POLLIN: i16 = 0x01; pub const POLLOUT: i16 = 0x04; pub const POLLHUP: i16 = 0x10; pub const POLLERR: i16 = 0x08; pub const POLLNVAL: i16 = 0x20; // sys/socket.h pub const AF_UNIX: i32 = 1; pub const SOCK_DGRAM: i32 = 2; pub const SOCK_STREAM: i32 = 1; pub const AF_INET: i32 = 2; pub const AF_INET6: i32 = 10; pub const MSG_PEEK: i32 = 0x02; pub const SOL_SOCKET: i32 = 1; pub const SHUT_WR: i32 = 2; pub const SHUT_RD: i32 = 1; pub const SHUT_RDWR: i32 = 3; pub const SO_ERROR: i32 = 4; pub const SO_REUSEADDR: i32 = 11; pub const SOMAXCONN: i32 = 8; pub const SO_LINGER: i32 = 6; pub const SO_RCVTIMEO: i32 = 0xa; pub const SO_SNDTIMEO: i32 = 0xe; pub const SO_BROADCAST: i32 = 1; // netinet/tcp.h pub const TCP_NODELAY: i32 = 0x10; // nuttx/fs/ioctl.h pub const FIONBIO: i32 = 0x30a; // unistd.h pub const STDIN_FILENO: i32 = 0; pub const STDOUT_FILENO: i32 = 1; pub const STDERR_FILENO: i32 = 2; pub const _SC_PAGESIZE: i32 = 0x36; pub const _SC_THREAD_STACK_MIN: i32 = 0x58; pub const _SC_GETPW_R_SIZE_MAX: i32 = 0x25; // signal.h pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGIOT: c_int = 6; pub const SIGBUS: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGUSR1: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGUSR2: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGSTKFLT: c_int = 16; pub const SIGCHLD: c_int = 17; pub const SIGCONT: c_int = 18; pub const SIGSTOP: c_int = 19; pub const SIGTSTP: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGURG: c_int = 23; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGIO: c_int = 29; pub const SIGPOLL: c_int = SIGIO; pub const SIGPWR: c_int = 30; pub const SIGSYS: c_int = 31; // pthread.h pub const PTHREAD_MUTEX_NORMAL: i32 = 0; // netinet/in.h pub const IP_TTL: i32 = 0x1e; pub const IPV6_V6ONLY: i32 = 0x17; pub const IPV6_JOIN_GROUP: i32 = 0x11; pub const IPV6_LEAVE_GROUP: i32 = 0x12; pub const IP_MULTICAST_LOOP: i32 = 0x13; pub const IPV6_MULTICAST_LOOP: i32 = 0x15; pub const IP_MULTICAST_TTL: i32 = 0x12; pub const IP_ADD_MEMBERSHIP: i32 = 0x14; pub const IP_DROP_MEMBERSHIP: i32 = 0x15; extern "C" { pub fn bind(sockfd: i32, addr: *const sockaddr, addrlen: socklen_t) -> i32; pub fn ioctl(fd: i32, request: i32, ...) -> i32; pub fn dirfd(dirp: *mut DIR) -> i32; pub fn recvfrom( sockfd: i32, buf: *mut c_void, len: usize, flags: i32, src_addr: *mut sockaddr, addrlen: *mut socklen_t, ) -> i32; pub fn pthread_create( thread: *mut pthread_t, attr: *const pthread_attr_t, start_routine: extern "C" fn(*mut c_void) -> *mut c_void, arg: *mut c_void, ) -> i32; pub fn clock_gettime(clockid: clockid_t, tp: *mut timespec) -> i32; pub fn futimens(fd: i32, times: *const timespec) -> i32; pub fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clock_id: clockid_t) -> i32; pub fn pthread_setname_np(thread: pthread_t, name: *const c_char) -> i32; pub fn pthread_getname_np(thread: pthread_t, name: *mut c_char, len: usize) -> i32; pub fn getrandom(buf: *mut c_void, buflen: usize, flags: u32) -> isize; } libc/src/unix/bsd/0000775000175000017500000000000015105742312013637 5ustar bdrungbdrunglibc/src/unix/bsd/mod.rs0000644000175000017500000007577215105742312015004 0ustar bdrungbdrunguse crate::prelude::*; pub type off_t = i64; pub type useconds_t = u32; pub type blkcnt_t = i64; pub type socklen_t = u32; pub type sa_family_t = u8; pub type pthread_t = crate::uintptr_t; pub type nfds_t = c_uint; pub type regoff_t = off_t; s! { pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [c_char; 14], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: crate::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: crate::in6_addr, pub sin6_scope_id: u32, } pub struct passwd { pub pw_name: *mut c_char, pub pw_passwd: *mut c_char, pub pw_uid: crate::uid_t, pub pw_gid: crate::gid_t, pub pw_change: crate::time_t, pub pw_class: *mut c_char, pub pw_gecos: *mut c_char, pub pw_dir: *mut c_char, pub pw_shell: *mut c_char, pub pw_expire: crate::time_t, #[cfg(not(any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", target_os = "netbsd", target_os = "openbsd" )))] pub pw_fields: c_int, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: c_uint, pub ifa_addr: *mut crate::sockaddr, pub ifa_netmask: *mut crate::sockaddr, pub ifa_dstaddr: *mut crate::sockaddr, pub ifa_data: *mut c_void, #[cfg(target_os = "netbsd")] pub ifa_addrflags: c_uint, } pub struct fd_set { #[cfg(all( target_pointer_width = "64", any(target_os = "freebsd", target_os = "dragonfly") ))] fds_bits: [i64; FD_SETSIZE as usize / 64], #[cfg(not(all( target_pointer_width = "64", any(target_os = "freebsd", target_os = "dragonfly") )))] fds_bits: [i32; FD_SETSIZE as usize / 32], } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *mut c_char, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: crate::socklen_t, pub msg_iov: *mut crate::iovec, pub msg_iovlen: c_int, pub msg_control: *mut c_void, pub msg_controllen: crate::socklen_t, pub msg_flags: c_int, } pub struct cmsghdr { pub cmsg_len: crate::socklen_t, pub cmsg_level: c_int, pub cmsg_type: c_int, } pub struct fsid_t { __fsid_val: [i32; 2], } pub struct if_nameindex { pub if_index: c_uint, pub if_name: *mut c_char, } pub struct regex_t { __re_magic: c_int, __re_nsub: size_t, __re_endp: *const c_char, __re_g: *mut c_void, } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct option { pub name: *const c_char, pub has_arg: c_int, pub flag: *mut c_int, pub val: c_int, } } s_no_extra_traits! { pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char; 104], } pub struct utsname { #[cfg(not(target_os = "dragonfly"))] pub sysname: [c_char; 256], #[cfg(target_os = "dragonfly")] pub sysname: [c_char; 32], #[cfg(not(target_os = "dragonfly"))] pub nodename: [c_char; 256], #[cfg(target_os = "dragonfly")] pub nodename: [c_char; 32], #[cfg(not(target_os = "dragonfly"))] pub release: [c_char; 256], #[cfg(target_os = "dragonfly")] pub release: [c_char; 32], #[cfg(not(target_os = "dragonfly"))] pub version: [c_char; 256], #[cfg(target_os = "dragonfly")] pub version: [c_char; 32], #[cfg(not(target_os = "dragonfly"))] pub machine: [c_char; 256], #[cfg(target_os = "dragonfly")] pub machine: [c_char; 32], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_len == other.sun_len && self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_un") .field("sun_len", &self.sun_len) .field("sun_family", &self.sun_family) // FIXME(debug): .field("sun_path", &self.sun_path) .finish() } } impl hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_len.hash(state); self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl fmt::Debug for utsname { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utsname") // FIXME(debug): .field("sysname", &self.sysname) // FIXME(debug): .field("nodename", &self.nodename) // FIXME(debug): .field("release", &self.release) // FIXME(debug): .field("version", &self.version) // FIXME(debug): .field("machine", &self.machine) .finish() } } impl hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); } } } } pub const LC_ALL: c_int = 0; pub const LC_COLLATE: c_int = 1; pub const LC_CTYPE: c_int = 2; pub const LC_MONETARY: c_int = 3; pub const LC_NUMERIC: c_int = 4; pub const LC_TIME: c_int = 5; pub const LC_MESSAGES: c_int = 6; pub const FIOCLEX: c_ulong = 0x20006601; pub const FIONCLEX: c_ulong = 0x20006602; pub const FIONREAD: c_ulong = 0x4004667f; pub const FIONBIO: c_ulong = 0x8004667e; pub const FIOASYNC: c_ulong = 0x8004667d; pub const FIOSETOWN: c_ulong = 0x8004667c; pub const FIOGETOWN: c_ulong = 0x4004667b; pub const PATH_MAX: c_int = 1024; pub const MAXPATHLEN: c_int = PATH_MAX; pub const IOV_MAX: c_int = 1024; pub const SA_ONSTACK: c_int = 0x0001; pub const SA_SIGINFO: c_int = 0x0040; pub const SA_RESTART: c_int = 0x0002; pub const SA_RESETHAND: c_int = 0x0004; pub const SA_NOCLDSTOP: c_int = 0x0008; pub const SA_NODEFER: c_int = 0x0010; pub const SA_NOCLDWAIT: c_int = 0x0020; pub const SS_ONSTACK: c_int = 1; pub const SS_DISABLE: c_int = 4; pub const SIGCHLD: c_int = 20; pub const SIGBUS: c_int = 10; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGCONT: c_int = 19; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGURG: c_int = 16; pub const SIGIO: c_int = 23; pub const SIGSYS: c_int = 12; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGINFO: c_int = 29; pub const SIG_SETMASK: c_int = 3; pub const SIG_BLOCK: c_int = 0x1; pub const SIG_UNBLOCK: c_int = 0x2; pub const IP_TOS: c_int = 3; pub const IP_MULTICAST_IF: c_int = 9; pub const IP_MULTICAST_TTL: c_int = 10; pub const IP_MULTICAST_LOOP: c_int = 11; pub const IPV6_UNICAST_HOPS: c_int = 4; pub const IPV6_MULTICAST_IF: c_int = 9; pub const IPV6_MULTICAST_HOPS: c_int = 10; pub const IPV6_MULTICAST_LOOP: c_int = 11; pub const IPV6_V6ONLY: c_int = 27; pub const IPV6_DONTFRAG: c_int = 62; pub const IPTOS_ECN_NOTECT: u8 = 0x00; pub const IPTOS_ECN_MASK: u8 = 0x03; pub const IPTOS_ECN_ECT1: u8 = 0x01; pub const IPTOS_ECN_ECT0: u8 = 0x02; pub const IPTOS_ECN_CE: u8 = 0x03; pub const ST_RDONLY: c_ulong = 1; pub const SCM_RIGHTS: c_int = 0x01; pub const NCCS: usize = 20; pub const O_ACCMODE: c_int = 0x3; pub const O_RDONLY: c_int = 0; pub const O_WRONLY: c_int = 1; pub const O_RDWR: c_int = 2; pub const O_APPEND: c_int = 8; pub const O_CREAT: c_int = 512; pub const O_TRUNC: c_int = 1024; pub const O_EXCL: c_int = 2048; pub const O_ASYNC: c_int = 0x40; pub const O_SYNC: c_int = 0x80; pub const O_NONBLOCK: c_int = 0x4; pub const O_NOFOLLOW: c_int = 0x100; pub const O_SHLOCK: c_int = 0x10; pub const O_EXLOCK: c_int = 0x20; pub const O_FSYNC: c_int = O_SYNC; pub const O_NDELAY: c_int = O_NONBLOCK; pub const F_GETOWN: c_int = 5; pub const F_SETOWN: c_int = 6; pub const F_RDLCK: c_short = 1; pub const F_UNLCK: c_short = 2; pub const F_WRLCK: c_short = 3; pub const MNT_RDONLY: c_int = 0x00000001; pub const MNT_SYNCHRONOUS: c_int = 0x00000002; pub const MNT_NOEXEC: c_int = 0x00000004; pub const MNT_NOSUID: c_int = 0x00000008; pub const MNT_ASYNC: c_int = 0x00000040; pub const MNT_EXPORTED: c_int = 0x00000100; pub const MNT_UPDATE: c_int = 0x00010000; pub const MNT_RELOAD: c_int = 0x00040000; pub const MNT_FORCE: c_int = 0x00080000; pub const Q_SYNC: c_int = 0x600; pub const Q_QUOTAON: c_int = 0x100; pub const Q_QUOTAOFF: c_int = 0x200; pub const TCIOFF: c_int = 3; pub const TCION: c_int = 4; pub const TCOOFF: c_int = 1; pub const TCOON: c_int = 2; pub const TCIFLUSH: c_int = 1; pub const TCOFLUSH: c_int = 2; pub const TCIOFLUSH: c_int = 3; pub const TCSANOW: c_int = 0; pub const TCSADRAIN: c_int = 1; pub const TCSAFLUSH: c_int = 2; pub const VEOF: usize = 0; pub const VEOL: usize = 1; pub const VEOL2: usize = 2; pub const VERASE: usize = 3; pub const VWERASE: usize = 4; pub const VKILL: usize = 5; pub const VREPRINT: usize = 6; pub const VINTR: usize = 8; pub const VQUIT: usize = 9; pub const VSUSP: usize = 10; pub const VDSUSP: usize = 11; pub const VSTART: usize = 12; pub const VSTOP: usize = 13; pub const VLNEXT: usize = 14; pub const VDISCARD: usize = 15; pub const VMIN: usize = 16; pub const VTIME: usize = 17; pub const VSTATUS: usize = 18; pub const _POSIX_VDISABLE: crate::cc_t = 0xff; pub const IGNBRK: crate::tcflag_t = 0x00000001; pub const BRKINT: crate::tcflag_t = 0x00000002; pub const IGNPAR: crate::tcflag_t = 0x00000004; pub const PARMRK: crate::tcflag_t = 0x00000008; pub const INPCK: crate::tcflag_t = 0x00000010; pub const ISTRIP: crate::tcflag_t = 0x00000020; pub const INLCR: crate::tcflag_t = 0x00000040; pub const IGNCR: crate::tcflag_t = 0x00000080; pub const ICRNL: crate::tcflag_t = 0x00000100; pub const IXON: crate::tcflag_t = 0x00000200; pub const IXOFF: crate::tcflag_t = 0x00000400; pub const IXANY: crate::tcflag_t = 0x00000800; pub const IMAXBEL: crate::tcflag_t = 0x00002000; pub const OPOST: crate::tcflag_t = 0x1; pub const ONLCR: crate::tcflag_t = 0x2; pub const OXTABS: crate::tcflag_t = 0x4; pub const ONOEOT: crate::tcflag_t = 0x8; pub const CIGNORE: crate::tcflag_t = 0x00000001; pub const CSIZE: crate::tcflag_t = 0x00000300; pub const CS5: crate::tcflag_t = 0x00000000; pub const CS6: crate::tcflag_t = 0x00000100; pub const CS7: crate::tcflag_t = 0x00000200; pub const CS8: crate::tcflag_t = 0x00000300; pub const CSTOPB: crate::tcflag_t = 0x00000400; pub const CREAD: crate::tcflag_t = 0x00000800; pub const PARENB: crate::tcflag_t = 0x00001000; pub const PARODD: crate::tcflag_t = 0x00002000; pub const HUPCL: crate::tcflag_t = 0x00004000; pub const CLOCAL: crate::tcflag_t = 0x00008000; pub const ECHOKE: crate::tcflag_t = 0x00000001; pub const ECHOE: crate::tcflag_t = 0x00000002; pub const ECHOK: crate::tcflag_t = 0x00000004; pub const ECHO: crate::tcflag_t = 0x00000008; pub const ECHONL: crate::tcflag_t = 0x00000010; pub const ECHOPRT: crate::tcflag_t = 0x00000020; pub const ECHOCTL: crate::tcflag_t = 0x00000040; pub const ISIG: crate::tcflag_t = 0x00000080; pub const ICANON: crate::tcflag_t = 0x00000100; pub const ALTWERASE: crate::tcflag_t = 0x00000200; pub const IEXTEN: crate::tcflag_t = 0x00000400; pub const EXTPROC: crate::tcflag_t = 0x00000800; pub const TOSTOP: crate::tcflag_t = 0x00400000; pub const FLUSHO: crate::tcflag_t = 0x00800000; pub const NOKERNINFO: crate::tcflag_t = 0x02000000; pub const PENDIN: crate::tcflag_t = 0x20000000; pub const NOFLSH: crate::tcflag_t = 0x80000000; pub const MDMBUF: crate::tcflag_t = 0x00100000; pub const WNOHANG: c_int = 0x00000001; pub const WUNTRACED: c_int = 0x00000002; pub const RTLD_LAZY: c_int = 0x1; pub const RTLD_NOW: c_int = 0x2; pub const RTLD_NEXT: *mut c_void = -1isize as *mut c_void; pub const RTLD_DEFAULT: *mut c_void = -2isize as *mut c_void; pub const RTLD_SELF: *mut c_void = -3isize as *mut c_void; pub const LOG_CRON: c_int = 9 << 3; pub const LOG_AUTHPRIV: c_int = 10 << 3; pub const LOG_FTP: c_int = 11 << 3; pub const LOG_PERROR: c_int = 0x20; pub const TCP_NODELAY: c_int = 1; pub const TCP_MAXSEG: c_int = 2; pub const PIPE_BUF: usize = 512; // si_code values for SIGBUS signal pub const BUS_ADRALN: c_int = 1; pub const BUS_ADRERR: c_int = 2; pub const BUS_OBJERR: c_int = 3; // si_code values for SIGCHLD signal pub const CLD_EXITED: c_int = 1; pub const CLD_KILLED: c_int = 2; pub const CLD_DUMPED: c_int = 3; pub const CLD_TRAPPED: c_int = 4; pub const CLD_STOPPED: c_int = 5; pub const CLD_CONTINUED: c_int = 6; pub const POLLIN: c_short = 0x1; pub const POLLPRI: c_short = 0x2; pub const POLLOUT: c_short = 0x4; pub const POLLERR: c_short = 0x8; pub const POLLHUP: c_short = 0x10; pub const POLLNVAL: c_short = 0x20; pub const POLLRDNORM: c_short = 0x040; pub const POLLWRNORM: c_short = 0x004; pub const POLLRDBAND: c_short = 0x080; pub const POLLWRBAND: c_short = 0x100; pub const BIOCGBLEN: c_ulong = 0x40044266; pub const BIOCSBLEN: c_ulong = 0xc0044266; pub const BIOCFLUSH: c_uint = 0x20004268; pub const BIOCPROMISC: c_uint = 0x20004269; pub const BIOCGDLT: c_ulong = 0x4004426a; pub const BIOCGETIF: c_ulong = 0x4020426b; pub const BIOCSETIF: c_ulong = 0x8020426c; pub const BIOCGSTATS: c_ulong = 0x4008426f; pub const BIOCIMMEDIATE: c_ulong = 0x80044270; pub const BIOCVERSION: c_ulong = 0x40044271; pub const BIOCGHDRCMPLT: c_ulong = 0x40044274; pub const BIOCSHDRCMPLT: c_ulong = 0x80044275; pub const SIOCGIFADDR: c_ulong = 0xc0206921; pub const REG_BASIC: c_int = 0o0000; pub const REG_EXTENDED: c_int = 0o0001; pub const REG_ICASE: c_int = 0o0002; pub const REG_NOSUB: c_int = 0o0004; pub const REG_NEWLINE: c_int = 0o0010; pub const REG_NOSPEC: c_int = 0o0020; pub const REG_PEND: c_int = 0o0040; pub const REG_DUMP: c_int = 0o0200; pub const REG_NOMATCH: c_int = 1; pub const REG_BADPAT: c_int = 2; pub const REG_ECOLLATE: c_int = 3; pub const REG_ECTYPE: c_int = 4; pub const REG_EESCAPE: c_int = 5; pub const REG_ESUBREG: c_int = 6; pub const REG_EBRACK: c_int = 7; pub const REG_EPAREN: c_int = 8; pub const REG_EBRACE: c_int = 9; pub const REG_BADBR: c_int = 10; pub const REG_ERANGE: c_int = 11; pub const REG_ESPACE: c_int = 12; pub const REG_BADRPT: c_int = 13; pub const REG_EMPTY: c_int = 14; pub const REG_ASSERT: c_int = 15; pub const REG_INVARG: c_int = 16; pub const REG_ATOI: c_int = 255; pub const REG_ITOA: c_int = 0o0400; pub const REG_NOTBOL: c_int = 0o00001; pub const REG_NOTEOL: c_int = 0o00002; pub const REG_STARTEND: c_int = 0o00004; pub const REG_TRACE: c_int = 0o00400; pub const REG_LARGE: c_int = 0o01000; pub const REG_BACKR: c_int = 0o02000; pub const TIOCCBRK: c_uint = 0x2000747a; pub const TIOCSBRK: c_uint = 0x2000747b; pub const PRIO_PROCESS: c_int = 0; pub const PRIO_PGRP: c_int = 1; pub const PRIO_USER: c_int = 2; pub const ITIMER_REAL: c_int = 0; pub const ITIMER_VIRTUAL: c_int = 1; pub const ITIMER_PROF: c_int = 2; // net/route.h pub const RTF_UP: c_int = 0x1; pub const RTF_GATEWAY: c_int = 0x2; pub const RTF_HOST: c_int = 0x4; pub const RTF_REJECT: c_int = 0x8; pub const RTF_DYNAMIC: c_int = 0x10; pub const RTF_MODIFIED: c_int = 0x20; pub const RTF_DONE: c_int = 0x40; pub const RTF_STATIC: c_int = 0x800; pub const RTF_BLACKHOLE: c_int = 0x1000; pub const RTF_PROTO2: c_int = 0x4000; pub const RTF_PROTO1: c_int = 0x8000; // Message types pub const RTM_ADD: c_int = 0x1; pub const RTM_DELETE: c_int = 0x2; pub const RTM_CHANGE: c_int = 0x3; pub const RTM_GET: c_int = 0x4; pub const RTM_LOSING: c_int = 0x5; pub const RTM_REDIRECT: c_int = 0x6; pub const RTM_MISS: c_int = 0x7; // Bitmask values for rtm_addrs. pub const RTA_DST: c_int = 0x1; pub const RTA_GATEWAY: c_int = 0x2; pub const RTA_NETMASK: c_int = 0x4; pub const RTA_GENMASK: c_int = 0x8; pub const RTA_IFP: c_int = 0x10; pub const RTA_IFA: c_int = 0x20; pub const RTA_AUTHOR: c_int = 0x40; pub const RTA_BRD: c_int = 0x80; // Index offsets for sockaddr array for alternate internal encoding. pub const RTAX_DST: c_int = 0; pub const RTAX_GATEWAY: c_int = 1; pub const RTAX_NETMASK: c_int = 2; pub const RTAX_GENMASK: c_int = 3; pub const RTAX_IFP: c_int = 4; pub const RTAX_IFA: c_int = 5; pub const RTAX_AUTHOR: c_int = 6; pub const RTAX_BRD: c_int = 7; f! { pub fn CMSG_FIRSTHDR(mhdr: *const crate::msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { core::ptr::null_mut() } } pub fn FD_CLR(fd: c_int, set: *mut fd_set) -> () { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); return; } pub fn FD_ISSET(fd: c_int, set: *const fd_set) -> bool { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0; } pub fn FD_SET(fd: c_int, set: *mut fd_set) -> () { let bits = mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] |= 1 << (fd % bits); return; } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub {const} fn WTERMSIG(status: c_int) -> c_int { status & 0o177 } pub {const} fn WIFEXITED(status: c_int) -> bool { (status & 0o177) == 0 } pub {const} fn WEXITSTATUS(status: c_int) -> c_int { (status >> 8) & 0x00ff } pub {const} fn WCOREDUMP(status: c_int) -> bool { (status & 0o200) != 0 } pub {const} fn QCMD(cmd: c_int, type_: c_int) -> c_int { (cmd << 8) | (type_ & 0x00ff) } } extern "C" { #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getrlimit$UNIX2003" )] pub fn getrlimit(resource: c_int, rlim: *mut crate::rlimit) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "setrlimit$UNIX2003" )] pub fn setrlimit(resource: c_int, rlim: *const crate::rlimit) -> c_int; pub fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; #[cfg_attr( all(target_os = "freebsd", any(freebsd12, freebsd11, freebsd10)), link_name = "rand@FBSD_1.0" )] pub fn rand() -> c_int; #[cfg_attr( all(target_os = "freebsd", any(freebsd12, freebsd11, freebsd10)), link_name = "srand@FBSD_1.0" )] pub fn srand(seed: c_uint); pub fn getifaddrs(ifap: *mut *mut crate::ifaddrs) -> c_int; pub fn freeifaddrs(ifa: *mut crate::ifaddrs); pub fn setgroups(ngroups: c_int, ptr: *const crate::gid_t) -> c_int; pub fn setlogin(name: *const c_char) -> c_int; pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int; pub fn kqueue() -> c_int; pub fn unmount(target: *const c_char, arg: c_int) -> c_int; pub fn syscall(num: c_int, ...) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__getpwent50")] pub fn getpwent() -> *mut passwd; pub fn setpwent(); pub fn endpwent(); pub fn endgrent(); pub fn getgrent() -> *mut crate::group; pub fn getprogname() -> *const c_char; pub fn setprogname(name: *const c_char); pub fn getloadavg(loadavg: *mut c_double, nelem: c_int) -> c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn getpeereid(socket: c_int, euid: *mut crate::uid_t, egid: *mut crate::gid_t) -> c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "glob$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__glob30")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "glob@FBSD_1.0" )] pub fn glob( pattern: *const c_char, flags: c_int, errfunc: Option c_int>, pglob: *mut crate::glob_t, ) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__globfree30")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "globfree@FBSD_1.0" )] pub fn globfree(pglob: *mut crate::glob_t); pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; pub fn shm_unlink(name: *const c_char) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "seekdir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "seekdir$INODE64$UNIX2003" )] pub fn seekdir(dirp: *mut crate::DIR, loc: c_long); #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "telldir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "telldir$INODE64$UNIX2003" )] pub fn telldir(dirp: *mut crate::DIR) -> c_long; pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "msync$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__msync13")] pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "recvfrom$UNIX2003" )] pub fn recvfrom( socket: c_int, buf: *mut c_void, len: size_t, flags: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, ) -> ssize_t; pub fn mkstemps(template: *mut c_char, suffixlen: c_int) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__futimes50")] pub fn futimes(fd: c_int, times: *const crate::timeval) -> c_int; pub fn nl_langinfo(item: crate::nl_item) -> *mut c_char; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "bind$UNIX2003" )] pub fn bind( socket: c_int, address: *const crate::sockaddr, address_len: crate::socklen_t, ) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "writev$UNIX2003" )] pub fn writev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "readv$UNIX2003" )] pub fn readv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sendmsg$UNIX2003" )] pub fn sendmsg(fd: c_int, msg: *const crate::msghdr, flags: c_int) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "recvmsg$UNIX2003" )] pub fn recvmsg(fd: c_int, msg: *mut crate::msghdr, flags: c_int) -> ssize_t; pub fn sync(); pub fn getgrgid_r( gid: crate::gid_t, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sigaltstack$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__sigaltstack14")] pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> c_int; pub fn sigsuspend(mask: *const crate::sigset_t) -> c_int; pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn getdtablesize() -> c_int; pub fn getgrnam_r( name: *const c_char, grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_sigmask$UNIX2003" )] pub fn pthread_sigmask(how: c_int, set: *const sigset_t, oldset: *mut sigset_t) -> c_int; pub fn sem_open(name: *const c_char, oflag: c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const c_char) -> *mut crate::group; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cancel$UNIX2003" )] pub fn pthread_cancel(thread: crate::pthread_t) -> c_int; pub fn pthread_kill(thread: crate::pthread_t, sig: c_int) -> c_int; pub fn sched_get_priority_min(policy: c_int) -> c_int; pub fn sched_get_priority_max(policy: c_int) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__getpwnam_r50")] pub fn getpwnam_r( name: *const c_char, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid_r50")] pub fn getpwuid_r( uid: crate::uid_t, pwd: *mut passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut passwd, ) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sigwait$UNIX2003" )] pub fn sigwait(set: *const sigset_t, sig: *mut c_int) -> c_int; pub fn pthread_atfork( prepare: Option, parent: Option, child: Option, ) -> c_int; pub fn getgrgid(gid: crate::gid_t) -> *mut crate::group; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "popen$UNIX2003" )] pub fn popen(command: *const c_char, mode: *const c_char) -> *mut crate::FILE; pub fn faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn pthread_create( native: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn acct(filename: *const c_char) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "wait4$UNIX2003" )] #[cfg_attr( all(target_os = "freebsd", any(freebsd12, freebsd11, freebsd10)), link_name = "wait4@FBSD_1.0" )] pub fn wait4( pid: crate::pid_t, status: *mut c_int, options: c_int, rusage: *mut crate::rusage, ) -> crate::pid_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getitimer$UNIX2003" )] pub fn getitimer(which: c_int, curr_value: *mut crate::itimerval) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "setitimer$UNIX2003" )] pub fn setitimer( which: c_int, new_value: *const crate::itimerval, old_value: *mut crate::itimerval, ) -> c_int; pub fn regcomp(preg: *mut regex_t, pattern: *const c_char, cflags: c_int) -> c_int; pub fn regexec( preg: *const regex_t, input: *const c_char, nmatch: size_t, pmatch: *mut regmatch_t, eflags: c_int, ) -> c_int; pub fn regerror( errcode: c_int, preg: *const regex_t, errbuf: *mut c_char, errbuf_size: size_t, ) -> size_t; pub fn regfree(preg: *mut regex_t); pub fn arc4random() -> u32; pub fn arc4random_buf(buf: *mut c_void, size: size_t); pub fn arc4random_uniform(l: u32) -> u32; pub fn drand48() -> c_double; pub fn erand48(xseed: *mut c_ushort) -> c_double; pub fn lrand48() -> c_long; pub fn nrand48(xseed: *mut c_ushort) -> c_long; pub fn mrand48() -> c_long; pub fn jrand48(xseed: *mut c_ushort) -> c_long; pub fn srand48(seed: c_long); pub fn seed48(xseed: *mut c_ushort) -> *mut c_ushort; pub fn lcong48(p: *mut c_ushort); pub fn getopt_long( argc: c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut c_int, ) -> c_int; pub fn strftime( buf: *mut c_char, maxsize: size_t, format: *const c_char, timeptr: *const crate::tm, ) -> size_t; pub fn strftime_l( buf: *mut c_char, maxsize: size_t, format: *const c_char, timeptr: *const crate::tm, locale: crate::locale_t, ) -> size_t; pub fn devname(dev: crate::dev_t, mode_t: crate::mode_t) -> *mut c_char; } cfg_if! { if #[cfg(any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos" ))] { mod apple; pub use self::apple::*; } else if #[cfg(any(target_os = "openbsd", target_os = "netbsd"))] { mod netbsdlike; pub use self::netbsdlike::*; } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] { mod freebsdlike; pub use self::freebsdlike::*; } else { // Unknown target_os } } libc/src/unix/bsd/netbsdlike/0000775000175000017500000000000015105742312015763 5ustar bdrungbdrunglibc/src/unix/bsd/netbsdlike/mod.rs0000644000175000017500000007066215105742312017121 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type wchar_t = i32; pub type time_t = i64; pub type mode_t = u32; pub type nlink_t = u32; pub type ino_t = u64; pub type pthread_key_t = c_int; pub type rlim_t = u64; pub type speed_t = c_uint; pub type tcflag_t = c_uint; pub type nl_item = c_long; pub type clockid_t = c_int; pub type id_t = u32; pub type sem_t = *mut sem; pub type key_t = c_long; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum sem {} impl Copy for sem {} impl Clone for sem { fn clone(&self) -> sem { *self } } s! { pub struct sched_param { pub sched_priority: c_int, } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_mask: crate::sigset_t, pub sa_flags: c_int, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct in6_pktinfo { pub ipi6_addr: crate::in6_addr, pub ipi6_ifindex: c_uint, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_cc: [crate::cc_t; crate::NCCS], pub c_ispeed: c_int, pub c_ospeed: c_int, } pub struct flock { pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, pub l_type: c_short, pub l_whence: c_short, } pub struct ipc_perm { pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub mode: crate::mode_t, #[cfg(target_os = "openbsd")] pub seq: c_ushort, #[cfg(target_os = "netbsd")] pub _seq: c_ushort, #[cfg(target_os = "openbsd")] pub key: crate::key_t, #[cfg(target_os = "netbsd")] pub _key: crate::key_t, } pub struct ptrace_io_desc { pub piod_op: c_int, pub piod_offs: *mut c_void, pub piod_addr: *mut c_void, pub piod_len: size_t, } pub struct mmsghdr { pub msg_hdr: crate::msghdr, pub msg_len: c_uint, } } pub const D_T_FMT: crate::nl_item = 0; pub const D_FMT: crate::nl_item = 1; pub const T_FMT: crate::nl_item = 2; pub const T_FMT_AMPM: crate::nl_item = 3; pub const AM_STR: crate::nl_item = 4; pub const PM_STR: crate::nl_item = 5; pub const DAY_1: crate::nl_item = 6; pub const DAY_2: crate::nl_item = 7; pub const DAY_3: crate::nl_item = 8; pub const DAY_4: crate::nl_item = 9; pub const DAY_5: crate::nl_item = 10; pub const DAY_6: crate::nl_item = 11; pub const DAY_7: crate::nl_item = 12; pub const ABDAY_1: crate::nl_item = 13; pub const ABDAY_2: crate::nl_item = 14; pub const ABDAY_3: crate::nl_item = 15; pub const ABDAY_4: crate::nl_item = 16; pub const ABDAY_5: crate::nl_item = 17; pub const ABDAY_6: crate::nl_item = 18; pub const ABDAY_7: crate::nl_item = 19; pub const MON_1: crate::nl_item = 20; pub const MON_2: crate::nl_item = 21; pub const MON_3: crate::nl_item = 22; pub const MON_4: crate::nl_item = 23; pub const MON_5: crate::nl_item = 24; pub const MON_6: crate::nl_item = 25; pub const MON_7: crate::nl_item = 26; pub const MON_8: crate::nl_item = 27; pub const MON_9: crate::nl_item = 28; pub const MON_10: crate::nl_item = 29; pub const MON_11: crate::nl_item = 30; pub const MON_12: crate::nl_item = 31; pub const ABMON_1: crate::nl_item = 32; pub const ABMON_2: crate::nl_item = 33; pub const ABMON_3: crate::nl_item = 34; pub const ABMON_4: crate::nl_item = 35; pub const ABMON_5: crate::nl_item = 36; pub const ABMON_6: crate::nl_item = 37; pub const ABMON_7: crate::nl_item = 38; pub const ABMON_8: crate::nl_item = 39; pub const ABMON_9: crate::nl_item = 40; pub const ABMON_10: crate::nl_item = 41; pub const ABMON_11: crate::nl_item = 42; pub const ABMON_12: crate::nl_item = 43; pub const RADIXCHAR: crate::nl_item = 44; pub const THOUSEP: crate::nl_item = 45; pub const YESSTR: crate::nl_item = 46; pub const YESEXPR: crate::nl_item = 47; pub const NOSTR: crate::nl_item = 48; pub const NOEXPR: crate::nl_item = 49; pub const CRNCYSTR: crate::nl_item = 50; pub const CODESET: crate::nl_item = 51; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 2147483647; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const BUFSIZ: c_uint = 1024; pub const FOPEN_MAX: c_uint = 20; pub const FILENAME_MAX: c_uint = 1024; pub const L_tmpnam: c_uint = 1024; pub const O_NOCTTY: c_int = 32768; pub const S_IFIFO: mode_t = 0o1_0000; pub const S_IFCHR: mode_t = 0o2_0000; pub const S_IFBLK: mode_t = 0o6_0000; pub const S_IFDIR: mode_t = 0o4_0000; pub const S_IFREG: mode_t = 0o10_0000; pub const S_IFLNK: mode_t = 0o12_0000; pub const S_IFSOCK: mode_t = 0o14_0000; pub const S_IFMT: mode_t = 0o17_0000; pub const S_IEXEC: mode_t = 0o0100; pub const S_IWRITE: mode_t = 0o0200; pub const S_IREAD: mode_t = 0o0400; pub const S_IRWXU: mode_t = 0o0700; pub const S_IXUSR: mode_t = 0o0100; pub const S_IWUSR: mode_t = 0o0200; pub const S_IRUSR: mode_t = 0o0400; pub const S_IRWXG: mode_t = 0o0070; pub const S_IXGRP: mode_t = 0o0010; pub const S_IWGRP: mode_t = 0o0020; pub const S_IRGRP: mode_t = 0o0040; pub const S_IRWXO: mode_t = 0o0007; pub const S_IXOTH: mode_t = 0o0001; pub const S_IWOTH: mode_t = 0o0002; pub const S_IROTH: mode_t = 0o0004; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const F_GETLK: c_int = 7; pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSEGV: c_int = 11; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const MAP_FILE: c_int = 0x0000; pub const MAP_SHARED: c_int = 0x0001; pub const MAP_PRIVATE: c_int = 0x0002; pub const MAP_FIXED: c_int = 0x0010; pub const MAP_ANON: c_int = 0x1000; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const IPC_CREAT: c_int = 0o001000; pub const IPC_EXCL: c_int = 0o002000; pub const IPC_NOWAIT: c_int = 0o004000; pub const IPC_PRIVATE: crate::key_t = 0; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 1; pub const IPC_STAT: c_int = 2; pub const IPC_R: c_int = 0o000400; pub const IPC_W: c_int = 0o000200; pub const IPC_M: c_int = 0o010000; pub const SHM_R: c_int = IPC_R; pub const SHM_W: c_int = IPC_W; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MS_ASYNC: c_int = 0x0001; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EDEADLK: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EAGAIN: c_int = 35; pub const EWOULDBLOCK: c_int = 35; pub const EINPROGRESS: c_int = 36; pub const EALREADY: c_int = 37; pub const ENOTSOCK: c_int = 38; pub const EDESTADDRREQ: c_int = 39; pub const EMSGSIZE: c_int = 40; pub const EPROTOTYPE: c_int = 41; pub const ENOPROTOOPT: c_int = 42; pub const EPROTONOSUPPORT: c_int = 43; pub const ESOCKTNOSUPPORT: c_int = 44; pub const EOPNOTSUPP: c_int = 45; pub const EPFNOSUPPORT: c_int = 46; pub const EAFNOSUPPORT: c_int = 47; pub const EADDRINUSE: c_int = 48; pub const EADDRNOTAVAIL: c_int = 49; pub const ENETDOWN: c_int = 50; pub const ENETUNREACH: c_int = 51; pub const ENETRESET: c_int = 52; pub const ECONNABORTED: c_int = 53; pub const ECONNRESET: c_int = 54; pub const ENOBUFS: c_int = 55; pub const EISCONN: c_int = 56; pub const ENOTCONN: c_int = 57; pub const ESHUTDOWN: c_int = 58; pub const ETOOMANYREFS: c_int = 59; pub const ETIMEDOUT: c_int = 60; pub const ECONNREFUSED: c_int = 61; pub const ELOOP: c_int = 62; pub const ENAMETOOLONG: c_int = 63; pub const EHOSTDOWN: c_int = 64; pub const EHOSTUNREACH: c_int = 65; pub const ENOTEMPTY: c_int = 66; pub const EPROCLIM: c_int = 67; pub const EUSERS: c_int = 68; pub const EDQUOT: c_int = 69; pub const ESTALE: c_int = 70; pub const EREMOTE: c_int = 71; pub const EBADRPC: c_int = 72; pub const ERPCMISMATCH: c_int = 73; pub const EPROGUNAVAIL: c_int = 74; pub const EPROGMISMATCH: c_int = 75; pub const EPROCUNAVAIL: c_int = 76; pub const ENOLCK: c_int = 77; pub const ENOSYS: c_int = 78; pub const EFTYPE: c_int = 79; pub const EAUTH: c_int = 80; pub const ENEEDAUTH: c_int = 81; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const GLOB_APPEND: c_int = 0x0001; pub const GLOB_DOOFFS: c_int = 0x0002; pub const GLOB_ERR: c_int = 0x0004; pub const GLOB_MARK: c_int = 0x0008; pub const GLOB_NOCHECK: c_int = 0x0010; pub const GLOB_NOSORT: c_int = 0x0020; pub const GLOB_NOESCAPE: c_int = 0x1000; pub const GLOB_NOSPACE: c_int = -1; pub const GLOB_ABORTED: c_int = -2; pub const GLOB_NOMATCH: c_int = -3; pub const GLOB_NOSYS: c_int = -4; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 1; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const POSIX_MADV_DONTNEED: c_int = 4; // DIFF(main): changed to `c_short` in f62eb023ab pub const POSIX_SPAWN_RESETIDS: c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: c_int = 0x02; pub const POSIX_SPAWN_SETSCHEDPARAM: c_int = 0x04; pub const POSIX_SPAWN_SETSCHEDULER: c_int = 0x08; pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x10; pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x20; pub const PTHREAD_CREATE_JOINABLE: c_int = 0; pub const PTHREAD_CREATE_DETACHED: c_int = 1; pub const PIOD_READ_D: c_int = 1; pub const PIOD_WRITE_D: c_int = 2; pub const PIOD_READ_I: c_int = 3; pub const PIOD_WRITE_I: c_int = 4; pub const PIOD_READ_AUXV: c_int = 5; pub const PT_TRACE_ME: c_int = 0; pub const PT_READ_I: c_int = 1; pub const PT_READ_D: c_int = 2; pub const PT_WRITE_I: c_int = 4; pub const PT_WRITE_D: c_int = 5; pub const PT_CONTINUE: c_int = 7; pub const PT_KILL: c_int = 8; pub const PT_ATTACH: c_int = 9; pub const PT_DETACH: c_int = 10; pub const PT_IO: c_int = 11; // http://man.openbsd.org/OpenBSD-current/man2/clock_getres.2 // The man page says clock_gettime(3) can accept various values as clockid_t but // http://fxr.watson.org/fxr/source/kern/kern_time.c?v=OPENBSD;im=excerpts#L161 // the implementation rejects anything other than the below two // // http://netbsd.gw.com/cgi-bin/man-cgi?clock_gettime // https://github.com/jsonn/src/blob/HEAD/sys/kern/subr_time.c#L222 // Basically the same goes for NetBSD pub const CLOCK_REALTIME: crate::clockid_t = 0; pub const CLOCK_MONOTONIC: crate::clockid_t = 3; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_RSS: c_int = 5; pub const RLIMIT_MEMLOCK: c_int = 6; pub const RLIMIT_NPROC: c_int = 7; pub const RLIMIT_NOFILE: c_int = 8; pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; pub const RUSAGE_SELF: c_int = 0; pub const RUSAGE_CHILDREN: c_int = -1; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const MADV_FREE: c_int = 6; // sys/fstypes.h in NetBSD, or sys/mount.h in OpenBSD pub const MNT_NODEV: c_int = 0x00000010; pub const MNT_LOCAL: c_int = 0x00001000; pub const MNT_QUOTA: c_int = 0x00002000; pub const AF_UNSPEC: c_int = 0; pub const AF_LOCAL: c_int = 1; pub const AF_UNIX: c_int = AF_LOCAL; pub const AF_INET: c_int = 2; pub const AF_IMPLINK: c_int = 3; pub const AF_PUP: c_int = 4; pub const AF_CHAOS: c_int = 5; pub const AF_NS: c_int = 6; pub const AF_ISO: c_int = 7; pub const AF_OSI: c_int = AF_ISO; pub const AF_DATAKIT: c_int = 9; pub const AF_CCITT: c_int = 10; pub const AF_SNA: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_DLI: c_int = 13; pub const AF_LAT: c_int = 14; pub const AF_HYLINK: c_int = 15; pub const AF_APPLETALK: c_int = 16; pub const AF_LINK: c_int = 18; pub const pseudo_AF_XTP: c_int = 19; pub const AF_COIP: c_int = 20; pub const AF_CNT: c_int = 21; pub const pseudo_AF_RTIP: c_int = 22; pub const AF_IPX: c_int = 23; pub const AF_INET6: c_int = 24; pub const pseudo_AF_PIP: c_int = 25; pub const AF_ISDN: c_int = 26; pub const AF_E164: c_int = AF_ISDN; pub const AF_NATM: c_int = 27; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_LOCAL: c_int = AF_LOCAL; pub const PF_UNIX: c_int = PF_LOCAL; pub const PF_INET: c_int = AF_INET; pub const PF_IMPLINK: c_int = AF_IMPLINK; pub const PF_PUP: c_int = AF_PUP; pub const PF_CHAOS: c_int = AF_CHAOS; pub const PF_NS: c_int = AF_NS; pub const PF_ISO: c_int = AF_ISO; pub const PF_OSI: c_int = AF_ISO; pub const PF_DATAKIT: c_int = AF_DATAKIT; pub const PF_CCITT: c_int = AF_CCITT; pub const PF_SNA: c_int = AF_SNA; pub const PF_DECnet: c_int = AF_DECnet; pub const PF_DLI: c_int = AF_DLI; pub const PF_LAT: c_int = AF_LAT; pub const PF_HYLINK: c_int = AF_HYLINK; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_LINK: c_int = AF_LINK; pub const PF_XTP: c_int = pseudo_AF_XTP; pub const PF_COIP: c_int = AF_COIP; pub const PF_CNT: c_int = AF_CNT; pub const PF_IPX: c_int = AF_IPX; pub const PF_INET6: c_int = AF_INET6; pub const PF_RTIP: c_int = pseudo_AF_RTIP; pub const PF_PIP: c_int = pseudo_AF_PIP; pub const PF_ISDN: c_int = AF_ISDN; pub const PF_NATM: c_int = AF_NATM; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_SEQPACKET: c_int = 5; pub const IP_TTL: c_int = 4; pub const IP_HDRINCL: c_int = 2; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IPV6_RECVPKTINFO: c_int = 36; pub const IPV6_PKTINFO: c_int = 46; pub const IPV6_RECVTCLASS: c_int = 57; pub const IPV6_TCLASS: c_int = 61; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_DEBUG: c_int = 0x01; pub const SO_ACCEPTCONN: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_USELOOPBACK: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVLOWAT: c_int = 0x1004; pub const SO_ERROR: c_int = 0x1007; pub const SO_TYPE: c_int = 0x1008; pub const SOMAXCONN: c_int = 128; pub const MSG_OOB: c_int = 0x1; pub const MSG_PEEK: c_int = 0x2; pub const MSG_DONTROUTE: c_int = 0x4; pub const MSG_EOR: c_int = 0x8; pub const MSG_TRUNC: c_int = 0x10; pub const MSG_CTRUNC: c_int = 0x20; pub const MSG_WAITALL: c_int = 0x40; pub const MSG_DONTWAIT: c_int = 0x80; pub const MSG_BCAST: c_int = 0x100; pub const MSG_MCAST: c_int = 0x200; pub const MSG_NOSIGNAL: c_int = 0x400; pub const MSG_CMSG_CLOEXEC: c_int = 0x800; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; pub const IPPROTO_RAW: c_int = 255; pub const _SC_ARG_MAX: c_int = 1; pub const _SC_CHILD_MAX: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 4; pub const _SC_OPEN_MAX: c_int = 5; pub const _SC_JOB_CONTROL: c_int = 6; pub const _SC_SAVED_IDS: c_int = 7; pub const _SC_VERSION: c_int = 8; pub const _SC_BC_BASE_MAX: c_int = 9; pub const _SC_BC_DIM_MAX: c_int = 10; pub const _SC_BC_SCALE_MAX: c_int = 11; pub const _SC_BC_STRING_MAX: c_int = 12; pub const _SC_COLL_WEIGHTS_MAX: c_int = 13; pub const _SC_EXPR_NEST_MAX: c_int = 14; pub const _SC_LINE_MAX: c_int = 15; pub const _SC_RE_DUP_MAX: c_int = 16; pub const _SC_2_VERSION: c_int = 17; pub const _SC_2_C_BIND: c_int = 18; pub const _SC_2_C_DEV: c_int = 19; pub const _SC_2_CHAR_TERM: c_int = 20; pub const _SC_2_FORT_DEV: c_int = 21; pub const _SC_2_FORT_RUN: c_int = 22; pub const _SC_2_LOCALEDEF: c_int = 23; pub const _SC_2_SW_DEV: c_int = 24; pub const _SC_2_UPE: c_int = 25; pub const _SC_STREAM_MAX: c_int = 26; pub const _SC_TZNAME_MAX: c_int = 27; pub const _SC_PAGESIZE: c_int = 28; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_FSYNC: c_int = 29; pub const _SC_XOPEN_SHM: c_int = 30; pub const Q_GETQUOTA: c_int = 0x300; pub const Q_SETQUOTA: c_int = 0x400; pub const RTLD_GLOBAL: c_int = 0x100; pub const LOG_NFACILITIES: c_int = 24; pub const HW_NCPU: c_int = 3; pub const B0: speed_t = 0; pub const B50: speed_t = 50; pub const B75: speed_t = 75; pub const B110: speed_t = 110; pub const B134: speed_t = 134; pub const B150: speed_t = 150; pub const B200: speed_t = 200; pub const B300: speed_t = 300; pub const B600: speed_t = 600; pub const B1200: speed_t = 1200; pub const B1800: speed_t = 1800; pub const B2400: speed_t = 2400; pub const B4800: speed_t = 4800; pub const B9600: speed_t = 9600; pub const B19200: speed_t = 19200; pub const B38400: speed_t = 38400; pub const B7200: speed_t = 7200; pub const B14400: speed_t = 14400; pub const B28800: speed_t = 28800; pub const B57600: speed_t = 57600; pub const B76800: speed_t = 76800; pub const B115200: speed_t = 115200; pub const B230400: speed_t = 230400; pub const EXTA: speed_t = 19200; pub const EXTB: speed_t = 38400; pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; pub const CRTSCTS: crate::tcflag_t = 0x00010000; pub const CRTS_IFLOW: crate::tcflag_t = CRTSCTS; pub const CCTS_OFLOW: crate::tcflag_t = CRTSCTS; pub const OCRNL: crate::tcflag_t = 0x10; pub const TIOCEXCL: c_ulong = 0x2000740d; pub const TIOCNXCL: c_ulong = 0x2000740e; pub const TIOCFLUSH: c_ulong = 0x80047410; pub const TIOCGETA: c_ulong = 0x402c7413; pub const TIOCSETA: c_ulong = 0x802c7414; pub const TIOCSETAW: c_ulong = 0x802c7415; pub const TIOCSETAF: c_ulong = 0x802c7416; pub const TIOCGETD: c_ulong = 0x4004741a; pub const TIOCSETD: c_ulong = 0x8004741b; pub const TIOCMGET: c_ulong = 0x4004746a; pub const TIOCMBIC: c_ulong = 0x8004746b; pub const TIOCMBIS: c_ulong = 0x8004746c; pub const TIOCMSET: c_ulong = 0x8004746d; pub const TIOCSTART: c_ulong = 0x2000746e; pub const TIOCSTOP: c_ulong = 0x2000746f; pub const TIOCSCTTY: c_ulong = 0x20007461; pub const TIOCGWINSZ: c_ulong = 0x40087468; pub const TIOCSWINSZ: c_ulong = 0x80087467; pub const TIOCM_LE: c_int = 0o0001; pub const TIOCM_DTR: c_int = 0o0002; pub const TIOCM_RTS: c_int = 0o0004; pub const TIOCM_ST: c_int = 0o0010; pub const TIOCM_SR: c_int = 0o0020; pub const TIOCM_CTS: c_int = 0o0040; pub const TIOCM_CAR: c_int = 0o0100; pub const TIOCM_RNG: c_int = 0o0200; pub const TIOCM_DSR: c_int = 0o0400; pub const TIOCM_CD: c_int = TIOCM_CAR; pub const TIOCM_RI: c_int = TIOCM_RNG; pub const TIMER_ABSTIME: c_int = 1; // sys/reboot.h pub const RB_AUTOBOOT: c_int = 0; pub const TCP_INFO: c_int = 9; #[link(name = "util")] extern "C" { pub fn setgrent(); pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn accept4( s: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, flags: c_int, ) -> c_int; pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_char) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_getres50")] pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_gettime50")] pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_settime50")] pub fn clock_settime(clk_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn __errno() -> *mut c_int; pub fn shm_open(name: *const c_char, oflag: c_int, mode: crate::mode_t) -> c_int; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn mkostemp(template: *mut c_char, flags: c_int) -> c_int; pub fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; pub fn login_tty(fd: c_int) -> c_int; pub fn getpriority(which: c_int, who: crate::id_t) -> c_int; pub fn setpriority(which: c_int, who: crate::id_t, prio: c_int) -> c_int; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn sethostname(name: *const c_char, len: size_t) -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const sched_param, ) -> c_int; pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut sched_param, ) -> c_int; pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; pub fn getgrouplist( name: *const c_char, basegid: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn initgroups(name: *const c_char, basegid: crate::gid_t) -> c_int; pub fn getdomainname(name: *mut c_char, len: size_t) -> c_int; pub fn setdomainname(name: *const c_char, len: size_t) -> c_int; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn shmget(key: crate::key_t, size: size_t, shmflg: c_int) -> c_int; pub fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void; pub fn shmdt(shmaddr: *const c_void) -> c_int; pub fn shmctl(shmid: c_int, cmd: c_int, buf: *mut crate::shmid_ds) -> c_int; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn execvpe( file: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; pub fn waitid( idtype: idtype_t, id: crate::id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: crate::pid_t) -> c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut c_int, ) -> c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: c_int) -> c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut crate::sched_param, ) -> c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const crate::sched_param, ) -> c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int, ) -> c_int; } extern "C" { pub fn reallocarray(ptr: *mut c_void, nmemb: size_t, size: size_t) -> *mut c_void; pub fn gethostid() -> c_long; pub fn sethostid(hostid: c_long) -> c_int; pub fn ftok(path: *const c_char, id: c_int) -> crate::key_t; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn basename(path: *mut c_char) -> *mut c_char; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; pub fn sendmmsg(sockfd: c_int, mmsg: *mut crate::mmsghdr, vlen: c_uint, flags: c_int) -> c_int; pub fn recvmmsg( sockfd: c_int, mmsg: *mut crate::mmsghdr, vlen: c_uint, flags: c_int, timeout: *mut crate::timespec, ) -> c_int; pub fn closefrom(lowfd: c_int) -> c_int; } cfg_if! { if #[cfg(target_os = "netbsd")] { mod netbsd; pub use self::netbsd::*; } else if #[cfg(target_os = "openbsd")] { mod openbsd; pub use self::openbsd::*; } else { // Unknown target_os } } libc/src/unix/bsd/netbsdlike/openbsd/0000775000175000017500000000000015105742312017415 5ustar bdrungbdrunglibc/src/unix/bsd/netbsdlike/openbsd/mod.rs0000644000175000017500000021734515105742312020554 0ustar bdrungbdrunguse crate::prelude::*; use crate::unix::bsd::O_SYNC; use crate::{cmsghdr, off_t}; pub type clock_t = i64; pub type suseconds_t = c_long; pub type dev_t = i32; pub type sigset_t = c_uint; pub type blksize_t = i32; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type idtype_t = c_uint; pub type pthread_attr_t = *mut c_void; pub type pthread_mutex_t = *mut c_void; pub type pthread_mutexattr_t = *mut c_void; pub type pthread_cond_t = *mut c_void; pub type pthread_condattr_t = *mut c_void; pub type pthread_rwlock_t = *mut c_void; pub type pthread_rwlockattr_t = *mut c_void; pub type pthread_spinlock_t = crate::uintptr_t; pub type caddr_t = *mut c_char; // elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Lword = u64; pub type Elf32_Off = u32; pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Lword = u64; pub type Elf64_Off = u64; pub type Elf64_Sword = i32; pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; // search.h pub type ENTRY = entry; pub type ACTION = c_uint; // spawn.h pub type posix_spawnattr_t = *mut c_void; pub type posix_spawn_file_actions_t = *mut c_void; cfg_if! { if #[cfg(target_pointer_width = "64")] { type Elf_Addr = Elf64_Addr; type Elf_Half = Elf64_Half; type Elf_Phdr = Elf64_Phdr; } else if #[cfg(target_pointer_width = "32")] { type Elf_Addr = Elf32_Addr; type Elf_Half = Elf32_Half; type Elf_Phdr = Elf32_Phdr; } } s! { pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: c_int, } pub struct glob_t { pub gl_pathc: size_t, pub gl_matchc: size_t, pub gl_offs: size_t, pub gl_flags: c_int, pub gl_pathv: *mut *mut c_char, __unused1: *mut c_void, __unused2: *mut c_void, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, __unused6: *mut c_void, __unused7: *mut c_void, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct ufs_args { pub fspec: *mut c_char, pub export_info: export_args, } pub struct mfs_args { pub fspec: *mut c_char, pub export_info: export_args, // https://github.com/openbsd/src/blob/HEAD/sys/sys/types.h#L134 pub base: *mut c_char, pub size: c_ulong, } pub struct iso_args { pub fspec: *mut c_char, pub export_info: export_args, pub flags: c_int, pub sess: c_int, } pub struct nfs_args { pub version: c_int, pub addr: *mut crate::sockaddr, pub addrlen: c_int, pub sotype: c_int, pub proto: c_int, pub fh: *mut c_uchar, pub fhsize: c_int, pub flags: c_int, pub wsize: c_int, pub rsize: c_int, pub readdirsize: c_int, pub timeo: c_int, pub retrans: c_int, pub maxgrouplist: c_int, pub readahead: c_int, pub leaseterm: c_int, pub deadthresh: c_int, pub hostname: *mut c_char, pub acregmin: c_int, pub acregmax: c_int, pub acdirmin: c_int, pub acdirmax: c_int, } pub struct msdosfs_args { pub fspec: *mut c_char, pub export_info: export_args, pub uid: crate::uid_t, pub gid: crate::gid_t, pub mask: crate::mode_t, pub flags: c_int, } pub struct ntfs_args { pub fspec: *mut c_char, pub export_info: export_args, pub uid: crate::uid_t, pub gid: crate::gid_t, pub mode: crate::mode_t, pub flag: c_ulong, } pub struct udf_args { pub fspec: *mut c_char, pub lastblock: u32, } pub struct tmpfs_args { pub ta_version: c_int, pub ta_nodes_max: crate::ino_t, pub ta_size_max: off_t, pub ta_root_uid: crate::uid_t, pub ta_root_gid: crate::gid_t, pub ta_root_mode: crate::mode_t, } pub struct fusefs_args { pub name: *mut c_char, pub fd: c_int, pub max_read: c_int, pub allow_other: c_int, } pub struct xucred { pub cr_uid: crate::uid_t, pub cr_gid: crate::gid_t, pub cr_ngroups: c_short, //https://github.com/openbsd/src/blob/HEAD/sys/sys/syslimits.h#L44 pub cr_groups: [crate::gid_t; 16], } pub struct export_args { pub ex_flags: c_int, pub ex_root: crate::uid_t, pub ex_anon: xucred, pub ex_addr: *mut crate::sockaddr, pub ex_addrlen: c_int, pub ex_mask: *mut crate::sockaddr, pub ex_masklen: c_int, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [i8; 8], } pub struct splice { pub sp_fd: c_int, pub sp_max: off_t, pub sp_idle: crate::timeval, } pub struct kevent { pub ident: crate::uintptr_t, pub filter: c_short, pub flags: c_ushort, pub fflags: c_uint, pub data: i64, pub udata: *mut c_void, } pub struct stat { pub st_mode: crate::mode_t, pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: crate::blksize_t, pub st_flags: u32, pub st_gen: u32, pub st_birthtime: crate::time_t, pub st_birthtime_nsec: c_long, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: crate::socklen_t, pub ai_addr: *mut crate::sockaddr, pub ai_canonname: *mut c_char, pub ai_next: *mut crate::addrinfo, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct if_data { pub ifi_type: c_uchar, pub ifi_addrlen: c_uchar, pub ifi_hdrlen: c_uchar, pub ifi_link_state: c_uchar, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_rdomain: u32, pub ifi_baudrate: u64, pub ifi_ipackets: u64, pub ifi_ierrors: u64, pub ifi_opackets: u64, pub ifi_oerrors: u64, pub ifi_collisions: u64, pub ifi_ibytes: u64, pub ifi_obytes: u64, pub ifi_imcasts: u64, pub ifi_omcasts: u64, pub ifi_iqdrops: u64, pub ifi_oqdrops: u64, pub ifi_noproto: u64, pub ifi_capabilities: u32, pub ifi_lastchange: crate::timeval, } pub struct if_msghdr { pub ifm_msglen: c_ushort, pub ifm_version: c_uchar, pub ifm_type: c_uchar, pub ifm_hdrlen: c_ushort, pub ifm_index: c_ushort, pub ifm_tableid: c_ushort, pub ifm_pad1: c_uchar, pub ifm_pad2: c_uchar, pub ifm_addrs: c_int, pub ifm_flags: c_int, pub ifm_xflags: c_int, pub ifm_data: if_data, } pub struct sockaddr_dl { pub sdl_len: c_uchar, pub sdl_family: c_uchar, pub sdl_index: c_ushort, pub sdl_type: c_uchar, pub sdl_nlen: c_uchar, pub sdl_alen: c_uchar, pub sdl_slen: c_uchar, pub sdl_data: [c_char; 24], } pub struct sockpeercred { pub uid: crate::uid_t, pub gid: crate::gid_t, pub pid: crate::pid_t, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: c_int, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: c_short, pub shm_atime: crate::time_t, __shm_atimensec: c_long, pub shm_dtime: crate::time_t, __shm_dtimensec: c_long, pub shm_ctime: crate::time_t, __shm_ctimensec: c_long, pub shm_internal: *mut c_void, } // elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } // link.h pub struct dl_phdr_info { pub dlpi_addr: Elf_Addr, pub dlpi_name: *const c_char, pub dlpi_phdr: *const Elf_Phdr, pub dlpi_phnum: Elf_Half, } // sys/sysctl.h pub struct kinfo_proc { pub p_forw: u64, pub p_back: u64, pub p_paddr: u64, pub p_addr: u64, pub p_fd: u64, pub p_stats: u64, pub p_limit: u64, pub p_vmspace: u64, pub p_sigacts: u64, pub p_sess: u64, pub p_tsess: u64, pub p_ru: u64, pub p_eflag: i32, pub p_exitsig: i32, pub p_flag: i32, pub p_pid: i32, pub p_ppid: i32, pub p_sid: i32, pub p__pgid: i32, pub p_tpgid: i32, pub p_uid: u32, pub p_ruid: u32, pub p_gid: u32, pub p_rgid: u32, pub p_groups: [u32; KI_NGROUPS as usize], pub p_ngroups: i16, pub p_jobc: i16, pub p_tdev: u32, pub p_estcpu: u32, pub p_rtime_sec: u32, pub p_rtime_usec: u32, pub p_cpticks: i32, pub p_pctcpu: u32, pub p_swtime: u32, pub p_slptime: u32, pub p_schedflags: i32, pub p_uticks: u64, pub p_sticks: u64, pub p_iticks: u64, pub p_tracep: u64, pub p_traceflag: i32, pub p_holdcnt: i32, pub p_siglist: i32, pub p_sigmask: u32, pub p_sigignore: u32, pub p_sigcatch: u32, pub p_stat: i8, pub p_priority: u8, pub p_usrpri: u8, pub p_nice: u8, pub p_xstat: u16, pub p_spare: u16, pub p_comm: [c_char; KI_MAXCOMLEN as usize], pub p_wmesg: [c_char; KI_WMESGLEN as usize], pub p_wchan: u64, pub p_login: [c_char; KI_MAXLOGNAME as usize], pub p_vm_rssize: i32, pub p_vm_tsize: i32, pub p_vm_dsize: i32, pub p_vm_ssize: i32, pub p_uvalid: i64, pub p_ustart_sec: u64, pub p_ustart_usec: u32, pub p_uutime_sec: u32, pub p_uutime_usec: u32, pub p_ustime_sec: u32, pub p_ustime_usec: u32, pub p_uru_maxrss: u64, pub p_uru_ixrss: u64, pub p_uru_idrss: u64, pub p_uru_isrss: u64, pub p_uru_minflt: u64, pub p_uru_majflt: u64, pub p_uru_nswap: u64, pub p_uru_inblock: u64, pub p_uru_oublock: u64, pub p_uru_msgsnd: u64, pub p_uru_msgrcv: u64, pub p_uru_nsignals: u64, pub p_uru_nvcsw: u64, pub p_uru_nivcsw: u64, pub p_uctime_sec: u32, pub p_uctime_usec: u32, pub p_psflags: u32, pub p_acflag: u32, pub p_svuid: u32, pub p_svgid: u32, pub p_emul: [c_char; KI_EMULNAMELEN as usize], pub p_rlim_rss_cur: u64, pub p_cpuid: u64, pub p_vm_map_size: u64, pub p_tid: i32, pub p_rtableid: u32, pub p_pledge: u64, pub p_name: [c_char; KI_MAXCOMLEN as usize], } pub struct kinfo_vmentry { pub kve_start: c_ulong, pub kve_end: c_ulong, pub kve_guard: c_ulong, pub kve_fspace: c_ulong, pub kve_fspace_augment: c_ulong, pub kve_offset: u64, pub kve_wired_count: c_int, pub kve_etype: c_int, pub kve_protection: c_int, pub kve_max_protection: c_int, pub kve_advice: c_int, pub kve_inheritance: c_int, pub kve_flags: u8, } pub struct ptrace_state { pub pe_report_event: c_int, pub pe_other_pid: crate::pid_t, pub pe_tid: crate::pid_t, } pub struct ptrace_thread_state { pub pts_tid: crate::pid_t, } // search.h pub struct entry { pub key: *mut c_char, pub data: *mut c_void, } pub struct ifreq { pub ifr_name: [c_char; crate::IFNAMSIZ], pub ifr_ifru: __c_anonymous_ifr_ifru, } pub struct tcp_info { pub tcpi_state: u8, pub __tcpi_ca_state: u8, pub __tcpi_retransmits: u8, pub __tcpi_probes: u8, pub __tcpi_backoff: u8, pub tcpi_options: u8, pub tcpi_snd_wscale: u8, pub tcpi_rcv_wscale: u8, pub tcpi_rto: u32, pub __tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub __tcpi_unacked: u32, pub __tcpi_sacked: u32, pub __tcpi_lost: u32, pub __tcpi_retrans: u32, pub __tcpi_fackets: u32, pub tcpi_last_data_sent: u32, pub tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub tcpi_last_ack_recv: u32, pub __tcpi_pmtu: u32, pub __tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub __tcpi_advmss: u32, pub __tcpi_reordering: u32, pub __tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_snd_wnd: u32, pub tcpi_snd_nxt: u32, pub tcpi_rcv_nxt: u32, pub tcpi_toe_tid: u32, pub tcpi_snd_rexmitpack: u32, pub tcpi_rcv_ooopack: u32, pub tcpi_snd_zerowin: u32, pub tcpi_rttmin: u32, pub tcpi_max_sndwnd: u32, pub tcpi_rcv_adv: u32, pub tcpi_rcv_up: u32, pub tcpi_snd_una: u32, pub tcpi_snd_up: u32, pub tcpi_snd_wl1: u32, pub tcpi_snd_wl2: u32, pub tcpi_snd_max: u32, pub tcpi_ts_recent: u32, pub tcpi_ts_recent_age: u32, pub tcpi_rfbuf_cnt: u32, pub tcpi_rfbuf_ts: u32, pub tcpi_so_rcv_sb_cc: u32, pub tcpi_so_rcv_sb_hiwat: u32, pub tcpi_so_rcv_sb_lowat: u32, pub tcpi_so_rcv_sb_wat: u32, pub tcpi_so_snd_sb_cc: u32, pub tcpi_so_snd_sb_hiwat: u32, pub tcpi_so_snd_sb_lowat: u32, pub tcpi_so_snd_sb_wat: u32, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_char { self.si_addr } pub unsafe fn si_code(&self) -> c_int { self.si_code } pub unsafe fn si_errno(&self) -> c_int { self.si_errno } pub unsafe fn si_pid(&self) -> crate::pid_t { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_code: c_int, _si_errno: c_int, _pad: [c_int; SI_PAD], _pid: crate::pid_t, } (*(self as *const siginfo_t as *const siginfo_timer))._pid } pub unsafe fn si_uid(&self) -> crate::uid_t { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_code: c_int, _si_errno: c_int, _pad: [c_int; SI_PAD], _pid: crate::pid_t, _uid: crate::uid_t, } (*(self as *const siginfo_t as *const siginfo_timer))._uid } pub unsafe fn si_value(&self) -> crate::sigval { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_code: c_int, _si_errno: c_int, _pad: [c_int; SI_PAD], _pid: crate::pid_t, _uid: crate::uid_t, value: crate::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).value } } s_no_extra_traits! { pub struct dirent { pub d_fileno: crate::ino_t, pub d_off: off_t, pub d_reclen: u16, pub d_type: u8, pub d_namlen: u8, __d_padding: [u8; 4], pub d_name: [c_char; 256], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: crate::sa_family_t, __ss_pad1: [u8; 6], __ss_pad2: i64, __ss_pad3: [u8; 240], } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, pub si_addr: *mut c_char, #[cfg(target_pointer_width = "32")] __pad: [u8; 112], #[cfg(target_pointer_width = "64")] __pad: [u8; 108], } pub struct lastlog { ll_time: crate::time_t, ll_line: [c_char; UT_LINESIZE], ll_host: [c_char; UT_HOSTSIZE], } pub struct utmp { pub ut_line: [c_char; UT_LINESIZE], pub ut_name: [c_char; UT_NAMESIZE], pub ut_host: [c_char; UT_HOSTSIZE], pub ut_time: crate::time_t, } pub union mount_info { pub ufs_args: ufs_args, pub mfs_args: mfs_args, pub nfs_args: nfs_args, pub iso_args: iso_args, pub msdosfs_args: msdosfs_args, pub ntfs_args: ntfs_args, pub tmpfs_args: tmpfs_args, align: [c_char; 160], } pub union __c_anonymous_ifr_ifru { pub ifru_addr: crate::sockaddr, pub ifru_dstaddr: crate::sockaddr, pub ifru_broadaddr: crate::sockaddr, pub ifru_flags: c_short, pub ifru_metric: c_int, pub ifru_vnetid: i64, pub ifru_media: u64, pub ifru_data: crate::caddr_t, pub ifru_index: c_uint, } // This type uses the union mount_info: pub struct statfs { pub f_flags: u32, pub f_bsize: u32, pub f_iosize: u32, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: u64, pub f_favail: i64, pub f_syncwrites: u64, pub f_syncreads: u64, pub f_asyncwrites: u64, pub f_asyncreads: u64, pub f_fsid: crate::fsid_t, pub f_namemax: u32, pub f_owner: crate::uid_t, pub f_ctime: u64, pub f_fstypename: [c_char; 16], pub f_mntonname: [c_char; 90], pub f_mntfromname: [c_char; 90], pub f_mntfromspec: [c_char; 90], pub mount_info: mount_info, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); } } impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { self.si_signo == other.si_signo && self.si_code == other.si_code && self.si_errno == other.si_errno && self.si_addr == other.si_addr } } impl Eq for siginfo_t {} impl fmt::Debug for siginfo_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("siginfo_t") .field("si_signo", &self.si_signo) .field("si_code", &self.si_code) .field("si_errno", &self.si_errno) .field("si_addr", &self.si_addr) .finish() } } impl hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_code.hash(state); self.si_errno.hash(state); self.si_addr.hash(state); } } impl PartialEq for lastlog { fn eq(&self, other: &lastlog) -> bool { self.ll_time == other.ll_time && self .ll_line .iter() .zip(other.ll_line.iter()) .all(|(a, b)| a == b) && self .ll_host .iter() .zip(other.ll_host.iter()) .all(|(a, b)| a == b) } } impl Eq for lastlog {} impl fmt::Debug for lastlog { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("lastlog") .field("ll_time", &self.ll_time) // FIXME(debug): .field("ll_line", &self.ll_line) // FIXME(debug): .field("ll_host", &self.ll_host) .finish() } } impl hash::Hash for lastlog { fn hash(&self, state: &mut H) { self.ll_time.hash(state); self.ll_line.hash(state); self.ll_host.hash(state); } } impl PartialEq for utmp { fn eq(&self, other: &utmp) -> bool { self.ut_time == other.ut_time && self .ut_line .iter() .zip(other.ut_line.iter()) .all(|(a, b)| a == b) && self .ut_name .iter() .zip(other.ut_name.iter()) .all(|(a, b)| a == b) && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) } } impl Eq for utmp {} impl fmt::Debug for utmp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmp") // FIXME(debug): .field("ut_line", &self.ut_line) // FIXME(debug): .field("ut_name", &self.ut_name) // FIXME(debug): .field("ut_host", &self.ut_host) .field("ut_time", &self.ut_time) .finish() } } impl hash::Hash for utmp { fn hash(&self, state: &mut H) { self.ut_line.hash(state); self.ut_name.hash(state); self.ut_host.hash(state); self.ut_time.hash(state); } } impl PartialEq for mount_info { fn eq(&self, other: &mount_info) -> bool { unsafe { self.align .iter() .zip(other.align.iter()) .all(|(a, b)| a == b) } } } impl Eq for mount_info {} impl hash::Hash for mount_info { fn hash(&self, state: &mut H) { unsafe { self.align.hash(state) }; } } impl PartialEq for __c_anonymous_ifr_ifru { fn eq(&self, other: &__c_anonymous_ifr_ifru) -> bool { unsafe { self.ifru_addr == other.ifru_addr && self.ifru_dstaddr == other.ifru_dstaddr && self.ifru_broadaddr == other.ifru_broadaddr && self.ifru_flags == other.ifru_flags && self.ifru_metric == other.ifru_metric && self.ifru_vnetid == other.ifru_vnetid && self.ifru_media == other.ifru_media && self.ifru_data == other.ifru_data && self.ifru_index == other.ifru_index } } } impl Eq for __c_anonymous_ifr_ifru {} impl hash::Hash for __c_anonymous_ifr_ifru { fn hash(&self, state: &mut H) { unsafe { self.ifru_addr.hash(state); self.ifru_dstaddr.hash(state); self.ifru_broadaddr.hash(state); self.ifru_flags.hash(state); self.ifru_metric.hash(state); self.ifru_vnetid.hash(state); self.ifru_media.hash(state); self.ifru_data.hash(state); self.ifru_index.hash(state); } } } impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_favail == other.f_favail && self.f_syncwrites == other.f_syncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncwrites == other.f_asyncwrites && self.f_asyncreads == other.f_asyncreads && self.f_fsid == other.f_fsid && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_ctime == other.f_ctime && self .f_fstypename .iter() .zip(other.f_fstypename.iter()) .all(|(a, b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) && self .f_mntfromspec .iter() .zip(other.f_mntfromspec.iter()) .all(|(a, b)| a == b) && self.mount_info == other.mount_info } } impl Eq for statfs {} impl fmt::Debug for statfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statfs") .field("f_flags", &self.f_flags) .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_favail", &self.f_favail) .field("f_syncwrites", &self.f_syncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_asyncreads", &self.f_asyncreads) .field("f_fsid", &self.f_fsid) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_ctime", &self.f_ctime) // FIXME(debug): .field("f_fstypename", &self.f_fstypename) // FIXME(debug): .field("f_mntonname", &self.f_mntonname) // FIXME(debug): .field("f_mntfromname", &self.f_mntfromname) // FIXME(debug): .field("f_mntfromspec", &self.f_mntfromspec) .field("mount_info", &self.mount_info) .finish() } } impl hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_favail.hash(state); self.f_syncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncwrites.hash(state); self.f_asyncreads.hash(state); self.f_fsid.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_ctime.hash(state); self.f_fstypename.hash(state); self.f_mntonname.hash(state); self.f_mntfromname.hash(state); self.f_mntfromspec.hash(state); self.mount_info.hash(state); } } } } pub const UT_NAMESIZE: usize = 32; pub const UT_LINESIZE: usize = 8; pub const UT_HOSTSIZE: usize = 256; pub const O_CLOEXEC: c_int = 0x10000; pub const O_DIRECTORY: c_int = 0x20000; pub const O_RSYNC: c_int = O_SYNC; pub const MS_SYNC: c_int = 0x0002; pub const MS_INVALIDATE: c_int = 0x0004; pub const POLLNORM: c_short = crate::POLLRDNORM; pub const ENOATTR: c_int = 83; pub const EILSEQ: c_int = 84; pub const EOVERFLOW: c_int = 87; pub const ECANCELED: c_int = 88; pub const EIDRM: c_int = 89; pub const ENOMSG: c_int = 90; pub const ENOTSUP: c_int = 91; pub const EBADMSG: c_int = 92; pub const ENOTRECOVERABLE: c_int = 93; pub const EOWNERDEAD: c_int = 94; pub const EPROTO: c_int = 95; pub const ELAST: c_int = 95; pub const F_DUPFD_CLOEXEC: c_int = 10; pub const UTIME_OMIT: c_long = -1; pub const UTIME_NOW: c_long = -2; pub const AT_FDCWD: c_int = -100; pub const AT_EACCESS: c_int = 0x01; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x02; pub const AT_SYMLINK_FOLLOW: c_int = 0x04; pub const AT_REMOVEDIR: c_int = 0x08; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 9; pub const SO_TIMESTAMP: c_int = 0x0800; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_BINDANY: c_int = 0x1000; pub const SO_NETPROC: c_int = 0x1020; pub const SO_RTABLE: c_int = 0x1021; pub const SO_PEERCRED: c_int = 0x1022; pub const SO_SPLICE: c_int = 0x1023; pub const SO_DOMAIN: c_int = 0x1024; pub const SO_PROTOCOL: c_int = 0x1025; // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// Hop-by-hop option header pub const IPPROTO_HOPOPTS: c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: c_int = 2; /// gateway^2 (deprecated) pub const IPPROTO_GGP: c_int = 3; /// for compatibility pub const IPPROTO_IPIP: c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// exterior gateway protocol pub const IPPROTO_EGP: c_int = 8; /// pup pub const IPPROTO_PUP: c_int = 12; // IPPROTO_UDP defined in src/unix/mod.rs /// xns idp pub const IPPROTO_IDP: c_int = 22; /// tp-4 w/ class negotiation pub const IPPROTO_TP: c_int = 29; // IPPROTO_IPV6 defined in src/unix/mod.rs /// IP6 routing header pub const IPPROTO_ROUTING: c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: c_int = 44; /// resource reservation pub const IPPROTO_RSVP: c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: c_int = 47; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: c_int = 51; /// IP Mobility RFC 2004 pub const IPPROTO_MOBILE: c_int = 55; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: c_int = 60; /// ISO cnlp pub const IPPROTO_EON: c_int = 80; /// Ethernet-in-IP pub const IPPROTO_ETHERIP: c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: c_int = 98; /// Protocol indep. multicast pub const IPPROTO_PIM: c_int = 103; /// IP Payload Comp. Protocol pub const IPPROTO_IPCOMP: c_int = 108; /// CARP pub const IPPROTO_CARP: c_int = 112; /// unicast MPLS packet pub const IPPROTO_MPLS: c_int = 137; /// PFSYNC pub const IPPROTO_PFSYNC: c_int = 240; pub const IPPROTO_MAX: c_int = 256; // Only used internally, so it can be outside the range of valid IP protocols pub const IPPROTO_DIVERT: c_int = 258; pub const IP_RECVDSTADDR: c_int = 7; pub const IP_SENDSRCADDR: c_int = IP_RECVDSTADDR; pub const IP_RECVIF: c_int = 30; // sys/netinet/in.h pub const TCP_MD5SIG: c_int = 0x04; pub const TCP_NOPUSH: c_int = 0x10; pub const MSG_WAITFORONE: c_int = 0x1000; pub const AF_ECMA: c_int = 8; pub const AF_ROUTE: c_int = 17; pub const AF_ENCAP: c_int = 28; pub const AF_SIP: c_int = 29; pub const AF_KEY: c_int = 30; pub const pseudo_AF_HDRCMPLT: c_int = 31; pub const AF_BLUETOOTH: c_int = 32; pub const AF_MPLS: c_int = 33; pub const pseudo_AF_PFLOW: c_int = 34; pub const pseudo_AF_PIPEX: c_int = 35; pub const NET_RT_DUMP: c_int = 1; pub const NET_RT_FLAGS: c_int = 2; pub const NET_RT_IFLIST: c_int = 3; pub const NET_RT_STATS: c_int = 4; pub const NET_RT_TABLE: c_int = 5; pub const NET_RT_IFNAMES: c_int = 6; #[doc(hidden)] #[deprecated( since = "0.2.95", note = "Possibly increasing over the releases and might not be so used in the field" )] pub const NET_RT_MAXID: c_int = 7; pub const IPV6_JOIN_GROUP: c_int = 12; pub const IPV6_LEAVE_GROUP: c_int = 13; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_ECMA: c_int = AF_ECMA; pub const PF_ENCAP: c_int = AF_ENCAP; pub const PF_SIP: c_int = AF_SIP; pub const PF_KEY: c_int = AF_KEY; pub const PF_BPF: c_int = pseudo_AF_HDRCMPLT; pub const PF_BLUETOOTH: c_int = AF_BLUETOOTH; pub const PF_MPLS: c_int = AF_MPLS; pub const PF_PFLOW: c_int = pseudo_AF_PFLOW; pub const PF_PIPEX: c_int = pseudo_AF_PIPEX; pub const SCM_TIMESTAMP: c_int = 0x04; pub const O_DSYNC: c_int = 128; pub const MAP_RENAME: c_int = 0x0000; pub const MAP_NORESERVE: c_int = 0x0000; pub const MAP_HASSEMAPHORE: c_int = 0x0000; pub const MAP_TRYFIXED: c_int = 0; pub const EIPSEC: c_int = 82; pub const ENOMEDIUM: c_int = 85; pub const EMEDIUMTYPE: c_int = 86; pub const EAI_BADFLAGS: c_int = -1; pub const EAI_NONAME: c_int = -2; pub const EAI_AGAIN: c_int = -3; pub const EAI_FAIL: c_int = -4; pub const EAI_NODATA: c_int = -5; pub const EAI_FAMILY: c_int = -6; pub const EAI_SOCKTYPE: c_int = -7; pub const EAI_SERVICE: c_int = -8; pub const EAI_MEMORY: c_int = -10; pub const EAI_SYSTEM: c_int = -11; pub const EAI_OVERFLOW: c_int = -14; pub const RUSAGE_THREAD: c_int = 1; pub const MAP_COPY: c_int = 0x0002; pub const MAP_NOEXTEND: c_int = 0x0000; pub const _PC_LINK_MAX: c_int = 1; pub const _PC_MAX_CANON: c_int = 2; pub const _PC_MAX_INPUT: c_int = 3; pub const _PC_NAME_MAX: c_int = 4; pub const _PC_PATH_MAX: c_int = 5; pub const _PC_PIPE_BUF: c_int = 6; pub const _PC_CHOWN_RESTRICTED: c_int = 7; pub const _PC_NO_TRUNC: c_int = 8; pub const _PC_VDISABLE: c_int = 9; pub const _PC_2_SYMLINKS: c_int = 10; pub const _PC_ALLOC_SIZE_MIN: c_int = 11; pub const _PC_ASYNC_IO: c_int = 12; pub const _PC_FILESIZEBITS: c_int = 13; pub const _PC_PRIO_IO: c_int = 14; pub const _PC_REC_INCR_XFER_SIZE: c_int = 15; pub const _PC_REC_MAX_XFER_SIZE: c_int = 16; pub const _PC_REC_MIN_XFER_SIZE: c_int = 17; pub const _PC_REC_XFER_ALIGN: c_int = 18; pub const _PC_SYMLINK_MAX: c_int = 19; pub const _PC_SYNC_IO: c_int = 20; pub const _PC_TIMESTAMP_RESOLUTION: c_int = 21; pub const _SC_CLK_TCK: c_int = 3; pub const _SC_SEM_NSEMS_MAX: c_int = 31; pub const _SC_SEM_VALUE_MAX: c_int = 32; pub const _SC_HOST_NAME_MAX: c_int = 33; pub const _SC_MONOTONIC_CLOCK: c_int = 34; pub const _SC_2_PBS: c_int = 35; pub const _SC_2_PBS_ACCOUNTING: c_int = 36; pub const _SC_2_PBS_CHECKPOINT: c_int = 37; pub const _SC_2_PBS_LOCATE: c_int = 38; pub const _SC_2_PBS_MESSAGE: c_int = 39; pub const _SC_2_PBS_TRACK: c_int = 40; pub const _SC_ADVISORY_INFO: c_int = 41; pub const _SC_AIO_LISTIO_MAX: c_int = 42; pub const _SC_AIO_MAX: c_int = 43; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44; pub const _SC_ASYNCHRONOUS_IO: c_int = 45; pub const _SC_ATEXIT_MAX: c_int = 46; pub const _SC_BARRIERS: c_int = 47; pub const _SC_CLOCK_SELECTION: c_int = 48; pub const _SC_CPUTIME: c_int = 49; pub const _SC_DELAYTIMER_MAX: c_int = 50; pub const _SC_IOV_MAX: c_int = 51; pub const _SC_IPV6: c_int = 52; pub const _SC_MAPPED_FILES: c_int = 53; pub const _SC_MEMLOCK: c_int = 54; pub const _SC_MEMLOCK_RANGE: c_int = 55; pub const _SC_MEMORY_PROTECTION: c_int = 56; pub const _SC_MESSAGE_PASSING: c_int = 57; pub const _SC_MQ_OPEN_MAX: c_int = 58; pub const _SC_MQ_PRIO_MAX: c_int = 59; pub const _SC_PRIORITIZED_IO: c_int = 60; pub const _SC_PRIORITY_SCHEDULING: c_int = 61; pub const _SC_RAW_SOCKETS: c_int = 62; pub const _SC_READER_WRITER_LOCKS: c_int = 63; pub const _SC_REALTIME_SIGNALS: c_int = 64; pub const _SC_REGEXP: c_int = 65; pub const _SC_RTSIG_MAX: c_int = 66; pub const _SC_SEMAPHORES: c_int = 67; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 68; pub const _SC_SHELL: c_int = 69; pub const _SC_SIGQUEUE_MAX: c_int = 70; pub const _SC_SPAWN: c_int = 71; pub const _SC_SPIN_LOCKS: c_int = 72; pub const _SC_SPORADIC_SERVER: c_int = 73; pub const _SC_SS_REPL_MAX: c_int = 74; pub const _SC_SYNCHRONIZED_IO: c_int = 75; pub const _SC_SYMLOOP_MAX: c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; pub const _SC_THREAD_CPUTIME: c_int = 79; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 80; pub const _SC_THREAD_KEYS_MAX: c_int = 81; pub const _SC_THREAD_PRIO_INHERIT: c_int = 82; pub const _SC_THREAD_PRIO_PROTECT: c_int = 83; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 84; pub const _SC_THREAD_PROCESS_SHARED: c_int = 85; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 86; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 87; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 88; pub const _SC_THREAD_STACK_MIN: c_int = 89; pub const _SC_THREAD_THREADS_MAX: c_int = 90; pub const _SC_THREADS: c_int = 91; pub const _SC_TIMEOUTS: c_int = 92; pub const _SC_TIMER_MAX: c_int = 93; pub const _SC_TIMERS: c_int = 94; pub const _SC_TRACE: c_int = 95; pub const _SC_TRACE_EVENT_FILTER: c_int = 96; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 97; pub const _SC_TRACE_INHERIT: c_int = 98; pub const _SC_TRACE_LOG: c_int = 99; pub const _SC_GETGR_R_SIZE_MAX: c_int = 100; pub const _SC_GETPW_R_SIZE_MAX: c_int = 101; pub const _SC_LOGIN_NAME_MAX: c_int = 102; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 103; pub const _SC_TRACE_NAME_MAX: c_int = 104; pub const _SC_TRACE_SYS_MAX: c_int = 105; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 106; pub const _SC_TTY_NAME_MAX: c_int = 107; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 108; pub const _SC_V6_ILP32_OFF32: c_int = 109; pub const _SC_V6_ILP32_OFFBIG: c_int = 110; pub const _SC_V6_LP64_OFF64: c_int = 111; pub const _SC_V6_LPBIG_OFFBIG: c_int = 112; pub const _SC_V7_ILP32_OFF32: c_int = 113; pub const _SC_V7_ILP32_OFFBIG: c_int = 114; pub const _SC_V7_LP64_OFF64: c_int = 115; pub const _SC_V7_LPBIG_OFFBIG: c_int = 116; pub const _SC_XOPEN_CRYPT: c_int = 117; pub const _SC_XOPEN_ENH_I18N: c_int = 118; pub const _SC_XOPEN_LEGACY: c_int = 119; pub const _SC_XOPEN_REALTIME: c_int = 120; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 121; pub const _SC_XOPEN_STREAMS: c_int = 122; pub const _SC_XOPEN_UNIX: c_int = 123; pub const _SC_XOPEN_UUCP: c_int = 124; pub const _SC_XOPEN_VERSION: c_int = 125; pub const _SC_PHYS_PAGES: c_int = 500; pub const _SC_AVPHYS_PAGES: c_int = 501; pub const _SC_NPROCESSORS_CONF: c_int = 502; pub const _SC_NPROCESSORS_ONLN: c_int = 503; pub const FD_SETSIZE: usize = 1024; pub const SCHED_FIFO: c_int = 1; pub const SCHED_OTHER: c_int = 2; pub const SCHED_RR: c_int = 3; pub const ST_NOSUID: c_ulong = 2; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = 0 as *mut _; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = 0 as *mut _; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = 0 as *mut _; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 2; pub const PTHREAD_MUTEX_NORMAL: c_int = 3; pub const PTHREAD_MUTEX_STRICT_NP: c_int = 4; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_STRICT_NP; pub const EVFILT_READ: i16 = -1; pub const EVFILT_WRITE: i16 = -2; pub const EVFILT_AIO: i16 = -3; pub const EVFILT_VNODE: i16 = -4; pub const EVFILT_PROC: i16 = -5; pub const EVFILT_SIGNAL: i16 = -6; pub const EVFILT_TIMER: i16 = -7; pub const EVFILT_DEVICE: i16 = -8; pub const EVFILT_EXCEPT: i16 = -9; pub const EV_ADD: u16 = 0x1; pub const EV_DELETE: u16 = 0x2; pub const EV_ENABLE: u16 = 0x4; pub const EV_DISABLE: u16 = 0x8; pub const EV_ONESHOT: u16 = 0x10; pub const EV_CLEAR: u16 = 0x20; pub const EV_RECEIPT: u16 = 0x40; pub const EV_DISPATCH: u16 = 0x80; pub const EV_FLAG1: u16 = 0x2000; pub const EV_ERROR: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; #[deprecated(since = "0.2.113", note = "Not stable across OS versions")] pub const EV_SYSFLAGS: u16 = 0xf800; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_EOF: u32 = 0x00000002; pub const NOTE_OOB: u32 = 0x00000004; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_TRUNCATE: u32 = 0x00000080; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xf0000000; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const NOTE_CHANGE: u32 = 0x00000001; pub const TMP_MAX: c_uint = 0x7fffffff; pub const AI_PASSIVE: c_int = 1; pub const AI_CANONNAME: c_int = 2; pub const AI_NUMERICHOST: c_int = 4; pub const AI_EXT: c_int = 8; pub const AI_NUMERICSERV: c_int = 16; pub const AI_FQDN: c_int = 32; pub const AI_ADDRCONFIG: c_int = 64; pub const NI_NUMERICHOST: c_int = 1; pub const NI_NUMERICSERV: c_int = 2; pub const NI_NOFQDN: c_int = 4; pub const NI_NAMEREQD: c_int = 8; pub const NI_DGRAM: c_int = 16; pub const NI_MAXHOST: size_t = 256; pub const RTLD_LOCAL: c_int = 0; pub const CTL_MAXNAME: c_int = 12; pub const CTLTYPE_NODE: c_int = 1; pub const CTLTYPE_INT: c_int = 2; pub const CTLTYPE_STRING: c_int = 3; pub const CTLTYPE_QUAD: c_int = 4; pub const CTLTYPE_STRUCT: c_int = 5; pub const CTL_UNSPEC: c_int = 0; pub const CTL_KERN: c_int = 1; pub const CTL_VM: c_int = 2; pub const CTL_FS: c_int = 3; pub const CTL_NET: c_int = 4; pub const CTL_DEBUG: c_int = 5; pub const CTL_HW: c_int = 6; pub const CTL_MACHDEP: c_int = 7; pub const CTL_DDB: c_int = 9; pub const CTL_VFS: c_int = 10; pub const CTL_MAXID: c_int = 11; pub const HW_NCPUONLINE: c_int = 25; pub const KERN_OSTYPE: c_int = 1; pub const KERN_OSRELEASE: c_int = 2; pub const KERN_OSREV: c_int = 3; pub const KERN_VERSION: c_int = 4; pub const KERN_MAXVNODES: c_int = 5; pub const KERN_MAXPROC: c_int = 6; pub const KERN_MAXFILES: c_int = 7; pub const KERN_ARGMAX: c_int = 8; pub const KERN_SECURELVL: c_int = 9; pub const KERN_HOSTNAME: c_int = 10; pub const KERN_HOSTID: c_int = 11; pub const KERN_CLOCKRATE: c_int = 12; pub const KERN_PROF: c_int = 16; pub const KERN_POSIX1: c_int = 17; pub const KERN_NGROUPS: c_int = 18; pub const KERN_JOB_CONTROL: c_int = 19; pub const KERN_SAVED_IDS: c_int = 20; pub const KERN_BOOTTIME: c_int = 21; pub const KERN_DOMAINNAME: c_int = 22; pub const KERN_MAXPARTITIONS: c_int = 23; pub const KERN_RAWPARTITION: c_int = 24; pub const KERN_MAXTHREAD: c_int = 25; pub const KERN_NTHREADS: c_int = 26; pub const KERN_OSVERSION: c_int = 27; pub const KERN_SOMAXCONN: c_int = 28; pub const KERN_SOMINCONN: c_int = 29; #[deprecated(since = "0.2.71", note = "Removed in OpenBSD 6.0")] pub const KERN_USERMOUNT: c_int = 30; pub const KERN_NOSUIDCOREDUMP: c_int = 32; pub const KERN_FSYNC: c_int = 33; pub const KERN_SYSVMSG: c_int = 34; pub const KERN_SYSVSEM: c_int = 35; pub const KERN_SYSVSHM: c_int = 36; #[deprecated(since = "0.2.71", note = "Removed in OpenBSD 6.0")] pub const KERN_ARND: c_int = 37; pub const KERN_MSGBUFSIZE: c_int = 38; pub const KERN_MALLOCSTATS: c_int = 39; pub const KERN_CPTIME: c_int = 40; pub const KERN_NCHSTATS: c_int = 41; pub const KERN_FORKSTAT: c_int = 42; pub const KERN_NSELCOLL: c_int = 43; pub const KERN_TTY: c_int = 44; pub const KERN_CCPU: c_int = 45; pub const KERN_FSCALE: c_int = 46; pub const KERN_NPROCS: c_int = 47; pub const KERN_MSGBUF: c_int = 48; pub const KERN_POOL: c_int = 49; pub const KERN_STACKGAPRANDOM: c_int = 50; pub const KERN_SYSVIPC_INFO: c_int = 51; pub const KERN_SPLASSERT: c_int = 54; pub const KERN_PROC_ARGS: c_int = 55; pub const KERN_NFILES: c_int = 56; pub const KERN_TTYCOUNT: c_int = 57; pub const KERN_NUMVNODES: c_int = 58; pub const KERN_MBSTAT: c_int = 59; pub const KERN_SEMINFO: c_int = 61; pub const KERN_SHMINFO: c_int = 62; pub const KERN_INTRCNT: c_int = 63; pub const KERN_WATCHDOG: c_int = 64; pub const KERN_PROC: c_int = 66; pub const KERN_MAXCLUSTERS: c_int = 67; pub const KERN_EVCOUNT: c_int = 68; pub const KERN_TIMECOUNTER: c_int = 69; pub const KERN_MAXLOCKSPERUID: c_int = 70; pub const KERN_CPTIME2: c_int = 71; pub const KERN_CACHEPCT: c_int = 72; pub const KERN_FILE: c_int = 73; pub const KERN_CONSDEV: c_int = 75; pub const KERN_NETLIVELOCKS: c_int = 76; pub const KERN_POOL_DEBUG: c_int = 77; pub const KERN_PROC_CWD: c_int = 78; pub const KERN_PROC_NOBROADCASTKILL: c_int = 79; pub const KERN_PROC_VMMAP: c_int = 80; pub const KERN_GLOBAL_PTRACE: c_int = 81; pub const KERN_CONSBUFSIZE: c_int = 82; pub const KERN_CONSBUF: c_int = 83; pub const KERN_AUDIO: c_int = 84; pub const KERN_CPUSTATS: c_int = 85; pub const KERN_PFSTATUS: c_int = 86; pub const KERN_TIMEOUT_STATS: c_int = 87; #[deprecated( since = "0.2.95", note = "Possibly increasing over the releases and might not be so used in the field" )] pub const KERN_MAXID: c_int = 88; pub const KERN_PROC_ALL: c_int = 0; pub const KERN_PROC_PID: c_int = 1; pub const KERN_PROC_PGRP: c_int = 2; pub const KERN_PROC_SESSION: c_int = 3; pub const KERN_PROC_TTY: c_int = 4; pub const KERN_PROC_UID: c_int = 5; pub const KERN_PROC_RUID: c_int = 6; pub const KERN_PROC_KTHREAD: c_int = 7; pub const KERN_PROC_SHOW_THREADS: c_int = 0x40000000; pub const KERN_SYSVIPC_MSG_INFO: c_int = 1; pub const KERN_SYSVIPC_SEM_INFO: c_int = 2; pub const KERN_SYSVIPC_SHM_INFO: c_int = 3; pub const KERN_PROC_ARGV: c_int = 1; pub const KERN_PROC_NARGV: c_int = 2; pub const KERN_PROC_ENV: c_int = 3; pub const KERN_PROC_NENV: c_int = 4; pub const KI_NGROUPS: c_int = 16; pub const KI_MAXCOMLEN: c_int = 24; pub const KI_WMESGLEN: c_int = 8; pub const KI_MAXLOGNAME: c_int = 32; pub const KI_EMULNAMELEN: c_int = 8; pub const KVE_ET_OBJ: c_int = 0x00000001; pub const KVE_ET_SUBMAP: c_int = 0x00000002; pub const KVE_ET_COPYONWRITE: c_int = 0x00000004; pub const KVE_ET_NEEDSCOPY: c_int = 0x00000008; pub const KVE_ET_HOLE: c_int = 0x00000010; pub const KVE_ET_NOFAULT: c_int = 0x00000020; pub const KVE_ET_STACK: c_int = 0x00000040; pub const KVE_ET_WC: c_int = 0x000000080; pub const KVE_ET_CONCEAL: c_int = 0x000000100; pub const KVE_ET_SYSCALL: c_int = 0x000000200; pub const KVE_ET_FREEMAPPED: c_int = 0x000000800; pub const KVE_PROT_NONE: c_int = 0x00000000; pub const KVE_PROT_READ: c_int = 0x00000001; pub const KVE_PROT_WRITE: c_int = 0x00000002; pub const KVE_PROT_EXEC: c_int = 0x00000004; pub const KVE_ADV_NORMAL: c_int = 0x00000000; pub const KVE_ADV_RANDOM: c_int = 0x00000001; pub const KVE_ADV_SEQUENTIAL: c_int = 0x00000002; pub const KVE_INH_SHARE: c_int = 0x00000000; pub const KVE_INH_COPY: c_int = 0x00000010; pub const KVE_INH_NONE: c_int = 0x00000020; pub const KVE_INH_ZERO: c_int = 0x00000030; pub const KVE_F_STATIC: c_int = 0x1; pub const KVE_F_KMEM: c_int = 0x2; pub const CHWFLOW: crate::tcflag_t = crate::MDMBUF | crate::CRTSCTS; pub const OLCUC: crate::tcflag_t = 0x20; pub const ONOCR: crate::tcflag_t = 0x40; pub const ONLRET: crate::tcflag_t = 0x80; //https://github.com/openbsd/src/blob/HEAD/sys/sys/mount.h pub const ISOFSMNT_NORRIP: c_int = 0x1; // disable Rock Ridge Ext pub const ISOFSMNT_GENS: c_int = 0x2; // enable generation numbers pub const ISOFSMNT_EXTATT: c_int = 0x4; // enable extended attr pub const ISOFSMNT_NOJOLIET: c_int = 0x8; // disable Joliet Ext pub const ISOFSMNT_SESS: c_int = 0x10; // use iso_args.sess pub const NFS_ARGSVERSION: c_int = 4; // change when nfs_args changes pub const NFSMNT_RESVPORT: c_int = 0; // always use reserved ports pub const NFSMNT_SOFT: c_int = 0x1; // soft mount (hard is default) pub const NFSMNT_WSIZE: c_int = 0x2; // set write size pub const NFSMNT_RSIZE: c_int = 0x4; // set read size pub const NFSMNT_TIMEO: c_int = 0x8; // set initial timeout pub const NFSMNT_RETRANS: c_int = 0x10; // set number of request retries pub const NFSMNT_MAXGRPS: c_int = 0x20; // set maximum grouplist size pub const NFSMNT_INT: c_int = 0x40; // allow interrupts on hard mount pub const NFSMNT_NOCONN: c_int = 0x80; // Don't Connect the socket pub const NFSMNT_NQNFS: c_int = 0x100; // Use Nqnfs protocol pub const NFSMNT_NFSV3: c_int = 0x200; // Use NFS Version 3 protocol pub const NFSMNT_KERB: c_int = 0x400; // Use Kerberos authentication pub const NFSMNT_DUMBTIMR: c_int = 0x800; // Don't estimate rtt dynamically pub const NFSMNT_LEASETERM: c_int = 0x1000; // set lease term (nqnfs) pub const NFSMNT_READAHEAD: c_int = 0x2000; // set read ahead pub const NFSMNT_DEADTHRESH: c_int = 0x4000; // set dead server retry thresh pub const NFSMNT_NOAC: c_int = 0x8000; // disable attribute cache pub const NFSMNT_RDIRPLUS: c_int = 0x10000; // Use Readdirplus for V3 pub const NFSMNT_READDIRSIZE: c_int = 0x20000; // Set readdir size /* Flags valid only in mount syscall arguments */ pub const NFSMNT_ACREGMIN: c_int = 0x40000; // acregmin field valid pub const NFSMNT_ACREGMAX: c_int = 0x80000; // acregmax field valid pub const NFSMNT_ACDIRMIN: c_int = 0x100000; // acdirmin field valid pub const NFSMNT_ACDIRMAX: c_int = 0x200000; // acdirmax field valid /* Flags valid only in kernel */ pub const NFSMNT_INTERNAL: c_int = 0xfffc0000; // Bits set internally pub const NFSMNT_HASWRITEVERF: c_int = 0x40000; // Has write verifier for V3 pub const NFSMNT_GOTPATHCONF: c_int = 0x80000; // Got the V3 pathconf info pub const NFSMNT_GOTFSINFO: c_int = 0x100000; // Got the V3 fsinfo pub const NFSMNT_MNTD: c_int = 0x200000; // Mnt server for mnt point pub const NFSMNT_DISMINPROG: c_int = 0x400000; // Dismount in progress pub const NFSMNT_DISMNT: c_int = 0x800000; // Dismounted pub const NFSMNT_SNDLOCK: c_int = 0x1000000; // Send socket lock pub const NFSMNT_WANTSND: c_int = 0x2000000; // Want above pub const NFSMNT_RCVLOCK: c_int = 0x4000000; // Rcv socket lock pub const NFSMNT_WANTRCV: c_int = 0x8000000; // Want above pub const NFSMNT_WAITAUTH: c_int = 0x10000000; // Wait for authentication pub const NFSMNT_HASAUTH: c_int = 0x20000000; // Has authenticator pub const NFSMNT_WANTAUTH: c_int = 0x40000000; // Wants an authenticator pub const NFSMNT_AUTHERR: c_int = 0x80000000; // Authentication error pub const MSDOSFSMNT_SHORTNAME: c_int = 0x1; // Force old DOS short names only pub const MSDOSFSMNT_LONGNAME: c_int = 0x2; // Force Win'95 long names pub const MSDOSFSMNT_NOWIN95: c_int = 0x4; // Completely ignore Win95 entries pub const NTFS_MFLAG_CASEINS: c_int = 0x1; pub const NTFS_MFLAG_ALLNAMES: c_int = 0x2; pub const TMPFS_ARGS_VERSION: c_int = 1; const SI_MAXSZ: size_t = 128; const SI_PAD: size_t = (SI_MAXSZ / mem::size_of::()) - 3; pub const MAP_STACK: c_int = 0x4000; pub const MAP_CONCEAL: c_int = 0x8000; // https://github.com/openbsd/src/blob/HEAD/sys/net/if.h#L187 pub const IFF_UP: c_int = 0x1; // interface is up pub const IFF_BROADCAST: c_int = 0x2; // broadcast address valid pub const IFF_DEBUG: c_int = 0x4; // turn on debugging pub const IFF_LOOPBACK: c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: c_int = 0x10; // interface is point-to-point link pub const IFF_STATICARP: c_int = 0x20; // only static ARP pub const IFF_RUNNING: c_int = 0x40; // resources allocated pub const IFF_NOARP: c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: c_int = 0x100; // receive all packets pub const IFF_ALLMULTI: c_int = 0x200; // receive all multicast packets pub const IFF_OACTIVE: c_int = 0x400; // transmission in progress pub const IFF_SIMPLEX: c_int = 0x800; // can't hear own transmissions pub const IFF_LINK0: c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: c_int = 0x4000; // per link layer defined bit pub const IFF_MULTICAST: c_int = 0x8000; // supports multicast pub const PTHREAD_STACK_MIN: size_t = 1_usize << _MAX_PAGE_SHIFT; pub const MINSIGSTKSZ: size_t = 3_usize << _MAX_PAGE_SHIFT; pub const SIGSTKSZ: size_t = MINSIGSTKSZ + (1_usize << _MAX_PAGE_SHIFT) * 4; pub const PT_SET_EVENT_MASK: c_int = 12; pub const PT_GET_EVENT_MASK: c_int = 13; pub const PT_GET_PROCESS_STATE: c_int = 14; pub const PT_GET_THREAD_FIRST: c_int = 15; pub const PT_GET_THREAD_NEXT: c_int = 16; pub const PT_FIRSTMACH: c_int = 32; pub const SOCK_CLOEXEC: c_int = 0x8000; pub const SOCK_NONBLOCK: c_int = 0x4000; pub const SOCK_DNS: c_int = 0x1000; pub const BIOCGRSIG: c_ulong = 0x40044273; pub const BIOCSRSIG: c_ulong = 0x80044272; pub const BIOCSDLT: c_ulong = 0x8004427a; pub const PTRACE_FORK: c_int = 0x0002; pub const WCONTINUED: c_int = 0x08; pub const WEXITED: c_int = 0x04; pub const WSTOPPED: c_int = 0x02; // same as WUNTRACED pub const WNOWAIT: c_int = 0x10; pub const WTRAPPED: c_int = 0x20; pub const P_ALL: crate::idtype_t = 0; pub const P_PGID: crate::idtype_t = 1; pub const P_PID: crate::idtype_t = 2; // search.h pub const FIND: crate::ACTION = 0; pub const ENTER: crate::ACTION = 1; // futex.h pub const FUTEX_WAIT: c_int = 1; pub const FUTEX_WAKE: c_int = 2; pub const FUTEX_REQUEUE: c_int = 3; pub const FUTEX_PRIVATE_FLAG: c_int = 128; // sysctl.h, kinfo_proc p_eflag constants pub const EPROC_CTTY: i32 = 0x01; // controlling tty vnode active pub const EPROC_SLEADER: i32 = 0x02; // session leader pub const EPROC_UNVEIL: i32 = 0x04; // has unveil settings pub const EPROC_LKUNVEIL: i32 = 0x08; // unveil is locked // Flags for chflags(2) pub const UF_SETTABLE: c_uint = 0x0000ffff; pub const UF_NODUMP: c_uint = 0x00000001; pub const UF_IMMUTABLE: c_uint = 0x00000002; pub const UF_APPEND: c_uint = 0x00000004; pub const UF_OPAQUE: c_uint = 0x00000008; pub const SF_SETTABLE: c_uint = 0xffff0000; pub const SF_ARCHIVED: c_uint = 0x00010000; pub const SF_IMMUTABLE: c_uint = 0x00020000; pub const SF_APPEND: c_uint = 0x00040000; // sys/exec_elf.h - Legal values for p_type (segment type). pub const PT_NULL: u32 = 0; pub const PT_LOAD: u32 = 1; pub const PT_DYNAMIC: u32 = 2; pub const PT_INTERP: u32 = 3; pub const PT_NOTE: u32 = 4; pub const PT_SHLIB: u32 = 5; pub const PT_PHDR: u32 = 6; pub const PT_TLS: u32 = 7; pub const PT_LOOS: u32 = 0x60000000; pub const PT_HIOS: u32 = 0x6fffffff; pub const PT_LOPROC: u32 = 0x70000000; pub const PT_HIPROC: u32 = 0x7fffffff; pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; pub const PT_GNU_RELRO: u32 = 0x6474e552; // sys/exec_elf.h - Legal values for p_flags (segment flags). pub const PF_X: u32 = 0x1; pub const PF_W: u32 = 0x2; pub const PF_R: u32 = 0x4; pub const PF_MASKOS: u32 = 0x0ff00000; pub const PF_MASKPROC: u32 = 0xf0000000; // sys/mount.h pub const MNT_NOPERM: c_int = 0x00000020; pub const MNT_WXALLOWED: c_int = 0x00000800; pub const MNT_EXRDONLY: c_int = 0x00000080; pub const MNT_DEFEXPORTED: c_int = 0x00000200; pub const MNT_EXPORTANON: c_int = 0x00000400; pub const MNT_ROOTFS: c_int = 0x00004000; pub const MNT_NOATIME: c_int = 0x00008000; pub const MNT_DELEXPORT: c_int = 0x00020000; pub const MNT_STALLED: c_int = 0x00100000; pub const MNT_SWAPPABLE: c_int = 0x00200000; pub const MNT_WANTRDWR: c_int = 0x02000000; pub const MNT_SOFTDEP: c_int = 0x04000000; pub const MNT_DOOMED: c_int = 0x08000000; // For use with vfs_fsync and getfsstat pub const MNT_WAIT: c_int = 1; pub const MNT_NOWAIT: c_int = 2; pub const MNT_LAZY: c_int = 3; // sys/_time.h pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 4; pub const CLOCK_UPTIME: crate::clockid_t = 5; pub const CLOCK_BOOTTIME: crate::clockid_t = 6; pub const LC_COLLATE_MASK: c_int = 1 << crate::LC_COLLATE; pub const LC_CTYPE_MASK: c_int = 1 << crate::LC_CTYPE; pub const LC_MONETARY_MASK: c_int = 1 << crate::LC_MONETARY; pub const LC_NUMERIC_MASK: c_int = 1 << crate::LC_NUMERIC; pub const LC_TIME_MASK: c_int = 1 << crate::LC_TIME; pub const LC_MESSAGES_MASK: c_int = 1 << crate::LC_MESSAGES; const _LC_LAST: c_int = 7; pub const LC_ALL_MASK: c_int = (1 << _LC_LAST) - 2; pub const LC_GLOBAL_LOCALE: crate::locale_t = -1isize as crate::locale_t; // sys/reboot.h pub const RB_ASKNAME: c_int = 0x00001; pub const RB_SINGLE: c_int = 0x00002; pub const RB_NOSYNC: c_int = 0x00004; pub const RB_HALT: c_int = 0x00008; pub const RB_INITNAME: c_int = 0x00010; pub const RB_KDB: c_int = 0x00040; pub const RB_RDONLY: c_int = 0x00080; pub const RB_DUMP: c_int = 0x00100; pub const RB_MINIROOT: c_int = 0x00200; pub const RB_CONFIG: c_int = 0x00400; pub const RB_TIMEBAD: c_int = 0x00800; pub const RB_POWERDOWN: c_int = 0x01000; pub const RB_SERCONS: c_int = 0x02000; pub const RB_USERREQ: c_int = 0x04000; pub const RB_RESET: c_int = 0x08000; pub const RB_GOODRANDOM: c_int = 0x10000; pub const RB_UNHIBERNATE: c_int = 0x20000; // net/route.h pub const RTF_CLONING: c_int = 0x100; pub const RTF_MULTICAST: c_int = 0x200; pub const RTF_LLINFO: c_int = 0x400; pub const RTF_PROTO3: c_int = 0x2000; pub const RTF_ANNOUNCE: c_int = crate::RTF_PROTO2; pub const RTF_CLONED: c_int = 0x10000; pub const RTF_CACHED: c_int = 0x20000; pub const RTF_MPATH: c_int = 0x40000; pub const RTF_MPLS: c_int = 0x100000; pub const RTF_LOCAL: c_int = 0x200000; pub const RTF_BROADCAST: c_int = 0x400000; pub const RTF_CONNECTED: c_int = 0x800000; pub const RTF_BFD: c_int = 0x1000000; pub const RTF_FMASK: c_int = crate::RTF_LLINFO | crate::RTF_PROTO1 | crate::RTF_PROTO2 | crate::RTF_PROTO3 | crate::RTF_BLACKHOLE | crate::RTF_REJECT | crate::RTF_STATIC | crate::RTF_MPLS | crate::RTF_BFD; pub const RTM_VERSION: c_int = 5; pub const RTM_RESOLVE: c_int = 0xb; pub const RTM_NEWADDR: c_int = 0xc; pub const RTM_DELADDR: c_int = 0xd; pub const RTM_IFINFO: c_int = 0xe; pub const RTM_IFANNOUNCE: c_int = 0xf; pub const RTM_DESYNC: c_int = 0x10; pub const RTM_INVALIDATE: c_int = 0x11; pub const RTM_BFD: c_int = 0x12; pub const RTM_PROPOSAL: c_int = 0x13; pub const RTM_CHGADDRATTR: c_int = 0x14; pub const RTM_80211INFO: c_int = 0x15; pub const RTM_SOURCE: c_int = 0x16; pub const RTA_SRC: c_int = 0x100; pub const RTA_SRCMASK: c_int = 0x200; pub const RTA_LABEL: c_int = 0x400; pub const RTA_BFD: c_int = 0x800; pub const RTA_DNS: c_int = 0x1000; pub const RTA_STATIC: c_int = 0x2000; pub const RTA_SEARCH: c_int = 0x4000; pub const RTAX_SRC: c_int = 8; pub const RTAX_SRCMASK: c_int = 9; pub const RTAX_LABEL: c_int = 10; pub const RTAX_BFD: c_int = 11; pub const RTAX_DNS: c_int = 12; pub const RTAX_STATIC: c_int = 13; pub const RTAX_SEARCH: c_int = 14; pub const RTAX_MAX: c_int = 15; const_fn! { {const} fn _ALIGN(p: usize) -> usize { (p + _ALIGNBYTES) & !_ALIGNBYTES } } f! { pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(_ALIGN(mem::size_of::()) as isize) } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { _ALIGN(mem::size_of::()) as c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const crate::msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { return crate::CMSG_FIRSTHDR(mhdr); }; let next = cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize) + _ALIGN(mem::size_of::()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut cmsghdr } else { (cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr } } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (_ALIGN(mem::size_of::()) + _ALIGN(length as usize)) as c_uint } } safe_f! { pub {const} fn WSTOPSIG(status: c_int) -> c_int { status >> 8 } pub {const} fn WIFSIGNALED(status: c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 } pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0xff) == 0o177 } pub {const} fn WIFCONTINUED(status: c_int) -> bool { (status & 0o177777) == 0o177777 } pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= (major & 0xff) << 8; dev |= minor & 0xff; dev |= (minor & 0xffff00) << 8; dev } pub {const} fn major(dev: crate::dev_t) -> c_uint { ((dev as c_uint) >> 8) & 0xff } pub {const} fn minor(dev: crate::dev_t) -> c_uint { let dev = dev as c_uint; let mut res = 0; res |= (dev) & 0xff; res |= ((dev) & 0xffff0000) >> 8; res } } extern "C" { pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut crate::timezone) -> c_int; pub fn settimeofday(tp: *const crate::timeval, tz: *const crate::timezone) -> c_int; pub fn pledge(promises: *const c_char, execpromises: *const c_char) -> c_int; pub fn unveil(path: *const c_char, permissions: *const c_char) -> c_int; pub fn strtonum( nptr: *const c_char, minval: c_longlong, maxval: c_longlong, errstr: *mut *const c_char, ) -> c_longlong; pub fn dup3(src: c_int, dst: c_int, flags: c_int) -> c_int; pub fn chflags(path: *const c_char, flags: c_uint) -> c_int; pub fn fchflags(fd: c_int, flags: c_uint) -> c_int; pub fn chflagsat(fd: c_int, path: *const c_char, flags: c_uint, atflag: c_int) -> c_int; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: size_t, serv: *mut c_char, servlen: size_t, flags: c_int, ) -> c_int; pub fn getresgid( rgid: *mut crate::gid_t, egid: *mut crate::gid_t, sgid: *mut crate::gid_t, ) -> c_int; pub fn getresuid( ruid: *mut crate::uid_t, euid: *mut crate::uid_t, suid: *mut crate::uid_t, ) -> c_int; pub fn kevent( kq: c_int, changelist: *const crate::kevent, nchanges: c_int, eventlist: *mut crate::kevent, nevents: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn getthrid() -> crate::pid_t; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_main_np() -> c_int; pub fn pthread_get_name_np(tid: crate::pthread_t, name: *mut c_char, len: size_t); pub fn pthread_set_name_np(tid: crate::pthread_t, name: *const c_char); pub fn pthread_stackseg_np(thread: crate::pthread_t, sinfo: *mut crate::stack_t) -> c_int; pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *const crate::termios, winp: *const crate::winsize, ) -> c_int; pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *const crate::termios, winp: *const crate::winsize, ) -> crate::pid_t; pub fn sysctl( name: *const c_int, namelen: c_uint, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; pub fn setresgid(rgid: crate::gid_t, egid: crate::gid_t, sgid: crate::gid_t) -> c_int; pub fn setresuid(ruid: crate::uid_t, euid: crate::uid_t, suid: crate::uid_t) -> c_int; pub fn ptrace(request: c_int, pid: crate::pid_t, addr: caddr_t, data: c_int) -> c_int; pub fn utrace(label: *const c_char, addr: *const c_void, len: size_t) -> c_int; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; // #include pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn(info: *mut dl_phdr_info, size: usize, data: *mut c_void) -> c_int, >, data: *mut c_void, ) -> c_int; pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn freelocale(loc: crate::locale_t); pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; // Added in `OpenBSD` 5.5 pub fn explicit_bzero(s: *mut c_void, len: size_t); pub fn setproctitle(fmt: *const c_char, ...); pub fn freezero(ptr: *mut c_void, size: size_t); pub fn malloc_conceal(size: size_t) -> *mut c_void; pub fn calloc_conceal(nmemb: size_t, size: size_t) -> *mut c_void; pub fn srand48_deterministic(seed: c_long); pub fn seed48_deterministic(xseed: *mut c_ushort) -> *mut c_ushort; pub fn lcong48_deterministic(p: *mut c_ushort); pub fn lsearch( key: *const c_void, base: *mut c_void, nelp: *mut size_t, width: size_t, compar: Option c_int>, ) -> *mut c_void; pub fn lfind( key: *const c_void, base: *const c_void, nelp: *mut size_t, width: size_t, compar: Option c_int>, ) -> *mut c_void; pub fn hcreate(nelt: size_t) -> c_int; pub fn hdestroy(); pub fn hsearch(entry: crate::ENTRY, action: crate::ACTION) -> *mut crate::ENTRY; // futex.h pub fn futex( uaddr: *mut u32, op: c_int, val: c_int, timeout: *const crate::timespec, uaddr2: *mut u32, ) -> c_int; pub fn mimmutable(addr: *mut c_void, len: size_t) -> c_int; pub fn reboot(mode: c_int) -> c_int; pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn getmntinfo(mntbufp: *mut *mut crate::statfs, flags: c_int) -> c_int; pub fn getfsstat(buf: *mut statfs, bufsize: size_t, flags: c_int) -> c_int; } #[link(name = "execinfo")] extern "C" { pub fn backtrace(addrlist: *mut *mut c_void, len: size_t) -> size_t; pub fn backtrace_symbols(addrlist: *const *mut c_void, len: size_t) -> *mut *mut c_char; pub fn backtrace_symbols_fd(addrlist: *const *mut c_void, len: size_t, fd: c_int) -> c_int; pub fn backtrace_symbols_fmt( addrlist: *const *mut c_void, len: size_t, fmt: *const c_char, ) -> *mut *mut c_char; } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "mips64")] { mod mips64; pub use self::mips64::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "powerpc64")] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else if #[cfg(target_arch = "sparc64")] { mod sparc64; pub use self::sparc64::*; } else if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/netbsdlike/openbsd/arm.rs0000644000175000017500000000020415105742312020534 0ustar bdrungbdrunguse crate::prelude::*; pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/riscv64.rs0000644000175000017500000000111215105742312021254 0ustar bdrungbdrunguse crate::prelude::*; pub type ucontext_t = sigcontext; s! { pub struct sigcontext { __sc_unused: c_int, pub sc_mask: c_int, pub sc_ra: c_long, pub sc_sp: c_long, pub sc_gp: c_long, pub sc_tp: c_long, pub sc_t: [c_long; 7], pub sc_s: [c_long; 12], pub sc_a: [c_long; 8], pub sc_sepc: c_long, pub sc_f: [c_long; 32], pub sc_fcsr: c_long, pub sc_cookie: c_long, } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/powerpc.rs0000644000175000017500000000020415105742312021434 0ustar bdrungbdrunguse crate::prelude::*; pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/x86.rs0000644000175000017500000000020115105742312020377 0ustar bdrungbdrunguse crate::prelude::*; pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/powerpc64.rs0000644000175000017500000000020215105742312021604 0ustar bdrungbdrunguse crate::prelude::*; pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/x86_64.rs0000644000175000017500000001032615105742312020721 0ustar bdrungbdrunguse crate::prelude::*; use crate::PT_FIRSTMACH; pub type ucontext_t = sigcontext; s! { pub struct sigcontext { pub sc_rdi: c_long, pub sc_rsi: c_long, pub sc_rdx: c_long, pub sc_rcx: c_long, pub sc_r8: c_long, pub sc_r9: c_long, pub sc_r10: c_long, pub sc_r11: c_long, pub sc_r12: c_long, pub sc_r13: c_long, pub sc_r14: c_long, pub sc_r15: c_long, pub sc_rbp: c_long, pub sc_rbx: c_long, pub sc_rax: c_long, pub sc_gs: c_long, pub sc_fs: c_long, pub sc_es: c_long, pub sc_ds: c_long, pub sc_trapno: c_long, pub sc_err: c_long, pub sc_rip: c_long, pub sc_cs: c_long, pub sc_rflags: c_long, pub sc_rsp: c_long, pub sc_ss: c_long, pub sc_fpstate: *mut fxsave64, __sc_unused: c_int, pub sc_mask: c_int, pub sc_cookie: c_long, } } s_no_extra_traits! { #[repr(packed)] pub struct fxsave64 { pub fx_fcw: u16, pub fx_fsw: u16, pub fx_ftw: u8, __fx_unused1: u8, pub fx_fop: u16, pub fx_rip: u64, pub fx_rdp: u64, pub fx_mxcsr: u32, pub fx_mxcsr_mask: u32, pub fx_st: [[u64; 2]; 8], pub fx_xmm: [[u64; 2]; 16], __fx_unused3: [u8; 96], } } cfg_if! { if #[cfg(feature = "extra_traits")] { // `fxsave64` is packed, so field access is unaligned. // use {x} to create temporary storage, copy field to it, and do aligned access. impl PartialEq for fxsave64 { fn eq(&self, other: &fxsave64) -> bool { return { self.fx_fcw } == { other.fx_fcw } && { self.fx_fsw } == { other.fx_fsw } && { self.fx_ftw } == { other.fx_ftw } && { self.fx_fop } == { other.fx_fop } && { self.fx_rip } == { other.fx_rip } && { self.fx_rdp } == { other.fx_rdp } && { self.fx_mxcsr } == { other.fx_mxcsr } && { self.fx_mxcsr_mask } == { other.fx_mxcsr_mask } && { self.fx_st } .iter() .zip({ other.fx_st }.iter()) .all(|(a, b)| a == b) && { self.fx_xmm } .iter() .zip({ other.fx_xmm }.iter()) .all(|(a, b)| a == b); } } impl Eq for fxsave64 {} impl fmt::Debug for fxsave64 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fxsave64") .field("fx_fcw", &{ self.fx_fcw }) .field("fx_fsw", &{ self.fx_fsw }) .field("fx_ftw", &{ self.fx_ftw }) .field("fx_fop", &{ self.fx_fop }) .field("fx_rip", &{ self.fx_rip }) .field("fx_rdp", &{ self.fx_rdp }) .field("fx_mxcsr", &{ self.fx_mxcsr }) .field("fx_mxcsr_mask", &{ self.fx_mxcsr_mask }) // FIXME(debug): .field("fx_st", &{self.fx_st}) // FIXME(debug): .field("fx_xmm", &{self.fx_xmm}) .finish() } } impl hash::Hash for fxsave64 { fn hash(&self, state: &mut H) { { self.fx_fcw }.hash(state); { self.fx_fsw }.hash(state); { self.fx_ftw }.hash(state); { self.fx_fop }.hash(state); { self.fx_rip }.hash(state); { self.fx_rdp }.hash(state); { self.fx_mxcsr }.hash(state); { self.fx_mxcsr_mask }.hash(state); { self.fx_st }.hash(state); { self.fx_xmm }.hash(state); } } } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const _MAX_PAGE_SHIFT: u32 = 12; pub const PT_STEP: c_int = PT_FIRSTMACH + 0; pub const PT_GETREGS: c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: c_int = PT_FIRSTMACH + 2; pub const PT_GETFPREGS: c_int = PT_FIRSTMACH + 3; pub const PT_SETFPREGS: c_int = PT_FIRSTMACH + 4; libc/src/unix/bsd/netbsdlike/openbsd/sparc64.rs0000644000175000017500000000013115105742312021236 0ustar bdrungbdrung#[doc(hidden)] pub const _ALIGNBYTES: usize = 0xf; pub const _MAX_PAGE_SHIFT: u32 = 13; libc/src/unix/bsd/netbsdlike/openbsd/mips64.rs0000644000175000017500000000012715105742312021103 0ustar bdrungbdrung#[doc(hidden)] pub const _ALIGNBYTES: usize = 7; pub const _MAX_PAGE_SHIFT: u32 = 14; libc/src/unix/bsd/netbsdlike/openbsd/aarch64.rs0000644000175000017500000000067215105742312021216 0ustar bdrungbdrunguse crate::prelude::*; pub type ucontext_t = sigcontext; s! { pub struct sigcontext { __sc_unused: c_int, pub sc_mask: c_int, pub sc_sp: c_ulong, pub sc_lr: c_ulong, pub sc_elr: c_ulong, pub sc_spsr: c_ulong, pub sc_x: [c_ulong; 30], pub sc_cookie: c_long, } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/netbsd/0000775000175000017500000000000015105742312017242 5ustar bdrungbdrunglibc/src/unix/bsd/netbsdlike/netbsd/mod.rs0000644000175000017500000030747015105742312020400 0ustar bdrungbdrunguse crate::prelude::*; use crate::{cmsghdr, off_t}; pub type clock_t = c_uint; pub type suseconds_t = c_int; pub type dev_t = u64; pub type blksize_t = i32; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type idtype_t = c_int; pub type mqd_t = c_int; type __pthread_spin_t = __cpu_simple_lock_nv_t; pub type vm_size_t = crate::uintptr_t; // FIXME(deprecated): deprecated since long time pub type lwpid_t = c_uint; pub type shmatt_t = c_uint; pub type cpuid_t = c_ulong; pub type cpuset_t = _cpuset; pub type pthread_spin_t = c_uchar; pub type timer_t = c_int; // elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Lword = u64; pub type Elf32_Off = u32; pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Lword = u64; pub type Elf64_Off = u64; pub type Elf64_Sword = i32; pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; pub type iconv_t = *mut c_void; e! { pub enum fae_action { FAE_OPEN, FAE_DUP2, FAE_CLOSE, } } cfg_if! { if #[cfg(target_pointer_width = "64")] { type Elf_Addr = Elf64_Addr; type Elf_Half = Elf64_Half; type Elf_Phdr = Elf64_Phdr; } else if #[cfg(target_pointer_width = "32")] { type Elf_Addr = Elf32_Addr; type Elf_Half = Elf32_Half; type Elf_Phdr = Elf32_Phdr; } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { self.si_addr } pub unsafe fn si_code(&self) -> c_int { self.si_code } pub unsafe fn si_errno(&self) -> c_int { self.si_errno } pub unsafe fn si_pid(&self) -> crate::pid_t { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, __pad1: c_int, _pid: crate::pid_t, } (*(self as *const siginfo_t as *const siginfo_timer))._pid } pub unsafe fn si_uid(&self) -> crate::uid_t { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, __pad1: c_int, _pid: crate::pid_t, _uid: crate::uid_t, } (*(self as *const siginfo_t as *const siginfo_timer))._uid } pub unsafe fn si_value(&self) -> crate::sigval { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, __pad1: c_int, _pid: crate::pid_t, _uid: crate::uid_t, value: crate::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).value } pub unsafe fn si_status(&self) -> c_int { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, __pad1: c_int, _pid: crate::pid_t, _uid: crate::uid_t, _value: crate::sigval, _cpid: crate::pid_t, _cuid: crate::uid_t, status: c_int, } (*(self as *const siginfo_t as *const siginfo_timer)).status } } s! { pub struct aiocb { pub aio_offset: off_t, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_fildes: c_int, pub aio_lio_opcode: c_int, pub aio_reqprio: c_int, pub aio_sigevent: crate::sigevent, _state: c_int, _errno: c_int, _retval: ssize_t, } pub struct glob_t { pub gl_pathc: size_t, pub gl_matchc: size_t, pub gl_offs: size_t, pub gl_flags: c_int, pub gl_pathv: *mut *mut c_char, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, __unused6: *mut c_void, __unused7: *mut c_void, __unused8: *mut c_void, } pub struct mq_attr { pub mq_flags: c_long, pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_curmsgs: c_long, } pub struct itimerspec { pub it_interval: crate::timespec, pub it_value: crate::timespec, } pub struct sigset_t { __bits: [u32; 4], } pub struct stat { pub st_dev: crate::dev_t, pub st_mode: crate::mode_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_atime: crate::time_t, pub st_atimensec: c_long, pub st_mtime: crate::time_t, pub st_mtimensec: c_long, pub st_ctime: crate::time_t, pub st_ctimensec: c_long, pub st_birthtime: crate::time_t, pub st_birthtimensec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: crate::blksize_t, pub st_flags: u32, pub st_gen: u32, pub st_spare: [u32; 2], } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: crate::socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut crate::addrinfo, } pub struct siginfo_t { pub si_signo: c_int, pub si_code: c_int, pub si_errno: c_int, __pad1: c_int, pub si_addr: *mut c_void, __pad2: [u64; 13], } pub struct pthread_attr_t { pta_magic: c_uint, pta_flags: c_int, pta_private: *mut c_void, } pub struct pthread_mutex_t { ptm_magic: c_uint, ptm_errorcheck: __pthread_spin_t, #[cfg(any( target_arch = "sparc", target_arch = "sparc64", target_arch = "x86", target_arch = "x86_64" ))] ptm_pad1: [u8; 3], // actually a union with a non-unused, 0-initialized field ptm_unused: __pthread_spin_t, #[cfg(any( target_arch = "sparc", target_arch = "sparc64", target_arch = "x86", target_arch = "x86_64" ))] ptm_pad2: [u8; 3], ptm_owner: crate::pthread_t, ptm_waiters: *mut u8, ptm_recursed: c_uint, ptm_spare2: *mut c_void, } pub struct pthread_mutexattr_t { ptma_magic: c_uint, ptma_private: *mut c_void, } pub struct pthread_rwlockattr_t { ptra_magic: c_uint, ptra_private: *mut c_void, } pub struct pthread_cond_t { ptc_magic: c_uint, ptc_lock: __pthread_spin_t, ptc_waiters_first: *mut u8, ptc_waiters_last: *mut u8, ptc_mutex: *mut crate::pthread_mutex_t, ptc_private: *mut c_void, } pub struct pthread_condattr_t { ptca_magic: c_uint, ptca_private: *mut c_void, } pub struct pthread_rwlock_t { ptr_magic: c_uint, ptr_interlock: __pthread_spin_t, ptr_rblocked_first: *mut u8, ptr_rblocked_last: *mut u8, ptr_wblocked_first: *mut u8, ptr_wblocked_last: *mut u8, ptr_nreaders: c_uint, ptr_owner: crate::pthread_t, ptr_private: *mut c_void, } pub struct pthread_spinlock_t { pts_magic: c_uint, pts_spin: crate::pthread_spin_t, pts_flags: c_int, } pub struct kevent { pub ident: crate::uintptr_t, pub filter: u32, pub flags: u32, pub fflags: u32, pub data: i64, // FIXME(netbsd): NetBSD 10.0 will finally have same layout as other BSD pub udata: intptr_t, } pub struct dqblk { pub dqb_bhardlimit: u32, pub dqb_bsoftlimit: u32, pub dqb_curblocks: u32, pub dqb_ihardlimit: u32, pub dqb_isoftlimit: u32, pub dqb_curinodes: u32, pub dqb_btime: i32, pub dqb_itime: i32, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *const c_void, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_n_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct if_data { pub ifi_type: c_uchar, pub ifi_addrlen: c_uchar, pub ifi_hdrlen: c_uchar, pub ifi_link_state: c_int, pub ifi_mtu: u64, pub ifi_metric: u64, pub ifi_baudrate: u64, pub ifi_ipackets: u64, pub ifi_ierrors: u64, pub ifi_opackets: u64, pub ifi_oerrors: u64, pub ifi_collisions: u64, pub ifi_ibytes: u64, pub ifi_obytes: u64, pub ifi_imcasts: u64, pub ifi_omcasts: u64, pub ifi_iqdrops: u64, pub ifi_noproto: u64, pub ifi_lastchange: crate::timespec, } pub struct if_msghdr { pub ifm_msglen: c_ushort, pub ifm_version: c_uchar, pub ifm_type: c_uchar, pub ifm_addrs: c_int, pub ifm_flags: c_int, pub ifm_index: c_ushort, pub ifm_data: if_data, } pub struct sockcred { pub sc_pid: crate::pid_t, pub sc_uid: crate::uid_t, pub sc_euid: crate::uid_t, pub sc_gid: crate::gid_t, pub sc_egid: crate::gid_t, pub sc_ngroups: c_int, pub sc_groups: [crate::gid_t; 1], } pub struct uucred { pub cr_unused: c_ushort, pub cr_uid: crate::uid_t, pub cr_gid: crate::gid_t, pub cr_ngroups: c_int, pub cr_groups: [crate::gid_t; NGROUPS_MAX as usize], } pub struct unpcbid { pub unp_pid: crate::pid_t, pub unp_euid: crate::uid_t, pub unp_egid: crate::gid_t, } pub struct sockaddr_dl { pub sdl_len: c_uchar, pub sdl_family: c_uchar, pub sdl_index: c_ushort, pub sdl_type: u8, pub sdl_nlen: u8, pub sdl_alen: u8, pub sdl_slen: u8, pub sdl_data: [c_char; 12], } pub struct __exit_status { pub e_termination: u16, pub e_exit: u16, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, _shm_internal: *mut c_void, } pub struct utmp { pub ut_line: [c_char; UT_LINESIZE], pub ut_name: [c_char; UT_NAMESIZE], pub ut_host: [c_char; UT_HOSTSIZE], pub ut_time: crate::time_t, } pub struct lastlog { pub ll_line: [c_char; UT_LINESIZE], pub ll_host: [c_char; UT_HOSTSIZE], pub ll_time: crate::time_t, } pub struct timex { pub modes: c_uint, pub offset: c_long, pub freq: c_long, pub maxerror: c_long, pub esterror: c_long, pub status: c_int, pub constant: c_long, pub precision: c_long, pub tolerance: c_long, pub ppsfreq: c_long, pub jitter: c_long, pub shift: c_int, pub stabil: c_long, pub jitcnt: c_long, pub calcnt: c_long, pub errcnt: c_long, pub stbcnt: c_long, } pub struct ntptimeval { pub time: crate::timespec, pub maxerror: c_long, pub esterror: c_long, pub tai: c_long, pub time_state: c_int, } // elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } pub struct Aux32Info { pub a_type: Elf32_Word, pub a_v: Elf32_Word, } pub struct Aux64Info { pub a_type: Elf64_Word, pub a_v: Elf64_Xword, } // link.h pub struct dl_phdr_info { pub dlpi_addr: Elf_Addr, pub dlpi_name: *const c_char, pub dlpi_phdr: *const Elf_Phdr, pub dlpi_phnum: Elf_Half, pub dlpi_adds: c_ulonglong, pub dlpi_subs: c_ulonglong, pub dlpi_tls_modid: usize, pub dlpi_tls_data: *mut c_void, } pub struct _cpuset { bits: [u32; 0], } pub struct accept_filter_arg { pub af_name: [c_char; 16], af_arg: [c_char; 256 - 16], } pub struct ki_sigset_t { pub __bits: [u32; 4], } pub struct kinfo_proc2 { pub p_forw: u64, pub p_back: u64, pub p_paddr: u64, pub p_addr: u64, pub p_fd: u64, pub p_cwdi: u64, pub p_stats: u64, pub p_limit: u64, pub p_vmspace: u64, pub p_sigacts: u64, pub p_sess: u64, pub p_tsess: u64, pub p_ru: u64, pub p_eflag: i32, pub p_exitsig: i32, pub p_flag: i32, pub p_pid: i32, pub p_ppid: i32, pub p_sid: i32, pub p__pgid: i32, pub p_tpgid: i32, pub p_uid: u32, pub p_ruid: u32, pub p_gid: u32, pub p_rgid: u32, pub p_groups: [u32; KI_NGROUPS as usize], pub p_ngroups: i16, pub p_jobc: i16, pub p_tdev: u32, pub p_estcpu: u32, pub p_rtime_sec: u32, pub p_rtime_usec: u32, pub p_cpticks: i32, pub p_pctcpu: u32, pub p_swtime: u32, pub p_slptime: u32, pub p_schedflags: i32, pub p_uticks: u64, pub p_sticks: u64, pub p_iticks: u64, pub p_tracep: u64, pub p_traceflag: i32, pub p_holdcnt: i32, pub p_siglist: ki_sigset_t, pub p_sigmask: ki_sigset_t, pub p_sigignore: ki_sigset_t, pub p_sigcatch: ki_sigset_t, pub p_stat: i8, pub p_priority: u8, pub p_usrpri: u8, pub p_nice: u8, pub p_xstat: u16, pub p_acflag: u16, pub p_comm: [c_char; KI_MAXCOMLEN as usize], pub p_wmesg: [c_char; KI_WMESGLEN as usize], pub p_wchan: u64, pub p_login: [c_char; KI_MAXLOGNAME as usize], pub p_vm_rssize: i32, pub p_vm_tsize: i32, pub p_vm_dsize: i32, pub p_vm_ssize: i32, pub p_uvalid: i64, pub p_ustart_sec: u32, pub p_ustart_usec: u32, pub p_uutime_sec: u32, pub p_uutime_usec: u32, pub p_ustime_sec: u32, pub p_ustime_usec: u32, pub p_uru_maxrss: u64, pub p_uru_ixrss: u64, pub p_uru_idrss: u64, pub p_uru_isrss: u64, pub p_uru_minflt: u64, pub p_uru_majflt: u64, pub p_uru_nswap: u64, pub p_uru_inblock: u64, pub p_uru_oublock: u64, pub p_uru_msgsnd: u64, pub p_uru_msgrcv: u64, pub p_uru_nsignals: u64, pub p_uru_nvcsw: u64, pub p_uru_nivcsw: u64, pub p_uctime_sec: u32, pub p_uctime_usec: u32, pub p_cpuid: u64, pub p_realflag: u64, pub p_nlwps: u64, pub p_nrlwps: u64, pub p_realstat: u64, pub p_svuid: u32, pub p_svgid: u32, pub p_ename: [c_char; KI_MAXEMULLEN as usize], pub p_vm_vsize: i64, pub p_vm_msize: i64, } pub struct kinfo_lwp { pub l_forw: u64, pub l_back: u64, pub l_laddr: u64, pub l_addr: u64, pub l_lid: i32, pub l_flag: i32, pub l_swtime: u32, pub l_slptime: u32, pub l_schedflags: i32, pub l_holdcnt: i32, pub l_priority: u8, pub l_usrpri: u8, pub l_stat: i8, l_pad1: i8, l_pad2: i32, pub l_wmesg: [c_char; KI_WMESGLEN as usize], pub l_wchan: u64, pub l_cpuid: u64, pub l_rtime_sec: u32, pub l_rtime_usec: u32, pub l_cpticks: u32, pub l_pctcpu: u32, pub l_pid: u32, pub l_name: [c_char; KI_LNAMELEN as usize], } pub struct kinfo_vmentry { pub kve_start: u64, pub kve_end: u64, pub kve_offset: u64, pub kve_type: u32, pub kve_flags: u32, pub kve_count: u32, pub kve_wired_count: u32, pub kve_advice: u32, pub kve_attributes: u32, pub kve_protection: u32, pub kve_max_protection: u32, pub kve_ref_count: u32, pub kve_inheritance: u32, pub kve_vn_fileid: u64, pub kve_vn_size: u64, pub kve_vn_fsid: u64, pub kve_vn_rdev: u64, pub kve_vn_type: u32, pub kve_vn_mode: u32, pub kve_path: [[c_char; 32]; 32], } pub struct __c_anonymous_posix_spawn_fae_open { pub path: *mut c_char, pub oflag: c_int, pub mode: crate::mode_t, } pub struct __c_anonymous_posix_spawn_fae_dup2 { pub newfildes: c_int, } pub struct posix_spawnattr_t { pub sa_flags: c_short, pub sa_pgroup: crate::pid_t, pub sa_schedparam: crate::sched_param, pub sa_schedpolicy: c_int, pub sa_sigdefault: sigset_t, pub sa_sigmask: sigset_t, } pub struct posix_spawn_file_actions_entry_t { pub fae_action: fae_action, pub fae_fildes: c_int, pub fae_data: __c_anonymous_posix_spawn_fae, } pub struct posix_spawn_file_actions_t { pub size: c_uint, pub len: c_uint, pub fae: *mut posix_spawn_file_actions_entry_t, } pub struct ptrace_lwpinfo { pub pl_lwpid: lwpid_t, pub pl_event: c_int, } pub struct ptrace_lwpstatus { pub pl_lwpid: lwpid_t, pub pl_sigpend: sigset_t, pub pl_sigmask: sigset_t, pub pl_name: [c_char; 20], pub pl_private: *mut c_void, } pub struct ptrace_siginfo { pub psi_siginfo: siginfo_t, pub psi_lwpid: lwpid_t, } pub struct ptrace_event { pub pe_set_event: c_int, } pub struct sysctldesc { pub descr_num: i32, pub descr_ver: u32, pub descr_len: u32, pub descr_str: [c_char; 1], } pub struct ifreq { pub _priv: [[c_char; 6]; 24], } pub struct ifconf { pub ifc_len: c_int, pub ifc_ifcu: __c_anonymous_ifc_ifcu, } pub struct tcp_info { pub tcpi_state: u8, pub __tcpi_ca_state: u8, pub __tcpi_retransmits: u8, pub __tcpi_probes: u8, pub __tcpi_backoff: u8, pub tcpi_options: u8, pub tcp_snd_wscale: u8, pub tcp_rcv_wscale: u8, pub tcpi_rto: u32, pub __tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub __tcpi_unacked: u32, pub __tcpi_sacked: u32, pub __tcpi_lost: u32, pub __tcpi_retrans: u32, pub __tcpi_fackets: u32, pub __tcpi_last_data_sent: u32, pub __tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub __tcpi_last_ack_recv: u32, pub __tcpi_pmtu: u32, pub __tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub __tcpi_advmss: u32, pub __tcpi_reordering: u32, pub __tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_snd_wnd: u32, pub tcpi_snd_bwnd: u32, pub tcpi_snd_nxt: u32, pub tcpi_rcv_nxt: u32, pub tcpi_toe_tid: u32, pub tcpi_snd_rexmitpack: u32, pub tcpi_rcv_ooopack: u32, pub tcpi_snd_zerowin: u32, pub __tcpi_pad: [u32; 26], } } s_no_extra_traits! { pub struct utmpx { pub ut_name: [c_char; _UTX_USERSIZE], pub ut_id: [c_char; _UTX_IDSIZE], pub ut_line: [c_char; _UTX_LINESIZE], pub ut_host: [c_char; _UTX_HOSTSIZE], pub ut_session: u16, pub ut_type: u16, pub ut_pid: crate::pid_t, pub ut_exit: __exit_status, // FIXME(netbsd): when anonymous struct are supported pub ut_ss: sockaddr_storage, pub ut_tv: crate::timeval, pub ut_pad: [u8; _UTX_PADSIZE], } pub struct lastlogx { pub ll_tv: crate::timeval, pub ll_line: [c_char; _UTX_LINESIZE], pub ll_host: [c_char; _UTX_HOSTSIZE], pub ll_ss: sockaddr_storage, } pub struct in_pktinfo { pub ipi_addr: crate::in_addr, pub ipi_ifindex: c_uint, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [i8; 8], } pub struct dirent { pub d_fileno: crate::ino_t, pub d_reclen: u16, pub d_namlen: u16, pub d_type: u8, pub d_name: [c_char; 512], } pub struct statvfs { pub f_flag: c_ulong, pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_iosize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_bresvd: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fresvd: crate::fsfilcnt_t, pub f_syncreads: u64, pub f_syncwrites: u64, pub f_asyncreads: u64, pub f_asyncwrites: u64, pub f_fsidx: crate::fsid_t, pub f_fsid: c_ulong, pub f_namemax: c_ulong, pub f_owner: crate::uid_t, pub f_spare: [u32; 4], pub f_fstypename: [c_char; 32], pub f_mntonname: [c_char; 1024], pub f_mntfromname: [c_char; 1024], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: crate::sa_family_t, __ss_pad1: [u8; 6], __ss_pad2: i64, __ss_pad3: [u8; 112], } pub struct sigevent { pub sigev_notify: c_int, pub sigev_signo: c_int, pub sigev_value: crate::sigval, __unused1: *mut c_void, //actually a function pointer pub sigev_notify_attributes: *mut c_void, } pub union __c_anonymous_posix_spawn_fae { pub open: __c_anonymous_posix_spawn_fae_open, pub dup2: __c_anonymous_posix_spawn_fae_dup2, } pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: *mut c_void, pub ifcu_req: *mut ifreq, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_name == other.ut_name && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_ss == other.ut_ss && self .ut_pad .iter() .zip(other.ut_pad.iter()) .all(|(a, b)| a == b) && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_name", &self.ut_name) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) // FIXME(debug) .field("ut_host", &self.ut_host) .field("ut_session", &self.ut_session) .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_exit", &self.ut_exit) .field("ut_ss", &self.ut_ss) .field("ut_tv", &self.ut_tv) // FIXME(debug) .field("ut_pad", &self.ut_pad) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_name.hash(state); self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_ss.hash(state); self.ut_pad.hash(state); } } impl PartialEq for lastlogx { fn eq(&self, other: &lastlogx) -> bool { self.ll_tv == other.ll_tv && self.ll_line == other.ll_line && self.ll_ss == other.ll_ss && self .ll_host .iter() .zip(other.ll_host.iter()) .all(|(a, b)| a == b) } } impl Eq for lastlogx {} impl fmt::Debug for lastlogx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("lastlogx") .field("ll_tv", &self.ll_tv) .field("ll_line", &self.ll_line) // FIXME(debug).field("ll_host", &self.ll_host) .field("ll_ss", &self.ll_ss) .finish() } } impl hash::Hash for lastlogx { fn hash(&self, state: &mut H) { self.ll_tv.hash(state); self.ll_line.hash(state); self.ll_host.hash(state); self.ll_ss.hash(state); } } impl PartialEq for in_pktinfo { fn eq(&self, other: &in_pktinfo) -> bool { self.ipi_addr == other.ipi_addr && self.ipi_ifindex == other.ipi_ifindex } } impl Eq for in_pktinfo {} impl fmt::Debug for in_pktinfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("in_pktinfo") .field("ipi_addr", &self.ipi_addr) .field("ipi_ifindex", &self.ipi_ifindex) .finish() } } impl hash::Hash for in_pktinfo { fn hash(&self, state: &mut H) { self.ipi_addr.hash(state); self.ipi_ifindex.hash(state); } } impl PartialEq for arphdr { fn eq(&self, other: &arphdr) -> bool { self.ar_hrd == other.ar_hrd && self.ar_pro == other.ar_pro && self.ar_hln == other.ar_hln && self.ar_pln == other.ar_pln && self.ar_op == other.ar_op } } impl Eq for arphdr {} impl fmt::Debug for arphdr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let ar_hrd = self.ar_hrd; let ar_pro = self.ar_pro; let ar_op = self.ar_op; f.debug_struct("arphdr") .field("ar_hrd", &ar_hrd) .field("ar_pro", &ar_pro) .field("ar_hln", &self.ar_hln) .field("ar_pln", &self.ar_pln) .field("ar_op", &ar_op) .finish() } } impl hash::Hash for arphdr { fn hash(&self, state: &mut H) { let ar_hrd = self.ar_hrd; let ar_pro = self.ar_pro; let ar_op = self.ar_op; ar_hrd.hash(state); ar_pro.hash(state); self.ar_hln.hash(state); self.ar_pln.hash(state); ar_op.hash(state); } } impl PartialEq for in_addr { fn eq(&self, other: &in_addr) -> bool { self.s_addr == other.s_addr } } impl Eq for in_addr {} impl fmt::Debug for in_addr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s_addr = self.s_addr; f.debug_struct("in_addr").field("s_addr", &s_addr).finish() } } impl hash::Hash for in_addr { fn hash(&self, state: &mut H) { let s_addr = self.s_addr; s_addr.hash(state); } } impl PartialEq for ip_mreq { fn eq(&self, other: &ip_mreq) -> bool { self.imr_multiaddr == other.imr_multiaddr && self.imr_interface == other.imr_interface } } impl Eq for ip_mreq {} impl fmt::Debug for ip_mreq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ip_mreq") .field("imr_multiaddr", &self.imr_multiaddr) .field("imr_interface", &self.imr_interface) .finish() } } impl hash::Hash for ip_mreq { fn hash(&self, state: &mut H) { self.imr_multiaddr.hash(state); self.imr_interface.hash(state); } } impl PartialEq for sockaddr_in { fn eq(&self, other: &sockaddr_in) -> bool { self.sin_len == other.sin_len && self.sin_family == other.sin_family && self.sin_port == other.sin_port && self.sin_addr == other.sin_addr && self.sin_zero == other.sin_zero } } impl Eq for sockaddr_in {} impl fmt::Debug for sockaddr_in { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_in") .field("sin_len", &self.sin_len) .field("sin_family", &self.sin_family) .field("sin_port", &self.sin_port) .field("sin_addr", &self.sin_addr) .field("sin_zero", &self.sin_zero) .finish() } } impl hash::Hash for sockaddr_in { fn hash(&self, state: &mut H) { self.sin_len.hash(state); self.sin_family.hash(state); self.sin_port.hash(state); self.sin_addr.hash(state); self.sin_zero.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_reclen == other.d_reclen && self.d_namlen == other.d_namlen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_reclen", &self.d_reclen) .field("d_namlen", &self.d_namlen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_reclen.hash(state); self.d_namlen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for statvfs { fn eq(&self, other: &statvfs) -> bool { self.f_flag == other.f_flag && self.f_bsize == other.f_bsize && self.f_frsize == other.f_frsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_bresvd == other.f_bresvd && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_favail == other.f_favail && self.f_fresvd == other.f_fresvd && self.f_syncreads == other.f_syncreads && self.f_syncwrites == other.f_syncwrites && self.f_asyncreads == other.f_asyncreads && self.f_asyncwrites == other.f_asyncwrites && self.f_fsidx == other.f_fsidx && self.f_fsid == other.f_fsid && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_spare == other.f_spare && self.f_fstypename == other.f_fstypename && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) } } impl Eq for statvfs {} impl fmt::Debug for statvfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statvfs") .field("f_flag", &self.f_flag) .field("f_bsize", &self.f_bsize) .field("f_frsize", &self.f_frsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_bresvd", &self.f_bresvd) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_favail", &self.f_favail) .field("f_fresvd", &self.f_fresvd) .field("f_syncreads", &self.f_syncreads) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncreads", &self.f_asyncreads) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_fsidx", &self.f_fsidx) .field("f_fsid", &self.f_fsid) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_spare", &self.f_spare) .field("f_fstypename", &self.f_fstypename) // FIXME(debug): .field("f_mntonname", &self.f_mntonname) // FIXME(debug): .field("f_mntfromname", &self.f_mntfromname) .finish() } } impl hash::Hash for statvfs { fn hash(&self, state: &mut H) { self.f_flag.hash(state); self.f_bsize.hash(state); self.f_frsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_bresvd.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_favail.hash(state); self.f_fresvd.hash(state); self.f_syncreads.hash(state); self.f_syncwrites.hash(state); self.f_asyncreads.hash(state); self.f_asyncwrites.hash(state); self.f_fsidx.hash(state); self.f_fsid.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_spare.hash(state); self.f_fstypename.hash(state); self.f_mntonname.hash(state); self.f_mntfromname.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self.__ss_pad1 == other.__ss_pad1 && self.__ss_pad2 == other.__ss_pad2 && self .__ss_pad3 .iter() .zip(other.__ss_pad3.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_pad2", &self.__ss_pad2) // FIXME(debug): .field("__ss_pad3", &self.__ss_pad3) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_pad2.hash(state); self.__ss_pad3.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.sigev_notify_attributes.hash(state); } } impl Eq for __c_anonymous_posix_spawn_fae {} impl PartialEq for __c_anonymous_posix_spawn_fae { fn eq(&self, other: &__c_anonymous_posix_spawn_fae) -> bool { unsafe { self.open == other.open || self.dup2 == other.dup2 } } } impl hash::Hash for __c_anonymous_posix_spawn_fae { fn hash(&self, state: &mut H) { unsafe { self.open.hash(state); self.dup2.hash(state); } } } impl Eq for __c_anonymous_ifc_ifcu {} impl PartialEq for __c_anonymous_ifc_ifcu { fn eq(&self, other: &__c_anonymous_ifc_ifcu) -> bool { unsafe { self.ifcu_buf == other.ifcu_buf || self.ifcu_req == other.ifcu_req } } } impl hash::Hash for __c_anonymous_ifc_ifcu { fn hash(&self, state: &mut H) { unsafe { self.ifcu_buf.hash(state); self.ifcu_req.hash(state); } } } } } pub const AT_FDCWD: c_int = -100; pub const AT_EACCESS: c_int = 0x100; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x200; pub const AT_SYMLINK_FOLLOW: c_int = 0x400; pub const AT_REMOVEDIR: c_int = 0x800; pub const AT_NULL: c_int = 0; pub const AT_IGNORE: c_int = 1; pub const AT_EXECFD: c_int = 2; pub const AT_PHDR: c_int = 3; pub const AT_PHENT: c_int = 4; pub const AT_PHNUM: c_int = 5; pub const AT_PAGESZ: c_int = 6; pub const AT_BASE: c_int = 7; pub const AT_FLAGS: c_int = 8; pub const AT_ENTRY: c_int = 9; pub const AT_DCACHEBSIZE: c_int = 10; pub const AT_ICACHEBSIZE: c_int = 11; pub const AT_UCACHEBSIZE: c_int = 12; pub const AT_STACKBASE: c_int = 13; pub const AT_EUID: c_int = 2000; pub const AT_RUID: c_int = 2001; pub const AT_EGID: c_int = 2002; pub const AT_RGID: c_int = 2003; pub const AT_SUN_LDELF: c_int = 2004; pub const AT_SUN_LDSHDR: c_int = 2005; pub const AT_SUN_LDNAME: c_int = 2006; pub const AT_SUN_LDPGSIZE: c_int = 2007; pub const AT_SUN_PLATFORM: c_int = 2008; pub const AT_SUN_HWCAP: c_int = 2009; pub const AT_SUN_IFLUSH: c_int = 2010; pub const AT_SUN_CPU: c_int = 2011; pub const AT_SUN_EMUL_ENTRY: c_int = 2012; pub const AT_SUN_EMUL_EXECFD: c_int = 2013; pub const AT_SUN_EXECNAME: c_int = 2014; pub const EXTATTR_NAMESPACE_USER: c_int = 1; pub const EXTATTR_NAMESPACE_SYSTEM: c_int = 2; pub const LC_COLLATE_MASK: c_int = 1 << crate::LC_COLLATE; pub const LC_CTYPE_MASK: c_int = 1 << crate::LC_CTYPE; pub const LC_MONETARY_MASK: c_int = 1 << crate::LC_MONETARY; pub const LC_NUMERIC_MASK: c_int = 1 << crate::LC_NUMERIC; pub const LC_TIME_MASK: c_int = 1 << crate::LC_TIME; pub const LC_MESSAGES_MASK: c_int = 1 << crate::LC_MESSAGES; pub const LC_ALL_MASK: c_int = !0; pub const ERA: crate::nl_item = 52; pub const ERA_D_FMT: crate::nl_item = 53; pub const ERA_D_T_FMT: crate::nl_item = 54; pub const ERA_T_FMT: crate::nl_item = 55; pub const ALT_DIGITS: crate::nl_item = 56; pub const O_CLOEXEC: c_int = 0x400000; pub const O_ALT_IO: c_int = 0x40000; pub const O_NOSIGPIPE: c_int = 0x1000000; pub const O_SEARCH: c_int = 0x800000; pub const O_DIRECTORY: c_int = 0x200000; pub const O_DIRECT: c_int = 0x00080000; pub const O_RSYNC: c_int = 0x00020000; pub const MS_SYNC: c_int = 0x4; pub const MS_INVALIDATE: c_int = 0x2; // Here because they are not present on OpenBSD // (https://github.com/openbsd/src/blob/HEAD/sys/sys/resource.h) pub const RLIMIT_SBSIZE: c_int = 9; pub const RLIMIT_AS: c_int = 10; pub const RLIMIT_NTHR: c_int = 11; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 12; pub const EIDRM: c_int = 82; pub const ENOMSG: c_int = 83; pub const EOVERFLOW: c_int = 84; pub const EILSEQ: c_int = 85; pub const ENOTSUP: c_int = 86; pub const ECANCELED: c_int = 87; pub const EBADMSG: c_int = 88; pub const ENODATA: c_int = 89; pub const ENOSR: c_int = 90; pub const ENOSTR: c_int = 91; pub const ETIME: c_int = 92; pub const ENOATTR: c_int = 93; pub const EMULTIHOP: c_int = 94; pub const ENOLINK: c_int = 95; pub const EPROTO: c_int = 96; pub const EOWNERDEAD: c_int = 97; pub const ENOTRECOVERABLE: c_int = 98; #[deprecated( since = "0.2.143", note = "This value will always match the highest defined error number \ and thus is not stable. \ See #3040 for more info." )] pub const ELAST: c_int = 98; pub const F_DUPFD_CLOEXEC: c_int = 12; pub const F_CLOSEM: c_int = 10; pub const F_GETNOSIGPIPE: c_int = 13; pub const F_SETNOSIGPIPE: c_int = 14; pub const F_MAXFD: c_int = 11; pub const F_GETPATH: c_int = 15; pub const FUTEX_WAIT: c_int = 0; pub const FUTEX_WAKE: c_int = 1; pub const FUTEX_FD: c_int = 2; pub const FUTEX_REQUEUE: c_int = 3; pub const FUTEX_CMP_REQUEUE: c_int = 4; pub const FUTEX_WAKE_OP: c_int = 5; pub const FUTEX_LOCK_PI: c_int = 6; pub const FUTEX_UNLOCK_PI: c_int = 7; pub const FUTEX_TRYLOCK_PI: c_int = 8; pub const FUTEX_WAIT_BITSET: c_int = 9; pub const FUTEX_WAKE_BITSET: c_int = 10; pub const FUTEX_WAIT_REQUEUE_PI: c_int = 11; pub const FUTEX_CMP_REQUEUE_PI: c_int = 12; pub const FUTEX_PRIVATE_FLAG: c_int = 1 << 7; pub const FUTEX_CLOCK_REALTIME: c_int = 1 << 8; pub const FUTEX_CMD_MASK: c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); pub const FUTEX_WAITERS: u32 = 1 << 31; pub const FUTEX_OWNER_DIED: u32 = 1 << 30; pub const FUTEX_SYNCOBJ_1: u32 = 1 << 29; pub const FUTEX_SYNCOBJ_0: u32 = 1 << 28; pub const FUTEX_TID_MASK: u32 = (1 << 28) - 1; pub const FUTEX_BITSET_MATCH_ANY: u32 = !0; pub const IP_RECVDSTADDR: c_int = 7; pub const IP_SENDSRCADDR: c_int = IP_RECVDSTADDR; pub const IP_RECVIF: c_int = 20; pub const IP_PKTINFO: c_int = 25; pub const IP_RECVPKTINFO: c_int = 26; pub const IPV6_JOIN_GROUP: c_int = 12; pub const IPV6_LEAVE_GROUP: c_int = 13; pub const TCP_KEEPIDLE: c_int = 3; pub const TCP_KEEPINTVL: c_int = 5; pub const TCP_KEEPCNT: c_int = 6; pub const TCP_KEEPINIT: c_int = 7; pub const TCP_MD5SIG: c_int = 0x10; pub const TCP_CONGCTL: c_int = 0x20; pub const SOCK_CONN_DGRAM: c_int = 6; pub const SOCK_DCCP: c_int = SOCK_CONN_DGRAM; pub const SOCK_NOSIGPIPE: c_int = 0x40000000; pub const SOCK_FLAGS_MASK: c_int = 0xf0000000; pub const SO_SNDTIMEO: c_int = 0x100b; pub const SO_RCVTIMEO: c_int = 0x100c; pub const SO_NOSIGPIPE: c_int = 0x0800; pub const SO_ACCEPTFILTER: c_int = 0x1000; pub const SO_TIMESTAMP: c_int = 0x2000; pub const SO_OVERFLOWED: c_int = 0x1009; pub const SO_NOHEADER: c_int = 0x100a; // http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/un.h?annotate pub const LOCAL_OCREDS: c_int = 0x0001; // pass credentials to receiver pub const LOCAL_CONNWAIT: c_int = 0x0002; // connects block until accepted pub const LOCAL_PEEREID: c_int = 0x0003; // get peer identification pub const LOCAL_CREDS: c_int = 0x0004; // pass credentials to receiver // https://github.com/NetBSD/src/blob/trunk/sys/net/if.h#L373 pub const IFF_UP: c_int = 0x0001; // interface is up pub const IFF_BROADCAST: c_int = 0x0002; // broadcast address valid pub const IFF_DEBUG: c_int = 0x0004; // turn on debugging pub const IFF_LOOPBACK: c_int = 0x0008; // is a loopback net pub const IFF_POINTOPOINT: c_int = 0x0010; // interface is point-to-point link pub const IFF_NOTRAILERS: c_int = 0x0020; // avoid use of trailers pub const IFF_RUNNING: c_int = 0x0040; // resources allocated pub const IFF_NOARP: c_int = 0x0080; // no address resolution protocol pub const IFF_PROMISC: c_int = 0x0100; // receive all packets pub const IFF_ALLMULTI: c_int = 0x0200; // receive all multicast packets pub const IFF_OACTIVE: c_int = 0x0400; // transmission in progress pub const IFF_SIMPLEX: c_int = 0x0800; // can't hear own transmissions pub const IFF_LINK0: c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: c_int = 0x4000; // per link layer defined bit pub const IFF_MULTICAST: c_int = 0x8000; // supports multicast // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// Hop-by-hop option header pub const IPPROTO_HOPOPTS: c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: c_int = 2; /// gateway^2 (deprecated) pub const IPPROTO_GGP: c_int = 3; /// for compatibility pub const IPPROTO_IPIP: c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// exterior gateway protocol pub const IPPROTO_EGP: c_int = 8; /// pup pub const IPPROTO_PUP: c_int = 12; // IPPROTO_UDP defined in src/unix/mod.rs /// xns idp pub const IPPROTO_IDP: c_int = 22; /// tp-4 w/ class negotiation pub const IPPROTO_TP: c_int = 29; /// DCCP pub const IPPROTO_DCCP: c_int = 33; // IPPROTO_IPV6 defined in src/unix/mod.rs /// IP6 routing header pub const IPPROTO_ROUTING: c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: c_int = 44; /// resource reservation pub const IPPROTO_RSVP: c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: c_int = 47; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: c_int = 51; /// IP Mobility RFC 2004 pub const IPPROTO_MOBILE: c_int = 55; /// IPv6 ICMP pub const IPPROTO_IPV6_ICMP: c_int = 58; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: c_int = 60; /// ISO cnlp pub const IPPROTO_EON: c_int = 80; /// Ethernet-in-IP pub const IPPROTO_ETHERIP: c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: c_int = 98; /// Protocol indep. multicast pub const IPPROTO_PIM: c_int = 103; /// IP Payload Comp. Protocol pub const IPPROTO_IPCOMP: c_int = 108; /// VRRP RFC 2338 pub const IPPROTO_VRRP: c_int = 112; /// Common Address Resolution Protocol pub const IPPROTO_CARP: c_int = 112; /// L2TPv3 pub const IPPROTO_L2TP: c_int = 115; /// SCTP pub const IPPROTO_SCTP: c_int = 132; /// PFSYNC pub const IPPROTO_PFSYNC: c_int = 240; pub const IPPROTO_MAX: c_int = 256; /// last return value of *_input(), meaning "all job for this pkt is done". pub const IPPROTO_DONE: c_int = 257; /// sysctl placeholder for (FAST_)IPSEC pub const CTL_IPPROTO_IPSEC: c_int = 258; pub const AF_OROUTE: c_int = 17; pub const AF_ARP: c_int = 28; pub const pseudo_AF_KEY: c_int = 29; pub const pseudo_AF_HDRCMPLT: c_int = 30; pub const AF_BLUETOOTH: c_int = 31; pub const AF_IEEE80211: c_int = 32; pub const AF_MPLS: c_int = 33; pub const AF_ROUTE: c_int = 34; pub const NET_RT_DUMP: c_int = 1; pub const NET_RT_FLAGS: c_int = 2; pub const NET_RT_OOOIFLIST: c_int = 3; pub const NET_RT_OOIFLIST: c_int = 4; pub const NET_RT_OIFLIST: c_int = 5; pub const NET_RT_IFLIST: c_int = 6; pub const NET_RT_MAXID: c_int = 7; pub const PF_OROUTE: c_int = AF_OROUTE; pub const PF_ARP: c_int = AF_ARP; pub const PF_KEY: c_int = pseudo_AF_KEY; pub const PF_BLUETOOTH: c_int = AF_BLUETOOTH; pub const PF_MPLS: c_int = AF_MPLS; pub const PF_ROUTE: c_int = AF_ROUTE; pub const MSG_NBIO: c_int = 0x1000; pub const MSG_WAITFORONE: c_int = 0x2000; pub const MSG_NOTIFICATION: c_int = 0x4000; pub const SCM_TIMESTAMP: c_int = 0x08; pub const SCM_CREDS: c_int = 0x10; pub const O_DSYNC: c_int = 0x10000; pub const MAP_RENAME: c_int = 0x20; pub const MAP_NORESERVE: c_int = 0x40; pub const MAP_HASSEMAPHORE: c_int = 0x200; pub const MAP_TRYFIXED: c_int = 0x400; pub const MAP_WIRED: c_int = 0x800; pub const MAP_STACK: c_int = 0x2000; // map alignment aliases for MAP_ALIGNED pub const MAP_ALIGNMENT_SHIFT: c_int = 24; pub const MAP_ALIGNMENT_MASK: c_int = 0xff << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_64KB: c_int = 16 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_16MB: c_int = 24 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_4GB: c_int = 32 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_1TB: c_int = 40 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_256TB: c_int = 48 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_64PB: c_int = 56 << MAP_ALIGNMENT_SHIFT; // mremap flag pub const MAP_REMAPDUP: c_int = 0x004; pub const DCCP_TYPE_REQUEST: c_int = 0; pub const DCCP_TYPE_RESPONSE: c_int = 1; pub const DCCP_TYPE_DATA: c_int = 2; pub const DCCP_TYPE_ACK: c_int = 3; pub const DCCP_TYPE_DATAACK: c_int = 4; pub const DCCP_TYPE_CLOSEREQ: c_int = 5; pub const DCCP_TYPE_CLOSE: c_int = 6; pub const DCCP_TYPE_RESET: c_int = 7; pub const DCCP_TYPE_MOVE: c_int = 8; pub const DCCP_FEATURE_CC: c_int = 1; pub const DCCP_FEATURE_ECN: c_int = 2; pub const DCCP_FEATURE_ACKRATIO: c_int = 3; pub const DCCP_FEATURE_ACKVECTOR: c_int = 4; pub const DCCP_FEATURE_MOBILITY: c_int = 5; pub const DCCP_FEATURE_LOSSWINDOW: c_int = 6; pub const DCCP_FEATURE_CONN_NONCE: c_int = 8; pub const DCCP_FEATURE_IDENTREG: c_int = 7; pub const DCCP_OPT_PADDING: c_int = 0; pub const DCCP_OPT_DATA_DISCARD: c_int = 1; pub const DCCP_OPT_SLOW_RECV: c_int = 2; pub const DCCP_OPT_BUF_CLOSED: c_int = 3; pub const DCCP_OPT_CHANGE_L: c_int = 32; pub const DCCP_OPT_CONFIRM_L: c_int = 33; pub const DCCP_OPT_CHANGE_R: c_int = 34; pub const DCCP_OPT_CONFIRM_R: c_int = 35; pub const DCCP_OPT_INIT_COOKIE: c_int = 36; pub const DCCP_OPT_NDP_COUNT: c_int = 37; pub const DCCP_OPT_ACK_VECTOR0: c_int = 38; pub const DCCP_OPT_ACK_VECTOR1: c_int = 39; pub const DCCP_OPT_RECV_BUF_DROPS: c_int = 40; pub const DCCP_OPT_TIMESTAMP: c_int = 41; pub const DCCP_OPT_TIMESTAMP_ECHO: c_int = 42; pub const DCCP_OPT_ELAPSEDTIME: c_int = 43; pub const DCCP_OPT_DATACHECKSUM: c_int = 44; pub const DCCP_REASON_UNSPEC: c_int = 0; pub const DCCP_REASON_CLOSED: c_int = 1; pub const DCCP_REASON_INVALID: c_int = 2; pub const DCCP_REASON_OPTION_ERR: c_int = 3; pub const DCCP_REASON_FEA_ERR: c_int = 4; pub const DCCP_REASON_CONN_REF: c_int = 5; pub const DCCP_REASON_BAD_SNAME: c_int = 6; pub const DCCP_REASON_BAD_COOKIE: c_int = 7; pub const DCCP_REASON_INV_MOVE: c_int = 8; pub const DCCP_REASON_UNANSW_CH: c_int = 10; pub const DCCP_REASON_FRUITLESS_NEG: c_int = 11; pub const DCCP_CCID: c_int = 1; pub const DCCP_CSLEN: c_int = 2; pub const DCCP_MAXSEG: c_int = 4; pub const DCCP_SERVICE: c_int = 8; pub const DCCP_NDP_LIMIT: c_int = 16; pub const DCCP_SEQ_NUM_LIMIT: c_int = 16777216; pub const DCCP_MAX_OPTIONS: c_int = 32; pub const DCCP_MAX_PKTS: c_int = 100; pub const _PC_LINK_MAX: c_int = 1; pub const _PC_MAX_CANON: c_int = 2; pub const _PC_MAX_INPUT: c_int = 3; pub const _PC_NAME_MAX: c_int = 4; pub const _PC_PATH_MAX: c_int = 5; pub const _PC_PIPE_BUF: c_int = 6; pub const _PC_CHOWN_RESTRICTED: c_int = 7; pub const _PC_NO_TRUNC: c_int = 8; pub const _PC_VDISABLE: c_int = 9; pub const _PC_SYNC_IO: c_int = 10; pub const _PC_FILESIZEBITS: c_int = 11; pub const _PC_SYMLINK_MAX: c_int = 12; pub const _PC_2_SYMLINKS: c_int = 13; pub const _PC_ACL_EXTENDED: c_int = 14; pub const _PC_MIN_HOLE_SIZE: c_int = 15; pub const _SC_SYNCHRONIZED_IO: c_int = 31; pub const _SC_IOV_MAX: c_int = 32; pub const _SC_MAPPED_FILES: c_int = 33; pub const _SC_MEMLOCK: c_int = 34; pub const _SC_MEMLOCK_RANGE: c_int = 35; pub const _SC_MEMORY_PROTECTION: c_int = 36; pub const _SC_LOGIN_NAME_MAX: c_int = 37; pub const _SC_MONOTONIC_CLOCK: c_int = 38; pub const _SC_CLK_TCK: c_int = 39; pub const _SC_ATEXIT_MAX: c_int = 40; pub const _SC_THREADS: c_int = 41; pub const _SC_SEMAPHORES: c_int = 42; pub const _SC_BARRIERS: c_int = 43; pub const _SC_TIMERS: c_int = 44; pub const _SC_SPIN_LOCKS: c_int = 45; pub const _SC_READER_WRITER_LOCKS: c_int = 46; pub const _SC_GETGR_R_SIZE_MAX: c_int = 47; pub const _SC_GETPW_R_SIZE_MAX: c_int = 48; pub const _SC_CLOCK_SELECTION: c_int = 49; pub const _SC_ASYNCHRONOUS_IO: c_int = 50; pub const _SC_AIO_LISTIO_MAX: c_int = 51; pub const _SC_AIO_MAX: c_int = 52; pub const _SC_MESSAGE_PASSING: c_int = 53; pub const _SC_MQ_OPEN_MAX: c_int = 54; pub const _SC_MQ_PRIO_MAX: c_int = 55; pub const _SC_PRIORITY_SCHEDULING: c_int = 56; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 57; pub const _SC_THREAD_KEYS_MAX: c_int = 58; pub const _SC_THREAD_STACK_MIN: c_int = 59; pub const _SC_THREAD_THREADS_MAX: c_int = 60; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 61; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 62; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 63; pub const _SC_THREAD_PRIO_INHERIT: c_int = 64; pub const _SC_THREAD_PRIO_PROTECT: c_int = 65; pub const _SC_THREAD_PROCESS_SHARED: c_int = 66; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 67; pub const _SC_TTY_NAME_MAX: c_int = 68; pub const _SC_HOST_NAME_MAX: c_int = 69; pub const _SC_PASS_MAX: c_int = 70; pub const _SC_REGEXP: c_int = 71; pub const _SC_SHELL: c_int = 72; pub const _SC_SYMLOOP_MAX: c_int = 73; pub const _SC_V6_ILP32_OFF32: c_int = 74; pub const _SC_V6_ILP32_OFFBIG: c_int = 75; pub const _SC_V6_LP64_OFF64: c_int = 76; pub const _SC_V6_LPBIG_OFFBIG: c_int = 77; pub const _SC_2_PBS: c_int = 80; pub const _SC_2_PBS_ACCOUNTING: c_int = 81; pub const _SC_2_PBS_CHECKPOINT: c_int = 82; pub const _SC_2_PBS_LOCATE: c_int = 83; pub const _SC_2_PBS_MESSAGE: c_int = 84; pub const _SC_2_PBS_TRACK: c_int = 85; pub const _SC_SPAWN: c_int = 86; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 87; pub const _SC_TIMER_MAX: c_int = 88; pub const _SC_SEM_NSEMS_MAX: c_int = 89; pub const _SC_CPUTIME: c_int = 90; pub const _SC_THREAD_CPUTIME: c_int = 91; pub const _SC_DELAYTIMER_MAX: c_int = 92; // These two variables will be supported in NetBSD 8.0 // pub const _SC_SIGQUEUE_MAX : c_int = 93; // pub const _SC_REALTIME_SIGNALS : c_int = 94; pub const _SC_PHYS_PAGES: c_int = 121; pub const _SC_NPROCESSORS_CONF: c_int = 1001; pub const _SC_NPROCESSORS_ONLN: c_int = 1002; pub const _SC_SCHED_RT_TS: c_int = 2001; pub const _SC_SCHED_PRI_MIN: c_int = 2002; pub const _SC_SCHED_PRI_MAX: c_int = 2003; pub const FD_SETSIZE: usize = 0x100; pub const ST_NOSUID: c_ulong = 8; pub const BIOCGRSIG: c_ulong = 0x40044272; pub const BIOCSRSIG: c_ulong = 0x80044273; pub const BIOCSDLT: c_ulong = 0x80044278; pub const BIOCGSEESENT: c_ulong = 0x40044276; pub const BIOCSSEESENT: c_ulong = 0x80044277; // pub const MNT_UNION: c_int = 0x00000020; pub const MNT_NOCOREDUMP: c_int = 0x00008000; pub const MNT_RELATIME: c_int = 0x00020000; pub const MNT_IGNORE: c_int = 0x00100000; pub const MNT_NFS4ACLS: c_int = 0x00200000; pub const MNT_DISCARD: c_int = 0x00800000; pub const MNT_EXTATTR: c_int = 0x01000000; pub const MNT_LOG: c_int = 0x02000000; pub const MNT_NOATIME: c_int = 0x04000000; pub const MNT_AUTOMOUNTED: c_int = 0x10000000; pub const MNT_SYMPERM: c_int = 0x20000000; pub const MNT_NODEVMTIME: c_int = 0x40000000; pub const MNT_SOFTDEP: c_int = 0x80000000; pub const MNT_POSIX1EACLS: c_int = 0x00000800; pub const MNT_ACLS: c_int = MNT_POSIX1EACLS; pub const MNT_WAIT: c_int = 1; pub const MNT_NOWAIT: c_int = 2; pub const MNT_LAZY: c_int = 3; // pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 4; pub const NTP_API: c_int = 4; pub const MAXPHASE: c_long = 500000000; pub const MAXFREQ: c_long = 500000; pub const MINSEC: c_int = 256; pub const MAXSEC: c_int = 2048; pub const NANOSECOND: c_long = 1000000000; pub const SCALE_PPM: c_int = 65; pub const MAXTC: c_int = 10; pub const MOD_OFFSET: c_uint = 0x0001; pub const MOD_FREQUENCY: c_uint = 0x0002; pub const MOD_MAXERROR: c_uint = 0x0004; pub const MOD_ESTERROR: c_uint = 0x0008; pub const MOD_STATUS: c_uint = 0x0010; pub const MOD_TIMECONST: c_uint = 0x0020; pub const MOD_PPSMAX: c_uint = 0x0040; pub const MOD_TAI: c_uint = 0x0080; pub const MOD_MICRO: c_uint = 0x1000; pub const MOD_NANO: c_uint = 0x2000; pub const MOD_CLKB: c_uint = 0x4000; pub const MOD_CLKA: c_uint = 0x8000; pub const STA_PLL: c_int = 0x0001; pub const STA_PPSFREQ: c_int = 0x0002; pub const STA_PPSTIME: c_int = 0x0004; pub const STA_FLL: c_int = 0x0008; pub const STA_INS: c_int = 0x0010; pub const STA_DEL: c_int = 0x0020; pub const STA_UNSYNC: c_int = 0x0040; pub const STA_FREQHOLD: c_int = 0x0080; pub const STA_PPSSIGNAL: c_int = 0x0100; pub const STA_PPSJITTER: c_int = 0x0200; pub const STA_PPSWANDER: c_int = 0x0400; pub const STA_PPSERROR: c_int = 0x0800; pub const STA_CLOCKERR: c_int = 0x1000; pub const STA_NANO: c_int = 0x2000; pub const STA_MODE: c_int = 0x4000; pub const STA_CLK: c_int = 0x8000; pub const STA_RONLY: c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const TIME_OK: c_int = 0; pub const TIME_INS: c_int = 1; pub const TIME_DEL: c_int = 2; pub const TIME_OOP: c_int = 3; pub const TIME_WAIT: c_int = 4; pub const TIME_ERROR: c_int = 5; pub const LITTLE_ENDIAN: c_int = 1234; pub const BIG_ENDIAN: c_int = 4321; pub const PL_EVENT_NONE: c_int = 0; pub const PL_EVENT_SIGNAL: c_int = 1; pub const PL_EVENT_SUSPENDED: c_int = 2; cfg_if! { if #[cfg(any( target_arch = "sparc", target_arch = "sparc64", target_arch = "x86", target_arch = "x86_64" ))] { pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { ptm_magic: 0x33330003, ptm_errorcheck: 0, ptm_pad1: [0; 3], ptm_unused: 0, ptm_pad2: [0; 3], ptm_waiters: 0 as *mut _, ptm_owner: 0, ptm_recursed: 0, ptm_spare2: 0 as *mut _, }; } else { pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { ptm_magic: 0x33330003, ptm_errorcheck: 0, ptm_unused: 0, ptm_waiters: 0 as *mut _, ptm_owner: 0, ptm_recursed: 0, ptm_spare2: 0 as *mut _, }; } } pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { ptc_magic: 0x55550005, ptc_lock: 0, ptc_waiters_first: 0 as *mut _, ptc_waiters_last: 0 as *mut _, ptc_mutex: 0 as *mut _, ptc_private: 0 as *mut _, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { ptr_magic: 0x99990009, ptr_interlock: 0, ptr_rblocked_first: 0 as *mut _, ptr_rblocked_last: 0 as *mut _, ptr_wblocked_first: 0 as *mut _, ptr_wblocked_last: 0 as *mut _, ptr_nreaders: 0, ptr_owner: 0, ptr_private: 0 as *mut _, }; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const SCHED_NONE: c_int = -1; pub const SCHED_OTHER: c_int = 0; pub const SCHED_FIFO: c_int = 1; pub const SCHED_RR: c_int = 2; pub const EVFILT_AIO: u32 = 2; pub const EVFILT_PROC: u32 = 4; pub const EVFILT_READ: u32 = 0; pub const EVFILT_SIGNAL: u32 = 5; pub const EVFILT_TIMER: u32 = 6; pub const EVFILT_VNODE: u32 = 3; pub const EVFILT_WRITE: u32 = 1; pub const EVFILT_FS: u32 = 7; pub const EVFILT_USER: u32 = 8; pub const EVFILT_EMPTY: u32 = 9; pub const EV_ADD: u32 = 0x1; pub const EV_DELETE: u32 = 0x2; pub const EV_ENABLE: u32 = 0x4; pub const EV_DISABLE: u32 = 0x8; pub const EV_ONESHOT: u32 = 0x10; pub const EV_CLEAR: u32 = 0x20; pub const EV_RECEIPT: u32 = 0x40; pub const EV_DISPATCH: u32 = 0x80; pub const EV_FLAG1: u32 = 0x2000; pub const EV_ERROR: u32 = 0x4000; pub const EV_EOF: u32 = 0x8000; pub const EV_SYSFLAGS: u32 = 0xf000; pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; pub const NOTE_FFOR: u32 = 0x80000000; pub const NOTE_FFCOPY: u32 = 0xc0000000; pub const NOTE_FFCTRLMASK: u32 = 0xc0000000; pub const NOTE_FFLAGSMASK: u32 = 0x00ffffff; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xf0000000; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const NOTE_MSECONDS: u32 = 0x00000000; pub const NOTE_SECONDS: u32 = 0x00000001; pub const NOTE_USECONDS: u32 = 0x00000002; pub const NOTE_NSECONDS: u32 = 0x00000003; pub const NOTE_ABSTIME: u32 = 0x000000010; pub const TMP_MAX: c_uint = 308915776; pub const AI_PASSIVE: c_int = 0x00000001; pub const AI_CANONNAME: c_int = 0x00000002; pub const AI_NUMERICHOST: c_int = 0x00000004; pub const AI_NUMERICSERV: c_int = 0x00000008; pub const AI_ADDRCONFIG: c_int = 0x00000400; pub const AI_SRV: c_int = 0x00000800; pub const NI_MAXHOST: crate::socklen_t = 1025; pub const NI_MAXSERV: crate::socklen_t = 32; pub const NI_NOFQDN: c_int = 0x00000001; pub const NI_NUMERICHOST: c_int = 0x000000002; pub const NI_NAMEREQD: c_int = 0x000000004; pub const NI_NUMERICSERV: c_int = 0x000000008; pub const NI_DGRAM: c_int = 0x00000010; pub const NI_WITHSCOPEID: c_int = 0x00000020; pub const NI_NUMERICSCOPE: c_int = 0x00000040; pub const RTLD_NOLOAD: c_int = 0x2000; pub const RTLD_LOCAL: c_int = 0x200; pub const CTL_MAXNAME: c_int = 12; pub const SYSCTL_NAMELEN: c_int = 32; pub const SYSCTL_DEFSIZE: c_int = 8; pub const CTLTYPE_NODE: c_int = 1; pub const CTLTYPE_INT: c_int = 2; pub const CTLTYPE_STRING: c_int = 3; pub const CTLTYPE_QUAD: c_int = 4; pub const CTLTYPE_STRUCT: c_int = 5; pub const CTLTYPE_BOOL: c_int = 6; pub const CTLFLAG_READONLY: c_int = 0x00000000; pub const CTLFLAG_READWRITE: c_int = 0x00000070; pub const CTLFLAG_ANYWRITE: c_int = 0x00000080; pub const CTLFLAG_PRIVATE: c_int = 0x00000100; pub const CTLFLAG_PERMANENT: c_int = 0x00000200; pub const CTLFLAG_OWNDATA: c_int = 0x00000400; pub const CTLFLAG_IMMEDIATE: c_int = 0x00000800; pub const CTLFLAG_HEX: c_int = 0x00001000; pub const CTLFLAG_ROOT: c_int = 0x00002000; pub const CTLFLAG_ANYNUMBER: c_int = 0x00004000; pub const CTLFLAG_HIDDEN: c_int = 0x00008000; pub const CTLFLAG_ALIAS: c_int = 0x00010000; pub const CTLFLAG_MMAP: c_int = 0x00020000; pub const CTLFLAG_OWNDESC: c_int = 0x00040000; pub const CTLFLAG_UNSIGNED: c_int = 0x00080000; pub const SYSCTL_VERS_MASK: c_int = 0xff000000; pub const SYSCTL_VERS_0: c_int = 0x00000000; pub const SYSCTL_VERS_1: c_int = 0x01000000; pub const SYSCTL_VERSION: c_int = SYSCTL_VERS_1; pub const CTL_EOL: c_int = -1; pub const CTL_QUERY: c_int = -2; pub const CTL_CREATE: c_int = -3; pub const CTL_CREATESYM: c_int = -4; pub const CTL_DESTROY: c_int = -5; pub const CTL_MMAP: c_int = -6; pub const CTL_DESCRIBE: c_int = -7; pub const CTL_UNSPEC: c_int = 0; pub const CTL_KERN: c_int = 1; pub const CTL_VM: c_int = 2; pub const CTL_VFS: c_int = 3; pub const CTL_NET: c_int = 4; pub const CTL_DEBUG: c_int = 5; pub const CTL_HW: c_int = 6; pub const CTL_MACHDEP: c_int = 7; pub const CTL_USER: c_int = 8; pub const CTL_DDB: c_int = 9; pub const CTL_PROC: c_int = 10; pub const CTL_VENDOR: c_int = 11; pub const CTL_EMUL: c_int = 12; pub const CTL_SECURITY: c_int = 13; pub const CTL_MAXID: c_int = 14; pub const KERN_OSTYPE: c_int = 1; pub const KERN_OSRELEASE: c_int = 2; pub const KERN_OSREV: c_int = 3; pub const KERN_VERSION: c_int = 4; pub const KERN_MAXVNODES: c_int = 5; pub const KERN_MAXPROC: c_int = 6; pub const KERN_MAXFILES: c_int = 7; pub const KERN_ARGMAX: c_int = 8; pub const KERN_SECURELVL: c_int = 9; pub const KERN_HOSTNAME: c_int = 10; pub const KERN_HOSTID: c_int = 11; pub const KERN_CLOCKRATE: c_int = 12; pub const KERN_VNODE: c_int = 13; pub const KERN_PROC: c_int = 14; pub const KERN_FILE: c_int = 15; pub const KERN_PROF: c_int = 16; pub const KERN_POSIX1: c_int = 17; pub const KERN_NGROUPS: c_int = 18; pub const KERN_JOB_CONTROL: c_int = 19; pub const KERN_SAVED_IDS: c_int = 20; pub const KERN_OBOOTTIME: c_int = 21; pub const KERN_DOMAINNAME: c_int = 22; pub const KERN_MAXPARTITIONS: c_int = 23; pub const KERN_RAWPARTITION: c_int = 24; pub const KERN_NTPTIME: c_int = 25; pub const KERN_TIMEX: c_int = 26; pub const KERN_AUTONICETIME: c_int = 27; pub const KERN_AUTONICEVAL: c_int = 28; pub const KERN_RTC_OFFSET: c_int = 29; pub const KERN_ROOT_DEVICE: c_int = 30; pub const KERN_MSGBUFSIZE: c_int = 31; pub const KERN_FSYNC: c_int = 32; pub const KERN_OLDSYSVMSG: c_int = 33; pub const KERN_OLDSYSVSEM: c_int = 34; pub const KERN_OLDSYSVSHM: c_int = 35; pub const KERN_OLDSHORTCORENAME: c_int = 36; pub const KERN_SYNCHRONIZED_IO: c_int = 37; pub const KERN_IOV_MAX: c_int = 38; pub const KERN_MBUF: c_int = 39; pub const KERN_MAPPED_FILES: c_int = 40; pub const KERN_MEMLOCK: c_int = 41; pub const KERN_MEMLOCK_RANGE: c_int = 42; pub const KERN_MEMORY_PROTECTION: c_int = 43; pub const KERN_LOGIN_NAME_MAX: c_int = 44; pub const KERN_DEFCORENAME: c_int = 45; pub const KERN_LOGSIGEXIT: c_int = 46; pub const KERN_PROC2: c_int = 47; pub const KERN_PROC_ARGS: c_int = 48; pub const KERN_FSCALE: c_int = 49; pub const KERN_CCPU: c_int = 50; pub const KERN_CP_TIME: c_int = 51; pub const KERN_OLDSYSVIPC_INFO: c_int = 52; pub const KERN_MSGBUF: c_int = 53; pub const KERN_CONSDEV: c_int = 54; pub const KERN_MAXPTYS: c_int = 55; pub const KERN_PIPE: c_int = 56; pub const KERN_MAXPHYS: c_int = 57; pub const KERN_SBMAX: c_int = 58; pub const KERN_TKSTAT: c_int = 59; pub const KERN_MONOTONIC_CLOCK: c_int = 60; pub const KERN_URND: c_int = 61; pub const KERN_LABELSECTOR: c_int = 62; pub const KERN_LABELOFFSET: c_int = 63; pub const KERN_LWP: c_int = 64; pub const KERN_FORKFSLEEP: c_int = 65; pub const KERN_POSIX_THREADS: c_int = 66; pub const KERN_POSIX_SEMAPHORES: c_int = 67; pub const KERN_POSIX_BARRIERS: c_int = 68; pub const KERN_POSIX_TIMERS: c_int = 69; pub const KERN_POSIX_SPIN_LOCKS: c_int = 70; pub const KERN_POSIX_READER_WRITER_LOCKS: c_int = 71; pub const KERN_DUMP_ON_PANIC: c_int = 72; pub const KERN_SOMAXKVA: c_int = 73; pub const KERN_ROOT_PARTITION: c_int = 74; pub const KERN_DRIVERS: c_int = 75; pub const KERN_BUF: c_int = 76; pub const KERN_FILE2: c_int = 77; pub const KERN_VERIEXEC: c_int = 78; pub const KERN_CP_ID: c_int = 79; pub const KERN_HARDCLOCK_TICKS: c_int = 80; pub const KERN_ARND: c_int = 81; pub const KERN_SYSVIPC: c_int = 82; pub const KERN_BOOTTIME: c_int = 83; pub const KERN_EVCNT: c_int = 84; pub const KERN_MAXID: c_int = 85; pub const KERN_PROC_ALL: c_int = 0; pub const KERN_PROC_PID: c_int = 1; pub const KERN_PROC_PGRP: c_int = 2; pub const KERN_PROC_SESSION: c_int = 3; pub const KERN_PROC_TTY: c_int = 4; pub const KERN_PROC_UID: c_int = 5; pub const KERN_PROC_RUID: c_int = 6; pub const KERN_PROC_GID: c_int = 7; pub const KERN_PROC_RGID: c_int = 8; pub const KERN_PROC_ARGV: c_int = 1; pub const KERN_PROC_NARGV: c_int = 2; pub const KERN_PROC_ENV: c_int = 3; pub const KERN_PROC_NENV: c_int = 4; pub const KERN_PROC_PATHNAME: c_int = 5; pub const VM_PROC: c_int = 16; pub const VM_PROC_MAP: c_int = 1; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_MEMORY: c_int = 6; pub const EAI_NODATA: c_int = 7; pub const EAI_NONAME: c_int = 8; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 14; pub const AIO_CANCELED: c_int = 1; pub const AIO_NOTCANCELED: c_int = 2; pub const AIO_ALLDONE: c_int = 3; pub const LIO_NOP: c_int = 0; pub const LIO_WRITE: c_int = 1; pub const LIO_READ: c_int = 2; pub const LIO_WAIT: c_int = 1; pub const LIO_NOWAIT: c_int = 0; pub const SIGEV_NONE: c_int = 0; pub const SIGEV_SIGNAL: c_int = 1; pub const SIGEV_THREAD: c_int = 2; pub const WSTOPPED: c_int = 0x00000002; // same as WUNTRACED pub const WCONTINUED: c_int = 0x00000010; pub const WEXITED: c_int = 0x000000020; pub const WNOWAIT: c_int = 0x00010000; pub const WALTSIG: c_int = 0x00000004; pub const WALLSIG: c_int = 0x00000008; pub const WTRAPPED: c_int = 0x00000040; pub const WNOZOMBIE: c_int = 0x00020000; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 4; pub const UTIME_OMIT: c_long = 1073741822; pub const UTIME_NOW: c_long = 1073741823; pub const B460800: crate::speed_t = 460800; pub const B921600: crate::speed_t = 921600; pub const ONOCR: crate::tcflag_t = 0x20; pub const ONLRET: crate::tcflag_t = 0x40; pub const CDTRCTS: crate::tcflag_t = 0x00020000; pub const CHWFLOW: crate::tcflag_t = crate::MDMBUF | crate::CRTSCTS | crate::CDTRCTS; // pub const _PATH_UTMPX: &[c_char; 14] = b"/var/run/utmpx"; // pub const _PATH_WTMPX: &[c_char; 14] = b"/var/log/wtmpx"; // pub const _PATH_LASTLOGX: &[c_char; 17] = b"/var/log/lastlogx"; // pub const _PATH_UTMP_UPDATE: &[c_char; 24] = b"/usr/libexec/utmp_update"; pub const UT_NAMESIZE: usize = 8; pub const UT_LINESIZE: usize = 8; pub const UT_HOSTSIZE: usize = 16; pub const _UTX_USERSIZE: usize = 32; pub const _UTX_LINESIZE: usize = 32; pub const _UTX_PADSIZE: usize = 40; pub const _UTX_IDSIZE: usize = 4; pub const _UTX_HOSTSIZE: usize = 256; pub const EMPTY: u16 = 0; pub const RUN_LVL: u16 = 1; pub const BOOT_TIME: u16 = 2; pub const OLD_TIME: u16 = 3; pub const NEW_TIME: u16 = 4; pub const INIT_PROCESS: u16 = 5; pub const LOGIN_PROCESS: u16 = 6; pub const USER_PROCESS: u16 = 7; pub const DEAD_PROCESS: u16 = 8; pub const ACCOUNTING: u16 = 9; pub const SIGNATURE: u16 = 10; pub const DOWN_TIME: u16 = 11; pub const SOCK_CLOEXEC: c_int = 0x10000000; pub const SOCK_NONBLOCK: c_int = 0x20000000; // Uncomment on next NetBSD release // pub const FIOSEEKDATA: c_ulong = 0xc0086661; // pub const FIOSEEKHOLE: c_ulong = 0xc0086662; pub const OFIOGETBMAP: c_ulong = 0xc004667a; pub const FIOGETBMAP: c_ulong = 0xc008667a; pub const FIONWRITE: c_ulong = 0x40046679; pub const FIONSPACE: c_ulong = 0x40046678; pub const FIBMAP: c_ulong = 0xc008667a; pub const SIGSTKSZ: size_t = 40960; pub const REG_ENOSYS: c_int = 17; pub const PT_DUMPCORE: c_int = 12; pub const PT_LWPINFO: c_int = 13; pub const PT_SYSCALL: c_int = 14; pub const PT_SYSCALLEMU: c_int = 15; pub const PT_SET_EVENT_MASK: c_int = 16; pub const PT_GET_EVENT_MASK: c_int = 17; pub const PT_GET_PROCESS_STATE: c_int = 18; pub const PT_SET_SIGINFO: c_int = 19; pub const PT_GET_SIGINFO: c_int = 20; pub const PT_RESUME: c_int = 21; pub const PT_SUSPEND: c_int = 23; pub const PT_STOP: c_int = 23; pub const PT_LWPSTATUS: c_int = 24; pub const PT_LWPNEXT: c_int = 25; pub const PT_SET_SIGPASS: c_int = 26; pub const PT_GET_SIGPASS: c_int = 27; pub const PT_FIRSTMACH: c_int = 32; pub const POSIX_SPAWN_RETURNERROR: c_int = 0x40; // Flags for chflags(2) pub const SF_APPEND: c_ulong = 0x00040000; pub const SF_ARCHIVED: c_ulong = 0x00010000; pub const SF_IMMUTABLE: c_ulong = 0x00020000; pub const SF_LOG: c_ulong = 0x00400000; pub const SF_SETTABLE: c_ulong = 0xffff0000; pub const SF_SNAPINVAL: c_ulong = 0x00800000; pub const SF_SNAPSHOT: c_ulong = 0x00200000; pub const UF_APPEND: c_ulong = 0x00000004; pub const UF_IMMUTABLE: c_ulong = 0x00000002; pub const UF_NODUMP: c_ulong = 0x00000001; pub const UF_OPAQUE: c_ulong = 0x00000008; pub const UF_SETTABLE: c_ulong = 0x0000ffff; // sys/sysctl.h pub const KVME_PROT_READ: c_int = 0x00000001; pub const KVME_PROT_WRITE: c_int = 0x00000002; pub const KVME_PROT_EXEC: c_int = 0x00000004; pub const KVME_FLAG_COW: c_int = 0x00000001; pub const KVME_FLAG_NEEDS_COPY: c_int = 0x00000002; pub const KVME_FLAG_NOCOREDUMP: c_int = 0x000000004; pub const KVME_FLAG_PAGEABLE: c_int = 0x000000008; pub const KVME_FLAG_GROWS_UP: c_int = 0x000000010; pub const KVME_FLAG_GROWS_DOWN: c_int = 0x000000020; pub const NGROUPS_MAX: c_int = 16; pub const KI_NGROUPS: c_int = 16; pub const KI_MAXCOMLEN: c_int = 24; pub const KI_WMESGLEN: c_int = 8; pub const KI_MAXLOGNAME: c_int = 24; pub const KI_MAXEMULLEN: c_int = 16; pub const KI_LNAMELEN: c_int = 20; // sys/lwp.h pub const LSIDL: c_int = 1; pub const LSRUN: c_int = 2; pub const LSSLEEP: c_int = 3; pub const LSSTOP: c_int = 4; pub const LSZOMB: c_int = 5; pub const LSONPROC: c_int = 7; pub const LSSUSPENDED: c_int = 8; // sys/xattr.h pub const XATTR_CREATE: c_int = 0x01; pub const XATTR_REPLACE: c_int = 0x02; // sys/extattr.h pub const EXTATTR_NAMESPACE_EMPTY: c_int = 0; // For getrandom() pub const GRND_NONBLOCK: c_uint = 0x1; pub const GRND_RANDOM: c_uint = 0x2; pub const GRND_INSECURE: c_uint = 0x4; // sys/reboot.h pub const RB_ASKNAME: c_int = 0x000000001; pub const RB_SINGLE: c_int = 0x000000002; pub const RB_NOSYNC: c_int = 0x000000004; pub const RB_HALT: c_int = 0x000000008; pub const RB_INITNAME: c_int = 0x000000010; pub const RB_KDB: c_int = 0x000000040; pub const RB_RDONLY: c_int = 0x000000080; pub const RB_DUMP: c_int = 0x000000100; pub const RB_MINIROOT: c_int = 0x000000200; pub const RB_STRING: c_int = 0x000000400; pub const RB_POWERDOWN: c_int = RB_HALT | 0x000000800; pub const RB_USERCONF: c_int = 0x000001000; pub const fn MAP_ALIGNED(alignment: c_int) -> c_int { alignment << MAP_ALIGNMENT_SHIFT } // net/route.h pub const RTF_MASK: c_int = 0x80; pub const RTF_CONNECTED: c_int = 0x100; pub const RTF_ANNOUNCE: c_int = 0x20000; pub const RTF_SRC: c_int = 0x10000; pub const RTF_LOCAL: c_int = 0x40000; pub const RTF_BROADCAST: c_int = 0x80000; pub const RTF_UPDATING: c_int = 0x100000; pub const RTF_DONTCHANGEIFA: c_int = 0x200000; pub const RTM_VERSION: c_int = 4; pub const RTM_LOCK: c_int = 0x8; pub const RTM_IFANNOUNCE: c_int = 0x10; pub const RTM_IEEE80211: c_int = 0x11; pub const RTM_SETGATE: c_int = 0x12; pub const RTM_LLINFO_UPD: c_int = 0x13; pub const RTM_IFINFO: c_int = 0x14; pub const RTM_OCHGADDR: c_int = 0x15; pub const RTM_NEWADDR: c_int = 0x16; pub const RTM_DELADDR: c_int = 0x17; pub const RTM_CHGADDR: c_int = 0x18; pub const RTA_TAG: c_int = 0x100; pub const RTAX_TAG: c_int = 8; pub const RTAX_MAX: c_int = 9; // sys/timerfd.h pub const TFD_CLOEXEC: i32 = crate::O_CLOEXEC; pub const TFD_NONBLOCK: i32 = crate::O_NONBLOCK; pub const TFD_TIMER_ABSTIME: i32 = crate::O_WRONLY; pub const TFD_TIMER_CANCEL_ON_SET: i32 = crate::O_RDWR; const_fn! { {const} fn _ALIGN(p: usize) -> usize { (p + _ALIGNBYTES) & !_ALIGNBYTES } } f! { pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(_ALIGN(mem::size_of::()) as isize) } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { _ALIGN(mem::size_of::()) as c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const crate::msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { return crate::CMSG_FIRSTHDR(mhdr); }; let next = cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize) + _ALIGN(mem::size_of::()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut cmsghdr } else { (cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr } } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (_ALIGN(mem::size_of::()) + _ALIGN(length as usize)) as c_uint } // dirfd() is a macro on netbsd to access // the first field of the struct where dirp points to: // http://cvsweb.netbsd.org/bsdweb.cgi/src/include/dirent.h?rev=1.36 pub fn dirfd(dirp: *mut crate::DIR) -> c_int { *(dirp as *const c_int) } pub fn SOCKCREDSIZE(ngrps: usize) -> usize { let ngrps = if ngrps > 0 { ngrps - 1 } else { 0 }; mem::size_of::() + mem::size_of::() * ngrps } pub fn PROT_MPROTECT(x: c_int) -> c_int { x << 3 } pub fn PROT_MPROTECT_EXTRACT(x: c_int) -> c_int { (x >> 3) & 0x7 } } safe_f! { pub {const} fn WSTOPSIG(status: c_int) -> c_int { status >> 8 } pub {const} fn WIFSIGNALED(status: c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 } pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0o177) == 0o177 } pub {const} fn WIFCONTINUED(status: c_int) -> bool { status == 0xffff } pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= (major << 8) & 0x000ff00; dev |= (minor << 12) & 0xfff00000; dev |= minor & 0xff; dev } pub {const} fn major(dev: crate::dev_t) -> c_int { (((dev as u32) & 0x000fff00) >> 8) as c_int } pub {const} fn minor(dev: crate::dev_t) -> c_int { let mut res = 0; res |= ((dev as u32) & 0xfff00000) >> 12; res |= (dev as u32) & 0x000000ff; res as c_int } } extern "C" { pub fn ntp_adjtime(buf: *mut timex) -> c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn reallocarr(ptr: *mut c_void, number: size_t, size: size_t) -> c_int; pub fn chflags(path: *const c_char, flags: c_ulong) -> c_int; pub fn fchflags(fd: c_int, flags: c_ulong) -> c_int; pub fn lchflags(path: *const c_char, flags: c_ulong) -> c_int; pub fn extattr_list_fd( fd: c_int, attrnamespace: c_int, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_list_file( path: *const c_char, attrnamespace: c_int, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_list_link( path: *const c_char, attrnamespace: c_int, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_delete_fd(fd: c_int, attrnamespace: c_int, attrname: *const c_char) -> c_int; pub fn extattr_delete_file( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, ) -> c_int; pub fn extattr_delete_link( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, ) -> c_int; pub fn extattr_get_fd( fd: c_int, attrnamespace: c_int, attrname: *const c_char, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_get_file( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_get_link( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_namespace_to_string(attrnamespace: c_int, string: *mut *mut c_char) -> c_int; pub fn extattr_set_fd( fd: c_int, attrnamespace: c_int, attrname: *const c_char, data: *const c_void, nbytes: size_t, ) -> c_int; pub fn extattr_set_file( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, data: *const c_void, nbytes: size_t, ) -> c_int; pub fn extattr_set_link( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, data: *const c_void, nbytes: size_t, ) -> c_int; pub fn extattr_string_to_namespace(string: *const c_char, attrnamespace: *mut c_int) -> c_int; pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *mut crate::termios, winp: *mut crate::winsize, ) -> c_int; pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *mut crate::termios, winp: *mut crate::winsize, ) -> crate::pid_t; #[link_name = "__lutimes50"] pub fn lutimes(file: *const c_char, times: *const crate::timeval) -> c_int; #[link_name = "__gettimeofday50"] pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn sysctl( name: *const c_int, namelen: c_uint, oldp: *mut c_void, oldlenp: *mut size_t, newp: *const c_void, newlen: size_t, ) -> c_int; pub fn sysctlbyname( name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t, newp: *const c_void, newlen: size_t, ) -> c_int; pub fn sysctlnametomib(sname: *const c_char, name: *mut c_int, namelenp: *mut size_t) -> c_int; #[link_name = "__kevent50"] pub fn kevent( kq: c_int, changelist: *const crate::kevent, nchanges: size_t, eventlist: *mut crate::kevent, nevents: size_t, timeout: *const crate::timespec, ) -> c_int; #[link_name = "__mount50"] pub fn mount( src: *const c_char, target: *const c_char, flags: c_int, data: *mut c_void, size: size_t, ) -> c_int; pub fn mq_open(name: *const c_char, oflag: c_int, ...) -> crate::mqd_t; pub fn mq_close(mqd: crate::mqd_t) -> c_int; pub fn mq_getattr(mqd: crate::mqd_t, attr: *mut crate::mq_attr) -> c_int; pub fn mq_notify(mqd: crate::mqd_t, notification: *const crate::sigevent) -> c_int; pub fn mq_receive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, ) -> ssize_t; pub fn mq_send( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, ) -> c_int; pub fn mq_setattr( mqd: crate::mqd_t, newattr: *const crate::mq_attr, oldattr: *mut crate::mq_attr, ) -> c_int; #[link_name = "__mq_timedreceive50"] pub fn mq_timedreceive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, abs_timeout: *const crate::timespec, ) -> ssize_t; #[link_name = "__mq_timedsend50"] pub fn mq_timedsend( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, abs_timeout: *const crate::timespec, ) -> c_int; pub fn mq_unlink(name: *const c_char) -> c_int; pub fn ptrace(request: c_int, pid: crate::pid_t, addr: *mut c_void, data: c_int) -> c_int; pub fn utrace(label: *const c_char, addr: *mut c_void, len: size_t) -> c_int; pub fn pthread_getname_np(t: crate::pthread_t, name: *mut c_char, len: size_t) -> c_int; pub fn pthread_setname_np( t: crate::pthread_t, name: *const c_char, arg: *const c_void, ) -> c_int; pub fn pthread_attr_get_np(thread: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_getattr_np(native: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_getaffinity_np( thread: crate::pthread_t, size: size_t, set: *mut cpuset_t, ) -> c_int; pub fn pthread_setaffinity_np( thread: crate::pthread_t, size: size_t, set: *mut cpuset_t, ) -> c_int; pub fn _cpuset_create() -> *mut cpuset_t; pub fn _cpuset_destroy(set: *mut cpuset_t); pub fn _cpuset_clr(cpu: cpuid_t, set: *mut cpuset_t) -> c_int; pub fn _cpuset_set(cpu: cpuid_t, set: *mut cpuset_t) -> c_int; pub fn _cpuset_isset(cpu: cpuid_t, set: *const cpuset_t) -> c_int; pub fn _cpuset_size(set: *const cpuset_t) -> size_t; pub fn _cpuset_zero(set: *mut cpuset_t); #[link_name = "__sigtimedwait50"] pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; pub fn freelocale(loc: crate::locale_t); pub fn localeconv_l(loc: crate::locale_t) -> *mut lconv; pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; #[link_name = "__settimeofday50"] pub fn settimeofday(tv: *const crate::timeval, tz: *const c_void) -> c_int; pub fn dup3(src: c_int, dst: c_int, flags: c_int) -> c_int; pub fn kqueue1(flags: c_int) -> c_int; pub fn _lwp_self() -> lwpid_t; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; // link.h pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn(info: *mut dl_phdr_info, size: usize, data: *mut c_void) -> c_int, >, data: *mut c_void, ) -> c_int; // dlfcn.h pub fn _dlauxinfo() -> *mut c_void; pub fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut c_char, inbytesleft: *mut size_t, outbuf: *mut *mut c_char, outbytesleft: *mut size_t, ) -> size_t; pub fn iconv_close(cd: iconv_t) -> c_int; pub fn timer_create( clockid: crate::clockid_t, sevp: *mut crate::sigevent, timerid: *mut crate::timer_t, ) -> c_int; pub fn timer_delete(timerid: crate::timer_t) -> c_int; pub fn timer_getoverrun(timerid: crate::timer_t) -> c_int; pub fn timer_gettime(timerid: crate::timer_t, curr_value: *mut crate::itimerspec) -> c_int; pub fn timer_settime( timerid: crate::timer_t, flags: c_int, new_value: *const crate::itimerspec, old_value: *mut crate::itimerspec, ) -> c_int; // Added in `NetBSD` 7.0 pub fn explicit_memset(b: *mut c_void, c: c_int, len: size_t); pub fn consttime_memequal(a: *const c_void, b: *const c_void, len: size_t) -> c_int; pub fn setproctitle(fmt: *const c_char, ...); pub fn mremap( oldp: *mut c_void, oldsize: size_t, newp: *mut c_void, newsize: size_t, flags: c_int, ) -> *mut c_void; pub fn sched_rr_get_interval(pid: crate::pid_t, t: *mut crate::timespec) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const crate::sched_param) -> c_int; pub fn sched_getparam(pid: crate::pid_t, param: *mut crate::sched_param) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; #[link_name = "__pollts50"] pub fn pollts( fds: *mut crate::pollfd, nfds: crate::nfds_t, ts: *const crate::timespec, sigmask: *const crate::sigset_t, ) -> c_int; pub fn ppoll( fds: *mut crate::pollfd, nfds: crate::nfds_t, ts: *const crate::timespec, sigmask: *const crate::sigset_t, ) -> c_int; pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; pub fn reboot(mode: c_int, bootstr: *mut c_char) -> c_int; #[link_name = "___lwp_park60"] pub fn _lwp_park( clock: crate::clockid_t, flags: c_int, ts: *const crate::timespec, unpark: crate::lwpid_t, hint: *const c_void, unparkhint: *mut c_void, ) -> c_int; pub fn _lwp_unpark(lwp: crate::lwpid_t, hint: *const c_void) -> c_int; pub fn _lwp_unpark_all( targets: *const crate::lwpid_t, ntargets: size_t, hint: *const c_void, ) -> c_int; #[link_name = "__getmntinfo13"] pub fn getmntinfo(mntbufp: *mut *mut crate::statvfs, flags: c_int) -> c_int; pub fn getvfsstat(buf: *mut statvfs, bufsize: size_t, flags: c_int) -> c_int; // Added in `NetBSD` 10.0 pub fn timerfd_create(clockid: crate::clockid_t, flags: c_int) -> c_int; pub fn timerfd_gettime(fd: c_int, curr_value: *mut itimerspec) -> c_int; pub fn timerfd_settime( fd: c_int, flags: c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> c_int; } #[link(name = "rt")] extern "C" { pub fn aio_read(aiocbp: *mut aiocb) -> c_int; pub fn aio_write(aiocbp: *mut aiocb) -> c_int; pub fn aio_fsync(op: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_error(aiocbp: *const aiocb) -> c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ssize_t; #[link_name = "__aio_suspend50"] pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn aio_cancel(fd: c_int, aiocbp: *mut aiocb) -> c_int; pub fn lio_listio( mode: c_int, aiocb_list: *const *mut aiocb, nitems: c_int, sevp: *mut sigevent, ) -> c_int; } #[link(name = "util")] extern "C" { #[cfg_attr(target_os = "netbsd", link_name = "__getpwent_r50")] pub fn getpwent_r( pwd: *mut crate::passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::passwd, ) -> c_int; pub fn getgrent_r( grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn updwtmpx(file: *const c_char, ut: *const utmpx) -> c_int; pub fn getlastlogx(fname: *const c_char, uid: crate::uid_t, ll: *mut lastlogx) -> *mut lastlogx; pub fn updlastlogx(fname: *const c_char, uid: crate::uid_t, ll: *mut lastlogx) -> c_int; pub fn utmpxname(file: *const c_char) -> c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn getutmp(ux: *const utmpx, u: *mut utmp); pub fn getutmpx(u: *const utmp, ux: *mut utmpx); pub fn utpname(file: *const c_char) -> c_int; pub fn setutent(); pub fn endutent(); pub fn getutent() -> *mut utmp; pub fn efopen(p: *const c_char, m: *const c_char) -> crate::FILE; pub fn emalloc(n: size_t) -> *mut c_void; pub fn ecalloc(n: size_t, c: size_t) -> *mut c_void; pub fn erealloc(p: *mut c_void, n: size_t) -> *mut c_void; pub fn ereallocarr(p: *mut c_void, n: size_t, s: size_t); pub fn estrdup(s: *const c_char) -> *mut c_char; pub fn estrndup(s: *const c_char, len: size_t) -> *mut c_char; pub fn estrlcpy(dst: *mut c_char, src: *const c_char, len: size_t) -> size_t; pub fn estrlcat(dst: *mut c_char, src: *const c_char, len: size_t) -> size_t; pub fn estrtoi( nptr: *const c_char, base: c_int, lo: crate::intmax_t, hi: crate::intmax_t, ) -> crate::intmax_t; pub fn estrtou( nptr: *const c_char, base: c_int, lo: crate::uintmax_t, hi: crate::uintmax_t, ) -> crate::uintmax_t; pub fn easprintf(string: *mut *mut c_char, fmt: *const c_char, ...) -> c_int; pub fn evasprintf(string: *mut *mut c_char, fmt: *const c_char, ...) -> c_int; pub fn esetfunc( cb: Option, ) -> Option; pub fn secure_path(path: *const c_char) -> c_int; pub fn snprintb(buf: *mut c_char, buflen: size_t, fmt: *const c_char, val: u64) -> c_int; pub fn snprintb_m( buf: *mut c_char, buflen: size_t, fmt: *const c_char, val: u64, max: size_t, ) -> c_int; pub fn getbootfile() -> *const c_char; pub fn getbyteorder() -> c_int; pub fn getdiskrawname(buf: *mut c_char, buflen: size_t, name: *const c_char) -> *const c_char; pub fn getdiskcookedname( buf: *mut c_char, buflen: size_t, name: *const c_char, ) -> *const c_char; pub fn getfsspecname(buf: *mut c_char, buflen: size_t, spec: *const c_char) -> *const c_char; pub fn strpct( buf: *mut c_char, bufsiz: size_t, numerator: crate::uintmax_t, denominator: crate::uintmax_t, precision: size_t, ) -> *mut c_char; pub fn strspct( buf: *mut c_char, bufsiz: size_t, numerator: crate::intmax_t, denominator: crate::intmax_t, precision: size_t, ) -> *mut c_char; #[link_name = "__login50"] pub fn login(ut: *const utmp); #[link_name = "__loginx50"] pub fn loginx(ut: *const utmpx); pub fn logout(line: *const c_char); pub fn logoutx(line: *const c_char, status: c_int, tpe: c_int); pub fn logwtmp(line: *const c_char, name: *const c_char, host: *const c_char); pub fn logwtmpx( line: *const c_char, name: *const c_char, host: *const c_char, status: c_int, tpe: c_int, ); pub fn getxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn lgetxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn fgetxattr( filedes: c_int, name: *const c_char, value: *mut c_void, size: size_t, ) -> ssize_t; pub fn setxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, ) -> c_int; pub fn lsetxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, ) -> c_int; pub fn fsetxattr( filedes: c_int, name: *const c_char, value: *const c_void, size: size_t, flags: c_int, ) -> c_int; pub fn listxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; pub fn llistxattr(path: *const c_char, list: *mut c_char, size: size_t) -> ssize_t; pub fn flistxattr(filedes: c_int, list: *mut c_char, size: size_t) -> ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> c_int; pub fn lremovexattr(path: *const c_char, name: *const c_char) -> c_int; pub fn fremovexattr(fd: c_int, path: *const c_char, name: *const c_char) -> c_int; pub fn string_to_flags( string_p: *mut *mut c_char, setp: *mut c_ulong, clrp: *mut c_ulong, ) -> c_int; pub fn flags_to_string(flags: c_ulong, def: *const c_char) -> c_int; pub fn kinfo_getvmmap(pid: crate::pid_t, cntp: *mut size_t) -> *mut kinfo_vmentry; } #[link(name = "execinfo")] extern "C" { pub fn backtrace(addrlist: *mut *mut c_void, len: size_t) -> size_t; pub fn backtrace_symbols(addrlist: *const *mut c_void, len: size_t) -> *mut *mut c_char; pub fn backtrace_symbols_fd(addrlist: *const *mut c_void, len: size_t, fd: c_int) -> c_int; pub fn backtrace_symbols_fmt( addrlist: *const *mut c_void, len: size_t, fmt: *const c_char, ) -> *mut *mut c_char; pub fn backtrace_symbols_fd_fmt( addrlist: *const *mut c_void, len: size_t, fd: c_int, fmt: *const c_char, ) -> c_int; } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "sparc64")] { mod sparc64; pub use self::sparc64::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "mips")] { mod mips; pub use self::mips::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/netbsdlike/netbsd/arm.rs0000644000175000017500000000417615105742312020375 0ustar bdrungbdrunguse crate::prelude::*; use crate::PT_FIRSTMACH; pub type __cpu_simple_lock_nv_t = c_int; pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const PT_GETREGS: c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: c_int = PT_FIRSTMACH + 2; pub const PT_GETFPREGS: c_int = PT_FIRSTMACH + 3; pub const PT_SETFPREGS: c_int = PT_FIRSTMACH + 4; pub const _REG_R0: c_int = 0; pub const _REG_R1: c_int = 1; pub const _REG_R2: c_int = 2; pub const _REG_R3: c_int = 3; pub const _REG_R4: c_int = 4; pub const _REG_R5: c_int = 5; pub const _REG_R6: c_int = 6; pub const _REG_R7: c_int = 7; pub const _REG_R8: c_int = 8; pub const _REG_R9: c_int = 9; pub const _REG_R10: c_int = 10; pub const _REG_R11: c_int = 11; pub const _REG_R12: c_int = 12; pub const _REG_R13: c_int = 13; pub const _REG_R14: c_int = 14; pub const _REG_R15: c_int = 15; pub const _REG_CPSR: c_int = 16; pub const _REG_X0: c_int = 0; pub const _REG_X1: c_int = 1; pub const _REG_X2: c_int = 2; pub const _REG_X3: c_int = 3; pub const _REG_X4: c_int = 4; pub const _REG_X5: c_int = 5; pub const _REG_X6: c_int = 6; pub const _REG_X7: c_int = 7; pub const _REG_X8: c_int = 8; pub const _REG_X9: c_int = 9; pub const _REG_X10: c_int = 10; pub const _REG_X11: c_int = 11; pub const _REG_X12: c_int = 12; pub const _REG_X13: c_int = 13; pub const _REG_X14: c_int = 14; pub const _REG_X15: c_int = 15; pub const _REG_X16: c_int = 16; pub const _REG_X17: c_int = 17; pub const _REG_X18: c_int = 18; pub const _REG_X19: c_int = 19; pub const _REG_X20: c_int = 20; pub const _REG_X21: c_int = 21; pub const _REG_X22: c_int = 22; pub const _REG_X23: c_int = 23; pub const _REG_X24: c_int = 24; pub const _REG_X25: c_int = 25; pub const _REG_X26: c_int = 26; pub const _REG_X27: c_int = 27; pub const _REG_X28: c_int = 28; pub const _REG_X29: c_int = 29; pub const _REG_X30: c_int = 30; pub const _REG_X31: c_int = 31; pub const _REG_ELR: c_int = 32; pub const _REG_SPSR: c_int = 33; pub const _REG_TIPDR: c_int = 34; pub const _REG_RV: c_int = _REG_R0; pub const _REG_FP: c_int = _REG_R11; pub const _REG_LR: c_int = _REG_R13; pub const _REG_SP: c_int = _REG_R14; pub const _REG_PC: c_int = _REG_R15; libc/src/unix/bsd/netbsdlike/netbsd/riscv64.rs0000644000175000017500000000405415105742312021111 0ustar bdrungbdrunguse PT_FIRSTMACH; use crate::prelude::*; pub type __greg_t = u64; pub type __cpu_simple_lock_nv_t = c_int; pub type __gregset = [__greg_t; _NGREG]; pub type __fregset = [__freg; _NFREG]; s! { pub struct mcontext_t { pub __gregs: __gregset, pub __fregs: __fpregset, __spare: [crate::__greg_t; 7], } } s_no_extra_traits! { pub union __fpreg { pub u_u64: u64, pub u_d: c_double, } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const PT_GETREGS: c_int = PT_FIRSTMACH + 0; pub const PT_SETREGS: c_int = PT_FIRSTMACH + 1; pub const PT_GETFPREGS: c_int = PT_FIRSTMACH + 2; pub const PT_SETFPREGS: c_int = PT_FIRSTMACH + 3; pub const _NGREG: usize = 32; pub const _NFREG: usize = 33; pub const _REG_X1: c_int = 0; pub const _REG_X2: c_int = 1; pub const _REG_X3: c_int = 2; pub const _REG_X4: c_int = 3; pub const _REG_X5: c_int = 4; pub const _REG_X6: c_int = 5; pub const _REG_X7: c_int = 6; pub const _REG_X8: c_int = 7; pub const _REG_X9: c_int = 8; pub const _REG_X10: c_int = 9; pub const _REG_X11: c_int = 10; pub const _REG_X12: c_int = 11; pub const _REG_X13: c_int = 12; pub const _REG_X14: c_int = 13; pub const _REG_X15: c_int = 14; pub const _REG_X16: c_int = 15; pub const _REG_X17: c_int = 16; pub const _REG_X18: c_int = 17; pub const _REG_X19: c_int = 18; pub const _REG_X20: c_int = 19; pub const _REG_X21: c_int = 20; pub const _REG_X22: c_int = 21; pub const _REG_X23: c_int = 22; pub const _REG_X24: c_int = 23; pub const _REG_X25: c_int = 24; pub const _REG_X26: c_int = 25; pub const _REG_X27: c_int = 26; pub const _REG_X28: c_int = 27; pub const _REG_X29: c_int = 28; pub const _REG_X30: c_int = 29; pub const _REG_X31: c_int = 30; pub const _REG_PC: c_int = 31; pub const _REG_RA: c_int = _REG_X1; pub const _REG_SP: c_int = _REG_X2; pub const _REG_GP: c_int = _REG_X3; pub const _REG_TP: c_int = _REG_X4; pub const _REG_S0: c_int = _REG_X8; pub const _REG_RV: c_int = _REG_X10; pub const _REG_A0: c_int = _REG_X10; pub const _REG_F0: c_int = 0; pub const _REG_FPCSR: c_int = 32; libc/src/unix/bsd/netbsdlike/netbsd/powerpc.rs0000644000175000017500000000045715105742312021273 0ustar bdrungbdrunguse crate::prelude::*; use crate::PT_FIRSTMACH; pub type __cpu_simple_lock_nv_t = c_int; pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const PT_STEP: c_int = PT_FIRSTMACH + 0; pub const PT_GETREGS: c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: c_int = PT_FIRSTMACH + 2; libc/src/unix/bsd/netbsdlike/netbsd/x86.rs0000644000175000017500000000020715105742312020232 0ustar bdrungbdrunguse crate::prelude::*; pub type __cpu_simple_lock_nv_t = c_uchar; pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; libc/src/unix/bsd/netbsdlike/netbsd/x86_64.rs0000644000175000017500000000315415105742312020547 0ustar bdrungbdrunguse crate::prelude::*; use crate::PT_FIRSTMACH; pub type c___greg_t = u64; pub type __cpu_simple_lock_nv_t = c_uchar; s! { pub struct mcontext_t { pub __gregs: [c___greg_t; 26], pub _mc_tlsbase: c___greg_t, pub __fpregs: [[c_char; 32]; 16], } pub struct ucontext_t { pub uc_flags: c_uint, pub uc_link: *mut crate::ucontext_t, pub uc_sigmask: crate::sigset_t, pub uc_stack: crate::stack_t, pub uc_mcontext: crate::mcontext_t, } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const PT_STEP: c_int = PT_FIRSTMACH + 0; pub const PT_GETREGS: c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: c_int = PT_FIRSTMACH + 2; pub const PT_GETFPREGS: c_int = PT_FIRSTMACH + 3; pub const PT_SETFPREGS: c_int = PT_FIRSTMACH + 4; pub const _REG_RDI: c_int = 0; pub const _REG_RSI: c_int = 1; pub const _REG_RDX: c_int = 2; pub const _REG_RCX: c_int = 3; pub const _REG_R8: c_int = 4; pub const _REG_R9: c_int = 5; pub const _REG_R10: c_int = 6; pub const _REG_R11: c_int = 7; pub const _REG_R12: c_int = 8; pub const _REG_R13: c_int = 9; pub const _REG_R14: c_int = 10; pub const _REG_R15: c_int = 11; pub const _REG_RBP: c_int = 12; pub const _REG_RBX: c_int = 13; pub const _REG_RAX: c_int = 14; pub const _REG_GS: c_int = 15; pub const _REG_FS: c_int = 16; pub const _REG_ES: c_int = 17; pub const _REG_DS: c_int = 18; pub const _REG_TRAPNO: c_int = 19; pub const _REG_ERR: c_int = 20; pub const _REG_RIP: c_int = 21; pub const _REG_CS: c_int = 22; pub const _REG_RFLAGS: c_int = 23; pub const _REG_RSP: c_int = 24; pub const _REG_SS: c_int = 25; libc/src/unix/bsd/netbsdlike/netbsd/sparc64.rs0000644000175000017500000000025615105742312021073 0ustar bdrungbdrunguse crate::prelude::*; pub type __cpu_simple_lock_nv_t = c_uchar; // should be pub(crate), but that requires Rust 1.18.0 #[doc(hidden)] pub const _ALIGNBYTES: usize = 0xf; libc/src/unix/bsd/netbsdlike/netbsd/mips.rs0000644000175000017500000000055015105742312020556 0ustar bdrungbdrunguse crate::prelude::*; use crate::PT_FIRSTMACH; pub type __cpu_simple_lock_nv_t = c_int; pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const PT_GETREGS: c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: c_int = PT_FIRSTMACH + 2; pub const PT_GETFPREGS: c_int = PT_FIRSTMACH + 3; pub const PT_SETFPREGS: c_int = PT_FIRSTMACH + 4; libc/src/unix/bsd/netbsdlike/netbsd/aarch64.rs0000644000175000017500000000744115105742312021044 0ustar bdrungbdrunguse crate::prelude::*; use crate::PT_FIRSTMACH; pub type greg_t = u64; pub type __cpu_simple_lock_nv_t = c_uchar; s! { pub struct __fregset { pub __qregs: [__c_anonymous__freg; 32], pub __fpcr: u32, pub __fpsr: u32, } pub struct mcontext_t { pub __gregs: [crate::greg_t; 32], pub __fregs: __fregset, __spare: [crate::greg_t; 8], } pub struct ucontext_t { pub uc_flags: c_uint, pub uc_link: *mut ucontext_t, pub uc_sigmask: crate::sigset_t, pub uc_stack: crate::stack_t, pub uc_mcontext: mcontext_t, } } s_no_extra_traits! { #[repr(align(16))] pub union __c_anonymous__freg { pub __b8: [u8; 16], pub __h16: [u16; 8], pub __s32: [u32; 4], pub __d64: [u64; 2], pub __q128: [u128; 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __c_anonymous__freg { fn eq(&self, other: &__c_anonymous__freg) -> bool { unsafe { self.__b8 == other.__b8 || self.__h16 == other.__h16 || self.__s32 == other.__s32 || self.__d64 == other.__d64 || self.__q128 == other.__q128 } } } impl Eq for __c_anonymous__freg {} impl hash::Hash for __c_anonymous__freg { fn hash(&self, state: &mut H) { unsafe { self.__b8.hash(state); self.__h16.hash(state); self.__s32.hash(state); self.__d64.hash(state); self.__q128.hash(state); } } } } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const PT_GETREGS: c_int = PT_FIRSTMACH + 0; pub const PT_SETREGS: c_int = PT_FIRSTMACH + 1; pub const PT_GETFPREGS: c_int = PT_FIRSTMACH + 2; pub const PT_SETFPREGS: c_int = PT_FIRSTMACH + 3; pub const _REG_R0: c_int = 0; pub const _REG_R1: c_int = 1; pub const _REG_R2: c_int = 2; pub const _REG_R3: c_int = 3; pub const _REG_R4: c_int = 4; pub const _REG_R5: c_int = 5; pub const _REG_R6: c_int = 6; pub const _REG_R7: c_int = 7; pub const _REG_R8: c_int = 8; pub const _REG_R9: c_int = 9; pub const _REG_R10: c_int = 10; pub const _REG_R11: c_int = 11; pub const _REG_R12: c_int = 12; pub const _REG_R13: c_int = 13; pub const _REG_R14: c_int = 14; pub const _REG_R15: c_int = 15; pub const _REG_CPSR: c_int = 16; pub const _REG_X0: c_int = 0; pub const _REG_X1: c_int = 1; pub const _REG_X2: c_int = 2; pub const _REG_X3: c_int = 3; pub const _REG_X4: c_int = 4; pub const _REG_X5: c_int = 5; pub const _REG_X6: c_int = 6; pub const _REG_X7: c_int = 7; pub const _REG_X8: c_int = 8; pub const _REG_X9: c_int = 9; pub const _REG_X10: c_int = 10; pub const _REG_X11: c_int = 11; pub const _REG_X12: c_int = 12; pub const _REG_X13: c_int = 13; pub const _REG_X14: c_int = 14; pub const _REG_X15: c_int = 15; pub const _REG_X16: c_int = 16; pub const _REG_X17: c_int = 17; pub const _REG_X18: c_int = 18; pub const _REG_X19: c_int = 19; pub const _REG_X20: c_int = 20; pub const _REG_X21: c_int = 21; pub const _REG_X22: c_int = 22; pub const _REG_X23: c_int = 23; pub const _REG_X24: c_int = 24; pub const _REG_X25: c_int = 25; pub const _REG_X26: c_int = 26; pub const _REG_X27: c_int = 27; pub const _REG_X28: c_int = 28; pub const _REG_X29: c_int = 29; pub const _REG_X30: c_int = 30; pub const _REG_X31: c_int = 31; pub const _REG_ELR: c_int = 32; pub const _REG_SPSR: c_int = 33; pub const _REG_TIPDR: c_int = 34; pub const _REG_RV: c_int = _REG_X0; pub const _REG_FP: c_int = _REG_X29; pub const _REG_LR: c_int = _REG_X30; pub const _REG_SP: c_int = _REG_X31; pub const _REG_PC: c_int = _REG_ELR; libc/src/unix/bsd/freebsdlike/0000775000175000017500000000000015105742312016116 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/mod.rs0000644000175000017500000020202015105742312017235 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; pub type mode_t = u16; pub type pthread_attr_t = *mut c_void; pub type rlim_t = i64; pub type pthread_mutex_t = *mut c_void; pub type pthread_mutexattr_t = *mut c_void; pub type pthread_cond_t = *mut c_void; pub type pthread_condattr_t = *mut c_void; pub type pthread_rwlock_t = *mut c_void; pub type pthread_rwlockattr_t = *mut c_void; pub type pthread_key_t = c_int; pub type tcflag_t = c_uint; pub type speed_t = c_uint; pub type nl_item = c_int; pub type id_t = i64; pub type vm_size_t = crate::uintptr_t; pub type key_t = c_long; // elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Lword = u64; pub type Elf32_Off = u32; pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Lword = u64; pub type Elf64_Off = u64; pub type Elf64_Sword = i32; pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; pub type iconv_t = *mut c_void; // It's an alias over "struct __kvm_t". However, its fields aren't supposed to be used directly, // making the type definition system dependent. Better not bind it exactly. pub type kvm_t = c_void; pub type posix_spawnattr_t = *mut c_void; pub type posix_spawn_file_actions_t = *mut c_void; cfg_if! { if #[cfg(target_pointer_width = "64")] { type Elf_Addr = Elf64_Addr; type Elf_Half = Elf64_Half; type Elf_Phdr = Elf64_Phdr; } else if #[cfg(target_pointer_width = "32")] { type Elf_Addr = Elf32_Addr; type Elf_Half = Elf32_Half; type Elf_Phdr = Elf32_Phdr; } } // link.h #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { self.si_addr } pub unsafe fn si_value(&self) -> crate::sigval { self.si_value } pub unsafe fn si_pid(&self) -> crate::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> c_int { self.si_status } } s! { pub struct in_addr { pub s_addr: crate::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: c_int, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct glob_t { pub gl_pathc: size_t, pub gl_matchc: size_t, pub gl_offs: size_t, pub gl_flags: c_int, pub gl_pathv: *mut *mut c_char, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, __unused6: *mut c_void, __unused7: *mut c_void, __unused8: *mut c_void, } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: crate::socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut addrinfo, } pub struct sigset_t { bits: [u32; 4], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, pub si_pid: crate::pid_t, pub si_uid: crate::uid_t, pub si_status: c_int, pub si_addr: *mut c_void, pub si_value: crate::sigval, _pad1: c_long, _pad2: [c_int; 7], } pub struct sigaction { pub sa_sigaction: crate::sighandler_t, pub sa_flags: c_int, pub sa_mask: sigset_t, } pub struct sched_param { pub sched_priority: c_int, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_cc: [crate::cc_t; crate::NCCS], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } pub struct flock { pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, pub l_type: c_short, pub l_whence: c_short, #[cfg(not(target_os = "dragonfly"))] pub l_sysid: c_int, } pub struct sf_hdtr { pub headers: *mut crate::iovec, pub hdr_cnt: c_int, pub trailers: *mut crate::iovec, pub trl_cnt: c_int, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_n_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct cmsgcred { pub cmcred_pid: crate::pid_t, pub cmcred_uid: crate::uid_t, pub cmcred_euid: crate::uid_t, pub cmcred_gid: crate::gid_t, pub cmcred_ngroups: c_short, pub cmcred_groups: [crate::gid_t; CMGROUP_MAX], } pub struct rtprio { pub type_: c_ushort, pub prio: c_ushort, } pub struct in6_pktinfo { pub ipi6_addr: crate::in6_addr, pub ipi6_ifindex: c_uint, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct timex { pub modes: c_uint, pub offset: c_long, pub freq: c_long, pub maxerror: c_long, pub esterror: c_long, pub status: c_int, pub constant: c_long, pub precision: c_long, pub tolerance: c_long, pub ppsfreq: c_long, pub jitter: c_long, pub shift: c_int, pub stabil: c_long, pub jitcnt: c_long, pub calcnt: c_long, pub errcnt: c_long, pub stbcnt: c_long, } pub struct ntptimeval { pub time: crate::timespec, pub maxerror: c_long, pub esterror: c_long, pub tai: c_long, pub time_state: c_int, } pub struct accept_filter_arg { pub af_name: [c_char; 16], af_arg: [c_char; 256 - 16], } pub struct ptrace_io_desc { pub piod_op: c_int, pub piod_offs: *mut c_void, pub piod_addr: *mut c_void, pub piod_len: size_t, } // bpf.h pub struct bpf_program { pub bf_len: c_uint, pub bf_insns: *mut bpf_insn, } pub struct bpf_stat { pub bs_recv: c_uint, pub bs_drop: c_uint, } pub struct bpf_version { pub bv_major: c_ushort, pub bv_minor: c_ushort, } pub struct bpf_hdr { pub bh_tstamp: crate::timeval, pub bh_caplen: u32, pub bh_datalen: u32, pub bh_hdrlen: c_ushort, } pub struct bpf_insn { pub code: c_ushort, pub jt: c_uchar, pub jf: c_uchar, pub k: u32, } pub struct bpf_dltlist { bfl_len: c_uint, bfl_list: *mut c_uint, } // elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } // link.h pub struct dl_phdr_info { pub dlpi_addr: Elf_Addr, pub dlpi_name: *const c_char, pub dlpi_phdr: *const Elf_Phdr, pub dlpi_phnum: Elf_Half, pub dlpi_adds: c_ulonglong, pub dlpi_subs: c_ulonglong, pub dlpi_tls_modid: usize, pub dlpi_tls_data: *mut c_void, } pub struct ipc_perm { pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub uid: crate::uid_t, pub gid: crate::gid_t, pub mode: crate::mode_t, pub seq: c_ushort, pub key: crate::key_t, } pub struct eui64 { pub octet: [u8; EUI64_LEN], } } s_no_extra_traits! { pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: crate::sa_family_t, __ss_pad1: [u8; 6], __ss_align: i64, __ss_pad2: [u8; 112], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self.__ss_pad1 == other.__ss_pad1 && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_align", &self.__ss_align) // FIXME(debug): .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } } } // Non-public helper constant const SIZEOF_LONG: usize = mem::size_of::(); #[deprecated( since = "0.2.64", note = "Can vary at runtime. Use sysconf(3) instead" )] pub const AIO_LISTIO_MAX: c_int = 16; pub const AIO_CANCELED: c_int = 1; pub const AIO_NOTCANCELED: c_int = 2; pub const AIO_ALLDONE: c_int = 3; pub const LIO_NOP: c_int = 0; pub const LIO_WRITE: c_int = 1; pub const LIO_READ: c_int = 2; pub const LIO_WAIT: c_int = 1; pub const LIO_NOWAIT: c_int = 0; pub const SIGEV_NONE: c_int = 0; pub const SIGEV_SIGNAL: c_int = 1; pub const SIGEV_THREAD: c_int = 2; pub const SIGEV_KEVENT: c_int = 3; pub const CODESET: crate::nl_item = 0; pub const D_T_FMT: crate::nl_item = 1; pub const D_FMT: crate::nl_item = 2; pub const T_FMT: crate::nl_item = 3; pub const T_FMT_AMPM: crate::nl_item = 4; pub const AM_STR: crate::nl_item = 5; pub const PM_STR: crate::nl_item = 6; pub const DAY_1: crate::nl_item = 7; pub const DAY_2: crate::nl_item = 8; pub const DAY_3: crate::nl_item = 9; pub const DAY_4: crate::nl_item = 10; pub const DAY_5: crate::nl_item = 11; pub const DAY_6: crate::nl_item = 12; pub const DAY_7: crate::nl_item = 13; pub const ABDAY_1: crate::nl_item = 14; pub const ABDAY_2: crate::nl_item = 15; pub const ABDAY_3: crate::nl_item = 16; pub const ABDAY_4: crate::nl_item = 17; pub const ABDAY_5: crate::nl_item = 18; pub const ABDAY_6: crate::nl_item = 19; pub const ABDAY_7: crate::nl_item = 20; pub const MON_1: crate::nl_item = 21; pub const MON_2: crate::nl_item = 22; pub const MON_3: crate::nl_item = 23; pub const MON_4: crate::nl_item = 24; pub const MON_5: crate::nl_item = 25; pub const MON_6: crate::nl_item = 26; pub const MON_7: crate::nl_item = 27; pub const MON_8: crate::nl_item = 28; pub const MON_9: crate::nl_item = 29; pub const MON_10: crate::nl_item = 30; pub const MON_11: crate::nl_item = 31; pub const MON_12: crate::nl_item = 32; pub const ABMON_1: crate::nl_item = 33; pub const ABMON_2: crate::nl_item = 34; pub const ABMON_3: crate::nl_item = 35; pub const ABMON_4: crate::nl_item = 36; pub const ABMON_5: crate::nl_item = 37; pub const ABMON_6: crate::nl_item = 38; pub const ABMON_7: crate::nl_item = 39; pub const ABMON_8: crate::nl_item = 40; pub const ABMON_9: crate::nl_item = 41; pub const ABMON_10: crate::nl_item = 42; pub const ABMON_11: crate::nl_item = 43; pub const ABMON_12: crate::nl_item = 44; pub const ERA: crate::nl_item = 45; pub const ERA_D_FMT: crate::nl_item = 46; pub const ERA_D_T_FMT: crate::nl_item = 47; pub const ERA_T_FMT: crate::nl_item = 48; pub const ALT_DIGITS: crate::nl_item = 49; pub const RADIXCHAR: crate::nl_item = 50; pub const THOUSEP: crate::nl_item = 51; pub const YESEXPR: crate::nl_item = 52; pub const NOEXPR: crate::nl_item = 53; pub const YESSTR: crate::nl_item = 54; pub const NOSTR: crate::nl_item = 55; pub const CRNCYSTR: crate::nl_item = 56; pub const D_MD_ORDER: crate::nl_item = 57; pub const ALTMON_1: crate::nl_item = 58; pub const ALTMON_2: crate::nl_item = 59; pub const ALTMON_3: crate::nl_item = 60; pub const ALTMON_4: crate::nl_item = 61; pub const ALTMON_5: crate::nl_item = 62; pub const ALTMON_6: crate::nl_item = 63; pub const ALTMON_7: crate::nl_item = 64; pub const ALTMON_8: crate::nl_item = 65; pub const ALTMON_9: crate::nl_item = 66; pub const ALTMON_10: crate::nl_item = 67; pub const ALTMON_11: crate::nl_item = 68; pub const ALTMON_12: crate::nl_item = 69; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const SEEK_DATA: c_int = 3; pub const SEEK_HOLE: c_int = 4; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const BUFSIZ: c_uint = 1024; pub const FOPEN_MAX: c_uint = 20; pub const FILENAME_MAX: c_uint = 1024; pub const L_tmpnam: c_uint = 1024; pub const TMP_MAX: c_uint = 308915776; pub const O_NOCTTY: c_int = 32768; pub const O_DIRECT: c_int = 0x00010000; pub const S_IFIFO: mode_t = 0o1_0000; pub const S_IFCHR: mode_t = 0o2_0000; pub const S_IFBLK: mode_t = 0o6_0000; pub const S_IFDIR: mode_t = 0o4_0000; pub const S_IFREG: mode_t = 0o10_0000; pub const S_IFLNK: mode_t = 0o12_0000; pub const S_IFSOCK: mode_t = 0o14_0000; pub const S_IFMT: mode_t = 0o17_0000; pub const S_IEXEC: mode_t = 0o0100; pub const S_IWRITE: mode_t = 0o0200; pub const S_IREAD: mode_t = 0o0400; pub const S_IRWXU: mode_t = 0o0700; pub const S_IXUSR: mode_t = 0o0100; pub const S_IWUSR: mode_t = 0o0200; pub const S_IRUSR: mode_t = 0o0400; pub const S_IRWXG: mode_t = 0o0070; pub const S_IXGRP: mode_t = 0o0010; pub const S_IWGRP: mode_t = 0o0020; pub const S_IRGRP: mode_t = 0o0040; pub const S_IRWXO: mode_t = 0o0007; pub const S_IXOTH: mode_t = 0o0001; pub const S_IWOTH: mode_t = 0o0002; pub const S_IROTH: mode_t = 0o0004; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const F_DUPFD_CLOEXEC: c_int = 17; pub const F_DUP2FD: c_int = 10; pub const F_DUP2FD_CLOEXEC: c_int = 18; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSEGV: c_int = 11; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const MAP_FILE: c_int = 0x0000; pub const MAP_SHARED: c_int = 0x0001; pub const MAP_PRIVATE: c_int = 0x0002; pub const MAP_FIXED: c_int = 0x0010; pub const MAP_ANON: c_int = 0x1000; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MNT_EXPUBLIC: c_int = 0x20000000; pub const MNT_NOATIME: c_int = 0x10000000; pub const MNT_NOCLUSTERR: c_int = 0x40000000; pub const MNT_NOCLUSTERW: c_int = 0x80000000; pub const MNT_NOSYMFOLLOW: c_int = 0x00400000; pub const MNT_SOFTDEP: c_int = 0x00200000; pub const MNT_SUIDDIR: c_int = 0x00100000; pub const MNT_EXRDONLY: c_int = 0x00000080; pub const MNT_DEFEXPORTED: c_int = 0x00000200; pub const MNT_EXPORTANON: c_int = 0x00000400; pub const MNT_EXKERB: c_int = 0x00000800; pub const MNT_DELEXPORT: c_int = 0x00020000; pub const MS_SYNC: c_int = 0x0000; pub const MS_ASYNC: c_int = 0x0001; pub const MS_INVALIDATE: c_int = 0x0002; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EDEADLK: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EAGAIN: c_int = 35; pub const EWOULDBLOCK: c_int = 35; pub const EINPROGRESS: c_int = 36; pub const EALREADY: c_int = 37; pub const ENOTSOCK: c_int = 38; pub const EDESTADDRREQ: c_int = 39; pub const EMSGSIZE: c_int = 40; pub const EPROTOTYPE: c_int = 41; pub const ENOPROTOOPT: c_int = 42; pub const EPROTONOSUPPORT: c_int = 43; pub const ESOCKTNOSUPPORT: c_int = 44; pub const EOPNOTSUPP: c_int = 45; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 46; pub const EAFNOSUPPORT: c_int = 47; pub const EADDRINUSE: c_int = 48; pub const EADDRNOTAVAIL: c_int = 49; pub const ENETDOWN: c_int = 50; pub const ENETUNREACH: c_int = 51; pub const ENETRESET: c_int = 52; pub const ECONNABORTED: c_int = 53; pub const ECONNRESET: c_int = 54; pub const ENOBUFS: c_int = 55; pub const EISCONN: c_int = 56; pub const ENOTCONN: c_int = 57; pub const ESHUTDOWN: c_int = 58; pub const ETOOMANYREFS: c_int = 59; pub const ETIMEDOUT: c_int = 60; pub const ECONNREFUSED: c_int = 61; pub const ELOOP: c_int = 62; pub const ENAMETOOLONG: c_int = 63; pub const EHOSTDOWN: c_int = 64; pub const EHOSTUNREACH: c_int = 65; pub const ENOTEMPTY: c_int = 66; pub const EPROCLIM: c_int = 67; pub const EUSERS: c_int = 68; pub const EDQUOT: c_int = 69; pub const ESTALE: c_int = 70; pub const EREMOTE: c_int = 71; pub const EBADRPC: c_int = 72; pub const ERPCMISMATCH: c_int = 73; pub const EPROGUNAVAIL: c_int = 74; pub const EPROGMISMATCH: c_int = 75; pub const EPROCUNAVAIL: c_int = 76; pub const ENOLCK: c_int = 77; pub const ENOSYS: c_int = 78; pub const EFTYPE: c_int = 79; pub const EAUTH: c_int = 80; pub const ENEEDAUTH: c_int = 81; pub const EIDRM: c_int = 82; pub const ENOMSG: c_int = 83; pub const EOVERFLOW: c_int = 84; pub const ECANCELED: c_int = 85; pub const EILSEQ: c_int = 86; pub const ENOATTR: c_int = 87; pub const EDOOFUS: c_int = 88; pub const EBADMSG: c_int = 89; pub const EMULTIHOP: c_int = 90; pub const ENOLINK: c_int = 91; pub const EPROTO: c_int = 92; pub const POLLSTANDARD: c_short = crate::POLLIN | crate::POLLPRI | crate::POLLOUT | crate::POLLRDNORM | crate::POLLRDBAND | crate::POLLWRBAND | crate::POLLERR | crate::POLLHUP | crate::POLLNVAL; pub const AI_PASSIVE: c_int = 0x00000001; pub const AI_CANONNAME: c_int = 0x00000002; pub const AI_NUMERICHOST: c_int = 0x00000004; pub const AI_NUMERICSERV: c_int = 0x00000008; pub const AI_ALL: c_int = 0x00000100; pub const AI_ADDRCONFIG: c_int = 0x00000400; pub const AI_V4MAPPED: c_int = 0x00000800; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_MEMORY: c_int = 6; pub const EAI_NONAME: c_int = 8; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 14; pub const F_DUPFD: c_int = 0; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const GLOB_APPEND: c_int = 0x0001; pub const GLOB_DOOFFS: c_int = 0x0002; pub const GLOB_ERR: c_int = 0x0004; pub const GLOB_MARK: c_int = 0x0008; pub const GLOB_NOCHECK: c_int = 0x0010; pub const GLOB_NOSORT: c_int = 0x0020; pub const GLOB_NOESCAPE: c_int = 0x2000; pub const GLOB_NOSPACE: c_int = -1; pub const GLOB_ABORTED: c_int = -2; pub const GLOB_NOMATCH: c_int = -3; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 1; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1; pub const PTHREAD_PROCESS_PRIVATE: c_int = 0; pub const PTHREAD_PROCESS_SHARED: c_int = 1; pub const PTHREAD_CREATE_JOINABLE: c_int = 0; pub const PTHREAD_CREATE_DETACHED: c_int = 1; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_RSS: c_int = 5; pub const RLIMIT_MEMLOCK: c_int = 6; pub const RLIMIT_NPROC: c_int = 7; pub const RLIMIT_NOFILE: c_int = 8; pub const RLIMIT_SBSIZE: c_int = 9; pub const RLIMIT_VMEM: c_int = 10; pub const RLIMIT_AS: c_int = RLIMIT_VMEM; pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; pub const RUSAGE_SELF: c_int = 0; pub const RUSAGE_CHILDREN: c_int = -1; pub const CLOCK_REALTIME: crate::clockid_t = 0; pub const CLOCK_VIRTUAL: crate::clockid_t = 1; pub const CLOCK_PROF: crate::clockid_t = 2; pub const CLOCK_MONOTONIC: crate::clockid_t = 4; pub const CLOCK_UPTIME: crate::clockid_t = 5; pub const CLOCK_UPTIME_PRECISE: crate::clockid_t = 7; pub const CLOCK_UPTIME_FAST: crate::clockid_t = 8; pub const CLOCK_REALTIME_PRECISE: crate::clockid_t = 9; pub const CLOCK_REALTIME_FAST: crate::clockid_t = 10; pub const CLOCK_MONOTONIC_PRECISE: crate::clockid_t = 11; pub const CLOCK_MONOTONIC_FAST: crate::clockid_t = 12; pub const CLOCK_SECOND: crate::clockid_t = 13; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 14; pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 15; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const MADV_FREE: c_int = 5; pub const MADV_NOSYNC: c_int = 6; pub const MADV_AUTOSYNC: c_int = 7; pub const MADV_NOCORE: c_int = 8; pub const MADV_CORE: c_int = 9; pub const MINCORE_INCORE: c_int = 0x1; pub const MINCORE_REFERENCED: c_int = 0x2; pub const MINCORE_MODIFIED: c_int = 0x4; pub const MINCORE_REFERENCED_OTHER: c_int = 0x8; pub const MINCORE_MODIFIED_OTHER: c_int = 0x10; pub const AF_UNSPEC: c_int = 0; pub const AF_LOCAL: c_int = 1; pub const AF_UNIX: c_int = AF_LOCAL; pub const AF_INET: c_int = 2; pub const AF_IMPLINK: c_int = 3; pub const AF_PUP: c_int = 4; pub const AF_CHAOS: c_int = 5; pub const AF_NETBIOS: c_int = 6; pub const AF_ISO: c_int = 7; pub const AF_OSI: c_int = AF_ISO; pub const AF_ECMA: c_int = 8; pub const AF_DATAKIT: c_int = 9; pub const AF_CCITT: c_int = 10; pub const AF_SNA: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_DLI: c_int = 13; pub const AF_LAT: c_int = 14; pub const AF_HYLINK: c_int = 15; pub const AF_APPLETALK: c_int = 16; pub const AF_ROUTE: c_int = 17; pub const AF_LINK: c_int = 18; pub const pseudo_AF_XTP: c_int = 19; pub const AF_COIP: c_int = 20; pub const AF_CNT: c_int = 21; pub const pseudo_AF_RTIP: c_int = 22; pub const AF_IPX: c_int = 23; pub const AF_SIP: c_int = 24; pub const pseudo_AF_PIP: c_int = 25; pub const AF_ISDN: c_int = 26; pub const AF_E164: c_int = AF_ISDN; pub const pseudo_AF_KEY: c_int = 27; pub const AF_INET6: c_int = 28; pub const AF_NATM: c_int = 29; pub const AF_ATM: c_int = 30; pub const pseudo_AF_HDRCMPLT: c_int = 31; pub const AF_NETGRAPH: c_int = 32; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_LOCAL: c_int = AF_LOCAL; pub const PF_UNIX: c_int = PF_LOCAL; pub const PF_INET: c_int = AF_INET; pub const PF_IMPLINK: c_int = AF_IMPLINK; pub const PF_PUP: c_int = AF_PUP; pub const PF_CHAOS: c_int = AF_CHAOS; pub const PF_NETBIOS: c_int = AF_NETBIOS; pub const PF_ISO: c_int = AF_ISO; pub const PF_OSI: c_int = AF_ISO; pub const PF_ECMA: c_int = AF_ECMA; pub const PF_DATAKIT: c_int = AF_DATAKIT; pub const PF_CCITT: c_int = AF_CCITT; pub const PF_SNA: c_int = AF_SNA; pub const PF_DECnet: c_int = AF_DECnet; pub const PF_DLI: c_int = AF_DLI; pub const PF_LAT: c_int = AF_LAT; pub const PF_HYLINK: c_int = AF_HYLINK; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_LINK: c_int = AF_LINK; pub const PF_XTP: c_int = pseudo_AF_XTP; pub const PF_COIP: c_int = AF_COIP; pub const PF_CNT: c_int = AF_CNT; pub const PF_SIP: c_int = AF_SIP; pub const PF_IPX: c_int = AF_IPX; pub const PF_RTIP: c_int = pseudo_AF_RTIP; pub const PF_PIP: c_int = pseudo_AF_PIP; pub const PF_ISDN: c_int = AF_ISDN; pub const PF_KEY: c_int = pseudo_AF_KEY; pub const PF_INET6: c_int = AF_INET6; pub const PF_NATM: c_int = AF_NATM; pub const PF_ATM: c_int = AF_ATM; pub const PF_NETGRAPH: c_int = AF_NETGRAPH; pub const PIOD_READ_D: c_int = 1; pub const PIOD_WRITE_D: c_int = 2; pub const PIOD_READ_I: c_int = 3; pub const PIOD_WRITE_I: c_int = 4; pub const PT_TRACE_ME: c_int = 0; pub const PT_READ_I: c_int = 1; pub const PT_READ_D: c_int = 2; pub const PT_WRITE_I: c_int = 4; pub const PT_WRITE_D: c_int = 5; pub const PT_CONTINUE: c_int = 7; pub const PT_KILL: c_int = 8; pub const PT_STEP: c_int = 9; pub const PT_ATTACH: c_int = 10; pub const PT_DETACH: c_int = 11; pub const PT_IO: c_int = 12; pub const SOMAXCONN: c_int = 128; pub const MSG_OOB: c_int = 0x00000001; pub const MSG_PEEK: c_int = 0x00000002; pub const MSG_DONTROUTE: c_int = 0x00000004; pub const MSG_EOR: c_int = 0x00000008; pub const MSG_TRUNC: c_int = 0x00000010; pub const MSG_CTRUNC: c_int = 0x00000020; pub const MSG_WAITALL: c_int = 0x00000040; pub const MSG_DONTWAIT: c_int = 0x00000080; pub const MSG_EOF: c_int = 0x00000100; pub const SCM_TIMESTAMP: c_int = 0x02; pub const SCM_CREDS: c_int = 0x03; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_SEQPACKET: c_int = 5; pub const SOCK_CLOEXEC: c_int = 0x10000000; pub const SOCK_NONBLOCK: c_int = 0x20000000; pub const SOCK_MAXADDRLEN: c_int = 255; pub const IP_TTL: c_int = 4; pub const IP_HDRINCL: c_int = 2; pub const IP_RECVDSTADDR: c_int = 7; pub const IP_SENDSRCADDR: c_int = IP_RECVDSTADDR; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IP_RECVIF: c_int = 20; pub const IP_RECVTTL: c_int = 65; pub const IPV6_RECVHOPLIMIT: c_int = 37; pub const IPV6_JOIN_GROUP: c_int = 12; pub const IPV6_LEAVE_GROUP: c_int = 13; pub const IPV6_CHECKSUM: c_int = 26; pub const IPV6_RECVPKTINFO: c_int = 36; pub const IPV6_PKTINFO: c_int = 46; pub const IPV6_HOPLIMIT: c_int = 47; pub const IPV6_RECVTCLASS: c_int = 57; pub const IPV6_TCLASS: c_int = 61; pub const IP_ADD_SOURCE_MEMBERSHIP: c_int = 70; pub const IP_DROP_SOURCE_MEMBERSHIP: c_int = 71; pub const IP_BLOCK_SOURCE: c_int = 72; pub const IP_UNBLOCK_SOURCE: c_int = 73; pub const TCP_NOPUSH: c_int = 4; pub const TCP_NOOPT: c_int = 8; pub const TCP_KEEPIDLE: c_int = 256; pub const TCP_KEEPINTVL: c_int = 512; pub const TCP_KEEPCNT: c_int = 1024; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_DEBUG: c_int = 0x01; pub const SO_ACCEPTCONN: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_USELOOPBACK: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_TIMESTAMP: c_int = 0x0400; pub const SO_NOSIGPIPE: c_int = 0x0800; pub const SO_ACCEPTFILTER: c_int = 0x1000; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVLOWAT: c_int = 0x1004; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; pub const SO_TYPE: c_int = 0x1008; pub const LOCAL_PEERCRED: c_int = 1; // net/route.h pub const RTF_XRESOLVE: c_int = 0x200; pub const RTF_LLINFO: c_int = 0x400; pub const RTF_PROTO3: c_int = 0x40000; pub const RTF_PINNED: c_int = 0x100000; pub const RTF_LOCAL: c_int = 0x200000; pub const RTF_BROADCAST: c_int = 0x400000; pub const RTF_MULTICAST: c_int = 0x800000; pub const RTM_LOCK: c_int = 0x8; pub const RTM_RESOLVE: c_int = 0xb; pub const RTM_NEWADDR: c_int = 0xc; pub const RTM_DELADDR: c_int = 0xd; pub const RTM_IFINFO: c_int = 0xe; pub const RTM_NEWMADDR: c_int = 0xf; pub const RTM_DELMADDR: c_int = 0x10; pub const RTM_IFANNOUNCE: c_int = 0x11; pub const RTM_IEEE80211: c_int = 0x12; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; pub const MAP_COPY: c_int = 0x0002; #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Removed in FreeBSD 11, unused in DragonFlyBSD" )] pub const MAP_RENAME: c_int = 0x0020; #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Removed in FreeBSD 11, unused in DragonFlyBSD" )] pub const MAP_NORESERVE: c_int = 0x0040; pub const MAP_HASSEMAPHORE: c_int = 0x0200; pub const MAP_STACK: c_int = 0x0400; pub const MAP_NOSYNC: c_int = 0x0800; pub const MAP_NOCORE: c_int = 0x020000; pub const IPPROTO_RAW: c_int = 255; pub const _PC_LINK_MAX: c_int = 1; pub const _PC_MAX_CANON: c_int = 2; pub const _PC_MAX_INPUT: c_int = 3; pub const _PC_NAME_MAX: c_int = 4; pub const _PC_PATH_MAX: c_int = 5; pub const _PC_PIPE_BUF: c_int = 6; pub const _PC_CHOWN_RESTRICTED: c_int = 7; pub const _PC_NO_TRUNC: c_int = 8; pub const _PC_VDISABLE: c_int = 9; pub const _PC_ALLOC_SIZE_MIN: c_int = 10; pub const _PC_FILESIZEBITS: c_int = 12; pub const _PC_REC_INCR_XFER_SIZE: c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: c_int = 16; pub const _PC_REC_XFER_ALIGN: c_int = 17; pub const _PC_SYMLINK_MAX: c_int = 18; pub const _PC_MIN_HOLE_SIZE: c_int = 21; pub const _PC_ASYNC_IO: c_int = 53; pub const _PC_PRIO_IO: c_int = 54; pub const _PC_SYNC_IO: c_int = 55; pub const _PC_ACL_EXTENDED: c_int = 59; pub const _PC_ACL_PATH_MAX: c_int = 60; pub const _PC_CAP_PRESENT: c_int = 61; pub const _PC_INF_PRESENT: c_int = 62; pub const _PC_MAC_PRESENT: c_int = 63; pub const _SC_ARG_MAX: c_int = 1; pub const _SC_CHILD_MAX: c_int = 2; pub const _SC_CLK_TCK: c_int = 3; pub const _SC_NGROUPS_MAX: c_int = 4; pub const _SC_OPEN_MAX: c_int = 5; pub const _SC_JOB_CONTROL: c_int = 6; pub const _SC_SAVED_IDS: c_int = 7; pub const _SC_VERSION: c_int = 8; pub const _SC_BC_BASE_MAX: c_int = 9; pub const _SC_BC_DIM_MAX: c_int = 10; pub const _SC_BC_SCALE_MAX: c_int = 11; pub const _SC_BC_STRING_MAX: c_int = 12; pub const _SC_COLL_WEIGHTS_MAX: c_int = 13; pub const _SC_EXPR_NEST_MAX: c_int = 14; pub const _SC_LINE_MAX: c_int = 15; pub const _SC_RE_DUP_MAX: c_int = 16; pub const _SC_2_VERSION: c_int = 17; pub const _SC_2_C_BIND: c_int = 18; pub const _SC_2_C_DEV: c_int = 19; pub const _SC_2_CHAR_TERM: c_int = 20; pub const _SC_2_FORT_DEV: c_int = 21; pub const _SC_2_FORT_RUN: c_int = 22; pub const _SC_2_LOCALEDEF: c_int = 23; pub const _SC_2_SW_DEV: c_int = 24; pub const _SC_2_UPE: c_int = 25; pub const _SC_STREAM_MAX: c_int = 26; pub const _SC_TZNAME_MAX: c_int = 27; pub const _SC_ASYNCHRONOUS_IO: c_int = 28; pub const _SC_MAPPED_FILES: c_int = 29; pub const _SC_MEMLOCK: c_int = 30; pub const _SC_MEMLOCK_RANGE: c_int = 31; pub const _SC_MEMORY_PROTECTION: c_int = 32; pub const _SC_MESSAGE_PASSING: c_int = 33; pub const _SC_PRIORITIZED_IO: c_int = 34; pub const _SC_PRIORITY_SCHEDULING: c_int = 35; pub const _SC_REALTIME_SIGNALS: c_int = 36; pub const _SC_SEMAPHORES: c_int = 37; pub const _SC_FSYNC: c_int = 38; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 39; pub const _SC_SYNCHRONIZED_IO: c_int = 40; pub const _SC_TIMERS: c_int = 41; pub const _SC_AIO_LISTIO_MAX: c_int = 42; pub const _SC_AIO_MAX: c_int = 43; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44; pub const _SC_DELAYTIMER_MAX: c_int = 45; pub const _SC_MQ_OPEN_MAX: c_int = 46; pub const _SC_PAGESIZE: c_int = 47; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_RTSIG_MAX: c_int = 48; pub const _SC_SEM_NSEMS_MAX: c_int = 49; pub const _SC_SEM_VALUE_MAX: c_int = 50; pub const _SC_SIGQUEUE_MAX: c_int = 51; pub const _SC_TIMER_MAX: c_int = 52; pub const _SC_IOV_MAX: c_int = 56; pub const _SC_NPROCESSORS_CONF: c_int = 57; pub const _SC_2_PBS: c_int = 59; pub const _SC_2_PBS_ACCOUNTING: c_int = 60; pub const _SC_2_PBS_CHECKPOINT: c_int = 61; pub const _SC_2_PBS_LOCATE: c_int = 62; pub const _SC_2_PBS_MESSAGE: c_int = 63; pub const _SC_2_PBS_TRACK: c_int = 64; pub const _SC_ADVISORY_INFO: c_int = 65; pub const _SC_BARRIERS: c_int = 66; pub const _SC_CLOCK_SELECTION: c_int = 67; pub const _SC_CPUTIME: c_int = 68; pub const _SC_FILE_LOCKING: c_int = 69; pub const _SC_NPROCESSORS_ONLN: c_int = 58; pub const _SC_GETGR_R_SIZE_MAX: c_int = 70; pub const _SC_GETPW_R_SIZE_MAX: c_int = 71; pub const _SC_HOST_NAME_MAX: c_int = 72; pub const _SC_LOGIN_NAME_MAX: c_int = 73; pub const _SC_MONOTONIC_CLOCK: c_int = 74; pub const _SC_MQ_PRIO_MAX: c_int = 75; pub const _SC_READER_WRITER_LOCKS: c_int = 76; pub const _SC_REGEXP: c_int = 77; pub const _SC_SHELL: c_int = 78; pub const _SC_SPAWN: c_int = 79; pub const _SC_SPIN_LOCKS: c_int = 80; pub const _SC_SPORADIC_SERVER: c_int = 81; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 82; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 83; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 85; pub const _SC_THREAD_KEYS_MAX: c_int = 86; pub const _SC_THREAD_PRIO_INHERIT: c_int = 87; pub const _SC_THREAD_PRIO_PROTECT: c_int = 88; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 89; pub const _SC_THREAD_PROCESS_SHARED: c_int = 90; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 91; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 92; pub const _SC_THREAD_STACK_MIN: c_int = 93; pub const _SC_THREAD_THREADS_MAX: c_int = 94; pub const _SC_TIMEOUTS: c_int = 95; pub const _SC_THREADS: c_int = 96; pub const _SC_TRACE: c_int = 97; pub const _SC_TRACE_EVENT_FILTER: c_int = 98; pub const _SC_TRACE_INHERIT: c_int = 99; pub const _SC_TRACE_LOG: c_int = 100; pub const _SC_TTY_NAME_MAX: c_int = 101; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 102; pub const _SC_V6_ILP32_OFF32: c_int = 103; pub const _SC_V6_ILP32_OFFBIG: c_int = 104; pub const _SC_V6_LP64_OFF64: c_int = 105; pub const _SC_V6_LPBIG_OFFBIG: c_int = 106; pub const _SC_ATEXIT_MAX: c_int = 107; pub const _SC_XOPEN_CRYPT: c_int = 108; pub const _SC_XOPEN_ENH_I18N: c_int = 109; pub const _SC_XOPEN_LEGACY: c_int = 110; pub const _SC_XOPEN_REALTIME: c_int = 111; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 112; pub const _SC_XOPEN_SHM: c_int = 113; pub const _SC_XOPEN_STREAMS: c_int = 114; pub const _SC_XOPEN_UNIX: c_int = 115; pub const _SC_XOPEN_VERSION: c_int = 116; pub const _SC_XOPEN_XCU_VERSION: c_int = 117; pub const _SC_IPV6: c_int = 118; pub const _SC_RAW_SOCKETS: c_int = 119; pub const _SC_SYMLOOP_MAX: c_int = 120; pub const _SC_PHYS_PAGES: c_int = 121; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = 0 as *mut _; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = 0 as *mut _; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = 0 as *mut _; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 2; pub const PTHREAD_MUTEX_NORMAL: c_int = 3; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_ERRORCHECK; pub const SCHED_FIFO: c_int = 1; pub const SCHED_OTHER: c_int = 2; pub const SCHED_RR: c_int = 3; pub const FD_SETSIZE: usize = 1024; pub const ST_NOSUID: c_ulong = 2; pub const NI_MAXHOST: size_t = 1025; pub const XUCRED_VERSION: c_uint = 0; pub const RTLD_LOCAL: c_int = 0; pub const RTLD_NODELETE: c_int = 0x1000; pub const RTLD_NOLOAD: c_int = 0x2000; pub const RTLD_GLOBAL: c_int = 0x100; pub const LOG_NTP: c_int = 12 << 3; pub const LOG_SECURITY: c_int = 13 << 3; pub const LOG_CONSOLE: c_int = 14 << 3; pub const LOG_NFACILITIES: c_int = 24; pub const TIOCEXCL: c_ulong = 0x2000740d; pub const TIOCNXCL: c_ulong = 0x2000740e; pub const TIOCFLUSH: c_ulong = 0x80047410; pub const TIOCGETA: c_ulong = 0x402c7413; pub const TIOCSETA: c_ulong = 0x802c7414; pub const TIOCSETAW: c_ulong = 0x802c7415; pub const TIOCSETAF: c_ulong = 0x802c7416; pub const TIOCGETD: c_ulong = 0x4004741a; pub const TIOCSETD: c_ulong = 0x8004741b; pub const TIOCGDRAINWAIT: c_ulong = 0x40047456; pub const TIOCSDRAINWAIT: c_ulong = 0x80047457; pub const TIOCMGDTRWAIT: c_ulong = 0x4004745a; pub const TIOCMSDTRWAIT: c_ulong = 0x8004745b; pub const TIOCDRAIN: c_ulong = 0x2000745e; pub const TIOCEXT: c_ulong = 0x80047460; pub const TIOCSCTTY: c_ulong = 0x20007461; pub const TIOCCONS: c_ulong = 0x80047462; pub const TIOCGSID: c_ulong = 0x40047463; pub const TIOCSTAT: c_ulong = 0x20007465; pub const TIOCUCNTL: c_ulong = 0x80047466; pub const TIOCSWINSZ: c_ulong = 0x80087467; pub const TIOCGWINSZ: c_ulong = 0x40087468; pub const TIOCMGET: c_ulong = 0x4004746a; pub const TIOCM_LE: c_int = 0x1; pub const TIOCM_DTR: c_int = 0x2; pub const TIOCM_RTS: c_int = 0x4; pub const TIOCM_ST: c_int = 0x8; pub const TIOCM_SR: c_int = 0x10; pub const TIOCM_CTS: c_int = 0x20; pub const TIOCM_RI: c_int = 0x80; pub const TIOCM_DSR: c_int = 0x100; pub const TIOCM_CD: c_int = 0x40; pub const TIOCM_CAR: c_int = 0x40; pub const TIOCM_RNG: c_int = 0x80; pub const TIOCMBIC: c_ulong = 0x8004746b; pub const TIOCMBIS: c_ulong = 0x8004746c; pub const TIOCMSET: c_ulong = 0x8004746d; pub const TIOCSTART: c_ulong = 0x2000746e; pub const TIOCSTOP: c_ulong = 0x2000746f; pub const TIOCPKT: c_ulong = 0x80047470; pub const TIOCPKT_DATA: c_int = 0x0; pub const TIOCPKT_FLUSHREAD: c_int = 0x1; pub const TIOCPKT_FLUSHWRITE: c_int = 0x2; pub const TIOCPKT_STOP: c_int = 0x4; pub const TIOCPKT_START: c_int = 0x8; pub const TIOCPKT_NOSTOP: c_int = 0x10; pub const TIOCPKT_DOSTOP: c_int = 0x20; pub const TIOCPKT_IOCTL: c_int = 0x40; pub const TIOCNOTTY: c_ulong = 0x20007471; pub const TIOCSTI: c_ulong = 0x80017472; pub const TIOCOUTQ: c_ulong = 0x40047473; pub const TIOCSPGRP: c_ulong = 0x80047476; pub const TIOCGPGRP: c_ulong = 0x40047477; pub const TIOCCDTR: c_ulong = 0x20007478; pub const TIOCSDTR: c_ulong = 0x20007479; pub const TTYDISC: c_int = 0x0; pub const SLIPDISC: c_int = 0x4; pub const PPPDISC: c_int = 0x5; pub const NETGRAPHDISC: c_int = 0x6; pub const BIOCGRSIG: c_ulong = 0x40044272; pub const BIOCSRSIG: c_ulong = 0x80044273; pub const BIOCSDLT: c_ulong = 0x80044278; pub const BIOCGSEESENT: c_ulong = 0x40044276; pub const BIOCSSEESENT: c_ulong = 0x80044277; cfg_if! { if #[cfg(target_pointer_width = "64")] { pub const BIOCGDLTLIST: c_ulong = 0xc0104279; pub const BIOCSETF: c_ulong = 0x80104267; } else if #[cfg(target_pointer_width = "32")] { pub const BIOCGDLTLIST: c_ulong = 0xc0084279; pub const BIOCSETF: c_ulong = 0x80084267; } } pub const FIODTYPE: c_ulong = 0x4004667a; pub const FIOGETLBA: c_ulong = 0x40046679; pub const B0: speed_t = 0; pub const B50: speed_t = 50; pub const B75: speed_t = 75; pub const B110: speed_t = 110; pub const B134: speed_t = 134; pub const B150: speed_t = 150; pub const B200: speed_t = 200; pub const B300: speed_t = 300; pub const B600: speed_t = 600; pub const B1200: speed_t = 1200; pub const B1800: speed_t = 1800; pub const B2400: speed_t = 2400; pub const B4800: speed_t = 4800; pub const B9600: speed_t = 9600; pub const B19200: speed_t = 19200; pub const B38400: speed_t = 38400; pub const B7200: speed_t = 7200; pub const B14400: speed_t = 14400; pub const B28800: speed_t = 28800; pub const B57600: speed_t = 57600; pub const B76800: speed_t = 76800; pub const B115200: speed_t = 115200; pub const B230400: speed_t = 230400; pub const EXTA: speed_t = 19200; pub const EXTB: speed_t = 38400; pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; pub const CRTSCTS: crate::tcflag_t = 0x00030000; pub const CCTS_OFLOW: crate::tcflag_t = 0x00010000; pub const CRTS_IFLOW: crate::tcflag_t = 0x00020000; pub const CDTR_IFLOW: crate::tcflag_t = 0x00040000; pub const CDSR_OFLOW: crate::tcflag_t = 0x00080000; pub const CCAR_OFLOW: crate::tcflag_t = 0x00100000; pub const VERASE2: usize = 7; pub const OCRNL: crate::tcflag_t = 0x10; pub const ONOCR: crate::tcflag_t = 0x20; pub const ONLRET: crate::tcflag_t = 0x40; pub const CMGROUP_MAX: usize = 16; pub const EUI64_LEN: usize = 8; // https://github.com/freebsd/freebsd/blob/HEAD/sys/net/bpf.h pub const BPF_ALIGNMENT: usize = SIZEOF_LONG; // Values for rtprio struct (prio field) and syscall (function argument) pub const RTP_PRIO_MIN: c_ushort = 0; pub const RTP_PRIO_MAX: c_ushort = 31; pub const RTP_LOOKUP: c_int = 0; pub const RTP_SET: c_int = 1; // Flags for chflags(2) pub const UF_SETTABLE: c_ulong = 0x0000ffff; pub const UF_NODUMP: c_ulong = 0x00000001; pub const UF_IMMUTABLE: c_ulong = 0x00000002; pub const UF_APPEND: c_ulong = 0x00000004; pub const UF_OPAQUE: c_ulong = 0x00000008; pub const UF_NOUNLINK: c_ulong = 0x00000010; pub const SF_SETTABLE: c_ulong = 0xffff0000; pub const SF_ARCHIVED: c_ulong = 0x00010000; pub const SF_IMMUTABLE: c_ulong = 0x00020000; pub const SF_APPEND: c_ulong = 0x00040000; pub const SF_NOUNLINK: c_ulong = 0x00100000; pub const TIMER_ABSTIME: c_int = 1; // pub const NTP_API: c_int = 4; pub const MAXPHASE: c_long = 500000000; pub const MAXFREQ: c_long = 500000; pub const MINSEC: c_int = 256; pub const MAXSEC: c_int = 2048; pub const NANOSECOND: c_long = 1000000000; pub const SCALE_PPM: c_int = 65; pub const MAXTC: c_int = 10; pub const MOD_OFFSET: c_uint = 0x0001; pub const MOD_FREQUENCY: c_uint = 0x0002; pub const MOD_MAXERROR: c_uint = 0x0004; pub const MOD_ESTERROR: c_uint = 0x0008; pub const MOD_STATUS: c_uint = 0x0010; pub const MOD_TIMECONST: c_uint = 0x0020; pub const MOD_PPSMAX: c_uint = 0x0040; pub const MOD_TAI: c_uint = 0x0080; pub const MOD_MICRO: c_uint = 0x1000; pub const MOD_NANO: c_uint = 0x2000; pub const MOD_CLKB: c_uint = 0x4000; pub const MOD_CLKA: c_uint = 0x8000; pub const STA_PLL: c_int = 0x0001; pub const STA_PPSFREQ: c_int = 0x0002; pub const STA_PPSTIME: c_int = 0x0004; pub const STA_FLL: c_int = 0x0008; pub const STA_INS: c_int = 0x0010; pub const STA_DEL: c_int = 0x0020; pub const STA_UNSYNC: c_int = 0x0040; pub const STA_FREQHOLD: c_int = 0x0080; pub const STA_PPSSIGNAL: c_int = 0x0100; pub const STA_PPSJITTER: c_int = 0x0200; pub const STA_PPSWANDER: c_int = 0x0400; pub const STA_PPSERROR: c_int = 0x0800; pub const STA_CLOCKERR: c_int = 0x1000; pub const STA_NANO: c_int = 0x2000; pub const STA_MODE: c_int = 0x4000; pub const STA_CLK: c_int = 0x8000; pub const STA_RONLY: c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const TIME_OK: c_int = 0; pub const TIME_INS: c_int = 1; pub const TIME_DEL: c_int = 2; pub const TIME_OOP: c_int = 3; pub const TIME_WAIT: c_int = 4; pub const TIME_ERROR: c_int = 5; pub const REG_ENOSYS: c_int = -1; pub const REG_ILLSEQ: c_int = 17; pub const IPC_PRIVATE: crate::key_t = 0; pub const IPC_CREAT: c_int = 0o1000; pub const IPC_EXCL: c_int = 0o2000; pub const IPC_NOWAIT: c_int = 0o4000; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 1; pub const IPC_STAT: c_int = 2; pub const IPC_R: c_int = 0o400; pub const IPC_W: c_int = 0o200; pub const IPC_M: c_int = 0o10000; pub const SHM_RDONLY: c_int = 0o10000; pub const SHM_RND: c_int = 0o20000; pub const SHM_R: c_int = 0o400; pub const SHM_W: c_int = 0o200; pub const KENV_GET: c_int = 0; pub const KENV_SET: c_int = 1; pub const KENV_UNSET: c_int = 2; pub const KENV_DUMP: c_int = 3; pub const KENV_MNAMELEN: c_int = 128; pub const KENV_MVALLEN: c_int = 128; pub const RB_ASKNAME: c_int = 0x001; pub const RB_SINGLE: c_int = 0x002; pub const RB_NOSYNC: c_int = 0x004; pub const RB_HALT: c_int = 0x008; pub const RB_INITNAME: c_int = 0x010; pub const RB_DFLTROOT: c_int = 0x020; pub const RB_KDB: c_int = 0x040; pub const RB_RDONLY: c_int = 0x080; pub const RB_DUMP: c_int = 0x100; pub const RB_MINIROOT: c_int = 0x200; pub const RB_VERBOSE: c_int = 0x800; pub const RB_SERIAL: c_int = 0x1000; pub const RB_CDROM: c_int = 0x2000; pub const RB_POWEROFF: c_int = 0x4000; pub const RB_GDB: c_int = 0x8000; pub const RB_MUTE: c_int = 0x10000; pub const RB_SELFTEST: c_int = 0x20000; // For getrandom() pub const GRND_NONBLOCK: c_uint = 0x1; pub const GRND_RANDOM: c_uint = 0x2; pub const GRND_INSECURE: c_uint = 0x4; // DIFF(main): changed to `c_short` in f62eb023ab pub const POSIX_SPAWN_RESETIDS: c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: c_int = 0x02; pub const POSIX_SPAWN_SETSCHEDPARAM: c_int = 0x04; pub const POSIX_SPAWN_SETSCHEDULER: c_int = 0x08; pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x10; pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x20; safe_f! { pub {const} fn WIFCONTINUED(status: c_int) -> bool { status == 0x13 } pub {const} fn WSTOPSIG(status: c_int) -> c_int { status >> 8 } pub {const} fn WIFSTOPPED(status: c_int) -> bool { (status & 0o177) == 0o177 } } extern "C" { pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut crate::timezone) -> c_int; pub fn accept4( s: c_int, addr: *mut crate::sockaddr, addrlen: *mut crate::socklen_t, flags: c_int, ) -> c_int; pub fn chflags(path: *const c_char, flags: c_ulong) -> c_int; pub fn chflagsat(fd: c_int, path: *const c_char, flags: c_ulong, atflag: c_int) -> c_int; pub fn clock_nanosleep( clk_id: crate::clockid_t, flags: c_int, rqtp: *const crate::timespec, rmtp: *mut crate::timespec, ) -> c_int; pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_settime(clk_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; pub fn clock_getcpuclockid(pid: crate::pid_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn pthread_getcpuclockid(thread: crate::pthread_t, clk_id: *mut crate::clockid_t) -> c_int; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; pub fn endutxent(); pub fn fchflags(fd: c_int, flags: c_ulong) -> c_int; // DIFF(main): changed to `*const *mut` in e77f551de9 pub fn fexecve(fd: c_int, argv: *const *const c_char, envp: *const *const c_char) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn getdomainname(name: *mut c_char, len: c_int) -> c_int; pub fn getgrent_r( grp: *mut crate::group, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::group, ) -> c_int; pub fn getpwent_r( pwd: *mut crate::passwd, buf: *mut c_char, buflen: size_t, result: *mut *mut crate::passwd, ) -> c_int; pub fn getgrouplist( name: *const c_char, basegid: crate::gid_t, groups: *mut crate::gid_t, ngroups: *mut c_int, ) -> c_int; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: size_t, serv: *mut c_char, servlen: size_t, flags: c_int, ) -> c_int; pub fn getpriority(which: c_int, who: c_int) -> c_int; pub fn getresgid( rgid: *mut crate::gid_t, egid: *mut crate::gid_t, sgid: *mut crate::gid_t, ) -> c_int; pub fn getresuid( ruid: *mut crate::uid_t, euid: *mut crate::uid_t, suid: *mut crate::uid_t, ) -> c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn initgroups(name: *const c_char, basegid: crate::gid_t) -> c_int; #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "kevent@FBSD_1.0" )] pub fn kevent( kq: c_int, changelist: *const crate::kevent, nchanges: c_int, eventlist: *mut crate::kevent, nevents: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn lchflags(path: *const c_char, flags: c_ulong) -> c_int; pub fn lutimes(file: *const c_char, times: *const crate::timeval) -> c_int; pub fn memrchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "mknodat@FBSD_1.1" )] pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn malloc_usable_size(ptr: *const c_void) -> size_t; pub fn mincore(addr: *const c_void, len: size_t, vec: *mut c_char) -> c_int; pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn nl_langinfo_l(item: crate::nl_item, locale: crate::locale_t) -> *mut c_char; pub fn pipe2(fds: *mut c_int, flags: c_int) -> c_int; pub fn posix_fallocate(fd: c_int, offset: off_t, len: off_t) -> c_int; pub fn posix_fadvise(fd: c_int, offset: off_t, len: off_t, advise: c_int) -> c_int; pub fn ppoll( fds: *mut crate::pollfd, nfds: crate::nfds_t, timeout: *const crate::timespec, sigmask: *const sigset_t, ) -> c_int; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn pthread_attr_get_np(tid: crate::pthread_t, attr: *mut crate::pthread_attr_t) -> c_int; pub fn pthread_attr_getguardsize( attr: *const crate::pthread_attr_t, guardsize: *mut size_t, ) -> c_int; pub fn pthread_attr_setguardsize(attr: *mut crate::pthread_attr_t, guardsize: size_t) -> c_int; pub fn pthread_attr_getstack( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: crate::clockid_t, ) -> c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: c_int) -> c_int; pub fn pthread_main_np() -> c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const crate::timespec, ) -> c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: c_int) -> c_int; pub fn pthread_barrierattr_init(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_destroy(attr: *mut crate::pthread_barrierattr_t) -> c_int; pub fn pthread_barrierattr_getpshared( attr: *const crate::pthread_barrierattr_t, shared: *mut c_int, ) -> c_int; pub fn pthread_barrierattr_setpshared( attr: *mut crate::pthread_barrierattr_t, shared: c_int, ) -> c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const crate::pthread_barrierattr_t, count: c_uint, ) -> c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> c_int; pub fn pthread_get_name_np(tid: crate::pthread_t, name: *mut c_char, len: size_t); pub fn pthread_set_name_np(tid: crate::pthread_t, name: *const c_char); pub fn pthread_getname_np( thread: crate::pthread_t, buffer: *mut c_char, length: size_t, ) -> c_int; pub fn pthread_setname_np(thread: crate::pthread_t, name: *const c_char) -> c_int; pub fn pthread_setschedparam( native: crate::pthread_t, policy: c_int, param: *const sched_param, ) -> c_int; pub fn pthread_getschedparam( native: crate::pthread_t, policy: *mut c_int, param: *mut sched_param, ) -> c_int; pub fn ptrace(request: c_int, pid: crate::pid_t, addr: *mut c_char, data: c_int) -> c_int; pub fn utrace(addr: *const c_void, len: size_t) -> c_int; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn querylocale(mask: c_int, loc: crate::locale_t) -> *const c_char; pub fn rtprio(function: c_int, pid: crate::pid_t, rtp: *mut rtprio) -> c_int; pub fn sched_rr_get_interval(pid: crate::pid_t, t: *mut crate::timespec) -> c_int; pub fn sched_getparam(pid: crate::pid_t, param: *mut sched_param) -> c_int; pub fn sched_setparam(pid: crate::pid_t, param: *const sched_param) -> c_int; pub fn sched_getscheduler(pid: crate::pid_t) -> c_int; pub fn sched_setscheduler( pid: crate::pid_t, policy: c_int, param: *const crate::sched_param, ) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const crate::timespec) -> c_int; pub fn sendfile( fd: c_int, s: c_int, offset: off_t, nbytes: size_t, hdtr: *mut crate::sf_hdtr, sbytes: *mut off_t, flags: c_int, ) -> c_int; pub fn setdomainname(name: *const c_char, len: c_int) -> c_int; pub fn sethostname(name: *const c_char, len: c_int) -> c_int; pub fn setpriority(which: c_int, who: c_int, prio: c_int) -> c_int; pub fn setresgid(rgid: crate::gid_t, egid: crate::gid_t, sgid: crate::gid_t) -> c_int; pub fn setresuid(ruid: crate::uid_t, euid: crate::uid_t, suid: crate::uid_t) -> c_int; pub fn settimeofday(tv: *const crate::timeval, tz: *const crate::timezone) -> c_int; pub fn setutxent(); pub fn shm_open(name: *const c_char, oflag: c_int, mode: crate::mode_t) -> c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const crate::timespec, ) -> c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> c_int; pub fn sysctl( name: *const c_int, namelen: c_uint, oldp: *mut c_void, oldlenp: *mut size_t, newp: *const c_void, newlen: size_t, ) -> c_int; pub fn sysctlbyname( name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t, newp: *const c_void, newlen: size_t, ) -> c_int; pub fn sysctlnametomib(name: *const c_char, mibp: *mut c_int, sizep: *mut size_t) -> c_int; pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn ntp_adjtime(buf: *mut timex) -> c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> c_int; // #include pub fn dl_iterate_phdr( callback: Option< unsafe extern "C" fn(info: *mut dl_phdr_info, size: usize, data: *mut c_void) -> c_int, >, data: *mut c_void, ) -> c_int; pub fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut c_char, inbytesleft: *mut size_t, outbuf: *mut *mut c_char, outbytesleft: *mut size_t, ) -> size_t; pub fn iconv_close(cd: iconv_t) -> c_int; // Added in `FreeBSD` 11.0 // Added in `DragonFly BSD` 5.4 pub fn explicit_bzero(s: *mut c_void, len: size_t); // ISO/IEC 9899:2011 ("ISO C11") K.3.7.4.1 pub fn memset_s(s: *mut c_void, smax: size_t, c: c_int, n: size_t) -> c_int; pub fn gethostid() -> c_long; pub fn sethostid(hostid: c_long); pub fn eui64_aton(a: *const c_char, e: *mut eui64) -> c_int; pub fn eui64_ntoa(id: *const eui64, a: *mut c_char, len: size_t) -> c_int; pub fn eui64_ntohost(hostname: *mut c_char, len: size_t, id: *const eui64) -> c_int; pub fn eui64_hostton(hostname: *const c_char, id: *mut eui64) -> c_int; pub fn eaccess(path: *const c_char, mode: c_int) -> c_int; pub fn kenv(action: c_int, name: *const c_char, value: *mut c_char, len: c_int) -> c_int; pub fn reboot(howto: c_int) -> c_int; pub fn exect(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int; pub fn execvP( file: *const c_char, search_path: *const c_char, argv: *const *mut c_char, ) -> c_int; pub fn mkostemp(template: *mut c_char, flags: c_int) -> c_int; pub fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int; pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: crate::pid_t) -> c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut c_int, ) -> c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: c_int) -> c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut crate::sched_param, ) -> c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const crate::sched_param, ) -> c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int, ) -> c_int; } #[link(name = "rt")] extern "C" { pub fn mq_close(mqd: crate::mqd_t) -> c_int; pub fn mq_getattr(mqd: crate::mqd_t, attr: *mut crate::mq_attr) -> c_int; pub fn mq_notify(mqd: crate::mqd_t, notification: *const crate::sigevent) -> c_int; pub fn mq_open(name: *const c_char, oflag: c_int, ...) -> crate::mqd_t; pub fn mq_receive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, ) -> ssize_t; pub fn mq_send( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, ) -> c_int; pub fn mq_setattr( mqd: crate::mqd_t, newattr: *const crate::mq_attr, oldattr: *mut crate::mq_attr, ) -> c_int; pub fn mq_timedreceive( mqd: crate::mqd_t, msg_ptr: *mut c_char, msg_len: size_t, msg_prio: *mut c_uint, abs_timeout: *const crate::timespec, ) -> ssize_t; pub fn mq_timedsend( mqd: crate::mqd_t, msg_ptr: *const c_char, msg_len: size_t, msg_prio: c_uint, abs_timeout: *const crate::timespec, ) -> c_int; pub fn mq_unlink(name: *const c_char) -> c_int; pub fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; } #[link(name = "util")] extern "C" { pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> c_int; pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> crate::pid_t; pub fn login_tty(fd: c_int) -> c_int; pub fn fparseln( stream: *mut crate::FILE, len: *mut size_t, lineno: *mut size_t, delim: *const c_char, flags: c_int, ) -> *mut c_char; } #[link(name = "execinfo")] extern "C" { pub fn backtrace(addrlist: *mut *mut c_void, len: size_t) -> size_t; pub fn backtrace_symbols(addrlist: *const *mut c_void, len: size_t) -> *mut *mut c_char; pub fn backtrace_symbols_fd(addrlist: *const *mut c_void, len: size_t, fd: c_int) -> c_int; } #[link(name = "kvm")] extern "C" { pub fn kvm_open( execfile: *const c_char, corefile: *const c_char, swapfile: *const c_char, flags: c_int, errstr: *const c_char, ) -> *mut crate::kvm_t; pub fn kvm_close(kd: *mut crate::kvm_t) -> c_int; pub fn kvm_getprocs( kd: *mut crate::kvm_t, op: c_int, arg: c_int, cnt: *mut c_int, ) -> *mut crate::kinfo_proc; pub fn kvm_getloadavg(kd: *mut kvm_t, loadavg: *mut c_double, nelem: c_int) -> c_int; pub fn kvm_openfiles( execfile: *const c_char, corefile: *const c_char, swapfile: *const c_char, flags: c_int, errbuf: *mut c_char, ) -> *mut crate::kvm_t; pub fn kvm_read( kd: *mut crate::kvm_t, addr: c_ulong, buf: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn kvm_write( kd: *mut crate::kvm_t, addr: c_ulong, buf: *const c_void, nbytes: size_t, ) -> ssize_t; } cfg_if! { if #[cfg(target_os = "freebsd")] { mod freebsd; pub use self::freebsd::*; } else if #[cfg(target_os = "dragonfly")] { mod dragonfly; pub use self::dragonfly::*; } else { // ... } } libc/src/unix/bsd/freebsdlike/dragonfly/0000775000175000017500000000000015105742312020103 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/dragonfly/mod.rs0000644000175000017500000016351515105742312021241 0ustar bdrungbdrunguse crate::prelude::*; use crate::{cmsghdr, off_t}; pub type dev_t = u32; pub type wchar_t = i32; pub type clock_t = u64; pub type ino_t = u64; pub type lwpid_t = i32; pub type nlink_t = u32; pub type blksize_t = i64; pub type clockid_t = c_ulong; pub type time_t = i64; pub type suseconds_t = i64; pub type uuid_t = crate::uuid; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type idtype_t = c_uint; pub type shmatt_t = c_uint; pub type mqd_t = c_int; pub type sem_t = *mut sem; pub type cpuset_t = cpumask_t; pub type cpu_set_t = cpumask_t; pub type register_t = c_long; pub type umtx_t = c_int; pub type pthread_barrierattr_t = c_int; pub type pthread_barrier_t = crate::uintptr_t; pub type pthread_spinlock_t = crate::uintptr_t; pub type segsz_t = usize; pub type vm_prot_t = u8; pub type vm_maptype_t = u8; pub type vm_inherit_t = i8; pub type vm_subsys_t = c_int; pub type vm_eflags_t = c_uint; pub type vm_map_t = *mut __c_anonymous_vm_map; pub type vm_map_entry_t = *mut vm_map_entry; pub type pmap = __c_anonymous_pmap; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum sem {} impl Copy for sem {} impl Clone for sem { fn clone(&self) -> sem { *self } } e! { #[repr(u32)] pub enum lwpstat { LSRUN = 1, LSSTOP = 2, LSSLEEP = 3, } #[repr(u32)] pub enum procstat { SIDL = 1, SACTIVE = 2, SSTOP = 3, SZOMB = 4, SCORE = 5, } } s! { pub struct kevent { pub ident: crate::uintptr_t, pub filter: c_short, pub flags: c_ushort, pub fflags: c_uint, pub data: intptr_t, pub udata: *mut c_void, } pub struct exit_status { pub e_termination: u16, pub e_exit: u16, } pub struct aiocb { pub aio_fildes: c_int, pub aio_offset: off_t, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_sigevent: sigevent, pub aio_lio_opcode: c_int, pub aio_reqprio: c_int, _aio_val: c_int, _aio_err: c_int, } pub struct uuid { pub time_low: u32, pub time_mid: u16, pub time_hi_and_version: u16, pub clock_seq_hi_and_reserved: u8, pub clock_seq_low: u8, pub node: [u8; 6], } pub struct mq_attr { pub mq_flags: c_long, pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_curmsgs: c_long, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, pub f_owner: crate::uid_t, pub f_type: c_uint, pub f_syncreads: u64, pub f_syncwrites: u64, pub f_asyncreads: u64, pub f_asyncwrites: u64, pub f_fsid_uuid: crate::uuid_t, pub f_uid_uuid: crate::uuid_t, } pub struct stat { pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_dev: crate::dev_t, pub st_mode: crate::mode_t, pub st_padding1: u16, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_size: off_t, pub st_blocks: i64, pub __old_st_blksize: u32, pub st_flags: u32, pub st_gen: u32, pub st_lspare: i32, pub st_blksize: i64, pub st_qspare2: i64, } pub struct if_data { pub ifi_type: c_uchar, pub ifi_physical: c_uchar, pub ifi_addrlen: c_uchar, pub ifi_hdrlen: c_uchar, pub ifi_recvquota: c_uchar, pub ifi_xmitquota: c_uchar, pub ifi_mtu: c_ulong, pub ifi_metric: c_ulong, pub ifi_link_state: c_ulong, pub ifi_baudrate: u64, pub ifi_ipackets: c_ulong, pub ifi_ierrors: c_ulong, pub ifi_opackets: c_ulong, pub ifi_oerrors: c_ulong, pub ifi_collisions: c_ulong, pub ifi_ibytes: c_ulong, pub ifi_obytes: c_ulong, pub ifi_imcasts: c_ulong, pub ifi_omcasts: c_ulong, pub ifi_iqdrops: c_ulong, pub ifi_noproto: c_ulong, pub ifi_hwassist: c_ulong, pub ifi_oqdrops: c_ulong, pub ifi_lastchange: crate::timeval, } pub struct if_msghdr { pub ifm_msglen: c_ushort, pub ifm_version: c_uchar, pub ifm_type: c_uchar, pub ifm_addrs: c_int, pub ifm_flags: c_int, pub ifm_index: c_ushort, pub ifm_data: if_data, } pub struct sockaddr_dl { pub sdl_len: c_uchar, pub sdl_family: c_uchar, pub sdl_index: c_ushort, pub sdl_type: c_uchar, pub sdl_nlen: c_uchar, pub sdl_alen: c_uchar, pub sdl_slen: c_uchar, pub sdl_data: [c_char; 12], pub sdl_rcf: c_ushort, pub sdl_route: [c_ushort; 16], } pub struct xucred { pub cr_version: c_uint, pub cr_uid: crate::uid_t, pub cr_ngroups: c_short, pub cr_groups: [crate::gid_t; 16], __cr_unused1: *mut c_void, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct cpumask_t { ary: [u64; 4], } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, shm_internal: *mut c_void, } pub struct kinfo_file { pub f_size: size_t, pub f_pid: crate::pid_t, pub f_uid: crate::uid_t, pub f_fd: c_int, pub f_file: *mut c_void, pub f_type: c_short, pub f_count: c_int, pub f_msgcount: c_int, pub f_offset: off_t, pub f_data: *mut c_void, pub f_flag: c_uint, } pub struct kinfo_cputime { pub cp_user: u64, pub cp_nice: u64, pub cp_sys: u64, pub cp_intr: u64, pub cp_idel: u64, cp_unused01: u64, cp_unused02: u64, pub cp_sample_pc: u64, pub cp_sample_sp: u64, pub cp_msg: [c_char; 32], } pub struct kinfo_lwp { pub kl_pid: crate::pid_t, pub kl_tid: crate::lwpid_t, pub kl_flags: c_int, pub kl_stat: crate::lwpstat, pub kl_lock: c_int, pub kl_tdflags: c_int, pub kl_mpcount: c_int, pub kl_prio: c_int, pub kl_tdprio: c_int, pub kl_rtprio: crate::rtprio, pub kl_uticks: u64, pub kl_sticks: u64, pub kl_iticks: u64, pub kl_cpticks: u64, pub kl_pctcpu: c_uint, pub kl_slptime: c_uint, pub kl_origcpu: c_int, pub kl_estcpu: c_int, pub kl_cpuid: c_int, pub kl_ru: crate::rusage, pub kl_siglist: crate::sigset_t, pub kl_sigmask: crate::sigset_t, pub kl_wchan: crate::uintptr_t, pub kl_wmesg: [c_char; 9], pub kl_comm: [c_char; MAXCOMLEN + 1], } pub struct kinfo_proc { pub kp_paddr: crate::uintptr_t, pub kp_flags: c_int, pub kp_stat: crate::procstat, pub kp_lock: c_int, pub kp_acflag: c_int, pub kp_traceflag: c_int, pub kp_fd: crate::uintptr_t, pub kp_siglist: crate::sigset_t, pub kp_sigignore: crate::sigset_t, pub kp_sigcatch: crate::sigset_t, pub kp_sigflag: c_int, pub kp_start: crate::timeval, pub kp_comm: [c_char; MAXCOMLEN + 1], pub kp_uid: crate::uid_t, pub kp_ngroups: c_short, pub kp_groups: [crate::gid_t; NGROUPS], pub kp_ruid: crate::uid_t, pub kp_svuid: crate::uid_t, pub kp_rgid: crate::gid_t, pub kp_svgid: crate::gid_t, pub kp_pid: crate::pid_t, pub kp_ppid: crate::pid_t, pub kp_pgid: crate::pid_t, pub kp_jobc: c_int, pub kp_sid: crate::pid_t, pub kp_login: [c_char; 40], // MAXNAMELEN rounded up to the nearest sizeof(long) pub kp_tdev: crate::dev_t, pub kp_tpgid: crate::pid_t, pub kp_tsid: crate::pid_t, pub kp_exitstat: c_ushort, pub kp_nthreads: c_int, pub kp_nice: c_int, pub kp_swtime: c_uint, pub kp_vm_map_size: size_t, pub kp_vm_rssize: crate::segsz_t, pub kp_vm_swrss: crate::segsz_t, pub kp_vm_tsize: crate::segsz_t, pub kp_vm_dsize: crate::segsz_t, pub kp_vm_ssize: crate::segsz_t, pub kp_vm_prssize: c_uint, pub kp_jailid: c_int, pub kp_ru: crate::rusage, pub kp_cru: crate::rusage, pub kp_auxflags: c_int, pub kp_lwp: crate::kinfo_lwp, pub kp_ktaddr: crate::uintptr_t, kp_spare: [c_int; 2], } pub struct __c_anonymous_vm_map { _priv: [crate::uintptr_t; 36], } pub struct vm_map_entry { _priv: [crate::uintptr_t; 15], pub eflags: crate::vm_eflags_t, pub maptype: crate::vm_maptype_t, pub protection: crate::vm_prot_t, pub max_protection: crate::vm_prot_t, pub inheritance: crate::vm_inherit_t, pub wired_count: c_int, pub id: crate::vm_subsys_t, } pub struct __c_anonymous_pmap { _priv1: [crate::uintptr_t; 32], _priv2: [crate::uintptr_t; 32], _priv3: [crate::uintptr_t; 32], _priv4: [crate::uintptr_t; 32], _priv5: [crate::uintptr_t; 8], } pub struct vmspace { vm_map: __c_anonymous_vm_map, vm_pmap: __c_anonymous_pmap, pub vm_flags: c_int, pub vm_shm: *mut c_char, pub vm_rssize: crate::segsz_t, pub vm_swrss: crate::segsz_t, pub vm_tsize: crate::segsz_t, pub vm_dsize: crate::segsz_t, pub vm_ssize: crate::segsz_t, pub vm_taddr: *mut c_char, pub vm_daddr: *mut c_char, pub vm_maxsaddr: *mut c_char, pub vm_minsaddr: *mut c_char, _unused1: c_int, _unused2: c_int, pub vm_pagesupply: c_int, pub vm_holdcnt: c_uint, pub vm_refcnt: c_uint, } pub struct cpuctl_msr_args_t { pub msr: c_int, pub data: u64, } pub struct cpuctl_cpuid_args_t { pub level: c_int, pub data: [u32; 4], } pub struct cpuctl_cpuid_count_args_t { pub level: c_int, pub level_type: c_int, pub data: [u32; 4], } pub struct cpuctl_update_args_t { pub data: *mut c_void, pub size: size_t, } } s_no_extra_traits! { pub struct utmpx { pub ut_name: [c_char; 32], pub ut_id: [c_char; 4], pub ut_line: [c_char; 32], pub ut_host: [c_char; 256], pub ut_unused: [u8; 16], pub ut_session: u16, pub ut_type: u16, pub ut_pid: crate::pid_t, ut_exit: exit_status, ut_ss: crate::sockaddr_storage, pub ut_tv: crate::timeval, pub ut_unused2: [u8; 16], } pub struct lastlogx { pub ll_tv: crate::timeval, pub ll_line: [c_char; _UTX_LINESIZE], pub ll_host: [c_char; _UTX_HOSTSIZE], pub ll_ss: crate::sockaddr_storage, } pub struct dirent { pub d_fileno: crate::ino_t, pub d_namlen: u16, pub d_type: u8, __unused1: u8, __unused2: u32, pub d_name: [c_char; 256], } pub struct statfs { __spare2: c_long, pub f_bsize: c_long, pub f_iosize: c_long, pub f_blocks: c_long, pub f_bfree: c_long, pub f_bavail: c_long, pub f_files: c_long, pub f_ffree: c_long, pub f_fsid: crate::fsid_t, pub f_owner: crate::uid_t, pub f_type: c_int, pub f_flags: c_int, pub f_syncwrites: c_long, pub f_asyncwrites: c_long, pub f_fstypename: [c_char; 16], pub f_mntonname: [c_char; 80], pub f_syncreads: c_long, pub f_asyncreads: c_long, __spares1: c_short, pub f_mntfromname: [c_char; 80], __spares2: c_short, __spare: [c_long; 2], } pub struct sigevent { pub sigev_notify: c_int, // The union is 8-byte in size, so it is aligned at a 8-byte offset. #[cfg(target_pointer_width = "64")] __unused1: c_int, pub sigev_signo: c_int, //actually a union // pad the union #[cfg(target_pointer_width = "64")] __unused2: c_int, pub sigev_value: crate::sigval, __unused3: *mut c_void, //actually a function pointer } pub struct mcontext_t { pub mc_onstack: register_t, pub mc_rdi: register_t, pub mc_rsi: register_t, pub mc_rdx: register_t, pub mc_rcx: register_t, pub mc_r8: register_t, pub mc_r9: register_t, pub mc_rax: register_t, pub mc_rbx: register_t, pub mc_rbp: register_t, pub mc_r10: register_t, pub mc_r11: register_t, pub mc_r12: register_t, pub mc_r13: register_t, pub mc_r14: register_t, pub mc_r15: register_t, pub mc_xflags: register_t, pub mc_trapno: register_t, pub mc_addr: register_t, pub mc_flags: register_t, pub mc_err: register_t, pub mc_rip: register_t, pub mc_cs: register_t, pub mc_rflags: register_t, pub mc_rsp: register_t, pub mc_ss: register_t, pub mc_len: c_uint, pub mc_fpformat: c_uint, pub mc_ownedfp: c_uint, __reserved: c_uint, __unused: [c_uint; 8], pub mc_fpregs: [[c_uint; 8]; 32], } pub struct ucontext_t { pub uc_sigmask: crate::sigset_t, pub uc_mcontext: mcontext_t, pub uc_link: *mut ucontext_t, pub uc_stack: stack_t, pub uc_cofunc: Option, pub uc_arg: *mut c_void, __pad: [c_int; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_name == other.ut_name && self.ut_id == other.ut_id && self.ut_line == other.ut_line && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) && self.ut_unused == other.ut_unused && self.ut_session == other.ut_session && self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_exit == other.ut_exit && self.ut_ss == other.ut_ss && self.ut_tv == other.ut_tv && self.ut_unused2 == other.ut_unused2 } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_name", &self.ut_name) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) // FIXME(debug): .field("ut_host", &self.ut_host) .field("ut_unused", &self.ut_unused) .field("ut_session", &self.ut_session) .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_exit", &self.ut_exit) .field("ut_ss", &self.ut_ss) .field("ut_tv", &self.ut_tv) .field("ut_unused2", &self.ut_unused2) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_name.hash(state); self.ut_id.hash(state); self.ut_line.hash(state); self.ut_host.hash(state); self.ut_unused.hash(state); self.ut_session.hash(state); self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_exit.hash(state); self.ut_ss.hash(state); self.ut_tv.hash(state); self.ut_unused2.hash(state); } } impl PartialEq for lastlogx { fn eq(&self, other: &lastlogx) -> bool { self.ll_tv == other.ll_tv && self.ll_line == other.ll_line && self.ll_host == other.ll_host && self.ll_ss == other.ll_ss } } impl Eq for lastlogx {} impl fmt::Debug for lastlogx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("lastlogx") .field("ll_tv", &self.ll_tv) .field("ll_line", &self.ll_line) .field("ll_host", &self.ll_host) .field("ll_ss", &self.ll_ss) .finish() } } impl hash::Hash for lastlogx { fn hash(&self, state: &mut H) { self.ll_tv.hash(state); self.ll_line.hash(state); self.ll_host.hash(state); self.ll_ss.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_namlen == other.d_namlen && self.d_type == other.d_type // Ignore __unused1 // Ignore __unused2 && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_namlen", &self.d_namlen) .field("d_type", &self.d_type) // Ignore __unused1 // Ignore __unused2 // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_namlen.hash(state); self.d_type.hash(state); // Ignore __unused1 // Ignore __unused2 self.d_name.hash(state); } } impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_fsid == other.f_fsid && self.f_owner == other.f_owner && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_fstypename == other.f_fstypename && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) } } impl Eq for statfs {} impl fmt::Debug for statfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_fsid", &self.f_fsid) .field("f_owner", &self.f_owner) .field("f_type", &self.f_type) .field("f_flags", &self.f_flags) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) // FIXME(debug): .field("f_mntonname", &self.f_mntonname) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) // FIXME(debug): .field("f_mntfromname", &self.f_mntfromname) .finish() } } impl hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_fsid.hash(state); self.f_owner.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_fstypename.hash(state); self.f_mntonname.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_mntfromname.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_onstack == other.mc_onstack && self.mc_rdi == other.mc_rdi && self.mc_rsi == other.mc_rsi && self.mc_rdx == other.mc_rdx && self.mc_rcx == other.mc_rcx && self.mc_r8 == other.mc_r8 && self.mc_r9 == other.mc_r9 && self.mc_rax == other.mc_rax && self.mc_rbx == other.mc_rbx && self.mc_rbp == other.mc_rbp && self.mc_r10 == other.mc_r10 && self.mc_r11 == other.mc_r11 && self.mc_r12 == other.mc_r12 && self.mc_r13 == other.mc_r13 && self.mc_r14 == other.mc_r14 && self.mc_r15 == other.mc_r15 && self.mc_xflags == other.mc_xflags && self.mc_trapno == other.mc_trapno && self.mc_addr == other.mc_addr && self.mc_flags == other.mc_flags && self.mc_err == other.mc_err && self.mc_rip == other.mc_rip && self.mc_cs == other.mc_cs && self.mc_rflags == other.mc_rflags && self.mc_rsp == other.mc_rsp && self.mc_ss == other.mc_ss && self.mc_len == other.mc_len && self.mc_fpformat == other.mc_fpformat && self.mc_ownedfp == other.mc_ownedfp && self.mc_fpregs == other.mc_fpregs } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("mc_onstack", &self.mc_onstack) .field("mc_rdi", &self.mc_rdi) .field("mc_rsi", &self.mc_rsi) .field("mc_rdx", &self.mc_rdx) .field("mc_rcx", &self.mc_rcx) .field("mc_r8", &self.mc_r8) .field("mc_r9", &self.mc_r9) .field("mc_rax", &self.mc_rax) .field("mc_rbx", &self.mc_rbx) .field("mc_rbp", &self.mc_rbp) .field("mc_r10", &self.mc_r10) .field("mc_r11", &self.mc_r11) .field("mc_r12", &self.mc_r12) .field("mc_r13", &self.mc_r13) .field("mc_r14", &self.mc_r14) .field("mc_r15", &self.mc_r15) .field("mc_xflags", &self.mc_xflags) .field("mc_trapno", &self.mc_trapno) .field("mc_addr", &self.mc_addr) .field("mc_flags", &self.mc_flags) .field("mc_err", &self.mc_err) .field("mc_rip", &self.mc_rip) .field("mc_cs", &self.mc_cs) .field("mc_rflags", &self.mc_rflags) .field("mc_rsp", &self.mc_rsp) .field("mc_ss", &self.mc_ss) .field("mc_len", &self.mc_len) .field("mc_fpformat", &self.mc_fpformat) .field("mc_ownedfp", &self.mc_ownedfp) .field("mc_fpregs", &self.mc_fpregs) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_onstack.hash(state); self.mc_rdi.hash(state); self.mc_rsi.hash(state); self.mc_rdx.hash(state); self.mc_rcx.hash(state); self.mc_r8.hash(state); self.mc_r9.hash(state); self.mc_rax.hash(state); self.mc_rbx.hash(state); self.mc_rbp.hash(state); self.mc_r10.hash(state); self.mc_r11.hash(state); self.mc_r10.hash(state); self.mc_r11.hash(state); self.mc_r12.hash(state); self.mc_r13.hash(state); self.mc_r14.hash(state); self.mc_r15.hash(state); self.mc_xflags.hash(state); self.mc_trapno.hash(state); self.mc_addr.hash(state); self.mc_flags.hash(state); self.mc_err.hash(state); self.mc_rip.hash(state); self.mc_cs.hash(state); self.mc_rflags.hash(state); self.mc_rsp.hash(state); self.mc_ss.hash(state); self.mc_len.hash(state); self.mc_fpformat.hash(state); self.mc_ownedfp.hash(state); self.mc_fpregs.hash(state); } } // FIXME(msrv): suggested method was added in 1.85 #[allow(unpredictable_function_pointer_comparisons)] impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_sigmask == other.uc_sigmask && self.uc_mcontext == other.uc_mcontext && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_cofunc == other.uc_cofunc && self.uc_arg == other.uc_arg } } impl Eq for ucontext_t {} impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_sigmask", &self.uc_sigmask) .field("uc_mcontext", &self.uc_mcontext) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_cofunc", &self.uc_cofunc) .field("uc_arg", &self.uc_arg) .finish() } } impl hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_sigmask.hash(state); self.uc_mcontext.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_cofunc.hash(state); self.uc_arg.hash(state); } } } } pub const RAND_MAX: c_int = 0x7fff_ffff; pub const PTHREAD_STACK_MIN: size_t = 16384; pub const SIGSTKSZ: size_t = 40960; pub const SIGCKPT: c_int = 33; pub const SIGCKPTEXIT: c_int = 34; pub const CKPT_FREEZE: c_int = 0x1; pub const CKPT_THAW: c_int = 0x2; pub const MADV_INVAL: c_int = 10; pub const MADV_SETMAP: c_int = 11; pub const O_CLOEXEC: c_int = 0x00020000; pub const O_DIRECTORY: c_int = 0x08000000; pub const F_GETLK: c_int = 7; pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; pub const F_GETPATH: c_int = 19; pub const ENOMEDIUM: c_int = 93; pub const ENOTRECOVERABLE: c_int = 94; pub const EOWNERDEAD: c_int = 95; pub const EASYNC: c_int = 99; pub const ELAST: c_int = 99; pub const RLIMIT_POSIXLOCKS: c_int = 11; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: crate::rlim_t = 12; pub const Q_GETQUOTA: c_int = 0x300; pub const Q_SETQUOTA: c_int = 0x400; pub const CTL_UNSPEC: c_int = 0; pub const CTL_KERN: c_int = 1; pub const CTL_VM: c_int = 2; pub const CTL_VFS: c_int = 3; pub const CTL_NET: c_int = 4; pub const CTL_DEBUG: c_int = 5; pub const CTL_HW: c_int = 6; pub const CTL_MACHDEP: c_int = 7; pub const CTL_USER: c_int = 8; pub const CTL_P1003_1B: c_int = 9; pub const CTL_LWKT: c_int = 10; pub const CTL_MAXID: c_int = 11; pub const KERN_OSTYPE: c_int = 1; pub const KERN_OSRELEASE: c_int = 2; pub const KERN_OSREV: c_int = 3; pub const KERN_VERSION: c_int = 4; pub const KERN_MAXVNODES: c_int = 5; pub const KERN_MAXPROC: c_int = 6; pub const KERN_MAXFILES: c_int = 7; pub const KERN_ARGMAX: c_int = 8; pub const KERN_SECURELVL: c_int = 9; pub const KERN_HOSTNAME: c_int = 10; pub const KERN_HOSTID: c_int = 11; pub const KERN_CLOCKRATE: c_int = 12; pub const KERN_VNODE: c_int = 13; pub const KERN_PROC: c_int = 14; pub const KERN_FILE: c_int = 15; pub const KERN_PROF: c_int = 16; pub const KERN_POSIX1: c_int = 17; pub const KERN_NGROUPS: c_int = 18; pub const KERN_JOB_CONTROL: c_int = 19; pub const KERN_SAVED_IDS: c_int = 20; pub const KERN_BOOTTIME: c_int = 21; pub const KERN_NISDOMAINNAME: c_int = 22; pub const KERN_UPDATEINTERVAL: c_int = 23; pub const KERN_OSRELDATE: c_int = 24; pub const KERN_NTP_PLL: c_int = 25; pub const KERN_BOOTFILE: c_int = 26; pub const KERN_MAXFILESPERPROC: c_int = 27; pub const KERN_MAXPROCPERUID: c_int = 28; pub const KERN_DUMPDEV: c_int = 29; pub const KERN_IPC: c_int = 30; pub const KERN_DUMMY: c_int = 31; pub const KERN_PS_STRINGS: c_int = 32; pub const KERN_USRSTACK: c_int = 33; pub const KERN_LOGSIGEXIT: c_int = 34; pub const KERN_IOV_MAX: c_int = 35; pub const KERN_MAXPOSIXLOCKSPERUID: c_int = 36; pub const KERN_MAXID: c_int = 37; pub const KERN_PROC_ALL: c_int = 0; pub const KERN_PROC_PID: c_int = 1; pub const KERN_PROC_PGRP: c_int = 2; pub const KERN_PROC_SESSION: c_int = 3; pub const KERN_PROC_TTY: c_int = 4; pub const KERN_PROC_UID: c_int = 5; pub const KERN_PROC_RUID: c_int = 6; pub const KERN_PROC_ARGS: c_int = 7; pub const KERN_PROC_CWD: c_int = 8; pub const KERN_PROC_PATHNAME: c_int = 9; pub const KERN_PROC_FLAGMASK: c_int = 0x10; pub const KERN_PROC_FLAG_LWP: c_int = 0x10; pub const KIPC_MAXSOCKBUF: c_int = 1; pub const KIPC_SOCKBUF_WASTE: c_int = 2; pub const KIPC_SOMAXCONN: c_int = 3; pub const KIPC_MAX_LINKHDR: c_int = 4; pub const KIPC_MAX_PROTOHDR: c_int = 5; pub const KIPC_MAX_HDR: c_int = 6; pub const KIPC_MAX_DATALEN: c_int = 7; pub const KIPC_MBSTAT: c_int = 8; pub const KIPC_NMBCLUSTERS: c_int = 9; pub const HW_MACHINE: c_int = 1; pub const HW_MODEL: c_int = 2; pub const HW_NCPU: c_int = 3; pub const HW_BYTEORDER: c_int = 4; pub const HW_PHYSMEM: c_int = 5; pub const HW_USERMEM: c_int = 6; pub const HW_PAGESIZE: c_int = 7; pub const HW_DISKNAMES: c_int = 8; pub const HW_DISKSTATS: c_int = 9; pub const HW_FLOATINGPT: c_int = 10; pub const HW_MACHINE_ARCH: c_int = 11; pub const HW_MACHINE_PLATFORM: c_int = 12; pub const HW_SENSORS: c_int = 13; pub const HW_MAXID: c_int = 14; pub const USER_CS_PATH: c_int = 1; pub const USER_BC_BASE_MAX: c_int = 2; pub const USER_BC_DIM_MAX: c_int = 3; pub const USER_BC_SCALE_MAX: c_int = 4; pub const USER_BC_STRING_MAX: c_int = 5; pub const USER_COLL_WEIGHTS_MAX: c_int = 6; pub const USER_EXPR_NEST_MAX: c_int = 7; pub const USER_LINE_MAX: c_int = 8; pub const USER_RE_DUP_MAX: c_int = 9; pub const USER_POSIX2_VERSION: c_int = 10; pub const USER_POSIX2_C_BIND: c_int = 11; pub const USER_POSIX2_C_DEV: c_int = 12; pub const USER_POSIX2_CHAR_TERM: c_int = 13; pub const USER_POSIX2_FORT_DEV: c_int = 14; pub const USER_POSIX2_FORT_RUN: c_int = 15; pub const USER_POSIX2_LOCALEDEF: c_int = 16; pub const USER_POSIX2_SW_DEV: c_int = 17; pub const USER_POSIX2_UPE: c_int = 18; pub const USER_STREAM_MAX: c_int = 19; pub const USER_TZNAME_MAX: c_int = 20; pub const USER_MAXID: c_int = 21; pub const CTL_P1003_1B_ASYNCHRONOUS_IO: c_int = 1; pub const CTL_P1003_1B_MAPPED_FILES: c_int = 2; pub const CTL_P1003_1B_MEMLOCK: c_int = 3; pub const CTL_P1003_1B_MEMLOCK_RANGE: c_int = 4; pub const CTL_P1003_1B_MEMORY_PROTECTION: c_int = 5; pub const CTL_P1003_1B_MESSAGE_PASSING: c_int = 6; pub const CTL_P1003_1B_PRIORITIZED_IO: c_int = 7; pub const CTL_P1003_1B_PRIORITY_SCHEDULING: c_int = 8; pub const CTL_P1003_1B_REALTIME_SIGNALS: c_int = 9; pub const CTL_P1003_1B_SEMAPHORES: c_int = 10; pub const CTL_P1003_1B_FSYNC: c_int = 11; pub const CTL_P1003_1B_SHARED_MEMORY_OBJECTS: c_int = 12; pub const CTL_P1003_1B_SYNCHRONIZED_IO: c_int = 13; pub const CTL_P1003_1B_TIMERS: c_int = 14; pub const CTL_P1003_1B_AIO_LISTIO_MAX: c_int = 15; pub const CTL_P1003_1B_AIO_MAX: c_int = 16; pub const CTL_P1003_1B_AIO_PRIO_DELTA_MAX: c_int = 17; pub const CTL_P1003_1B_DELAYTIMER_MAX: c_int = 18; pub const CTL_P1003_1B_UNUSED1: c_int = 19; pub const CTL_P1003_1B_PAGESIZE: c_int = 20; pub const CTL_P1003_1B_RTSIG_MAX: c_int = 21; pub const CTL_P1003_1B_SEM_NSEMS_MAX: c_int = 22; pub const CTL_P1003_1B_SEM_VALUE_MAX: c_int = 23; pub const CTL_P1003_1B_SIGQUEUE_MAX: c_int = 24; pub const CTL_P1003_1B_TIMER_MAX: c_int = 25; pub const CTL_P1003_1B_MAXID: c_int = 26; pub const CPUCTL_RSMSR: c_int = 0xc0106301; pub const CPUCTL_WRMSR: c_int = 0xc0106302; pub const CPUCTL_CPUID: c_int = 0xc0106303; pub const CPUCTL_UPDATE: c_int = 0xc0106304; pub const CPUCTL_MSRSBIT: c_int = 0xc0106305; pub const CPUCTL_MSRCBIT: c_int = 0xc0106306; pub const CPUCTL_CPUID_COUNT: c_int = 0xc0106307; pub const CPU_SETSIZE: size_t = mem::size_of::() * 8; pub const EVFILT_READ: i16 = -1; pub const EVFILT_WRITE: i16 = -2; pub const EVFILT_AIO: i16 = -3; pub const EVFILT_VNODE: i16 = -4; pub const EVFILT_PROC: i16 = -5; pub const EVFILT_SIGNAL: i16 = -6; pub const EVFILT_TIMER: i16 = -7; pub const EVFILT_EXCEPT: i16 = -8; pub const EVFILT_USER: i16 = -9; pub const EVFILT_FS: i16 = -10; pub const EV_ADD: u16 = 0x1; pub const EV_DELETE: u16 = 0x2; pub const EV_ENABLE: u16 = 0x4; pub const EV_DISABLE: u16 = 0x8; pub const EV_ONESHOT: u16 = 0x10; pub const EV_CLEAR: u16 = 0x20; pub const EV_RECEIPT: u16 = 0x40; pub const EV_DISPATCH: u16 = 0x80; pub const EV_NODATA: u16 = 0x1000; pub const EV_FLAG1: u16 = 0x2000; pub const EV_ERROR: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; pub const EV_HUP: u16 = 0x8000; pub const EV_SYSFLAGS: u16 = 0xf000; pub const FIODNAME: c_ulong = 0x80106678; pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; pub const NOTE_FFOR: u32 = 0x80000000; pub const NOTE_FFCOPY: u32 = 0xc0000000; pub const NOTE_FFCTRLMASK: u32 = 0xc0000000; pub const NOTE_FFLAGSMASK: u32 = 0x00ffffff; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_OOB: u32 = 0x00000002; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xf0000000; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const SO_SNDSPACE: c_int = 0x100a; pub const SO_CPUHINT: c_int = 0x1030; pub const SO_PASSCRED: c_int = 0x4000; pub const PT_FIRSTMACH: c_int = 32; pub const PROC_REAP_ACQUIRE: c_int = 0x0001; pub const PROC_REAP_RELEASE: c_int = 0x0002; pub const PROC_REAP_STATUS: c_int = 0x0003; pub const PROC_PDEATHSIG_CTL: c_int = 0x0004; pub const PROC_PDEATHSIG_STATUS: c_int = 0x0005; // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/HEAD/sys/net/if.h#L101 pub const IFF_UP: c_int = 0x1; // interface is up pub const IFF_BROADCAST: c_int = 0x2; // broadcast address valid pub const IFF_DEBUG: c_int = 0x4; // turn on debugging pub const IFF_LOOPBACK: c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: c_int = 0x10; // interface is point-to-point link pub const IFF_SMART: c_int = 0x20; // interface manages own routes pub const IFF_RUNNING: c_int = 0x40; // resources allocated pub const IFF_NOARP: c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: c_int = 0x100; // receive all packets pub const IFF_ALLMULTI: c_int = 0x200; // receive all multicast packets pub const IFF_OACTIVE_COMPAT: c_int = 0x400; // was transmission in progress pub const IFF_SIMPLEX: c_int = 0x800; // can't hear own transmissions pub const IFF_LINK0: c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: c_int = 0x4000; // per link layer defined bit pub const IFF_ALTPHYS: c_int = IFF_LINK2; // use alternate physical connection pub const IFF_MULTICAST: c_int = 0x8000; // supports multicast // was interface is in polling mode pub const IFF_POLLING_COMPAT: c_int = 0x10000; pub const IFF_PPROMISC: c_int = 0x20000; // user-requested promisc mode pub const IFF_MONITOR: c_int = 0x40000; // user-requested monitor mode pub const IFF_STATICARP: c_int = 0x80000; // static ARP pub const IFF_NPOLLING: c_int = 0x100000; // interface is in polling mode pub const IFF_IDIRECT: c_int = 0x200000; // direct input // // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// IP6 hop-by-hop options pub const IPPROTO_HOPOPTS: c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: c_int = 2; /// gateway^2 (deprecated) pub const IPPROTO_GGP: c_int = 3; /// for compatibility pub const IPPROTO_IPIP: c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// Stream protocol II. pub const IPPROTO_ST: c_int = 7; /// exterior gateway protocol pub const IPPROTO_EGP: c_int = 8; /// private interior gateway pub const IPPROTO_PIGP: c_int = 9; /// BBN RCC Monitoring pub const IPPROTO_RCCMON: c_int = 10; /// network voice protocol pub const IPPROTO_NVPII: c_int = 11; /// pup pub const IPPROTO_PUP: c_int = 12; /// Argus pub const IPPROTO_ARGUS: c_int = 13; /// EMCON pub const IPPROTO_EMCON: c_int = 14; /// Cross Net Debugger pub const IPPROTO_XNET: c_int = 15; /// Chaos pub const IPPROTO_CHAOS: c_int = 16; // IPPROTO_UDP defined in src/unix/mod.rs /// Multiplexing pub const IPPROTO_MUX: c_int = 18; /// DCN Measurement Subsystems pub const IPPROTO_MEAS: c_int = 19; /// Host Monitoring pub const IPPROTO_HMP: c_int = 20; /// Packet Radio Measurement pub const IPPROTO_PRM: c_int = 21; /// xns idp pub const IPPROTO_IDP: c_int = 22; /// Trunk-1 pub const IPPROTO_TRUNK1: c_int = 23; /// Trunk-2 pub const IPPROTO_TRUNK2: c_int = 24; /// Leaf-1 pub const IPPROTO_LEAF1: c_int = 25; /// Leaf-2 pub const IPPROTO_LEAF2: c_int = 26; /// Reliable Data pub const IPPROTO_RDP: c_int = 27; /// Reliable Transaction pub const IPPROTO_IRTP: c_int = 28; /// tp-4 w/ class negotiation pub const IPPROTO_TP: c_int = 29; /// Bulk Data Transfer pub const IPPROTO_BLT: c_int = 30; /// Network Services pub const IPPROTO_NSP: c_int = 31; /// Merit Internodal pub const IPPROTO_INP: c_int = 32; /// Sequential Exchange pub const IPPROTO_SEP: c_int = 33; /// Third Party Connect pub const IPPROTO_3PC: c_int = 34; /// InterDomain Policy Routing pub const IPPROTO_IDPR: c_int = 35; /// XTP pub const IPPROTO_XTP: c_int = 36; /// Datagram Delivery pub const IPPROTO_DDP: c_int = 37; /// Control Message Transport pub const IPPROTO_CMTP: c_int = 38; /// TP++ Transport pub const IPPROTO_TPXX: c_int = 39; /// IL transport protocol pub const IPPROTO_IL: c_int = 40; // IPPROTO_IPV6 defined in src/unix/mod.rs /// Source Demand Routing pub const IPPROTO_SDRP: c_int = 42; /// IP6 routing header pub const IPPROTO_ROUTING: c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: c_int = 44; /// InterDomain Routing pub const IPPROTO_IDRP: c_int = 45; /// resource reservation pub const IPPROTO_RSVP: c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: c_int = 47; /// Mobile Host Routing pub const IPPROTO_MHRP: c_int = 48; /// BHA pub const IPPROTO_BHA: c_int = 49; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: c_int = 51; /// Integ. Net Layer Security pub const IPPROTO_INLSP: c_int = 52; /// IP with encryption pub const IPPROTO_SWIPE: c_int = 53; /// Next Hop Resolution pub const IPPROTO_NHRP: c_int = 54; /// IP Mobility pub const IPPROTO_MOBILE: c_int = 55; /// Transport Layer Security pub const IPPROTO_TLSP: c_int = 56; /// SKIP pub const IPPROTO_SKIP: c_int = 57; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: c_int = 60; /// any host internal protocol pub const IPPROTO_AHIP: c_int = 61; /// CFTP pub const IPPROTO_CFTP: c_int = 62; /// "hello" routing protocol pub const IPPROTO_HELLO: c_int = 63; /// SATNET/Backroom EXPAK pub const IPPROTO_SATEXPAK: c_int = 64; /// Kryptolan pub const IPPROTO_KRYPTOLAN: c_int = 65; /// Remote Virtual Disk pub const IPPROTO_RVD: c_int = 66; /// Pluribus Packet Core pub const IPPROTO_IPPC: c_int = 67; /// Any distributed FS pub const IPPROTO_ADFS: c_int = 68; /// Satnet Monitoring pub const IPPROTO_SATMON: c_int = 69; /// VISA Protocol pub const IPPROTO_VISA: c_int = 70; /// Packet Core Utility pub const IPPROTO_IPCV: c_int = 71; /// Comp. Prot. Net. Executive pub const IPPROTO_CPNX: c_int = 72; /// Comp. Prot. HeartBeat pub const IPPROTO_CPHB: c_int = 73; /// Wang Span Network pub const IPPROTO_WSN: c_int = 74; /// Packet Video Protocol pub const IPPROTO_PVP: c_int = 75; /// BackRoom SATNET Monitoring pub const IPPROTO_BRSATMON: c_int = 76; /// Sun net disk proto (temp.) pub const IPPROTO_ND: c_int = 77; /// WIDEBAND Monitoring pub const IPPROTO_WBMON: c_int = 78; /// WIDEBAND EXPAK pub const IPPROTO_WBEXPAK: c_int = 79; /// ISO cnlp pub const IPPROTO_EON: c_int = 80; /// VMTP pub const IPPROTO_VMTP: c_int = 81; /// Secure VMTP pub const IPPROTO_SVMTP: c_int = 82; /// Banyon VINES pub const IPPROTO_VINES: c_int = 83; /// TTP pub const IPPROTO_TTP: c_int = 84; /// NSFNET-IGP pub const IPPROTO_IGP: c_int = 85; /// dissimilar gateway prot. pub const IPPROTO_DGP: c_int = 86; /// TCF pub const IPPROTO_TCF: c_int = 87; /// Cisco/GXS IGRP pub const IPPROTO_IGRP: c_int = 88; /// OSPFIGP pub const IPPROTO_OSPFIGP: c_int = 89; /// Strite RPC protocol pub const IPPROTO_SRPC: c_int = 90; /// Locus Address Resoloution pub const IPPROTO_LARP: c_int = 91; /// Multicast Transport pub const IPPROTO_MTP: c_int = 92; /// AX.25 Frames pub const IPPROTO_AX25: c_int = 93; /// IP encapsulated in IP pub const IPPROTO_IPEIP: c_int = 94; /// Mobile Int.ing control pub const IPPROTO_MICP: c_int = 95; /// Semaphore Comm. security pub const IPPROTO_SCCSP: c_int = 96; /// Ethernet IP encapsulation pub const IPPROTO_ETHERIP: c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: c_int = 98; /// any private encr. scheme pub const IPPROTO_APES: c_int = 99; /// GMTP pub const IPPROTO_GMTP: c_int = 100; /// payload compression (IPComp) pub const IPPROTO_IPCOMP: c_int = 108; /* 101-254: Partly Unassigned */ /// Protocol Independent Mcast pub const IPPROTO_PIM: c_int = 103; /// CARP pub const IPPROTO_CARP: c_int = 112; /// PGM pub const IPPROTO_PGM: c_int = 113; /// PFSYNC pub const IPPROTO_PFSYNC: c_int = 240; /* 255: Reserved */ /* BSD Private, local use, namespace incursion, no longer used */ /// divert pseudo-protocol pub const IPPROTO_DIVERT: c_int = 254; pub const IPPROTO_MAX: c_int = 256; /// last return value of *_input(), meaning "all job for this pkt is done". pub const IPPROTO_DONE: c_int = 257; /// Used by RSS: the layer3 protocol is unknown pub const IPPROTO_UNKNOWN: c_int = 258; // sys/netinet/tcp.h pub const TCP_SIGNATURE_ENABLE: c_int = 16; pub const TCP_KEEPINIT: c_int = 32; pub const TCP_FASTKEEP: c_int = 128; pub const AF_BLUETOOTH: c_int = 33; pub const AF_MPLS: c_int = 34; pub const AF_IEEE80211: c_int = 35; pub const PF_BLUETOOTH: c_int = AF_BLUETOOTH; pub const NET_RT_DUMP: c_int = 1; pub const NET_RT_FLAGS: c_int = 2; pub const NET_RT_IFLIST: c_int = 3; pub const NET_RT_MAXID: c_int = 4; pub const SOMAXOPT_SIZE: c_int = 65536; pub const MSG_UNUSED09: c_int = 0x00000200; pub const MSG_NOSIGNAL: c_int = 0x00000400; pub const MSG_SYNC: c_int = 0x00000800; pub const MSG_CMSG_CLOEXEC: c_int = 0x00001000; pub const MSG_FBLOCKING: c_int = 0x00010000; pub const MSG_FNONBLOCKING: c_int = 0x00020000; pub const MSG_FMASK: c_int = 0xFFFF0000; // sys/mount.h pub const MNT_NODEV: c_int = 0x00000010; pub const MNT_AUTOMOUNTED: c_int = 0x00000020; pub const MNT_TRIM: c_int = 0x01000000; pub const MNT_LOCAL: c_int = 0x00001000; pub const MNT_QUOTA: c_int = 0x00002000; pub const MNT_ROOTFS: c_int = 0x00004000; pub const MNT_USER: c_int = 0x00008000; pub const MNT_IGNORE: c_int = 0x00800000; // utmpx entry types pub const EMPTY: c_short = 0; pub const RUN_LVL: c_short = 1; pub const BOOT_TIME: c_short = 2; pub const OLD_TIME: c_short = 3; pub const NEW_TIME: c_short = 4; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const USER_PROCESS: c_short = 7; pub const DEAD_PROCESS: c_short = 8; pub const ACCOUNTING: c_short = 9; pub const SIGNATURE: c_short = 10; pub const DOWNTIME: c_short = 11; // utmpx database types pub const UTX_DB_UTMPX: c_uint = 0; pub const UTX_DB_WTMPX: c_uint = 1; pub const UTX_DB_LASTLOG: c_uint = 2; pub const _UTX_LINESIZE: usize = 32; pub const _UTX_USERSIZE: usize = 32; pub const _UTX_IDSIZE: usize = 4; pub const _UTX_HOSTSIZE: usize = 256; pub const LC_COLLATE_MASK: c_int = 1 << 0; pub const LC_CTYPE_MASK: c_int = 1 << 1; pub const LC_MONETARY_MASK: c_int = 1 << 2; pub const LC_NUMERIC_MASK: c_int = 1 << 3; pub const LC_TIME_MASK: c_int = 1 << 4; pub const LC_MESSAGES_MASK: c_int = 1 << 5; pub const LC_ALL_MASK: c_int = LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK; pub const TIOCSIG: c_ulong = 0x2000745f; pub const BTUARTDISC: c_int = 0x7; pub const TIOCDCDTIMESTAMP: c_ulong = 0x40107458; pub const TIOCISPTMASTER: c_ulong = 0x20007455; pub const TIOCMODG: c_ulong = 0x40047403; pub const TIOCMODS: c_ulong = 0x80047404; pub const TIOCREMOTE: c_ulong = 0x80047469; pub const TIOCTIMESTAMP: c_ulong = 0x40107459; // Constants used by "at" family of system calls. pub const AT_FDCWD: c_int = 0xFFFAFDCD; // invalid file descriptor pub const AT_SYMLINK_NOFOLLOW: c_int = 1; pub const AT_REMOVEDIR: c_int = 2; pub const AT_EACCESS: c_int = 4; pub const AT_SYMLINK_FOLLOW: c_int = 8; pub const VCHECKPT: usize = 19; pub const _PC_2_SYMLINKS: c_int = 22; pub const _PC_TIMESTAMP_RESOLUTION: c_int = 23; pub const _SC_V7_ILP32_OFF32: c_int = 122; pub const _SC_V7_ILP32_OFFBIG: c_int = 123; pub const _SC_V7_LP64_OFF64: c_int = 124; pub const _SC_V7_LPBIG_OFFBIG: c_int = 125; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 126; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 127; pub const WCONTINUED: c_int = 0x4; pub const WSTOPPED: c_int = 0x2; pub const WNOWAIT: c_int = 0x8; pub const WEXITED: c_int = 0x10; pub const WTRAPPED: c_int = 0x20; // Similar to FreeBSD, only the standardized ones are exposed. // There are more. pub const P_PID: idtype_t = 0; pub const P_PGID: idtype_t = 2; pub const P_ALL: idtype_t = 7; // Values for struct rtprio (type_ field) pub const RTP_PRIO_REALTIME: c_ushort = 0; pub const RTP_PRIO_NORMAL: c_ushort = 1; pub const RTP_PRIO_IDLE: c_ushort = 2; pub const RTP_PRIO_THREAD: c_ushort = 3; // Flags for chflags(2) pub const UF_NOHISTORY: c_ulong = 0x00000040; pub const UF_CACHE: c_ulong = 0x00000080; pub const UF_XLINK: c_ulong = 0x00000100; pub const SF_NOHISTORY: c_ulong = 0x00400000; pub const SF_CACHE: c_ulong = 0x00800000; pub const SF_XLINK: c_ulong = 0x01000000; // timespec constants pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; pub const MINCORE_SUPER: c_int = 0x20; // kinfo_proc constants pub const MAXCOMLEN: usize = 16; pub const MAXLOGNAME: usize = 33; pub const NGROUPS: usize = 16; pub const RB_PAUSE: c_int = 0x40000; pub const RB_VIDEO: c_int = 0x20000000; // net/route.h pub const RTF_CLONING: c_int = 0x100; pub const RTF_PRCLONING: c_int = 0x10000; pub const RTF_WASCLONED: c_int = 0x20000; pub const RTF_MPLSOPS: c_int = 0x1000000; pub const RTM_VERSION: c_int = 7; pub const RTAX_MPLS1: c_int = 8; pub const RTAX_MPLS2: c_int = 9; pub const RTAX_MPLS3: c_int = 10; pub const RTAX_MAX: c_int = 11; const_fn! { {const} fn _CMSG_ALIGN(n: usize) -> usize { (n + (mem::size_of::() - 1)) & !(mem::size_of::() - 1) } } f! { pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(_CMSG_ALIGN(mem::size_of::()) as isize) } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { (_CMSG_ALIGN(mem::size_of::()) + length as usize) as c_uint } pub fn CMSG_NXTHDR(mhdr: *const crate::msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { let next = cmsg as usize + _CMSG_ALIGN((*cmsg).cmsg_len as usize) + _CMSG_ALIGN(mem::size_of::()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next <= max { (cmsg as usize + _CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (_CMSG_ALIGN(mem::size_of::()) + _CMSG_ALIGN(length as usize)) as c_uint } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.ary.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let (idx, offset) = ((cpu >> 6) & 3, cpu & 63); cpuset.ary[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let (idx, offset) = ((cpu >> 6) & 3, cpu & 63); cpuset.ary[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let (idx, offset) = ((cpu >> 6) & 3, cpu & 63); 0 != cpuset.ary[idx] & (1 << offset) } } safe_f! { pub {const} fn WIFSIGNALED(status: c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 } pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= major << 8; dev |= minor; dev } pub {const} fn major(dev: crate::dev_t) -> c_int { ((dev >> 8) & 0xff) as c_int } pub {const} fn minor(dev: crate::dev_t) -> c_int { (dev & 0xffff00ff) as c_int } } extern "C" { pub fn __errno_location() -> *mut c_int; pub fn setgrent(); pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn setutxdb(_type: c_uint, file: *mut c_char) -> c_int; pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, timeout: *mut crate::timespec) -> c_int; pub fn devname_r( dev: crate::dev_t, mode: crate::mode_t, buf: *mut c_char, len: size_t, ) -> *mut c_char; pub fn waitid( idtype: idtype_t, id: crate::id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn freelocale(loc: crate::locale_t); pub fn lwp_rtprio( function: c_int, pid: crate::pid_t, lwpid: lwpid_t, rtp: *mut super::rtprio, ) -> c_int; pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int; pub fn sched_getaffinity(pid: crate::pid_t, cpusetsize: size_t, mask: *mut cpu_set_t) -> c_int; pub fn sched_setaffinity( pid: crate::pid_t, cpusetsize: size_t, mask: *const cpu_set_t, ) -> c_int; pub fn sched_getcpu() -> c_int; pub fn setproctitle(fmt: *const c_char, ...); pub fn shmget(key: crate::key_t, size: size_t, shmflg: c_int) -> c_int; pub fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void; pub fn shmdt(shmaddr: *const c_void) -> c_int; pub fn shmctl(shmid: c_int, cmd: c_int, buf: *mut crate::shmid_ds) -> c_int; pub fn procctl( idtype: crate::idtype_t, id: crate::id_t, cmd: c_int, data: *mut c_void, ) -> c_int; pub fn updwtmpx(file: *const c_char, ut: *const utmpx) -> c_int; pub fn getlastlogx(fname: *const c_char, uid: crate::uid_t, ll: *mut lastlogx) -> *mut lastlogx; pub fn updlastlogx(fname: *const c_char, uid: crate::uid_t, ll: *mut lastlogx) -> c_int; pub fn getutxuser(name: *const c_char) -> utmpx; pub fn utmpxname(file: *const c_char) -> c_int; pub fn sys_checkpoint(tpe: c_int, fd: c_int, pid: crate::pid_t, retval: c_int) -> c_int; pub fn umtx_sleep(ptr: *const c_int, value: c_int, timeout: c_int) -> c_int; pub fn umtx_wakeup(ptr: *const c_int, count: c_int) -> c_int; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn basename(path: *mut c_char) -> *mut c_char; pub fn getmntinfo(mntbufp: *mut *mut crate::statfs, flags: c_int) -> c_int; pub fn getmntvinfo( mntbufp: *mut *mut crate::statfs, mntvbufp: *mut *mut crate::statvfs, flags: c_int, ) -> c_int; pub fn closefrom(lowfd: c_int) -> c_int; } #[link(name = "rt")] extern "C" { pub fn aio_cancel(fd: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_error(aiocbp: *const aiocb) -> c_int; pub fn aio_fsync(op: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_read(aiocbp: *mut aiocb) -> c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn aio_write(aiocbp: *mut aiocb) -> c_int; pub fn lio_listio( mode: c_int, aiocb_list: *const *mut aiocb, nitems: c_int, sevp: *mut sigevent, ) -> c_int; pub fn reallocf(ptr: *mut c_void, size: size_t) -> *mut c_void; pub fn freezero(ptr: *mut c_void, size: size_t); } #[link(name = "kvm")] extern "C" { pub fn kvm_vm_map_entry_first( kvm: *mut crate::kvm_t, map: vm_map_t, entry: vm_map_entry_t, ) -> vm_map_entry_t; pub fn kvm_vm_map_entry_next( kvm: *mut crate::kvm_t, map: vm_map_entry_t, entry: vm_map_entry_t, ) -> vm_map_entry_t; } // DIFF(main): module removed in de76fee6 cfg_if! { if #[cfg(libc_thread_local)] { mod errno; pub use self::errno::*; } } libc/src/unix/bsd/freebsdlike/dragonfly/errno.rs0000644000175000017500000000067315105742312021602 0ustar bdrungbdrunguse crate::prelude::*; /* DIFF(main): module removed in de76fee6 */ // DragonFlyBSD's __error function is declared with "static inline", so it must // be implemented in the libc crate, as a pointer to a static thread_local. f! { #[deprecated(since = "0.2.77", note = "Use `__errno_location()` instead")] pub fn __error() -> *mut c_int { &mut errno } } extern "C" { #[thread_local] pub static mut errno: c_int; } libc/src/unix/bsd/freebsdlike/freebsd/0000775000175000017500000000000015105742312017530 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/freebsd/mod.rs0000644000175000017500000060602515105742312020664 0ustar bdrungbdrunguse crate::prelude::*; use crate::{cmsghdr, off_t}; pub type fflags_t = u32; pub type vm_prot_t = u_char; pub type kvaddr_t = u64; pub type segsz_t = isize; pub type __fixpt_t = u32; pub type fixpt_t = __fixpt_t; pub type __lwpid_t = i32; pub type lwpid_t = __lwpid_t; pub type blksize_t = i32; pub type clockid_t = c_int; pub type sem_t = _sem; pub type timer_t = *mut __c_anonymous__timer; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type idtype_t = c_uint; pub type msglen_t = c_ulong; pub type msgqnum_t = c_ulong; pub type cpulevel_t = c_int; pub type cpuwhich_t = c_int; pub type mqd_t = *mut c_void; pub type pthread_spinlock_t = *mut __c_anonymous_pthread_spinlock; pub type pthread_barrierattr_t = *mut __c_anonymous_pthread_barrierattr; pub type pthread_barrier_t = *mut __c_anonymous_pthread_barrier; pub type uuid_t = crate::uuid; pub type u_int = c_uint; pub type u_char = c_uchar; pub type u_long = c_ulong; pub type u_short = c_ushort; pub type caddr_t = *mut c_char; pub type fhandle_t = fhandle; pub type au_id_t = crate::uid_t; pub type au_asid_t = crate::pid_t; pub type cpusetid_t = c_int; pub type sctp_assoc_t = u32; pub type eventfd_t = u64; #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_support_flags { DEVSTAT_ALL_SUPPORTED = 0x00, DEVSTAT_NO_BLOCKSIZE = 0x01, DEVSTAT_NO_ORDERED_TAGS = 0x02, DEVSTAT_BS_UNAVAILABLE = 0x04, } impl Copy for devstat_support_flags {} impl Clone for devstat_support_flags { fn clone(&self) -> devstat_support_flags { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_trans_flags { DEVSTAT_NO_DATA = 0x00, DEVSTAT_READ = 0x01, DEVSTAT_WRITE = 0x02, DEVSTAT_FREE = 0x03, } impl Copy for devstat_trans_flags {} impl Clone for devstat_trans_flags { fn clone(&self) -> devstat_trans_flags { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_tag_type { DEVSTAT_TAG_SIMPLE = 0x00, DEVSTAT_TAG_HEAD = 0x01, DEVSTAT_TAG_ORDERED = 0x02, DEVSTAT_TAG_NONE = 0x03, } impl Copy for devstat_tag_type {} impl Clone for devstat_tag_type { fn clone(&self) -> devstat_tag_type { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_match_flags { DEVSTAT_MATCH_NONE = 0x00, DEVSTAT_MATCH_TYPE = 0x01, DEVSTAT_MATCH_IF = 0x02, DEVSTAT_MATCH_PASS = 0x04, } impl Copy for devstat_match_flags {} impl Clone for devstat_match_flags { fn clone(&self) -> devstat_match_flags { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_priority { DEVSTAT_PRIORITY_MIN = 0x000, DEVSTAT_PRIORITY_OTHER = 0x020, DEVSTAT_PRIORITY_PASS = 0x030, DEVSTAT_PRIORITY_FD = 0x040, DEVSTAT_PRIORITY_WFD = 0x050, DEVSTAT_PRIORITY_TAPE = 0x060, DEVSTAT_PRIORITY_CD = 0x090, DEVSTAT_PRIORITY_DISK = 0x110, DEVSTAT_PRIORITY_ARRAY = 0x120, DEVSTAT_PRIORITY_MAX = 0xfff, } impl Copy for devstat_priority {} impl Clone for devstat_priority { fn clone(&self) -> devstat_priority { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_type_flags { DEVSTAT_TYPE_DIRECT = 0x000, DEVSTAT_TYPE_SEQUENTIAL = 0x001, DEVSTAT_TYPE_PRINTER = 0x002, DEVSTAT_TYPE_PROCESSOR = 0x003, DEVSTAT_TYPE_WORM = 0x004, DEVSTAT_TYPE_CDROM = 0x005, DEVSTAT_TYPE_SCANNER = 0x006, DEVSTAT_TYPE_OPTICAL = 0x007, DEVSTAT_TYPE_CHANGER = 0x008, DEVSTAT_TYPE_COMM = 0x009, DEVSTAT_TYPE_ASC0 = 0x00a, DEVSTAT_TYPE_ASC1 = 0x00b, DEVSTAT_TYPE_STORARRAY = 0x00c, DEVSTAT_TYPE_ENCLOSURE = 0x00d, DEVSTAT_TYPE_FLOPPY = 0x00e, DEVSTAT_TYPE_MASK = 0x00f, DEVSTAT_TYPE_IF_SCSI = 0x010, DEVSTAT_TYPE_IF_IDE = 0x020, DEVSTAT_TYPE_IF_OTHER = 0x030, DEVSTAT_TYPE_IF_MASK = 0x0f0, DEVSTAT_TYPE_PASS = 0x100, } impl Copy for devstat_type_flags {} impl Clone for devstat_type_flags { fn clone(&self) -> devstat_type_flags { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_metric { DSM_NONE, DSM_TOTAL_BYTES, DSM_TOTAL_BYTES_READ, DSM_TOTAL_BYTES_WRITE, DSM_TOTAL_TRANSFERS, DSM_TOTAL_TRANSFERS_READ, DSM_TOTAL_TRANSFERS_WRITE, DSM_TOTAL_TRANSFERS_OTHER, DSM_TOTAL_BLOCKS, DSM_TOTAL_BLOCKS_READ, DSM_TOTAL_BLOCKS_WRITE, DSM_KB_PER_TRANSFER, DSM_KB_PER_TRANSFER_READ, DSM_KB_PER_TRANSFER_WRITE, DSM_TRANSFERS_PER_SECOND, DSM_TRANSFERS_PER_SECOND_READ, DSM_TRANSFERS_PER_SECOND_WRITE, DSM_TRANSFERS_PER_SECOND_OTHER, DSM_MB_PER_SECOND, DSM_MB_PER_SECOND_READ, DSM_MB_PER_SECOND_WRITE, DSM_BLOCKS_PER_SECOND, DSM_BLOCKS_PER_SECOND_READ, DSM_BLOCKS_PER_SECOND_WRITE, DSM_MS_PER_TRANSACTION, DSM_MS_PER_TRANSACTION_READ, DSM_MS_PER_TRANSACTION_WRITE, DSM_SKIP, DSM_TOTAL_BYTES_FREE, DSM_TOTAL_TRANSFERS_FREE, DSM_TOTAL_BLOCKS_FREE, DSM_KB_PER_TRANSFER_FREE, DSM_MB_PER_SECOND_FREE, DSM_TRANSFERS_PER_SECOND_FREE, DSM_BLOCKS_PER_SECOND_FREE, DSM_MS_PER_TRANSACTION_OTHER, DSM_MS_PER_TRANSACTION_FREE, DSM_BUSY_PCT, DSM_QUEUE_LENGTH, DSM_TOTAL_DURATION, DSM_TOTAL_DURATION_READ, DSM_TOTAL_DURATION_WRITE, DSM_TOTAL_DURATION_FREE, DSM_TOTAL_DURATION_OTHER, DSM_TOTAL_BUSY_TIME, DSM_MAX, } impl Copy for devstat_metric {} impl Clone for devstat_metric { fn clone(&self) -> devstat_metric { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_select_mode { DS_SELECT_ADD, DS_SELECT_ONLY, DS_SELECT_REMOVE, DS_SELECT_ADDONLY, } impl Copy for devstat_select_mode {} impl Clone for devstat_select_mode { fn clone(&self) -> devstat_select_mode { *self } } s! { pub struct aiocb { pub aio_fildes: c_int, pub aio_offset: off_t, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, __unused1: [c_int; 2], __unused2: *mut c_void, pub aio_lio_opcode: c_int, pub aio_reqprio: c_int, // unused 3 through 5 are the __aiocb_private structure __unused3: c_long, __unused4: c_long, __unused5: *mut c_void, pub aio_sigevent: sigevent, } pub struct jail { pub version: u32, pub path: *mut c_char, pub hostname: *mut c_char, pub jailname: *mut c_char, pub ip4s: c_uint, pub ip6s: c_uint, pub ip4: *mut crate::in_addr, pub ip6: *mut crate::in6_addr, } pub struct statvfs { pub f_bavail: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_blocks: crate::fsblkcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_files: crate::fsfilcnt_t, pub f_bsize: c_ulong, pub f_flag: c_ulong, pub f_frsize: c_ulong, pub f_fsid: c_ulong, pub f_namemax: c_ulong, } // internal structure has changed over time pub struct _sem { data: [u32; 4], } pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } pub struct input_event { pub time: crate::timeval, pub type_: crate::u_short, pub code: crate::u_short, pub value: i32, } pub struct input_absinfo { pub value: i32, pub minimum: i32, pub maximum: i32, pub fuzz: i32, pub flat: i32, pub resolution: i32, } pub struct msqid_ds { pub msg_perm: crate::ipc_perm, __unused1: *mut c_void, __unused2: *mut c_void, pub msg_cbytes: crate::msglen_t, pub msg_qnum: crate::msgqnum_t, pub msg_qbytes: crate::msglen_t, pub msg_lspid: crate::pid_t, pub msg_lrpid: crate::pid_t, pub msg_stime: crate::time_t, pub msg_rtime: crate::time_t, pub msg_ctime: crate::time_t, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct mmsghdr { pub msg_hdr: crate::msghdr, pub msg_len: ssize_t, } pub struct sockcred { pub sc_uid: crate::uid_t, pub sc_euid: crate::uid_t, pub sc_gid: crate::gid_t, pub sc_egid: crate::gid_t, pub sc_ngroups: c_int, pub sc_groups: [crate::gid_t; 1], } pub struct ptrace_vm_entry { pub pve_entry: c_int, pub pve_timestamp: c_int, pub pve_start: c_ulong, pub pve_end: c_ulong, pub pve_offset: c_ulong, pub pve_prot: c_uint, pub pve_pathlen: c_uint, pub pve_fileid: c_long, pub pve_fsid: u32, pub pve_path: *mut c_char, } pub struct ptrace_lwpinfo { pub pl_lwpid: lwpid_t, pub pl_event: c_int, pub pl_flags: c_int, pub pl_sigmask: crate::sigset_t, pub pl_siglist: crate::sigset_t, pub pl_siginfo: crate::siginfo_t, pub pl_tdname: [c_char; crate::MAXCOMLEN as usize + 1], pub pl_child_pid: crate::pid_t, pub pl_syscall_code: c_uint, pub pl_syscall_narg: c_uint, } pub struct ptrace_sc_ret { pub sr_retval: [crate::register_t; 2], pub sr_error: c_int, } pub struct ptrace_coredump { pub pc_fd: c_int, pub pc_flags: u32, pub pc_limit: off_t, } pub struct ptrace_sc_remote { pub pscr_ret: ptrace_sc_ret, pub pscr_syscall: c_uint, pub pscr_nargs: c_uint, pub pscr_args: *mut crate::register_t, } pub struct cpuset_t { #[cfg(all(any(freebsd15, freebsd14), target_pointer_width = "64"))] __bits: [c_long; 16], #[cfg(all(any(freebsd15, freebsd14), target_pointer_width = "32"))] __bits: [c_long; 32], #[cfg(all(not(any(freebsd15, freebsd14)), target_pointer_width = "64"))] __bits: [c_long; 4], #[cfg(all(not(any(freebsd15, freebsd14)), target_pointer_width = "32"))] __bits: [c_long; 8], } pub struct cap_rights_t { cr_rights: [u64; 2], } pub struct umutex { m_owner: crate::lwpid_t, m_flags: u32, m_ceilings: [u32; 2], m_rb_link: crate::uintptr_t, #[cfg(target_pointer_width = "32")] m_pad: u32, m_spare: [u32; 2], } pub struct ucond { c_has_waiters: u32, c_flags: u32, c_clockid: u32, c_spare: [u32; 1], } pub struct uuid { pub time_low: u32, pub time_mid: u16, pub time_hi_and_version: u16, pub clock_seq_hi_and_reserved: u8, pub clock_seq_low: u8, pub node: [u8; _UUID_NODE_LEN], } pub struct __c_anonymous_pthread_spinlock { s_clock: umutex, } pub struct __c_anonymous_pthread_barrierattr { pshared: c_int, } pub struct __c_anonymous_pthread_barrier { b_lock: umutex, b_cv: ucond, b_cycle: i64, b_count: c_int, b_waiters: c_int, b_refcount: c_int, b_destroying: c_int, } pub struct kinfo_vmentry { pub kve_structsize: c_int, pub kve_type: c_int, pub kve_start: u64, pub kve_end: u64, pub kve_offset: u64, pub kve_vn_fileid: u64, #[cfg(not(freebsd11))] pub kve_vn_fsid_freebsd11: u32, #[cfg(freebsd11)] pub kve_vn_fsid: u32, pub kve_flags: c_int, pub kve_resident: c_int, pub kve_private_resident: c_int, pub kve_protection: c_int, pub kve_ref_count: c_int, pub kve_shadow_count: c_int, pub kve_vn_type: c_int, pub kve_vn_size: u64, #[cfg(not(freebsd11))] pub kve_vn_rdev_freebsd11: u32, #[cfg(freebsd11)] pub kve_vn_rdev: u32, pub kve_vn_mode: u16, pub kve_status: u16, #[cfg(not(freebsd11))] pub kve_vn_fsid: u64, #[cfg(not(freebsd11))] pub kve_vn_rdev: u64, #[cfg(not(freebsd11))] _kve_is_spare: [c_int; 8], #[cfg(freebsd11)] _kve_is_spare: [c_int; 12], pub kve_path: [[c_char; 32]; 32], } pub struct __c_anonymous_filestat { pub stqe_next: *mut filestat, } pub struct filestat { pub fs_type: c_int, pub fs_flags: c_int, pub fs_fflags: c_int, pub fs_uflags: c_int, pub fs_fd: c_int, pub fs_ref_count: c_int, pub fs_offset: off_t, pub fs_typedep: *mut c_void, pub fs_path: *mut c_char, pub next: __c_anonymous_filestat, pub fs_cap_rights: cap_rights_t, } pub struct filestat_list { pub stqh_first: *mut filestat, pub stqh_last: *mut *mut filestat, } pub struct procstat { pub tpe: c_int, pub kd: crate::uintptr_t, pub vmentries: *mut c_void, pub files: *mut c_void, pub argv: *mut c_void, pub envv: *mut c_void, pub core: crate::uintptr_t, } pub struct itimerspec { pub it_interval: crate::timespec, pub it_value: crate::timespec, } pub struct __c_anonymous__timer { _priv: [c_int; 3], } /// Used to hold a copy of the command line, if it had a sane length. pub struct pargs { /// Reference count. pub ar_ref: u_int, /// Length. pub ar_length: u_int, /// Arguments. pub ar_args: [c_uchar; 1], } pub struct priority { /// Scheduling class. pub pri_class: u_char, /// Normal priority level. pub pri_level: u_char, /// Priority before propagation. pub pri_native: u_char, /// User priority based on p_cpu and p_nice. pub pri_user: u_char, } pub struct kvm_swap { pub ksw_devname: [c_char; 32], pub ksw_used: u_int, pub ksw_total: u_int, pub ksw_flags: c_int, pub ksw_reserved1: u_int, pub ksw_reserved2: u_int, } pub struct nlist { /// symbol name (in memory) pub n_name: *const c_char, /// type defines pub n_type: c_uchar, /// "type" and binding information pub n_other: c_char, /// used by stab entries pub n_desc: c_short, pub n_value: c_ulong, } pub struct kvm_nlist { pub n_name: *const c_char, pub n_type: c_uchar, pub n_value: crate::kvaddr_t, } pub struct __c_anonymous_sem { _priv: crate::uintptr_t, } pub struct semid_ds { pub sem_perm: crate::ipc_perm, pub __sem_base: *mut __c_anonymous_sem, pub sem_nsems: c_ushort, pub sem_otime: crate::time_t, pub sem_ctime: crate::time_t, } pub struct vmtotal { pub t_vm: u64, pub t_avm: u64, pub t_rm: u64, pub t_arm: u64, pub t_vmshr: u64, pub t_avmshr: u64, pub t_rmshr: u64, pub t_armshr: u64, pub t_free: u64, pub t_rq: i16, pub t_dw: i16, pub t_pw: i16, pub t_sl: i16, pub t_sw: i16, pub t_pad: [u16; 3], } pub struct sockstat { pub inp_ppcb: u64, pub so_addr: u64, pub so_pcb: u64, pub unp_conn: u64, pub dom_family: c_int, pub proto: c_int, pub so_rcv_sb_state: c_int, pub so_snd_sb_state: c_int, /// Socket address. pub sa_local: crate::sockaddr_storage, /// Peer address. pub sa_peer: crate::sockaddr_storage, pub type_: c_int, pub dname: [c_char; 32], #[cfg(any(freebsd12, freebsd13, freebsd14, freebsd15))] pub sendq: c_uint, #[cfg(any(freebsd12, freebsd13, freebsd14, freebsd15))] pub recvq: c_uint, } pub struct shmstat { pub size: u64, pub mode: u16, } pub struct spacectl_range { pub r_offset: off_t, pub r_len: off_t, } pub struct rusage_ext { pub rux_runtime: u64, pub rux_uticks: u64, pub rux_sticks: u64, pub rux_iticks: u64, pub rux_uu: u64, pub rux_su: u64, pub rux_tu: u64, } pub struct if_clonereq { pub ifcr_total: c_int, pub ifcr_count: c_int, pub ifcr_buffer: *mut c_char, } pub struct if_msghdr { /// to skip over non-understood messages pub ifm_msglen: c_ushort, /// future binary compatibility pub ifm_version: c_uchar, /// message type pub ifm_type: c_uchar, /// like rtm_addrs pub ifm_addrs: c_int, /// value of if_flags pub ifm_flags: c_int, /// index for associated ifp pub ifm_index: c_ushort, pub _ifm_spare1: c_ushort, /// statistics and other data about if pub ifm_data: if_data, } pub struct if_msghdrl { /// to skip over non-understood messages pub ifm_msglen: c_ushort, /// future binary compatibility pub ifm_version: c_uchar, /// message type pub ifm_type: c_uchar, /// like rtm_addrs pub ifm_addrs: c_int, /// value of if_flags pub ifm_flags: c_int, /// index for associated ifp pub ifm_index: c_ushort, /// spare space to grow if_index, see if_var.h pub _ifm_spare1: c_ushort, /// length of if_msghdrl incl. if_data pub ifm_len: c_ushort, /// offset of if_data from beginning pub ifm_data_off: c_ushort, pub _ifm_spare2: c_int, /// statistics and other data about if pub ifm_data: if_data, } pub struct ifa_msghdr { /// to skip over non-understood messages pub ifam_msglen: c_ushort, /// future binary compatibility pub ifam_version: c_uchar, /// message type pub ifam_type: c_uchar, /// like rtm_addrs pub ifam_addrs: c_int, /// value of ifa_flags pub ifam_flags: c_int, /// index for associated ifp pub ifam_index: c_ushort, pub _ifam_spare1: c_ushort, /// value of ifa_ifp->if_metric pub ifam_metric: c_int, } pub struct ifa_msghdrl { /// to skip over non-understood messages pub ifam_msglen: c_ushort, /// future binary compatibility pub ifam_version: c_uchar, /// message type pub ifam_type: c_uchar, /// like rtm_addrs pub ifam_addrs: c_int, /// value of ifa_flags pub ifam_flags: c_int, /// index for associated ifp pub ifam_index: c_ushort, /// spare space to grow if_index, see if_var.h pub _ifam_spare1: c_ushort, /// length of ifa_msghdrl incl. if_data pub ifam_len: c_ushort, /// offset of if_data from beginning pub ifam_data_off: c_ushort, /// value of ifa_ifp->if_metric pub ifam_metric: c_int, /// statistics and other data about if or address pub ifam_data: if_data, } pub struct ifma_msghdr { /// to skip over non-understood messages pub ifmam_msglen: c_ushort, /// future binary compatibility pub ifmam_version: c_uchar, /// message type pub ifmam_type: c_uchar, /// like rtm_addrs pub ifmam_addrs: c_int, /// value of ifa_flags pub ifmam_flags: c_int, /// index for associated ifp pub ifmam_index: c_ushort, pub _ifmam_spare1: c_ushort, } pub struct if_announcemsghdr { /// to skip over non-understood messages pub ifan_msglen: c_ushort, /// future binary compatibility pub ifan_version: c_uchar, /// message type pub ifan_type: c_uchar, /// index for associated ifp pub ifan_index: c_ushort, /// if name, e.g. "en0" pub ifan_name: [c_char; crate::IFNAMSIZ as usize], /// what type of announcement pub ifan_what: c_ushort, } pub struct ifreq_buffer { pub length: size_t, pub buffer: *mut c_void, } pub struct ifaliasreq { /// if name, e.g. "en0" pub ifra_name: [c_char; crate::IFNAMSIZ as usize], pub ifra_addr: crate::sockaddr, pub ifra_broadaddr: crate::sockaddr, pub ifra_mask: crate::sockaddr, pub ifra_vhid: c_int, } /// 9.x compat pub struct oifaliasreq { /// if name, e.g. "en0" pub ifra_name: [c_char; crate::IFNAMSIZ as usize], pub ifra_addr: crate::sockaddr, pub ifra_broadaddr: crate::sockaddr, pub ifra_mask: crate::sockaddr, } pub struct ifmediareq { /// if name, e.g. "en0" pub ifm_name: [c_char; crate::IFNAMSIZ as usize], /// current media options pub ifm_current: c_int, /// don't care mask pub ifm_mask: c_int, /// media status pub ifm_status: c_int, /// active options pub ifm_active: c_int, /// # entries in ifm_ulist array pub ifm_count: c_int, /// media words pub ifm_ulist: *mut c_int, } pub struct ifdrv { /// if name, e.g. "en0" pub ifd_name: [c_char; crate::IFNAMSIZ as usize], pub ifd_cmd: c_ulong, pub ifd_len: size_t, pub ifd_data: *mut c_void, } pub struct ifi2creq { /// i2c address (0xA0, 0xA2) pub dev_addr: u8, /// read offset pub offset: u8, /// read length pub len: u8, pub spare0: u8, pub spare1: u32, /// read buffer pub data: [u8; 8], } pub struct ifrsshash { /// if name, e.g. "en0" pub ifrh_name: [c_char; crate::IFNAMSIZ as usize], /// RSS_FUNC_ pub ifrh_func: u8, pub ifrh_spare0: u8, pub ifrh_spare1: u16, /// RSS_TYPE_ pub ifrh_types: u32, } pub struct ifmibdata { /// name of interface pub ifmd_name: [c_char; crate::IFNAMSIZ as usize], /// number of promiscuous listeners pub ifmd_pcount: c_int, /// interface flags pub ifmd_flags: c_int, /// instantaneous length of send queue pub ifmd_snd_len: c_int, /// maximum length of send queue pub ifmd_snd_maxlen: c_int, /// number of drops in send queue pub ifmd_snd_drops: c_int, /// for future expansion pub ifmd_filler: [c_int; 4], /// generic information and statistics pub ifmd_data: if_data, } pub struct ifmib_iso_8802_3 { pub dot3StatsAlignmentErrors: u32, pub dot3StatsFCSErrors: u32, pub dot3StatsSingleCollisionFrames: u32, pub dot3StatsMultipleCollisionFrames: u32, pub dot3StatsSQETestErrors: u32, pub dot3StatsDeferredTransmissions: u32, pub dot3StatsLateCollisions: u32, pub dot3StatsExcessiveCollisions: u32, pub dot3StatsInternalMacTransmitErrors: u32, pub dot3StatsCarrierSenseErrors: u32, pub dot3StatsFrameTooLongs: u32, pub dot3StatsInternalMacReceiveErrors: u32, pub dot3StatsEtherChipSet: u32, pub dot3StatsMissedFrames: u32, pub dot3StatsCollFrequencies: [u32; 16], pub dot3Compliance: u32, } pub struct __c_anonymous_ph { pub ph1: u64, pub ph2: u64, } pub struct fid { pub fid_len: c_ushort, pub fid_data0: c_ushort, pub fid_data: [c_char; crate::MAXFIDSZ as usize], } pub struct fhandle { pub fh_fsid: crate::fsid_t, pub fh_fid: fid, } pub struct bintime { pub sec: crate::time_t, pub frac: u64, } pub struct clockinfo { /// clock frequency pub hz: c_int, /// micro-seconds per hz tick pub tick: c_int, pub spare: c_int, /// statistics clock frequency pub stathz: c_int, /// profiling clock frequency pub profhz: c_int, } pub struct __c_anonymous_stailq_entry_devstat { pub stqe_next: *mut devstat, } pub struct devstat { /// Update sequence pub sequence0: crate::u_int, /// Allocated entry pub allocated: c_int, /// started ops pub start_count: crate::u_int, /// completed ops pub end_count: crate::u_int, /// busy time unaccounted for since this time pub busy_from: bintime, pub dev_links: __c_anonymous_stailq_entry_devstat, /// Devstat device number. pub device_number: u32, pub device_name: [c_char; DEVSTAT_NAME_LEN as usize], pub unit_number: c_int, pub bytes: [u64; DEVSTAT_N_TRANS_FLAGS as usize], pub operations: [u64; DEVSTAT_N_TRANS_FLAGS as usize], pub duration: [bintime; DEVSTAT_N_TRANS_FLAGS as usize], pub busy_time: bintime, /// Time the device was created. pub creation_time: bintime, /// Block size, bytes pub block_size: u32, /// The number of simple, ordered, and head of queue tags sent. pub tag_types: [u64; 3], /// Which statistics are supported by a given device. pub flags: devstat_support_flags, /// Device type pub device_type: devstat_type_flags, /// Controls list pos. pub priority: devstat_priority, /// Identification for GEOM nodes pub id: *const c_void, /// Update sequence pub sequence1: crate::u_int, } pub struct devstat_match { pub match_fields: devstat_match_flags, pub device_type: devstat_type_flags, pub num_match_categories: c_int, } pub struct devstat_match_table { pub match_str: *const c_char, pub type_: devstat_type_flags, pub match_field: devstat_match_flags, } pub struct device_selection { pub device_number: u32, pub device_name: [c_char; DEVSTAT_NAME_LEN as usize], pub unit_number: c_int, pub selected: c_int, pub bytes: u64, pub position: c_int, } pub struct devinfo { pub devices: *mut devstat, pub mem_ptr: *mut u8, pub generation: c_long, pub numdevs: c_int, } pub struct sockcred2 { pub sc_version: c_int, pub sc_pid: crate::pid_t, pub sc_uid: crate::uid_t, pub sc_euid: crate::uid_t, pub sc_gid: crate::gid_t, pub sc_egid: crate::gid_t, pub sc_ngroups: c_int, pub sc_groups: [crate::gid_t; 1], } pub struct ifconf { pub ifc_len: c_int, pub ifc_ifcu: __c_anonymous_ifc_ifcu, } pub struct au_mask_t { pub am_success: c_uint, pub am_failure: c_uint, } pub struct au_tid_t { pub port: u32, pub machine: u32, } pub struct auditinfo_t { pub ai_auid: crate::au_id_t, pub ai_mask: crate::au_mask_t, pub ai_termid: au_tid_t, pub ai_asid: crate::au_asid_t, } pub struct tcp_fastopen { pub enable: c_int, pub psk: [u8; crate::TCP_FASTOPEN_PSK_LEN as usize], } pub struct tcp_function_set { pub function_set_name: [c_char; crate::TCP_FUNCTION_NAME_LEN_MAX as usize], pub pcbcnt: u32, } // Note: this structure will change in a backwards-incompatible way in // FreeBSD 15. pub struct tcp_info { pub tcpi_state: u8, pub __tcpi_ca_state: u8, pub __tcpi_retransmits: u8, pub __tcpi_probes: u8, pub __tcpi_backoff: u8, pub tcpi_options: u8, pub tcp_snd_wscale: u8, pub tcp_rcv_wscale: u8, pub tcpi_rto: u32, pub __tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub __tcpi_unacked: u32, pub __tcpi_sacked: u32, pub __tcpi_lost: u32, pub __tcpi_retrans: u32, pub __tcpi_fackets: u32, pub __tcpi_last_data_sent: u32, pub __tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub __tcpi_last_ack_recv: u32, pub __tcpi_pmtu: u32, pub __tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub __tcpi_advmss: u32, pub __tcpi_reordering: u32, pub __tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_snd_wnd: u32, pub tcpi_snd_bwnd: u32, pub tcpi_snd_nxt: u32, pub tcpi_rcv_nxt: u32, pub tcpi_toe_tid: u32, pub tcpi_snd_rexmitpack: u32, pub tcpi_rcv_ooopack: u32, pub tcpi_snd_zerowin: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_delivered_ce: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_received_ce: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_delivered_e1_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_delivered_e0_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_delivered_ce_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_received_e1_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_received_e0_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_received_ce_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_total_tlp: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_total_tlp_bytes: u64, #[cfg(any(freebsd15, freebsd14))] pub tcpi_snd_una: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_snd_max: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_rcv_numsacks: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_rcv_adv: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_dupacks: u32, #[cfg(freebsd14)] pub __tcpi_pad: [u32; 10], #[cfg(freebsd15)] pub __tcpi_pad: [u32; 14], #[cfg(not(any(freebsd15, freebsd14)))] pub __tcpi_pad: [u32; 26], } pub struct _umtx_time { pub _timeout: crate::timespec, pub _flags: u32, pub _clockid: u32, } pub struct shm_largepage_conf { pub psind: c_int, pub alloc_policy: c_int, __pad: [c_int; 10], } pub struct memory_type { __priva: [crate::uintptr_t; 32], __privb: [crate::uintptr_t; 26], } pub struct memory_type_list { __priv: [crate::uintptr_t; 2], } pub struct pidfh { __priva: [[crate::uintptr_t; 32]; 8], __privb: [crate::uintptr_t; 2], } pub struct sctp_event { pub se_assoc_id: crate::sctp_assoc_t, pub se_type: u16, pub se_on: u8, } pub struct sctp_event_subscribe { pub sctp_data_io_event: u8, pub sctp_association_event: u8, pub sctp_address_event: u8, pub sctp_send_failure_event: u8, pub sctp_peer_error_event: u8, pub sctp_shutdown_event: u8, pub sctp_partial_delivery_event: u8, pub sctp_adaptation_layer_event: u8, pub sctp_authentication_event: u8, pub sctp_sender_dry_event: u8, pub sctp_stream_reset_event: u8, } pub struct sctp_initmsg { pub sinit_num_ostreams: u16, pub sinit_max_instreams: u16, pub sinit_max_attempts: u16, pub sinit_max_init_timeo: u16, } pub struct sctp_sndrcvinfo { pub sinfo_stream: u16, pub sinfo_ssn: u16, pub sinfo_flags: u16, pub sinfo_ppid: u32, pub sinfo_context: u32, pub sinfo_timetolive: u32, pub sinfo_tsn: u32, pub sinfo_cumtsn: u32, pub sinfo_assoc_id: crate::sctp_assoc_t, pub sinfo_keynumber: u16, pub sinfo_keynumber_valid: u16, pub __reserve_pad: [[u8; 23]; 4], } pub struct sctp_extrcvinfo { pub sinfo_stream: u16, pub sinfo_ssn: u16, pub sinfo_flags: u16, pub sinfo_ppid: u32, pub sinfo_context: u32, pub sinfo_timetolive: u32, pub sinfo_tsn: u32, pub sinfo_cumtsn: u32, pub sinfo_assoc_id: crate::sctp_assoc_t, pub serinfo_next_flags: u16, pub serinfo_next_stream: u16, pub serinfo_next_aid: u32, pub serinfo_next_length: u32, pub serinfo_next_ppid: u32, pub sinfo_keynumber: u16, pub sinfo_keynumber_valid: u16, pub __reserve_pad: [[u8; 19]; 4], } pub struct sctp_sndinfo { pub snd_sid: u16, pub snd_flags: u16, pub snd_ppid: u32, pub snd_context: u32, pub snd_assoc_id: crate::sctp_assoc_t, } pub struct sctp_prinfo { pub pr_policy: u16, pub pr_value: u32, } pub struct sctp_default_prinfo { pub pr_policy: u16, pub pr_value: u32, pub pr_assoc_id: crate::sctp_assoc_t, } pub struct sctp_authinfo { pub auth_keynumber: u16, } pub struct sctp_rcvinfo { pub rcv_sid: u16, pub rcv_ssn: u16, pub rcv_flags: u16, pub rcv_ppid: u32, pub rcv_tsn: u32, pub rcv_cumtsn: u32, pub rcv_context: u32, pub rcv_assoc_id: crate::sctp_assoc_t, } pub struct sctp_nxtinfo { pub nxt_sid: u16, pub nxt_flags: u16, pub nxt_ppid: u32, pub nxt_length: u32, pub nxt_assoc_id: crate::sctp_assoc_t, } pub struct sctp_recvv_rn { pub recvv_rcvinfo: sctp_rcvinfo, pub recvv_nxtinfo: sctp_nxtinfo, } pub struct sctp_sendv_spa { pub sendv_flags: u32, pub sendv_sndinfo: sctp_sndinfo, pub sendv_prinfo: sctp_prinfo, pub sendv_authinfo: sctp_authinfo, } pub struct sctp_snd_all_completes { pub sall_stream: u16, pub sall_flags: u16, pub sall_ppid: u32, pub sall_context: u32, pub sall_num_sent: u32, pub sall_num_failed: u32, } pub struct sctp_pcbinfo { pub ep_count: u32, pub asoc_count: u32, pub laddr_count: u32, pub raddr_count: u32, pub chk_count: u32, pub readq_count: u32, pub free_chunks: u32, pub stream_oque: u32, } pub struct sctp_sockstat { pub ss_assoc_id: crate::sctp_assoc_t, pub ss_total_sndbuf: u32, pub ss_total_recv_buf: u32, } pub struct sctp_assoc_change { pub sac_type: u16, pub sac_flags: u16, pub sac_length: u32, pub sac_state: u16, pub sac_error: u16, pub sac_outbound_streams: u16, pub sac_inbound_streams: u16, pub sac_assoc_id: crate::sctp_assoc_t, pub sac_info: [u8; 0], } pub struct sctp_paddr_change { pub spc_type: u16, pub spc_flags: u16, pub spc_length: u32, pub spc_aaddr: crate::sockaddr_storage, pub spc_state: u32, pub spc_error: u32, pub spc_assoc_id: crate::sctp_assoc_t, } pub struct sctp_remote_error { pub sre_type: u16, pub sre_flags: u16, pub sre_length: u32, pub sre_error: u16, pub sre_assoc_id: crate::sctp_assoc_t, pub sre_data: [u8; 0], } pub struct sctp_send_failed_event { pub ssfe_type: u16, pub ssfe_flags: u16, pub ssfe_length: u32, pub ssfe_error: u32, pub ssfe_info: sctp_sndinfo, pub ssfe_assoc_id: crate::sctp_assoc_t, pub ssfe_data: [u8; 0], } pub struct sctp_shutdown_event { pub sse_type: u16, pub sse_flags: u16, pub sse_length: u32, pub sse_assoc_id: crate::sctp_assoc_t, } pub struct sctp_adaptation_event { pub sai_type: u16, pub sai_flags: u16, pub sai_length: u32, pub sai_adaptation_ind: u32, pub sai_assoc_id: crate::sctp_assoc_t, } pub struct sctp_setadaptation { pub ssb_adaptation_ind: u32, } pub struct sctp_pdapi_event { pub pdapi_type: u16, pub pdapi_flags: u16, pub pdapi_length: u32, pub pdapi_indication: u32, pub pdapi_stream: u16, pub pdapi_seq: u16, pub pdapi_assoc_id: crate::sctp_assoc_t, } pub struct sctp_sender_dry_event { pub sender_dry_type: u16, pub sender_dry_flags: u16, pub sender_dry_length: u32, pub sender_dry_assoc_id: crate::sctp_assoc_t, } pub struct sctp_stream_reset_event { pub strreset_type: u16, pub strreset_flags: u16, pub strreset_length: u32, pub strreset_assoc_id: crate::sctp_assoc_t, pub strreset_stream_list: [u16; 0], } pub struct sctp_stream_change_event { pub strchange_type: u16, pub strchange_flags: u16, pub strchange_length: u32, pub strchange_assoc_id: crate::sctp_assoc_t, pub strchange_instrms: u16, pub strchange_outstrms: u16, } pub struct filedesc { pub fd_files: *mut fdescenttbl, pub fd_map: *mut c_ulong, pub fd_freefile: c_int, pub fd_refcnt: c_int, pub fd_holdcnt: c_int, fd_sx: sx, fd_kqlist: kqlist, pub fd_holdleaderscount: c_int, pub fd_holdleaderswakeup: c_int, } pub struct fdescenttbl { pub fdt_nfiles: c_int, fdt_ofiles: [*mut c_void; 0], } // FIXME: Should be private. #[doc(hidden)] pub struct sx { lock_object: lock_object, sx_lock: crate::uintptr_t, } // FIXME: Should be private. #[doc(hidden)] pub struct lock_object { lo_name: *const c_char, lo_flags: c_uint, lo_data: c_uint, // This is normally `struct witness`. lo_witness: *mut c_void, } // FIXME: Should be private. #[doc(hidden)] pub struct kqlist { tqh_first: *mut c_void, tqh_last: *mut *mut c_void, } } s_no_extra_traits! { pub struct utmpx { pub ut_type: c_short, pub ut_tv: crate::timeval, pub ut_id: [c_char; 8], pub ut_pid: crate::pid_t, pub ut_user: [c_char; 32], pub ut_line: [c_char; 16], pub ut_host: [c_char; 128], pub __ut_spare: [c_char; 64], } pub union __c_anonymous_cr_pid { __cr_unused: *mut c_void, pub cr_pid: crate::pid_t, } pub struct xucred { pub cr_version: c_uint, pub cr_uid: crate::uid_t, pub cr_ngroups: c_short, pub cr_groups: [crate::gid_t; 16], pub cr_pid__c_anonymous_union: __c_anonymous_cr_pid, } pub struct sockaddr_dl { pub sdl_len: c_uchar, pub sdl_family: c_uchar, pub sdl_index: c_ushort, pub sdl_type: c_uchar, pub sdl_nlen: c_uchar, pub sdl_alen: c_uchar, pub sdl_slen: c_uchar, pub sdl_data: [c_char; 46], } pub struct mq_attr { pub mq_flags: c_long, pub mq_maxmsg: c_long, pub mq_msgsize: c_long, pub mq_curmsgs: c_long, __reserved: [c_long; 4], } pub struct sigevent { pub sigev_notify: c_int, pub sigev_signo: c_int, pub sigev_value: crate::sigval, //The rest of the structure is actually a union. We expose only //sigev_notify_thread_id because it's the most useful union member. pub sigev_notify_thread_id: crate::lwpid_t, #[cfg(target_pointer_width = "64")] __unused1: c_int, __unused2: [c_long; 7], } pub struct ptsstat { #[cfg(any(freebsd12, freebsd13, freebsd14, freebsd15))] pub dev: u64, #[cfg(not(any(freebsd12, freebsd13, freebsd14, freebsd15)))] pub dev: u32, pub devname: [c_char; SPECNAMELEN as usize + 1], } pub union __c_anonymous_elf32_auxv_union { pub a_val: c_int, } pub struct Elf32_Auxinfo { pub a_type: c_int, pub a_un: __c_anonymous_elf32_auxv_union, } pub union __c_anonymous_ifi_epoch { pub tt: crate::time_t, pub ph: u64, } pub union __c_anonymous_ifi_lastchange { pub tv: crate::timeval, pub ph: __c_anonymous_ph, } pub struct if_data { /// ethernet, tokenring, etc pub ifi_type: u8, /// e.g., AUI, Thinnet, 10base-T, etc pub ifi_physical: u8, /// media address length pub ifi_addrlen: u8, /// media header length pub ifi_hdrlen: u8, /// current link state pub ifi_link_state: u8, /// carp vhid pub ifi_vhid: u8, /// length of this data struct pub ifi_datalen: u16, /// maximum transmission unit pub ifi_mtu: u32, /// routing metric (external only) pub ifi_metric: u32, /// linespeed pub ifi_baudrate: u64, /// packets received on interface pub ifi_ipackets: u64, /// input errors on interface pub ifi_ierrors: u64, /// packets sent on interface pub ifi_opackets: u64, /// output errors on interface pub ifi_oerrors: u64, /// collisions on csma interfaces pub ifi_collisions: u64, /// total number of octets received pub ifi_ibytes: u64, /// total number of octets sent pub ifi_obytes: u64, /// packets received via multicast pub ifi_imcasts: u64, /// packets sent via multicast pub ifi_omcasts: u64, /// dropped on input pub ifi_iqdrops: u64, /// dropped on output pub ifi_oqdrops: u64, /// destined for unsupported protocol pub ifi_noproto: u64, /// HW offload capabilities, see IFCAP pub ifi_hwassist: u64, /// uptime at attach or stat reset pub __ifi_epoch: __c_anonymous_ifi_epoch, /// time of last administrative change pub __ifi_lastchange: __c_anonymous_ifi_lastchange, } pub union __c_anonymous_ifr_ifru { pub ifru_addr: crate::sockaddr, pub ifru_dstaddr: crate::sockaddr, pub ifru_broadaddr: crate::sockaddr, pub ifru_buffer: ifreq_buffer, pub ifru_flags: [c_short; 2], pub ifru_index: c_short, pub ifru_jid: c_int, pub ifru_metric: c_int, pub ifru_mtu: c_int, pub ifru_phys: c_int, pub ifru_media: c_int, pub ifru_data: crate::caddr_t, pub ifru_cap: [c_int; 2], pub ifru_fib: c_uint, pub ifru_vlan_pcp: c_uchar, } pub struct ifreq { /// if name, e.g. "en0" pub ifr_name: [c_char; crate::IFNAMSIZ], pub ifr_ifru: __c_anonymous_ifr_ifru, } pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: crate::caddr_t, pub ifcu_req: *mut ifreq, } pub struct ifstat { /// if name, e.g. "en0" pub ifs_name: [c_char; crate::IFNAMSIZ as usize], pub ascii: [c_char; crate::IFSTATMAX as usize + 1], } pub struct ifrsskey { /// if name, e.g. "en0" pub ifrk_name: [c_char; crate::IFNAMSIZ as usize], /// RSS_FUNC_ pub ifrk_func: u8, pub ifrk_spare0: u8, pub ifrk_keylen: u16, pub ifrk_key: [u8; crate::RSS_KEYLEN as usize], } pub struct ifdownreason { pub ifdr_name: [c_char; crate::IFNAMSIZ as usize], pub ifdr_reason: u32, pub ifdr_vendor: u32, pub ifdr_msg: [c_char; crate::IFDR_MSG_SIZE as usize], } #[repr(packed)] pub struct sctphdr { pub src_port: u16, pub dest_port: u16, pub v_tag: u32, pub checksum: u32, } #[repr(packed)] pub struct sctp_chunkhdr { pub chunk_type: u8, pub chunk_flags: u8, pub chunk_length: u16, } #[repr(packed)] pub struct sctp_paramhdr { pub param_type: u16, pub param_length: u16, } #[repr(packed)] pub struct sctp_gen_error_cause { pub code: u16, pub length: u16, pub info: [u8; 0], } #[repr(packed)] pub struct sctp_error_cause { pub code: u16, pub length: u16, } #[repr(packed)] pub struct sctp_error_invalid_stream { pub cause: sctp_error_cause, pub stream_id: u16, __reserved: u16, } #[repr(packed)] pub struct sctp_error_missing_param { pub cause: sctp_error_cause, pub num_missing_params: u32, pub tpe: [u8; 0], } #[repr(packed)] pub struct sctp_error_stale_cookie { pub cause: sctp_error_cause, pub stale_time: u32, } #[repr(packed)] pub struct sctp_error_out_of_resource { pub cause: sctp_error_cause, } #[repr(packed)] pub struct sctp_error_unresolv_addr { pub cause: sctp_error_cause, } #[repr(packed)] pub struct sctp_error_unrecognized_chunk { pub cause: sctp_error_cause, pub ch: sctp_chunkhdr, } #[repr(packed)] pub struct sctp_error_no_user_data { pub cause: sctp_error_cause, pub tsn: u32, } #[repr(packed)] pub struct sctp_error_auth_invalid_hmac { pub cause: sctp_error_cause, pub hmac_id: u16, } pub struct kinfo_file { pub kf_structsize: c_int, pub kf_type: c_int, pub kf_fd: c_int, pub kf_ref_count: c_int, pub kf_flags: c_int, _kf_pad0: c_int, pub kf_offset: i64, _priv: [u8; 304], // FIXME(freebsd): this is really a giant union pub kf_status: u16, _kf_pad1: u16, _kf_ispare0: c_int, pub kf_cap_rights: crate::cap_rights_t, _kf_cap_spare: u64, pub kf_path: [c_char; crate::PATH_MAX as usize], } pub struct ucontext_t { pub uc_sigmask: crate::sigset_t, pub uc_mcontext: crate::mcontext_t, pub uc_link: *mut crate::ucontext_t, pub uc_stack: crate::stack_t, pub uc_flags: c_int, __spare__: [c_int; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_tv == other.ut_tv && self.ut_id == other.ut_id && self.ut_pid == other.ut_pid && self.ut_user == other.ut_user && self.ut_line == other.ut_line && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) && self .__ut_spare .iter() .zip(other.__ut_spare.iter()) .all(|(a, b)| a == b) } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) .field("ut_tv", &self.ut_tv) .field("ut_id", &self.ut_id) .field("ut_pid", &self.ut_pid) .field("ut_user", &self.ut_user) .field("ut_line", &self.ut_line) // FIXME(debug): .field("ut_host", &self.ut_host) // FIXME(debug): .field("__ut_spare", &self.__ut_spare) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_tv.hash(state); self.ut_id.hash(state); self.ut_pid.hash(state); self.ut_user.hash(state); self.ut_line.hash(state); self.ut_host.hash(state); self.__ut_spare.hash(state); } } impl PartialEq for __c_anonymous_cr_pid { fn eq(&self, other: &__c_anonymous_cr_pid) -> bool { unsafe { self.cr_pid == other.cr_pid } } } impl Eq for __c_anonymous_cr_pid {} impl hash::Hash for __c_anonymous_cr_pid { fn hash(&self, state: &mut H) { unsafe { self.cr_pid.hash(state) }; } } impl PartialEq for xucred { fn eq(&self, other: &xucred) -> bool { self.cr_version == other.cr_version && self.cr_uid == other.cr_uid && self.cr_ngroups == other.cr_ngroups && self.cr_groups == other.cr_groups && self.cr_pid__c_anonymous_union == other.cr_pid__c_anonymous_union } } impl Eq for xucred {} impl fmt::Debug for xucred { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("xucred") .field("cr_version", &self.cr_version) .field("cr_uid", &self.cr_uid) .field("cr_ngroups", &self.cr_ngroups) .field("cr_groups", &self.cr_groups) .field("cr_pid__c_anonymous_union", &self.cr_pid__c_anonymous_union) .finish() } } impl hash::Hash for xucred { fn hash(&self, state: &mut H) { self.cr_version.hash(state); self.cr_uid.hash(state); self.cr_ngroups.hash(state); self.cr_groups.hash(state); self.cr_pid__c_anonymous_union.hash(state); } } impl PartialEq for sockaddr_dl { fn eq(&self, other: &sockaddr_dl) -> bool { self.sdl_len == other.sdl_len && self.sdl_family == other.sdl_family && self.sdl_index == other.sdl_index && self.sdl_type == other.sdl_type && self.sdl_nlen == other.sdl_nlen && self.sdl_alen == other.sdl_alen && self.sdl_slen == other.sdl_slen && self .sdl_data .iter() .zip(other.sdl_data.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_dl {} impl fmt::Debug for sockaddr_dl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_dl") .field("sdl_len", &self.sdl_len) .field("sdl_family", &self.sdl_family) .field("sdl_index", &self.sdl_index) .field("sdl_type", &self.sdl_type) .field("sdl_nlen", &self.sdl_nlen) .field("sdl_alen", &self.sdl_alen) .field("sdl_slen", &self.sdl_slen) // FIXME(debug): .field("sdl_data", &self.sdl_data) .finish() } } impl hash::Hash for sockaddr_dl { fn hash(&self, state: &mut H) { self.sdl_len.hash(state); self.sdl_family.hash(state); self.sdl_index.hash(state); self.sdl_type.hash(state); self.sdl_nlen.hash(state); self.sdl_alen.hash(state); self.sdl_slen.hash(state); self.sdl_data.hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_flags == other.mq_flags && self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_curmsgs == other.mq_curmsgs } } impl Eq for mq_attr {} impl fmt::Debug for mq_attr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mq_attr") .field("mq_flags", &self.mq_flags) .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_curmsgs", &self.mq_curmsgs) .finish() } } impl hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_flags.hash(state); self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_curmsgs.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.sigev_notify_thread_id == other.sigev_notify_thread_id } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("sigev_notify_thread_id", &self.sigev_notify_thread_id) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.sigev_notify_thread_id.hash(state); } } impl PartialEq for ptsstat { fn eq(&self, other: &ptsstat) -> bool { let self_devname: &[c_char] = &self.devname; let other_devname: &[c_char] = &other.devname; self.dev == other.dev && self_devname == other_devname } } impl Eq for ptsstat {} impl fmt::Debug for ptsstat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let self_devname: &[c_char] = &self.devname; f.debug_struct("ptsstat") .field("dev", &self.dev) .field("devname", &self_devname) .finish() } } impl hash::Hash for ptsstat { fn hash(&self, state: &mut H) { let self_devname: &[c_char] = &self.devname; self.dev.hash(state); self_devname.hash(state); } } impl PartialEq for __c_anonymous_elf32_auxv_union { fn eq(&self, other: &__c_anonymous_elf32_auxv_union) -> bool { unsafe { self.a_val == other.a_val } } } impl Eq for __c_anonymous_elf32_auxv_union {} impl PartialEq for Elf32_Auxinfo { fn eq(&self, other: &Elf32_Auxinfo) -> bool { self.a_type == other.a_type && self.a_un == other.a_un } } impl Eq for Elf32_Auxinfo {} impl fmt::Debug for Elf32_Auxinfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Elf32_Auxinfo") .field("a_type", &self.a_type) .field("a_un", &self.a_un) .finish() } } impl PartialEq for __c_anonymous_ifr_ifru { fn eq(&self, other: &__c_anonymous_ifr_ifru) -> bool { unsafe { self.ifru_addr == other.ifru_addr && self.ifru_dstaddr == other.ifru_dstaddr && self.ifru_broadaddr == other.ifru_broadaddr && self.ifru_buffer == other.ifru_buffer && self.ifru_flags == other.ifru_flags && self.ifru_index == other.ifru_index && self.ifru_jid == other.ifru_jid && self.ifru_metric == other.ifru_metric && self.ifru_mtu == other.ifru_mtu && self.ifru_phys == other.ifru_phys && self.ifru_media == other.ifru_media && self.ifru_data == other.ifru_data && self.ifru_cap == other.ifru_cap && self.ifru_fib == other.ifru_fib && self.ifru_vlan_pcp == other.ifru_vlan_pcp } } } impl Eq for __c_anonymous_ifr_ifru {} impl hash::Hash for __c_anonymous_ifr_ifru { fn hash(&self, state: &mut H) { unsafe { self.ifru_addr.hash(state) }; unsafe { self.ifru_dstaddr.hash(state) }; unsafe { self.ifru_broadaddr.hash(state) }; unsafe { self.ifru_buffer.hash(state) }; unsafe { self.ifru_flags.hash(state) }; unsafe { self.ifru_index.hash(state) }; unsafe { self.ifru_jid.hash(state) }; unsafe { self.ifru_metric.hash(state) }; unsafe { self.ifru_mtu.hash(state) }; unsafe { self.ifru_phys.hash(state) }; unsafe { self.ifru_media.hash(state) }; unsafe { self.ifru_data.hash(state) }; unsafe { self.ifru_cap.hash(state) }; unsafe { self.ifru_fib.hash(state) }; unsafe { self.ifru_vlan_pcp.hash(state) }; } } impl PartialEq for ifreq { fn eq(&self, other: &ifreq) -> bool { self.ifr_name == other.ifr_name && self.ifr_ifru == other.ifr_ifru } } impl Eq for ifreq {} impl fmt::Debug for ifreq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } impl hash::Hash for ifreq { fn hash(&self, state: &mut H) { self.ifr_name.hash(state); self.ifr_ifru.hash(state); } } impl Eq for __c_anonymous_ifc_ifcu {} impl PartialEq for __c_anonymous_ifc_ifcu { fn eq(&self, other: &__c_anonymous_ifc_ifcu) -> bool { unsafe { self.ifcu_buf == other.ifcu_buf && self.ifcu_req == other.ifcu_req } } } impl hash::Hash for __c_anonymous_ifc_ifcu { fn hash(&self, state: &mut H) { unsafe { self.ifcu_buf.hash(state) }; unsafe { self.ifcu_req.hash(state) }; } } impl PartialEq for ifstat { fn eq(&self, other: &ifstat) -> bool { let self_ascii: &[c_char] = &self.ascii; let other_ascii: &[c_char] = &other.ascii; self.ifs_name == other.ifs_name && self_ascii == other_ascii } } impl Eq for ifstat {} impl fmt::Debug for ifstat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let ascii: &[c_char] = &self.ascii; f.debug_struct("ifstat") .field("ifs_name", &self.ifs_name) .field("ascii", &ascii) .finish() } } impl hash::Hash for ifstat { fn hash(&self, state: &mut H) { self.ifs_name.hash(state); self.ascii.hash(state); } } impl PartialEq for ifrsskey { fn eq(&self, other: &ifrsskey) -> bool { let self_ifrk_key: &[u8] = &self.ifrk_key; let other_ifrk_key: &[u8] = &other.ifrk_key; self.ifrk_name == other.ifrk_name && self.ifrk_func == other.ifrk_func && self.ifrk_spare0 == other.ifrk_spare0 && self.ifrk_keylen == other.ifrk_keylen && self_ifrk_key == other_ifrk_key } } impl Eq for ifrsskey {} impl fmt::Debug for ifrsskey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let ifrk_key: &[u8] = &self.ifrk_key; f.debug_struct("ifrsskey") .field("ifrk_name", &self.ifrk_name) .field("ifrk_func", &self.ifrk_func) .field("ifrk_spare0", &self.ifrk_spare0) .field("ifrk_keylen", &self.ifrk_keylen) .field("ifrk_key", &ifrk_key) .finish() } } impl hash::Hash for ifrsskey { fn hash(&self, state: &mut H) { self.ifrk_name.hash(state); self.ifrk_func.hash(state); self.ifrk_spare0.hash(state); self.ifrk_keylen.hash(state); self.ifrk_key.hash(state); } } impl PartialEq for ifdownreason { fn eq(&self, other: &ifdownreason) -> bool { let self_ifdr_msg: &[c_char] = &self.ifdr_msg; let other_ifdr_msg: &[c_char] = &other.ifdr_msg; self.ifdr_name == other.ifdr_name && self.ifdr_reason == other.ifdr_reason && self.ifdr_vendor == other.ifdr_vendor && self_ifdr_msg == other_ifdr_msg } } impl Eq for ifdownreason {} impl fmt::Debug for ifdownreason { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let ifdr_msg: &[c_char] = &self.ifdr_msg; f.debug_struct("ifdownreason") .field("ifdr_name", &self.ifdr_name) .field("ifdr_reason", &self.ifdr_reason) .field("ifdr_vendor", &self.ifdr_vendor) .field("ifdr_msg", &ifdr_msg) .finish() } } impl hash::Hash for ifdownreason { fn hash(&self, state: &mut H) { self.ifdr_name.hash(state); self.ifdr_reason.hash(state); self.ifdr_vendor.hash(state); self.ifdr_msg.hash(state); } } impl PartialEq for __c_anonymous_ifi_epoch { fn eq(&self, other: &__c_anonymous_ifi_epoch) -> bool { unsafe { self.tt == other.tt && self.ph == other.ph } } } impl Eq for __c_anonymous_ifi_epoch {} impl hash::Hash for __c_anonymous_ifi_epoch { fn hash(&self, state: &mut H) { unsafe { self.tt.hash(state); self.ph.hash(state); } } } impl PartialEq for __c_anonymous_ifi_lastchange { fn eq(&self, other: &__c_anonymous_ifi_lastchange) -> bool { unsafe { self.tv == other.tv && self.ph == other.ph } } } impl Eq for __c_anonymous_ifi_lastchange {} impl hash::Hash for __c_anonymous_ifi_lastchange { fn hash(&self, state: &mut H) { unsafe { self.tv.hash(state); self.ph.hash(state); } } } impl PartialEq for if_data { fn eq(&self, other: &if_data) -> bool { self.ifi_type == other.ifi_type && self.ifi_physical == other.ifi_physical && self.ifi_addrlen == other.ifi_addrlen && self.ifi_hdrlen == other.ifi_hdrlen && self.ifi_link_state == other.ifi_link_state && self.ifi_vhid == other.ifi_vhid && self.ifi_datalen == other.ifi_datalen && self.ifi_mtu == other.ifi_mtu && self.ifi_metric == other.ifi_metric && self.ifi_baudrate == other.ifi_baudrate && self.ifi_ipackets == other.ifi_ipackets && self.ifi_ierrors == other.ifi_ierrors && self.ifi_opackets == other.ifi_opackets && self.ifi_oerrors == other.ifi_oerrors && self.ifi_collisions == other.ifi_collisions && self.ifi_ibytes == other.ifi_ibytes && self.ifi_obytes == other.ifi_obytes && self.ifi_imcasts == other.ifi_imcasts && self.ifi_omcasts == other.ifi_omcasts && self.ifi_iqdrops == other.ifi_iqdrops && self.ifi_oqdrops == other.ifi_oqdrops && self.ifi_noproto == other.ifi_noproto && self.ifi_hwassist == other.ifi_hwassist && self.__ifi_epoch == other.__ifi_epoch && self.__ifi_lastchange == other.__ifi_lastchange } } impl Eq for if_data {} impl fmt::Debug for if_data { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("if_data") .field("ifi_type", &self.ifi_type) .field("ifi_physical", &self.ifi_physical) .field("ifi_addrlen", &self.ifi_addrlen) .field("ifi_hdrlen", &self.ifi_hdrlen) .field("ifi_link_state", &self.ifi_link_state) .field("ifi_vhid", &self.ifi_vhid) .field("ifi_datalen", &self.ifi_datalen) .field("ifi_mtu", &self.ifi_mtu) .field("ifi_metric", &self.ifi_metric) .field("ifi_baudrate", &self.ifi_baudrate) .field("ifi_ipackets", &self.ifi_ipackets) .field("ifi_ierrors", &self.ifi_ierrors) .field("ifi_opackets", &self.ifi_opackets) .field("ifi_oerrors", &self.ifi_oerrors) .field("ifi_collisions", &self.ifi_collisions) .field("ifi_ibytes", &self.ifi_ibytes) .field("ifi_obytes", &self.ifi_obytes) .field("ifi_imcasts", &self.ifi_imcasts) .field("ifi_omcasts", &self.ifi_omcasts) .field("ifi_iqdrops", &self.ifi_iqdrops) .field("ifi_oqdrops", &self.ifi_oqdrops) .field("ifi_noproto", &self.ifi_noproto) .field("ifi_hwassist", &self.ifi_hwassist) .field("__ifi_epoch", &self.__ifi_epoch) .field("__ifi_lastchange", &self.__ifi_lastchange) .finish() } } impl hash::Hash for if_data { fn hash(&self, state: &mut H) { self.ifi_type.hash(state); self.ifi_physical.hash(state); self.ifi_addrlen.hash(state); self.ifi_hdrlen.hash(state); self.ifi_link_state.hash(state); self.ifi_vhid.hash(state); self.ifi_datalen.hash(state); self.ifi_mtu.hash(state); self.ifi_metric.hash(state); self.ifi_baudrate.hash(state); self.ifi_ipackets.hash(state); self.ifi_ierrors.hash(state); self.ifi_opackets.hash(state); self.ifi_oerrors.hash(state); self.ifi_collisions.hash(state); self.ifi_ibytes.hash(state); self.ifi_obytes.hash(state); self.ifi_imcasts.hash(state); self.ifi_omcasts.hash(state); self.ifi_iqdrops.hash(state); self.ifi_oqdrops.hash(state); self.ifi_noproto.hash(state); self.ifi_hwassist.hash(state); self.__ifi_epoch.hash(state); self.__ifi_lastchange.hash(state); } } impl PartialEq for sctphdr { fn eq(&self, other: &sctphdr) -> bool { return { self.src_port } == { other.src_port } && { self.dest_port } == { other.dest_port } && { self.v_tag } == { other.v_tag } && { self.checksum } == { other.checksum }; } } impl Eq for sctphdr {} impl fmt::Debug for sctphdr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctphdr") .field("src_port", &{ self.src_port }) .field("dest_port", &{ self.dest_port }) .field("v_tag", &{ self.v_tag }) .field("checksum", &{ self.checksum }) .finish() } } impl hash::Hash for sctphdr { fn hash(&self, state: &mut H) { { self.src_port }.hash(state); { self.dest_port }.hash(state); { self.v_tag }.hash(state); { self.checksum }.hash(state); } } impl PartialEq for sctp_chunkhdr { fn eq(&self, other: &sctp_chunkhdr) -> bool { return { self.chunk_type } == { other.chunk_type } && { self.chunk_flags } == { other.chunk_flags } && { self.chunk_length } == { other.chunk_length }; } } impl Eq for sctp_chunkhdr {} impl fmt::Debug for sctp_chunkhdr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_chunkhdr") .field("chunk_type", &{ self.chunk_type }) .field("chunk_flags", &{ self.chunk_flags }) .field("chunk_length", &{ self.chunk_length }) .finish() } } impl hash::Hash for sctp_chunkhdr { fn hash(&self, state: &mut H) { { self.chunk_type }.hash(state); { self.chunk_flags }.hash(state); { self.chunk_length }.hash(state); } } impl PartialEq for sctp_paramhdr { fn eq(&self, other: &sctp_paramhdr) -> bool { return { self.param_type } == { other.param_type } && { self.param_length } == { other.param_length }; } } impl Eq for sctp_paramhdr {} impl fmt::Debug for sctp_paramhdr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_paramhdr") .field("param_type", &{ self.param_type }) .field("param_length", &{ self.param_length }) .finish() } } impl hash::Hash for sctp_paramhdr { fn hash(&self, state: &mut H) { { self.param_type }.hash(state); { self.param_length }.hash(state); } } impl PartialEq for sctp_gen_error_cause { fn eq(&self, other: &sctp_gen_error_cause) -> bool { return { self.code } == { other.code } && { self.length } == { other.length } && { self.info } .iter() .zip({ other.info }.iter()) .all(|(a, b)| a == b); } } impl Eq for sctp_gen_error_cause {} impl fmt::Debug for sctp_gen_error_cause { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_gen_error_cause") .field("code", &{ self.code }) .field("length", &{ self.length }) // FIXME(debug): .field("info", &{self.info}) .finish() } } impl hash::Hash for sctp_gen_error_cause { fn hash(&self, state: &mut H) { { self.code }.hash(state); { self.length }.hash(state); { self.info }.hash(state); } } impl PartialEq for sctp_error_cause { fn eq(&self, other: &sctp_error_cause) -> bool { return { self.code } == { other.code } && { self.length } == { other.length }; } } impl Eq for sctp_error_cause {} impl fmt::Debug for sctp_error_cause { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_cause") .field("code", &{ self.code }) .field("length", &{ self.length }) .finish() } } impl hash::Hash for sctp_error_cause { fn hash(&self, state: &mut H) { { self.code }.hash(state); { self.length }.hash(state); } } impl PartialEq for sctp_error_invalid_stream { fn eq(&self, other: &sctp_error_invalid_stream) -> bool { return { self.cause } == { other.cause } && { self.stream_id } == { other.stream_id }; } } impl Eq for sctp_error_invalid_stream {} impl fmt::Debug for sctp_error_invalid_stream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_invalid_stream") .field("cause", &{ self.cause }) .field("stream_id", &{ self.stream_id }) .finish() } } impl hash::Hash for sctp_error_invalid_stream { fn hash(&self, state: &mut H) { { self.cause }.hash(state); { self.stream_id }.hash(state); } } impl PartialEq for sctp_error_missing_param { fn eq(&self, other: &sctp_error_missing_param) -> bool { return { self.cause } == { other.cause } && { self.num_missing_params } == { other.num_missing_params } && { self.tpe } .iter() .zip({ other.tpe }.iter()) .all(|(a, b)| a == b); } } impl Eq for sctp_error_missing_param {} impl fmt::Debug for sctp_error_missing_param { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_missing_param") .field("cause", &{ self.cause }) .field("num_missing_params", &{ self.num_missing_params }) // FIXME(debug): .field("tpe", &{self.tpe}) .finish() } } impl hash::Hash for sctp_error_missing_param { fn hash(&self, state: &mut H) { { self.cause }.hash(state); { self.num_missing_params }.hash(state); { self.tpe }.hash(state); } } impl PartialEq for sctp_error_stale_cookie { fn eq(&self, other: &sctp_error_stale_cookie) -> bool { return { self.cause } == { other.cause } && { self.stale_time } == { other.stale_time }; } } impl Eq for sctp_error_stale_cookie {} impl fmt::Debug for sctp_error_stale_cookie { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_stale_cookie") .field("cause", &{ self.cause }) .field("stale_time", &{ self.stale_time }) .finish() } } impl hash::Hash for sctp_error_stale_cookie { fn hash(&self, state: &mut H) { { self.cause }.hash(state); { self.stale_time }.hash(state); } } impl PartialEq for sctp_error_out_of_resource { fn eq(&self, other: &sctp_error_out_of_resource) -> bool { return { self.cause } == { other.cause }; } } impl Eq for sctp_error_out_of_resource {} impl fmt::Debug for sctp_error_out_of_resource { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_out_of_resource") .field("cause", &{ self.cause }) .finish() } } impl hash::Hash for sctp_error_out_of_resource { fn hash(&self, state: &mut H) { { self.cause }.hash(state); } } impl PartialEq for sctp_error_unresolv_addr { fn eq(&self, other: &sctp_error_unresolv_addr) -> bool { return { self.cause } == { other.cause }; } } impl Eq for sctp_error_unresolv_addr {} impl fmt::Debug for sctp_error_unresolv_addr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_unresolv_addr") .field("cause", &{ self.cause }) .finish() } } impl hash::Hash for sctp_error_unresolv_addr { fn hash(&self, state: &mut H) { { self.cause }.hash(state); } } impl PartialEq for sctp_error_unrecognized_chunk { fn eq(&self, other: &sctp_error_unrecognized_chunk) -> bool { return { self.cause } == { other.cause } && { self.ch } == { other.ch }; } } impl Eq for sctp_error_unrecognized_chunk {} impl fmt::Debug for sctp_error_unrecognized_chunk { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_unrecognized_chunk") .field("cause", &{ self.cause }) .field("ch", &{ self.ch }) .finish() } } impl hash::Hash for sctp_error_unrecognized_chunk { fn hash(&self, state: &mut H) { { self.cause }.hash(state); { self.ch }.hash(state); } } impl PartialEq for sctp_error_no_user_data { fn eq(&self, other: &sctp_error_no_user_data) -> bool { return { self.cause } == { other.cause } && { self.tsn } == { other.tsn }; } } impl Eq for sctp_error_no_user_data {} impl fmt::Debug for sctp_error_no_user_data { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_no_user_data") .field("cause", &{ self.cause }) .field("tsn", &{ self.tsn }) .finish() } } impl hash::Hash for sctp_error_no_user_data { fn hash(&self, state: &mut H) { { self.cause }.hash(state); { self.tsn }.hash(state); } } impl PartialEq for sctp_error_auth_invalid_hmac { fn eq(&self, other: &sctp_error_auth_invalid_hmac) -> bool { return { self.cause } == { other.cause } && { self.hmac_id } == { other.hmac_id }; } } impl Eq for sctp_error_auth_invalid_hmac {} impl fmt::Debug for sctp_error_auth_invalid_hmac { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sctp_error_invalid_hmac") .field("cause", &{ self.cause }) .field("hmac_id", &{ self.hmac_id }) .finish() } } impl hash::Hash for sctp_error_auth_invalid_hmac { fn hash(&self, state: &mut H) { { self.cause }.hash(state); { self.hmac_id }.hash(state); } } impl PartialEq for kinfo_file { fn eq(&self, other: &kinfo_file) -> bool { self.kf_structsize == other.kf_structsize && self.kf_type == other.kf_type && self.kf_fd == other.kf_fd && self.kf_ref_count == other.kf_ref_count && self.kf_flags == other.kf_flags && self.kf_offset == other.kf_offset && self.kf_status == other.kf_status && self.kf_cap_rights == other.kf_cap_rights && self .kf_path .iter() .zip(other.kf_path.iter()) .all(|(a, b)| a == b) } } impl Eq for kinfo_file {} impl fmt::Debug for kinfo_file { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("kinfo_file") .field("kf_structsize", &self.kf_structsize) .field("kf_type", &self.kf_type) .field("kf_fd", &self.kf_fd) .field("kf_ref_count", &self.kf_ref_count) .field("kf_flags", &self.kf_flags) .field("kf_offset", &self.kf_offset) .field("kf_status", &self.kf_status) .field("kf_cap_rights", &self.kf_cap_rights) .field("kf_path", &&self.kf_path[..]) .finish() } } impl hash::Hash for kinfo_file { fn hash(&self, state: &mut H) { self.kf_structsize.hash(state); self.kf_type.hash(state); self.kf_fd.hash(state); self.kf_ref_count.hash(state); self.kf_flags.hash(state); self.kf_offset.hash(state); self.kf_status.hash(state); self.kf_cap_rights.hash(state); self.kf_path.hash(state); } } impl fmt::Debug for ucontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ucontext_t") .field("uc_sigmask", &self.uc_sigmask) .field("uc_mcontext", &self.uc_mcontext) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_flags", &self.uc_flags) .finish() } } } } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(u32)] pub enum dot3Vendors { dot3VendorAMD = 1, dot3VendorIntel = 2, dot3VendorNational = 4, dot3VendorFujitsu = 5, dot3VendorDigital = 6, dot3VendorWesternDigital = 7, } impl Copy for dot3Vendors {} impl Clone for dot3Vendors { fn clone(&self) -> dot3Vendors { *self } } // aio.h pub const LIO_VECTORED: c_int = 4; pub const LIO_WRITEV: c_int = 5; pub const LIO_READV: c_int = 6; // sys/caprights.h pub const CAP_RIGHTS_VERSION_00: i32 = 0; pub const CAP_RIGHTS_VERSION: i32 = CAP_RIGHTS_VERSION_00; // sys/capsicum.h macro_rules! cap_right { ($idx:expr, $bit:expr) => { ((1u64 << (57 + ($idx))) | ($bit)) }; } pub const CAP_READ: u64 = cap_right!(0, 0x0000000000000001u64); pub const CAP_WRITE: u64 = cap_right!(0, 0x0000000000000002u64); pub const CAP_SEEK_TELL: u64 = cap_right!(0, 0x0000000000000004u64); pub const CAP_SEEK: u64 = CAP_SEEK_TELL | 0x0000000000000008u64; pub const CAP_PREAD: u64 = CAP_SEEK | CAP_READ; pub const CAP_PWRITE: u64 = CAP_SEEK | CAP_WRITE; pub const CAP_MMAP: u64 = cap_right!(0, 0x0000000000000010u64); pub const CAP_MMAP_R: u64 = CAP_MMAP | CAP_SEEK | CAP_READ; pub const CAP_MMAP_W: u64 = CAP_MMAP | CAP_SEEK | CAP_WRITE; pub const CAP_MMAP_X: u64 = CAP_MMAP | CAP_SEEK | 0x0000000000000020u64; pub const CAP_MMAP_RW: u64 = CAP_MMAP_R | CAP_MMAP_W; pub const CAP_MMAP_RX: u64 = CAP_MMAP_R | CAP_MMAP_X; pub const CAP_MMAP_WX: u64 = CAP_MMAP_W | CAP_MMAP_X; pub const CAP_MMAP_RWX: u64 = CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X; pub const CAP_CREATE: u64 = cap_right!(0, 0x0000000000000040u64); pub const CAP_FEXECVE: u64 = cap_right!(0, 0x0000000000000080u64); pub const CAP_FSYNC: u64 = cap_right!(0, 0x0000000000000100u64); pub const CAP_FTRUNCATE: u64 = cap_right!(0, 0x0000000000000200u64); pub const CAP_LOOKUP: u64 = cap_right!(0, 0x0000000000000400u64); pub const CAP_FCHDIR: u64 = cap_right!(0, 0x0000000000000800u64); pub const CAP_FCHFLAGS: u64 = cap_right!(0, 0x0000000000001000u64); pub const CAP_CHFLAGSAT: u64 = CAP_FCHFLAGS | CAP_LOOKUP; pub const CAP_FCHMOD: u64 = cap_right!(0, 0x0000000000002000u64); pub const CAP_FCHMODAT: u64 = CAP_FCHMOD | CAP_LOOKUP; pub const CAP_FCHOWN: u64 = cap_right!(0, 0x0000000000004000u64); pub const CAP_FCHOWNAT: u64 = CAP_FCHOWN | CAP_LOOKUP; pub const CAP_FCNTL: u64 = cap_right!(0, 0x0000000000008000u64); pub const CAP_FLOCK: u64 = cap_right!(0, 0x0000000000010000u64); pub const CAP_FPATHCONF: u64 = cap_right!(0, 0x0000000000020000u64); pub const CAP_FSCK: u64 = cap_right!(0, 0x0000000000040000u64); pub const CAP_FSTAT: u64 = cap_right!(0, 0x0000000000080000u64); pub const CAP_FSTATAT: u64 = CAP_FSTAT | CAP_LOOKUP; pub const CAP_FSTATFS: u64 = cap_right!(0, 0x0000000000100000u64); pub const CAP_FUTIMES: u64 = cap_right!(0, 0x0000000000200000u64); pub const CAP_FUTIMESAT: u64 = CAP_FUTIMES | CAP_LOOKUP; // Note: this was named CAP_LINKAT prior to FreeBSD 11.0. pub const CAP_LINKAT_TARGET: u64 = CAP_LOOKUP | 0x0000000000400000u64; pub const CAP_MKDIRAT: u64 = CAP_LOOKUP | 0x0000000000800000u64; pub const CAP_MKFIFOAT: u64 = CAP_LOOKUP | 0x0000000001000000u64; pub const CAP_MKNODAT: u64 = CAP_LOOKUP | 0x0000000002000000u64; // Note: this was named CAP_RENAMEAT prior to FreeBSD 11.0. pub const CAP_RENAMEAT_SOURCE: u64 = CAP_LOOKUP | 0x0000000004000000u64; pub const CAP_SYMLINKAT: u64 = CAP_LOOKUP | 0x0000000008000000u64; pub const CAP_UNLINKAT: u64 = CAP_LOOKUP | 0x0000000010000000u64; pub const CAP_ACCEPT: u64 = cap_right!(0, 0x0000000020000000u64); pub const CAP_BIND: u64 = cap_right!(0, 0x0000000040000000u64); pub const CAP_CONNECT: u64 = cap_right!(0, 0x0000000080000000u64); pub const CAP_GETPEERNAME: u64 = cap_right!(0, 0x0000000100000000u64); pub const CAP_GETSOCKNAME: u64 = cap_right!(0, 0x0000000200000000u64); pub const CAP_GETSOCKOPT: u64 = cap_right!(0, 0x0000000400000000u64); pub const CAP_LISTEN: u64 = cap_right!(0, 0x0000000800000000u64); pub const CAP_PEELOFF: u64 = cap_right!(0, 0x0000001000000000u64); pub const CAP_RECV: u64 = CAP_READ; pub const CAP_SEND: u64 = CAP_WRITE; pub const CAP_SETSOCKOPT: u64 = cap_right!(0, 0x0000002000000000u64); pub const CAP_SHUTDOWN: u64 = cap_right!(0, 0x0000004000000000u64); pub const CAP_BINDAT: u64 = CAP_LOOKUP | 0x0000008000000000u64; pub const CAP_CONNECTAT: u64 = CAP_LOOKUP | 0x0000010000000000u64; pub const CAP_LINKAT_SOURCE: u64 = CAP_LOOKUP | 0x0000020000000000u64; pub const CAP_RENAMEAT_TARGET: u64 = CAP_LOOKUP | 0x0000040000000000u64; pub const CAP_SOCK_CLIENT: u64 = CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN; pub const CAP_SOCK_SERVER: u64 = CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN; #[deprecated(since = "0.2.165", note = "Not stable across OS versions")] pub const CAP_ALL0: u64 = cap_right!(0, 0x000007FFFFFFFFFFu64); #[deprecated(since = "0.2.165", note = "Not stable across OS versions")] pub const CAP_UNUSED0_44: u64 = cap_right!(0, 0x0000080000000000u64); #[deprecated(since = "0.2.165", note = "Not stable across OS versions")] pub const CAP_UNUSED0_57: u64 = cap_right!(0, 0x0100000000000000u64); pub const CAP_MAC_GET: u64 = cap_right!(1, 0x0000000000000001u64); pub const CAP_MAC_SET: u64 = cap_right!(1, 0x0000000000000002u64); pub const CAP_SEM_GETVALUE: u64 = cap_right!(1, 0x0000000000000004u64); pub const CAP_SEM_POST: u64 = cap_right!(1, 0x0000000000000008u64); pub const CAP_SEM_WAIT: u64 = cap_right!(1, 0x0000000000000010u64); pub const CAP_EVENT: u64 = cap_right!(1, 0x0000000000000020u64); pub const CAP_KQUEUE_EVENT: u64 = cap_right!(1, 0x0000000000000040u64); pub const CAP_IOCTL: u64 = cap_right!(1, 0x0000000000000080u64); pub const CAP_TTYHOOK: u64 = cap_right!(1, 0x0000000000000100u64); pub const CAP_PDGETPID: u64 = cap_right!(1, 0x0000000000000200u64); pub const CAP_PDWAIT: u64 = cap_right!(1, 0x0000000000000400u64); pub const CAP_PDKILL: u64 = cap_right!(1, 0x0000000000000800u64); pub const CAP_EXTATTR_DELETE: u64 = cap_right!(1, 0x0000000000001000u64); pub const CAP_EXTATTR_GET: u64 = cap_right!(1, 0x0000000000002000u64); pub const CAP_EXTATTR_LIST: u64 = cap_right!(1, 0x0000000000004000u64); pub const CAP_EXTATTR_SET: u64 = cap_right!(1, 0x0000000000008000u64); pub const CAP_ACL_CHECK: u64 = cap_right!(1, 0x0000000000010000u64); pub const CAP_ACL_DELETE: u64 = cap_right!(1, 0x0000000000020000u64); pub const CAP_ACL_GET: u64 = cap_right!(1, 0x0000000000040000u64); pub const CAP_ACL_SET: u64 = cap_right!(1, 0x0000000000080000u64); pub const CAP_KQUEUE_CHANGE: u64 = cap_right!(1, 0x0000000000100000u64); pub const CAP_KQUEUE: u64 = CAP_KQUEUE_EVENT | CAP_KQUEUE_CHANGE; #[deprecated(since = "0.2.165", note = "Not stable across OS versions")] pub const CAP_ALL1: u64 = cap_right!(1, 0x00000000001FFFFFu64); #[deprecated(since = "0.2.165", note = "Not stable across OS versions")] pub const CAP_UNUSED1_22: u64 = cap_right!(1, 0x0000000000200000u64); #[deprecated(since = "0.2.165", note = "Not stable across OS versions")] pub const CAP_UNUSED1_57: u64 = cap_right!(1, 0x0100000000000000u64); pub const CAP_FCNTL_GETFL: u32 = 1 << 3; pub const CAP_FCNTL_SETFL: u32 = 1 << 4; pub const CAP_FCNTL_GETOWN: u32 = 1 << 5; pub const CAP_FCNTL_SETOWN: u32 = 1 << 6; // sys/devicestat.h pub const DEVSTAT_N_TRANS_FLAGS: c_int = 4; pub const DEVSTAT_NAME_LEN: c_int = 16; // sys/cpuset.h cfg_if! { if #[cfg(any(freebsd15, freebsd14))] { pub const CPU_SETSIZE: c_int = 1024; } else { pub const CPU_SETSIZE: c_int = 256; } } pub const SIGEV_THREAD_ID: c_int = 4; pub const EXTATTR_NAMESPACE_EMPTY: c_int = 0; pub const EXTATTR_NAMESPACE_USER: c_int = 1; pub const EXTATTR_NAMESPACE_SYSTEM: c_int = 2; pub const PTHREAD_STACK_MIN: size_t = MINSIGSTKSZ; pub const PTHREAD_MUTEX_ADAPTIVE_NP: c_int = 4; pub const PTHREAD_MUTEX_STALLED: c_int = 0; pub const PTHREAD_MUTEX_ROBUST: c_int = 1; pub const SIGSTKSZ: size_t = MINSIGSTKSZ + 32768; pub const SF_NODISKIO: c_int = 0x00000001; pub const SF_MNOWAIT: c_int = 0x00000002; pub const SF_SYNC: c_int = 0x00000004; pub const SF_USER_READAHEAD: c_int = 0x00000008; pub const SF_NOCACHE: c_int = 0x00000010; pub const O_CLOEXEC: c_int = 0x00100000; pub const O_DIRECTORY: c_int = 0x00020000; pub const O_DSYNC: c_int = 0x01000000; pub const O_EMPTY_PATH: c_int = 0x02000000; pub const O_EXEC: c_int = 0x00040000; pub const O_PATH: c_int = 0x00400000; pub const O_RESOLVE_BENEATH: c_int = 0x00800000; pub const O_SEARCH: c_int = O_EXEC; pub const O_TTY_INIT: c_int = 0x00080000; pub const O_VERIFY: c_int = 0x00200000; pub const F_GETLK: c_int = 11; pub const F_SETLK: c_int = 12; pub const F_SETLKW: c_int = 13; pub const ENOTCAPABLE: c_int = 93; pub const ECAPMODE: c_int = 94; pub const ENOTRECOVERABLE: c_int = 95; pub const EOWNERDEAD: c_int = 96; pub const EINTEGRITY: c_int = 97; pub const RLIMIT_NPTS: c_int = 11; pub const RLIMIT_SWAP: c_int = 12; pub const RLIMIT_KQUEUES: c_int = 13; pub const RLIMIT_UMTXP: c_int = 14; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: crate::rlim_t = 15; pub const RLIM_SAVED_MAX: crate::rlim_t = crate::RLIM_INFINITY; pub const RLIM_SAVED_CUR: crate::rlim_t = crate::RLIM_INFINITY; pub const CP_USER: c_int = 0; pub const CP_NICE: c_int = 1; pub const CP_SYS: c_int = 2; pub const CP_INTR: c_int = 3; pub const CP_IDLE: c_int = 4; pub const CPUSTATES: c_int = 5; pub const NI_NOFQDN: c_int = 0x00000001; pub const NI_NUMERICHOST: c_int = 0x00000002; pub const NI_NAMEREQD: c_int = 0x00000004; pub const NI_NUMERICSERV: c_int = 0x00000008; pub const NI_DGRAM: c_int = 0x00000010; pub const NI_NUMERICSCOPE: c_int = 0x00000020; pub const XU_NGROUPS: c_int = 16; pub const Q_GETQUOTA: c_int = 0x700; pub const Q_SETQUOTA: c_int = 0x800; pub const MAP_GUARD: c_int = 0x00002000; pub const MAP_EXCL: c_int = 0x00004000; pub const MAP_PREFAULT_READ: c_int = 0x00040000; pub const MAP_ALIGNMENT_SHIFT: c_int = 24; pub const MAP_ALIGNMENT_MASK: c_int = 0xff << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNED_SUPER: c_int = 1 << MAP_ALIGNMENT_SHIFT; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_RANDOM: c_int = 1; pub const POSIX_FADV_SEQUENTIAL: c_int = 2; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const POLLINIGNEOF: c_short = 0x2000; pub const POLLRDHUP: c_short = 0x4000; pub const EVFILT_READ: i16 = -1; pub const EVFILT_WRITE: i16 = -2; pub const EVFILT_AIO: i16 = -3; pub const EVFILT_VNODE: i16 = -4; pub const EVFILT_PROC: i16 = -5; pub const EVFILT_SIGNAL: i16 = -6; pub const EVFILT_TIMER: i16 = -7; pub const EVFILT_PROCDESC: i16 = -8; pub const EVFILT_FS: i16 = -9; pub const EVFILT_LIO: i16 = -10; pub const EVFILT_USER: i16 = -11; pub const EVFILT_SENDFILE: i16 = -12; pub const EVFILT_EMPTY: i16 = -13; pub const EV_ADD: u16 = 0x1; pub const EV_DELETE: u16 = 0x2; pub const EV_ENABLE: u16 = 0x4; pub const EV_DISABLE: u16 = 0x8; pub const EV_FORCEONESHOT: u16 = 0x100; pub const EV_KEEPUDATA: u16 = 0x200; pub const EV_ONESHOT: u16 = 0x10; pub const EV_CLEAR: u16 = 0x20; pub const EV_RECEIPT: u16 = 0x40; pub const EV_DISPATCH: u16 = 0x80; pub const EV_SYSFLAGS: u16 = 0xf000; pub const EV_DROP: u16 = 0x1000; pub const EV_FLAG1: u16 = 0x2000; pub const EV_FLAG2: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; pub const EV_ERROR: u16 = 0x4000; pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; pub const NOTE_FFOR: u32 = 0x80000000; pub const NOTE_FFCOPY: u32 = 0xc0000000; pub const NOTE_FFCTRLMASK: u32 = 0xc0000000; pub const NOTE_FFLAGSMASK: u32 = 0x00ffffff; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_FILE_POLL: u32 = 0x00000002; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_OPEN: u32 = 0x00000080; pub const NOTE_CLOSE: u32 = 0x00000100; pub const NOTE_CLOSE_WRITE: u32 = 0x00000200; pub const NOTE_READ: u32 = 0x00000400; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xf0000000; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const NOTE_SECONDS: u32 = 0x00000001; pub const NOTE_MSECONDS: u32 = 0x00000002; pub const NOTE_USECONDS: u32 = 0x00000004; pub const NOTE_NSECONDS: u32 = 0x00000008; pub const NOTE_ABSTIME: u32 = 0x00000010; pub const MADV_PROTECT: c_int = 10; #[doc(hidden)] #[deprecated( since = "0.2.72", note = "CTL_UNSPEC is deprecated. Use CTL_SYSCTL instead" )] pub const CTL_UNSPEC: c_int = 0; pub const CTL_SYSCTL: c_int = 0; pub const CTL_KERN: c_int = 1; pub const CTL_VM: c_int = 2; pub const CTL_VFS: c_int = 3; pub const CTL_NET: c_int = 4; pub const CTL_DEBUG: c_int = 5; pub const CTL_HW: c_int = 6; pub const CTL_MACHDEP: c_int = 7; pub const CTL_USER: c_int = 8; pub const CTL_P1003_1B: c_int = 9; // sys/sysctl.h pub const CTL_MAXNAME: c_int = 24; pub const CTLTYPE: c_int = 0xf; pub const CTLTYPE_NODE: c_int = 1; pub const CTLTYPE_INT: c_int = 2; pub const CTLTYPE_STRING: c_int = 3; pub const CTLTYPE_S64: c_int = 4; pub const CTLTYPE_OPAQUE: c_int = 5; pub const CTLTYPE_STRUCT: c_int = CTLTYPE_OPAQUE; pub const CTLTYPE_UINT: c_int = 6; pub const CTLTYPE_LONG: c_int = 7; pub const CTLTYPE_ULONG: c_int = 8; pub const CTLTYPE_U64: c_int = 9; pub const CTLTYPE_U8: c_int = 0xa; pub const CTLTYPE_U16: c_int = 0xb; pub const CTLTYPE_S8: c_int = 0xc; pub const CTLTYPE_S16: c_int = 0xd; pub const CTLTYPE_S32: c_int = 0xe; pub const CTLTYPE_U32: c_int = 0xf; pub const CTLFLAG_RD: c_int = 0x80000000; pub const CTLFLAG_WR: c_int = 0x40000000; pub const CTLFLAG_RW: c_int = CTLFLAG_RD | CTLFLAG_WR; pub const CTLFLAG_DORMANT: c_int = 0x20000000; pub const CTLFLAG_ANYBODY: c_int = 0x10000000; pub const CTLFLAG_SECURE: c_int = 0x08000000; pub const CTLFLAG_PRISON: c_int = 0x04000000; pub const CTLFLAG_DYN: c_int = 0x02000000; pub const CTLFLAG_SKIP: c_int = 0x01000000; pub const CTLMASK_SECURE: c_int = 0x00F00000; pub const CTLFLAG_TUN: c_int = 0x00080000; pub const CTLFLAG_RDTUN: c_int = CTLFLAG_RD | CTLFLAG_TUN; pub const CTLFLAG_RWTUN: c_int = CTLFLAG_RW | CTLFLAG_TUN; pub const CTLFLAG_MPSAFE: c_int = 0x00040000; pub const CTLFLAG_VNET: c_int = 0x00020000; pub const CTLFLAG_DYING: c_int = 0x00010000; pub const CTLFLAG_CAPRD: c_int = 0x00008000; pub const CTLFLAG_CAPWR: c_int = 0x00004000; pub const CTLFLAG_STATS: c_int = 0x00002000; pub const CTLFLAG_NOFETCH: c_int = 0x00001000; pub const CTLFLAG_CAPRW: c_int = CTLFLAG_CAPRD | CTLFLAG_CAPWR; pub const CTLFLAG_NEEDGIANT: c_int = 0x00000800; pub const CTLSHIFT_SECURE: c_int = 20; pub const CTLFLAG_SECURE1: c_int = CTLFLAG_SECURE | (0 << CTLSHIFT_SECURE); pub const CTLFLAG_SECURE2: c_int = CTLFLAG_SECURE | (1 << CTLSHIFT_SECURE); pub const CTLFLAG_SECURE3: c_int = CTLFLAG_SECURE | (2 << CTLSHIFT_SECURE); pub const OID_AUTO: c_int = -1; pub const CTL_SYSCTL_DEBUG: c_int = 0; pub const CTL_SYSCTL_NAME: c_int = 1; pub const CTL_SYSCTL_NEXT: c_int = 2; pub const CTL_SYSCTL_NAME2OID: c_int = 3; pub const CTL_SYSCTL_OIDFMT: c_int = 4; pub const CTL_SYSCTL_OIDDESCR: c_int = 5; pub const CTL_SYSCTL_OIDLABEL: c_int = 6; pub const CTL_SYSCTL_NEXTNOSKIP: c_int = 7; pub const KERN_OSTYPE: c_int = 1; pub const KERN_OSRELEASE: c_int = 2; pub const KERN_OSREV: c_int = 3; pub const KERN_VERSION: c_int = 4; pub const KERN_MAXVNODES: c_int = 5; pub const KERN_MAXPROC: c_int = 6; pub const KERN_MAXFILES: c_int = 7; pub const KERN_ARGMAX: c_int = 8; pub const KERN_SECURELVL: c_int = 9; pub const KERN_HOSTNAME: c_int = 10; pub const KERN_HOSTID: c_int = 11; pub const KERN_CLOCKRATE: c_int = 12; pub const KERN_VNODE: c_int = 13; pub const KERN_PROC: c_int = 14; pub const KERN_FILE: c_int = 15; pub const KERN_PROF: c_int = 16; pub const KERN_POSIX1: c_int = 17; pub const KERN_NGROUPS: c_int = 18; pub const KERN_JOB_CONTROL: c_int = 19; pub const KERN_SAVED_IDS: c_int = 20; pub const KERN_BOOTTIME: c_int = 21; pub const KERN_NISDOMAINNAME: c_int = 22; pub const KERN_UPDATEINTERVAL: c_int = 23; pub const KERN_OSRELDATE: c_int = 24; pub const KERN_NTP_PLL: c_int = 25; pub const KERN_BOOTFILE: c_int = 26; pub const KERN_MAXFILESPERPROC: c_int = 27; pub const KERN_MAXPROCPERUID: c_int = 28; pub const KERN_DUMPDEV: c_int = 29; pub const KERN_IPC: c_int = 30; pub const KERN_DUMMY: c_int = 31; pub const KERN_PS_STRINGS: c_int = 32; pub const KERN_USRSTACK: c_int = 33; pub const KERN_LOGSIGEXIT: c_int = 34; pub const KERN_IOV_MAX: c_int = 35; pub const KERN_HOSTUUID: c_int = 36; pub const KERN_ARND: c_int = 37; pub const KERN_MAXPHYS: c_int = 38; pub const KERN_PROC_ALL: c_int = 0; pub const KERN_PROC_PID: c_int = 1; pub const KERN_PROC_PGRP: c_int = 2; pub const KERN_PROC_SESSION: c_int = 3; pub const KERN_PROC_TTY: c_int = 4; pub const KERN_PROC_UID: c_int = 5; pub const KERN_PROC_RUID: c_int = 6; pub const KERN_PROC_ARGS: c_int = 7; pub const KERN_PROC_PROC: c_int = 8; pub const KERN_PROC_SV_NAME: c_int = 9; pub const KERN_PROC_RGID: c_int = 10; pub const KERN_PROC_GID: c_int = 11; pub const KERN_PROC_PATHNAME: c_int = 12; pub const KERN_PROC_OVMMAP: c_int = 13; pub const KERN_PROC_OFILEDESC: c_int = 14; pub const KERN_PROC_KSTACK: c_int = 15; pub const KERN_PROC_INC_THREAD: c_int = 0x10; pub const KERN_PROC_VMMAP: c_int = 32; pub const KERN_PROC_FILEDESC: c_int = 33; pub const KERN_PROC_GROUPS: c_int = 34; pub const KERN_PROC_ENV: c_int = 35; pub const KERN_PROC_AUXV: c_int = 36; pub const KERN_PROC_RLIMIT: c_int = 37; pub const KERN_PROC_PS_STRINGS: c_int = 38; pub const KERN_PROC_UMASK: c_int = 39; pub const KERN_PROC_OSREL: c_int = 40; pub const KERN_PROC_SIGTRAMP: c_int = 41; pub const KERN_PROC_CWD: c_int = 42; pub const KERN_PROC_NFDS: c_int = 43; pub const KERN_PROC_SIGFASTBLK: c_int = 44; pub const KIPC_MAXSOCKBUF: c_int = 1; pub const KIPC_SOCKBUF_WASTE: c_int = 2; pub const KIPC_SOMAXCONN: c_int = 3; pub const KIPC_MAX_LINKHDR: c_int = 4; pub const KIPC_MAX_PROTOHDR: c_int = 5; pub const KIPC_MAX_HDR: c_int = 6; pub const KIPC_MAX_DATALEN: c_int = 7; pub const HW_MACHINE: c_int = 1; pub const HW_MODEL: c_int = 2; pub const HW_NCPU: c_int = 3; pub const HW_BYTEORDER: c_int = 4; pub const HW_PHYSMEM: c_int = 5; pub const HW_USERMEM: c_int = 6; pub const HW_PAGESIZE: c_int = 7; pub const HW_DISKNAMES: c_int = 8; pub const HW_DISKSTATS: c_int = 9; pub const HW_FLOATINGPT: c_int = 10; pub const HW_MACHINE_ARCH: c_int = 11; pub const HW_REALMEM: c_int = 12; pub const USER_CS_PATH: c_int = 1; pub const USER_BC_BASE_MAX: c_int = 2; pub const USER_BC_DIM_MAX: c_int = 3; pub const USER_BC_SCALE_MAX: c_int = 4; pub const USER_BC_STRING_MAX: c_int = 5; pub const USER_COLL_WEIGHTS_MAX: c_int = 6; pub const USER_EXPR_NEST_MAX: c_int = 7; pub const USER_LINE_MAX: c_int = 8; pub const USER_RE_DUP_MAX: c_int = 9; pub const USER_POSIX2_VERSION: c_int = 10; pub const USER_POSIX2_C_BIND: c_int = 11; pub const USER_POSIX2_C_DEV: c_int = 12; pub const USER_POSIX2_CHAR_TERM: c_int = 13; pub const USER_POSIX2_FORT_DEV: c_int = 14; pub const USER_POSIX2_FORT_RUN: c_int = 15; pub const USER_POSIX2_LOCALEDEF: c_int = 16; pub const USER_POSIX2_SW_DEV: c_int = 17; pub const USER_POSIX2_UPE: c_int = 18; pub const USER_STREAM_MAX: c_int = 19; pub const USER_TZNAME_MAX: c_int = 20; pub const USER_LOCALBASE: c_int = 21; pub const CTL_P1003_1B_ASYNCHRONOUS_IO: c_int = 1; pub const CTL_P1003_1B_MAPPED_FILES: c_int = 2; pub const CTL_P1003_1B_MEMLOCK: c_int = 3; pub const CTL_P1003_1B_MEMLOCK_RANGE: c_int = 4; pub const CTL_P1003_1B_MEMORY_PROTECTION: c_int = 5; pub const CTL_P1003_1B_MESSAGE_PASSING: c_int = 6; pub const CTL_P1003_1B_PRIORITIZED_IO: c_int = 7; pub const CTL_P1003_1B_PRIORITY_SCHEDULING: c_int = 8; pub const CTL_P1003_1B_REALTIME_SIGNALS: c_int = 9; pub const CTL_P1003_1B_SEMAPHORES: c_int = 10; pub const CTL_P1003_1B_FSYNC: c_int = 11; pub const CTL_P1003_1B_SHARED_MEMORY_OBJECTS: c_int = 12; pub const CTL_P1003_1B_SYNCHRONIZED_IO: c_int = 13; pub const CTL_P1003_1B_TIMERS: c_int = 14; pub const CTL_P1003_1B_AIO_LISTIO_MAX: c_int = 15; pub const CTL_P1003_1B_AIO_MAX: c_int = 16; pub const CTL_P1003_1B_AIO_PRIO_DELTA_MAX: c_int = 17; pub const CTL_P1003_1B_DELAYTIMER_MAX: c_int = 18; pub const CTL_P1003_1B_MQ_OPEN_MAX: c_int = 19; pub const CTL_P1003_1B_PAGESIZE: c_int = 20; pub const CTL_P1003_1B_RTSIG_MAX: c_int = 21; pub const CTL_P1003_1B_SEM_NSEMS_MAX: c_int = 22; pub const CTL_P1003_1B_SEM_VALUE_MAX: c_int = 23; pub const CTL_P1003_1B_SIGQUEUE_MAX: c_int = 24; pub const CTL_P1003_1B_TIMER_MAX: c_int = 25; pub const TIOCGPTN: c_ulong = 0x4004740f; pub const TIOCPTMASTER: c_ulong = 0x2000741c; pub const TIOCSIG: c_ulong = 0x2004745f; pub const TIOCM_DCD: c_int = 0x40; pub const H4DISC: c_int = 0x7; pub const VM_TOTAL: c_int = 1; cfg_if! { if #[cfg(target_pointer_width = "64")] { pub const BIOCSETFNR: c_ulong = 0x80104282; } else { pub const BIOCSETFNR: c_ulong = 0x80084282; } } cfg_if! { if #[cfg(target_pointer_width = "64")] { pub const FIODGNAME: c_ulong = 0x80106678; } else { pub const FIODGNAME: c_ulong = 0x80086678; } } pub const FIONWRITE: c_ulong = 0x40046677; pub const FIONSPACE: c_ulong = 0x40046676; pub const FIOSEEKDATA: c_ulong = 0xc0086661; pub const FIOSEEKHOLE: c_ulong = 0xc0086662; pub const FIOSSHMLPGCNF: c_ulong = 0x80306664; pub const JAIL_API_VERSION: u32 = 2; pub const JAIL_CREATE: c_int = 0x01; pub const JAIL_UPDATE: c_int = 0x02; pub const JAIL_ATTACH: c_int = 0x04; pub const JAIL_DYING: c_int = 0x08; pub const JAIL_SET_MASK: c_int = 0x0f; pub const JAIL_GET_MASK: c_int = 0x08; pub const JAIL_SYS_DISABLE: c_int = 0; pub const JAIL_SYS_NEW: c_int = 1; pub const JAIL_SYS_INHERIT: c_int = 2; pub const MNT_ACLS: c_int = 0x08000000; pub const MNT_BYFSID: c_int = 0x08000000; pub const MNT_GJOURNAL: c_int = 0x02000000; pub const MNT_MULTILABEL: c_int = 0x04000000; pub const MNT_NFS4ACLS: c_int = 0x00000010; pub const MNT_SNAPSHOT: c_int = 0x01000000; pub const MNT_UNION: c_int = 0x00000020; pub const MNT_NONBUSY: c_int = 0x04000000; pub const SCM_BINTIME: c_int = 0x04; pub const SCM_REALTIME: c_int = 0x05; pub const SCM_MONOTONIC: c_int = 0x06; pub const SCM_TIME_INFO: c_int = 0x07; pub const SCM_CREDS2: c_int = 0x08; pub const SO_BINTIME: c_int = 0x2000; pub const SO_NO_OFFLOAD: c_int = 0x4000; pub const SO_NO_DDP: c_int = 0x8000; pub const SO_REUSEPORT_LB: c_int = 0x10000; pub const SO_LABEL: c_int = 0x1009; pub const SO_PEERLABEL: c_int = 0x1010; pub const SO_LISTENQLIMIT: c_int = 0x1011; pub const SO_LISTENQLEN: c_int = 0x1012; pub const SO_LISTENINCQLEN: c_int = 0x1013; pub const SO_SETFIB: c_int = 0x1014; pub const SO_USER_COOKIE: c_int = 0x1015; pub const SO_PROTOCOL: c_int = 0x1016; pub const SO_PROTOTYPE: c_int = SO_PROTOCOL; pub const SO_TS_CLOCK: c_int = 0x1017; pub const SO_DOMAIN: c_int = 0x1019; pub const SO_VENDOR: c_int = 0x80000000; pub const SO_TS_REALTIME_MICRO: c_int = 0; pub const SO_TS_BINTIME: c_int = 1; pub const SO_TS_REALTIME: c_int = 2; pub const SO_TS_MONOTONIC: c_int = 3; pub const SO_TS_DEFAULT: c_int = SO_TS_REALTIME_MICRO; pub const SO_TS_CLOCK_MAX: c_int = SO_TS_MONOTONIC; pub const LOCAL_CREDS: c_int = 2; pub const LOCAL_CREDS_PERSISTENT: c_int = 3; pub const LOCAL_CONNWAIT: c_int = 4; pub const LOCAL_VENDOR: c_int = SO_VENDOR; pub const PL_EVENT_NONE: c_int = 0; pub const PL_EVENT_SIGNAL: c_int = 1; pub const PL_FLAG_SA: c_int = 0x01; pub const PL_FLAG_BOUND: c_int = 0x02; pub const PL_FLAG_SCE: c_int = 0x04; pub const PL_FLAG_SCX: c_int = 0x08; pub const PL_FLAG_EXEC: c_int = 0x10; pub const PL_FLAG_SI: c_int = 0x20; pub const PL_FLAG_FORKED: c_int = 0x40; pub const PL_FLAG_CHILD: c_int = 0x80; pub const PL_FLAG_BORN: c_int = 0x100; pub const PL_FLAG_EXITED: c_int = 0x200; pub const PL_FLAG_VFORKED: c_int = 0x400; pub const PL_FLAG_VFORK_DONE: c_int = 0x800; pub const PT_LWPINFO: c_int = 13; pub const PT_GETNUMLWPS: c_int = 14; pub const PT_GETLWPLIST: c_int = 15; pub const PT_CLEARSTEP: c_int = 16; pub const PT_SETSTEP: c_int = 17; pub const PT_SUSPEND: c_int = 18; pub const PT_RESUME: c_int = 19; pub const PT_TO_SCE: c_int = 20; pub const PT_TO_SCX: c_int = 21; pub const PT_SYSCALL: c_int = 22; pub const PT_FOLLOW_FORK: c_int = 23; pub const PT_LWP_EVENTS: c_int = 24; pub const PT_GET_EVENT_MASK: c_int = 25; pub const PT_SET_EVENT_MASK: c_int = 26; pub const PT_GET_SC_ARGS: c_int = 27; pub const PT_GET_SC_RET: c_int = 28; pub const PT_COREDUMP: c_int = 29; pub const PT_GETREGS: c_int = 33; pub const PT_SETREGS: c_int = 34; pub const PT_GETFPREGS: c_int = 35; pub const PT_SETFPREGS: c_int = 36; pub const PT_GETDBREGS: c_int = 37; pub const PT_SETDBREGS: c_int = 38; pub const PT_VM_TIMESTAMP: c_int = 40; pub const PT_VM_ENTRY: c_int = 41; pub const PT_GETREGSET: c_int = 42; pub const PT_SETREGSET: c_int = 43; pub const PT_SC_REMOTE: c_int = 44; pub const PT_FIRSTMACH: c_int = 64; pub const PTRACE_EXEC: c_int = 0x0001; pub const PTRACE_SCE: c_int = 0x0002; pub const PTRACE_SCX: c_int = 0x0004; pub const PTRACE_SYSCALL: c_int = PTRACE_SCE | PTRACE_SCX; pub const PTRACE_FORK: c_int = 0x0008; pub const PTRACE_LWP: c_int = 0x0010; pub const PTRACE_VFORK: c_int = 0x0020; pub const PTRACE_DEFAULT: c_int = PTRACE_EXEC; pub const PC_COMPRESS: u32 = 0x00000001; pub const PC_ALL: u32 = 0x00000002; pub const PROC_SPROTECT: c_int = 1; pub const PROC_REAP_ACQUIRE: c_int = 2; pub const PROC_REAP_RELEASE: c_int = 3; pub const PROC_REAP_STATUS: c_int = 4; pub const PROC_REAP_GETPIDS: c_int = 5; pub const PROC_REAP_KILL: c_int = 6; pub const PROC_TRACE_CTL: c_int = 7; pub const PROC_TRACE_STATUS: c_int = 8; pub const PROC_TRAPCAP_CTL: c_int = 9; pub const PROC_TRAPCAP_STATUS: c_int = 10; pub const PROC_PDEATHSIG_CTL: c_int = 11; pub const PROC_PDEATHSIG_STATUS: c_int = 12; pub const PROC_ASLR_CTL: c_int = 13; pub const PROC_ASLR_STATUS: c_int = 14; pub const PROC_PROTMAX_CTL: c_int = 15; pub const PROC_PROTMAX_STATUS: c_int = 16; pub const PROC_STACKGAP_CTL: c_int = 17; pub const PROC_STACKGAP_STATUS: c_int = 18; pub const PROC_NO_NEW_PRIVS_CTL: c_int = 19; pub const PROC_NO_NEW_PRIVS_STATUS: c_int = 20; pub const PROC_WXMAP_CTL: c_int = 21; pub const PROC_WXMAP_STATUS: c_int = 22; pub const PROC_PROCCTL_MD_MIN: c_int = 0x10000000; pub const PPROT_SET: c_int = 1; pub const PPROT_CLEAR: c_int = 2; pub const PPROT_DESCEND: c_int = 0x10; pub const PPROT_INHERIT: c_int = 0x20; pub const PROC_TRACE_CTL_ENABLE: c_int = 1; pub const PROC_TRACE_CTL_DISABLE: c_int = 2; pub const PROC_TRACE_CTL_DISABLE_EXEC: c_int = 3; pub const PROC_TRAPCAP_CTL_ENABLE: c_int = 1; pub const PROC_TRAPCAP_CTL_DISABLE: c_int = 2; pub const PROC_ASLR_FORCE_ENABLE: c_int = 1; pub const PROC_ASLR_FORCE_DISABLE: c_int = 2; pub const PROC_ASLR_NOFORCE: c_int = 3; pub const PROC_ASLR_ACTIVE: c_int = 0x80000000; pub const PROC_PROTMAX_FORCE_ENABLE: c_int = 1; pub const PROC_PROTMAX_FORCE_DISABLE: c_int = 2; pub const PROC_PROTMAX_NOFORCE: c_int = 3; pub const PROC_PROTMAX_ACTIVE: c_int = 0x80000000; pub const PROC_STACKGAP_ENABLE: c_int = 0x0001; pub const PROC_STACKGAP_DISABLE: c_int = 0x0002; pub const PROC_STACKGAP_ENABLE_EXEC: c_int = 0x0004; pub const PROC_STACKGAP_DISABLE_EXEC: c_int = 0x0008; pub const PROC_NO_NEW_PRIVS_ENABLE: c_int = 1; pub const PROC_NO_NEW_PRIVS_DISABLE: c_int = 2; pub const PROC_WX_MAPPINGS_PERMIT: c_int = 0x0001; pub const PROC_WX_MAPPINGS_DISALLOW_EXEC: c_int = 0x0002; pub const PROC_WXORX_ENFORCE: c_int = 0x80000000; pub const AF_SLOW: c_int = 33; pub const AF_SCLUSTER: c_int = 34; pub const AF_ARP: c_int = 35; pub const AF_BLUETOOTH: c_int = 36; pub const AF_IEEE80211: c_int = 37; pub const AF_INET_SDP: c_int = 40; pub const AF_INET6_SDP: c_int = 42; // sys/net/if.h pub const IF_MAXUNIT: c_int = 0x7fff; /// (n) interface is up pub const IFF_UP: c_int = 0x1; /// (i) broadcast address valid pub const IFF_BROADCAST: c_int = 0x2; /// (n) turn on debugging pub const IFF_DEBUG: c_int = 0x4; /// (i) is a loopback net pub const IFF_LOOPBACK: c_int = 0x8; /// (i) is a point-to-point link pub const IFF_POINTOPOINT: c_int = 0x10; /// (i) calls if_input in net epoch #[deprecated(since = "0.2.149", note = "Removed in FreeBSD 14")] pub const IFF_KNOWSEPOCH: c_int = 0x20; /// (d) resources allocated pub const IFF_RUNNING: c_int = 0x40; #[doc(hidden)] #[deprecated( since = "0.2.54", note = "IFF_DRV_RUNNING is deprecated. Use the portable IFF_RUNNING instead" )] /// (d) resources allocate pub const IFF_DRV_RUNNING: c_int = 0x40; /// (n) no address resolution protocol pub const IFF_NOARP: c_int = 0x80; /// (n) receive all packets pub const IFF_PROMISC: c_int = 0x100; /// (n) receive all multicast packets pub const IFF_ALLMULTI: c_int = 0x200; /// (d) tx hardware queue is full pub const IFF_OACTIVE: c_int = 0x400; #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Use the portable `IFF_OACTIVE` instead")] /// (d) tx hardware queue is full pub const IFF_DRV_OACTIVE: c_int = 0x400; /// (i) can't hear own transmissions pub const IFF_SIMPLEX: c_int = 0x800; /// per link layer defined bit pub const IFF_LINK0: c_int = 0x1000; /// per link layer defined bit pub const IFF_LINK1: c_int = 0x2000; /// per link layer defined bit pub const IFF_LINK2: c_int = 0x4000; /// use alternate physical connection pub const IFF_ALTPHYS: c_int = IFF_LINK2; /// (i) supports multicast pub const IFF_MULTICAST: c_int = 0x8000; /// (i) unconfigurable using ioctl(2) pub const IFF_CANTCONFIG: c_int = 0x10000; /// (n) user-requested promisc mode pub const IFF_PPROMISC: c_int = 0x20000; /// (n) user-requested monitor mode pub const IFF_MONITOR: c_int = 0x40000; /// (n) static ARP pub const IFF_STATICARP: c_int = 0x80000; /// (n) interface is winding down pub const IFF_DYING: c_int = 0x200000; /// (n) interface is being renamed pub const IFF_RENAMING: c_int = 0x400000; /// interface is not part of any groups #[deprecated(since = "0.2.149", note = "Removed in FreeBSD 14")] pub const IFF_NOGROUP: c_int = 0x800000; /// link invalid/unknown pub const LINK_STATE_UNKNOWN: c_int = 0; /// link is down pub const LINK_STATE_DOWN: c_int = 1; /// link is up pub const LINK_STATE_UP: c_int = 2; /// can offload checksum on RX pub const IFCAP_RXCSUM: c_int = 0x00001; /// can offload checksum on TX pub const IFCAP_TXCSUM: c_int = 0x00002; /// can be a network console pub const IFCAP_NETCONS: c_int = 0x00004; /// VLAN-compatible MTU pub const IFCAP_VLAN_MTU: c_int = 0x00008; /// hardware VLAN tag support pub const IFCAP_VLAN_HWTAGGING: c_int = 0x00010; /// 9000 byte MTU supported pub const IFCAP_JUMBO_MTU: c_int = 0x00020; /// driver supports polling pub const IFCAP_POLLING: c_int = 0x00040; /// can do IFCAP_HWCSUM on VLANs pub const IFCAP_VLAN_HWCSUM: c_int = 0x00080; /// can do TCP Segmentation Offload pub const IFCAP_TSO4: c_int = 0x00100; /// can do TCP6 Segmentation Offload pub const IFCAP_TSO6: c_int = 0x00200; /// can do Large Receive Offload pub const IFCAP_LRO: c_int = 0x00400; /// wake on any unicast frame pub const IFCAP_WOL_UCAST: c_int = 0x00800; /// wake on any multicast frame pub const IFCAP_WOL_MCAST: c_int = 0x01000; /// wake on any Magic Packet pub const IFCAP_WOL_MAGIC: c_int = 0x02000; /// interface can offload TCP pub const IFCAP_TOE4: c_int = 0x04000; /// interface can offload TCP6 pub const IFCAP_TOE6: c_int = 0x08000; /// interface hw can filter vlan tag pub const IFCAP_VLAN_HWFILTER: c_int = 0x10000; /// can do SIOCGIFCAPNV/SIOCSIFCAPNV pub const IFCAP_NV: c_int = 0x20000; /// can do IFCAP_TSO on VLANs pub const IFCAP_VLAN_HWTSO: c_int = 0x40000; /// the runtime link state is dynamic pub const IFCAP_LINKSTATE: c_int = 0x80000; /// netmap mode supported/enabled pub const IFCAP_NETMAP: c_int = 0x100000; /// can offload checksum on IPv6 RX pub const IFCAP_RXCSUM_IPV6: c_int = 0x200000; /// can offload checksum on IPv6 TX pub const IFCAP_TXCSUM_IPV6: c_int = 0x400000; /// manages counters internally pub const IFCAP_HWSTATS: c_int = 0x800000; /// hardware supports TX rate limiting pub const IFCAP_TXRTLMT: c_int = 0x1000000; /// hardware rx timestamping pub const IFCAP_HWRXTSTMP: c_int = 0x2000000; /// understands M_EXTPG mbufs pub const IFCAP_MEXTPG: c_int = 0x4000000; /// can do TLS encryption and segmentation for TCP pub const IFCAP_TXTLS4: c_int = 0x8000000; /// can do TLS encryption and segmentation for TCP6 pub const IFCAP_TXTLS6: c_int = 0x10000000; /// can do IFCAN_HWCSUM on VXLANs pub const IFCAP_VXLAN_HWCSUM: c_int = 0x20000000; /// can do IFCAP_TSO on VXLANs pub const IFCAP_VXLAN_HWTSO: c_int = 0x40000000; /// can do TLS with rate limiting pub const IFCAP_TXTLS_RTLMT: c_int = 0x80000000; pub const IFCAP_HWCSUM_IPV6: c_int = IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6; pub const IFCAP_HWCSUM: c_int = IFCAP_RXCSUM | IFCAP_TXCSUM; pub const IFCAP_TSO: c_int = IFCAP_TSO4 | IFCAP_TSO6; pub const IFCAP_WOL: c_int = IFCAP_WOL_UCAST | IFCAP_WOL_MCAST | IFCAP_WOL_MAGIC; pub const IFCAP_TOE: c_int = IFCAP_TOE4 | IFCAP_TOE6; pub const IFCAP_TXTLS: c_int = IFCAP_TXTLS4 | IFCAP_TXTLS6; pub const IFCAP_CANTCHANGE: c_int = IFCAP_NETMAP | IFCAP_NV; pub const IFQ_MAXLEN: c_int = 50; pub const IFNET_SLOWHZ: c_int = 1; pub const IFAN_ARRIVAL: c_int = 0; pub const IFAN_DEPARTURE: c_int = 1; pub const IFSTATMAX: c_int = 800; pub const RSS_FUNC_NONE: c_int = 0; pub const RSS_FUNC_PRIVATE: c_int = 1; pub const RSS_FUNC_TOEPLITZ: c_int = 2; pub const RSS_TYPE_IPV4: c_int = 0x00000001; pub const RSS_TYPE_TCP_IPV4: c_int = 0x00000002; pub const RSS_TYPE_IPV6: c_int = 0x00000004; pub const RSS_TYPE_IPV6_EX: c_int = 0x00000008; pub const RSS_TYPE_TCP_IPV6: c_int = 0x00000010; pub const RSS_TYPE_TCP_IPV6_EX: c_int = 0x00000020; pub const RSS_TYPE_UDP_IPV4: c_int = 0x00000040; pub const RSS_TYPE_UDP_IPV6: c_int = 0x00000080; pub const RSS_TYPE_UDP_IPV6_EX: c_int = 0x00000100; pub const RSS_KEYLEN: c_int = 128; pub const IFNET_PCP_NONE: c_int = 0xff; pub const IFDR_MSG_SIZE: c_int = 64; pub const IFDR_REASON_MSG: c_int = 1; pub const IFDR_REASON_VENDOR: c_int = 2; // sys/net/if_mib.h /// non-interface-specific pub const IFMIB_SYSTEM: c_int = 1; /// per-interface data table pub const IFMIB_IFDATA: c_int = 2; /// generic stats for all kinds of ifaces pub const IFDATA_GENERAL: c_int = 1; /// specific to the type of interface pub const IFDATA_LINKSPECIFIC: c_int = 2; /// driver name and unit pub const IFDATA_DRIVERNAME: c_int = 3; /// number of interfaces configured pub const IFMIB_IFCOUNT: c_int = 1; /// functions not specific to a type of iface pub const NETLINK_GENERIC: c_int = 0; pub const DOT3COMPLIANCE_STATS: c_int = 1; pub const DOT3COMPLIANCE_COLLS: c_int = 2; pub const dot3ChipSetAMD7990: c_int = 1; pub const dot3ChipSetAMD79900: c_int = 2; pub const dot3ChipSetAMD79C940: c_int = 3; pub const dot3ChipSetIntel82586: c_int = 1; pub const dot3ChipSetIntel82596: c_int = 2; pub const dot3ChipSetIntel82557: c_int = 3; pub const dot3ChipSetNational8390: c_int = 1; pub const dot3ChipSetNationalSonic: c_int = 2; pub const dot3ChipSetFujitsu86950: c_int = 1; pub const dot3ChipSetDigitalDC21040: c_int = 1; pub const dot3ChipSetDigitalDC21140: c_int = 2; pub const dot3ChipSetDigitalDC21041: c_int = 3; pub const dot3ChipSetDigitalDC21140A: c_int = 4; pub const dot3ChipSetDigitalDC21142: c_int = 5; pub const dot3ChipSetWesternDigital83C690: c_int = 1; pub const dot3ChipSetWesternDigital83C790: c_int = 2; // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// IP6 hop-by-hop options pub const IPPROTO_HOPOPTS: c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: c_int = 2; /// gateway^2 (deprecated) pub const IPPROTO_GGP: c_int = 3; /// for compatibility pub const IPPROTO_IPIP: c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// Stream protocol II. pub const IPPROTO_ST: c_int = 7; /// exterior gateway protocol pub const IPPROTO_EGP: c_int = 8; /// private interior gateway pub const IPPROTO_PIGP: c_int = 9; /// BBN RCC Monitoring pub const IPPROTO_RCCMON: c_int = 10; /// network voice protocol pub const IPPROTO_NVPII: c_int = 11; /// pup pub const IPPROTO_PUP: c_int = 12; /// Argus pub const IPPROTO_ARGUS: c_int = 13; /// EMCON pub const IPPROTO_EMCON: c_int = 14; /// Cross Net Debugger pub const IPPROTO_XNET: c_int = 15; /// Chaos pub const IPPROTO_CHAOS: c_int = 16; // IPPROTO_UDP defined in src/unix/mod.rs /// Multiplexing pub const IPPROTO_MUX: c_int = 18; /// DCN Measurement Subsystems pub const IPPROTO_MEAS: c_int = 19; /// Host Monitoring pub const IPPROTO_HMP: c_int = 20; /// Packet Radio Measurement pub const IPPROTO_PRM: c_int = 21; /// xns idp pub const IPPROTO_IDP: c_int = 22; /// Trunk-1 pub const IPPROTO_TRUNK1: c_int = 23; /// Trunk-2 pub const IPPROTO_TRUNK2: c_int = 24; /// Leaf-1 pub const IPPROTO_LEAF1: c_int = 25; /// Leaf-2 pub const IPPROTO_LEAF2: c_int = 26; /// Reliable Data pub const IPPROTO_RDP: c_int = 27; /// Reliable Transaction pub const IPPROTO_IRTP: c_int = 28; /// tp-4 w/ class negotiation pub const IPPROTO_TP: c_int = 29; /// Bulk Data Transfer pub const IPPROTO_BLT: c_int = 30; /// Network Services pub const IPPROTO_NSP: c_int = 31; /// Merit Internodal pub const IPPROTO_INP: c_int = 32; #[doc(hidden)] #[deprecated( since = "0.2.72", note = "IPPROTO_SEP is deprecated. Use IPPROTO_DCCP instead" )] pub const IPPROTO_SEP: c_int = 33; /// Datagram Congestion Control Protocol pub const IPPROTO_DCCP: c_int = 33; /// Third Party Connect pub const IPPROTO_3PC: c_int = 34; /// InterDomain Policy Routing pub const IPPROTO_IDPR: c_int = 35; /// XTP pub const IPPROTO_XTP: c_int = 36; /// Datagram Delivery pub const IPPROTO_DDP: c_int = 37; /// Control Message Transport pub const IPPROTO_CMTP: c_int = 38; /// TP++ Transport pub const IPPROTO_TPXX: c_int = 39; /// IL transport protocol pub const IPPROTO_IL: c_int = 40; // IPPROTO_IPV6 defined in src/unix/mod.rs /// Source Demand Routing pub const IPPROTO_SDRP: c_int = 42; /// IP6 routing header pub const IPPROTO_ROUTING: c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: c_int = 44; /// InterDomain Routing pub const IPPROTO_IDRP: c_int = 45; /// resource reservation pub const IPPROTO_RSVP: c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: c_int = 47; /// Mobile Host Routing pub const IPPROTO_MHRP: c_int = 48; /// BHA pub const IPPROTO_BHA: c_int = 49; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: c_int = 51; /// Integ. Net Layer Security pub const IPPROTO_INLSP: c_int = 52; /// IP with encryption pub const IPPROTO_SWIPE: c_int = 53; /// Next Hop Resolution pub const IPPROTO_NHRP: c_int = 54; /// IP Mobility pub const IPPROTO_MOBILE: c_int = 55; /// Transport Layer Security pub const IPPROTO_TLSP: c_int = 56; /// SKIP pub const IPPROTO_SKIP: c_int = 57; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: c_int = 60; /// any host internal protocol pub const IPPROTO_AHIP: c_int = 61; /// CFTP pub const IPPROTO_CFTP: c_int = 62; /// "hello" routing protocol pub const IPPROTO_HELLO: c_int = 63; /// SATNET/Backroom EXPAK pub const IPPROTO_SATEXPAK: c_int = 64; /// Kryptolan pub const IPPROTO_KRYPTOLAN: c_int = 65; /// Remote Virtual Disk pub const IPPROTO_RVD: c_int = 66; /// Pluribus Packet Core pub const IPPROTO_IPPC: c_int = 67; /// Any distributed FS pub const IPPROTO_ADFS: c_int = 68; /// Satnet Monitoring pub const IPPROTO_SATMON: c_int = 69; /// VISA Protocol pub const IPPROTO_VISA: c_int = 70; /// Packet Core Utility pub const IPPROTO_IPCV: c_int = 71; /// Comp. Prot. Net. Executive pub const IPPROTO_CPNX: c_int = 72; /// Comp. Prot. HeartBeat pub const IPPROTO_CPHB: c_int = 73; /// Wang Span Network pub const IPPROTO_WSN: c_int = 74; /// Packet Video Protocol pub const IPPROTO_PVP: c_int = 75; /// BackRoom SATNET Monitoring pub const IPPROTO_BRSATMON: c_int = 76; /// Sun net disk proto (temp.) pub const IPPROTO_ND: c_int = 77; /// WIDEBAND Monitoring pub const IPPROTO_WBMON: c_int = 78; /// WIDEBAND EXPAK pub const IPPROTO_WBEXPAK: c_int = 79; /// ISO cnlp pub const IPPROTO_EON: c_int = 80; /// VMTP pub const IPPROTO_VMTP: c_int = 81; /// Secure VMTP pub const IPPROTO_SVMTP: c_int = 82; /// Banyon VINES pub const IPPROTO_VINES: c_int = 83; /// TTP pub const IPPROTO_TTP: c_int = 84; /// NSFNET-IGP pub const IPPROTO_IGP: c_int = 85; /// dissimilar gateway prot. pub const IPPROTO_DGP: c_int = 86; /// TCF pub const IPPROTO_TCF: c_int = 87; /// Cisco/GXS IGRP pub const IPPROTO_IGRP: c_int = 88; /// OSPFIGP pub const IPPROTO_OSPFIGP: c_int = 89; /// Strite RPC protocol pub const IPPROTO_SRPC: c_int = 90; /// Locus Address Resoloution pub const IPPROTO_LARP: c_int = 91; /// Multicast Transport pub const IPPROTO_MTP: c_int = 92; /// AX.25 Frames pub const IPPROTO_AX25: c_int = 93; /// IP encapsulated in IP pub const IPPROTO_IPEIP: c_int = 94; /// Mobile Int.ing control pub const IPPROTO_MICP: c_int = 95; /// Semaphore Comm. security pub const IPPROTO_SCCSP: c_int = 96; /// Ethernet IP encapsulation pub const IPPROTO_ETHERIP: c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: c_int = 98; /// any private encr. scheme pub const IPPROTO_APES: c_int = 99; /// GMTP pub const IPPROTO_GMTP: c_int = 100; /// payload compression (IPComp) pub const IPPROTO_IPCOMP: c_int = 108; /// SCTP pub const IPPROTO_SCTP: c_int = 132; /// IPv6 Mobility Header pub const IPPROTO_MH: c_int = 135; /// UDP-Lite pub const IPPROTO_UDPLITE: c_int = 136; /// IP6 Host Identity Protocol pub const IPPROTO_HIP: c_int = 139; /// IP6 Shim6 Protocol pub const IPPROTO_SHIM6: c_int = 140; /* 101-254: Partly Unassigned */ /// Protocol Independent Mcast pub const IPPROTO_PIM: c_int = 103; /// CARP pub const IPPROTO_CARP: c_int = 112; /// PGM pub const IPPROTO_PGM: c_int = 113; /// MPLS-in-IP pub const IPPROTO_MPLS: c_int = 137; /// PFSYNC pub const IPPROTO_PFSYNC: c_int = 240; /* 255: Reserved */ /* BSD Private, local use, namespace incursion, no longer used */ /// OLD divert pseudo-proto pub const IPPROTO_OLD_DIVERT: c_int = 254; pub const IPPROTO_MAX: c_int = 256; /// last return value of *_input(), meaning "all job for this pkt is done". pub const IPPROTO_DONE: c_int = 257; /* Only used internally, so can be outside the range of valid IP protocols. */ /// divert pseudo-protocol pub const IPPROTO_DIVERT: c_int = 258; /// SeND pseudo-protocol pub const IPPROTO_SEND: c_int = 259; // sys/netinet/TCP.h pub const TCP_MD5SIG: c_int = 16; pub const TCP_INFO: c_int = 32; pub const TCP_CONGESTION: c_int = 64; pub const TCP_CCALGOOPT: c_int = 65; pub const TCP_MAXUNACKTIME: c_int = 68; #[deprecated(since = "0.2.160", note = "Removed in FreeBSD 15")] pub const TCP_MAXPEAKRATE: c_int = 69; pub const TCP_IDLE_REDUCE: c_int = 70; pub const TCP_REMOTE_UDP_ENCAPS_PORT: c_int = 71; pub const TCP_DELACK: c_int = 72; pub const TCP_FIN_IS_RST: c_int = 73; pub const TCP_LOG_LIMIT: c_int = 74; pub const TCP_SHARED_CWND_ALLOWED: c_int = 75; pub const TCP_PROC_ACCOUNTING: c_int = 76; pub const TCP_USE_CMP_ACKS: c_int = 77; pub const TCP_PERF_INFO: c_int = 78; pub const TCP_LRD: c_int = 79; pub const TCP_KEEPINIT: c_int = 128; pub const TCP_FASTOPEN: c_int = 1025; #[deprecated(since = "0.2.171", note = "removed in FreeBSD 15")] pub const TCP_PCAP_OUT: c_int = 2048; #[deprecated(since = "0.2.171", note = "removed in FreeBSD 15")] pub const TCP_PCAP_IN: c_int = 4096; pub const TCP_FUNCTION_BLK: c_int = 8192; pub const TCP_FUNCTION_ALIAS: c_int = 8193; pub const TCP_FASTOPEN_PSK_LEN: c_int = 16; pub const TCP_FUNCTION_NAME_LEN_MAX: c_int = 32; pub const TCP_REUSPORT_LB_NUMA: c_int = 1026; pub const TCP_RACK_MBUF_QUEUE: c_int = 1050; pub const TCP_RACK_TLP_REDUCE: c_int = 1052; pub const TCP_RACK_PACE_MAX_SEG: c_int = 1054; pub const TCP_RACK_PACE_ALWAYS: c_int = 1055; pub const TCP_RACK_PRR_SENDALOT: c_int = 1057; pub const TCP_RACK_MIN_TO: c_int = 1058; pub const TCP_RACK_EARLY_SEG: c_int = 1060; pub const TCP_RACK_REORD_THRESH: c_int = 1061; pub const TCP_RACK_REORD_FADE: c_int = 1062; pub const TCP_RACK_TLP_THRESH: c_int = 1063; pub const TCP_RACK_PKT_DELAY: c_int = 1064; pub const TCP_BBR_IWINTSO: c_int = 1067; pub const TCP_BBR_STARTUP_PG: c_int = 1069; pub const TCP_BBR_DRAIN_PG: c_int = 1070; pub const TCP_BBR_PROBE_RTT_INT: c_int = 1072; pub const TCP_BBR_STARTUP_LOSS_EXIT: c_int = 1074; pub const TCP_BBR_TSLIMITS: c_int = 1076; pub const TCP_BBR_PACE_OH: c_int = 1077; pub const TCP_BBR_USEDEL_RATE: c_int = 1079; pub const TCP_BBR_MIN_RTO: c_int = 1080; pub const TCP_BBR_MAX_RTO: c_int = 1081; pub const TCP_BBR_ALGORITHM: c_int = 1083; pub const IP_BINDANY: c_int = 24; pub const IP_BINDMULTI: c_int = 25; pub const IP_RSS_LISTEN_BUCKET: c_int = 26; pub const IP_ORIGDSTADDR: c_int = 27; pub const IP_RECVORIGDSTADDR: c_int = IP_ORIGDSTADDR; pub const IP_DONTFRAG: c_int = 67; pub const IP_RECVTOS: c_int = 68; pub const IPV6_BINDANY: c_int = 64; pub const IPV6_ORIGDSTADDR: c_int = 72; pub const IPV6_RECVORIGDSTADDR: c_int = IPV6_ORIGDSTADDR; pub const PF_SLOW: c_int = AF_SLOW; pub const PF_SCLUSTER: c_int = AF_SCLUSTER; pub const PF_ARP: c_int = AF_ARP; pub const PF_BLUETOOTH: c_int = AF_BLUETOOTH; pub const PF_IEEE80211: c_int = AF_IEEE80211; pub const PF_INET_SDP: c_int = AF_INET_SDP; pub const PF_INET6_SDP: c_int = AF_INET6_SDP; pub const NET_RT_DUMP: c_int = 1; pub const NET_RT_FLAGS: c_int = 2; pub const NET_RT_IFLIST: c_int = 3; pub const NET_RT_IFMALIST: c_int = 4; pub const NET_RT_IFLISTL: c_int = 5; // System V IPC pub const IPC_INFO: c_int = 3; pub const MSG_NOERROR: c_int = 0o10000; pub const SHM_LOCK: c_int = 11; pub const SHM_UNLOCK: c_int = 12; pub const SHM_STAT: c_int = 13; pub const SHM_INFO: c_int = 14; pub const SHM_ANON: *mut c_char = 1 as *mut c_char; // The *_MAXID constants never should've been used outside of the // FreeBSD base system. And with the exception of CTL_P1003_1B_MAXID, // they were all removed in svn r262489. They remain here for backwards // compatibility only, and are scheduled to be removed in libc 1.0.0. #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Removed in FreeBSD 11")] pub const CTL_MAXID: c_int = 10; #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Removed in FreeBSD 11")] pub const KERN_MAXID: c_int = 38; #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Removed in FreeBSD 11")] pub const HW_MAXID: c_int = 13; #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Removed in FreeBSD 11")] pub const USER_MAXID: c_int = 21; #[doc(hidden)] #[deprecated(since = "0.2.74", note = "Removed in FreeBSD 13")] pub const CTL_P1003_1B_MAXID: c_int = 26; pub const MSG_NOTIFICATION: c_int = 0x00002000; pub const MSG_NBIO: c_int = 0x00004000; pub const MSG_COMPAT: c_int = 0x00008000; pub const MSG_CMSG_CLOEXEC: c_int = 0x00040000; pub const MSG_NOSIGNAL: c_int = 0x20000; pub const MSG_WAITFORONE: c_int = 0x00080000; // utmpx entry types pub const EMPTY: c_short = 0; pub const BOOT_TIME: c_short = 1; pub const OLD_TIME: c_short = 2; pub const NEW_TIME: c_short = 3; pub const USER_PROCESS: c_short = 4; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const DEAD_PROCESS: c_short = 7; pub const SHUTDOWN_TIME: c_short = 8; // utmp database types pub const UTXDB_ACTIVE: c_int = 0; pub const UTXDB_LASTLOGIN: c_int = 1; pub const UTXDB_LOG: c_int = 2; pub const LC_COLLATE_MASK: c_int = 1 << 0; pub const LC_CTYPE_MASK: c_int = 1 << 1; pub const LC_MONETARY_MASK: c_int = 1 << 2; pub const LC_NUMERIC_MASK: c_int = 1 << 3; pub const LC_TIME_MASK: c_int = 1 << 4; pub const LC_MESSAGES_MASK: c_int = 1 << 5; pub const LC_ALL_MASK: c_int = LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK; pub const WSTOPPED: c_int = 2; // same as WUNTRACED pub const WCONTINUED: c_int = 4; pub const WNOWAIT: c_int = 8; pub const WEXITED: c_int = 16; pub const WTRAPPED: c_int = 32; // FreeBSD defines a great many more of these, we only expose the // standardized ones. pub const P_PID: idtype_t = 0; pub const P_PGID: idtype_t = 2; pub const P_ALL: idtype_t = 7; pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; pub const B460800: crate::speed_t = 460800; pub const B921600: crate::speed_t = 921600; pub const AT_FDCWD: c_int = -100; pub const AT_EACCESS: c_int = 0x100; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x200; pub const AT_SYMLINK_FOLLOW: c_int = 0x400; pub const AT_REMOVEDIR: c_int = 0x800; pub const AT_RESOLVE_BENEATH: c_int = 0x2000; pub const AT_EMPTY_PATH: c_int = 0x4000; pub const AT_NULL: c_int = 0; pub const AT_IGNORE: c_int = 1; pub const AT_EXECFD: c_int = 2; pub const AT_PHDR: c_int = 3; pub const AT_PHENT: c_int = 4; pub const AT_PHNUM: c_int = 5; pub const AT_PAGESZ: c_int = 6; pub const AT_BASE: c_int = 7; pub const AT_FLAGS: c_int = 8; pub const AT_ENTRY: c_int = 9; pub const AT_NOTELF: c_int = 10; pub const AT_UID: c_int = 11; pub const AT_EUID: c_int = 12; pub const AT_GID: c_int = 13; pub const AT_EGID: c_int = 14; pub const AT_EXECPATH: c_int = 15; pub const AT_CANARY: c_int = 16; pub const AT_OSRELDATE: c_int = 18; pub const AT_NCPUS: c_int = 19; pub const AT_PAGESIZES: c_int = 20; pub const AT_TIMEKEEP: c_int = 22; pub const AT_HWCAP: c_int = 25; pub const AT_HWCAP2: c_int = 26; pub const AT_USRSTACKBASE: c_int = 35; pub const AT_USRSTACKLIM: c_int = 36; pub const TABDLY: crate::tcflag_t = 0x00000004; pub const TAB0: crate::tcflag_t = 0x00000000; pub const TAB3: crate::tcflag_t = 0x00000004; pub const _PC_ACL_NFS4: c_int = 64; pub const _SC_CPUSET_SIZE: c_int = 122; pub const _UUID_NODE_LEN: usize = 6; // Flags which can be passed to pdfork(2) pub const PD_DAEMON: c_int = 0x00000001; pub const PD_CLOEXEC: c_int = 0x00000002; pub const PD_ALLOWED_AT_FORK: c_int = PD_DAEMON | PD_CLOEXEC; // Values for struct rtprio (type_ field) pub const RTP_PRIO_REALTIME: c_ushort = 2; pub const RTP_PRIO_NORMAL: c_ushort = 3; pub const RTP_PRIO_IDLE: c_ushort = 4; // Flags for chflags(2) pub const UF_SYSTEM: c_ulong = 0x00000080; pub const UF_SPARSE: c_ulong = 0x00000100; pub const UF_OFFLINE: c_ulong = 0x00000200; pub const UF_REPARSE: c_ulong = 0x00000400; pub const UF_ARCHIVE: c_ulong = 0x00000800; pub const UF_READONLY: c_ulong = 0x00001000; pub const UF_HIDDEN: c_ulong = 0x00008000; pub const SF_SNAPSHOT: c_ulong = 0x00200000; // fcntl commands pub const F_ADD_SEALS: c_int = 19; pub const F_GET_SEALS: c_int = 20; pub const F_OGETLK: c_int = 7; pub const F_OSETLK: c_int = 8; pub const F_OSETLKW: c_int = 9; pub const F_RDAHEAD: c_int = 16; pub const F_READAHEAD: c_int = 15; pub const F_SETLK_REMOTE: c_int = 14; pub const F_KINFO: c_int = 22; // for use with F_ADD_SEALS pub const F_SEAL_GROW: c_int = 4; pub const F_SEAL_SEAL: c_int = 1; pub const F_SEAL_SHRINK: c_int = 2; pub const F_SEAL_WRITE: c_int = 8; // for use with fspacectl pub const SPACECTL_DEALLOC: c_int = 1; // For realhostname* api pub const HOSTNAME_FOUND: c_int = 0; pub const HOSTNAME_INCORRECTNAME: c_int = 1; pub const HOSTNAME_INVALIDADDR: c_int = 2; pub const HOSTNAME_INVALIDNAME: c_int = 3; // For rfork pub const RFFDG: c_int = 4; pub const RFPROC: c_int = 16; pub const RFMEM: c_int = 32; pub const RFNOWAIT: c_int = 64; pub const RFCFDG: c_int = 4096; pub const RFTHREAD: c_int = 8192; pub const RFSIGSHARE: c_int = 16384; pub const RFLINUXTHPN: c_int = 65536; pub const RFTSIGZMB: c_int = 524288; pub const RFSPAWN: c_int = 2147483648; // For eventfd pub const EFD_SEMAPHORE: c_int = 0x1; pub const EFD_NONBLOCK: c_int = 0x4; pub const EFD_CLOEXEC: c_int = 0x100000; pub const MALLOCX_ZERO: c_int = 0x40; /// size of returned wchan message pub const WMESGLEN: usize = 8; /// size of returned lock name pub const LOCKNAMELEN: usize = 8; /// size of returned thread name pub const TDNAMLEN: usize = 16; /// size of returned ki_comm name pub const COMMLEN: usize = 19; /// size of returned ki_emul pub const KI_EMULNAMELEN: usize = 16; /// number of groups in ki_groups pub const KI_NGROUPS: usize = 16; cfg_if! { if #[cfg(freebsd11)] { pub const KI_NSPARE_INT: usize = 4; } else { pub const KI_NSPARE_INT: usize = 2; } } pub const KI_NSPARE_LONG: usize = 12; /// Flags for the process credential. pub const KI_CRF_CAPABILITY_MODE: usize = 0x00000001; /// Steal a bit from ki_cr_flags to indicate that the cred had more than /// KI_NGROUPS groups. pub const KI_CRF_GRP_OVERFLOW: usize = 0x80000000; /// controlling tty vnode active pub const KI_CTTY: usize = 0x00000001; /// session leader pub const KI_SLEADER: usize = 0x00000002; /// proc blocked on lock ki_lockname pub const KI_LOCKBLOCK: usize = 0x00000004; /// size of returned ki_login pub const LOGNAMELEN: usize = 17; /// size of returned ki_loginclass pub const LOGINCLASSLEN: usize = 17; pub const KF_ATTR_VALID: c_int = 0x0001; pub const KF_TYPE_NONE: c_int = 0; pub const KF_TYPE_VNODE: c_int = 1; pub const KF_TYPE_SOCKET: c_int = 2; pub const KF_TYPE_PIPE: c_int = 3; pub const KF_TYPE_FIFO: c_int = 4; pub const KF_TYPE_KQUEUE: c_int = 5; pub const KF_TYPE_MQUEUE: c_int = 7; pub const KF_TYPE_SHM: c_int = 8; pub const KF_TYPE_SEM: c_int = 9; pub const KF_TYPE_PTS: c_int = 10; pub const KF_TYPE_PROCDESC: c_int = 11; pub const KF_TYPE_DEV: c_int = 12; pub const KF_TYPE_UNKNOWN: c_int = 255; pub const KF_VTYPE_VNON: c_int = 0; pub const KF_VTYPE_VREG: c_int = 1; pub const KF_VTYPE_VDIR: c_int = 2; pub const KF_VTYPE_VBLK: c_int = 3; pub const KF_VTYPE_VCHR: c_int = 4; pub const KF_VTYPE_VLNK: c_int = 5; pub const KF_VTYPE_VSOCK: c_int = 6; pub const KF_VTYPE_VFIFO: c_int = 7; pub const KF_VTYPE_VBAD: c_int = 8; pub const KF_VTYPE_UNKNOWN: c_int = 255; /// Current working directory pub const KF_FD_TYPE_CWD: c_int = -1; /// Root directory pub const KF_FD_TYPE_ROOT: c_int = -2; /// Jail directory pub const KF_FD_TYPE_JAIL: c_int = -3; /// Ktrace vnode pub const KF_FD_TYPE_TRACE: c_int = -4; pub const KF_FD_TYPE_TEXT: c_int = -5; /// Controlling terminal pub const KF_FD_TYPE_CTTY: c_int = -6; pub const KF_FLAG_READ: c_int = 0x00000001; pub const KF_FLAG_WRITE: c_int = 0x00000002; pub const KF_FLAG_APPEND: c_int = 0x00000004; pub const KF_FLAG_ASYNC: c_int = 0x00000008; pub const KF_FLAG_FSYNC: c_int = 0x00000010; pub const KF_FLAG_NONBLOCK: c_int = 0x00000020; pub const KF_FLAG_DIRECT: c_int = 0x00000040; pub const KF_FLAG_HASLOCK: c_int = 0x00000080; pub const KF_FLAG_SHLOCK: c_int = 0x00000100; pub const KF_FLAG_EXLOCK: c_int = 0x00000200; pub const KF_FLAG_NOFOLLOW: c_int = 0x00000400; pub const KF_FLAG_CREAT: c_int = 0x00000800; pub const KF_FLAG_TRUNC: c_int = 0x00001000; pub const KF_FLAG_EXCL: c_int = 0x00002000; pub const KF_FLAG_EXEC: c_int = 0x00004000; pub const KVME_TYPE_NONE: c_int = 0; pub const KVME_TYPE_DEFAULT: c_int = 1; pub const KVME_TYPE_VNODE: c_int = 2; pub const KVME_TYPE_SWAP: c_int = 3; pub const KVME_TYPE_DEVICE: c_int = 4; pub const KVME_TYPE_PHYS: c_int = 5; pub const KVME_TYPE_DEAD: c_int = 6; pub const KVME_TYPE_SG: c_int = 7; pub const KVME_TYPE_MGTDEVICE: c_int = 8; // Present in `sys/user.h` but is undefined for whatever reason... // pub const KVME_TYPE_GUARD: c_int = 9; pub const KVME_TYPE_UNKNOWN: c_int = 255; pub const KVME_PROT_READ: c_int = 0x00000001; pub const KVME_PROT_WRITE: c_int = 0x00000002; pub const KVME_PROT_EXEC: c_int = 0x00000004; pub const KVME_FLAG_COW: c_int = 0x00000001; pub const KVME_FLAG_NEEDS_COPY: c_int = 0x00000002; pub const KVME_FLAG_NOCOREDUMP: c_int = 0x00000004; pub const KVME_FLAG_SUPER: c_int = 0x00000008; pub const KVME_FLAG_GROWS_UP: c_int = 0x00000010; pub const KVME_FLAG_GROWS_DOWN: c_int = 0x00000020; pub const KVME_FLAG_USER_WIRED: c_int = 0x00000040; pub const KKST_MAXLEN: c_int = 1024; /// Stack is valid. pub const KKST_STATE_STACKOK: c_int = 0; /// Stack swapped out. pub const KKST_STATE_SWAPPED: c_int = 1; pub const KKST_STATE_RUNNING: c_int = 2; // Constants about priority. pub const PRI_MIN: c_int = 0; pub const PRI_MAX: c_int = 255; pub const PRI_MIN_ITHD: c_int = PRI_MIN; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PRI_MAX_ITHD: c_int = PRI_MIN_REALTIME - 1; pub const PI_REALTIME: c_int = PRI_MIN_ITHD + 0; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_AV: c_int = PRI_MIN_ITHD + 4; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_NET: c_int = PRI_MIN_ITHD + 8; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_DISK: c_int = PRI_MIN_ITHD + 12; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_TTY: c_int = PRI_MIN_ITHD + 16; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_DULL: c_int = PRI_MIN_ITHD + 20; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_SOFT: c_int = PRI_MIN_ITHD + 24; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PRI_MIN_REALTIME: c_int = 48; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PRI_MAX_REALTIME: c_int = PRI_MIN_KERN - 1; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PRI_MIN_KERN: c_int = 80; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PRI_MAX_KERN: c_int = PRI_MIN_TIMESHARE - 1; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PSWP: c_int = PRI_MIN_KERN + 0; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PVM: c_int = PRI_MIN_KERN + 4; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PINOD: c_int = PRI_MIN_KERN + 8; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PRIBIO: c_int = PRI_MIN_KERN + 12; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PVFS: c_int = PRI_MIN_KERN + 16; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PZERO: c_int = PRI_MIN_KERN + 20; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PSOCK: c_int = PRI_MIN_KERN + 24; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PWAIT: c_int = PRI_MIN_KERN + 28; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PLOCK: c_int = PRI_MIN_KERN + 32; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PPAUSE: c_int = PRI_MIN_KERN + 36; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PRI_MIN_TIMESHARE: c_int = 120; pub const PRI_MAX_TIMESHARE: c_int = PRI_MIN_IDLE - 1; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PUSER: c_int = PRI_MIN_TIMESHARE; pub const PRI_MIN_IDLE: c_int = 224; pub const PRI_MAX_IDLE: c_int = PRI_MAX; pub const NZERO: c_int = 0; // Resource utilization information. pub const RUSAGE_THREAD: c_int = 1; cfg_if! { if #[cfg(any(freebsd11, target_pointer_width = "32"))] { pub const ARG_MAX: c_int = 256 * 1024; } else { pub const ARG_MAX: c_int = 2 * 256 * 1024; } } pub const CHILD_MAX: c_int = 40; /// max command name remembered pub const MAXCOMLEN: usize = 19; /// max interpreter file name length pub const MAXINTERP: c_int = crate::PATH_MAX; /// max login name length (incl. NUL) pub const MAXLOGNAME: c_int = 33; /// max simultaneous processes pub const MAXUPRC: c_int = CHILD_MAX; /// max bytes for an exec function pub const NCARGS: c_int = ARG_MAX; /// /* max number groups pub const NGROUPS: c_int = NGROUPS_MAX + 1; /// max open files per process pub const NOFILE: c_int = OPEN_MAX; /// marker for empty group set member pub const NOGROUP: c_int = 65535; /// max hostname size pub const MAXHOSTNAMELEN: c_int = 256; /// max bytes in term canon input line pub const MAX_CANON: c_int = 255; /// max bytes in terminal input pub const MAX_INPUT: c_int = 255; /// max bytes in a file name pub const NAME_MAX: c_int = 255; pub const MAXSYMLINKS: c_int = 32; /// max supplemental group id's pub const NGROUPS_MAX: c_int = 1023; /// max open files per process pub const OPEN_MAX: c_int = 64; pub const _POSIX_ARG_MAX: c_int = 4096; pub const _POSIX_LINK_MAX: c_int = 8; pub const _POSIX_MAX_CANON: c_int = 255; pub const _POSIX_MAX_INPUT: c_int = 255; pub const _POSIX_NAME_MAX: c_int = 14; pub const _POSIX_PIPE_BUF: c_int = 512; pub const _POSIX_SSIZE_MAX: c_int = 32767; pub const _POSIX_STREAM_MAX: c_int = 8; /// max ibase/obase values in bc(1) pub const BC_BASE_MAX: c_int = 99; /// max array elements in bc(1) pub const BC_DIM_MAX: c_int = 2048; /// max scale value in bc(1) pub const BC_SCALE_MAX: c_int = 99; /// max const string length in bc(1) pub const BC_STRING_MAX: c_int = 1000; /// max character class name size pub const CHARCLASS_NAME_MAX: c_int = 14; /// max weights for order keyword pub const COLL_WEIGHTS_MAX: c_int = 10; /// max expressions nested in expr(1) pub const EXPR_NEST_MAX: c_int = 32; /// max bytes in an input line pub const LINE_MAX: c_int = 2048; /// max RE's in interval notation pub const RE_DUP_MAX: c_int = 255; pub const _POSIX2_BC_BASE_MAX: c_int = 99; pub const _POSIX2_BC_DIM_MAX: c_int = 2048; pub const _POSIX2_BC_SCALE_MAX: c_int = 99; pub const _POSIX2_BC_STRING_MAX: c_int = 1000; pub const _POSIX2_CHARCLASS_NAME_MAX: c_int = 14; pub const _POSIX2_COLL_WEIGHTS_MAX: c_int = 2; pub const _POSIX2_EQUIV_CLASS_MAX: c_int = 2; pub const _POSIX2_EXPR_NEST_MAX: c_int = 32; pub const _POSIX2_LINE_MAX: c_int = 2048; pub const _POSIX2_RE_DUP_MAX: c_int = 255; // sys/proc.h pub const TDF_BORROWING: c_int = 0x00000001; pub const TDF_INPANIC: c_int = 0x00000002; pub const TDF_INMEM: c_int = 0x00000004; pub const TDF_SINTR: c_int = 0x00000008; pub const TDF_TIMEOUT: c_int = 0x00000010; pub const TDF_IDLETD: c_int = 0x00000020; pub const TDF_CANSWAP: c_int = 0x00000040; pub const TDF_KTH_SUSP: c_int = 0x00000100; pub const TDF_ALLPROCSUSP: c_int = 0x00000200; pub const TDF_BOUNDARY: c_int = 0x00000400; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_ASTPENDING: c_int = 0x00000800; pub const TDF_SBDRY: c_int = 0x00002000; pub const TDF_UPIBLOCKED: c_int = 0x00004000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_NEEDSUSPCHK: c_int = 0x00008000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_NEEDRESCHED: c_int = 0x00010000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_NEEDSIGCHK: c_int = 0x00020000; pub const TDF_NOLOAD: c_int = 0x00040000; pub const TDF_SERESTART: c_int = 0x00080000; pub const TDF_THRWAKEUP: c_int = 0x00100000; pub const TDF_SEINTR: c_int = 0x00200000; pub const TDF_SWAPINREQ: c_int = 0x00400000; #[deprecated(since = "0.2.133", note = "Removed in FreeBSD 14")] pub const TDF_UNUSED23: c_int = 0x00800000; pub const TDF_SCHED0: c_int = 0x01000000; pub const TDF_SCHED1: c_int = 0x02000000; pub const TDF_SCHED2: c_int = 0x04000000; pub const TDF_SCHED3: c_int = 0x08000000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_ALRMPEND: c_int = 0x10000000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_PROFPEND: c_int = 0x20000000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_MACPEND: c_int = 0x40000000; pub const TDB_SUSPEND: c_int = 0x00000001; pub const TDB_XSIG: c_int = 0x00000002; pub const TDB_USERWR: c_int = 0x00000004; pub const TDB_SCE: c_int = 0x00000008; pub const TDB_SCX: c_int = 0x00000010; pub const TDB_EXEC: c_int = 0x00000020; pub const TDB_FORK: c_int = 0x00000040; pub const TDB_STOPATFORK: c_int = 0x00000080; pub const TDB_CHILD: c_int = 0x00000100; pub const TDB_BORN: c_int = 0x00000200; pub const TDB_EXIT: c_int = 0x00000400; pub const TDB_VFORK: c_int = 0x00000800; pub const TDB_FSTP: c_int = 0x00001000; pub const TDB_STEP: c_int = 0x00002000; pub const TDP_OLDMASK: c_int = 0x00000001; pub const TDP_INKTR: c_int = 0x00000002; pub const TDP_INKTRACE: c_int = 0x00000004; pub const TDP_BUFNEED: c_int = 0x00000008; pub const TDP_COWINPROGRESS: c_int = 0x00000010; pub const TDP_ALTSTACK: c_int = 0x00000020; pub const TDP_DEADLKTREAT: c_int = 0x00000040; pub const TDP_NOFAULTING: c_int = 0x00000080; pub const TDP_OWEUPC: c_int = 0x00000200; pub const TDP_ITHREAD: c_int = 0x00000400; pub const TDP_SYNCIO: c_int = 0x00000800; pub const TDP_SCHED1: c_int = 0x00001000; pub const TDP_SCHED2: c_int = 0x00002000; pub const TDP_SCHED3: c_int = 0x00004000; pub const TDP_SCHED4: c_int = 0x00008000; pub const TDP_GEOM: c_int = 0x00010000; pub const TDP_SOFTDEP: c_int = 0x00020000; pub const TDP_NORUNNINGBUF: c_int = 0x00040000; pub const TDP_WAKEUP: c_int = 0x00080000; pub const TDP_INBDFLUSH: c_int = 0x00100000; pub const TDP_KTHREAD: c_int = 0x00200000; pub const TDP_CALLCHAIN: c_int = 0x00400000; pub const TDP_IGNSUSP: c_int = 0x00800000; pub const TDP_AUDITREC: c_int = 0x01000000; pub const TDP_RFPPWAIT: c_int = 0x02000000; pub const TDP_RESETSPUR: c_int = 0x04000000; pub const TDP_NERRNO: c_int = 0x08000000; pub const TDP_EXECVMSPC: c_int = 0x40000000; pub const TDI_SUSPENDED: c_int = 0x0001; pub const TDI_SLEEPING: c_int = 0x0002; pub const TDI_SWAPPED: c_int = 0x0004; pub const TDI_LOCK: c_int = 0x0008; pub const TDI_IWAIT: c_int = 0x0010; pub const P_ADVLOCK: c_int = 0x00000001; pub const P_CONTROLT: c_int = 0x00000002; pub const P_KPROC: c_int = 0x00000004; pub const P_UNUSED3: c_int = 0x00000008; pub const P_PPWAIT: c_int = 0x00000010; pub const P_PROFIL: c_int = 0x00000020; pub const P_STOPPROF: c_int = 0x00000040; pub const P_HADTHREADS: c_int = 0x00000080; pub const P_SUGID: c_int = 0x00000100; pub const P_SYSTEM: c_int = 0x00000200; pub const P_SINGLE_EXIT: c_int = 0x00000400; pub const P_TRACED: c_int = 0x00000800; pub const P_WAITED: c_int = 0x00001000; pub const P_WEXIT: c_int = 0x00002000; pub const P_EXEC: c_int = 0x00004000; pub const P_WKILLED: c_int = 0x00008000; pub const P_CONTINUED: c_int = 0x00010000; pub const P_STOPPED_SIG: c_int = 0x00020000; pub const P_STOPPED_TRACE: c_int = 0x00040000; pub const P_STOPPED_SINGLE: c_int = 0x00080000; pub const P_PROTECTED: c_int = 0x00100000; pub const P_SIGEVENT: c_int = 0x00200000; pub const P_SINGLE_BOUNDARY: c_int = 0x00400000; pub const P_HWPMC: c_int = 0x00800000; pub const P_JAILED: c_int = 0x01000000; pub const P_TOTAL_STOP: c_int = 0x02000000; pub const P_INEXEC: c_int = 0x04000000; pub const P_STATCHILD: c_int = 0x08000000; pub const P_INMEM: c_int = 0x10000000; pub const P_SWAPPINGOUT: c_int = 0x20000000; pub const P_SWAPPINGIN: c_int = 0x40000000; pub const P_PPTRACE: c_int = 0x80000000; pub const P_STOPPED: c_int = P_STOPPED_SIG | P_STOPPED_SINGLE | P_STOPPED_TRACE; pub const P2_INHERIT_PROTECTED: c_int = 0x00000001; pub const P2_NOTRACE: c_int = 0x00000002; pub const P2_NOTRACE_EXEC: c_int = 0x00000004; pub const P2_AST_SU: c_int = 0x00000008; pub const P2_PTRACE_FSTP: c_int = 0x00000010; pub const P2_TRAPCAP: c_int = 0x00000020; pub const P2_STKGAP_DISABLE: c_int = 0x00000800; pub const P2_STKGAP_DISABLE_EXEC: c_int = 0x00001000; pub const P_TREE_ORPHANED: c_int = 0x00000001; pub const P_TREE_FIRST_ORPHAN: c_int = 0x00000002; pub const P_TREE_REAPER: c_int = 0x00000004; pub const SIDL: c_char = 1; pub const SRUN: c_char = 2; pub const SSLEEP: c_char = 3; pub const SSTOP: c_char = 4; pub const SZOMB: c_char = 5; pub const SWAIT: c_char = 6; pub const SLOCK: c_char = 7; pub const P_MAGIC: c_int = 0xbeefface; pub const TDP_SIGFASTBLOCK: c_int = 0x00000100; pub const TDP_UIOHELD: c_int = 0x10000000; pub const TDP_SIGFASTPENDING: c_int = 0x80000000; pub const TDP2_COMPAT32RB: c_int = 0x00000002; pub const P2_PROTMAX_ENABLE: c_int = 0x00000200; pub const P2_PROTMAX_DISABLE: c_int = 0x00000400; pub const TDP2_SBPAGES: c_int = 0x00000001; pub const P2_ASLR_ENABLE: c_int = 0x00000040; pub const P2_ASLR_DISABLE: c_int = 0x00000080; pub const P2_ASLR_IGNSTART: c_int = 0x00000100; pub const P_TREE_GRPEXITED: c_int = 0x00000008; // libprocstat.h pub const PS_FST_VTYPE_VNON: c_int = 1; pub const PS_FST_VTYPE_VREG: c_int = 2; pub const PS_FST_VTYPE_VDIR: c_int = 3; pub const PS_FST_VTYPE_VBLK: c_int = 4; pub const PS_FST_VTYPE_VCHR: c_int = 5; pub const PS_FST_VTYPE_VLNK: c_int = 6; pub const PS_FST_VTYPE_VSOCK: c_int = 7; pub const PS_FST_VTYPE_VFIFO: c_int = 8; pub const PS_FST_VTYPE_VBAD: c_int = 9; pub const PS_FST_VTYPE_UNKNOWN: c_int = 255; pub const PS_FST_TYPE_VNODE: c_int = 1; pub const PS_FST_TYPE_FIFO: c_int = 2; pub const PS_FST_TYPE_SOCKET: c_int = 3; pub const PS_FST_TYPE_PIPE: c_int = 4; pub const PS_FST_TYPE_PTS: c_int = 5; pub const PS_FST_TYPE_KQUEUE: c_int = 6; pub const PS_FST_TYPE_MQUEUE: c_int = 8; pub const PS_FST_TYPE_SHM: c_int = 9; pub const PS_FST_TYPE_SEM: c_int = 10; pub const PS_FST_TYPE_UNKNOWN: c_int = 11; pub const PS_FST_TYPE_NONE: c_int = 12; pub const PS_FST_TYPE_PROCDESC: c_int = 13; pub const PS_FST_TYPE_DEV: c_int = 14; pub const PS_FST_TYPE_EVENTFD: c_int = 15; pub const PS_FST_UFLAG_RDIR: c_int = 0x0001; pub const PS_FST_UFLAG_CDIR: c_int = 0x0002; pub const PS_FST_UFLAG_JAIL: c_int = 0x0004; pub const PS_FST_UFLAG_TRACE: c_int = 0x0008; pub const PS_FST_UFLAG_TEXT: c_int = 0x0010; pub const PS_FST_UFLAG_MMAP: c_int = 0x0020; pub const PS_FST_UFLAG_CTTY: c_int = 0x0040; pub const PS_FST_FFLAG_READ: c_int = 0x0001; pub const PS_FST_FFLAG_WRITE: c_int = 0x0002; pub const PS_FST_FFLAG_NONBLOCK: c_int = 0x0004; pub const PS_FST_FFLAG_APPEND: c_int = 0x0008; pub const PS_FST_FFLAG_SHLOCK: c_int = 0x0010; pub const PS_FST_FFLAG_EXLOCK: c_int = 0x0020; pub const PS_FST_FFLAG_ASYNC: c_int = 0x0040; pub const PS_FST_FFLAG_SYNC: c_int = 0x0080; pub const PS_FST_FFLAG_NOFOLLOW: c_int = 0x0100; pub const PS_FST_FFLAG_CREAT: c_int = 0x0200; pub const PS_FST_FFLAG_TRUNC: c_int = 0x0400; pub const PS_FST_FFLAG_EXCL: c_int = 0x0800; pub const PS_FST_FFLAG_DIRECT: c_int = 0x1000; pub const PS_FST_FFLAG_EXEC: c_int = 0x2000; pub const PS_FST_FFLAG_HASLOCK: c_int = 0x4000; // sys/mount.h /// File identifier. /// These are unique per filesystem on a single machine. /// /// Note that the offset of fid_data is 4 bytes, so care must be taken to avoid /// undefined behavior accessing unaligned fields within an embedded struct. pub const MAXFIDSZ: c_int = 16; /// Length of type name including null. pub const MFSNAMELEN: c_int = 16; cfg_if! { if #[cfg(any(freebsd10, freebsd11))] { /// Size of on/from name bufs. pub const MNAMELEN: c_int = 88; } else { /// Size of on/from name bufs. pub const MNAMELEN: c_int = 1024; } } /// Using journaled soft updates. pub const MNT_SUJ: u64 = 0x100000000; /// Mounted by automountd(8). pub const MNT_AUTOMOUNTED: u64 = 0x200000000; /// Filesys metadata untrusted. pub const MNT_UNTRUSTED: u64 = 0x800000000; /// Require TLS. pub const MNT_EXTLS: u64 = 0x4000000000; /// Require TLS with client cert. pub const MNT_EXTLSCERT: u64 = 0x8000000000; /// Require TLS with user cert. pub const MNT_EXTLSCERTUSER: u64 = 0x10000000000; /// Filesystem is stored locally. pub const MNT_LOCAL: u64 = 0x000001000; /// Quotas are enabled on fs. pub const MNT_QUOTA: u64 = 0x000002000; /// Identifies the root fs. pub const MNT_ROOTFS: u64 = 0x000004000; /// Mounted by a user. pub const MNT_USER: u64 = 0x000008000; /// Do not show entry in df. pub const MNT_IGNORE: u64 = 0x000800000; /// Filesystem is verified. pub const MNT_VERIFIED: u64 = 0x400000000; /// Do not cover a mount point. pub const MNT_NOCOVER: u64 = 0x001000000000; /// Only mount on empty dir. pub const MNT_EMPTYDIR: u64 = 0x002000000000; /// Recursively unmount uppers. pub const MNT_RECURSE: u64 = 0x100000000000; /// Unmount in async context. pub const MNT_DEFERRED: u64 = 0x200000000000; /// Get configured filesystems. pub const VFS_VFSCONF: c_int = 0; /// Generic filesystem information. pub const VFS_GENERIC: c_int = 0; /// int: highest defined filesystem type. pub const VFS_MAXTYPENUM: c_int = 1; /// struct: vfsconf for filesystem given as next argument. pub const VFS_CONF: c_int = 2; /// Synchronously wait for I/O to complete. pub const MNT_WAIT: c_int = 1; /// Start all I/O, but do not wait for it. pub const MNT_NOWAIT: c_int = 2; /// Push data not written by filesystem syncer. pub const MNT_LAZY: c_int = 3; /// Suspend file system after sync. pub const MNT_SUSPEND: c_int = 4; pub const MAXSECFLAVORS: c_int = 5; /// Statically compiled into kernel. pub const VFCF_STATIC: c_int = 0x00010000; /// May get data over the network. pub const VFCF_NETWORK: c_int = 0x00020000; /// Writes are not implemented. pub const VFCF_READONLY: c_int = 0x00040000; /// Data does not represent real files. pub const VFCF_SYNTHETIC: c_int = 0x00080000; /// Aliases some other mounted FS. pub const VFCF_LOOPBACK: c_int = 0x00100000; /// Stores file names as Unicode. pub const VFCF_UNICODE: c_int = 0x00200000; /// Can be mounted from within a jail. pub const VFCF_JAIL: c_int = 0x00400000; /// Supports delegated administration. pub const VFCF_DELEGADMIN: c_int = 0x00800000; /// Stop at Boundary: defer stop requests to kernel->user (AST) transition. pub const VFCF_SBDRY: c_int = 0x01000000; // time.h /// not on dst pub const DST_NONE: c_int = 0; /// USA style dst pub const DST_USA: c_int = 1; /// Australian style dst pub const DST_AUST: c_int = 2; /// Western European dst pub const DST_WET: c_int = 3; /// Middle European dst pub const DST_MET: c_int = 4; /// Eastern European dst pub const DST_EET: c_int = 5; /// Canada pub const DST_CAN: c_int = 6; pub const CPUCLOCK_WHICH_PID: c_int = 0; pub const CPUCLOCK_WHICH_TID: c_int = 1; pub const MFD_CLOEXEC: c_uint = 0x00000001; pub const MFD_ALLOW_SEALING: c_uint = 0x00000002; pub const MFD_HUGETLB: c_uint = 0x00000004; pub const MFD_HUGE_MASK: c_uint = 0xFC000000; pub const MFD_HUGE_64KB: c_uint = 16 << 26; pub const MFD_HUGE_512KB: c_uint = 19 << 26; pub const MFD_HUGE_1MB: c_uint = 20 << 26; pub const MFD_HUGE_2MB: c_uint = 21 << 26; pub const MFD_HUGE_8MB: c_uint = 23 << 26; pub const MFD_HUGE_16MB: c_uint = 24 << 26; pub const MFD_HUGE_32MB: c_uint = 25 << 26; pub const MFD_HUGE_256MB: c_uint = 28 << 26; pub const MFD_HUGE_512MB: c_uint = 29 << 26; pub const MFD_HUGE_1GB: c_uint = 30 << 26; pub const MFD_HUGE_2GB: c_uint = 31 << 26; pub const MFD_HUGE_16GB: c_uint = 34 << 26; pub const SHM_LARGEPAGE_ALLOC_DEFAULT: c_int = 0; pub const SHM_LARGEPAGE_ALLOC_NOWAIT: c_int = 1; pub const SHM_LARGEPAGE_ALLOC_HARD: c_int = 2; pub const SHM_RENAME_NOREPLACE: c_int = 1 << 0; pub const SHM_RENAME_EXCHANGE: c_int = 1 << 1; // sys/umtx.h pub const UMTX_OP_WAIT: c_int = 2; pub const UMTX_OP_WAKE: c_int = 3; pub const UMTX_OP_MUTEX_TRYLOCK: c_int = 4; pub const UMTX_OP_MUTEX_LOCK: c_int = 5; pub const UMTX_OP_MUTEX_UNLOCK: c_int = 6; pub const UMTX_OP_SET_CEILING: c_int = 7; pub const UMTX_OP_CV_WAIT: c_int = 8; pub const UMTX_OP_CV_SIGNAL: c_int = 9; pub const UMTX_OP_CV_BROADCAST: c_int = 10; pub const UMTX_OP_WAIT_UINT: c_int = 11; pub const UMTX_OP_RW_RDLOCK: c_int = 12; pub const UMTX_OP_RW_WRLOCK: c_int = 13; pub const UMTX_OP_RW_UNLOCK: c_int = 14; pub const UMTX_OP_WAIT_UINT_PRIVATE: c_int = 15; pub const UMTX_OP_WAKE_PRIVATE: c_int = 16; pub const UMTX_OP_MUTEX_WAIT: c_int = 17; pub const UMTX_OP_NWAKE_PRIVATE: c_int = 21; pub const UMTX_OP_MUTEX_WAKE2: c_int = 22; pub const UMTX_OP_SEM2_WAIT: c_int = 23; pub const UMTX_OP_SEM2_WAKE: c_int = 24; pub const UMTX_OP_SHM: c_int = 25; pub const UMTX_OP_ROBUST_LISTS: c_int = 26; pub const UMTX_ABSTIME: u32 = 1; pub const CPU_LEVEL_ROOT: c_int = 1; pub const CPU_LEVEL_CPUSET: c_int = 2; pub const CPU_LEVEL_WHICH: c_int = 3; pub const CPU_WHICH_TID: c_int = 1; pub const CPU_WHICH_PID: c_int = 2; pub const CPU_WHICH_CPUSET: c_int = 3; pub const CPU_WHICH_IRQ: c_int = 4; pub const CPU_WHICH_JAIL: c_int = 5; // net/route.h pub const RTF_LLDATA: c_int = 0x400; pub const RTF_FIXEDMTU: c_int = 0x80000; pub const RTM_VERSION: c_int = 5; pub const RTAX_MAX: c_int = 8; // sys/signal.h pub const SIGTHR: c_int = 32; pub const SIGLWP: c_int = SIGTHR; pub const SIGLIBRT: c_int = 33; // netinet/sctp.h pub const SCTP_FUTURE_ASSOC: c_int = 0; pub const SCTP_CURRENT_ASSOC: c_int = 1; pub const SCTP_ALL_ASSOC: c_int = 2; pub const SCTP_NO_NEXT_MSG: c_int = 0x0000; pub const SCTP_NEXT_MSG_AVAIL: c_int = 0x0001; pub const SCTP_NEXT_MSG_ISCOMPLETE: c_int = 0x0002; pub const SCTP_NEXT_MSG_IS_UNORDERED: c_int = 0x0004; pub const SCTP_NEXT_MSG_IS_NOTIFICATION: c_int = 0x0008; pub const SCTP_RECVV_NOINFO: c_int = 0; pub const SCTP_RECVV_RCVINFO: c_int = 1; pub const SCTP_RECVV_NXTINFO: c_int = 2; pub const SCTP_RECVV_RN: c_int = 3; pub const SCTP_SENDV_NOINFO: c_int = 0; pub const SCTP_SENDV_SNDINFO: c_int = 1; pub const SCTP_SENDV_PRINFO: c_int = 2; pub const SCTP_SENDV_AUTHINFO: c_int = 3; pub const SCTP_SENDV_SPA: c_int = 4; pub const SCTP_SEND_SNDINFO_VALID: c_int = 0x00000001; pub const SCTP_SEND_PRINFO_VALID: c_int = 0x00000002; pub const SCTP_SEND_AUTHINFO_VALID: c_int = 0x00000004; pub const SCTP_NOTIFICATION: c_int = 0x0010; pub const SCTP_COMPLETE: c_int = 0x0020; pub const SCTP_EOF: c_int = 0x0100; pub const SCTP_ABORT: c_int = 0x0200; pub const SCTP_UNORDERED: c_int = 0x0400; pub const SCTP_ADDR_OVER: c_int = 0x0800; pub const SCTP_SENDALL: c_int = 0x1000; pub const SCTP_EOR: c_int = 0x2000; pub const SCTP_SACK_IMMEDIATELY: c_int = 0x4000; pub const SCTP_PR_SCTP_NONE: c_int = 0x0000; pub const SCTP_PR_SCTP_TTL: c_int = 0x0001; pub const SCTP_PR_SCTP_PRIO: c_int = 0x0002; pub const SCTP_PR_SCTP_BUF: c_int = SCTP_PR_SCTP_PRIO; pub const SCTP_PR_SCTP_RTX: c_int = 0x0003; pub const SCTP_PR_SCTP_MAX: c_int = SCTP_PR_SCTP_RTX; pub const SCTP_PR_SCTP_ALL: c_int = 0x000f; pub const SCTP_INIT: c_int = 0x0001; pub const SCTP_SNDRCV: c_int = 0x0002; pub const SCTP_EXTRCV: c_int = 0x0003; pub const SCTP_SNDINFO: c_int = 0x0004; pub const SCTP_RCVINFO: c_int = 0x0005; pub const SCTP_NXTINFO: c_int = 0x0006; pub const SCTP_PRINFO: c_int = 0x0007; pub const SCTP_AUTHINFO: c_int = 0x0008; pub const SCTP_DSTADDRV4: c_int = 0x0009; pub const SCTP_DSTADDRV6: c_int = 0x000a; pub const SCTP_RTOINFO: c_int = 0x00000001; pub const SCTP_ASSOCINFO: c_int = 0x00000002; pub const SCTP_INITMSG: c_int = 0x00000003; pub const SCTP_NODELAY: c_int = 0x00000004; pub const SCTP_AUTOCLOSE: c_int = 0x00000005; pub const SCTP_SET_PEER_PRIMARY_ADDR: c_int = 0x00000006; pub const SCTP_PRIMARY_ADDR: c_int = 0x00000007; pub const SCTP_ADAPTATION_LAYER: c_int = 0x00000008; pub const SCTP_ADAPTION_LAYER: c_int = 0x00000008; pub const SCTP_DISABLE_FRAGMENTS: c_int = 0x00000009; pub const SCTP_PEER_ADDR_PARAMS: c_int = 0x0000000a; pub const SCTP_DEFAULT_SEND_PARAM: c_int = 0x0000000b; pub const SCTP_EVENTS: c_int = 0x0000000c; pub const SCTP_I_WANT_MAPPED_V4_ADDR: c_int = 0x0000000d; pub const SCTP_MAXSEG: c_int = 0x0000000e; pub const SCTP_DELAYED_SACK: c_int = 0x0000000f; pub const SCTP_FRAGMENT_INTERLEAVE: c_int = 0x00000010; pub const SCTP_PARTIAL_DELIVERY_POINT: c_int = 0x00000011; pub const SCTP_AUTH_CHUNK: c_int = 0x00000012; pub const SCTP_AUTH_KEY: c_int = 0x00000013; pub const SCTP_HMAC_IDENT: c_int = 0x00000014; pub const SCTP_AUTH_ACTIVE_KEY: c_int = 0x00000015; pub const SCTP_AUTH_DELETE_KEY: c_int = 0x00000016; pub const SCTP_USE_EXT_RCVINFO: c_int = 0x00000017; pub const SCTP_AUTO_ASCONF: c_int = 0x00000018; pub const SCTP_MAXBURST: c_int = 0x00000019; pub const SCTP_MAX_BURST: c_int = 0x00000019; pub const SCTP_CONTEXT: c_int = 0x0000001a; pub const SCTP_EXPLICIT_EOR: c_int = 0x00000001b; pub const SCTP_REUSE_PORT: c_int = 0x00000001c; pub const SCTP_AUTH_DEACTIVATE_KEY: c_int = 0x00000001d; pub const SCTP_EVENT: c_int = 0x0000001e; pub const SCTP_RECVRCVINFO: c_int = 0x0000001f; pub const SCTP_RECVNXTINFO: c_int = 0x00000020; pub const SCTP_DEFAULT_SNDINFO: c_int = 0x00000021; pub const SCTP_DEFAULT_PRINFO: c_int = 0x00000022; pub const SCTP_PEER_ADDR_THLDS: c_int = 0x00000023; pub const SCTP_REMOTE_UDP_ENCAPS_PORT: c_int = 0x00000024; pub const SCTP_ECN_SUPPORTED: c_int = 0x00000025; pub const SCTP_AUTH_SUPPORTED: c_int = 0x00000027; pub const SCTP_ASCONF_SUPPORTED: c_int = 0x00000028; pub const SCTP_RECONFIG_SUPPORTED: c_int = 0x00000029; pub const SCTP_NRSACK_SUPPORTED: c_int = 0x00000030; pub const SCTP_PKTDROP_SUPPORTED: c_int = 0x00000031; pub const SCTP_MAX_CWND: c_int = 0x00000032; pub const SCTP_STATUS: c_int = 0x00000100; pub const SCTP_GET_PEER_ADDR_INFO: c_int = 0x00000101; pub const SCTP_PEER_AUTH_CHUNKS: c_int = 0x00000102; pub const SCTP_LOCAL_AUTH_CHUNKS: c_int = 0x00000103; pub const SCTP_GET_ASSOC_NUMBER: c_int = 0x00000104; pub const SCTP_GET_ASSOC_ID_LIST: c_int = 0x00000105; pub const SCTP_TIMEOUTS: c_int = 0x00000106; pub const SCTP_PR_STREAM_STATUS: c_int = 0x00000107; pub const SCTP_PR_ASSOC_STATUS: c_int = 0x00000108; pub const SCTP_COMM_UP: c_int = 0x0001; pub const SCTP_COMM_LOST: c_int = 0x0002; pub const SCTP_RESTART: c_int = 0x0003; pub const SCTP_SHUTDOWN_COMP: c_int = 0x0004; pub const SCTP_CANT_STR_ASSOC: c_int = 0x0005; pub const SCTP_ASSOC_SUPPORTS_PR: c_int = 0x01; pub const SCTP_ASSOC_SUPPORTS_AUTH: c_int = 0x02; pub const SCTP_ASSOC_SUPPORTS_ASCONF: c_int = 0x03; pub const SCTP_ASSOC_SUPPORTS_MULTIBUF: c_int = 0x04; pub const SCTP_ASSOC_SUPPORTS_RE_CONFIG: c_int = 0x05; pub const SCTP_ASSOC_SUPPORTS_INTERLEAVING: c_int = 0x06; pub const SCTP_ASSOC_SUPPORTS_MAX: c_int = 0x06; pub const SCTP_ADDR_AVAILABLE: c_int = 0x0001; pub const SCTP_ADDR_UNREACHABLE: c_int = 0x0002; pub const SCTP_ADDR_REMOVED: c_int = 0x0003; pub const SCTP_ADDR_ADDED: c_int = 0x0004; pub const SCTP_ADDR_MADE_PRIM: c_int = 0x0005; pub const SCTP_ADDR_CONFIRMED: c_int = 0x0006; pub const SCTP_ACTIVE: c_int = 0x0001; pub const SCTP_INACTIVE: c_int = 0x0002; pub const SCTP_UNCONFIRMED: c_int = 0x0200; pub const SCTP_DATA_UNSENT: c_int = 0x0001; pub const SCTP_DATA_SENT: c_int = 0x0002; pub const SCTP_PARTIAL_DELIVERY_ABORTED: c_int = 0x0001; pub const SCTP_AUTH_NEW_KEY: c_int = 0x0001; pub const SCTP_AUTH_NEWKEY: c_int = SCTP_AUTH_NEW_KEY; pub const SCTP_AUTH_NO_AUTH: c_int = 0x0002; pub const SCTP_AUTH_FREE_KEY: c_int = 0x0003; pub const SCTP_STREAM_RESET_INCOMING_SSN: c_int = 0x0001; pub const SCTP_STREAM_RESET_OUTGOING_SSN: c_int = 0x0002; pub const SCTP_STREAM_RESET_DENIED: c_int = 0x0004; pub const SCTP_STREAM_RESET_FAILED: c_int = 0x0008; pub const SCTP_ASSOC_RESET_DENIED: c_int = 0x0004; pub const SCTP_ASSOC_RESET_FAILED: c_int = 0x0008; pub const SCTP_STREAM_CHANGE_DENIED: c_int = 0x0004; pub const SCTP_STREAM_CHANGE_FAILED: c_int = 0x0008; pub const KENV_DUMP_LOADER: c_int = 4; pub const KENV_DUMP_STATIC: c_int = 5; pub const RB_PAUSE: c_int = 0x100000; pub const RB_REROOT: c_int = 0x200000; pub const RB_POWERCYCLE: c_int = 0x400000; pub const RB_PROBE: c_int = 0x10000000; pub const RB_MULTIPLE: c_int = 0x20000000; // sys/time.h pub const CLOCK_BOOTTIME: crate::clockid_t = crate::CLOCK_UPTIME; pub const CLOCK_REALTIME_COARSE: crate::clockid_t = crate::CLOCK_REALTIME_FAST; pub const CLOCK_MONOTONIC_COARSE: crate::clockid_t = crate::CLOCK_MONOTONIC_FAST; // sys/timerfd.h pub const TFD_NONBLOCK: c_int = crate::O_NONBLOCK; pub const TFD_CLOEXEC: c_int = O_CLOEXEC; pub const TFD_TIMER_ABSTIME: c_int = 0x01; pub const TFD_TIMER_CANCEL_ON_SET: c_int = 0x02; // sys/unistd.h pub const CLOSE_RANGE_CLOEXEC: c_uint = 1 << 2; pub const KCMP_FILE: c_int = 100; pub const KCMP_FILEOBJ: c_int = 101; pub const KCMP_FILES: c_int = 102; pub const KCMP_SIGHAND: c_int = 103; pub const KCMP_VM: c_int = 104; pub const fn MAP_ALIGNED(a: c_int) -> c_int { a << 24 } const_fn! { {const} fn _ALIGN(p: usize) -> usize { (p + _ALIGNBYTES) & !_ALIGNBYTES } } f! { pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).offset(_ALIGN(mem::size_of::()) as isize) } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { _ALIGN(mem::size_of::()) as c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const crate::msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { return crate::CMSG_FIRSTHDR(mhdr); }; let next = cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize) + _ALIGN(mem::size_of::()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut cmsghdr } else { (cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr } } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (_ALIGN(mem::size_of::()) + _ALIGN(length as usize)) as c_uint } pub fn MALLOCX_ALIGN(lg: c_uint) -> c_int { ffsl(lg as c_long - 1) } pub {const} fn MALLOCX_TCACHE(tc: c_int) -> c_int { (tc + 2) << 8 as c_int } pub {const} fn MALLOCX_ARENA(a: c_int) -> c_int { (a + 1) << 20 as c_int } pub fn SOCKCREDSIZE(ngrps: usize) -> usize { let ngrps = if ngrps > 0 { ngrps - 1 } else { 0 }; mem::size_of::() + mem::size_of::() * ngrps } pub fn uname(buf: *mut crate::utsname) -> c_int { __xuname(256, buf as *mut c_void) } pub fn CPU_ZERO(cpuset: &mut cpuset_t) -> () { for slot in cpuset.__bits.iter_mut() { *slot = 0; } } pub fn CPU_FILL(cpuset: &mut cpuset_t) -> () { for slot in cpuset.__bits.iter_mut() { *slot = !0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpuset_t) -> () { let bitset_bits = 8 * mem::size_of::(); let (idx, offset) = (cpu / bitset_bits, cpu % bitset_bits); cpuset.__bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpuset_t) -> () { let bitset_bits = 8 * mem::size_of::(); let (idx, offset) = (cpu / bitset_bits, cpu % bitset_bits); cpuset.__bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpuset_t) -> bool { let bitset_bits = 8 * mem::size_of::(); let (idx, offset) = (cpu / bitset_bits, cpu % bitset_bits); 0 != cpuset.__bits[idx] & (1 << offset) } pub fn CPU_COUNT(cpuset: &cpuset_t) -> c_int { let mut s: u32 = 0; let cpuset_size = mem::size_of::(); let bitset_size = mem::size_of::(); for i in cpuset.__bits[..(cpuset_size / bitset_size)].iter() { s += i.count_ones(); } s as c_int } pub fn SOCKCRED2SIZE(ngrps: usize) -> usize { let ngrps = if ngrps > 0 { ngrps - 1 } else { 0 }; mem::size_of::() + mem::size_of::() * ngrps } pub fn PROT_MAX(x: c_int) -> c_int { x << 16 } pub fn PROT_MAX_EXTRACT(x: c_int) -> c_int { (x >> 16) & (crate::PROT_READ | crate::PROT_WRITE | crate::PROT_EXEC) } } safe_f! { pub {const} fn WIFSIGNALED(status: c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 && status != 0x13 } pub {const} fn INVALID_SINFO_FLAG(x: c_int) -> bool { (x) & 0xfffffff0 & !(SCTP_EOF | SCTP_ABORT | SCTP_UNORDERED | SCTP_ADDR_OVER | SCTP_SENDALL | SCTP_EOR | SCTP_SACK_IMMEDIATELY) != 0 } pub {const} fn PR_SCTP_POLICY(x: c_int) -> c_int { x & 0x0f } pub {const} fn PR_SCTP_ENABLED(x: c_int) -> bool { PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE && PR_SCTP_POLICY(x) != SCTP_PR_SCTP_ALL } pub {const} fn PR_SCTP_TTL_ENABLED(x: c_int) -> bool { PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL } pub {const} fn PR_SCTP_BUF_ENABLED(x: c_int) -> bool { PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF } pub {const} fn PR_SCTP_RTX_ENABLED(x: c_int) -> bool { PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX } pub {const} fn PR_SCTP_INVALID_POLICY(x: c_int) -> bool { PR_SCTP_POLICY(x) > SCTP_PR_SCTP_MAX } pub {const} fn PR_SCTP_VALID_POLICY(x: c_int) -> bool { PR_SCTP_POLICY(x) <= SCTP_PR_SCTP_MAX } } cfg_if! { if #[cfg(not(any(freebsd10, freebsd11)))] { extern "C" { pub fn fhlink(fhp: *mut fhandle_t, to: *const c_char) -> c_int; pub fn fhlinkat(fhp: *mut fhandle_t, tofd: c_int, to: *const c_char) -> c_int; pub fn fhreadlink(fhp: *mut fhandle_t, buf: *mut c_char, bufsize: size_t) -> c_int; pub fn getfhat(fd: c_int, path: *mut c_char, fhp: *mut fhandle, flag: c_int) -> c_int; } } } extern "C" { #[cfg_attr(doc, doc(alias = "__errno_location"))] #[cfg_attr(doc, doc(alias = "errno"))] pub fn __error() -> *mut c_int; pub fn aio_cancel(fd: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_error(aiocbp: *const aiocb) -> c_int; pub fn aio_fsync(op: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_read(aiocbp: *mut aiocb) -> c_int; pub fn aio_readv(aiocbp: *mut crate::aiocb) -> c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn aio_write(aiocbp: *mut aiocb) -> c_int; pub fn aio_writev(aiocbp: *mut crate::aiocb) -> c_int; pub fn copy_file_range( infd: c_int, inoffp: *mut off_t, outfd: c_int, outoffp: *mut off_t, len: size_t, flags: c_uint, ) -> ssize_t; pub fn devname_r( dev: crate::dev_t, mode: crate::mode_t, buf: *mut c_char, len: c_int, ) -> *mut c_char; pub fn extattr_delete_fd(fd: c_int, attrnamespace: c_int, attrname: *const c_char) -> c_int; pub fn extattr_delete_file( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, ) -> c_int; pub fn extattr_delete_link( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, ) -> c_int; pub fn extattr_get_fd( fd: c_int, attrnamespace: c_int, attrname: *const c_char, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_get_file( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_get_link( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_list_fd( fd: c_int, attrnamespace: c_int, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_list_file( path: *const c_char, attrnamespace: c_int, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_list_link( path: *const c_char, attrnamespace: c_int, data: *mut c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_set_fd( fd: c_int, attrnamespace: c_int, attrname: *const c_char, data: *const c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_set_file( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, data: *const c_void, nbytes: size_t, ) -> ssize_t; pub fn extattr_set_link( path: *const c_char, attrnamespace: c_int, attrname: *const c_char, data: *const c_void, nbytes: size_t, ) -> ssize_t; pub fn fspacectl( fd: c_int, cmd: c_int, rqsr: *const spacectl_range, flags: c_int, rmsr: *mut spacectl_range, ) -> c_int; pub fn jail(jail: *mut crate::jail) -> c_int; pub fn jail_attach(jid: c_int) -> c_int; pub fn jail_remove(jid: c_int) -> c_int; pub fn jail_get(iov: *mut crate::iovec, niov: c_uint, flags: c_int) -> c_int; pub fn jail_set(iov: *mut crate::iovec, niov: c_uint, flags: c_int) -> c_int; pub fn lio_listio( mode: c_int, aiocb_list: *const *mut aiocb, nitems: c_int, sevp: *mut sigevent, ) -> c_int; pub fn getutxuser(user: *const c_char) -> *mut utmpx; pub fn setutxdb(_type: c_int, file: *const c_char) -> c_int; pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, timeout: *mut crate::timespec) -> ssize_t; pub fn mq_getfd_np(mqd: crate::mqd_t) -> c_int; pub fn waitid( idtype: idtype_t, id: crate::id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int; pub fn ftok(pathname: *const c_char, proj_id: c_int) -> crate::key_t; pub fn shmget(key: crate::key_t, size: size_t, shmflg: c_int) -> c_int; pub fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void; pub fn shmdt(shmaddr: *const c_void) -> c_int; pub fn shmctl(shmid: c_int, cmd: c_int, buf: *mut crate::shmid_ds) -> c_int; pub fn semget(key: crate::key_t, nsems: c_int, semflg: c_int) -> c_int; pub fn semctl(semid: c_int, semnum: c_int, cmd: c_int, ...) -> c_int; pub fn semop(semid: c_int, sops: *mut sembuf, nsops: size_t) -> c_int; pub fn msgctl(msqid: c_int, cmd: c_int, buf: *mut crate::msqid_ds) -> c_int; pub fn msgget(key: crate::key_t, msgflg: c_int) -> c_int; pub fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: size_t, msgflg: c_int) -> c_int; pub fn cfmakesane(termios: *mut crate::termios); pub fn pdfork(fdp: *mut c_int, flags: c_int) -> crate::pid_t; pub fn pdgetpid(fd: c_int, pidp: *mut crate::pid_t) -> c_int; pub fn pdkill(fd: c_int, signum: c_int) -> c_int; pub fn rtprio_thread(function: c_int, lwpid: crate::lwpid_t, rtp: *mut super::rtprio) -> c_int; pub fn uuidgen(store: *mut uuid, count: c_int) -> c_int; pub fn thr_kill(id: c_long, sig: c_int) -> c_int; pub fn thr_kill2(pid: crate::pid_t, id: c_long, sig: c_int) -> c_int; pub fn thr_self(tid: *mut c_long) -> c_int; pub fn pthread_getthreadid_np() -> c_int; pub fn pthread_getaffinity_np( td: crate::pthread_t, cpusetsize: size_t, cpusetp: *mut cpuset_t, ) -> c_int; pub fn pthread_setaffinity_np( td: crate::pthread_t, cpusetsize: size_t, cpusetp: *const cpuset_t, ) -> c_int; // sched.h linux compatibility api pub fn sched_getaffinity( pid: crate::pid_t, cpusetsz: size_t, cpuset: *mut crate::cpuset_t, ) -> c_int; pub fn sched_setaffinity( pid: crate::pid_t, cpusetsz: size_t, cpuset: *const crate::cpuset_t, ) -> c_int; pub fn sched_getcpu() -> c_int; pub fn pthread_mutex_consistent(mutex: *mut crate::pthread_mutex_t) -> c_int; pub fn pthread_mutexattr_getrobust( attr: *mut crate::pthread_mutexattr_t, robust: *mut c_int, ) -> c_int; pub fn pthread_mutexattr_setrobust( attr: *mut crate::pthread_mutexattr_t, robust: c_int, ) -> c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int; #[cfg_attr(all(target_os = "freebsd", freebsd11), link_name = "statfs@FBSD_1.0")] pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; #[cfg_attr(all(target_os = "freebsd", freebsd11), link_name = "fstatfs@FBSD_1.0")] pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn dup3(src: c_int, dst: c_int, flags: c_int) -> c_int; pub fn __xuname(nmln: c_int, buf: *mut c_void) -> c_int; pub fn sendmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: size_t, flags: c_int, ) -> ssize_t; pub fn recvmmsg( sockfd: c_int, msgvec: *mut crate::mmsghdr, vlen: size_t, flags: c_int, timeout: *const crate::timespec, ) -> ssize_t; pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; pub fn fhopen(fhp: *const fhandle_t, flags: c_int) -> c_int; pub fn fhstat(fhp: *const fhandle, buf: *mut crate::stat) -> c_int; pub fn fhstatfs(fhp: *const fhandle_t, buf: *mut crate::statfs) -> c_int; pub fn getfh(path: *const c_char, fhp: *mut fhandle_t) -> c_int; pub fn lgetfh(path: *const c_char, fhp: *mut fhandle_t) -> c_int; pub fn getfsstat(buf: *mut crate::statfs, bufsize: c_long, mode: c_int) -> c_int; #[cfg_attr( all(target_os = "freebsd", freebsd11), link_name = "getmntinfo@FBSD_1.0" )] pub fn getmntinfo(mntbufp: *mut *mut crate::statfs, mode: c_int) -> c_int; pub fn mount( type_: *const c_char, dir: *const c_char, flags: c_int, data: *mut c_void, ) -> c_int; pub fn nmount(iov: *mut crate::iovec, niov: c_uint, flags: c_int) -> c_int; pub fn setproctitle(fmt: *const c_char, ...); pub fn rfork(flags: c_int) -> c_int; pub fn cpuset_getaffinity( level: cpulevel_t, which: cpuwhich_t, id: crate::id_t, setsize: size_t, mask: *mut cpuset_t, ) -> c_int; pub fn cpuset_setaffinity( level: cpulevel_t, which: cpuwhich_t, id: crate::id_t, setsize: size_t, mask: *const cpuset_t, ) -> c_int; pub fn cpuset(setid: *mut crate::cpusetid_t) -> c_int; pub fn cpuset_getid( level: cpulevel_t, which: cpuwhich_t, id: crate::id_t, setid: *mut crate::cpusetid_t, ) -> c_int; pub fn cpuset_setid(which: cpuwhich_t, id: crate::id_t, setid: crate::cpusetid_t) -> c_int; pub fn cap_enter() -> c_int; pub fn cap_getmode(modep: *mut c_uint) -> c_int; pub fn cap_fcntls_get(fd: c_int, fcntlrightsp: *mut u32) -> c_int; pub fn cap_fcntls_limit(fd: c_int, fcntlrights: u32) -> c_int; pub fn cap_ioctls_get(fd: c_int, cmds: *mut u_long, maxcmds: usize) -> isize; pub fn cap_ioctls_limit(fd: c_int, cmds: *const u_long, ncmds: usize) -> c_int; pub fn __cap_rights_init(version: c_int, rights: *mut cap_rights_t, ...) -> *mut cap_rights_t; pub fn __cap_rights_get(version: c_int, fd: c_int, rightsp: *mut cap_rights_t) -> c_int; pub fn __cap_rights_set(rights: *mut cap_rights_t, ...) -> *mut cap_rights_t; pub fn __cap_rights_clear(rights: *mut cap_rights_t, ...) -> *mut cap_rights_t; pub fn __cap_rights_is_set(rights: *const cap_rights_t, ...) -> bool; pub fn cap_rights_is_valid(rights: *const cap_rights_t) -> bool; pub fn cap_rights_limit(fd: c_int, rights: *const cap_rights_t) -> c_int; pub fn cap_rights_merge(dst: *mut cap_rights_t, src: *const cap_rights_t) -> *mut cap_rights_t; pub fn cap_rights_remove(dst: *mut cap_rights_t, src: *const cap_rights_t) -> *mut cap_rights_t; pub fn cap_rights_contains(big: *const cap_rights_t, little: *const cap_rights_t) -> bool; pub fn cap_sandboxed() -> bool; pub fn reallocarray(ptr: *mut c_void, nmemb: size_t, size: size_t) -> *mut c_void; pub fn ffs(value: c_int) -> c_int; pub fn ffsl(value: c_long) -> c_int; pub fn ffsll(value: c_longlong) -> c_int; pub fn fls(value: c_int) -> c_int; pub fn flsl(value: c_long) -> c_int; pub fn flsll(value: c_longlong) -> c_int; pub fn malloc_stats_print( write_cb: unsafe extern "C" fn(*mut c_void, *const c_char), cbopaque: *mut c_void, opt: *const c_char, ); pub fn mallctl( name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; pub fn mallctlnametomib(name: *const c_char, mibp: *mut size_t, miplen: *mut size_t) -> c_int; pub fn mallctlbymib( mib: *const size_t, mible: size_t, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; pub fn mallocx(size: size_t, flags: c_int) -> *mut c_void; pub fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; pub fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; pub fn sallocx(ptr: *const c_void, flags: c_int) -> size_t; pub fn dallocx(ptr: *mut c_void, flags: c_int); pub fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); pub fn nallocx(size: size_t, flags: c_int) -> size_t; pub fn procctl( idtype: crate::idtype_t, id: crate::id_t, cmd: c_int, data: *mut c_void, ) -> c_int; pub fn getpagesize() -> c_int; pub fn getpagesizes(pagesize: *mut size_t, nelem: c_int) -> c_int; pub fn clock_getcpuclockid2(arg1: crate::id_t, arg2: c_int, arg3: *mut clockid_t) -> c_int; pub fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char; pub fn shm_create_largepage( path: *const c_char, flags: c_int, psind: c_int, alloc_policy: c_int, mode: crate::mode_t, ) -> c_int; pub fn shm_rename(path_from: *const c_char, path_to: *const c_char, flags: c_int) -> c_int; pub fn memfd_create(name: *const c_char, flags: c_uint) -> c_int; pub fn setaudit(auditinfo: *const auditinfo_t) -> c_int; pub fn eventfd(init: c_uint, flags: c_int) -> c_int; pub fn eventfd_read(fd: c_int, value: *mut eventfd_t) -> c_int; pub fn eventfd_write(fd: c_int, value: eventfd_t) -> c_int; pub fn fdatasync(fd: c_int) -> c_int; pub fn elf_aux_info(aux: c_int, buf: *mut c_void, buflen: c_int) -> c_int; pub fn setproctitle_fast(fmt: *const c_char, ...); pub fn timingsafe_bcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int; pub fn timingsafe_memcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int; pub fn _umtx_op( obj: *mut c_void, op: c_int, val: c_ulong, uaddr: *mut c_void, uaddr2: *mut c_void, ) -> c_int; pub fn sctp_peeloff(s: c_int, id: crate::sctp_assoc_t) -> c_int; pub fn sctp_bindx(s: c_int, addrs: *mut crate::sockaddr, num: c_int, tpe: c_int) -> c_int; pub fn sctp_connectx( s: c_int, addrs: *const crate::sockaddr, addrcnt: c_int, id: *mut crate::sctp_assoc_t, ) -> c_int; pub fn sctp_getaddrlen(family: crate::sa_family_t) -> c_int; pub fn sctp_getpaddrs( s: c_int, asocid: crate::sctp_assoc_t, addrs: *mut *mut crate::sockaddr, ) -> c_int; pub fn sctp_freepaddrs(addrs: *mut crate::sockaddr); pub fn sctp_getladdrs( s: c_int, asocid: crate::sctp_assoc_t, addrs: *mut *mut crate::sockaddr, ) -> c_int; pub fn sctp_freeladdrs(addrs: *mut crate::sockaddr); pub fn sctp_opt_info( s: c_int, id: crate::sctp_assoc_t, opt: c_int, arg: *mut c_void, size: *mut crate::socklen_t, ) -> c_int; pub fn sctp_sendv( sd: c_int, iov: *const crate::iovec, iovcnt: c_int, addrs: *mut crate::sockaddr, addrcnt: c_int, info: *mut c_void, infolen: crate::socklen_t, infotype: c_uint, flags: c_int, ) -> ssize_t; pub fn sctp_recvv( sd: c_int, iov: *const crate::iovec, iovcnt: c_int, from: *mut crate::sockaddr, fromlen: *mut crate::socklen_t, info: *mut c_void, infolen: *mut crate::socklen_t, infotype: *mut c_uint, flags: *mut c_int, ) -> ssize_t; pub fn timerfd_create(clockid: c_int, flags: c_int) -> c_int; pub fn timerfd_gettime(fd: c_int, curr_value: *mut itimerspec) -> c_int; pub fn timerfd_settime( fd: c_int, flags: c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> c_int; pub fn closefrom(lowfd: c_int); pub fn close_range(lowfd: c_uint, highfd: c_uint, flags: c_int) -> c_int; pub fn execvpe( file: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> c_int; pub fn kcmp( pid1: crate::pid_t, pid2: crate::pid_t, type_: c_int, idx1: c_ulong, idx2: c_ulong, ) -> c_int; } #[link(name = "memstat")] extern "C" { pub fn memstat_strerror(error: c_int) -> *const c_char; pub fn memstat_mtl_alloc() -> *mut memory_type_list; pub fn memstat_mtl_first(list: *mut memory_type_list) -> *mut memory_type; pub fn memstat_mtl_next(mtp: *mut memory_type) -> *mut memory_type; pub fn memstat_mtl_find( list: *mut memory_type_list, allocator: c_int, name: *const c_char, ) -> *mut memory_type; pub fn memstat_mtl_free(list: *mut memory_type_list); pub fn memstat_mtl_geterror(list: *mut memory_type_list) -> c_int; pub fn memstat_get_name(mtp: *const memory_type) -> *const c_char; } #[link(name = "kvm")] extern "C" { pub fn kvm_dpcpu_setcpu(kd: *mut crate::kvm_t, cpu: c_uint) -> c_int; pub fn kvm_getargv( kd: *mut crate::kvm_t, p: *const kinfo_proc, nchr: c_int, ) -> *mut *mut c_char; pub fn kvm_getcptime(kd: *mut crate::kvm_t, cp_time: *mut c_long) -> c_int; pub fn kvm_getenvv( kd: *mut crate::kvm_t, p: *const kinfo_proc, nchr: c_int, ) -> *mut *mut c_char; pub fn kvm_geterr(kd: *mut crate::kvm_t) -> *mut c_char; pub fn kvm_getmaxcpu(kd: *mut crate::kvm_t) -> c_int; pub fn kvm_getncpus(kd: *mut crate::kvm_t) -> c_int; pub fn kvm_getpcpu(kd: *mut crate::kvm_t, cpu: c_int) -> *mut c_void; pub fn kvm_counter_u64_fetch(kd: *mut crate::kvm_t, base: c_ulong) -> u64; pub fn kvm_getswapinfo( kd: *mut crate::kvm_t, info: *mut kvm_swap, maxswap: c_int, flags: c_int, ) -> c_int; pub fn kvm_native(kd: *mut crate::kvm_t) -> c_int; pub fn kvm_nlist(kd: *mut crate::kvm_t, nl: *mut nlist) -> c_int; pub fn kvm_nlist2(kd: *mut crate::kvm_t, nl: *mut kvm_nlist) -> c_int; pub fn kvm_read_zpcpu( kd: *mut crate::kvm_t, base: c_ulong, buf: *mut c_void, size: size_t, cpu: c_int, ) -> ssize_t; pub fn kvm_read2( kd: *mut crate::kvm_t, addr: kvaddr_t, buf: *mut c_void, nbytes: size_t, ) -> ssize_t; } #[link(name = "util")] extern "C" { pub fn extattr_namespace_to_string(attrnamespace: c_int, string: *mut *mut c_char) -> c_int; pub fn extattr_string_to_namespace(string: *const c_char, attrnamespace: *mut c_int) -> c_int; pub fn realhostname(host: *mut c_char, hsize: size_t, ip: *const crate::in_addr) -> c_int; pub fn realhostname_sa( host: *mut c_char, hsize: size_t, addr: *mut crate::sockaddr, addrlen: c_int, ) -> c_int; pub fn kld_isloaded(name: *const c_char) -> c_int; pub fn kld_load(name: *const c_char) -> c_int; pub fn kinfo_getvmmap(pid: crate::pid_t, cntp: *mut c_int) -> *mut kinfo_vmentry; pub fn hexdump(ptr: *const c_void, length: c_int, hdr: *const c_char, flags: c_int); pub fn humanize_number( buf: *mut c_char, len: size_t, number: i64, suffix: *const c_char, scale: c_int, flags: c_int, ) -> c_int; pub fn flopen(path: *const c_char, flags: c_int, ...) -> c_int; pub fn flopenat(fd: c_int, path: *const c_char, flags: c_int, ...) -> c_int; pub fn getlocalbase() -> *const c_char; pub fn pidfile_open( path: *const c_char, mode: crate::mode_t, pidptr: *mut crate::pid_t, ) -> *mut crate::pidfh; pub fn pidfile_write(path: *mut crate::pidfh) -> c_int; pub fn pidfile_close(path: *mut crate::pidfh) -> c_int; pub fn pidfile_remove(path: *mut crate::pidfh) -> c_int; pub fn pidfile_fileno(path: *const crate::pidfh) -> c_int; // FIXME(freebsd): pidfile_signal in due time (both manpage present and updated image snapshot) } #[link(name = "procstat")] extern "C" { pub fn procstat_open_sysctl() -> *mut procstat; pub fn procstat_getfiles( procstat: *mut procstat, kp: *mut kinfo_proc, mmapped: c_int, ) -> *mut filestat_list; pub fn procstat_freefiles(procstat: *mut procstat, head: *mut filestat_list); pub fn procstat_getprocs( procstat: *mut procstat, what: c_int, arg: c_int, count: *mut c_uint, ) -> *mut kinfo_proc; pub fn procstat_freeprocs(procstat: *mut procstat, p: *mut kinfo_proc); pub fn procstat_getvmmap( procstat: *mut procstat, kp: *mut kinfo_proc, count: *mut c_uint, ) -> *mut kinfo_vmentry; pub fn procstat_freevmmap(procstat: *mut procstat, vmmap: *mut kinfo_vmentry); pub fn procstat_close(procstat: *mut procstat); pub fn procstat_freeargv(procstat: *mut procstat); pub fn procstat_freeenvv(procstat: *mut procstat); pub fn procstat_freegroups(procstat: *mut procstat, groups: *mut crate::gid_t); pub fn procstat_freeptlwpinfo(procstat: *mut procstat, pl: *mut ptrace_lwpinfo); pub fn procstat_getargv( procstat: *mut procstat, kp: *mut kinfo_proc, nchr: size_t, ) -> *mut *mut c_char; pub fn procstat_getenvv( procstat: *mut procstat, kp: *mut kinfo_proc, nchr: size_t, ) -> *mut *mut c_char; pub fn procstat_getgroups( procstat: *mut procstat, kp: *mut kinfo_proc, count: *mut c_uint, ) -> *mut crate::gid_t; pub fn procstat_getosrel( procstat: *mut procstat, kp: *mut kinfo_proc, osrelp: *mut c_int, ) -> c_int; pub fn procstat_getpathname( procstat: *mut procstat, kp: *mut kinfo_proc, pathname: *mut c_char, maxlen: size_t, ) -> c_int; pub fn procstat_getrlimit( procstat: *mut procstat, kp: *mut kinfo_proc, which: c_int, rlimit: *mut crate::rlimit, ) -> c_int; pub fn procstat_getumask( procstat: *mut procstat, kp: *mut kinfo_proc, maskp: *mut c_ushort, ) -> c_int; pub fn procstat_open_core(filename: *const c_char) -> *mut procstat; pub fn procstat_open_kvm(nlistf: *const c_char, memf: *const c_char) -> *mut procstat; pub fn procstat_get_socket_info( proc_: *mut procstat, fst: *mut filestat, sock: *mut sockstat, errbuf: *mut c_char, ) -> c_int; pub fn procstat_get_vnode_info( proc_: *mut procstat, fst: *mut filestat, vn: *mut vnstat, errbuf: *mut c_char, ) -> c_int; pub fn procstat_get_pts_info( proc_: *mut procstat, fst: *mut filestat, pts: *mut ptsstat, errbuf: *mut c_char, ) -> c_int; pub fn procstat_get_shm_info( proc_: *mut procstat, fst: *mut filestat, shm: *mut shmstat, errbuf: *mut c_char, ) -> c_int; } #[link(name = "rt")] extern "C" { pub fn timer_create(clock_id: clockid_t, evp: *mut sigevent, timerid: *mut timer_t) -> c_int; pub fn timer_delete(timerid: timer_t) -> c_int; pub fn timer_getoverrun(timerid: timer_t) -> c_int; pub fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> c_int; pub fn timer_settime( timerid: timer_t, flags: c_int, value: *const itimerspec, ovalue: *mut itimerspec, ) -> c_int; } #[link(name = "devstat")] extern "C" { pub fn devstat_getnumdevs(kd: *mut crate::kvm_t) -> c_int; pub fn devstat_getgeneration(kd: *mut crate::kvm_t) -> c_long; pub fn devstat_getversion(kd: *mut crate::kvm_t) -> c_int; pub fn devstat_checkversion(kd: *mut crate::kvm_t) -> c_int; pub fn devstat_selectdevs( dev_select: *mut *mut device_selection, num_selected: *mut c_int, num_selections: *mut c_int, select_generation: *mut c_long, current_generation: c_long, devices: *mut devstat, numdevs: c_int, matches: *mut devstat_match, num_matches: c_int, dev_selections: *mut *mut c_char, num_dev_selections: c_int, select_mode: devstat_select_mode, maxshowdevs: c_int, perf_select: c_int, ) -> c_int; pub fn devstat_buildmatch( match_str: *mut c_char, matches: *mut *mut devstat_match, num_matches: *mut c_int, ) -> c_int; } cfg_if! { if #[cfg(freebsd15)] { mod freebsd15; pub use self::freebsd15::*; } else if #[cfg(freebsd14)] { mod freebsd14; pub use self::freebsd14::*; } else if #[cfg(freebsd13)] { mod freebsd13; pub use self::freebsd13::*; } else if #[cfg(freebsd12)] { mod freebsd12; pub use self::freebsd12::*; } else if #[cfg(any(freebsd10, freebsd11))] { mod freebsd11; pub use self::freebsd11::*; } else { // Unknown freebsd version } } cfg_if! { if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "powerpc64")] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/freebsdlike/freebsd/x86_64/0000775000175000017500000000000015105742312020466 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs0000644000175000017500000003536315105742312021623 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = i32; pub type wchar_t = i32; pub type time_t = i64; pub type suseconds_t = i64; pub type register_t = i64; s! { pub struct reg32 { pub r_fs: u32, pub r_es: u32, pub r_ds: u32, pub r_edi: u32, pub r_esi: u32, pub r_ebp: u32, pub r_isp: u32, pub r_ebx: u32, pub r_edx: u32, pub r_ecx: u32, pub r_eax: u32, pub r_trapno: u32, pub r_err: u32, pub r_eip: u32, pub r_cs: u32, pub r_eflags: u32, pub r_esp: u32, pub r_ss: u32, pub r_gs: u32, } pub struct reg { pub r_r15: i64, pub r_r14: i64, pub r_r13: i64, pub r_r12: i64, pub r_r11: i64, pub r_r10: i64, pub r_r9: i64, pub r_r8: i64, pub r_rdi: i64, pub r_rsi: i64, pub r_rbp: i64, pub r_rbx: i64, pub r_rdx: i64, pub r_rcx: i64, pub r_rax: i64, pub r_trapno: u32, pub r_fs: u16, pub r_gs: u16, pub r_err: u32, pub r_es: u16, pub r_ds: u16, pub r_rip: i64, pub r_cs: i64, pub r_rflags: i64, pub r_rsp: i64, pub r_ss: i64, } } s_no_extra_traits! { pub struct fpreg32 { pub fpr_env: [u32; 7], pub fpr_acc: [[u8; 10]; 8], pub fpr_ex_sw: u32, pub fpr_pad: [u8; 64], } pub struct fpreg { pub fpr_env: [u64; 4], pub fpr_acc: [[u8; 16]; 8], pub fpr_xacc: [[u8; 16]; 16], pub fpr_spare: [u64; 12], } pub struct xmmreg { pub xmm_env: [u32; 8], pub xmm_acc: [[u8; 16]; 8], pub xmm_reg: [[u8; 16]; 8], pub xmm_pad: [u8; 224], } pub union __c_anonymous_elf64_auxv_union { pub a_val: c_long, pub a_ptr: *mut c_void, pub a_fcn: extern "C" fn(), } pub struct Elf64_Auxinfo { pub a_type: c_long, pub a_un: __c_anonymous_elf64_auxv_union, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4], } #[repr(align(16))] pub struct mcontext_t { pub mc_onstack: register_t, pub mc_rdi: register_t, pub mc_rsi: register_t, pub mc_rdx: register_t, pub mc_rcx: register_t, pub mc_r8: register_t, pub mc_r9: register_t, pub mc_rax: register_t, pub mc_rbx: register_t, pub mc_rbp: register_t, pub mc_r10: register_t, pub mc_r11: register_t, pub mc_r12: register_t, pub mc_r13: register_t, pub mc_r14: register_t, pub mc_r15: register_t, pub mc_trapno: u32, pub mc_fs: u16, pub mc_gs: u16, pub mc_addr: register_t, pub mc_flags: u32, pub mc_es: u16, pub mc_ds: u16, pub mc_err: register_t, pub mc_rip: register_t, pub mc_cs: register_t, pub mc_rflags: register_t, pub mc_rsp: register_t, pub mc_ss: register_t, pub mc_len: c_long, pub mc_fpformat: c_long, pub mc_ownedfp: c_long, pub mc_fpstate: [c_long; 64], pub mc_fsbase: register_t, pub mc_gsbase: register_t, pub mc_xfpustate: register_t, pub mc_xfpustate_len: register_t, pub mc_spare: [c_long; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for fpreg32 { fn eq(&self, other: &fpreg32) -> bool { self.fpr_env == other.fpr_env && self.fpr_acc == other.fpr_acc && self.fpr_ex_sw == other.fpr_ex_sw && self .fpr_pad .iter() .zip(other.fpr_pad.iter()) .all(|(a, b)| a == b) } } impl Eq for fpreg32 {} impl fmt::Debug for fpreg32 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fpreg32") .field("fpr_env", &&self.fpr_env[..]) .field("fpr_acc", &self.fpr_acc) .field("fpr_ex_sw", &self.fpr_ex_sw) .field("fpr_pad", &&self.fpr_pad[..]) .finish() } } impl hash::Hash for fpreg32 { fn hash(&self, state: &mut H) { self.fpr_env.hash(state); self.fpr_acc.hash(state); self.fpr_ex_sw.hash(state); self.fpr_pad.hash(state); } } impl PartialEq for fpreg { fn eq(&self, other: &fpreg) -> bool { self.fpr_env == other.fpr_env && self.fpr_acc == other.fpr_acc && self.fpr_xacc == other.fpr_xacc && self.fpr_spare == other.fpr_spare } } impl Eq for fpreg {} impl fmt::Debug for fpreg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fpreg") .field("fpr_env", &self.fpr_env) .field("fpr_acc", &self.fpr_acc) .field("fpr_xacc", &self.fpr_xacc) .field("fpr_spare", &self.fpr_spare) .finish() } } impl hash::Hash for fpreg { fn hash(&self, state: &mut H) { self.fpr_env.hash(state); self.fpr_acc.hash(state); self.fpr_xacc.hash(state); self.fpr_spare.hash(state); } } impl PartialEq for xmmreg { fn eq(&self, other: &xmmreg) -> bool { self.xmm_env == other.xmm_env && self.xmm_acc == other.xmm_acc && self.xmm_reg == other.xmm_reg && self .xmm_pad .iter() .zip(other.xmm_pad.iter()) .all(|(a, b)| a == b) } } impl Eq for xmmreg {} impl fmt::Debug for xmmreg { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("xmmreg") .field("xmm_env", &self.xmm_env) .field("xmm_acc", &self.xmm_acc) .field("xmm_reg", &self.xmm_reg) .field("xmm_pad", &&self.xmm_pad[..]) .finish() } } impl hash::Hash for xmmreg { fn hash(&self, state: &mut H) { self.xmm_env.hash(state); self.xmm_acc.hash(state); self.xmm_reg.hash(state); self.xmm_pad.hash(state); } } // FIXME(msrv): suggested method was added in 1.85 #[allow(unpredictable_function_pointer_comparisons)] impl PartialEq for __c_anonymous_elf64_auxv_union { fn eq(&self, other: &__c_anonymous_elf64_auxv_union) -> bool { unsafe { self.a_val == other.a_val || self.a_ptr == other.a_ptr || self.a_fcn == other.a_fcn } } } impl Eq for __c_anonymous_elf64_auxv_union {} impl PartialEq for Elf64_Auxinfo { fn eq(&self, other: &Elf64_Auxinfo) -> bool { self.a_type == other.a_type && self.a_un == other.a_un } } impl Eq for Elf64_Auxinfo {} impl fmt::Debug for Elf64_Auxinfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Elf64_Auxinfo") .field("a_type", &self.a_type) .field("a_un", &self.a_un) .finish() } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_onstack == other.mc_onstack && self.mc_rdi == other.mc_rdi && self.mc_rsi == other.mc_rsi && self.mc_rdx == other.mc_rdx && self.mc_rcx == other.mc_rcx && self.mc_r8 == other.mc_r8 && self.mc_r9 == other.mc_r9 && self.mc_rax == other.mc_rax && self.mc_rbx == other.mc_rbx && self.mc_rbp == other.mc_rbp && self.mc_r10 == other.mc_r10 && self.mc_r11 == other.mc_r11 && self.mc_r12 == other.mc_r12 && self.mc_r13 == other.mc_r13 && self.mc_r14 == other.mc_r14 && self.mc_r15 == other.mc_r15 && self.mc_trapno == other.mc_trapno && self.mc_fs == other.mc_fs && self.mc_gs == other.mc_gs && self.mc_addr == other.mc_addr && self.mc_flags == other.mc_flags && self.mc_es == other.mc_es && self.mc_ds == other.mc_ds && self.mc_err == other.mc_err && self.mc_rip == other.mc_rip && self.mc_cs == other.mc_cs && self.mc_rflags == other.mc_rflags && self.mc_rsp == other.mc_rsp && self.mc_ss == other.mc_ss && self.mc_len == other.mc_len && self.mc_fpformat == other.mc_fpformat && self.mc_ownedfp == other.mc_ownedfp && self .mc_fpstate .iter() .zip(other.mc_fpstate.iter()) .all(|(a, b)| a == b) && self.mc_fsbase == other.mc_fsbase && self.mc_gsbase == other.mc_gsbase && self.mc_xfpustate == other.mc_xfpustate && self.mc_xfpustate_len == other.mc_xfpustate_len && self.mc_spare == other.mc_spare } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("mc_onstack", &self.mc_onstack) .field("mc_rdi", &self.mc_rdi) .field("mc_rsi", &self.mc_rsi) .field("mc_rdx", &self.mc_rdx) .field("mc_rcx", &self.mc_rcx) .field("mc_r8", &self.mc_r8) .field("mc_r9", &self.mc_r9) .field("mc_rax", &self.mc_rax) .field("mc_rbx", &self.mc_rbx) .field("mc_rbp", &self.mc_rbp) .field("mc_r10", &self.mc_r10) .field("mc_r11", &self.mc_r11) .field("mc_r12", &self.mc_r12) .field("mc_r13", &self.mc_r13) .field("mc_r14", &self.mc_r14) .field("mc_r15", &self.mc_r15) .field("mc_trapno", &self.mc_trapno) .field("mc_fs", &self.mc_fs) .field("mc_gs", &self.mc_gs) .field("mc_addr", &self.mc_addr) .field("mc_flags", &self.mc_flags) .field("mc_es", &self.mc_es) .field("mc_ds", &self.mc_ds) .field("mc_err", &self.mc_err) .field("mc_rip", &self.mc_rip) .field("mc_cs", &self.mc_cs) .field("mc_rflags", &self.mc_rflags) .field("mc_rsp", &self.mc_rsp) .field("mc_ss", &self.mc_ss) .field("mc_len", &self.mc_len) .field("mc_fpformat", &self.mc_fpformat) .field("mc_ownedfp", &self.mc_ownedfp) // FIXME(debug): .field("mc_fpstate", &self.mc_fpstate) .field("mc_fsbase", &self.mc_fsbase) .field("mc_gsbase", &self.mc_gsbase) .field("mc_xfpustate", &self.mc_xfpustate) .field("mc_xfpustate_len", &self.mc_xfpustate_len) .field("mc_spare", &self.mc_spare) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_onstack.hash(state); self.mc_rdi.hash(state); self.mc_rsi.hash(state); self.mc_rdx.hash(state); self.mc_rcx.hash(state); self.mc_r8.hash(state); self.mc_r9.hash(state); self.mc_rax.hash(state); self.mc_rbx.hash(state); self.mc_rbp.hash(state); self.mc_r10.hash(state); self.mc_r11.hash(state); self.mc_r12.hash(state); self.mc_r13.hash(state); self.mc_r14.hash(state); self.mc_r15.hash(state); self.mc_trapno.hash(state); self.mc_fs.hash(state); self.mc_gs.hash(state); self.mc_addr.hash(state); self.mc_flags.hash(state); self.mc_es.hash(state); self.mc_ds.hash(state); self.mc_err.hash(state); self.mc_rip.hash(state); self.mc_cs.hash(state); self.mc_rflags.hash(state); self.mc_rsp.hash(state); self.mc_ss.hash(state); self.mc_len.hash(state); self.mc_fpformat.hash(state); self.mc_ownedfp.hash(state); self.mc_fpstate.hash(state); self.mc_fsbase.hash(state); self.mc_gsbase.hash(state); self.mc_xfpustate.hash(state); self.mc_xfpustate_len.hash(state); self.mc_spare.hash(state); } } } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const BIOCSRTIMEOUT: c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4010426e; pub const MAP_32BIT: c_int = 0x00080000; pub const MINSIGSTKSZ: size_t = 2048; // 512 * 4 pub const _MC_HASSEGS: u32 = 0x1; pub const _MC_HASBASES: u32 = 0x2; pub const _MC_HASFPXSTATE: u32 = 0x4; pub const _MC_FLAG_MASK: u32 = _MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE; pub const _MC_FPFMT_NODEV: c_long = 0x10000; pub const _MC_FPFMT_XMM: c_long = 0x10002; pub const _MC_FPOWNED_NONE: c_long = 0x20000; pub const _MC_FPOWNED_FPU: c_long = 0x20001; pub const _MC_FPOWNED_PCB: c_long = 0x20002; pub const KINFO_FILE_SIZE: c_int = 1392; pub const TIOCTIMESTAMP: c_ulong = 0x40107459; libc/src/unix/bsd/freebsdlike/freebsd/arm.rs0000644000175000017500000000376715105742312020670 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = u32; pub type wchar_t = u32; pub type time_t = i64; pub type suseconds_t = i32; pub type register_t = i32; pub type __greg_t = c_uint; pub type __gregset_t = [crate::__greg_t; 17]; s_no_extra_traits! { pub struct mcontext_t { pub __gregs: crate::__gregset_t, pub mc_vfp_size: usize, pub mc_vfp_ptr: *mut c_void, pub mc_spare: [c_uint; 33], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.__gregs == other.__gregs && self.mc_vfp_size == other.mc_vfp_size && self.mc_vfp_ptr == other.mc_vfp_ptr && self .mc_spare .iter() .zip(other.mc_spare.iter()) .all(|(a, b)| a == b) } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("__gregs", &self.__gregs) .field("mc_vfp_size", &self.mc_vfp_size) .field("mc_vfp_ptr", &self.mc_vfp_ptr) .field("mc_spare", &self.mc_spare) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.__gregs.hash(state); self.mc_vfp_size.hash(state); self.mc_vfp_ptr.hash(state); self.mc_spare.hash(state); } } } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const BIOCSRTIMEOUT: c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4010426e; pub const MAP_32BIT: c_int = 0x00080000; pub const MINSIGSTKSZ: size_t = 4096; // 1024 * 4 pub const TIOCTIMESTAMP: c_ulong = 0x40107459; libc/src/unix/bsd/freebsdlike/freebsd/freebsd15/0000775000175000017500000000000015105742312021310 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs0000644000175000017500000004716415105742312022447 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; // APIs in FreeBSD 15 that have changed since 11. pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = u64; pub type shmatt_t = c_uint; pub type kpaddr_t = u64; pub type kssize_t = i64; pub type domainset_t = __c_anonymous_domainset; s! { pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, } pub struct kevent { pub ident: crate::uintptr_t, pub filter: c_short, pub flags: c_ushort, pub fflags: c_uint, pub data: i64, pub udata: *mut c_void, pub ext: [u64; 4], } pub struct kvm_page { pub kp_version: crate::u_int, pub kp_paddr: crate::kpaddr_t, pub kp_kmap_vaddr: crate::kvaddr_t, pub kp_dmap_vaddr: crate::kvaddr_t, pub kp_prot: crate::vm_prot_t, pub kp_offset: off_t, pub kp_len: size_t, } pub struct __c_anonymous_domainset { #[cfg(target_pointer_width = "64")] _priv: [c_ulong; 4], #[cfg(target_pointer_width = "32")] _priv: [c_ulong; 8], } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: c_int, /// Reserved: layout identifier. pub ki_layout: c_int, /// Address of command arguments. pub ki_args: *mut crate::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut c_void, /// Pointer to open file info. pub ki_fd: *mut crate::filedesc, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut c_void, /// Sleep address. pub ki_wchan: *const c_void, /// Process identifier. pub ki_pid: crate::pid_t, /// Parent process ID. pub ki_ppid: crate::pid_t, /// Process group ID. pub ki_pgid: crate::pid_t, /// tty process group ID. pub ki_tpgid: crate::pid_t, /// Process session ID. pub ki_sid: crate::pid_t, /// Terminal session ID. pub ki_tsid: crate::pid_t, /// Job control counter. pub ki_jobc: c_short, /// Unused (just here for alignment). pub ki_spare_short1: c_short, /// Controlling tty dev. pub ki_tdev_freebsd11: u32, /// Signals arrived but not delivered. pub ki_siglist: crate::sigset_t, /// Current signal mask. pub ki_sigmask: crate::sigset_t, /// Signals being ignored. pub ki_sigignore: crate::sigset_t, /// Signals being caught by user. pub ki_sigcatch: crate::sigset_t, /// Effective user ID. pub ki_uid: crate::uid_t, /// Real user ID. pub ki_ruid: crate::uid_t, /// Saved effective user ID. pub ki_svuid: crate::uid_t, /// Real group ID. pub ki_rgid: crate::gid_t, /// Saved effective group ID. pub ki_svgid: crate::gid_t, /// Number of groups. pub ki_ngroups: c_short, /// Unused (just here for alignment). pub ki_spare_short2: c_short, /// Groups. pub ki_groups: [crate::gid_t; crate::KI_NGROUPS], /// Virtual size. pub ki_size: crate::vm_size_t, /// Current resident set size in pages. pub ki_rssize: crate::segsz_t, /// Resident set size before last swap. pub ki_swrss: crate::segsz_t, /// Text size (pages) XXX. pub ki_tsize: crate::segsz_t, /// Data size (pages) XXX. pub ki_dsize: crate::segsz_t, /// Stack size (pages). pub ki_ssize: crate::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: crate::u_short, /// Accounting flags. pub ki_acflag: crate::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: crate::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: crate::u_int, /// Time since last blocked. pub ki_slptime: crate::u_int, /// Time swapped in or out. pub ki_swtime: crate::u_int, /// Number of copy-on-write faults. pub ki_cow: crate::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: crate::timeval, /// Time used by process children. pub ki_childtime: crate::timeval, /// P_* flags. pub ki_flag: c_long, /// KI_* flags (below). pub ki_kiflag: c_long, /// Kernel trace points. pub ki_traceflag: c_int, /// S* process status. pub ki_stat: c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: c_char, /// Run queue index. pub ki_rqindex: c_char, /// Which cpu we are on. pub ki_oncpu_old: c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: c_uchar, /// Thread name. pub ki_tdname: [c_char; crate::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [c_char; crate::WMESGLEN + 1], /// Setlogin name. pub ki_login: [c_char; crate::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [c_char; crate::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [c_char; crate::COMMLEN + 1], /// Emulation name. pub ki_emul: [c_char; crate::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [c_char; crate::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [c_char; crate::MAXCOMLEN - crate::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [c_int; crate::KI_NSPARE_INT], /// Controlling tty dev. pub ki_tdev: u64, /// Which cpu we are on. pub ki_oncpu: c_int, /// Last cpu we were on. pub ki_lastcpu: c_int, /// PID of tracing process. pub ki_tracer: c_int, /// P2_* flags. pub ki_flag2: c_int, /// Default FIB number. pub ki_fibnum: c_int, /// Credential flags. pub ki_cr_flags: crate::u_int, /// Process jail ID. pub ki_jid: c_int, /// Number of threads in total. pub ki_numthreads: c_int, /// Thread ID. pub ki_tid: crate::lwpid_t, /// Process priority. pub ki_pri: crate::priority, /// Process rusage statistics. pub ki_rusage: crate::rusage, /// rusage of children processes. pub ki_rusage_ch: crate::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut c_void, /// User convenience pointer. pub ki_udata: *mut c_void, // This is normally "struct thread". pub ki_tdaddr: *mut c_void, // This is normally "struct pwddesc". /// Pointer to process paths info. pub ki_pd: *mut c_void, pub ki_spareptrs: [*mut c_void; crate::KI_NSPARE_PTR], pub ki_sparelongs: [c_long; crate::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: c_long, /// kthread flag. pub ki_tdflags: c_long, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, st_padding0: i16, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, st_padding1: i32, pub st_rdev: crate::dev_t, #[cfg(target_arch = "x86")] st_atim_ext: i32, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, #[cfg(target_arch = "x86")] st_mtim_ext: i32, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, #[cfg(target_arch = "x86")] st_ctim_ext: i32, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, #[cfg(target_arch = "x86")] st_btim_ext: i32, pub st_birthtime: crate::time_t, pub st_birthtime_nsec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: crate::blksize_t, pub st_flags: crate::fflags_t, pub st_gen: u64, pub st_filerev: u64, pub st_spare: [u64; 9], } } s_no_extra_traits! { pub struct dirent { pub d_fileno: crate::ino_t, pub d_off: off_t, pub d_reclen: u16, pub d_type: u8, d_pad0: u8, pub d_namlen: u16, d_pad1: u16, pub d_name: [c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: crate::uid_t, pub f_fsid: crate::fsid_t, f_charspare: [c_char; 80], pub f_fstypename: [c_char; 16], pub f_mntfromname: [c_char; 1024], pub f_mntonname: [c_char; 1024], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_dev: u64, pub vn_fsid: u64, pub vn_mntdir: *mut c_char, pub vn_type: c_int, pub vn_mode: u16, pub vn_devname: [c_char; crate::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) } } impl Eq for statfs {} impl fmt::Debug for statfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_charspare.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self.d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[c_char] = &self.vn_devname; let other_vn_devname: &[c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_mntdir == other.vn_mntdir && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl fmt::Debug for vnstat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let self_vn_devname: &[c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_mntdir", &self.vn_mntdir) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_mntdir.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const RAND_MAX: c_int = 0x7fff_ffff; pub const ELAST: c_int = 97; pub const KF_TYPE_EVENTFD: c_int = 13; /// max length of devicename pub const SPECNAMELEN: c_int = 255; pub const KI_NSPARE_PTR: usize = 5; /// domainset policies pub const DOMAINSET_POLICY_INVALID: c_int = 0; pub const DOMAINSET_POLICY_ROUNDROBIN: c_int = 1; pub const DOMAINSET_POLICY_FIRSTTOUCH: c_int = 2; pub const DOMAINSET_POLICY_PREFER: c_int = 3; pub const DOMAINSET_POLICY_INTERLEAVE: c_int = 4; pub const MINCORE_SUPER: c_int = 0x60; safe_f! { pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= ((major & 0xffffff00) as dev_t) << 32; dev |= ((major & 0x000000ff) as dev_t) << 8; dev |= ((minor & 0x0000ff00) as dev_t) << 24; dev |= ((minor & 0xffff00ff) as dev_t) << 0; dev } pub {const} fn major(dev: crate::dev_t) -> c_int { (((dev >> 32) & 0xffffff00) | ((dev >> 8) & 0xff)) as c_int } pub {const} fn minor(dev: crate::dev_t) -> c_int { (((dev >> 24) & 0xff00) | (dev & 0xffff00ff)) as c_int } } extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn freelocale(loc: crate::locale_t); pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtyp: c_long, msgflg: c_int, ) -> ssize_t; pub fn cpuset_getdomain( level: crate::cpulevel_t, which: crate::cpuwhich_t, id: crate::id_t, setsize: size_t, mask: *mut crate::domainset_t, policy: *mut c_int, ) -> c_int; pub fn cpuset_setdomain( level: crate::cpulevel_t, which: crate::cpuwhich_t, id: crate::id_t, setsize: size_t, mask: *const crate::domainset_t, policy: c_int, ) -> c_int; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn basename(path: *mut c_char) -> *mut c_char; } #[link(name = "kvm")] extern "C" { pub fn kvm_kerndisp(kd: *mut crate::kvm_t) -> crate::kssize_t; } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs0000644000175000017500000000125615105742312022616 0ustar bdrungbdrunguse crate::prelude::*; pub const PROC_KPTI_CTL: c_int = crate::PROC_PROCCTL_MD_MIN; pub const PROC_KPTI_CTL_ENABLE_ON_EXEC: c_int = 1; pub const PROC_KPTI_CTL_DISABLE_ON_EXEC: c_int = 2; pub const PROC_KPTI_STATUS: c_int = crate::PROC_PROCCTL_MD_MIN + 1; pub const PROC_KPTI_STATUS_ACTIVE: c_int = 0x80000000; pub const PROC_LA_CTL: c_int = crate::PROC_PROCCTL_MD_MIN + 2; pub const PROC_LA_STATUS: c_int = crate::PROC_PROCCTL_MD_MIN + 3; pub const PROC_LA_CTL_LA48_ON_EXEC: c_int = 1; pub const PROC_LA_CTL_LA57_ON_EXEC: c_int = 2; pub const PROC_LA_CTL_DEFAULT_ON_EXEC: c_int = 3; pub const PROC_LA_STATUS_LA48: c_int = 0x01000000; pub const PROC_LA_STATUS_LA57: c_int = 0x02000000; libc/src/unix/bsd/freebsdlike/freebsd/riscv64.rs0000644000175000017500000001256515105742312021405 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = i32; pub type wchar_t = c_int; pub type time_t = i64; pub type suseconds_t = c_long; pub type register_t = i64; s_no_extra_traits! { pub struct gpregs { pub gp_ra: crate::register_t, pub gp_sp: crate::register_t, pub gp_gp: crate::register_t, pub gp_tp: crate::register_t, pub gp_t: [crate::register_t; 7], pub gp_s: [crate::register_t; 12], pub gp_a: [crate::register_t; 8], pub gp_sepc: crate::register_t, pub gp_sstatus: crate::register_t, } pub struct fpregs { pub fp_x: [[u64; 2]; 32], pub fp_fcsr: u64, pub fp_flags: c_int, pub pad: c_int, } pub struct mcontext_t { pub mc_gpregs: gpregs, pub mc_fpregs: fpregs, pub mc_flags: c_int, pub mc_pad: c_int, pub mc_spare: [u64; 8], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for gpregs { fn eq(&self, other: &gpregs) -> bool { self.gp_ra == other.gp_ra && self.gp_sp == other.gp_sp && self.gp_gp == other.gp_gp && self.gp_tp == other.gp_tp && self.gp_t.iter().zip(other.gp_t.iter()).all(|(a, b)| a == b) && self.gp_s.iter().zip(other.gp_s.iter()).all(|(a, b)| a == b) && self.gp_a.iter().zip(other.gp_a.iter()).all(|(a, b)| a == b) && self.gp_sepc == other.gp_sepc && self.gp_sstatus == other.gp_sstatus } } impl Eq for gpregs {} impl fmt::Debug for gpregs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("gpregs") .field("gp_ra", &self.gp_ra) .field("gp_sp", &self.gp_sp) .field("gp_gp", &self.gp_gp) .field("gp_tp", &self.gp_tp) .field("gp_t", &self.gp_t) .field("gp_s", &self.gp_s) .field("gp_a", &self.gp_a) .field("gp_sepc", &self.gp_sepc) .field("gp_sstatus", &self.gp_sstatus) .finish() } } impl hash::Hash for gpregs { fn hash(&self, state: &mut H) { self.gp_ra.hash(state); self.gp_sp.hash(state); self.gp_gp.hash(state); self.gp_tp.hash(state); self.gp_t.hash(state); self.gp_s.hash(state); self.gp_a.hash(state); self.gp_sepc.hash(state); self.gp_sstatus.hash(state); } } impl PartialEq for fpregs { fn eq(&self, other: &fpregs) -> bool { self.fp_x == other.fp_x && self.fp_fcsr == other.fp_fcsr && self.fp_flags == other.fp_flags && self.pad == other.pad } } impl Eq for fpregs {} impl fmt::Debug for fpregs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fpregs") .field("fp_x", &self.fp_x) .field("fp_fcsr", &self.fp_fcsr) .field("fp_flags", &self.fp_flags) .field("pad", &self.pad) .finish() } } impl hash::Hash for fpregs { fn hash(&self, state: &mut H) { self.fp_x.hash(state); self.fp_fcsr.hash(state); self.fp_flags.hash(state); self.pad.hash(state); } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_gpregs == other.mc_gpregs && self.mc_fpregs == other.mc_fpregs && self.mc_flags == other.mc_flags && self.mc_pad == other.mc_pad && self .mc_spare .iter() .zip(other.mc_spare.iter()) .all(|(a, b)| a == b) } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("mc_gpregs", &self.mc_gpregs) .field("mc_fpregs", &self.mc_fpregs) .field("mc_flags", &self.mc_flags) .field("mc_pad", &self.mc_pad) .field("mc_spare", &self.mc_spare) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_gpregs.hash(state); self.mc_fpregs.hash(state); self.mc_flags.hash(state); self.mc_pad.hash(state); self.mc_spare.hash(state); } } } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const BIOCSRTIMEOUT: c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4010426e; pub const MAP_32BIT: c_int = 0x00080000; pub const MINSIGSTKSZ: size_t = 4096; // 1024 * 4 pub const TIOCTIMESTAMP: c_ulong = 0x40107459; libc/src/unix/bsd/freebsdlike/freebsd/powerpc.rs0000644000175000017500000000525215105742312021557 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = u32; pub type wchar_t = i32; pub type time_t = i64; pub type suseconds_t = i32; pub type register_t = i32; s_no_extra_traits! { #[repr(align(16))] pub struct mcontext_t { pub mc_vers: c_int, pub mc_flags: c_int, pub mc_onstack: c_int, pub mc_len: c_int, pub mc_avec: [u64; 64], pub mc_av: [u32; 2], pub mc_frame: [crate::register_t; 42], pub mc_fpreg: [u64; 33], pub mc_vsxfpreg: [u64; 32], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_vers == other.mc_vers && self.mc_flags == other.mc_flags && self.mc_onstack == other.mc_onstack && self.mc_len == other.mc_len && self.mc_avec == other.mc_avec && self.mc_av == other.mc_av && self.mc_frame == other.mc_frame && self.mc_fpreg == other.mc_fpreg && self.mc_vsxfpreg == other.mc_vsxfpreg } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("mc_vers", &self.mc_vers) .field("mc_flags", &self.mc_flags) .field("mc_onstack", &self.mc_onstack) .field("mc_len", &self.mc_len) .field("mc_avec", &self.mc_avec) .field("mc_av", &self.mc_av) .field("mc_frame", &self.mc_frame) .field("mc_fpreg", &self.mc_fpreg) .field("mc_vsxfpreg", &self.mc_vsxfpreg) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_vers.hash(state); self.mc_flags.hash(state); self.mc_onstack.hash(state); self.mc_len.hash(state); self.mc_avec.hash(state); self.mc_av.hash(state); self.mc_frame.hash(state); self.mc_fpreg.hash(state); self.mc_vsxfpreg.hash(state); } } } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const BIOCSRTIMEOUT: c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4010426e; pub const MAP_32BIT: c_int = 0x00080000; pub const MINSIGSTKSZ: size_t = 2048; // 512 * 4 pub const TIOCTIMESTAMP: c_ulong = 0x40107459; libc/src/unix/bsd/freebsdlike/freebsd/x86.rs0000644000175000017500000001530415105742312020524 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = c_ulong; pub type wchar_t = i32; pub type time_t = i32; pub type suseconds_t = i32; pub type register_t = i32; s_no_extra_traits! { #[repr(align(16))] pub struct mcontext_t { pub mc_onstack: register_t, pub mc_gs: register_t, pub mc_fs: register_t, pub mc_es: register_t, pub mc_ds: register_t, pub mc_edi: register_t, pub mc_esi: register_t, pub mc_ebp: register_t, pub mc_isp: register_t, pub mc_ebx: register_t, pub mc_edx: register_t, pub mc_ecx: register_t, pub mc_eax: register_t, pub mc_trapno: register_t, pub mc_err: register_t, pub mc_eip: register_t, pub mc_cs: register_t, pub mc_eflags: register_t, pub mc_esp: register_t, pub mc_ss: register_t, pub mc_len: c_int, pub mc_fpformat: c_int, pub mc_ownedfp: c_int, pub mc_flags: register_t, pub mc_fpstate: [c_int; 128], pub mc_fsbase: register_t, pub mc_gsbase: register_t, pub mc_xfpustate: register_t, pub mc_xfpustate_len: register_t, pub mc_spare2: [c_int; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_onstack == other.mc_onstack && self.mc_gs == other.mc_gs && self.mc_fs == other.mc_fs && self.mc_es == other.mc_es && self.mc_ds == other.mc_ds && self.mc_edi == other.mc_edi && self.mc_esi == other.mc_esi && self.mc_ebp == other.mc_ebp && self.mc_isp == other.mc_isp && self.mc_ebx == other.mc_ebx && self.mc_edx == other.mc_edx && self.mc_ecx == other.mc_ecx && self.mc_eax == other.mc_eax && self.mc_trapno == other.mc_trapno && self.mc_err == other.mc_err && self.mc_eip == other.mc_eip && self.mc_cs == other.mc_cs && self.mc_eflags == other.mc_eflags && self.mc_esp == other.mc_esp && self.mc_ss == other.mc_ss && self.mc_len == other.mc_len && self.mc_fpformat == other.mc_fpformat && self.mc_ownedfp == other.mc_ownedfp && self.mc_flags == other.mc_flags && self .mc_fpstate .iter() .zip(other.mc_fpstate.iter()) .all(|(a, b)| a == b) && self.mc_fsbase == other.mc_fsbase && self.mc_gsbase == other.mc_gsbase && self.mc_xfpustate == other.mc_xfpustate && self.mc_xfpustate_len == other.mc_xfpustate_len && self .mc_spare2 .iter() .zip(other.mc_spare2.iter()) .all(|(a, b)| a == b) } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("mc_onstack", &self.mc_onstack) .field("mc_gs", &self.mc_gs) .field("mc_fs", &self.mc_fs) .field("mc_es", &self.mc_es) .field("mc_ds", &self.mc_ds) .field("mc_edi", &self.mc_edi) .field("mc_esi", &self.mc_esi) .field("mc_ebp", &self.mc_ebp) .field("mc_isp", &self.mc_isp) .field("mc_ebx", &self.mc_ebx) .field("mc_edx", &self.mc_edx) .field("mc_ecx", &self.mc_ecx) .field("mc_eax", &self.mc_eax) .field("mc_trapno", &self.mc_trapno) .field("mc_err", &self.mc_err) .field("mc_eip", &self.mc_eip) .field("mc_cs", &self.mc_cs) .field("mc_eflags", &self.mc_eflags) .field("mc_esp", &self.mc_esp) .field("mc_ss", &self.mc_ss) .field("mc_len", &self.mc_len) .field("mc_fpformat", &self.mc_fpformat) .field("mc_ownedfp", &self.mc_ownedfp) .field("mc_flags", &self.mc_flags) .field("mc_fpstate", &self.mc_fpstate) .field("mc_fsbase", &self.mc_fsbase) .field("mc_gsbase", &self.mc_gsbase) .field("mc_xfpustate", &self.mc_xfpustate) .field("mc_xfpustate_len", &self.mc_xfpustate_len) .field("mc_spare2", &self.mc_spare2) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_onstack.hash(state); self.mc_gs.hash(state); self.mc_fs.hash(state); self.mc_es.hash(state); self.mc_ds.hash(state); self.mc_edi.hash(state); self.mc_esi.hash(state); self.mc_ebp.hash(state); self.mc_isp.hash(state); self.mc_ebx.hash(state); self.mc_edx.hash(state); self.mc_ecx.hash(state); self.mc_eax.hash(state); self.mc_trapno.hash(state); self.mc_err.hash(state); self.mc_eip.hash(state); self.mc_cs.hash(state); self.mc_eflags.hash(state); self.mc_esp.hash(state); self.mc_ss.hash(state); self.mc_len.hash(state); self.mc_fpformat.hash(state); self.mc_ownedfp.hash(state); self.mc_flags.hash(state); self.mc_fpstate.hash(state); self.mc_fsbase.hash(state); self.mc_gsbase.hash(state); self.mc_xfpustate.hash(state); self.mc_xfpustate_len.hash(state); self.mc_spare2.hash(state); } } } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const MINSIGSTKSZ: size_t = 2048; // 512 * 4 pub const BIOCSRTIMEOUT: c_ulong = 0x8008426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4008426e; pub const KINFO_FILE_SIZE: c_int = 1392; pub const TIOCTIMESTAMP: c_ulong = 0x40087459; libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/0000775000175000017500000000000015105742312021304 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs0000644000175000017500000004236715105742312022443 0ustar bdrungbdrunguse crate::prelude::*; // APIs that were changed after FreeBSD 11 // The type of `nlink_t` changed from `u16` to `u64` in FreeBSD 12: pub type nlink_t = u16; // Type of `dev_t` changed from `u32` to `u64` in FreeBSD 12: pub type dev_t = u32; // Type of `ino_t` changed from `__uint32_t` to `__uint64_t` in FreeBSD 12: pub type ino_t = u32; s! { pub struct kevent { pub ident: crate::uintptr_t, pub filter: c_short, pub flags: c_ushort, pub fflags: c_uint, pub data: intptr_t, pub udata: *mut c_void, } pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, // Type of shm_nattc changed from `int` to `shmatt_t` (aka `unsigned // int`) in FreeBSD 12: pub shm_nattch: c_int, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: c_int, /// Reserved: layout identifier. pub ki_layout: c_int, /// Address of command arguments. pub ki_args: *mut crate::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut c_void, /// Pointer to open file info. pub ki_fd: *mut crate::filedesc, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut c_void, /// Sleep address. pub ki_wchan: *mut c_void, /// Process identifier. pub ki_pid: crate::pid_t, /// Parent process ID. pub ki_ppid: crate::pid_t, /// Process group ID. pub ki_pgid: crate::pid_t, /// tty process group ID. pub ki_tpgid: crate::pid_t, /// Process session ID. pub ki_sid: crate::pid_t, /// Terminal session ID. pub ki_tsid: crate::pid_t, /// Job control counter. pub ki_jobc: c_short, /// Unused (just here for alignment). pub ki_spare_short1: c_short, /// Controlling tty dev. pub ki_tdev: crate::dev_t, /// Signals arrived but not delivered. pub ki_siglist: crate::sigset_t, /// Current signal mask. pub ki_sigmask: crate::sigset_t, /// Signals being ignored. pub ki_sigignore: crate::sigset_t, /// Signals being caught by user. pub ki_sigcatch: crate::sigset_t, /// Effective user ID. pub ki_uid: crate::uid_t, /// Real user ID. pub ki_ruid: crate::uid_t, /// Saved effective user ID. pub ki_svuid: crate::uid_t, /// Real group ID. pub ki_rgid: crate::gid_t, /// Saved effective group ID. pub ki_svgid: crate::gid_t, /// Number of groups. pub ki_ngroups: c_short, /// Unused (just here for alignment). pub ki_spare_short2: c_short, /// Groups. pub ki_groups: [crate::gid_t; crate::KI_NGROUPS], /// Virtual size. pub ki_size: crate::vm_size_t, /// Current resident set size in pages. pub ki_rssize: crate::segsz_t, /// Resident set size before last swap. pub ki_swrss: crate::segsz_t, /// Text size (pages) XXX. pub ki_tsize: crate::segsz_t, /// Data size (pages) XXX. pub ki_dsize: crate::segsz_t, /// Stack size (pages). pub ki_ssize: crate::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: crate::u_short, /// Accounting flags. pub ki_acflag: crate::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: crate::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: crate::u_int, /// Time since last blocked. pub ki_slptime: crate::u_int, /// Time swapped in or out. pub ki_swtime: crate::u_int, /// Number of copy-on-write faults. pub ki_cow: crate::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: crate::timeval, /// Time used by process children. pub ki_childtime: crate::timeval, /// P_* flags. pub ki_flag: c_long, /// KI_* flags (below). pub ki_kiflag: c_long, /// Kernel trace points. pub ki_traceflag: c_int, /// S* process status. pub ki_stat: c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: c_char, /// Run queue index. pub ki_rqindex: c_char, /// Which cpu we are on. pub ki_oncpu_old: c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: c_uchar, /// Thread name. pub ki_tdname: [c_char; crate::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [c_char; crate::WMESGLEN + 1], /// Setlogin name. pub ki_login: [c_char; crate::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [c_char; crate::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [c_char; crate::COMMLEN + 1], /// Emulation name. pub ki_emul: [c_char; crate::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [c_char; crate::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [c_char; crate::MAXCOMLEN - crate::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [c_int; crate::KI_NSPARE_INT], /// Which cpu we are on. pub ki_oncpu: c_int, /// Last cpu we were on. pub ki_lastcpu: c_int, /// PID of tracing process. pub ki_tracer: c_int, /// P2_* flags. pub ki_flag2: c_int, /// Default FIB number. pub ki_fibnum: c_int, /// Credential flags. pub ki_cr_flags: crate::u_int, /// Process jail ID. pub ki_jid: c_int, /// Number of threads in total. pub ki_numthreads: c_int, /// Thread ID. pub ki_tid: crate::lwpid_t, /// Process priority. pub ki_pri: crate::priority, /// Process rusage statistics. pub ki_rusage: crate::rusage, /// rusage of children processes. pub ki_rusage_ch: crate::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut c_void, /// User convenience pointer. pub ki_udata: *mut c_void, // This is normally "struct thread". pub ki_tdaddr: *mut c_void, pub ki_spareptrs: [*mut c_void; crate::KI_NSPARE_PTR], pub ki_sparelongs: [c_long; crate::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: c_long, /// kthread flag. pub ki_tdflags: c_long, } } s_no_extra_traits! { pub struct dirent { pub d_fileno: crate::ino_t, pub d_reclen: u16, pub d_type: u8, // Type of `d_namlen` changed from `char` to `u16` in FreeBSD 12: pub d_namlen: u8, pub d_name: [c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: crate::uid_t, pub f_fsid: crate::fsid_t, f_charspare: [c_char; 80], pub f_fstypename: [c_char; 16], // Array length changed from 88 to 1024 in FreeBSD 12: pub f_mntfromname: [c_char; 88], // Array length changed from 88 to 1024 in FreeBSD 12: pub f_mntonname: [c_char; 88], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_mntdir: *mut c_char, pub vn_dev: u32, pub vn_fsid: u32, pub vn_type: c_int, pub vn_mode: u16, pub vn_devname: [c_char; crate::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) } } impl Eq for statfs {} impl fmt::Debug for statfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self.d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[c_char] = &self.vn_devname; let other_vn_devname: &[c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_mntdir == other.vn_mntdir && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl fmt::Debug for vnstat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let self_vn_devname: &[c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_mntdir", &self.vn_mntdir) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_mntdir.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const ELAST: c_int = 96; pub const RAND_MAX: c_int = 0x7fff_fffd; pub const KI_NSPARE_PTR: usize = 6; pub const MINCORE_SUPER: c_int = 0x20; /// max length of devicename pub const SPECNAMELEN: c_int = 63; safe_f! { pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; (major << 8) | minor } pub {const} fn major(dev: crate::dev_t) -> c_int { ((dev >> 8) & 0xff) as c_int } pub {const} fn minor(dev: crate::dev_t) -> c_int { (dev & 0xffff00ff) as c_int } } extern "C" { // Return type c_int was removed in FreeBSD 12 pub fn setgrent() -> c_int; // Type of `addr` argument changed from `const void*` to `void*` // in FreeBSD 12 pub fn mprotect(addr: *const c_void, len: size_t, prot: c_int) -> c_int; // Return type c_int was removed in FreeBSD 12 pub fn freelocale(loc: crate::locale_t) -> c_int; // Return type c_int changed to ssize_t in FreeBSD 12: pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtyp: c_long, msgflg: c_int, ) -> c_int; // Type of `path` argument changed from `const void*` to `void*` // in FreeBSD 12 pub fn dirname(path: *const c_char) -> *mut c_char; pub fn basename(path: *const c_char) -> *mut c_char; } cfg_if! { if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { mod b32; pub use self::b32::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/b32.rs0000644000175000017500000000166315105742312022244 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; #[repr(C)] #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: crate::blksize_t, pub st_flags: crate::fflags_t, pub st_gen: u32, pub st_lspare: i32, pub st_birthtime: crate::time_t, pub st_birthtime_nsec: c_long, __unused: [u8; 8], } impl Copy for crate::stat {} impl Clone for crate::stat { fn clone(&self) -> crate::stat { *self } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs0000644000175000017500000000163415105742312022247 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; #[repr(C)] #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_mode: crate::mode_t, pub st_nlink: crate::nlink_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: crate::dev_t, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: crate::blksize_t, pub st_flags: crate::fflags_t, pub st_gen: u32, pub st_lspare: i32, pub st_birthtime: crate::time_t, pub st_birthtime_nsec: c_long, } impl Copy for crate::stat {} impl Clone for crate::stat { fn clone(&self) -> crate::stat { *self } } libc/src/unix/bsd/freebsdlike/freebsd/powerpc64.rs0000644000175000017500000000525415105742312021733 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = u32; pub type wchar_t = i32; pub type time_t = i64; pub type suseconds_t = i64; pub type register_t = i64; s_no_extra_traits! { #[repr(align(16))] pub struct mcontext_t { pub mc_vers: c_int, pub mc_flags: c_int, pub mc_onstack: c_int, pub mc_len: c_int, pub mc_avec: [u64; 64], pub mc_av: [u32; 2], pub mc_frame: [crate::register_t; 42], pub mc_fpreg: [u64; 33], pub mc_vsxfpreg: [u64; 32], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_vers == other.mc_vers && self.mc_flags == other.mc_flags && self.mc_onstack == other.mc_onstack && self.mc_len == other.mc_len && self.mc_avec == other.mc_avec && self.mc_av == other.mc_av && self.mc_frame == other.mc_frame && self.mc_fpreg == other.mc_fpreg && self.mc_vsxfpreg == other.mc_vsxfpreg } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("mc_vers", &self.mc_vers) .field("mc_flags", &self.mc_flags) .field("mc_onstack", &self.mc_onstack) .field("mc_len", &self.mc_len) .field("mc_avec", &self.mc_avec) .field("mc_av", &self.mc_av) .field("mc_frame", &self.mc_frame) .field("mc_fpreg", &self.mc_fpreg) .field("mc_vsxfpreg", &self.mc_vsxfpreg) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_vers.hash(state); self.mc_flags.hash(state); self.mc_onstack.hash(state); self.mc_len.hash(state); self.mc_avec.hash(state); self.mc_av.hash(state); self.mc_frame.hash(state); self.mc_fpreg.hash(state); self.mc_vsxfpreg.hash(state); } } } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; pub const BIOCSRTIMEOUT: c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4010426e; pub const MAP_32BIT: c_int = 0x00080000; pub const MINSIGSTKSZ: size_t = 2048; // 512 * 4 pub const TIOCTIMESTAMP: c_ulong = 0x40107459; libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/0000775000175000017500000000000015105742312021305 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs0000644000175000017500000004446015105742312022440 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; // APIs in FreeBSD 12 that have changed since 11. pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = u64; pub type shmatt_t = c_uint; s! { pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, } pub struct kevent { pub ident: crate::uintptr_t, pub filter: c_short, pub flags: c_ushort, pub fflags: c_uint, pub data: i64, pub udata: *mut c_void, pub ext: [u64; 4], } pub struct kvm_page { pub version: c_uint, pub paddr: c_ulong, pub kmap_vaddr: c_ulong, pub dmap_vaddr: c_ulong, pub prot: crate::vm_prot_t, pub offset: crate::u_long, pub len: size_t, } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: c_int, /// Reserved: layout identifier. pub ki_layout: c_int, /// Address of command arguments. pub ki_args: *mut crate::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut c_void, /// Pointer to open file info. pub ki_fd: *mut crate::filedesc, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut c_void, /// Sleep address. pub ki_wchan: *mut c_void, /// Process identifier. pub ki_pid: crate::pid_t, /// Parent process ID. pub ki_ppid: crate::pid_t, /// Process group ID. pub ki_pgid: crate::pid_t, /// tty process group ID. pub ki_tpgid: crate::pid_t, /// Process session ID. pub ki_sid: crate::pid_t, /// Terminal session ID. pub ki_tsid: crate::pid_t, /// Job control counter. pub ki_jobc: c_short, /// Unused (just here for alignment). pub ki_spare_short1: c_short, /// Controlling tty dev. pub ki_tdev_freebsd11: u32, /// Signals arrived but not delivered. pub ki_siglist: crate::sigset_t, /// Current signal mask. pub ki_sigmask: crate::sigset_t, /// Signals being ignored. pub ki_sigignore: crate::sigset_t, /// Signals being caught by user. pub ki_sigcatch: crate::sigset_t, /// Effective user ID. pub ki_uid: crate::uid_t, /// Real user ID. pub ki_ruid: crate::uid_t, /// Saved effective user ID. pub ki_svuid: crate::uid_t, /// Real group ID. pub ki_rgid: crate::gid_t, /// Saved effective group ID. pub ki_svgid: crate::gid_t, /// Number of groups. pub ki_ngroups: c_short, /// Unused (just here for alignment). pub ki_spare_short2: c_short, /// Groups. pub ki_groups: [crate::gid_t; crate::KI_NGROUPS], /// Virtual size. pub ki_size: crate::vm_size_t, /// Current resident set size in pages. pub ki_rssize: crate::segsz_t, /// Resident set size before last swap. pub ki_swrss: crate::segsz_t, /// Text size (pages) XXX. pub ki_tsize: crate::segsz_t, /// Data size (pages) XXX. pub ki_dsize: crate::segsz_t, /// Stack size (pages). pub ki_ssize: crate::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: crate::u_short, /// Accounting flags. pub ki_acflag: crate::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: crate::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: crate::u_int, /// Time since last blocked. pub ki_slptime: crate::u_int, /// Time swapped in or out. pub ki_swtime: crate::u_int, /// Number of copy-on-write faults. pub ki_cow: crate::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: crate::timeval, /// Time used by process children. pub ki_childtime: crate::timeval, /// P_* flags. pub ki_flag: c_long, /// KI_* flags (below). pub ki_kiflag: c_long, /// Kernel trace points. pub ki_traceflag: c_int, /// S* process status. pub ki_stat: c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: c_char, /// Run queue index. pub ki_rqindex: c_char, /// Which cpu we are on. pub ki_oncpu_old: c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: c_uchar, /// Thread name. pub ki_tdname: [c_char; crate::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [c_char; crate::WMESGLEN + 1], /// Setlogin name. pub ki_login: [c_char; crate::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [c_char; crate::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [c_char; crate::COMMLEN + 1], /// Emulation name. pub ki_emul: [c_char; crate::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [c_char; crate::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [c_char; crate::MAXCOMLEN - crate::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [c_int; crate::KI_NSPARE_INT], /// Controlling tty dev. pub ki_tdev: crate::dev_t, /// Which cpu we are on. pub ki_oncpu: c_int, /// Last cpu we were on. pub ki_lastcpu: c_int, /// PID of tracing process. pub ki_tracer: c_int, /// P2_* flags. pub ki_flag2: c_int, /// Default FIB number. pub ki_fibnum: c_int, /// Credential flags. pub ki_cr_flags: crate::u_int, /// Process jail ID. pub ki_jid: c_int, /// Number of threads in total. pub ki_numthreads: c_int, /// Thread ID. pub ki_tid: crate::lwpid_t, /// Process priority. pub ki_pri: crate::priority, /// Process rusage statistics. pub ki_rusage: crate::rusage, /// rusage of children processes. pub ki_rusage_ch: crate::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut c_void, /// User convenience pointer. pub ki_udata: *mut c_void, // This is normally "struct thread". pub ki_tdaddr: *mut c_void, pub ki_spareptrs: [*mut c_void; crate::KI_NSPARE_PTR], pub ki_sparelongs: [c_long; crate::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: c_long, /// kthread flag. pub ki_tdflags: c_long, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, st_padding0: i16, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, st_padding1: i32, pub st_rdev: crate::dev_t, #[cfg(target_arch = "x86")] st_atim_ext: i32, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, #[cfg(target_arch = "x86")] st_mtim_ext: i32, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, #[cfg(target_arch = "x86")] st_ctim_ext: i32, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, #[cfg(target_arch = "x86")] st_btim_ext: i32, pub st_birthtime: crate::time_t, pub st_birthtime_nsec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: crate::blksize_t, pub st_flags: crate::fflags_t, pub st_gen: u64, pub st_spare: [u64; 10], } } s_no_extra_traits! { pub struct dirent { pub d_fileno: crate::ino_t, pub d_off: off_t, pub d_reclen: u16, pub d_type: u8, d_pad0: u8, pub d_namlen: u16, d_pad1: u16, pub d_name: [c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: crate::uid_t, pub f_fsid: crate::fsid_t, f_charspare: [c_char; 80], pub f_fstypename: [c_char; 16], pub f_mntfromname: [c_char; 1024], pub f_mntonname: [c_char; 1024], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_dev: u64, pub vn_fsid: u64, pub vn_mntdir: *mut c_char, pub vn_type: c_int, pub vn_mode: u16, pub vn_devname: [c_char; crate::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) } } impl Eq for statfs {} impl fmt::Debug for statfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_charspare.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self.d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[c_char] = &self.vn_devname; let other_vn_devname: &[c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_mntdir == other.vn_mntdir && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl fmt::Debug for vnstat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let self_vn_devname: &[c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_mntdir", &self.vn_mntdir) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_mntdir.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const RAND_MAX: c_int = 0x7fff_fffd; pub const ELAST: c_int = 97; /// max length of devicename pub const SPECNAMELEN: c_int = 63; pub const KI_NSPARE_PTR: usize = 6; pub const MINCORE_SUPER: c_int = 0x20; safe_f! { pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= ((major & 0xffffff00) as dev_t) << 32; dev |= ((major & 0x000000ff) as dev_t) << 8; dev |= ((minor & 0x0000ff00) as dev_t) << 24; dev |= ((minor & 0xffff00ff) as dev_t) << 0; dev } pub {const} fn major(dev: crate::dev_t) -> c_int { (((dev >> 32) & 0xffffff00) | ((dev >> 8) & 0xff)) as c_int } pub {const} fn minor(dev: crate::dev_t) -> c_int { (((dev >> 24) & 0xff00) | (dev & 0xffff00ff)) as c_int } } extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn freelocale(loc: crate::locale_t); pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtyp: c_long, msgflg: c_int, ) -> ssize_t; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn basename(path: *mut c_char) -> *mut c_char; } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs0000644000175000017500000000046715105742312022616 0ustar bdrungbdrunguse crate::prelude::*; pub const PROC_KPTI_CTL: c_int = crate::PROC_PROCCTL_MD_MIN; pub const PROC_KPTI_CTL_ENABLE_ON_EXEC: c_int = 1; pub const PROC_KPTI_CTL_DISABLE_ON_EXEC: c_int = 2; pub const PROC_KPTI_STATUS: c_int = crate::PROC_PROCCTL_MD_MIN + 1; pub const PROC_KPTI_STATUS_ACTIVE: c_int = 0x80000000; libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/0000775000175000017500000000000015105742312021307 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs0000644000175000017500000004713015105742312022437 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; // APIs in FreeBSD 14 that have changed since 11. pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = u64; pub type shmatt_t = c_uint; pub type kpaddr_t = u64; pub type kssize_t = i64; pub type domainset_t = __c_anonymous_domainset; s! { pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, } pub struct kevent { pub ident: crate::uintptr_t, pub filter: c_short, pub flags: c_ushort, pub fflags: c_uint, pub data: i64, pub udata: *mut c_void, pub ext: [u64; 4], } pub struct kvm_page { pub kp_version: crate::u_int, pub kp_paddr: crate::kpaddr_t, pub kp_kmap_vaddr: crate::kvaddr_t, pub kp_dmap_vaddr: crate::kvaddr_t, pub kp_prot: crate::vm_prot_t, pub kp_offset: off_t, pub kp_len: size_t, } pub struct __c_anonymous_domainset { #[cfg(target_pointer_width = "64")] _priv: [c_ulong; 4], #[cfg(target_pointer_width = "32")] _priv: [c_ulong; 8], } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: c_int, /// Reserved: layout identifier. pub ki_layout: c_int, /// Address of command arguments. pub ki_args: *mut crate::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut c_void, /// Pointer to open file info. pub ki_fd: *mut crate::filedesc, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut c_void, /// Sleep address. pub ki_wchan: *const c_void, /// Process identifier. pub ki_pid: crate::pid_t, /// Parent process ID. pub ki_ppid: crate::pid_t, /// Process group ID. pub ki_pgid: crate::pid_t, /// tty process group ID. pub ki_tpgid: crate::pid_t, /// Process session ID. pub ki_sid: crate::pid_t, /// Terminal session ID. pub ki_tsid: crate::pid_t, /// Job control counter. pub ki_jobc: c_short, /// Unused (just here for alignment). pub ki_spare_short1: c_short, /// Controlling tty dev. pub ki_tdev_freebsd11: u32, /// Signals arrived but not delivered. pub ki_siglist: crate::sigset_t, /// Current signal mask. pub ki_sigmask: crate::sigset_t, /// Signals being ignored. pub ki_sigignore: crate::sigset_t, /// Signals being caught by user. pub ki_sigcatch: crate::sigset_t, /// Effective user ID. pub ki_uid: crate::uid_t, /// Real user ID. pub ki_ruid: crate::uid_t, /// Saved effective user ID. pub ki_svuid: crate::uid_t, /// Real group ID. pub ki_rgid: crate::gid_t, /// Saved effective group ID. pub ki_svgid: crate::gid_t, /// Number of groups. pub ki_ngroups: c_short, /// Unused (just here for alignment). pub ki_spare_short2: c_short, /// Groups. pub ki_groups: [crate::gid_t; crate::KI_NGROUPS], /// Virtual size. pub ki_size: crate::vm_size_t, /// Current resident set size in pages. pub ki_rssize: crate::segsz_t, /// Resident set size before last swap. pub ki_swrss: crate::segsz_t, /// Text size (pages) XXX. pub ki_tsize: crate::segsz_t, /// Data size (pages) XXX. pub ki_dsize: crate::segsz_t, /// Stack size (pages). pub ki_ssize: crate::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: crate::u_short, /// Accounting flags. pub ki_acflag: crate::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: crate::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: crate::u_int, /// Time since last blocked. pub ki_slptime: crate::u_int, /// Time swapped in or out. pub ki_swtime: crate::u_int, /// Number of copy-on-write faults. pub ki_cow: crate::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: crate::timeval, /// Time used by process children. pub ki_childtime: crate::timeval, /// P_* flags. pub ki_flag: c_long, /// KI_* flags (below). pub ki_kiflag: c_long, /// Kernel trace points. pub ki_traceflag: c_int, /// S* process status. pub ki_stat: c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: c_char, /// Run queue index. pub ki_rqindex: c_char, /// Which cpu we are on. pub ki_oncpu_old: c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: c_uchar, /// Thread name. pub ki_tdname: [c_char; crate::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [c_char; crate::WMESGLEN + 1], /// Setlogin name. pub ki_login: [c_char; crate::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [c_char; crate::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [c_char; crate::COMMLEN + 1], /// Emulation name. pub ki_emul: [c_char; crate::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [c_char; crate::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [c_char; crate::MAXCOMLEN - crate::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [c_int; crate::KI_NSPARE_INT], /// Controlling tty dev. pub ki_tdev: u64, /// Which cpu we are on. pub ki_oncpu: c_int, /// Last cpu we were on. pub ki_lastcpu: c_int, /// PID of tracing process. pub ki_tracer: c_int, /// P2_* flags. pub ki_flag2: c_int, /// Default FIB number. pub ki_fibnum: c_int, /// Credential flags. pub ki_cr_flags: crate::u_int, /// Process jail ID. pub ki_jid: c_int, /// Number of threads in total. pub ki_numthreads: c_int, /// Thread ID. pub ki_tid: crate::lwpid_t, /// Process priority. pub ki_pri: crate::priority, /// Process rusage statistics. pub ki_rusage: crate::rusage, /// rusage of children processes. pub ki_rusage_ch: crate::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut c_void, /// User convenience pointer. pub ki_udata: *mut c_void, // This is normally "struct thread". pub ki_tdaddr: *mut c_void, // This is normally "struct pwddesc". /// Pointer to process paths info. pub ki_pd: *mut c_void, pub ki_spareptrs: [*mut c_void; crate::KI_NSPARE_PTR], pub ki_sparelongs: [c_long; crate::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: c_long, /// kthread flag. pub ki_tdflags: c_long, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, st_padding0: i16, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, st_padding1: i32, pub st_rdev: crate::dev_t, #[cfg(target_arch = "x86")] st_atim_ext: i32, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, #[cfg(target_arch = "x86")] st_mtim_ext: i32, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, #[cfg(target_arch = "x86")] st_ctim_ext: i32, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, #[cfg(target_arch = "x86")] st_btim_ext: i32, pub st_birthtime: crate::time_t, pub st_birthtime_nsec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: crate::blksize_t, pub st_flags: crate::fflags_t, pub st_gen: u64, pub st_spare: [u64; 10], } } s_no_extra_traits! { pub struct dirent { pub d_fileno: crate::ino_t, pub d_off: off_t, pub d_reclen: u16, pub d_type: u8, d_pad0: u8, pub d_namlen: u16, d_pad1: u16, pub d_name: [c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: crate::uid_t, pub f_fsid: crate::fsid_t, f_charspare: [c_char; 80], pub f_fstypename: [c_char; 16], pub f_mntfromname: [c_char; 1024], pub f_mntonname: [c_char; 1024], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_dev: u64, pub vn_fsid: u64, pub vn_mntdir: *mut c_char, pub vn_type: c_int, pub vn_mode: u16, pub vn_devname: [c_char; crate::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) } } impl Eq for statfs {} impl fmt::Debug for statfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_charspare.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self.d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[c_char] = &self.vn_devname; let other_vn_devname: &[c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_mntdir == other.vn_mntdir && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl fmt::Debug for vnstat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let self_vn_devname: &[c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_mntdir", &self.vn_mntdir) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_mntdir.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const RAND_MAX: c_int = 0x7fff_ffff; pub const ELAST: c_int = 97; pub const KF_TYPE_EVENTFD: c_int = 13; /// max length of devicename pub const SPECNAMELEN: c_int = 255; pub const KI_NSPARE_PTR: usize = 5; /// domainset policies pub const DOMAINSET_POLICY_INVALID: c_int = 0; pub const DOMAINSET_POLICY_ROUNDROBIN: c_int = 1; pub const DOMAINSET_POLICY_FIRSTTOUCH: c_int = 2; pub const DOMAINSET_POLICY_PREFER: c_int = 3; pub const DOMAINSET_POLICY_INTERLEAVE: c_int = 4; pub const MINCORE_SUPER: c_int = 0x60; safe_f! { pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= ((major & 0xffffff00) as dev_t) << 32; dev |= ((major & 0x000000ff) as dev_t) << 8; dev |= ((minor & 0x0000ff00) as dev_t) << 24; dev |= ((minor & 0xffff00ff) as dev_t) << 0; dev } pub {const} fn major(dev: crate::dev_t) -> c_int { (((dev >> 32) & 0xffffff00) | ((dev >> 8) & 0xff)) as c_int } pub {const} fn minor(dev: crate::dev_t) -> c_int { (((dev >> 24) & 0xff00) | (dev & 0xffff00ff)) as c_int } } extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn freelocale(loc: crate::locale_t); pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtyp: c_long, msgflg: c_int, ) -> ssize_t; pub fn cpuset_getdomain( level: crate::cpulevel_t, which: crate::cpuwhich_t, id: crate::id_t, setsize: size_t, mask: *mut crate::domainset_t, policy: *mut c_int, ) -> c_int; pub fn cpuset_setdomain( level: crate::cpulevel_t, which: crate::cpuwhich_t, id: crate::id_t, setsize: size_t, mask: *const crate::domainset_t, policy: c_int, ) -> c_int; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn basename(path: *mut c_char) -> *mut c_char; } #[link(name = "kvm")] extern "C" { pub fn kvm_kerndisp(kd: *mut crate::kvm_t) -> crate::kssize_t; } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs0000644000175000017500000000125615105742312022615 0ustar bdrungbdrunguse crate::prelude::*; pub const PROC_KPTI_CTL: c_int = crate::PROC_PROCCTL_MD_MIN; pub const PROC_KPTI_CTL_ENABLE_ON_EXEC: c_int = 1; pub const PROC_KPTI_CTL_DISABLE_ON_EXEC: c_int = 2; pub const PROC_KPTI_STATUS: c_int = crate::PROC_PROCCTL_MD_MIN + 1; pub const PROC_KPTI_STATUS_ACTIVE: c_int = 0x80000000; pub const PROC_LA_CTL: c_int = crate::PROC_PROCCTL_MD_MIN + 2; pub const PROC_LA_STATUS: c_int = crate::PROC_PROCCTL_MD_MIN + 3; pub const PROC_LA_CTL_LA48_ON_EXEC: c_int = 1; pub const PROC_LA_CTL_LA57_ON_EXEC: c_int = 2; pub const PROC_LA_CTL_DEFAULT_ON_EXEC: c_int = 3; pub const PROC_LA_STATUS_LA48: c_int = 0x01000000; pub const PROC_LA_STATUS_LA57: c_int = 0x02000000; libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/0000775000175000017500000000000015105742312021306 5ustar bdrungbdrunglibc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs0000644000175000017500000004713015105742312022436 0ustar bdrungbdrunguse crate::off_t; use crate::prelude::*; // APIs in FreeBSD 13 that have changed since 11. pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = u64; pub type shmatt_t = c_uint; pub type kpaddr_t = u64; pub type kssize_t = i64; pub type domainset_t = __c_anonymous_domainset; s! { pub struct shmid_ds { pub shm_perm: crate::ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_atime: crate::time_t, pub shm_dtime: crate::time_t, pub shm_ctime: crate::time_t, } pub struct kevent { pub ident: crate::uintptr_t, pub filter: c_short, pub flags: c_ushort, pub fflags: c_uint, pub data: i64, pub udata: *mut c_void, pub ext: [u64; 4], } pub struct kvm_page { pub kp_version: crate::u_int, pub kp_paddr: crate::kpaddr_t, pub kp_kmap_vaddr: crate::kvaddr_t, pub kp_dmap_vaddr: crate::kvaddr_t, pub kp_prot: crate::vm_prot_t, pub kp_offset: off_t, pub kp_len: size_t, } pub struct __c_anonymous_domainset { #[cfg(target_pointer_width = "64")] _priv: [c_ulong; 4], #[cfg(target_pointer_width = "32")] _priv: [c_ulong; 8], } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: c_int, /// Reserved: layout identifier. pub ki_layout: c_int, /// Address of command arguments. pub ki_args: *mut crate::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut c_void, /// Pointer to open file info. pub ki_fd: *mut crate::filedesc, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut c_void, /// Sleep address. pub ki_wchan: *const c_void, /// Process identifier. pub ki_pid: crate::pid_t, /// Parent process ID. pub ki_ppid: crate::pid_t, /// Process group ID. pub ki_pgid: crate::pid_t, /// tty process group ID. pub ki_tpgid: crate::pid_t, /// Process session ID. pub ki_sid: crate::pid_t, /// Terminal session ID. pub ki_tsid: crate::pid_t, /// Job control counter. pub ki_jobc: c_short, /// Unused (just here for alignment). pub ki_spare_short1: c_short, /// Controlling tty dev. pub ki_tdev_freebsd11: u32, /// Signals arrived but not delivered. pub ki_siglist: crate::sigset_t, /// Current signal mask. pub ki_sigmask: crate::sigset_t, /// Signals being ignored. pub ki_sigignore: crate::sigset_t, /// Signals being caught by user. pub ki_sigcatch: crate::sigset_t, /// Effective user ID. pub ki_uid: crate::uid_t, /// Real user ID. pub ki_ruid: crate::uid_t, /// Saved effective user ID. pub ki_svuid: crate::uid_t, /// Real group ID. pub ki_rgid: crate::gid_t, /// Saved effective group ID. pub ki_svgid: crate::gid_t, /// Number of groups. pub ki_ngroups: c_short, /// Unused (just here for alignment). pub ki_spare_short2: c_short, /// Groups. pub ki_groups: [crate::gid_t; crate::KI_NGROUPS], /// Virtual size. pub ki_size: crate::vm_size_t, /// Current resident set size in pages. pub ki_rssize: crate::segsz_t, /// Resident set size before last swap. pub ki_swrss: crate::segsz_t, /// Text size (pages) XXX. pub ki_tsize: crate::segsz_t, /// Data size (pages) XXX. pub ki_dsize: crate::segsz_t, /// Stack size (pages). pub ki_ssize: crate::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: crate::u_short, /// Accounting flags. pub ki_acflag: crate::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: crate::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: crate::u_int, /// Time since last blocked. pub ki_slptime: crate::u_int, /// Time swapped in or out. pub ki_swtime: crate::u_int, /// Number of copy-on-write faults. pub ki_cow: crate::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: crate::timeval, /// Time used by process children. pub ki_childtime: crate::timeval, /// P_* flags. pub ki_flag: c_long, /// KI_* flags (below). pub ki_kiflag: c_long, /// Kernel trace points. pub ki_traceflag: c_int, /// S* process status. pub ki_stat: c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: c_char, /// Run queue index. pub ki_rqindex: c_char, /// Which cpu we are on. pub ki_oncpu_old: c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: c_uchar, /// Thread name. pub ki_tdname: [c_char; crate::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [c_char; crate::WMESGLEN + 1], /// Setlogin name. pub ki_login: [c_char; crate::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [c_char; crate::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [c_char; crate::COMMLEN + 1], /// Emulation name. pub ki_emul: [c_char; crate::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [c_char; crate::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [c_char; crate::MAXCOMLEN - crate::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [c_int; crate::KI_NSPARE_INT], /// Controlling tty dev. pub ki_tdev: u64, /// Which cpu we are on. pub ki_oncpu: c_int, /// Last cpu we were on. pub ki_lastcpu: c_int, /// PID of tracing process. pub ki_tracer: c_int, /// P2_* flags. pub ki_flag2: c_int, /// Default FIB number. pub ki_fibnum: c_int, /// Credential flags. pub ki_cr_flags: crate::u_int, /// Process jail ID. pub ki_jid: c_int, /// Number of threads in total. pub ki_numthreads: c_int, /// Thread ID. pub ki_tid: crate::lwpid_t, /// Process priority. pub ki_pri: crate::priority, /// Process rusage statistics. pub ki_rusage: crate::rusage, /// rusage of children processes. pub ki_rusage_ch: crate::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut c_void, /// User convenience pointer. pub ki_udata: *mut c_void, // This is normally "struct thread". pub ki_tdaddr: *mut c_void, // This is normally "struct pwddesc". /// Pointer to process paths info. pub ki_pd: *mut c_void, pub ki_spareptrs: [*mut c_void; crate::KI_NSPARE_PTR], pub ki_sparelongs: [c_long; crate::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: c_long, /// kthread flag. pub ki_tdflags: c_long, } pub struct stat { pub st_dev: crate::dev_t, pub st_ino: crate::ino_t, pub st_nlink: crate::nlink_t, pub st_mode: crate::mode_t, st_padding0: i16, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, st_padding1: i32, pub st_rdev: crate::dev_t, #[cfg(target_arch = "x86")] st_atim_ext: i32, pub st_atime: crate::time_t, pub st_atime_nsec: c_long, #[cfg(target_arch = "x86")] st_mtim_ext: i32, pub st_mtime: crate::time_t, pub st_mtime_nsec: c_long, #[cfg(target_arch = "x86")] st_ctim_ext: i32, pub st_ctime: crate::time_t, pub st_ctime_nsec: c_long, #[cfg(target_arch = "x86")] st_btim_ext: i32, pub st_birthtime: crate::time_t, pub st_birthtime_nsec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: crate::blksize_t, pub st_flags: crate::fflags_t, pub st_gen: u64, pub st_spare: [u64; 10], } } s_no_extra_traits! { pub struct dirent { pub d_fileno: crate::ino_t, pub d_off: off_t, pub d_reclen: u16, pub d_type: u8, d_pad0: u8, pub d_namlen: u16, d_pad1: u16, pub d_name: [c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: crate::uid_t, pub f_fsid: crate::fsid_t, f_charspare: [c_char; 80], pub f_fstypename: [c_char; 16], pub f_mntfromname: [c_char; 1024], pub f_mntonname: [c_char; 1024], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_dev: u64, pub vn_fsid: u64, pub vn_mntdir: *mut c_char, pub vn_type: c_int, pub vn_mode: u16, pub vn_devname: [c_char; crate::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) } } impl Eq for statfs {} impl fmt::Debug for statfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_charspare.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self.d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[c_char] = &self.vn_devname; let other_vn_devname: &[c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_mntdir == other.vn_mntdir && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl fmt::Debug for vnstat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let self_vn_devname: &[c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_mntdir", &self.vn_mntdir) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_mntdir.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const RAND_MAX: c_int = 0x7fff_ffff; pub const ELAST: c_int = 97; pub const KF_TYPE_EVENTFD: c_int = 13; /// max length of devicename pub const SPECNAMELEN: c_int = 255; pub const KI_NSPARE_PTR: usize = 5; /// domainset policies pub const DOMAINSET_POLICY_INVALID: c_int = 0; pub const DOMAINSET_POLICY_ROUNDROBIN: c_int = 1; pub const DOMAINSET_POLICY_FIRSTTOUCH: c_int = 2; pub const DOMAINSET_POLICY_PREFER: c_int = 3; pub const DOMAINSET_POLICY_INTERLEAVE: c_int = 4; pub const MINCORE_SUPER: c_int = 0x20; safe_f! { pub {const} fn makedev(major: c_uint, minor: c_uint) -> crate::dev_t { let major = major as crate::dev_t; let minor = minor as crate::dev_t; let mut dev = 0; dev |= ((major & 0xffffff00) as dev_t) << 32; dev |= ((major & 0x000000ff) as dev_t) << 8; dev |= ((minor & 0x0000ff00) as dev_t) << 24; dev |= ((minor & 0xffff00ff) as dev_t) << 0; dev } pub {const} fn major(dev: crate::dev_t) -> c_int { (((dev >> 32) & 0xffffff00) | ((dev >> 8) & 0xff)) as c_int } pub {const} fn minor(dev: crate::dev_t) -> c_int { (((dev >> 24) & 0xff00) | (dev & 0xffff00ff)) as c_int } } extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn freelocale(loc: crate::locale_t); pub fn msgrcv( msqid: c_int, msgp: *mut c_void, msgsz: size_t, msgtyp: c_long, msgflg: c_int, ) -> ssize_t; pub fn cpuset_getdomain( level: crate::cpulevel_t, which: crate::cpuwhich_t, id: crate::id_t, setsize: size_t, mask: *mut crate::domainset_t, policy: *mut c_int, ) -> c_int; pub fn cpuset_setdomain( level: crate::cpulevel_t, which: crate::cpuwhich_t, id: crate::id_t, setsize: size_t, mask: *const crate::domainset_t, policy: c_int, ) -> c_int; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn basename(path: *mut c_char) -> *mut c_char; } #[link(name = "kvm")] extern "C" { pub fn kvm_kerndisp(kd: *mut crate::kvm_t) -> crate::kssize_t; } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs0000644000175000017500000000046715105742312022617 0ustar bdrungbdrunguse crate::prelude::*; pub const PROC_KPTI_CTL: c_int = crate::PROC_PROCCTL_MD_MIN; pub const PROC_KPTI_CTL_ENABLE_ON_EXEC: c_int = 1; pub const PROC_KPTI_CTL_DISABLE_ON_EXEC: c_int = 2; pub const PROC_KPTI_STATUS: c_int = crate::PROC_PROCCTL_MD_MIN + 1; pub const PROC_KPTI_STATUS_ACTIVE: c_int = 0x80000000; libc/src/unix/bsd/freebsdlike/freebsd/aarch64.rs0000644000175000017500000001161215105742312021325 0ustar bdrungbdrunguse crate::prelude::*; pub type clock_t = i32; pub type wchar_t = u32; pub type time_t = i64; pub type suseconds_t = i64; pub type register_t = i64; s_no_extra_traits! { pub struct gpregs { pub gp_x: [crate::register_t; 30], pub gp_lr: crate::register_t, pub gp_sp: crate::register_t, pub gp_elr: crate::register_t, pub gp_spsr: u32, pub gp_pad: c_int, } pub struct fpregs { pub fp_q: u128, pub fp_sr: u32, pub fp_cr: u32, pub fp_flags: c_int, pub fp_pad: c_int, } pub struct mcontext_t { pub mc_gpregs: gpregs, pub mc_fpregs: fpregs, pub mc_flags: c_int, pub mc_pad: c_int, pub mc_spare: [u64; 8], } } pub(crate) const _ALIGNBYTES: usize = mem::size_of::() - 1; cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for gpregs { fn eq(&self, other: &gpregs) -> bool { self.gp_x.iter().zip(other.gp_x.iter()).all(|(a, b)| a == b) && self.gp_lr == other.gp_lr && self.gp_sp == other.gp_sp && self.gp_elr == other.gp_elr && self.gp_spsr == other.gp_spsr && self.gp_pad == other.gp_pad } } impl Eq for gpregs {} impl fmt::Debug for gpregs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("gpregs") .field("gp_x", &self.gp_x) .field("gp_lr", &self.gp_lr) .field("gp_sp", &self.gp_sp) .field("gp_elr", &self.gp_elr) .field("gp_spsr", &self.gp_spsr) .field("gp_pad", &self.gp_pad) .finish() } } impl hash::Hash for gpregs { fn hash(&self, state: &mut H) { self.gp_x.hash(state); self.gp_lr.hash(state); self.gp_sp.hash(state); self.gp_elr.hash(state); self.gp_spsr.hash(state); self.gp_pad.hash(state); } } impl PartialEq for fpregs { fn eq(&self, other: &fpregs) -> bool { self.fp_q == other.fp_q && self.fp_sr == other.fp_sr && self.fp_cr == other.fp_cr && self.fp_flags == other.fp_flags && self.fp_pad == other.fp_pad } } impl Eq for fpregs {} impl fmt::Debug for fpregs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("fpregs") .field("fp_q", &self.fp_q) .field("fp_sr", &self.fp_sr) .field("fp_cr", &self.fp_cr) .field("fp_flags", &self.fp_flags) .field("fp_pad", &self.fp_pad) .finish() } } impl hash::Hash for fpregs { fn hash(&self, state: &mut H) { self.fp_q.hash(state); self.fp_sr.hash(state); self.fp_cr.hash(state); self.fp_flags.hash(state); self.fp_pad.hash(state); } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_gpregs == other.mc_gpregs && self.mc_fpregs == other.mc_fpregs && self.mc_flags == other.mc_flags && self.mc_pad == other.mc_pad && self .mc_spare .iter() .zip(other.mc_spare.iter()) .all(|(a, b)| a == b) } } impl Eq for mcontext_t {} impl fmt::Debug for mcontext_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("mcontext_t") .field("mc_gpregs", &self.mc_gpregs) .field("mc_fpregs", &self.mc_fpregs) .field("mc_flags", &self.mc_flags) .field("mc_pad", &self.mc_pad) .field("mc_spare", &self.mc_spare) .finish() } } impl hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_gpregs.hash(state); self.mc_fpregs.hash(state); self.mc_flags.hash(state); self.mc_pad.hash(state); self.mc_spare.hash(state); } } } } pub const BIOCSRTIMEOUT: c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4010426e; pub const MAP_32BIT: c_int = 0x00080000; pub const MINSIGSTKSZ: size_t = 4096; // 1024 * 4 pub const TIOCTIMESTAMP: c_ulong = 0x40107459; libc/src/unix/bsd/apple/0000775000175000017500000000000015105742312014740 5ustar bdrungbdrunglibc/src/unix/bsd/apple/mod.rs0000644000175000017500000074245215105742312016101 0ustar bdrungbdrung//! Apple (ios/darwin)-specific definitions //! //! This covers *-apple-* triples currently use crate::prelude::*; use crate::{cmsghdr, off_t}; pub type wchar_t = i32; pub type clock_t = c_ulong; pub type time_t = c_long; pub type suseconds_t = i32; pub type dev_t = i32; pub type ino_t = u64; pub type mode_t = u16; pub type nlink_t = u16; pub type blksize_t = i32; pub type rlim_t = u64; pub type pthread_key_t = c_ulong; pub type sigset_t = u32; pub type clockid_t = c_uint; pub type fsblkcnt_t = c_uint; pub type fsfilcnt_t = c_uint; pub type speed_t = c_ulong; pub type tcflag_t = c_ulong; pub type nl_item = c_int; pub type id_t = c_uint; pub type sem_t = c_int; pub type idtype_t = c_uint; pub type integer_t = c_int; pub type cpu_type_t = integer_t; pub type cpu_subtype_t = integer_t; pub type natural_t = u32; pub type mach_msg_type_number_t = natural_t; pub type kern_return_t = c_int; pub type uuid_t = [u8; 16]; pub type task_info_t = *mut integer_t; pub type host_info_t = *mut integer_t; pub type task_flavor_t = natural_t; pub type rusage_info_t = *mut c_void; pub type vm_offset_t = crate::uintptr_t; pub type vm_size_t = crate::uintptr_t; pub type vm_address_t = vm_offset_t; pub type quad_t = i64; pub type u_quad_t = u64; pub type posix_spawnattr_t = *mut c_void; pub type posix_spawn_file_actions_t = *mut c_void; pub type key_t = c_int; pub type shmatt_t = c_ushort; pub type sae_associd_t = u32; pub type sae_connid_t = u32; pub type mach_port_t = c_uint; pub type host_t = c_uint; pub type host_flavor_t = integer_t; pub type host_info64_t = *mut integer_t; pub type processor_flavor_t = c_int; pub type thread_flavor_t = natural_t; pub type thread_inspect_t = crate::mach_port_t; pub type thread_act_t = crate::mach_port_t; pub type thread_act_array_t = *mut crate::thread_act_t; pub type policy_t = c_int; pub type mach_error_t = crate::kern_return_t; pub type mach_vm_address_t = u64; pub type mach_vm_offset_t = u64; pub type mach_vm_size_t = u64; pub type vm_map_t = crate::mach_port_t; pub type mem_entry_name_port_t = crate::mach_port_t; pub type memory_object_t = crate::mach_port_t; pub type memory_object_offset_t = c_ulonglong; pub type vm_inherit_t = c_uint; pub type vm_prot_t = c_int; pub type ledger_t = crate::mach_port_t; pub type ledger_array_t = *mut crate::ledger_t; pub type iconv_t = *mut c_void; // mach/host_info.h pub type host_cpu_load_info_t = *mut host_cpu_load_info; pub type host_cpu_load_info_data_t = host_cpu_load_info; // mach/processor_info.h pub type processor_cpu_load_info_t = *mut processor_cpu_load_info; pub type processor_cpu_load_info_data_t = processor_cpu_load_info; pub type processor_basic_info_t = *mut processor_basic_info; pub type processor_basic_info_data_t = processor_basic_info; pub type processor_set_basic_info_data_t = processor_set_basic_info; pub type processor_set_basic_info_t = *mut processor_set_basic_info; pub type processor_set_load_info_data_t = processor_set_load_info; pub type processor_set_load_info_t = *mut processor_set_load_info; pub type processor_info_t = *mut integer_t; pub type processor_info_array_t = *mut integer_t; pub type mach_task_basic_info_data_t = mach_task_basic_info; pub type mach_task_basic_info_t = *mut mach_task_basic_info; pub type task_thread_times_info_data_t = task_thread_times_info; pub type task_thread_times_info_t = *mut task_thread_times_info; pub type thread_info_t = *mut integer_t; pub type thread_basic_info_t = *mut thread_basic_info; pub type thread_basic_info_data_t = thread_basic_info; pub type thread_identifier_info_t = *mut thread_identifier_info; pub type thread_identifier_info_data_t = thread_identifier_info; pub type thread_extended_info_t = *mut thread_extended_info; pub type thread_extended_info_data_t = thread_extended_info; pub type thread_t = crate::mach_port_t; pub type thread_policy_flavor_t = natural_t; pub type thread_policy_t = *mut integer_t; pub type thread_latency_qos_t = integer_t; pub type thread_throughput_qos_t = integer_t; pub type thread_standard_policy_data_t = thread_standard_policy; pub type thread_standard_policy_t = *mut thread_standard_policy; pub type thread_extended_policy_data_t = thread_extended_policy; pub type thread_extended_policy_t = *mut thread_extended_policy; pub type thread_time_constraint_policy_data_t = thread_time_constraint_policy; pub type thread_time_constraint_policy_t = *mut thread_time_constraint_policy; pub type thread_precedence_policy_data_t = thread_precedence_policy; pub type thread_precedence_policy_t = *mut thread_precedence_policy; pub type thread_affinity_policy_data_t = thread_affinity_policy; pub type thread_affinity_policy_t = *mut thread_affinity_policy; pub type thread_background_policy_data_t = thread_background_policy; pub type thread_background_policy_t = *mut thread_background_policy; pub type thread_latency_qos_policy_data_t = thread_latency_qos_policy; pub type thread_latency_qos_policy_t = *mut thread_latency_qos_policy; pub type thread_throughput_qos_policy_data_t = thread_throughput_qos_policy; pub type thread_throughput_qos_policy_t = *mut thread_throughput_qos_policy; pub type pthread_introspection_hook_t = extern "C" fn(event: c_uint, thread: crate::pthread_t, addr: *mut c_void, size: size_t); pub type pthread_jit_write_callback_t = Option c_int>; pub type os_clockid_t = u32; pub type os_sync_wait_on_address_flags_t = u32; pub type os_sync_wake_by_address_flags_t = u32; pub type os_unfair_lock = os_unfair_lock_s; pub type os_unfair_lock_t = *mut os_unfair_lock; pub type os_log_t = *mut c_void; pub type os_log_type_t = u8; pub type os_signpost_id_t = u64; pub type os_signpost_type_t = u8; pub type vm_statistics_t = *mut vm_statistics; pub type vm_statistics_data_t = vm_statistics; pub type vm_statistics64_t = *mut vm_statistics64; pub type vm_statistics64_data_t = vm_statistics64; pub type task_t = crate::mach_port_t; pub type task_inspect_t = crate::mach_port_t; pub type sysdir_search_path_enumeration_state = c_uint; pub type CCStatus = i32; pub type CCCryptorStatus = i32; pub type CCRNGStatus = crate::CCCryptorStatus; pub type copyfile_state_t = *mut c_void; pub type copyfile_flags_t = u32; pub type copyfile_callback_t = Option< extern "C" fn( c_int, c_int, copyfile_state_t, *const c_char, *const c_char, *mut c_void, ) -> c_int, >; pub type attrgroup_t = u32; pub type vol_capabilities_set_t = [u32; 4]; deprecated_mach! { pub type mach_timebase_info_data_t = mach_timebase_info; } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl Copy for timezone {} impl Clone for timezone { fn clone(&self) -> timezone { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(u32)] pub enum qos_class_t { QOS_CLASS_USER_INTERACTIVE = 0x21, QOS_CLASS_USER_INITIATED = 0x19, QOS_CLASS_DEFAULT = 0x15, QOS_CLASS_UTILITY = 0x11, QOS_CLASS_BACKGROUND = 0x09, QOS_CLASS_UNSPECIFIED = 0x00, } impl Copy for qos_class_t {} impl Clone for qos_class_t { fn clone(&self) -> qos_class_t { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(u32)] pub enum sysdir_search_path_directory_t { SYSDIR_DIRECTORY_APPLICATION = 1, SYSDIR_DIRECTORY_DEMO_APPLICATION = 2, SYSDIR_DIRECTORY_DEVELOPER_APPLICATION = 3, SYSDIR_DIRECTORY_ADMIN_APPLICATION = 4, SYSDIR_DIRECTORY_LIBRARY = 5, SYSDIR_DIRECTORY_DEVELOPER = 6, SYSDIR_DIRECTORY_USER = 7, SYSDIR_DIRECTORY_DOCUMENTATION = 8, SYSDIR_DIRECTORY_DOCUMENT = 9, SYSDIR_DIRECTORY_CORESERVICE = 10, SYSDIR_DIRECTORY_AUTOSAVED_INFORMATION = 11, SYSDIR_DIRECTORY_DESKTOP = 12, SYSDIR_DIRECTORY_CACHES = 13, SYSDIR_DIRECTORY_APPLICATION_SUPPORT = 14, SYSDIR_DIRECTORY_DOWNLOADS = 15, SYSDIR_DIRECTORY_INPUT_METHODS = 16, SYSDIR_DIRECTORY_MOVIES = 17, SYSDIR_DIRECTORY_MUSIC = 18, SYSDIR_DIRECTORY_PICTURES = 19, SYSDIR_DIRECTORY_PRINTER_DESCRIPTION = 20, SYSDIR_DIRECTORY_SHARED_PUBLIC = 21, SYSDIR_DIRECTORY_PREFERENCE_PANES = 22, SYSDIR_DIRECTORY_ALL_APPLICATIONS = 100, SYSDIR_DIRECTORY_ALL_LIBRARIES = 101, } impl Copy for sysdir_search_path_directory_t {} impl Clone for sysdir_search_path_directory_t { fn clone(&self) -> sysdir_search_path_directory_t { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(u32)] pub enum sysdir_search_path_domain_mask_t { SYSDIR_DOMAIN_MASK_USER = (1 << 0), SYSDIR_DOMAIN_MASK_LOCAL = (1 << 1), SYSDIR_DOMAIN_MASK_NETWORK = (1 << 2), SYSDIR_DOMAIN_MASK_SYSTEM = (1 << 3), SYSDIR_DOMAIN_MASK_ALL = 0x0ffff, } impl Copy for sysdir_search_path_domain_mask_t {} impl Clone for sysdir_search_path_domain_mask_t { fn clone(&self) -> sysdir_search_path_domain_mask_t { *self } } s! { pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: c_int, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct aiocb { pub aio_fildes: c_int, pub aio_offset: off_t, pub aio_buf: *mut c_void, pub aio_nbytes: size_t, pub aio_reqprio: c_int, pub aio_sigevent: sigevent, pub aio_lio_opcode: c_int, } pub struct glob_t { pub gl_pathc: size_t, __unused1: c_int, pub gl_offs: size_t, __unused2: c_int, pub gl_pathv: *mut *mut c_char, __unused3: *mut c_void, __unused4: *mut c_void, __unused5: *mut c_void, __unused6: *mut c_void, __unused7: *mut c_void, __unused8: *mut c_void, } pub struct addrinfo { pub ai_flags: c_int, pub ai_family: c_int, pub ai_socktype: c_int, pub ai_protocol: c_int, pub ai_addrlen: crate::socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut crate::sockaddr, pub ai_next: *mut addrinfo, } #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub struct mach_timebase_info { pub numer: u32, pub denom: u32, } pub struct stat { pub st_dev: dev_t, pub st_mode: mode_t, pub st_nlink: nlink_t, pub st_ino: ino_t, pub st_uid: crate::uid_t, pub st_gid: crate::gid_t, pub st_rdev: dev_t, pub st_atime: time_t, pub st_atime_nsec: c_long, pub st_mtime: time_t, pub st_mtime_nsec: c_long, pub st_ctime: time_t, pub st_ctime_nsec: c_long, pub st_birthtime: time_t, pub st_birthtime_nsec: c_long, pub st_size: off_t, pub st_blocks: crate::blkcnt_t, pub st_blksize: blksize_t, pub st_flags: u32, pub st_gen: u32, pub st_lspare: i32, pub st_qspare: [i64; 2], } pub struct pthread_mutexattr_t { __sig: c_long, __opaque: [u8; 8], } pub struct pthread_condattr_t { __sig: c_long, __opaque: [u8; __PTHREAD_CONDATTR_SIZE__], } pub struct pthread_rwlockattr_t { __sig: c_long, __opaque: [u8; __PTHREAD_RWLOCKATTR_SIZE__], } pub struct siginfo_t { pub si_signo: c_int, pub si_errno: c_int, pub si_code: c_int, pub si_pid: crate::pid_t, pub si_uid: crate::uid_t, pub si_status: c_int, pub si_addr: *mut c_void, //Requires it to be union for tests //pub si_value: crate::sigval, _pad: [usize; 9], } pub struct sigaction { // FIXME(union): this field is actually a union pub sa_sigaction: crate::sighandler_t, pub sa_mask: sigset_t, pub sa_flags: c_int, } pub struct stack_t { pub ss_sp: *mut c_void, pub ss_size: size_t, pub ss_flags: c_int, } pub struct fstore_t { pub fst_flags: c_uint, pub fst_posmode: c_int, pub fst_offset: off_t, pub fst_length: off_t, pub fst_bytesalloc: off_t, } pub struct fpunchhole_t { pub fp_flags: c_uint, /* unused */ pub reserved: c_uint, /* (to maintain 8-byte alignment) */ pub fp_offset: off_t, /* IN: start of the region */ pub fp_length: off_t, /* IN: size of the region */ } pub struct ftrimactivefile_t { pub fta_offset: off_t, pub fta_length: off_t, } pub struct fspecread_t { pub fsr_flags: c_uint, pub reserved: c_uint, pub fsr_offset: off_t, pub fsr_length: off_t, } pub struct radvisory { pub ra_offset: off_t, pub ra_count: c_int, } pub struct statvfs { pub f_bsize: c_ulong, pub f_frsize: c_ulong, pub f_blocks: crate::fsblkcnt_t, pub f_bfree: crate::fsblkcnt_t, pub f_bavail: crate::fsblkcnt_t, pub f_files: crate::fsfilcnt_t, pub f_ffree: crate::fsfilcnt_t, pub f_favail: crate::fsfilcnt_t, pub f_fsid: c_ulong, pub f_flag: c_ulong, pub f_namemax: c_ulong, } pub struct Dl_info { pub dli_fname: *const c_char, pub dli_fbase: *mut c_void, pub dli_sname: *const c_char, pub dli_saddr: *mut c_void, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: crate::sa_family_t, pub sin_port: crate::in_port_t, pub sin_addr: crate::in_addr, pub sin_zero: [c_char; 8], } pub struct kevent64_s { pub ident: u64, pub filter: i16, pub flags: u16, pub fflags: u32, pub data: i64, pub udata: u64, pub ext: [u64; 2], } pub struct dqblk { pub dqb_bhardlimit: u64, pub dqb_bsoftlimit: u64, pub dqb_curbytes: u64, pub dqb_ihardlimit: u32, pub dqb_isoftlimit: u32, pub dqb_curinodes: u32, pub dqb_btime: u32, pub dqb_itime: u32, pub dqb_id: u32, pub dqb_spare: [u32; 4], } pub struct if_msghdr { pub ifm_msglen: c_ushort, pub ifm_version: c_uchar, pub ifm_type: c_uchar, pub ifm_addrs: c_int, pub ifm_flags: c_int, pub ifm_index: c_ushort, pub ifm_data: if_data, } pub struct ifa_msghdr { pub ifam_msglen: c_ushort, pub ifam_version: c_uchar, pub ifam_type: c_uchar, pub ifam_addrs: c_int, pub ifam_flags: c_int, pub ifam_index: c_ushort, pub ifam_metric: c_int, } pub struct ifma_msghdr { pub ifmam_msglen: c_ushort, pub ifmam_version: c_uchar, pub ifmam_type: c_uchar, pub ifmam_addrs: c_int, pub ifmam_flags: c_int, pub ifmam_index: c_ushort, } pub struct ifma_msghdr2 { pub ifmam_msglen: c_ushort, pub ifmam_version: c_uchar, pub ifmam_type: c_uchar, pub ifmam_addrs: c_int, pub ifmam_flags: c_int, pub ifmam_index: c_ushort, pub ifmam_refcount: i32, } pub struct rt_metrics { pub rmx_locks: u32, pub rmx_mtu: u32, pub rmx_hopcount: u32, pub rmx_expire: i32, pub rmx_recvpipe: u32, pub rmx_sendpipe: u32, pub rmx_ssthresh: u32, pub rmx_rtt: u32, pub rmx_rttvar: u32, pub rmx_pksent: u32, /// This field does not exist anymore, the u32 is now part of a resized /// `rmx_filler` array. pub rmx_state: u32, pub rmx_filler: [u32; 3], } pub struct rt_msghdr { pub rtm_msglen: c_ushort, pub rtm_version: c_uchar, pub rtm_type: c_uchar, pub rtm_index: c_ushort, pub rtm_flags: c_int, pub rtm_addrs: c_int, pub rtm_pid: crate::pid_t, pub rtm_seq: c_int, pub rtm_errno: c_int, pub rtm_use: c_int, pub rtm_inits: u32, pub rtm_rmx: rt_metrics, } pub struct rt_msghdr2 { pub rtm_msglen: c_ushort, pub rtm_version: c_uchar, pub rtm_type: c_uchar, pub rtm_index: c_ushort, pub rtm_flags: c_int, pub rtm_addrs: c_int, pub rtm_refcnt: i32, pub rtm_parentflags: c_int, pub rtm_reserved: c_int, pub rtm_use: c_int, pub rtm_inits: u32, pub rtm_rmx: rt_metrics, } pub struct termios { pub c_iflag: crate::tcflag_t, pub c_oflag: crate::tcflag_t, pub c_cflag: crate::tcflag_t, pub c_lflag: crate::tcflag_t, pub c_cc: [crate::cc_t; crate::NCCS], pub c_ispeed: crate::speed_t, pub c_ospeed: crate::speed_t, } pub struct flock { pub l_start: off_t, pub l_len: off_t, pub l_pid: crate::pid_t, pub l_type: c_short, pub l_whence: c_short, } pub struct sf_hdtr { pub headers: *mut crate::iovec, pub hdr_cnt: c_int, pub trailers: *mut crate::iovec, pub trl_cnt: c_int, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_n_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct proc_taskinfo { pub pti_virtual_size: u64, pub pti_resident_size: u64, pub pti_total_user: u64, pub pti_total_system: u64, pub pti_threads_user: u64, pub pti_threads_system: u64, pub pti_policy: i32, pub pti_faults: i32, pub pti_pageins: i32, pub pti_cow_faults: i32, pub pti_messages_sent: i32, pub pti_messages_received: i32, pub pti_syscalls_mach: i32, pub pti_syscalls_unix: i32, pub pti_csw: i32, pub pti_threadnum: i32, pub pti_numrunning: i32, pub pti_priority: i32, } pub struct proc_bsdinfo { pub pbi_flags: u32, pub pbi_status: u32, pub pbi_xstatus: u32, pub pbi_pid: u32, pub pbi_ppid: u32, pub pbi_uid: crate::uid_t, pub pbi_gid: crate::gid_t, pub pbi_ruid: crate::uid_t, pub pbi_rgid: crate::gid_t, pub pbi_svuid: crate::uid_t, pub pbi_svgid: crate::gid_t, pub rfu_1: u32, pub pbi_comm: [c_char; MAXCOMLEN], pub pbi_name: [c_char; 32], // MAXCOMLEN * 2, but macro isn't happy... pub pbi_nfiles: u32, pub pbi_pgid: u32, pub pbi_pjobc: u32, pub e_tdev: u32, pub e_tpgid: u32, pub pbi_nice: i32, pub pbi_start_tvsec: u64, pub pbi_start_tvusec: u64, } pub struct proc_taskallinfo { pub pbsd: proc_bsdinfo, pub ptinfo: proc_taskinfo, } pub struct xsw_usage { pub xsu_total: u64, pub xsu_avail: u64, pub xsu_used: u64, pub xsu_pagesize: u32, pub xsu_encrypted: crate::boolean_t, } pub struct xucred { pub cr_version: c_uint, pub cr_uid: crate::uid_t, pub cr_ngroups: c_short, pub cr_groups: [crate::gid_t; 16], } #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub struct mach_header { pub magic: u32, pub cputype: cpu_type_t, pub cpusubtype: cpu_subtype_t, pub filetype: u32, pub ncmds: u32, pub sizeofcmds: u32, pub flags: u32, } #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub struct mach_header_64 { pub magic: u32, pub cputype: cpu_type_t, pub cpusubtype: cpu_subtype_t, pub filetype: u32, pub ncmds: u32, pub sizeofcmds: u32, pub flags: u32, pub reserved: u32, } pub struct segment_command { pub cmd: u32, pub cmdsize: u32, pub segname: [c_char; 16], pub vmaddr: u32, pub vmsize: u32, pub fileoff: u32, pub filesize: u32, pub maxprot: vm_prot_t, pub initprot: vm_prot_t, pub nsects: u32, pub flags: u32, } pub struct segment_command_64 { pub cmd: u32, pub cmdsize: u32, pub segname: [c_char; 16], pub vmaddr: u64, pub vmsize: u64, pub fileoff: u64, pub filesize: u64, pub maxprot: vm_prot_t, pub initprot: vm_prot_t, pub nsects: u32, pub flags: u32, } pub struct load_command { pub cmd: u32, pub cmdsize: u32, } pub struct sockaddr_dl { pub sdl_len: c_uchar, pub sdl_family: c_uchar, pub sdl_index: c_ushort, pub sdl_type: c_uchar, pub sdl_nlen: c_uchar, pub sdl_alen: c_uchar, pub sdl_slen: c_uchar, pub sdl_data: [c_char; 12], } pub struct sockaddr_inarp { pub sin_len: c_uchar, pub sin_family: c_uchar, pub sin_port: c_ushort, pub sin_addr: crate::in_addr, pub sin_srcaddr: crate::in_addr, pub sin_tos: c_ushort, pub sin_other: c_ushort, } pub struct sockaddr_ctl { pub sc_len: c_uchar, pub sc_family: c_uchar, pub ss_sysaddr: u16, pub sc_id: u32, pub sc_unit: u32, pub sc_reserved: [u32; 5], } pub struct in_pktinfo { pub ipi_ifindex: c_uint, pub ipi_spec_dst: crate::in_addr, pub ipi_addr: crate::in_addr, } pub struct in6_pktinfo { pub ipi6_addr: crate::in6_addr, pub ipi6_ifindex: c_uint, } // sys/ipc.h: pub struct ipc_perm { pub uid: crate::uid_t, pub gid: crate::gid_t, pub cuid: crate::uid_t, pub cgid: crate::gid_t, pub mode: crate::mode_t, pub _seq: c_ushort, pub _key: crate::key_t, } // sys/sem.h pub struct sembuf { pub sem_num: c_ushort, pub sem_op: c_short, pub sem_flg: c_short, } // sys/shm.h pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct in_addr { pub s_addr: crate::in_addr_t, } // net/ndrv.h pub struct sockaddr_ndrv { pub snd_len: c_uchar, pub snd_family: c_uchar, pub snd_name: [c_uchar; crate::IFNAMSIZ], } // sys/socket.h pub struct sa_endpoints_t { pub sae_srcif: c_uint, // optional source interface pub sae_srcaddr: *const crate::sockaddr, // optional source address pub sae_srcaddrlen: crate::socklen_t, // size of source address pub sae_dstaddr: *const crate::sockaddr, // destination address pub sae_dstaddrlen: crate::socklen_t, // size of destination address } pub struct timex { pub modes: c_uint, pub offset: c_long, pub freq: c_long, pub maxerror: c_long, pub esterror: c_long, pub status: c_int, pub constant: c_long, pub precision: c_long, pub tolerance: c_long, pub ppsfreq: c_long, pub jitter: c_long, pub shift: c_int, pub stabil: c_long, pub jitcnt: c_long, pub calcnt: c_long, pub errcnt: c_long, pub stbcnt: c_long, } pub struct ntptimeval { pub time: crate::timespec, pub maxerror: c_long, pub esterror: c_long, pub tai: c_long, pub time_state: c_int, } pub struct thread_standard_policy { pub no_data: natural_t, } pub struct thread_extended_policy { pub timeshare: boolean_t, } pub struct thread_time_constraint_policy { pub period: u32, pub computation: u32, pub constraint: u32, pub preemptible: boolean_t, } pub struct thread_precedence_policy { pub importance: integer_t, } pub struct thread_affinity_policy { pub affinity_tag: integer_t, } pub struct thread_background_policy { pub priority: integer_t, } pub struct thread_latency_qos_policy { pub thread_latency_qos_tier: thread_latency_qos_t, } pub struct thread_throughput_qos_policy { pub thread_throughput_qos_tier: thread_throughput_qos_t, } // malloc/malloc.h pub struct malloc_statistics_t { pub blocks_in_use: c_uint, pub size_in_use: size_t, pub max_size_in_use: size_t, pub size_allocated: size_t, } pub struct mstats { pub bytes_total: size_t, pub chunks_used: size_t, pub bytes_used: size_t, pub chunks_free: size_t, pub bytes_free: size_t, } pub struct vm_range_t { pub address: crate::vm_address_t, pub size: crate::vm_size_t, } // sched.h pub struct sched_param { pub sched_priority: c_int, __opaque: [c_char; 4], } pub struct vinfo_stat { pub vst_dev: u32, pub vst_mode: u16, pub vst_nlink: u16, pub vst_ino: u64, pub vst_uid: crate::uid_t, pub vst_gid: crate::gid_t, pub vst_atime: i64, pub vst_atimensec: i64, pub vst_mtime: i64, pub vst_mtimensec: i64, pub vst_ctime: i64, pub vst_ctimensec: i64, pub vst_birthtime: i64, pub vst_birthtimensec: i64, pub vst_size: off_t, pub vst_blocks: i64, pub vst_blksize: i32, pub vst_flags: u32, pub vst_gen: u32, pub vst_rdev: u32, pub vst_qspare: [i64; 2], } pub struct vnode_info { pub vi_stat: vinfo_stat, pub vi_type: c_int, pub vi_pad: c_int, pub vi_fsid: crate::fsid_t, } pub struct vnode_info_path { pub vip_vi: vnode_info, // Normally it's `vip_path: [c_char; MAXPATHLEN]` but because libc supports an old rustc // version, we go around this limitation like this. pub vip_path: [[c_char; 32]; 32], } pub struct proc_vnodepathinfo { pub pvi_cdir: vnode_info_path, pub pvi_rdir: vnode_info_path, } pub struct vm_statistics { pub free_count: natural_t, pub active_count: natural_t, pub inactive_count: natural_t, pub wire_count: natural_t, pub zero_fill_count: natural_t, pub reactivations: natural_t, pub pageins: natural_t, pub pageouts: natural_t, pub faults: natural_t, pub cow_faults: natural_t, pub lookups: natural_t, pub hits: natural_t, pub purgeable_count: natural_t, pub purges: natural_t, pub speculative_count: natural_t, } pub struct task_thread_times_info { pub user_time: time_value_t, pub system_time: time_value_t, } pub struct rusage_info_v0 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, } pub struct rusage_info_v1 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, pub ri_child_user_time: u64, pub ri_child_system_time: u64, pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, } pub struct rusage_info_v2 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, pub ri_child_user_time: u64, pub ri_child_system_time: u64, pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, pub ri_diskio_bytesread: u64, pub ri_diskio_byteswritten: u64, } pub struct rusage_info_v3 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, pub ri_child_user_time: u64, pub ri_child_system_time: u64, pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, pub ri_diskio_bytesread: u64, pub ri_diskio_byteswritten: u64, pub ri_cpu_time_qos_default: u64, pub ri_cpu_time_qos_maintenance: u64, pub ri_cpu_time_qos_background: u64, pub ri_cpu_time_qos_utility: u64, pub ri_cpu_time_qos_legacy: u64, pub ri_cpu_time_qos_user_initiated: u64, pub ri_cpu_time_qos_user_interactive: u64, pub ri_billed_system_time: u64, pub ri_serviced_system_time: u64, } pub struct rusage_info_v4 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, pub ri_child_user_time: u64, pub ri_child_system_time: u64, pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, pub ri_diskio_bytesread: u64, pub ri_diskio_byteswritten: u64, pub ri_cpu_time_qos_default: u64, pub ri_cpu_time_qos_maintenance: u64, pub ri_cpu_time_qos_background: u64, pub ri_cpu_time_qos_utility: u64, pub ri_cpu_time_qos_legacy: u64, pub ri_cpu_time_qos_user_initiated: u64, pub ri_cpu_time_qos_user_interactive: u64, pub ri_billed_system_time: u64, pub ri_serviced_system_time: u64, pub ri_logical_writes: u64, pub ri_lifetime_max_phys_footprint: u64, pub ri_instructions: u64, pub ri_cycles: u64, pub ri_billed_energy: u64, pub ri_serviced_energy: u64, pub ri_interval_max_phys_footprint: u64, pub ri_runnable_time: u64, } pub struct image_offset { pub uuid: crate::uuid_t, pub offset: u32, } pub struct attrlist { pub bitmapcount: c_ushort, pub reserved: u16, pub commonattr: attrgroup_t, pub volattr: attrgroup_t, pub dirattr: attrgroup_t, pub fileattr: attrgroup_t, pub forkattr: attrgroup_t, } pub struct attrreference_t { pub attr_dataoffset: i32, pub attr_length: u32, } pub struct vol_capabilities_attr_t { pub capabilities: vol_capabilities_set_t, pub valid: vol_capabilities_set_t, } pub struct attribute_set_t { pub commonattr: attrgroup_t, pub volattr: attrgroup_t, pub dirattr: attrgroup_t, pub fileattr: attrgroup_t, pub forkattr: attrgroup_t, } pub struct vol_attributes_attr_t { pub validattr: attribute_set_t, pub nativeattr: attribute_set_t, } #[repr(align(8))] pub struct tcp_connection_info { pub tcpi_state: u8, pub tcpi_snd_wscale: u8, pub tcpi_rcv_wscale: u8, __pad1: u8, pub tcpi_options: u32, pub tcpi_flags: u32, pub tcpi_rto: u32, pub tcpi_maxseg: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub tcpi_snd_wnd: u32, pub tcpi_snd_sbbytes: u32, pub tcpi_rcv_wnd: u32, pub tcpi_rttcur: u32, pub tcpi_srtt: u32, pub tcpi_rttvar: u32, pub tcpi_tfo_cookie_req: u32, pub tcpi_tfo_cookie_rcv: u32, pub tcpi_tfo_syn_loss: u32, pub tcpi_tfo_syn_data_sent: u32, pub tcpi_tfo_syn_data_acked: u32, pub tcpi_tfo_syn_data_rcv: u32, pub tcpi_tfo_cookie_req_rcv: u32, pub tcpi_tfo_cookie_sent: u32, pub tcpi_tfo_cookie_invalid: u32, pub tcpi_tfo_cookie_wrong: u32, pub tcpi_tfo_no_cookie_rcv: u32, pub tcpi_tfo_heuristics_disable: u32, pub tcpi_tfo_send_blackhole: u32, pub tcpi_tfo_recv_blackhole: u32, pub tcpi_tfo_onebyte_proxy: u32, __pad2: u32, pub tcpi_txpackets: u64, pub tcpi_txbytes: u64, pub tcpi_txretransmitbytes: u64, pub tcpi_rxpackets: u64, pub tcpi_rxbytes: u64, pub tcpi_rxoutoforderbytes: u64, pub tcpi_rxretransmitpackets: u64, } pub struct in6_addrlifetime { pub ia6t_expire: time_t, pub ia6t_preferred: time_t, pub ia6t_vltime: u32, pub ia6t_pltime: u32, } pub struct in6_ifstat { pub ifs6_in_receive: crate::u_quad_t, pub ifs6_in_hdrerr: crate::u_quad_t, pub ifs6_in_toobig: crate::u_quad_t, pub ifs6_in_noroute: crate::u_quad_t, pub ifs6_in_addrerr: crate::u_quad_t, pub ifs6_in_protounknown: crate::u_quad_t, pub ifs6_in_truncated: crate::u_quad_t, pub ifs6_in_discard: crate::u_quad_t, pub ifs6_in_deliver: crate::u_quad_t, pub ifs6_out_forward: crate::u_quad_t, pub ifs6_out_request: crate::u_quad_t, pub ifs6_out_discard: crate::u_quad_t, pub ifs6_out_fragok: crate::u_quad_t, pub ifs6_out_fragfail: crate::u_quad_t, pub ifs6_out_fragcreat: crate::u_quad_t, pub ifs6_reass_reqd: crate::u_quad_t, pub ifs6_reass_ok: crate::u_quad_t, pub ifs6_atmfrag_rcvd: crate::u_quad_t, pub ifs6_reass_fail: crate::u_quad_t, pub ifs6_in_mcast: crate::u_quad_t, pub ifs6_out_mcast: crate::u_quad_t, pub ifs6_cantfoward_icmp6: crate::u_quad_t, pub ifs6_addr_expiry_cnt: crate::u_quad_t, pub ifs6_pfx_expiry_cnt: crate::u_quad_t, pub ifs6_defrtr_expiry_cnt: crate::u_quad_t, } pub struct icmp6_ifstat { pub ifs6_in_msg: crate::u_quad_t, pub ifs6_in_error: crate::u_quad_t, pub ifs6_in_dstunreach: crate::u_quad_t, pub ifs6_in_adminprohib: crate::u_quad_t, pub ifs6_in_timeexceed: crate::u_quad_t, pub ifs6_in_paramprob: crate::u_quad_t, pub ifs6_in_pkttoobig: crate::u_quad_t, pub ifs6_in_echo: crate::u_quad_t, pub ifs6_in_echoreply: crate::u_quad_t, pub ifs6_in_routersolicit: crate::u_quad_t, pub ifs6_in_routeradvert: crate::u_quad_t, pub ifs6_in_neighborsolicit: crate::u_quad_t, pub ifs6_in_neighboradvert: crate::u_quad_t, pub ifs6_in_redirect: crate::u_quad_t, pub ifs6_in_mldquery: crate::u_quad_t, pub ifs6_in_mldreport: crate::u_quad_t, pub ifs6_in_mlddone: crate::u_quad_t, pub ifs6_out_msg: crate::u_quad_t, pub ifs6_out_error: crate::u_quad_t, pub ifs6_out_dstunreach: crate::u_quad_t, pub ifs6_out_adminprohib: crate::u_quad_t, pub ifs6_out_timeexceed: crate::u_quad_t, pub ifs6_out_paramprob: crate::u_quad_t, pub ifs6_out_pkttoobig: crate::u_quad_t, pub ifs6_out_echo: crate::u_quad_t, pub ifs6_out_echoreply: crate::u_quad_t, pub ifs6_out_routersolicit: crate::u_quad_t, pub ifs6_out_routeradvert: crate::u_quad_t, pub ifs6_out_neighborsolicit: crate::u_quad_t, pub ifs6_out_neighboradvert: crate::u_quad_t, pub ifs6_out_redirect: crate::u_quad_t, pub ifs6_out_mldquery: crate::u_quad_t, pub ifs6_out_mldreport: crate::u_quad_t, pub ifs6_out_mlddone: crate::u_quad_t, } // mach/host_info.h pub struct host_cpu_load_info { pub cpu_ticks: [crate::natural_t; CPU_STATE_MAX as usize], } // net/if_mib.h pub struct ifmibdata { /// Name of interface pub ifmd_name: [c_char; crate::IFNAMSIZ], /// Number of promiscuous listeners pub ifmd_pcount: c_uint, /// Interface flags pub ifmd_flags: c_uint, /// Instantaneous length of send queue pub ifmd_snd_len: c_uint, /// Maximum length of send queue pub ifmd_snd_maxlen: c_uint, /// Number of drops in send queue pub ifmd_snd_drops: c_uint, /// For future expansion pub ifmd_filler: [c_uint; 4], /// Generic information and statistics pub ifmd_data: if_data64, } pub struct ifs_iso_8802_3 { pub dot3StatsAlignmentErrors: u32, pub dot3StatsFCSErrors: u32, pub dot3StatsSingleCollisionFrames: u32, pub dot3StatsMultipleCollisionFrames: u32, pub dot3StatsSQETestErrors: u32, pub dot3StatsDeferredTransmissions: u32, pub dot3StatsLateCollisions: u32, pub dot3StatsExcessiveCollisions: u32, pub dot3StatsInternalMacTransmitErrors: u32, pub dot3StatsCarrierSenseErrors: u32, pub dot3StatsFrameTooLongs: u32, pub dot3StatsInternalMacReceiveErrors: u32, pub dot3StatsEtherChipSet: u32, pub dot3StatsMissedFrames: u32, pub dot3StatsCollFrequencies: [u32; 16], pub dot3Compliance: u32, } // kern_control.h pub struct ctl_info { pub ctl_id: u32, pub ctl_name: [c_char; MAX_KCTL_NAME], } // sys/proc_info.h pub struct proc_fdinfo { pub proc_fd: i32, pub proc_fdtype: u32, } } s_no_extra_traits! { #[repr(packed(4))] pub struct ifconf { pub ifc_len: c_int, pub ifc_ifcu: __c_anonymous_ifc_ifcu, } #[repr(packed(4))] pub struct kevent { pub ident: crate::uintptr_t, pub filter: i16, pub flags: u16, pub fflags: u32, pub data: intptr_t, pub udata: *mut c_void, } #[repr(packed(4))] pub struct semid_ds { // Note the manpage shows different types than the system header. pub sem_perm: ipc_perm, pub sem_base: i32, pub sem_nsems: c_ushort, pub sem_otime: crate::time_t, pub sem_pad1: i32, pub sem_ctime: crate::time_t, pub sem_pad2: i32, pub sem_pad3: [i32; 4], } #[repr(packed(4))] pub struct shmid_ds { pub shm_perm: ipc_perm, pub shm_segsz: size_t, pub shm_lpid: crate::pid_t, pub shm_cpid: crate::pid_t, pub shm_nattch: crate::shmatt_t, pub shm_atime: crate::time_t, // FIXME(macos): 64-bit wrong align => wrong offset pub shm_dtime: crate::time_t, // FIXME(macos): 64-bit wrong align => wrong offset pub shm_ctime: crate::time_t, // FIXME(macos): 64-bit wrong align => wrong offset // FIXME: 64-bit wrong align => wrong offset: pub shm_internal: *mut c_void, } pub struct proc_threadinfo { pub pth_user_time: u64, pub pth_system_time: u64, pub pth_cpu_usage: i32, pub pth_policy: i32, pub pth_run_state: i32, pub pth_flags: i32, pub pth_sleep_time: i32, pub pth_curpri: i32, pub pth_priority: i32, pub pth_maxpriority: i32, pub pth_name: [c_char; MAXTHREADNAMESIZE], } pub struct statfs { pub f_bsize: u32, pub f_iosize: i32, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: crate::fsid_t, pub f_owner: crate::uid_t, pub f_type: u32, pub f_flags: u32, pub f_fssubtype: u32, pub f_fstypename: [c_char; 16], pub f_mntonname: [c_char; 1024], pub f_mntfromname: [c_char; 1024], pub f_flags_ext: u32, pub f_reserved: [u32; 7], } pub struct dirent { pub d_ino: u64, pub d_seekoff: u64, pub d_reclen: u16, pub d_namlen: u16, pub d_type: u8, pub d_name: [c_char; 1024], } pub struct pthread_rwlock_t { __sig: c_long, __opaque: [u8; __PTHREAD_RWLOCK_SIZE__], } pub struct pthread_mutex_t { __sig: c_long, __opaque: [u8; __PTHREAD_MUTEX_SIZE__], } pub struct pthread_cond_t { __sig: c_long, __opaque: [u8; __PTHREAD_COND_SIZE__], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: crate::sa_family_t, __ss_pad1: [u8; 6], __ss_align: i64, __ss_pad2: [u8; 112], } pub struct utmpx { pub ut_user: [c_char; _UTX_USERSIZE], pub ut_id: [c_char; _UTX_IDSIZE], pub ut_line: [c_char; _UTX_LINESIZE], pub ut_pid: crate::pid_t, pub ut_type: c_short, pub ut_tv: crate::timeval, pub ut_host: [c_char; _UTX_HOSTSIZE], ut_pad: [u32; 16], } pub struct sigevent { pub sigev_notify: c_int, pub sigev_signo: c_int, pub sigev_value: crate::sigval, __unused1: *mut c_void, //actually a function pointer pub sigev_notify_attributes: *mut crate::pthread_attr_t, } pub struct processor_cpu_load_info { pub cpu_ticks: [c_uint; CPU_STATE_MAX as usize], } pub struct processor_basic_info { pub cpu_type: cpu_type_t, pub cpu_subtype: cpu_subtype_t, pub running: crate::boolean_t, pub slot_num: c_int, pub is_master: crate::boolean_t, } pub struct processor_set_basic_info { pub processor_count: c_int, pub default_policy: c_int, } pub struct processor_set_load_info { pub task_count: c_int, pub thread_count: c_int, pub load_average: integer_t, pub mach_factor: integer_t, } pub struct time_value_t { pub seconds: integer_t, pub microseconds: integer_t, } pub struct thread_basic_info { pub user_time: time_value_t, pub system_time: time_value_t, pub cpu_usage: crate::integer_t, pub policy: crate::policy_t, pub run_state: crate::integer_t, pub flags: crate::integer_t, pub suspend_count: crate::integer_t, pub sleep_time: crate::integer_t, } pub struct thread_identifier_info { pub thread_id: u64, pub thread_handle: u64, pub dispatch_qaddr: u64, } pub struct thread_extended_info { pub pth_user_time: u64, pub pth_system_time: u64, pub pth_cpu_usage: i32, pub pth_policy: i32, pub pth_run_state: i32, pub pth_flags: i32, pub pth_sleep_time: i32, pub pth_curpri: i32, pub pth_priority: i32, pub pth_maxpriority: i32, pub pth_name: [c_char; MAXTHREADNAMESIZE], } #[repr(packed(4))] pub struct if_data64 { pub ifi_type: c_uchar, pub ifi_typelen: c_uchar, pub ifi_physical: c_uchar, pub ifi_addrlen: c_uchar, pub ifi_hdrlen: c_uchar, pub ifi_recvquota: c_uchar, pub ifi_xmitquota: c_uchar, pub ifi_unused1: c_uchar, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_baudrate: u64, pub ifi_ipackets: u64, pub ifi_ierrors: u64, pub ifi_opackets: u64, pub ifi_oerrors: u64, pub ifi_collisions: u64, pub ifi_ibytes: u64, pub ifi_obytes: u64, pub ifi_imcasts: u64, pub ifi_omcasts: u64, pub ifi_iqdrops: u64, pub ifi_noproto: u64, pub ifi_recvtiming: u32, pub ifi_xmittiming: u32, #[cfg(target_pointer_width = "32")] pub ifi_lastchange: crate::timeval, #[cfg(not(target_pointer_width = "32"))] pub ifi_lastchange: timeval32, } #[repr(packed(4))] pub struct if_msghdr2 { pub ifm_msglen: c_ushort, pub ifm_version: c_uchar, pub ifm_type: c_uchar, pub ifm_addrs: c_int, pub ifm_flags: c_int, pub ifm_index: c_ushort, pub ifm_snd_len: c_int, pub ifm_snd_maxlen: c_int, pub ifm_snd_drops: c_int, pub ifm_timer: c_int, pub ifm_data: if_data64, } #[repr(packed(8))] pub struct vm_statistics64 { pub free_count: natural_t, pub active_count: natural_t, pub inactive_count: natural_t, pub wire_count: natural_t, pub zero_fill_count: u64, pub reactivations: u64, pub pageins: u64, pub pageouts: u64, pub faults: u64, pub cow_faults: u64, pub lookups: u64, pub hits: u64, pub purges: u64, pub purgeable_count: natural_t, pub speculative_count: natural_t, pub decompressions: u64, pub compressions: u64, pub swapins: u64, pub swapouts: u64, pub compressor_page_count: natural_t, pub throttled_count: natural_t, pub external_page_count: natural_t, pub internal_page_count: natural_t, pub total_uncompressed_pages_in_compressor: u64, } #[repr(packed(4))] pub struct mach_task_basic_info { pub virtual_size: mach_vm_size_t, pub resident_size: mach_vm_size_t, pub resident_size_max: mach_vm_size_t, pub user_time: time_value_t, pub system_time: time_value_t, pub policy: crate::policy_t, pub suspend_count: integer_t, } #[repr(packed(4))] pub struct log2phys { pub l2p_flags: c_uint, pub l2p_contigbytes: off_t, pub l2p_devoffset: off_t, } pub struct os_unfair_lock_s { _os_unfair_lock_opaque: u32, } #[repr(packed(1))] pub struct sockaddr_vm { pub svm_len: c_uchar, pub svm_family: crate::sa_family_t, pub svm_reserved1: c_ushort, pub svm_port: c_uint, pub svm_cid: c_uint, } pub struct ifdevmtu { pub ifdm_current: c_int, pub ifdm_min: c_int, pub ifdm_max: c_int, } pub union __c_anonymous_ifk_data { pub ifk_ptr: *mut c_void, pub ifk_value: c_int, } #[repr(packed(4))] pub struct ifkpi { pub ifk_module_id: c_uint, pub ifk_type: c_uint, pub ifk_data: __c_anonymous_ifk_data, } pub union __c_anonymous_ifr_ifru { pub ifru_addr: crate::sockaddr, pub ifru_dstaddr: crate::sockaddr, pub ifru_broadaddr: crate::sockaddr, pub ifru_flags: c_short, pub ifru_metrics: c_int, pub ifru_mtu: c_int, pub ifru_phys: c_int, pub ifru_media: c_int, pub ifru_intval: c_int, pub ifru_data: *mut c_char, pub ifru_devmtu: ifdevmtu, pub ifru_kpi: ifkpi, pub ifru_wake_flags: u32, pub ifru_route_refcnt: u32, pub ifru_cap: [c_int; 2], pub ifru_functional_type: u32, } pub struct ifreq { pub ifr_name: [c_char; crate::IFNAMSIZ], pub ifr_ifru: __c_anonymous_ifr_ifru, } pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: *mut c_char, pub ifcu_req: *mut ifreq, } pub union __c_anonymous_ifr_ifru6 { pub ifru_addr: crate::sockaddr_in6, pub ifru_dstaddr: crate::sockaddr_in6, pub ifru_flags: c_int, pub ifru_flags6: c_int, pub ifru_metrics: c_int, pub ifru_intval: c_int, pub ifru_data: *mut c_char, pub ifru_lifetime: in6_addrlifetime, pub ifru_stat: in6_ifstat, pub ifru_icmp6stat: icmp6_ifstat, pub ifru_scope_id: [u32; SCOPE6_ID_MAX], } pub struct in6_ifreq { pub ifr_name: [c_char; crate::IFNAMSIZ], pub ifr_ifru: __c_anonymous_ifr_ifru6, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut c_void { self.si_addr } pub unsafe fn si_value(&self) -> crate::sigval { #[repr(C)] struct siginfo_timer { _si_signo: c_int, _si_errno: c_int, _si_code: c_int, _si_pid: crate::pid_t, _si_uid: crate::uid_t, _si_status: c_int, _si_addr: *mut c_void, si_value: crate::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).si_value } pub unsafe fn si_pid(&self) -> crate::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> crate::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> c_int { self.si_status } } s_no_extra_traits! { pub union semun { pub val: c_int, pub buf: *mut semid_ds, pub array: *mut c_ushort, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for semun { fn eq(&self, other: &semun) -> bool { unsafe { self.val == other.val } } } impl Eq for semun {} impl hash::Hash for semun { fn hash(&self, state: &mut H) { unsafe { self.val.hash(state) }; } } } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for ifconf where Self: Copy, { fn eq(&self, other: &Self) -> bool { let len_ptr1 = core::ptr::addr_of!(self.ifc_len); let len_ptr2 = core::ptr::addr_of!(other.ifc_len); let ifcu_ptr1 = core::ptr::addr_of!(self.ifc_ifcu); let ifcu_ptr2 = core::ptr::addr_of!(other.ifc_ifcu); // SAFETY: `ifconf` implements `Copy` so the reads are valid let len1 = unsafe { len_ptr1.read_unaligned() }; let len2 = unsafe { len_ptr2.read_unaligned() }; let ifcu1 = unsafe { ifcu_ptr1.read_unaligned() }; let ifcu2 = unsafe { ifcu_ptr2.read_unaligned() }; len1 == len2 && ifcu1 == ifcu2 } } impl Eq for ifconf {} impl fmt::Debug for ifconf { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifconf").finish_non_exhaustive() } } impl PartialEq for kevent { fn eq(&self, other: &kevent) -> bool { self.ident == other.ident && self.filter == other.filter && self.flags == other.flags && self.fflags == other.fflags && self.data == other.data && self.udata == other.udata } } impl Eq for kevent {} impl fmt::Debug for kevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let ident = self.ident; let filter = self.filter; let flags = self.flags; let fflags = self.fflags; let data = self.data; let udata = self.udata; f.debug_struct("kevent") .field("ident", &ident) .field("filter", &filter) .field("flags", &flags) .field("fflags", &fflags) .field("data", &data) .field("udata", &udata) .finish() } } impl hash::Hash for kevent { fn hash(&self, state: &mut H) { let ident = self.ident; let filter = self.filter; let flags = self.flags; let fflags = self.fflags; let data = self.data; let udata = self.udata; ident.hash(state); filter.hash(state); flags.hash(state); fflags.hash(state); data.hash(state); udata.hash(state); } } impl PartialEq for semid_ds { fn eq(&self, other: &semid_ds) -> bool { let sem_perm = self.sem_perm; let sem_pad3 = self.sem_pad3; let other_sem_perm = other.sem_perm; let other_sem_pad3 = other.sem_pad3; sem_perm == other_sem_perm && self.sem_base == other.sem_base && self.sem_nsems == other.sem_nsems && self.sem_otime == other.sem_otime && self.sem_pad1 == other.sem_pad1 && self.sem_ctime == other.sem_ctime && self.sem_pad2 == other.sem_pad2 && sem_pad3 == other_sem_pad3 } } impl Eq for semid_ds {} impl fmt::Debug for semid_ds { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let sem_perm = self.sem_perm; let sem_base = self.sem_base; let sem_nsems = self.sem_nsems; let sem_otime = self.sem_otime; let sem_pad1 = self.sem_pad1; let sem_ctime = self.sem_ctime; let sem_pad2 = self.sem_pad2; let sem_pad3 = self.sem_pad3; f.debug_struct("semid_ds") .field("sem_perm", &sem_perm) .field("sem_base", &sem_base) .field("sem_nsems", &sem_nsems) .field("sem_otime", &sem_otime) .field("sem_pad1", &sem_pad1) .field("sem_ctime", &sem_ctime) .field("sem_pad2", &sem_pad2) .field("sem_pad3", &sem_pad3) .finish() } } impl hash::Hash for semid_ds { fn hash(&self, state: &mut H) { let sem_perm = self.sem_perm; let sem_base = self.sem_base; let sem_nsems = self.sem_nsems; let sem_otime = self.sem_otime; let sem_pad1 = self.sem_pad1; let sem_ctime = self.sem_ctime; let sem_pad2 = self.sem_pad2; let sem_pad3 = self.sem_pad3; sem_perm.hash(state); sem_base.hash(state); sem_nsems.hash(state); sem_otime.hash(state); sem_pad1.hash(state); sem_ctime.hash(state); sem_pad2.hash(state); sem_pad3.hash(state); } } impl PartialEq for shmid_ds { fn eq(&self, other: &shmid_ds) -> bool { let shm_perm = self.shm_perm; let other_shm_perm = other.shm_perm; shm_perm == other_shm_perm && self.shm_segsz == other.shm_segsz && self.shm_lpid == other.shm_lpid && self.shm_cpid == other.shm_cpid && self.shm_nattch == other.shm_nattch && self.shm_atime == other.shm_atime && self.shm_dtime == other.shm_dtime && self.shm_ctime == other.shm_ctime && self.shm_internal == other.shm_internal } } impl Eq for shmid_ds {} impl fmt::Debug for shmid_ds { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let shm_perm = self.shm_perm; let shm_segsz = self.shm_segsz; let shm_lpid = self.shm_lpid; let shm_cpid = self.shm_cpid; let shm_nattch = self.shm_nattch; let shm_atime = self.shm_atime; let shm_dtime = self.shm_dtime; let shm_ctime = self.shm_ctime; let shm_internal = self.shm_internal; f.debug_struct("shmid_ds") .field("shm_perm", &shm_perm) .field("shm_segsz", &shm_segsz) .field("shm_lpid", &shm_lpid) .field("shm_cpid", &shm_cpid) .field("shm_nattch", &shm_nattch) .field("shm_atime", &shm_atime) .field("shm_dtime", &shm_dtime) .field("shm_ctime", &shm_ctime) .field("shm_internal", &shm_internal) .finish() } } impl hash::Hash for shmid_ds { fn hash(&self, state: &mut H) { let shm_perm = self.shm_perm; let shm_segsz = self.shm_segsz; let shm_lpid = self.shm_lpid; let shm_cpid = self.shm_cpid; let shm_nattch = self.shm_nattch; let shm_atime = self.shm_atime; let shm_dtime = self.shm_dtime; let shm_ctime = self.shm_ctime; let shm_internal = self.shm_internal; shm_perm.hash(state); shm_segsz.hash(state); shm_lpid.hash(state); shm_cpid.hash(state); shm_nattch.hash(state); shm_atime.hash(state); shm_dtime.hash(state); shm_ctime.hash(state); shm_internal.hash(state); } } impl PartialEq for proc_threadinfo { fn eq(&self, other: &proc_threadinfo) -> bool { self.pth_user_time == other.pth_user_time && self.pth_system_time == other.pth_system_time && self.pth_cpu_usage == other.pth_cpu_usage && self.pth_policy == other.pth_policy && self.pth_run_state == other.pth_run_state && self.pth_flags == other.pth_flags && self.pth_sleep_time == other.pth_sleep_time && self.pth_curpri == other.pth_curpri && self.pth_priority == other.pth_priority && self.pth_maxpriority == other.pth_maxpriority && self .pth_name .iter() .zip(other.pth_name.iter()) .all(|(a, b)| a == b) } } impl Eq for proc_threadinfo {} impl fmt::Debug for proc_threadinfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("proc_threadinfo") .field("pth_user_time", &self.pth_user_time) .field("pth_system_time", &self.pth_system_time) .field("pth_cpu_usage", &self.pth_cpu_usage) .field("pth_policy", &self.pth_policy) .field("pth_run_state", &self.pth_run_state) .field("pth_flags", &self.pth_flags) .field("pth_sleep_time", &self.pth_sleep_time) .field("pth_curpri", &self.pth_curpri) .field("pth_priority", &self.pth_priority) .field("pth_maxpriority", &self.pth_maxpriority) // FIXME(debug): .field("pth_name", &self.pth_name) .finish() } } impl hash::Hash for proc_threadinfo { fn hash(&self, state: &mut H) { self.pth_user_time.hash(state); self.pth_system_time.hash(state); self.pth_cpu_usage.hash(state); self.pth_policy.hash(state); self.pth_run_state.hash(state); self.pth_flags.hash(state); self.pth_sleep_time.hash(state); self.pth_curpri.hash(state); self.pth_priority.hash(state); self.pth_maxpriority.hash(state); self.pth_name.hash(state); } } impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_fsid == other.f_fsid && self.f_owner == other.f_owner && self.f_flags == other.f_flags && self.f_fssubtype == other.f_fssubtype && self.f_fstypename == other.f_fstypename && self.f_type == other.f_type && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a, b)| a == b) && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a, b)| a == b) && self.f_reserved == other.f_reserved } } impl Eq for statfs {} impl fmt::Debug for statfs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_fsid", &self.f_fsid) .field("f_owner", &self.f_owner) .field("f_flags", &self.f_flags) .field("f_fssubtype", &self.f_fssubtype) .field("f_fstypename", &self.f_fstypename) .field("f_type", &self.f_type) // FIXME(debug): .field("f_mntonname", &self.f_mntonname) // FIXME(debug): .field("f_mntfromname", &self.f_mntfromname) .field("f_reserved", &self.f_reserved) .finish() } } impl hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_fsid.hash(state); self.f_owner.hash(state); self.f_flags.hash(state); self.f_fssubtype.hash(state); self.f_fstypename.hash(state); self.f_type.hash(state); self.f_mntonname.hash(state); self.f_mntfromname.hash(state); self.f_reserved.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_seekoff == other.d_seekoff && self.d_reclen == other.d_reclen && self.d_namlen == other.d_namlen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a, b)| a == b) } } impl Eq for dirent {} impl fmt::Debug for dirent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_seekoff", &self.d_seekoff) .field("d_reclen", &self.d_reclen) .field("d_namlen", &self.d_namlen) .field("d_type", &self.d_type) // FIXME(debug): .field("d_name", &self.d_name) .finish() } } impl hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_seekoff.hash(state); self.d_reclen.hash(state); self.d_namlen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { self.__sig == other.__sig && self .__opaque .iter() .zip(other.__opaque.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_rwlock_t {} impl fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_rwlock_t") .field("__sig", &self.__sig) // FIXME(debug): .field("__opaque", &self.__opaque) .finish() } } impl hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { self.__sig == other.__sig && self .__opaque .iter() .zip(other.__opaque.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_mutex_t {} impl fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_mutex_t") .field("__sig", &self.__sig) // FIXME(debug): .field("__opaque", &self.__opaque) .finish() } } impl hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.__sig == other.__sig && self .__opaque .iter() .zip(other.__opaque.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_cond_t {} impl fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_cond_t") .field("__sig", &self.__sig) // FIXME(debug): .field("__opaque", &self.__opaque) .finish() } } impl hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self .__ss_pad1 .iter() .zip(other.__ss_pad1.iter()) .all(|(a, b)| a == b) && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_align", &self.__ss_align) // FIXME(debug): .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_user .iter() .zip(other.ut_user.iter()) .all(|(a, b)| a == b) && self.ut_id == other.ut_id && self.ut_line == other.ut_line && self.ut_pid == other.ut_pid && self.ut_type == other.ut_type && self.ut_tv == other.ut_tv && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a, b)| a == b) && self.ut_pad == other.ut_pad } } impl Eq for utmpx {} impl fmt::Debug for utmpx { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("utmpx") // FIXME(debug): .field("ut_user", &self.ut_user) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) .field("ut_pid", &self.ut_pid) .field("ut_type", &self.ut_type) .field("ut_tv", &self.ut_tv) // FIXME(debug): .field("ut_host", &self.ut_host) .field("ut_pad", &self.ut_pad) .finish() } } impl hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_user.hash(state); self.ut_id.hash(state); self.ut_line.hash(state); self.ut_pid.hash(state); self.ut_type.hash(state); self.ut_tv.hash(state); self.ut_host.hash(state); self.ut_pad.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl fmt::Debug for sigevent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.sigev_notify_attributes.hash(state); } } impl PartialEq for processor_cpu_load_info { fn eq(&self, other: &processor_cpu_load_info) -> bool { self.cpu_ticks == other.cpu_ticks } } impl Eq for processor_cpu_load_info {} impl fmt::Debug for processor_cpu_load_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("processor_cpu_load_info") .field("cpu_ticks", &self.cpu_ticks) .finish() } } impl hash::Hash for processor_cpu_load_info { fn hash(&self, state: &mut H) { self.cpu_ticks.hash(state); } } impl PartialEq for processor_basic_info { fn eq(&self, other: &processor_basic_info) -> bool { self.cpu_type == other.cpu_type && self.cpu_subtype == other.cpu_subtype && self.running == other.running && self.slot_num == other.slot_num && self.is_master == other.is_master } } impl Eq for processor_basic_info {} impl fmt::Debug for processor_basic_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("processor_basic_info") .field("cpu_type", &self.cpu_type) .field("cpu_subtype", &self.cpu_subtype) .field("running", &self.running) .field("slot_num", &self.slot_num) .field("is_master", &self.is_master) .finish() } } impl hash::Hash for processor_basic_info { fn hash(&self, state: &mut H) { self.cpu_type.hash(state); self.cpu_subtype.hash(state); self.running.hash(state); self.slot_num.hash(state); self.is_master.hash(state); } } impl PartialEq for processor_set_basic_info { fn eq(&self, other: &processor_set_basic_info) -> bool { self.processor_count == other.processor_count && self.default_policy == other.default_policy } } impl Eq for processor_set_basic_info {} impl fmt::Debug for processor_set_basic_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("processor_set_basic_info") .field("processor_count", &self.processor_count) .field("default_policy", &self.default_policy) .finish() } } impl hash::Hash for processor_set_basic_info { fn hash(&self, state: &mut H) { self.processor_count.hash(state); self.default_policy.hash(state); } } impl PartialEq for processor_set_load_info { fn eq(&self, other: &processor_set_load_info) -> bool { self.task_count == other.task_count && self.thread_count == other.thread_count && self.load_average == other.load_average && self.mach_factor == other.mach_factor } } impl Eq for processor_set_load_info {} impl fmt::Debug for processor_set_load_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("processor_set_load_info") .field("task_count", &self.task_count) .field("thread_count", &self.thread_count) .field("load_average", &self.load_average) .field("mach_factor", &self.mach_factor) .finish() } } impl hash::Hash for processor_set_load_info { fn hash(&self, state: &mut H) { self.task_count.hash(state); self.thread_count.hash(state); self.load_average.hash(state); self.mach_factor.hash(state); } } impl PartialEq for time_value_t { fn eq(&self, other: &time_value_t) -> bool { self.seconds == other.seconds && self.microseconds == other.microseconds } } impl Eq for time_value_t {} impl fmt::Debug for time_value_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("time_value_t") .field("seconds", &self.seconds) .field("microseconds", &self.microseconds) .finish() } } impl hash::Hash for time_value_t { fn hash(&self, state: &mut H) { self.seconds.hash(state); self.microseconds.hash(state); } } impl PartialEq for thread_basic_info { fn eq(&self, other: &thread_basic_info) -> bool { self.user_time == other.user_time && self.system_time == other.system_time && self.cpu_usage == other.cpu_usage && self.policy == other.policy && self.run_state == other.run_state && self.flags == other.flags && self.suspend_count == other.suspend_count && self.sleep_time == other.sleep_time } } impl Eq for thread_basic_info {} impl fmt::Debug for thread_basic_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("thread_basic_info") .field("user_time", &self.user_time) .field("system_time", &self.system_time) .field("cpu_usage", &self.cpu_usage) .field("policy", &self.policy) .field("run_state", &self.run_state) .field("flags", &self.flags) .field("suspend_count", &self.suspend_count) .field("sleep_time", &self.sleep_time) .finish() } } impl hash::Hash for thread_basic_info { fn hash(&self, state: &mut H) { self.user_time.hash(state); self.system_time.hash(state); self.cpu_usage.hash(state); self.policy.hash(state); self.run_state.hash(state); self.flags.hash(state); self.suspend_count.hash(state); self.sleep_time.hash(state); } } impl PartialEq for thread_extended_info { fn eq(&self, other: &thread_extended_info) -> bool { self.pth_user_time == other.pth_user_time && self.pth_system_time == other.pth_system_time && self.pth_cpu_usage == other.pth_cpu_usage && self.pth_policy == other.pth_policy && self.pth_run_state == other.pth_run_state && self.pth_flags == other.pth_flags && self.pth_sleep_time == other.pth_sleep_time && self.pth_curpri == other.pth_curpri && self.pth_priority == other.pth_priority && self.pth_maxpriority == other.pth_maxpriority && self .pth_name .iter() .zip(other.pth_name.iter()) .all(|(a, b)| a == b) } } impl Eq for thread_extended_info {} impl fmt::Debug for thread_extended_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("proc_threadinfo") .field("pth_user_time", &self.pth_user_time) .field("pth_system_time", &self.pth_system_time) .field("pth_cpu_usage", &self.pth_cpu_usage) .field("pth_policy", &self.pth_policy) .field("pth_run_state", &self.pth_run_state) .field("pth_flags", &self.pth_flags) .field("pth_sleep_time", &self.pth_sleep_time) .field("pth_curpri", &self.pth_curpri) .field("pth_priority", &self.pth_priority) .field("pth_maxpriority", &self.pth_maxpriority) // FIXME(debug): .field("pth_name", &self.pth_name) .finish() } } impl hash::Hash for thread_extended_info { fn hash(&self, state: &mut H) { self.pth_user_time.hash(state); self.pth_system_time.hash(state); self.pth_cpu_usage.hash(state); self.pth_policy.hash(state); self.pth_run_state.hash(state); self.pth_flags.hash(state); self.pth_sleep_time.hash(state); self.pth_curpri.hash(state); self.pth_priority.hash(state); self.pth_maxpriority.hash(state); self.pth_name.hash(state); } } impl PartialEq for thread_identifier_info { fn eq(&self, other: &thread_identifier_info) -> bool { self.thread_id == other.thread_id && self.thread_handle == other.thread_handle && self.dispatch_qaddr == other.dispatch_qaddr } } impl Eq for thread_identifier_info {} impl fmt::Debug for thread_identifier_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("thread_identifier_info") .field("thread_id", &self.thread_id) .field("thread_handle", &self.thread_handle) .field("dispatch_qaddr", &self.dispatch_qaddr) .finish() } } impl hash::Hash for thread_identifier_info { fn hash(&self, state: &mut H) { self.thread_id.hash(state); self.thread_handle.hash(state); self.dispatch_qaddr.hash(state); } } impl PartialEq for if_data64 { fn eq(&self, other: &if_data64) -> bool { self.ifi_type == other.ifi_type && self.ifi_typelen == other.ifi_typelen && self.ifi_physical == other.ifi_physical && self.ifi_addrlen == other.ifi_addrlen && self.ifi_hdrlen == other.ifi_hdrlen && self.ifi_recvquota == other.ifi_recvquota && self.ifi_xmitquota == other.ifi_xmitquota && self.ifi_unused1 == other.ifi_unused1 && self.ifi_mtu == other.ifi_mtu && self.ifi_metric == other.ifi_metric && self.ifi_baudrate == other.ifi_baudrate && self.ifi_ipackets == other.ifi_ipackets && self.ifi_ierrors == other.ifi_ierrors && self.ifi_opackets == other.ifi_opackets && self.ifi_oerrors == other.ifi_oerrors && self.ifi_collisions == other.ifi_collisions && self.ifi_ibytes == other.ifi_ibytes && self.ifi_obytes == other.ifi_obytes && self.ifi_imcasts == other.ifi_imcasts && self.ifi_omcasts == other.ifi_omcasts && self.ifi_iqdrops == other.ifi_iqdrops && self.ifi_noproto == other.ifi_noproto && self.ifi_recvtiming == other.ifi_recvtiming && self.ifi_xmittiming == other.ifi_xmittiming && self.ifi_lastchange == other.ifi_lastchange } } impl Eq for if_data64 {} impl fmt::Debug for if_data64 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let ifi_type = self.ifi_type; let ifi_typelen = self.ifi_typelen; let ifi_physical = self.ifi_physical; let ifi_addrlen = self.ifi_addrlen; let ifi_hdrlen = self.ifi_hdrlen; let ifi_recvquota = self.ifi_recvquota; let ifi_xmitquota = self.ifi_xmitquota; let ifi_unused1 = self.ifi_unused1; let ifi_mtu = self.ifi_mtu; let ifi_metric = self.ifi_metric; let ifi_baudrate = self.ifi_baudrate; let ifi_ipackets = self.ifi_ipackets; let ifi_ierrors = self.ifi_ierrors; let ifi_opackets = self.ifi_opackets; let ifi_oerrors = self.ifi_oerrors; let ifi_collisions = self.ifi_collisions; let ifi_ibytes = self.ifi_ibytes; let ifi_obytes = self.ifi_obytes; let ifi_imcasts = self.ifi_imcasts; let ifi_omcasts = self.ifi_omcasts; let ifi_iqdrops = self.ifi_iqdrops; let ifi_noproto = self.ifi_noproto; let ifi_recvtiming = self.ifi_recvtiming; let ifi_xmittiming = self.ifi_xmittiming; let ifi_lastchange = self.ifi_lastchange; f.debug_struct("if_data64") .field("ifi_type", &ifi_type) .field("ifi_typelen", &ifi_typelen) .field("ifi_physical", &ifi_physical) .field("ifi_addrlen", &ifi_addrlen) .field("ifi_hdrlen", &ifi_hdrlen) .field("ifi_recvquota", &ifi_recvquota) .field("ifi_xmitquota", &ifi_xmitquota) .field("ifi_unused1", &ifi_unused1) .field("ifi_mtu", &ifi_mtu) .field("ifi_metric", &ifi_metric) .field("ifi_baudrate", &ifi_baudrate) .field("ifi_ipackets", &ifi_ipackets) .field("ifi_ierrors", &ifi_ierrors) .field("ifi_opackets", &ifi_opackets) .field("ifi_oerrors", &ifi_oerrors) .field("ifi_collisions", &ifi_collisions) .field("ifi_ibytes", &ifi_ibytes) .field("ifi_obytes", &ifi_obytes) .field("ifi_imcasts", &ifi_imcasts) .field("ifi_omcasts", &ifi_omcasts) .field("ifi_iqdrops", &ifi_iqdrops) .field("ifi_noproto", &ifi_noproto) .field("ifi_recvtiming", &ifi_recvtiming) .field("ifi_xmittiming", &ifi_xmittiming) .field("ifi_lastchange", &ifi_lastchange) .finish() } } impl hash::Hash for if_data64 { fn hash(&self, state: &mut H) { let ifi_type = self.ifi_type; let ifi_typelen = self.ifi_typelen; let ifi_physical = self.ifi_physical; let ifi_addrlen = self.ifi_addrlen; let ifi_hdrlen = self.ifi_hdrlen; let ifi_recvquota = self.ifi_recvquota; let ifi_xmitquota = self.ifi_xmitquota; let ifi_unused1 = self.ifi_unused1; let ifi_mtu = self.ifi_mtu; let ifi_metric = self.ifi_metric; let ifi_baudrate = self.ifi_baudrate; let ifi_ipackets = self.ifi_ipackets; let ifi_ierrors = self.ifi_ierrors; let ifi_opackets = self.ifi_opackets; let ifi_oerrors = self.ifi_oerrors; let ifi_collisions = self.ifi_collisions; let ifi_ibytes = self.ifi_ibytes; let ifi_obytes = self.ifi_obytes; let ifi_imcasts = self.ifi_imcasts; let ifi_omcasts = self.ifi_omcasts; let ifi_iqdrops = self.ifi_iqdrops; let ifi_noproto = self.ifi_noproto; let ifi_recvtiming = self.ifi_recvtiming; let ifi_xmittiming = self.ifi_xmittiming; let ifi_lastchange = self.ifi_lastchange; ifi_type.hash(state); ifi_typelen.hash(state); ifi_physical.hash(state); ifi_addrlen.hash(state); ifi_hdrlen.hash(state); ifi_recvquota.hash(state); ifi_xmitquota.hash(state); ifi_unused1.hash(state); ifi_mtu.hash(state); ifi_metric.hash(state); ifi_baudrate.hash(state); ifi_ipackets.hash(state); ifi_ierrors.hash(state); ifi_opackets.hash(state); ifi_oerrors.hash(state); ifi_collisions.hash(state); ifi_ibytes.hash(state); ifi_obytes.hash(state); ifi_imcasts.hash(state); ifi_omcasts.hash(state); ifi_iqdrops.hash(state); ifi_noproto.hash(state); ifi_recvtiming.hash(state); ifi_xmittiming.hash(state); ifi_lastchange.hash(state); } } impl PartialEq for if_msghdr2 { fn eq(&self, other: &if_msghdr2) -> bool { self.ifm_msglen == other.ifm_msglen && self.ifm_version == other.ifm_version && self.ifm_type == other.ifm_type && self.ifm_addrs == other.ifm_addrs && self.ifm_flags == other.ifm_flags && self.ifm_index == other.ifm_index && self.ifm_snd_len == other.ifm_snd_len && self.ifm_snd_maxlen == other.ifm_snd_maxlen && self.ifm_snd_drops == other.ifm_snd_drops && self.ifm_timer == other.ifm_timer && self.ifm_data == other.ifm_data } } impl Eq for if_msghdr2 {} impl fmt::Debug for if_msghdr2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let ifm_msglen = self.ifm_msglen; let ifm_version = self.ifm_version; let ifm_type = self.ifm_type; let ifm_addrs = self.ifm_addrs; let ifm_flags = self.ifm_flags; let ifm_index = self.ifm_index; let ifm_snd_len = self.ifm_snd_len; let ifm_snd_maxlen = self.ifm_snd_maxlen; let ifm_snd_drops = self.ifm_snd_drops; let ifm_timer = self.ifm_timer; let ifm_data = self.ifm_data; f.debug_struct("if_msghdr2") .field("ifm_msglen", &ifm_msglen) .field("ifm_version", &ifm_version) .field("ifm_type", &ifm_type) .field("ifm_addrs", &ifm_addrs) .field("ifm_flags", &ifm_flags) .field("ifm_index", &ifm_index) .field("ifm_snd_len", &ifm_snd_len) .field("ifm_snd_maxlen", &ifm_snd_maxlen) .field("ifm_snd_drops", &ifm_snd_drops) .field("ifm_timer", &ifm_timer) .field("ifm_data", &ifm_data) .finish() } } impl hash::Hash for if_msghdr2 { fn hash(&self, state: &mut H) { let ifm_msglen = self.ifm_msglen; let ifm_version = self.ifm_version; let ifm_type = self.ifm_type; let ifm_addrs = self.ifm_addrs; let ifm_flags = self.ifm_flags; let ifm_index = self.ifm_index; let ifm_snd_len = self.ifm_snd_len; let ifm_snd_maxlen = self.ifm_snd_maxlen; let ifm_snd_drops = self.ifm_snd_drops; let ifm_timer = self.ifm_timer; let ifm_data = self.ifm_data; ifm_msglen.hash(state); ifm_version.hash(state); ifm_type.hash(state); ifm_addrs.hash(state); ifm_flags.hash(state); ifm_index.hash(state); ifm_snd_len.hash(state); ifm_snd_maxlen.hash(state); ifm_snd_drops.hash(state); ifm_timer.hash(state); ifm_data.hash(state); } } impl PartialEq for vm_statistics64 { fn eq(&self, other: &vm_statistics64) -> bool { // Otherwise rustfmt crashes... let total_uncompressed = self.total_uncompressed_pages_in_compressor; self.free_count == other.free_count && self.active_count == other.active_count && self.inactive_count == other.inactive_count && self.wire_count == other.wire_count && self.zero_fill_count == other.zero_fill_count && self.reactivations == other.reactivations && self.pageins == other.pageins && self.pageouts == other.pageouts && self.faults == other.faults && self.cow_faults == other.cow_faults && self.lookups == other.lookups && self.hits == other.hits && self.purges == other.purges && self.purgeable_count == other.purgeable_count && self.speculative_count == other.speculative_count && self.decompressions == other.decompressions && self.compressions == other.compressions && self.swapins == other.swapins && self.swapouts == other.swapouts && self.compressor_page_count == other.compressor_page_count && self.throttled_count == other.throttled_count && self.external_page_count == other.external_page_count && self.internal_page_count == other.internal_page_count && total_uncompressed == other.total_uncompressed_pages_in_compressor } } impl Eq for vm_statistics64 {} impl fmt::Debug for vm_statistics64 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let free_count = self.free_count; let active_count = self.active_count; let inactive_count = self.inactive_count; let wire_count = self.wire_count; let zero_fill_count = self.zero_fill_count; let reactivations = self.reactivations; let pageins = self.pageins; let pageouts = self.pageouts; let faults = self.faults; let cow_faults = self.cow_faults; let lookups = self.lookups; let hits = self.hits; let purges = self.purges; let purgeable_count = self.purgeable_count; let speculative_count = self.speculative_count; let decompressions = self.decompressions; let compressions = self.compressions; let swapins = self.swapins; let swapouts = self.swapouts; let compressor_page_count = self.compressor_page_count; let throttled_count = self.throttled_count; let external_page_count = self.external_page_count; let internal_page_count = self.internal_page_count; // Otherwise rustfmt crashes... let total_uncompressed = self.total_uncompressed_pages_in_compressor; f.debug_struct("vm_statistics64") .field("free_count", &free_count) .field("active_count", &active_count) .field("inactive_count", &inactive_count) .field("wire_count", &wire_count) .field("zero_fill_count", &zero_fill_count) .field("reactivations", &reactivations) .field("pageins", &pageins) .field("pageouts", &pageouts) .field("faults", &faults) .field("cow_faults", &cow_faults) .field("lookups", &lookups) .field("hits", &hits) .field("purges", &purges) .field("purgeable_count", &purgeable_count) .field("speculative_count", &speculative_count) .field("decompressions", &decompressions) .field("compressions", &compressions) .field("swapins", &swapins) .field("swapouts", &swapouts) .field("compressor_page_count", &compressor_page_count) .field("throttled_count", &throttled_count) .field("external_page_count", &external_page_count) .field("internal_page_count", &internal_page_count) .field( "total_uncompressed_pages_in_compressor", &total_uncompressed, ) .finish() } } impl hash::Hash for vm_statistics64 { fn hash(&self, state: &mut H) { let free_count = self.free_count; let active_count = self.active_count; let inactive_count = self.inactive_count; let wire_count = self.wire_count; let zero_fill_count = self.zero_fill_count; let reactivations = self.reactivations; let pageins = self.pageins; let pageouts = self.pageouts; let faults = self.faults; let cow_faults = self.cow_faults; let lookups = self.lookups; let hits = self.hits; let purges = self.purges; let purgeable_count = self.purgeable_count; let speculative_count = self.speculative_count; let decompressions = self.decompressions; let compressions = self.compressions; let swapins = self.swapins; let swapouts = self.swapouts; let compressor_page_count = self.compressor_page_count; let throttled_count = self.throttled_count; let external_page_count = self.external_page_count; let internal_page_count = self.internal_page_count; // Otherwise rustfmt crashes... let total_uncompressed = self.total_uncompressed_pages_in_compressor; free_count.hash(state); active_count.hash(state); inactive_count.hash(state); wire_count.hash(state); zero_fill_count.hash(state); reactivations.hash(state); pageins.hash(state); pageouts.hash(state); faults.hash(state); cow_faults.hash(state); lookups.hash(state); hits.hash(state); purges.hash(state); purgeable_count.hash(state); speculative_count.hash(state); decompressions.hash(state); compressions.hash(state); swapins.hash(state); swapouts.hash(state); compressor_page_count.hash(state); throttled_count.hash(state); external_page_count.hash(state); internal_page_count.hash(state); total_uncompressed.hash(state); } } impl PartialEq for mach_task_basic_info { fn eq(&self, other: &mach_task_basic_info) -> bool { self.virtual_size == other.virtual_size && self.resident_size == other.resident_size && self.resident_size_max == other.resident_size_max && self.user_time == other.user_time && self.system_time == other.system_time && self.policy == other.policy && self.suspend_count == other.suspend_count } } impl Eq for mach_task_basic_info {} impl fmt::Debug for mach_task_basic_info { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let virtual_size = self.virtual_size; let resident_size = self.resident_size; let resident_size_max = self.resident_size_max; let user_time = self.user_time; let system_time = self.system_time; let policy = self.policy; let suspend_count = self.suspend_count; f.debug_struct("mach_task_basic_info") .field("virtual_size", &virtual_size) .field("resident_size", &resident_size) .field("resident_size_max", &resident_size_max) .field("user_time", &user_time) .field("system_time", &system_time) .field("policy", &policy) .field("suspend_count", &suspend_count) .finish() } } impl hash::Hash for mach_task_basic_info { fn hash(&self, state: &mut H) { let virtual_size = self.virtual_size; let resident_size = self.resident_size; let resident_size_max = self.resident_size_max; let user_time = self.user_time; let system_time = self.system_time; let policy = self.policy; let suspend_count = self.suspend_count; virtual_size.hash(state); resident_size.hash(state); resident_size_max.hash(state); user_time.hash(state); system_time.hash(state); policy.hash(state); suspend_count.hash(state); } } impl PartialEq for log2phys { fn eq(&self, other: &log2phys) -> bool { self.l2p_flags == other.l2p_flags && self.l2p_contigbytes == other.l2p_contigbytes && self.l2p_devoffset == other.l2p_devoffset } } impl Eq for log2phys {} impl fmt::Debug for log2phys { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let l2p_flags = self.l2p_flags; let l2p_contigbytes = self.l2p_contigbytes; let l2p_devoffset = self.l2p_devoffset; f.debug_struct("log2phys") .field("l2p_flags", &l2p_flags) .field("l2p_contigbytes", &l2p_contigbytes) .field("l2p_devoffset", &l2p_devoffset) .finish() } } impl hash::Hash for log2phys { fn hash(&self, state: &mut H) { let l2p_flags = self.l2p_flags; let l2p_contigbytes = self.l2p_contigbytes; let l2p_devoffset = self.l2p_devoffset; l2p_flags.hash(state); l2p_contigbytes.hash(state); l2p_devoffset.hash(state); } } impl PartialEq for os_unfair_lock { fn eq(&self, other: &os_unfair_lock) -> bool { self._os_unfair_lock_opaque == other._os_unfair_lock_opaque } } impl Eq for os_unfair_lock {} impl fmt::Debug for os_unfair_lock { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("os_unfair_lock") .field("_os_unfair_lock_opaque", &self._os_unfair_lock_opaque) .finish() } } impl hash::Hash for os_unfair_lock { fn hash(&self, state: &mut H) { self._os_unfair_lock_opaque.hash(state); } } impl PartialEq for sockaddr_vm { fn eq(&self, other: &sockaddr_vm) -> bool { self.svm_len == other.svm_len && self.svm_family == other.svm_family && self.svm_reserved1 == other.svm_reserved1 && self.svm_port == other.svm_port && self.svm_cid == other.svm_cid } } impl Eq for sockaddr_vm {} impl fmt::Debug for sockaddr_vm { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let svm_len = self.svm_len; let svm_family = self.svm_family; let svm_reserved1 = self.svm_reserved1; let svm_port = self.svm_port; let svm_cid = self.svm_cid; f.debug_struct("sockaddr_vm") .field("svm_len", &svm_len) .field("svm_family", &svm_family) .field("svm_reserved1", &svm_reserved1) .field("svm_port", &svm_port) .field("svm_cid", &svm_cid) .finish() } } impl hash::Hash for sockaddr_vm { fn hash(&self, state: &mut H) { let svm_len = self.svm_len; let svm_family = self.svm_family; let svm_reserved1 = self.svm_reserved1; let svm_port = self.svm_port; let svm_cid = self.svm_cid; svm_len.hash(state); svm_family.hash(state); svm_reserved1.hash(state); svm_port.hash(state); svm_cid.hash(state); } } impl PartialEq for ifdevmtu { fn eq(&self, other: &ifdevmtu) -> bool { self.ifdm_current == other.ifdm_current && self.ifdm_min == other.ifdm_min && self.ifdm_max == other.ifdm_max } } impl Eq for ifdevmtu {} impl fmt::Debug for ifdevmtu { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifdevmtu") .field("ifdm_current", &self.ifdm_current) .field("ifdm_min", &self.ifdm_min) .field("ifdm_max", &self.ifdm_max) .finish() } } impl hash::Hash for ifdevmtu { fn hash(&self, state: &mut H) { self.ifdm_current.hash(state); self.ifdm_min.hash(state); self.ifdm_max.hash(state); } } impl PartialEq for __c_anonymous_ifk_data { fn eq(&self, other: &__c_anonymous_ifk_data) -> bool { unsafe { self.ifk_ptr == other.ifk_ptr && self.ifk_value == other.ifk_value } } } impl Eq for __c_anonymous_ifk_data {} impl hash::Hash for __c_anonymous_ifk_data { fn hash(&self, state: &mut H) { unsafe { self.ifk_ptr.hash(state); self.ifk_value.hash(state); } } } impl PartialEq for ifkpi { fn eq(&self, other: &ifkpi) -> bool { self.ifk_module_id == other.ifk_module_id && self.ifk_type == other.ifk_type } } impl Eq for ifkpi {} impl fmt::Debug for ifkpi { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifkpi") .field("ifk_module_id", &self.ifk_module_id) .field("ifk_type", &self.ifk_type) .finish() } } impl hash::Hash for ifkpi { fn hash(&self, state: &mut H) { self.ifk_module_id.hash(state); self.ifk_type.hash(state); } } impl PartialEq for __c_anonymous_ifr_ifru { fn eq(&self, other: &__c_anonymous_ifr_ifru) -> bool { unsafe { self.ifru_addr == other.ifru_addr && self.ifru_dstaddr == other.ifru_dstaddr && self.ifru_broadaddr == other.ifru_broadaddr && self.ifru_flags == other.ifru_flags && self.ifru_metrics == other.ifru_metrics && self.ifru_mtu == other.ifru_mtu && self.ifru_phys == other.ifru_phys && self.ifru_media == other.ifru_media && self.ifru_intval == other.ifru_intval && self.ifru_data == other.ifru_data && self.ifru_devmtu == other.ifru_devmtu && self.ifru_kpi == other.ifru_kpi && self.ifru_wake_flags == other.ifru_wake_flags && self.ifru_route_refcnt == other.ifru_route_refcnt && self .ifru_cap .iter() .zip(other.ifru_cap.iter()) .all(|(a, b)| a == b) && self.ifru_functional_type == other.ifru_functional_type } } } impl Eq for __c_anonymous_ifr_ifru {} impl hash::Hash for __c_anonymous_ifr_ifru { fn hash(&self, state: &mut H) { unsafe { self.ifru_addr.hash(state); self.ifru_dstaddr.hash(state); self.ifru_broadaddr.hash(state); self.ifru_flags.hash(state); self.ifru_metrics.hash(state); self.ifru_mtu.hash(state); self.ifru_phys.hash(state); self.ifru_media.hash(state); self.ifru_intval.hash(state); self.ifru_data.hash(state); self.ifru_devmtu.hash(state); self.ifru_kpi.hash(state); self.ifru_wake_flags.hash(state); self.ifru_route_refcnt.hash(state); self.ifru_cap.hash(state); self.ifru_functional_type.hash(state); } } } impl PartialEq for ifreq { fn eq(&self, other: &ifreq) -> bool { self.ifr_name == other.ifr_name && self.ifr_ifru == other.ifr_ifru } } impl Eq for ifreq {} impl fmt::Debug for ifreq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } impl hash::Hash for ifreq { fn hash(&self, state: &mut H) { self.ifr_name.hash(state); self.ifr_ifru.hash(state); } } impl Eq for __c_anonymous_ifc_ifcu {} impl PartialEq for __c_anonymous_ifc_ifcu { fn eq(&self, other: &__c_anonymous_ifc_ifcu) -> bool { unsafe { self.ifcu_buf == other.ifcu_buf && self.ifcu_req == other.ifcu_req } } } impl hash::Hash for __c_anonymous_ifc_ifcu { fn hash(&self, state: &mut H) { unsafe { self.ifcu_buf.hash(state) }; unsafe { self.ifcu_req.hash(state) }; } } impl PartialEq for __c_anonymous_ifr_ifru6 { fn eq(&self, other: &__c_anonymous_ifr_ifru6) -> bool { unsafe { self.ifru_addr == other.ifru_addr && self.ifru_dstaddr == other.ifru_dstaddr && self.ifru_flags == other.ifru_flags && self.ifru_flags6 == other.ifru_flags6 && self.ifru_metrics == other.ifru_metrics && self.ifru_intval == other.ifru_intval && self.ifru_data == other.ifru_data && self .ifru_scope_id .iter() .zip(other.ifru_scope_id.iter()) .all(|(a, b)| a == b) } } } impl Eq for __c_anonymous_ifr_ifru6 {} impl hash::Hash for __c_anonymous_ifr_ifru6 { fn hash(&self, state: &mut H) { unsafe { self.ifru_addr.hash(state); self.ifru_dstaddr.hash(state); self.ifru_flags.hash(state); self.ifru_flags6.hash(state); self.ifru_metrics.hash(state); self.ifru_intval.hash(state); self.ifru_data.hash(state); self.ifru_scope_id.hash(state); } } } impl PartialEq for in6_ifreq { fn eq(&self, other: &in6_ifreq) -> bool { self.ifr_name == other.ifr_name && self.ifr_ifru == other.ifr_ifru } } impl Eq for in6_ifreq {} impl fmt::Debug for in6_ifreq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("in6_ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } } } pub const _UTX_USERSIZE: usize = 256; pub const _UTX_LINESIZE: usize = 32; pub const _UTX_IDSIZE: usize = 4; pub const _UTX_HOSTSIZE: usize = 256; pub const EMPTY: c_short = 0; pub const RUN_LVL: c_short = 1; pub const BOOT_TIME: c_short = 2; pub const OLD_TIME: c_short = 3; pub const NEW_TIME: c_short = 4; pub const INIT_PROCESS: c_short = 5; pub const LOGIN_PROCESS: c_short = 6; pub const USER_PROCESS: c_short = 7; pub const DEAD_PROCESS: c_short = 8; pub const ACCOUNTING: c_short = 9; pub const SIGNATURE: c_short = 10; pub const SHUTDOWN_TIME: c_short = 11; pub const LC_COLLATE_MASK: c_int = 1 << 0; pub const LC_CTYPE_MASK: c_int = 1 << 1; pub const LC_MESSAGES_MASK: c_int = 1 << 2; pub const LC_MONETARY_MASK: c_int = 1 << 3; pub const LC_NUMERIC_MASK: c_int = 1 << 4; pub const LC_TIME_MASK: c_int = 1 << 5; pub const LC_ALL_MASK: c_int = LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK; pub const CODESET: crate::nl_item = 0; pub const D_T_FMT: crate::nl_item = 1; pub const D_FMT: crate::nl_item = 2; pub const T_FMT: crate::nl_item = 3; pub const T_FMT_AMPM: crate::nl_item = 4; pub const AM_STR: crate::nl_item = 5; pub const PM_STR: crate::nl_item = 6; pub const DAY_1: crate::nl_item = 7; pub const DAY_2: crate::nl_item = 8; pub const DAY_3: crate::nl_item = 9; pub const DAY_4: crate::nl_item = 10; pub const DAY_5: crate::nl_item = 11; pub const DAY_6: crate::nl_item = 12; pub const DAY_7: crate::nl_item = 13; pub const ABDAY_1: crate::nl_item = 14; pub const ABDAY_2: crate::nl_item = 15; pub const ABDAY_3: crate::nl_item = 16; pub const ABDAY_4: crate::nl_item = 17; pub const ABDAY_5: crate::nl_item = 18; pub const ABDAY_6: crate::nl_item = 19; pub const ABDAY_7: crate::nl_item = 20; pub const MON_1: crate::nl_item = 21; pub const MON_2: crate::nl_item = 22; pub const MON_3: crate::nl_item = 23; pub const MON_4: crate::nl_item = 24; pub const MON_5: crate::nl_item = 25; pub const MON_6: crate::nl_item = 26; pub const MON_7: crate::nl_item = 27; pub const MON_8: crate::nl_item = 28; pub const MON_9: crate::nl_item = 29; pub const MON_10: crate::nl_item = 30; pub const MON_11: crate::nl_item = 31; pub const MON_12: crate::nl_item = 32; pub const ABMON_1: crate::nl_item = 33; pub const ABMON_2: crate::nl_item = 34; pub const ABMON_3: crate::nl_item = 35; pub const ABMON_4: crate::nl_item = 36; pub const ABMON_5: crate::nl_item = 37; pub const ABMON_6: crate::nl_item = 38; pub const ABMON_7: crate::nl_item = 39; pub const ABMON_8: crate::nl_item = 40; pub const ABMON_9: crate::nl_item = 41; pub const ABMON_10: crate::nl_item = 42; pub const ABMON_11: crate::nl_item = 43; pub const ABMON_12: crate::nl_item = 44; pub const CLOCK_REALTIME: crate::clockid_t = 0; pub const CLOCK_MONOTONIC_RAW: crate::clockid_t = 4; pub const CLOCK_MONOTONIC_RAW_APPROX: crate::clockid_t = 5; pub const CLOCK_MONOTONIC: crate::clockid_t = 6; pub const CLOCK_UPTIME_RAW: crate::clockid_t = 8; pub const CLOCK_UPTIME_RAW_APPROX: crate::clockid_t = 9; pub const CLOCK_PROCESS_CPUTIME_ID: crate::clockid_t = 12; pub const CLOCK_THREAD_CPUTIME_ID: crate::clockid_t = 16; pub const ERA: crate::nl_item = 45; pub const ERA_D_FMT: crate::nl_item = 46; pub const ERA_D_T_FMT: crate::nl_item = 47; pub const ERA_T_FMT: crate::nl_item = 48; pub const ALT_DIGITS: crate::nl_item = 49; pub const RADIXCHAR: crate::nl_item = 50; pub const THOUSEP: crate::nl_item = 51; pub const YESEXPR: crate::nl_item = 52; pub const NOEXPR: crate::nl_item = 53; pub const YESSTR: crate::nl_item = 54; pub const NOSTR: crate::nl_item = 55; pub const CRNCYSTR: crate::nl_item = 56; pub const D_MD_ORDER: crate::nl_item = 57; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 2147483647; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const SEEK_HOLE: c_int = 3; pub const SEEK_DATA: c_int = 4; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const BUFSIZ: c_uint = 1024; pub const FOPEN_MAX: c_uint = 20; pub const FILENAME_MAX: c_uint = 1024; pub const L_tmpnam: c_uint = 1024; pub const TMP_MAX: c_uint = 308915776; pub const _PC_LINK_MAX: c_int = 1; pub const _PC_MAX_CANON: c_int = 2; pub const _PC_MAX_INPUT: c_int = 3; pub const _PC_NAME_MAX: c_int = 4; pub const _PC_PATH_MAX: c_int = 5; pub const _PC_PIPE_BUF: c_int = 6; pub const _PC_CHOWN_RESTRICTED: c_int = 7; pub const _PC_NO_TRUNC: c_int = 8; pub const _PC_VDISABLE: c_int = 9; pub const _PC_NAME_CHARS_MAX: c_int = 10; pub const _PC_CASE_SENSITIVE: c_int = 11; pub const _PC_CASE_PRESERVING: c_int = 12; pub const _PC_EXTENDED_SECURITY_NP: c_int = 13; pub const _PC_AUTH_OPAQUE_NP: c_int = 14; pub const _PC_2_SYMLINKS: c_int = 15; pub const _PC_ALLOC_SIZE_MIN: c_int = 16; pub const _PC_ASYNC_IO: c_int = 17; pub const _PC_FILESIZEBITS: c_int = 18; pub const _PC_PRIO_IO: c_int = 19; pub const _PC_REC_INCR_XFER_SIZE: c_int = 20; pub const _PC_REC_MAX_XFER_SIZE: c_int = 21; pub const _PC_REC_MIN_XFER_SIZE: c_int = 22; pub const _PC_REC_XFER_ALIGN: c_int = 23; pub const _PC_SYMLINK_MAX: c_int = 24; pub const _PC_SYNC_IO: c_int = 25; pub const _PC_XATTR_SIZE_BITS: c_int = 26; pub const _PC_MIN_HOLE_SIZE: c_int = 27; pub const O_EVTONLY: c_int = 0x00008000; pub const O_NOCTTY: c_int = 0x00020000; pub const O_DIRECTORY: c_int = 0x00100000; pub const O_SYMLINK: c_int = 0x00200000; pub const O_DSYNC: c_int = 0x00400000; pub const O_CLOEXEC: c_int = 0x01000000; pub const O_NOFOLLOW_ANY: c_int = 0x20000000; pub const O_EXEC: c_int = 0x40000000; pub const O_SEARCH: c_int = O_EXEC | O_DIRECTORY; pub const S_IFIFO: mode_t = 0o1_0000; pub const S_IFCHR: mode_t = 0o2_0000; pub const S_IFBLK: mode_t = 0o6_0000; pub const S_IFDIR: mode_t = 0o4_0000; pub const S_IFREG: mode_t = 0o10_0000; pub const S_IFLNK: mode_t = 0o12_0000; pub const S_IFSOCK: mode_t = 0o14_0000; pub const S_IFMT: mode_t = 0o17_0000; pub const S_IEXEC: mode_t = 0o0100; pub const S_IWRITE: mode_t = 0o0200; pub const S_IREAD: mode_t = 0o0400; pub const S_IRWXU: mode_t = 0o0700; pub const S_IXUSR: mode_t = 0o0100; pub const S_IWUSR: mode_t = 0o0200; pub const S_IRUSR: mode_t = 0o0400; pub const S_IRWXG: mode_t = 0o0070; pub const S_IXGRP: mode_t = 0o0010; pub const S_IWGRP: mode_t = 0o0020; pub const S_IRGRP: mode_t = 0o0040; pub const S_IRWXO: mode_t = 0o0007; pub const S_IXOTH: mode_t = 0o0001; pub const S_IWOTH: mode_t = 0o0002; pub const S_IROTH: mode_t = 0o0004; pub const F_OK: c_int = 0; pub const R_OK: c_int = 4; pub const W_OK: c_int = 2; pub const X_OK: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const F_LOCK: c_int = 1; pub const F_TEST: c_int = 3; pub const F_TLOCK: c_int = 2; pub const F_ULOCK: c_int = 0; pub const F_GETLK: c_int = 7; pub const F_SETLK: c_int = 8; pub const F_SETLKW: c_int = 9; pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGABRT: c_int = 6; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGSEGV: c_int = 11; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const PROT_NONE: c_int = 0; pub const PROT_READ: c_int = 1; pub const PROT_WRITE: c_int = 2; pub const PROT_EXEC: c_int = 4; pub const PT_TRACE_ME: c_int = 0; pub const PT_READ_I: c_int = 1; pub const PT_READ_D: c_int = 2; pub const PT_READ_U: c_int = 3; pub const PT_WRITE_I: c_int = 4; pub const PT_WRITE_D: c_int = 5; pub const PT_WRITE_U: c_int = 6; pub const PT_CONTINUE: c_int = 7; pub const PT_KILL: c_int = 8; pub const PT_STEP: c_int = 9; pub const PT_ATTACH: c_int = 10; pub const PT_DETACH: c_int = 11; pub const PT_SIGEXC: c_int = 12; pub const PT_THUPDATE: c_int = 13; pub const PT_ATTACHEXC: c_int = 14; pub const PT_FORCEQUOTA: c_int = 30; pub const PT_DENY_ATTACH: c_int = 31; pub const PT_FIRSTMACH: c_int = 32; pub const MAP_FILE: c_int = 0x0000; pub const MAP_SHARED: c_int = 0x0001; pub const MAP_PRIVATE: c_int = 0x0002; pub const MAP_FIXED: c_int = 0x0010; pub const MAP_ANON: c_int = 0x1000; pub const MAP_ANONYMOUS: c_int = MAP_ANON; pub const CPU_STATE_USER: c_int = 0; pub const CPU_STATE_SYSTEM: c_int = 1; pub const CPU_STATE_IDLE: c_int = 2; pub const CPU_STATE_NICE: c_int = 3; pub const CPU_STATE_MAX: c_int = 4; pub const PROCESSOR_BASIC_INFO: c_int = 1; pub const PROCESSOR_CPU_LOAD_INFO: c_int = 2; pub const PROCESSOR_PM_REGS_INFO: c_int = 0x10000001; pub const PROCESSOR_TEMPERATURE: c_int = 0x10000002; pub const PROCESSOR_SET_LOAD_INFO: c_int = 4; pub const PROCESSOR_SET_BASIC_INFO: c_int = 5; deprecated_mach! { pub const VM_FLAGS_FIXED: c_int = 0x0000; pub const VM_FLAGS_ANYWHERE: c_int = 0x0001; pub const VM_FLAGS_PURGABLE: c_int = 0x0002; pub const VM_FLAGS_RANDOM_ADDR: c_int = 0x0008; pub const VM_FLAGS_NO_CACHE: c_int = 0x0010; pub const VM_FLAGS_RESILIENT_CODESIGN: c_int = 0x0020; pub const VM_FLAGS_RESILIENT_MEDIA: c_int = 0x0040; pub const VM_FLAGS_OVERWRITE: c_int = 0x4000; pub const VM_FLAGS_SUPERPAGE_MASK: c_int = 0x70000; pub const VM_FLAGS_RETURN_DATA_ADDR: c_int = 0x100000; pub const VM_FLAGS_RETURN_4K_DATA_ADDR: c_int = 0x800000; pub const VM_FLAGS_ALIAS_MASK: c_int = 0xFF000000; pub const VM_FLAGS_USER_ALLOCATE: c_int = 0xff07401f; pub const VM_FLAGS_USER_MAP: c_int = 0xff97401f; pub const VM_FLAGS_USER_REMAP: c_int = VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR | VM_FLAGS_OVERWRITE | VM_FLAGS_RETURN_DATA_ADDR | VM_FLAGS_RESILIENT_CODESIGN; pub const VM_FLAGS_SUPERPAGE_SHIFT: c_int = 16; pub const SUPERPAGE_NONE: c_int = 0; pub const SUPERPAGE_SIZE_ANY: c_int = 1; pub const VM_FLAGS_SUPERPAGE_NONE: c_int = SUPERPAGE_NONE << VM_FLAGS_SUPERPAGE_SHIFT; pub const VM_FLAGS_SUPERPAGE_SIZE_ANY: c_int = SUPERPAGE_SIZE_ANY << VM_FLAGS_SUPERPAGE_SHIFT; pub const SUPERPAGE_SIZE_2MB: c_int = 2; pub const VM_FLAGS_SUPERPAGE_SIZE_2MB: c_int = SUPERPAGE_SIZE_2MB << VM_FLAGS_SUPERPAGE_SHIFT; pub const VM_MEMORY_MALLOC: c_int = 1; pub const VM_MEMORY_MALLOC_SMALL: c_int = 2; pub const VM_MEMORY_MALLOC_LARGE: c_int = 3; pub const VM_MEMORY_MALLOC_HUGE: c_int = 4; pub const VM_MEMORY_SBRK: c_int = 5; pub const VM_MEMORY_REALLOC: c_int = 6; pub const VM_MEMORY_MALLOC_TINY: c_int = 7; pub const VM_MEMORY_MALLOC_LARGE_REUSABLE: c_int = 8; pub const VM_MEMORY_MALLOC_LARGE_REUSED: c_int = 9; pub const VM_MEMORY_ANALYSIS_TOOL: c_int = 10; pub const VM_MEMORY_MALLOC_NANO: c_int = 11; pub const VM_MEMORY_MACH_MSG: c_int = 20; pub const VM_MEMORY_IOKIT: c_int = 21; pub const VM_MEMORY_STACK: c_int = 30; pub const VM_MEMORY_GUARD: c_int = 31; pub const VM_MEMORY_SHARED_PMAP: c_int = 32; pub const VM_MEMORY_DYLIB: c_int = 33; pub const VM_MEMORY_OBJC_DISPATCHERS: c_int = 34; pub const VM_MEMORY_UNSHARED_PMAP: c_int = 35; pub const VM_MEMORY_APPKIT: c_int = 40; pub const VM_MEMORY_FOUNDATION: c_int = 41; pub const VM_MEMORY_COREGRAPHICS: c_int = 42; pub const VM_MEMORY_CORESERVICES: c_int = 43; pub const VM_MEMORY_CARBON: c_int = VM_MEMORY_CORESERVICES; pub const VM_MEMORY_JAVA: c_int = 44; pub const VM_MEMORY_COREDATA: c_int = 45; pub const VM_MEMORY_COREDATA_OBJECTIDS: c_int = 46; pub const VM_MEMORY_ATS: c_int = 50; pub const VM_MEMORY_LAYERKIT: c_int = 51; pub const VM_MEMORY_CGIMAGE: c_int = 52; pub const VM_MEMORY_TCMALLOC: c_int = 53; pub const VM_MEMORY_COREGRAPHICS_DATA: c_int = 54; pub const VM_MEMORY_COREGRAPHICS_SHARED: c_int = 55; pub const VM_MEMORY_COREGRAPHICS_FRAMEBUFFERS: c_int = 56; pub const VM_MEMORY_COREGRAPHICS_BACKINGSTORES: c_int = 57; pub const VM_MEMORY_COREGRAPHICS_XALLOC: c_int = 58; pub const VM_MEMORY_COREGRAPHICS_MISC: c_int = VM_MEMORY_COREGRAPHICS; pub const VM_MEMORY_DYLD: c_int = 60; pub const VM_MEMORY_DYLD_MALLOC: c_int = 61; pub const VM_MEMORY_SQLITE: c_int = 62; pub const VM_MEMORY_JAVASCRIPT_CORE: c_int = 63; pub const VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR: c_int = 64; pub const VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE: c_int = 65; pub const VM_MEMORY_GLSL: c_int = 66; pub const VM_MEMORY_OPENCL: c_int = 67; pub const VM_MEMORY_COREIMAGE: c_int = 68; pub const VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS: c_int = 69; pub const VM_MEMORY_IMAGEIO: c_int = 70; pub const VM_MEMORY_COREPROFILE: c_int = 71; pub const VM_MEMORY_ASSETSD: c_int = 72; pub const VM_MEMORY_OS_ALLOC_ONCE: c_int = 73; pub const VM_MEMORY_LIBDISPATCH: c_int = 74; pub const VM_MEMORY_ACCELERATE: c_int = 75; pub const VM_MEMORY_COREUI: c_int = 76; pub const VM_MEMORY_COREUIFILE: c_int = 77; pub const VM_MEMORY_GENEALOGY: c_int = 78; pub const VM_MEMORY_RAWCAMERA: c_int = 79; pub const VM_MEMORY_CORPSEINFO: c_int = 80; pub const VM_MEMORY_ASL: c_int = 81; pub const VM_MEMORY_SWIFT_RUNTIME: c_int = 82; pub const VM_MEMORY_SWIFT_METADATA: c_int = 83; pub const VM_MEMORY_DHMM: c_int = 84; pub const VM_MEMORY_SCENEKIT: c_int = 86; pub const VM_MEMORY_SKYWALK: c_int = 87; pub const VM_MEMORY_APPLICATION_SPECIFIC_1: c_int = 240; pub const VM_MEMORY_APPLICATION_SPECIFIC_16: c_int = 255; } pub const MAP_FAILED: *mut c_void = !0 as *mut c_void; pub const MCL_CURRENT: c_int = 0x0001; pub const MCL_FUTURE: c_int = 0x0002; pub const MS_ASYNC: c_int = 0x0001; pub const MS_INVALIDATE: c_int = 0x0002; pub const MS_SYNC: c_int = 0x0010; pub const MS_KILLPAGES: c_int = 0x0004; pub const MS_DEACTIVATE: c_int = 0x0008; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EDEADLK: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EAGAIN: c_int = 35; pub const EWOULDBLOCK: c_int = EAGAIN; pub const EINPROGRESS: c_int = 36; pub const EALREADY: c_int = 37; pub const ENOTSOCK: c_int = 38; pub const EDESTADDRREQ: c_int = 39; pub const EMSGSIZE: c_int = 40; pub const EPROTOTYPE: c_int = 41; pub const ENOPROTOOPT: c_int = 42; pub const EPROTONOSUPPORT: c_int = 43; pub const ESOCKTNOSUPPORT: c_int = 44; pub const ENOTSUP: c_int = 45; pub const EPFNOSUPPORT: c_int = 46; pub const EAFNOSUPPORT: c_int = 47; pub const EADDRINUSE: c_int = 48; pub const EADDRNOTAVAIL: c_int = 49; pub const ENETDOWN: c_int = 50; pub const ENETUNREACH: c_int = 51; pub const ENETRESET: c_int = 52; pub const ECONNABORTED: c_int = 53; pub const ECONNRESET: c_int = 54; pub const ENOBUFS: c_int = 55; pub const EISCONN: c_int = 56; pub const ENOTCONN: c_int = 57; pub const ESHUTDOWN: c_int = 58; pub const ETOOMANYREFS: c_int = 59; pub const ETIMEDOUT: c_int = 60; pub const ECONNREFUSED: c_int = 61; pub const ELOOP: c_int = 62; pub const ENAMETOOLONG: c_int = 63; pub const EHOSTDOWN: c_int = 64; pub const EHOSTUNREACH: c_int = 65; pub const ENOTEMPTY: c_int = 66; pub const EPROCLIM: c_int = 67; pub const EUSERS: c_int = 68; pub const EDQUOT: c_int = 69; pub const ESTALE: c_int = 70; pub const EREMOTE: c_int = 71; pub const EBADRPC: c_int = 72; pub const ERPCMISMATCH: c_int = 73; pub const EPROGUNAVAIL: c_int = 74; pub const EPROGMISMATCH: c_int = 75; pub const EPROCUNAVAIL: c_int = 76; pub const ENOLCK: c_int = 77; pub const ENOSYS: c_int = 78; pub const EFTYPE: c_int = 79; pub const EAUTH: c_int = 80; pub const ENEEDAUTH: c_int = 81; pub const EPWROFF: c_int = 82; pub const EDEVERR: c_int = 83; pub const EOVERFLOW: c_int = 84; pub const EBADEXEC: c_int = 85; pub const EBADARCH: c_int = 86; pub const ESHLIBVERS: c_int = 87; pub const EBADMACHO: c_int = 88; pub const ECANCELED: c_int = 89; pub const EIDRM: c_int = 90; pub const ENOMSG: c_int = 91; pub const EILSEQ: c_int = 92; pub const ENOATTR: c_int = 93; pub const EBADMSG: c_int = 94; pub const EMULTIHOP: c_int = 95; pub const ENODATA: c_int = 96; pub const ENOLINK: c_int = 97; pub const ENOSR: c_int = 98; pub const ENOSTR: c_int = 99; pub const EPROTO: c_int = 100; pub const ETIME: c_int = 101; pub const EOPNOTSUPP: c_int = 102; pub const ENOPOLICY: c_int = 103; pub const ENOTRECOVERABLE: c_int = 104; pub const EOWNERDEAD: c_int = 105; pub const EQFULL: c_int = 106; pub const ELAST: c_int = 106; pub const EAI_AGAIN: c_int = 2; pub const EAI_BADFLAGS: c_int = 3; pub const EAI_FAIL: c_int = 4; pub const EAI_FAMILY: c_int = 5; pub const EAI_MEMORY: c_int = 6; pub const EAI_NODATA: c_int = 7; pub const EAI_NONAME: c_int = 8; pub const EAI_SERVICE: c_int = 9; pub const EAI_SOCKTYPE: c_int = 10; pub const EAI_SYSTEM: c_int = 11; pub const EAI_OVERFLOW: c_int = 14; pub const F_DUPFD: c_int = 0; pub const F_DUPFD_CLOEXEC: c_int = 67; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const F_PREALLOCATE: c_int = 42; pub const F_RDADVISE: c_int = 44; pub const F_RDAHEAD: c_int = 45; pub const F_NOCACHE: c_int = 48; pub const F_LOG2PHYS: c_int = 49; pub const F_GETPATH: c_int = 50; pub const F_FULLFSYNC: c_int = 51; pub const F_FREEZE_FS: c_int = 53; pub const F_THAW_FS: c_int = 54; pub const F_GLOBAL_NOCACHE: c_int = 55; pub const F_NODIRECT: c_int = 62; pub const F_LOG2PHYS_EXT: c_int = 65; pub const F_BARRIERFSYNC: c_int = 85; // See https://github.com/apple/darwin-xnu/blob/main/bsd/sys/fcntl.h pub const F_OFD_SETLK: c_int = 90; /* Acquire or release open file description lock */ pub const F_OFD_SETLKW: c_int = 91; /* (as F_OFD_SETLK but blocking if conflicting lock) */ pub const F_OFD_GETLK: c_int = 92; /* Examine OFD lock */ pub const F_PUNCHHOLE: c_int = 99; pub const F_TRIM_ACTIVE_FILE: c_int = 100; pub const F_SPECULATIVE_READ: c_int = 101; pub const F_GETPATH_NOFIRMLINK: c_int = 102; pub const F_TRANSFEREXTENTS: c_int = 110; pub const F_ALLOCATECONTIG: c_uint = 0x02; pub const F_ALLOCATEALL: c_uint = 0x04; pub const F_ALLOCATEPERSIST: c_uint = 0x08; pub const F_PEOFPOSMODE: c_int = 3; pub const F_VOLPOSMODE: c_int = 4; pub const AT_FDCWD: c_int = -2; pub const AT_EACCESS: c_int = 0x0010; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x0020; pub const AT_SYMLINK_FOLLOW: c_int = 0x0040; pub const AT_REMOVEDIR: c_int = 0x0080; pub const PTHREAD_INTROSPECTION_THREAD_CREATE: c_uint = 1; pub const PTHREAD_INTROSPECTION_THREAD_START: c_uint = 2; pub const PTHREAD_INTROSPECTION_THREAD_TERMINATE: c_uint = 3; pub const PTHREAD_INTROSPECTION_THREAD_DESTROY: c_uint = 4; pub const TIOCMODG: c_ulong = 0x40047403; pub const TIOCMODS: c_ulong = 0x80047404; pub const TIOCM_LE: c_int = 0x1; pub const TIOCM_DTR: c_int = 0x2; pub const TIOCM_RTS: c_int = 0x4; pub const TIOCM_ST: c_int = 0x8; pub const TIOCM_SR: c_int = 0x10; pub const TIOCM_CTS: c_int = 0x20; pub const TIOCM_CAR: c_int = 0x40; pub const TIOCM_CD: c_int = 0x40; pub const TIOCM_RNG: c_int = 0x80; pub const TIOCM_RI: c_int = 0x80; pub const TIOCM_DSR: c_int = 0x100; pub const TIOCEXCL: c_int = 0x2000740d; pub const TIOCNXCL: c_int = 0x2000740e; pub const TIOCFLUSH: c_ulong = 0x80047410; pub const TIOCGETD: c_ulong = 0x4004741a; pub const TIOCSETD: c_ulong = 0x8004741b; pub const TIOCIXON: c_uint = 0x20007481; pub const TIOCIXOFF: c_uint = 0x20007480; pub const TIOCSDTR: c_uint = 0x20007479; pub const TIOCCDTR: c_uint = 0x20007478; pub const TIOCGPGRP: c_ulong = 0x40047477; pub const TIOCSPGRP: c_ulong = 0x80047476; pub const TIOCOUTQ: c_ulong = 0x40047473; pub const TIOCSTI: c_ulong = 0x80017472; pub const TIOCNOTTY: c_uint = 0x20007471; pub const TIOCPKT: c_ulong = 0x80047470; pub const TIOCPKT_DATA: c_int = 0x0; pub const TIOCPKT_FLUSHREAD: c_int = 0x1; pub const TIOCPKT_FLUSHWRITE: c_int = 0x2; pub const TIOCPKT_STOP: c_int = 0x4; pub const TIOCPKT_START: c_int = 0x8; pub const TIOCPKT_NOSTOP: c_int = 0x10; pub const TIOCPKT_DOSTOP: c_int = 0x20; pub const TIOCPKT_IOCTL: c_int = 0x40; pub const TIOCSTOP: c_uint = 0x2000746f; pub const TIOCSTART: c_uint = 0x2000746e; pub const TIOCMSET: c_ulong = 0x8004746d; pub const TIOCMBIS: c_ulong = 0x8004746c; pub const TIOCMBIC: c_ulong = 0x8004746b; pub const TIOCMGET: c_ulong = 0x4004746a; pub const TIOCREMOTE: c_ulong = 0x80047469; pub const TIOCGWINSZ: c_ulong = 0x40087468; pub const TIOCSWINSZ: c_ulong = 0x80087467; pub const TIOCUCNTL: c_ulong = 0x80047466; pub const TIOCSTAT: c_uint = 0x20007465; pub const TIOCSCONS: c_uint = 0x20007463; pub const TIOCCONS: c_ulong = 0x80047462; pub const TIOCSCTTY: c_uint = 0x20007461; pub const TIOCEXT: c_ulong = 0x80047460; pub const TIOCSIG: c_uint = 0x2000745f; pub const TIOCDRAIN: c_uint = 0x2000745e; pub const TIOCMSDTRWAIT: c_ulong = 0x8004745b; pub const TIOCMGDTRWAIT: c_ulong = 0x4004745a; pub const TIOCSDRAINWAIT: c_ulong = 0x80047457; pub const TIOCGDRAINWAIT: c_ulong = 0x40047456; pub const TIOCDSIMICROCODE: c_uint = 0x20007455; pub const TIOCPTYGRANT: c_uint = 0x20007454; pub const TIOCPTYGNAME: c_uint = 0x40807453; pub const TIOCPTYUNLK: c_uint = 0x20007452; pub const BIOCGRSIG: c_ulong = 0x40044272; pub const BIOCSRSIG: c_ulong = 0x80044273; pub const BIOCSDLT: c_ulong = 0x80044278; pub const BIOCGSEESENT: c_ulong = 0x40044276; pub const BIOCSSEESENT: c_ulong = 0x80044277; pub const BIOCGDLTLIST: c_ulong = 0xc00c4279; pub const FIODTYPE: c_ulong = 0x4004667a; pub const B0: speed_t = 0; pub const B50: speed_t = 50; pub const B75: speed_t = 75; pub const B110: speed_t = 110; pub const B134: speed_t = 134; pub const B150: speed_t = 150; pub const B200: speed_t = 200; pub const B300: speed_t = 300; pub const B600: speed_t = 600; pub const B1200: speed_t = 1200; pub const B1800: speed_t = 1800; pub const B2400: speed_t = 2400; pub const B4800: speed_t = 4800; pub const B9600: speed_t = 9600; pub const B19200: speed_t = 19200; pub const B38400: speed_t = 38400; pub const B7200: speed_t = 7200; pub const B14400: speed_t = 14400; pub const B28800: speed_t = 28800; pub const B57600: speed_t = 57600; pub const B76800: speed_t = 76800; pub const B115200: speed_t = 115200; pub const B230400: speed_t = 230400; pub const EXTA: speed_t = 19200; pub const EXTB: speed_t = 38400; pub const SIGTRAP: c_int = 5; pub const GLOB_APPEND: c_int = 0x0001; pub const GLOB_DOOFFS: c_int = 0x0002; pub const GLOB_ERR: c_int = 0x0004; pub const GLOB_MARK: c_int = 0x0008; pub const GLOB_NOCHECK: c_int = 0x0010; pub const GLOB_NOSORT: c_int = 0x0020; pub const GLOB_NOESCAPE: c_int = 0x2000; pub const GLOB_NOSPACE: c_int = -1; pub const GLOB_ABORTED: c_int = -2; pub const GLOB_NOMATCH: c_int = -3; pub const POSIX_MADV_NORMAL: c_int = 0; pub const POSIX_MADV_RANDOM: c_int = 1; pub const POSIX_MADV_SEQUENTIAL: c_int = 2; pub const POSIX_MADV_WILLNEED: c_int = 3; pub const POSIX_MADV_DONTNEED: c_int = 4; pub const _SC_IOV_MAX: c_int = 56; pub const _SC_GETGR_R_SIZE_MAX: c_int = 70; pub const _SC_GETPW_R_SIZE_MAX: c_int = 71; pub const _SC_LOGIN_NAME_MAX: c_int = 73; pub const _SC_MQ_PRIO_MAX: c_int = 75; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 82; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 83; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 85; pub const _SC_THREAD_KEYS_MAX: c_int = 86; pub const _SC_THREAD_PRIO_INHERIT: c_int = 87; pub const _SC_THREAD_PRIO_PROTECT: c_int = 88; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 89; pub const _SC_THREAD_PROCESS_SHARED: c_int = 90; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 91; pub const _SC_THREAD_STACK_MIN: c_int = 93; pub const _SC_THREAD_THREADS_MAX: c_int = 94; pub const _SC_THREADS: c_int = 96; pub const _SC_TTY_NAME_MAX: c_int = 101; pub const _SC_ATEXIT_MAX: c_int = 107; pub const _SC_XOPEN_CRYPT: c_int = 108; pub const _SC_XOPEN_ENH_I18N: c_int = 109; pub const _SC_XOPEN_LEGACY: c_int = 110; pub const _SC_XOPEN_REALTIME: c_int = 111; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 112; pub const _SC_XOPEN_SHM: c_int = 113; pub const _SC_XOPEN_UNIX: c_int = 115; pub const _SC_XOPEN_VERSION: c_int = 116; pub const _SC_XOPEN_XCU_VERSION: c_int = 121; pub const _SC_PHYS_PAGES: c_int = 200; pub const PTHREAD_PROCESS_PRIVATE: c_int = 2; pub const PTHREAD_PROCESS_SHARED: c_int = 1; pub const PTHREAD_CREATE_JOINABLE: c_int = 1; pub const PTHREAD_CREATE_DETACHED: c_int = 2; pub const PTHREAD_INHERIT_SCHED: c_int = 1; pub const PTHREAD_EXPLICIT_SCHED: c_int = 2; pub const PTHREAD_CANCEL_ENABLE: c_int = 0x01; pub const PTHREAD_CANCEL_DISABLE: c_int = 0x00; pub const PTHREAD_CANCEL_DEFERRED: c_int = 0x02; pub const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 0x00; pub const PTHREAD_CANCELED: *mut c_void = 1 as *mut c_void; pub const PTHREAD_SCOPE_SYSTEM: c_int = 1; pub const PTHREAD_SCOPE_PROCESS: c_int = 2; pub const PTHREAD_PRIO_NONE: c_int = 0; pub const PTHREAD_PRIO_INHERIT: c_int = 1; pub const PTHREAD_PRIO_PROTECT: c_int = 2; #[cfg(target_arch = "aarch64")] pub const PTHREAD_STACK_MIN: size_t = 16384; #[cfg(not(target_arch = "aarch64"))] pub const PTHREAD_STACK_MIN: size_t = 8192; pub const RLIMIT_CPU: c_int = 0; pub const RLIMIT_FSIZE: c_int = 1; pub const RLIMIT_DATA: c_int = 2; pub const RLIMIT_STACK: c_int = 3; pub const RLIMIT_CORE: c_int = 4; pub const RLIMIT_AS: c_int = 5; pub const RLIMIT_RSS: c_int = RLIMIT_AS; pub const RLIMIT_MEMLOCK: c_int = 6; pub const RLIMIT_NPROC: c_int = 7; pub const RLIMIT_NOFILE: c_int = 8; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: c_int = 9; pub const _RLIMIT_POSIX_FLAG: c_int = 0x1000; pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; pub const RUSAGE_SELF: c_int = 0; pub const RUSAGE_CHILDREN: c_int = -1; pub const MADV_NORMAL: c_int = 0; pub const MADV_RANDOM: c_int = 1; pub const MADV_SEQUENTIAL: c_int = 2; pub const MADV_WILLNEED: c_int = 3; pub const MADV_DONTNEED: c_int = 4; pub const MADV_FREE: c_int = 5; pub const MADV_ZERO_WIRED_PAGES: c_int = 6; pub const MADV_FREE_REUSABLE: c_int = 7; pub const MADV_FREE_REUSE: c_int = 8; pub const MADV_CAN_REUSE: c_int = 9; pub const MINCORE_INCORE: c_int = 0x1; pub const MINCORE_REFERENCED: c_int = 0x2; pub const MINCORE_MODIFIED: c_int = 0x4; pub const MINCORE_REFERENCED_OTHER: c_int = 0x8; pub const MINCORE_MODIFIED_OTHER: c_int = 0x10; pub const CTLIOCGINFO: c_ulong = 0xc0644e03; // // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// IP6 hop-by-hop options pub const IPPROTO_HOPOPTS: c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: c_int = 2; /// gateway2 (deprecated) pub const IPPROTO_GGP: c_int = 3; /// for compatibility pub const IPPROTO_IPIP: c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// Stream protocol II. pub const IPPROTO_ST: c_int = 7; /// exterior gateway protocol pub const IPPROTO_EGP: c_int = 8; /// private interior gateway pub const IPPROTO_PIGP: c_int = 9; /// BBN RCC Monitoring pub const IPPROTO_RCCMON: c_int = 10; /// network voice protocol pub const IPPROTO_NVPII: c_int = 11; /// pup pub const IPPROTO_PUP: c_int = 12; /// Argus pub const IPPROTO_ARGUS: c_int = 13; /// EMCON pub const IPPROTO_EMCON: c_int = 14; /// Cross Net Debugger pub const IPPROTO_XNET: c_int = 15; /// Chaos pub const IPPROTO_CHAOS: c_int = 16; // IPPROTO_UDP defined in src/unix/mod.rs /// Multiplexing pub const IPPROTO_MUX: c_int = 18; /// DCN Measurement Subsystems pub const IPPROTO_MEAS: c_int = 19; /// Host Monitoring pub const IPPROTO_HMP: c_int = 20; /// Packet Radio Measurement pub const IPPROTO_PRM: c_int = 21; /// xns idp pub const IPPROTO_IDP: c_int = 22; /// Trunk-1 pub const IPPROTO_TRUNK1: c_int = 23; /// Trunk-2 pub const IPPROTO_TRUNK2: c_int = 24; /// Leaf-1 pub const IPPROTO_LEAF1: c_int = 25; /// Leaf-2 pub const IPPROTO_LEAF2: c_int = 26; /// Reliable Data pub const IPPROTO_RDP: c_int = 27; /// Reliable Transaction pub const IPPROTO_IRTP: c_int = 28; /// tp-4 w/ class negotiation pub const IPPROTO_TP: c_int = 29; /// Bulk Data Transfer pub const IPPROTO_BLT: c_int = 30; /// Network Services pub const IPPROTO_NSP: c_int = 31; /// Merit Internodal pub const IPPROTO_INP: c_int = 32; /// Sequential Exchange pub const IPPROTO_SEP: c_int = 33; /// Third Party Connect pub const IPPROTO_3PC: c_int = 34; /// InterDomain Policy Routing pub const IPPROTO_IDPR: c_int = 35; /// XTP pub const IPPROTO_XTP: c_int = 36; /// Datagram Delivery pub const IPPROTO_DDP: c_int = 37; /// Control Message Transport pub const IPPROTO_CMTP: c_int = 38; /// TP++ Transport pub const IPPROTO_TPXX: c_int = 39; /// IL transport protocol pub const IPPROTO_IL: c_int = 40; // IPPROTO_IPV6 defined in src/unix/mod.rs /// Source Demand Routing pub const IPPROTO_SDRP: c_int = 42; /// IP6 routing header pub const IPPROTO_ROUTING: c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: c_int = 44; /// InterDomain Routing pub const IPPROTO_IDRP: c_int = 45; /// resource reservation pub const IPPROTO_RSVP: c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: c_int = 47; /// Mobile Host Routing pub const IPPROTO_MHRP: c_int = 48; /// BHA pub const IPPROTO_BHA: c_int = 49; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: c_int = 51; /// Integ. Net Layer Security pub const IPPROTO_INLSP: c_int = 52; /// IP with encryption pub const IPPROTO_SWIPE: c_int = 53; /// Next Hop Resolution pub const IPPROTO_NHRP: c_int = 54; /* 55-57: Unassigned */ // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: c_int = 60; /// any host internal protocol pub const IPPROTO_AHIP: c_int = 61; /// CFTP pub const IPPROTO_CFTP: c_int = 62; /// "hello" routing protocol pub const IPPROTO_HELLO: c_int = 63; /// SATNET/Backroom EXPAK pub const IPPROTO_SATEXPAK: c_int = 64; /// Kryptolan pub const IPPROTO_KRYPTOLAN: c_int = 65; /// Remote Virtual Disk pub const IPPROTO_RVD: c_int = 66; /// Pluribus Packet Core pub const IPPROTO_IPPC: c_int = 67; /// Any distributed FS pub const IPPROTO_ADFS: c_int = 68; /// Satnet Monitoring pub const IPPROTO_SATMON: c_int = 69; /// VISA Protocol pub const IPPROTO_VISA: c_int = 70; /// Packet Core Utility pub const IPPROTO_IPCV: c_int = 71; /// Comp. Prot. Net. Executive pub const IPPROTO_CPNX: c_int = 72; /// Comp. Prot. HeartBeat pub const IPPROTO_CPHB: c_int = 73; /// Wang Span Network pub const IPPROTO_WSN: c_int = 74; /// Packet Video Protocol pub const IPPROTO_PVP: c_int = 75; /// BackRoom SATNET Monitoring pub const IPPROTO_BRSATMON: c_int = 76; /// Sun net disk proto (temp.) pub const IPPROTO_ND: c_int = 77; /// WIDEBAND Monitoring pub const IPPROTO_WBMON: c_int = 78; /// WIDEBAND EXPAK pub const IPPROTO_WBEXPAK: c_int = 79; /// ISO cnlp pub const IPPROTO_EON: c_int = 80; /// VMTP pub const IPPROTO_VMTP: c_int = 81; /// Secure VMTP pub const IPPROTO_SVMTP: c_int = 82; /// Banyon VINES pub const IPPROTO_VINES: c_int = 83; /// TTP pub const IPPROTO_TTP: c_int = 84; /// NSFNET-IGP pub const IPPROTO_IGP: c_int = 85; /// dissimilar gateway prot. pub const IPPROTO_DGP: c_int = 86; /// TCF pub const IPPROTO_TCF: c_int = 87; /// Cisco/GXS IGRP pub const IPPROTO_IGRP: c_int = 88; /// OSPFIGP pub const IPPROTO_OSPFIGP: c_int = 89; /// Strite RPC protocol pub const IPPROTO_SRPC: c_int = 90; /// Locus Address Resoloution pub const IPPROTO_LARP: c_int = 91; /// Multicast Transport pub const IPPROTO_MTP: c_int = 92; /// AX.25 Frames pub const IPPROTO_AX25: c_int = 93; /// IP encapsulated in IP pub const IPPROTO_IPEIP: c_int = 94; /// Mobile Int.ing control pub const IPPROTO_MICP: c_int = 95; /// Semaphore Comm. security pub const IPPROTO_SCCSP: c_int = 96; /// Ethernet IP encapsulation pub const IPPROTO_ETHERIP: c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: c_int = 98; /// any private encr. scheme pub const IPPROTO_APES: c_int = 99; /// GMTP pub const IPPROTO_GMTP: c_int = 100; /* 101-254: Partly Unassigned */ /// Protocol Independent Mcast pub const IPPROTO_PIM: c_int = 103; /// payload compression (IPComp) pub const IPPROTO_IPCOMP: c_int = 108; /// PGM pub const IPPROTO_PGM: c_int = 113; /// SCTP pub const IPPROTO_SCTP: c_int = 132; /* 255: Reserved */ /* BSD Private, local use, namespace incursion */ /// divert pseudo-protocol pub const IPPROTO_DIVERT: c_int = 254; /// raw IP packet pub const IPPROTO_RAW: c_int = 255; pub const IPPROTO_MAX: c_int = 256; /// last return value of *_input(), meaning "all job for this pkt is done". pub const IPPROTO_DONE: c_int = 257; pub const AF_UNSPEC: c_int = 0; pub const AF_LOCAL: c_int = 1; pub const AF_UNIX: c_int = AF_LOCAL; pub const AF_INET: c_int = 2; pub const AF_IMPLINK: c_int = 3; pub const AF_PUP: c_int = 4; pub const AF_CHAOS: c_int = 5; pub const AF_NS: c_int = 6; pub const AF_ISO: c_int = 7; pub const AF_OSI: c_int = AF_ISO; pub const AF_ECMA: c_int = 8; pub const AF_DATAKIT: c_int = 9; pub const AF_CCITT: c_int = 10; pub const AF_SNA: c_int = 11; pub const AF_DECnet: c_int = 12; pub const AF_DLI: c_int = 13; pub const AF_LAT: c_int = 14; pub const AF_HYLINK: c_int = 15; pub const AF_APPLETALK: c_int = 16; pub const AF_ROUTE: c_int = 17; pub const AF_LINK: c_int = 18; pub const pseudo_AF_XTP: c_int = 19; pub const AF_COIP: c_int = 20; pub const AF_CNT: c_int = 21; pub const pseudo_AF_RTIP: c_int = 22; pub const AF_IPX: c_int = 23; pub const AF_SIP: c_int = 24; pub const pseudo_AF_PIP: c_int = 25; pub const AF_NDRV: c_int = 27; pub const AF_ISDN: c_int = 28; pub const AF_E164: c_int = AF_ISDN; pub const pseudo_AF_KEY: c_int = 29; pub const AF_INET6: c_int = 30; pub const AF_NATM: c_int = 31; pub const AF_SYSTEM: c_int = 32; pub const AF_NETBIOS: c_int = 33; pub const AF_PPP: c_int = 34; pub const pseudo_AF_HDRCMPLT: c_int = 35; pub const AF_IEEE80211: c_int = 37; pub const AF_UTUN: c_int = 38; pub const AF_VSOCK: c_int = 40; pub const AF_SYS_CONTROL: c_int = 2; pub const SYSPROTO_EVENT: c_int = 1; pub const SYSPROTO_CONTROL: c_int = 2; pub const PF_UNSPEC: c_int = AF_UNSPEC; pub const PF_LOCAL: c_int = AF_LOCAL; pub const PF_UNIX: c_int = PF_LOCAL; pub const PF_INET: c_int = AF_INET; pub const PF_IMPLINK: c_int = AF_IMPLINK; pub const PF_PUP: c_int = AF_PUP; pub const PF_CHAOS: c_int = AF_CHAOS; pub const PF_NS: c_int = AF_NS; pub const PF_ISO: c_int = AF_ISO; pub const PF_OSI: c_int = AF_ISO; pub const PF_ECMA: c_int = AF_ECMA; pub const PF_DATAKIT: c_int = AF_DATAKIT; pub const PF_CCITT: c_int = AF_CCITT; pub const PF_SNA: c_int = AF_SNA; pub const PF_DECnet: c_int = AF_DECnet; pub const PF_DLI: c_int = AF_DLI; pub const PF_LAT: c_int = AF_LAT; pub const PF_HYLINK: c_int = AF_HYLINK; pub const PF_APPLETALK: c_int = AF_APPLETALK; pub const PF_ROUTE: c_int = AF_ROUTE; pub const PF_LINK: c_int = AF_LINK; pub const PF_XTP: c_int = pseudo_AF_XTP; pub const PF_COIP: c_int = AF_COIP; pub const PF_CNT: c_int = AF_CNT; pub const PF_SIP: c_int = AF_SIP; pub const PF_IPX: c_int = AF_IPX; pub const PF_RTIP: c_int = pseudo_AF_RTIP; pub const PF_PIP: c_int = pseudo_AF_PIP; pub const PF_NDRV: c_int = AF_NDRV; pub const PF_ISDN: c_int = AF_ISDN; pub const PF_KEY: c_int = pseudo_AF_KEY; pub const PF_INET6: c_int = AF_INET6; pub const PF_NATM: c_int = AF_NATM; pub const PF_SYSTEM: c_int = AF_SYSTEM; pub const PF_NETBIOS: c_int = AF_NETBIOS; pub const PF_PPP: c_int = AF_PPP; pub const PF_VSOCK: c_int = AF_VSOCK; pub const NET_RT_DUMP: c_int = 1; pub const NET_RT_FLAGS: c_int = 2; pub const NET_RT_IFLIST: c_int = 3; pub const SOMAXCONN: c_int = 128; pub const SOCK_MAXADDRLEN: c_int = 255; pub const SOCK_STREAM: c_int = 1; pub const SOCK_DGRAM: c_int = 2; pub const SOCK_RAW: c_int = 3; pub const SOCK_RDM: c_int = 4; pub const SOCK_SEQPACKET: c_int = 5; pub const IP_TTL: c_int = 4; pub const IP_HDRINCL: c_int = 2; pub const IP_RECVDSTADDR: c_int = 7; pub const IP_ADD_MEMBERSHIP: c_int = 12; pub const IP_DROP_MEMBERSHIP: c_int = 13; pub const IP_RECVIF: c_int = 20; pub const IP_RECVTTL: c_int = 24; pub const IP_BOUND_IF: c_int = 25; pub const IP_PKTINFO: c_int = 26; pub const IP_RECVTOS: c_int = 27; pub const IP_DONTFRAG: c_int = 28; pub const IPV6_JOIN_GROUP: c_int = 12; pub const IPV6_LEAVE_GROUP: c_int = 13; pub const IPV6_CHECKSUM: c_int = 26; pub const IPV6_RECVTCLASS: c_int = 35; pub const IPV6_TCLASS: c_int = 36; pub const IPV6_RECVHOPLIMIT: c_int = 37; pub const IPV6_PKTINFO: c_int = 46; pub const IPV6_HOPLIMIT: c_int = 47; pub const IPV6_RECVPKTINFO: c_int = 61; pub const IP_ADD_SOURCE_MEMBERSHIP: c_int = 70; pub const IP_DROP_SOURCE_MEMBERSHIP: c_int = 71; pub const IP_BLOCK_SOURCE: c_int = 72; pub const IP_UNBLOCK_SOURCE: c_int = 73; pub const IPV6_BOUND_IF: c_int = 125; pub const TCP_NOPUSH: c_int = 4; pub const TCP_NOOPT: c_int = 8; pub const TCP_KEEPALIVE: c_int = 0x10; pub const TCP_KEEPINTVL: c_int = 0x101; pub const TCP_KEEPCNT: c_int = 0x102; /// Enable/Disable TCP Fastopen on this socket pub const TCP_FASTOPEN: c_int = 0x105; pub const TCP_CONNECTION_INFO: c_int = 0x106; pub const SOL_LOCAL: c_int = 0; /// Retrieve peer credentials. pub const LOCAL_PEERCRED: c_int = 0x001; /// Retrieve peer PID. pub const LOCAL_PEERPID: c_int = 0x002; /// Retrieve effective peer PID. pub const LOCAL_PEEREPID: c_int = 0x003; /// Retrieve peer UUID. pub const LOCAL_PEERUUID: c_int = 0x004; /// Retrieve effective peer UUID. pub const LOCAL_PEEREUUID: c_int = 0x005; /// Retrieve peer audit token. pub const LOCAL_PEERTOKEN: c_int = 0x006; pub const SOL_SOCKET: c_int = 0xffff; pub const SO_DEBUG: c_int = 0x01; pub const SO_ACCEPTCONN: c_int = 0x0002; pub const SO_REUSEADDR: c_int = 0x0004; pub const SO_KEEPALIVE: c_int = 0x0008; pub const SO_DONTROUTE: c_int = 0x0010; pub const SO_BROADCAST: c_int = 0x0020; pub const SO_USELOOPBACK: c_int = 0x0040; pub const SO_LINGER: c_int = 0x0080; pub const SO_OOBINLINE: c_int = 0x0100; pub const SO_REUSEPORT: c_int = 0x0200; pub const SO_TIMESTAMP: c_int = 0x0400; pub const SO_TIMESTAMP_MONOTONIC: c_int = 0x0800; pub const SO_DONTTRUNC: c_int = 0x2000; pub const SO_WANTMORE: c_int = 0x4000; pub const SO_WANTOOBFLAG: c_int = 0x8000; pub const SO_SNDBUF: c_int = 0x1001; pub const SO_RCVBUF: c_int = 0x1002; pub const SO_SNDLOWAT: c_int = 0x1003; pub const SO_RCVLOWAT: c_int = 0x1004; pub const SO_SNDTIMEO: c_int = 0x1005; pub const SO_RCVTIMEO: c_int = 0x1006; pub const SO_ERROR: c_int = 0x1007; pub const SO_TYPE: c_int = 0x1008; pub const SO_LABEL: c_int = 0x1010; pub const SO_PEERLABEL: c_int = 0x1011; pub const SO_NREAD: c_int = 0x1020; pub const SO_NKE: c_int = 0x1021; pub const SO_NOSIGPIPE: c_int = 0x1022; pub const SO_NOADDRERR: c_int = 0x1023; pub const SO_NWRITE: c_int = 0x1024; pub const SO_REUSESHAREUID: c_int = 0x1025; pub const SO_NOTIFYCONFLICT: c_int = 0x1026; pub const SO_LINGER_SEC: c_int = 0x1080; pub const SO_RANDOMPORT: c_int = 0x1082; pub const SO_NP_EXTENSIONS: c_int = 0x1083; pub const MSG_OOB: c_int = 0x1; pub const MSG_PEEK: c_int = 0x2; pub const MSG_DONTROUTE: c_int = 0x4; pub const MSG_EOR: c_int = 0x8; pub const MSG_TRUNC: c_int = 0x10; pub const MSG_CTRUNC: c_int = 0x20; pub const MSG_WAITALL: c_int = 0x40; pub const MSG_DONTWAIT: c_int = 0x80; pub const MSG_EOF: c_int = 0x100; pub const MSG_FLUSH: c_int = 0x400; pub const MSG_HOLD: c_int = 0x800; pub const MSG_SEND: c_int = 0x1000; pub const MSG_HAVEMORE: c_int = 0x2000; pub const MSG_RCVMORE: c_int = 0x4000; pub const MSG_NEEDSA: c_int = 0x10000; pub const MSG_NOSIGNAL: c_int = 0x80000; pub const SCM_TIMESTAMP: c_int = 0x02; pub const SCM_CREDS: c_int = 0x03; // https://github.com/aosm/xnu/blob/HEAD/bsd/net/if.h#L140-L156 pub const IFF_UP: c_int = 0x1; // interface is up pub const IFF_BROADCAST: c_int = 0x2; // broadcast address valid pub const IFF_DEBUG: c_int = 0x4; // turn on debugging pub const IFF_LOOPBACK: c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: c_int = 0x10; // interface is point-to-point link pub const IFF_NOTRAILERS: c_int = 0x20; // obsolete: avoid use of trailers pub const IFF_RUNNING: c_int = 0x40; // resources allocated pub const IFF_NOARP: c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: c_int = 0x100; // receive all packets pub const IFF_ALLMULTI: c_int = 0x200; // receive all multicast packets pub const IFF_OACTIVE: c_int = 0x400; // transmission in progress pub const IFF_SIMPLEX: c_int = 0x800; // can't hear own transmissions pub const IFF_LINK0: c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: c_int = 0x4000; // per link layer defined bit pub const IFF_ALTPHYS: c_int = IFF_LINK2; // use alternate physical connection pub const IFF_MULTICAST: c_int = 0x8000; // supports multicast pub const SCOPE6_ID_MAX: size_t = 16; pub const SHUT_RD: c_int = 0; pub const SHUT_WR: c_int = 1; pub const SHUT_RDWR: c_int = 2; pub const SAE_ASSOCID_ANY: crate::sae_associd_t = 0; /// ((sae_associd_t)(-1ULL)) pub const SAE_ASSOCID_ALL: crate::sae_associd_t = 0xffffffff; pub const SAE_CONNID_ANY: crate::sae_connid_t = 0; /// ((sae_connid_t)(-1ULL)) pub const SAE_CONNID_ALL: crate::sae_connid_t = 0xffffffff; // connectx() flag parameters /// resume connect() on read/write pub const CONNECT_RESUME_ON_READ_WRITE: c_uint = 0x1; /// data is idempotent pub const CONNECT_DATA_IDEMPOTENT: c_uint = 0x2; /// data includes security that replaces the TFO-cookie pub const CONNECT_DATA_AUTHENTICATED: c_uint = 0x4; pub const LOCK_SH: c_int = 1; pub const LOCK_EX: c_int = 2; pub const LOCK_NB: c_int = 4; pub const LOCK_UN: c_int = 8; pub const MAP_COPY: c_int = 0x0002; pub const MAP_RENAME: c_int = 0x0020; pub const MAP_NORESERVE: c_int = 0x0040; pub const MAP_NOEXTEND: c_int = 0x0100; pub const MAP_HASSEMAPHORE: c_int = 0x0200; pub const MAP_NOCACHE: c_int = 0x0400; pub const MAP_JIT: c_int = 0x0800; pub const _SC_ARG_MAX: c_int = 1; pub const _SC_CHILD_MAX: c_int = 2; pub const _SC_CLK_TCK: c_int = 3; pub const _SC_NGROUPS_MAX: c_int = 4; pub const _SC_OPEN_MAX: c_int = 5; pub const _SC_JOB_CONTROL: c_int = 6; pub const _SC_SAVED_IDS: c_int = 7; pub const _SC_VERSION: c_int = 8; pub const _SC_BC_BASE_MAX: c_int = 9; pub const _SC_BC_DIM_MAX: c_int = 10; pub const _SC_BC_SCALE_MAX: c_int = 11; pub const _SC_BC_STRING_MAX: c_int = 12; pub const _SC_COLL_WEIGHTS_MAX: c_int = 13; pub const _SC_EXPR_NEST_MAX: c_int = 14; pub const _SC_LINE_MAX: c_int = 15; pub const _SC_RE_DUP_MAX: c_int = 16; pub const _SC_2_VERSION: c_int = 17; pub const _SC_2_C_BIND: c_int = 18; pub const _SC_2_C_DEV: c_int = 19; pub const _SC_2_CHAR_TERM: c_int = 20; pub const _SC_2_FORT_DEV: c_int = 21; pub const _SC_2_FORT_RUN: c_int = 22; pub const _SC_2_LOCALEDEF: c_int = 23; pub const _SC_2_SW_DEV: c_int = 24; pub const _SC_2_UPE: c_int = 25; pub const _SC_STREAM_MAX: c_int = 26; pub const _SC_TZNAME_MAX: c_int = 27; pub const _SC_ASYNCHRONOUS_IO: c_int = 28; pub const _SC_PAGESIZE: c_int = 29; pub const _SC_MEMLOCK: c_int = 30; pub const _SC_MEMLOCK_RANGE: c_int = 31; pub const _SC_MEMORY_PROTECTION: c_int = 32; pub const _SC_MESSAGE_PASSING: c_int = 33; pub const _SC_PRIORITIZED_IO: c_int = 34; pub const _SC_PRIORITY_SCHEDULING: c_int = 35; pub const _SC_REALTIME_SIGNALS: c_int = 36; pub const _SC_SEMAPHORES: c_int = 37; pub const _SC_FSYNC: c_int = 38; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 39; pub const _SC_SYNCHRONIZED_IO: c_int = 40; pub const _SC_TIMERS: c_int = 41; pub const _SC_AIO_LISTIO_MAX: c_int = 42; pub const _SC_AIO_MAX: c_int = 43; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44; pub const _SC_DELAYTIMER_MAX: c_int = 45; pub const _SC_MQ_OPEN_MAX: c_int = 46; pub const _SC_MAPPED_FILES: c_int = 47; pub const _SC_RTSIG_MAX: c_int = 48; pub const _SC_SEM_NSEMS_MAX: c_int = 49; pub const _SC_SEM_VALUE_MAX: c_int = 50; pub const _SC_SIGQUEUE_MAX: c_int = 51; pub const _SC_TIMER_MAX: c_int = 52; pub const _SC_NPROCESSORS_CONF: c_int = 57; pub const _SC_NPROCESSORS_ONLN: c_int = 58; pub const _SC_2_PBS: c_int = 59; pub const _SC_2_PBS_ACCOUNTING: c_int = 60; pub const _SC_2_PBS_CHECKPOINT: c_int = 61; pub const _SC_2_PBS_LOCATE: c_int = 62; pub const _SC_2_PBS_MESSAGE: c_int = 63; pub const _SC_2_PBS_TRACK: c_int = 64; pub const _SC_ADVISORY_INFO: c_int = 65; pub const _SC_BARRIERS: c_int = 66; pub const _SC_CLOCK_SELECTION: c_int = 67; pub const _SC_CPUTIME: c_int = 68; pub const _SC_FILE_LOCKING: c_int = 69; pub const _SC_HOST_NAME_MAX: c_int = 72; pub const _SC_MONOTONIC_CLOCK: c_int = 74; pub const _SC_READER_WRITER_LOCKS: c_int = 76; pub const _SC_REGEXP: c_int = 77; pub const _SC_SHELL: c_int = 78; pub const _SC_SPAWN: c_int = 79; pub const _SC_SPIN_LOCKS: c_int = 80; pub const _SC_SPORADIC_SERVER: c_int = 81; pub const _SC_THREAD_CPUTIME: c_int = 84; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 92; pub const _SC_TIMEOUTS: c_int = 95; pub const _SC_TRACE: c_int = 97; pub const _SC_TRACE_EVENT_FILTER: c_int = 98; pub const _SC_TRACE_INHERIT: c_int = 99; pub const _SC_TRACE_LOG: c_int = 100; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 102; pub const _SC_V6_ILP32_OFF32: c_int = 103; pub const _SC_V6_ILP32_OFFBIG: c_int = 104; pub const _SC_V6_LP64_OFF64: c_int = 105; pub const _SC_V6_LPBIG_OFFBIG: c_int = 106; pub const _SC_IPV6: c_int = 118; pub const _SC_RAW_SOCKETS: c_int = 119; pub const _SC_SYMLOOP_MAX: c_int = 120; pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE; pub const _SC_XOPEN_STREAMS: c_int = 114; pub const _SC_XBS5_ILP32_OFF32: c_int = 122; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 123; pub const _SC_XBS5_LP64_OFF64: c_int = 124; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 125; pub const _SC_SS_REPL_MAX: c_int = 126; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 127; pub const _SC_TRACE_NAME_MAX: c_int = 128; pub const _SC_TRACE_SYS_MAX: c_int = 129; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 130; pub const _SC_PASS_MAX: c_int = 131; // `confstr` keys (only the values guaranteed by `man confstr`). pub const _CS_PATH: c_int = 1; pub const _CS_DARWIN_USER_DIR: c_int = 65536; pub const _CS_DARWIN_USER_TEMP_DIR: c_int = 65537; pub const _CS_DARWIN_USER_CACHE_DIR: c_int = 65538; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const _PTHREAD_MUTEX_SIG_init: c_long = 0x32AAABA7; pub const _PTHREAD_COND_SIG_init: c_long = 0x3CB0B1BB; pub const _PTHREAD_RWLOCK_SIG_init: c_long = 0x2DA8B3B4; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __sig: _PTHREAD_MUTEX_SIG_init, __opaque: [0; __PTHREAD_MUTEX_SIZE__], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __sig: _PTHREAD_COND_SIG_init, __opaque: [0; __PTHREAD_COND_SIZE__], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __sig: _PTHREAD_RWLOCK_SIG_init, __opaque: [0; __PTHREAD_RWLOCK_SIZE__], }; pub const OS_UNFAIR_LOCK_INIT: os_unfair_lock = os_unfair_lock { _os_unfair_lock_opaque: 0, }; pub const OS_LOG_TYPE_DEFAULT: crate::os_log_type_t = 0x00; pub const OS_LOG_TYPE_INFO: crate::os_log_type_t = 0x01; pub const OS_LOG_TYPE_DEBUG: crate::os_log_type_t = 0x02; pub const OS_LOG_TYPE_ERROR: crate::os_log_type_t = 0x10; pub const OS_LOG_TYPE_FAULT: crate::os_log_type_t = 0x11; pub const OS_SIGNPOST_EVENT: crate::os_signpost_type_t = 0x00; pub const OS_SIGNPOST_INTERVAL_BEGIN: crate::os_signpost_type_t = 0x01; pub const OS_SIGNPOST_INTERVAL_END: crate::os_signpost_type_t = 0x02; pub const MINSIGSTKSZ: size_t = 32768; pub const SIGSTKSZ: size_t = 131072; pub const FD_SETSIZE: usize = 1024; pub const ST_NOSUID: c_ulong = 2; pub const SCHED_OTHER: c_int = 1; pub const SCHED_FIFO: c_int = 4; pub const SCHED_RR: c_int = 2; pub const EVFILT_READ: i16 = -1; pub const EVFILT_WRITE: i16 = -2; pub const EVFILT_AIO: i16 = -3; pub const EVFILT_VNODE: i16 = -4; pub const EVFILT_PROC: i16 = -5; pub const EVFILT_SIGNAL: i16 = -6; pub const EVFILT_TIMER: i16 = -7; pub const EVFILT_MACHPORT: i16 = -8; pub const EVFILT_FS: i16 = -9; pub const EVFILT_USER: i16 = -10; pub const EVFILT_VM: i16 = -12; pub const EV_ADD: u16 = 0x1; pub const EV_DELETE: u16 = 0x2; pub const EV_ENABLE: u16 = 0x4; pub const EV_DISABLE: u16 = 0x8; pub const EV_ONESHOT: u16 = 0x10; pub const EV_CLEAR: u16 = 0x20; pub const EV_RECEIPT: u16 = 0x40; pub const EV_DISPATCH: u16 = 0x80; pub const EV_FLAG0: u16 = 0x1000; pub const EV_POLL: u16 = 0x1000; pub const EV_FLAG1: u16 = 0x2000; pub const EV_OOBAND: u16 = 0x2000; pub const EV_ERROR: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; pub const EV_SYSFLAGS: u16 = 0xf000; pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; pub const NOTE_FFOR: u32 = 0x80000000; pub const NOTE_FFCOPY: u32 = 0xc0000000; pub const NOTE_FFCTRLMASK: u32 = 0xc0000000; pub const NOTE_FFLAGSMASK: u32 = 0x00ffffff; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_NONE: u32 = 0x00000080; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated since MacOSX 10.9")] pub const NOTE_REAP: u32 = 0x10000000; pub const NOTE_SIGNAL: u32 = 0x08000000; pub const NOTE_EXITSTATUS: u32 = 0x04000000; pub const NOTE_EXIT_DETAIL: u32 = 0x02000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xfff00000; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated since MacOSX 10.9")] pub const NOTE_EXIT_REPARENTED: u32 = 0x00080000; pub const NOTE_EXIT_DETAIL_MASK: u32 = 0x00070000; pub const NOTE_EXIT_DECRYPTFAIL: u32 = 0x00010000; pub const NOTE_EXIT_MEMORY: u32 = 0x00020000; pub const NOTE_EXIT_CSERROR: u32 = 0x00040000; pub const NOTE_VM_PRESSURE: u32 = 0x80000000; pub const NOTE_VM_PRESSURE_TERMINATE: u32 = 0x40000000; pub const NOTE_VM_PRESSURE_SUDDEN_TERMINATE: u32 = 0x20000000; pub const NOTE_VM_ERROR: u32 = 0x10000000; pub const NOTE_SECONDS: u32 = 0x00000001; pub const NOTE_USECONDS: u32 = 0x00000002; pub const NOTE_NSECONDS: u32 = 0x00000004; pub const NOTE_ABSOLUTE: u32 = 0x00000008; pub const NOTE_LEEWAY: u32 = 0x00000010; pub const NOTE_CRITICAL: u32 = 0x00000020; pub const NOTE_BACKGROUND: u32 = 0x00000040; pub const NOTE_MACH_CONTINUOUS_TIME: u32 = 0x00000080; pub const NOTE_MACHTIME: u32 = 0x00000100; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const OCRNL: crate::tcflag_t = 0x00000010; pub const ONOCR: crate::tcflag_t = 0x00000020; pub const ONLRET: crate::tcflag_t = 0x00000040; pub const OFILL: crate::tcflag_t = 0x00000080; pub const NLDLY: crate::tcflag_t = 0x00000300; pub const TABDLY: crate::tcflag_t = 0x00000c04; pub const CRDLY: crate::tcflag_t = 0x00003000; pub const FFDLY: crate::tcflag_t = 0x00004000; pub const BSDLY: crate::tcflag_t = 0x00008000; pub const VTDLY: crate::tcflag_t = 0x00010000; pub const OFDEL: crate::tcflag_t = 0x00020000; pub const NL0: crate::tcflag_t = 0x00000000; pub const NL1: crate::tcflag_t = 0x00000100; pub const TAB0: crate::tcflag_t = 0x00000000; pub const TAB1: crate::tcflag_t = 0x00000400; pub const TAB2: crate::tcflag_t = 0x00000800; pub const CR0: crate::tcflag_t = 0x00000000; pub const CR1: crate::tcflag_t = 0x00001000; pub const CR2: crate::tcflag_t = 0x00002000; pub const CR3: crate::tcflag_t = 0x00003000; pub const FF0: crate::tcflag_t = 0x00000000; pub const FF1: crate::tcflag_t = 0x00004000; pub const BS0: crate::tcflag_t = 0x00000000; pub const BS1: crate::tcflag_t = 0x00008000; pub const TAB3: crate::tcflag_t = 0x00000004; pub const VT0: crate::tcflag_t = 0x00000000; pub const VT1: crate::tcflag_t = 0x00010000; pub const IUTF8: crate::tcflag_t = 0x00004000; pub const CRTSCTS: crate::tcflag_t = 0x00030000; pub const NI_MAXHOST: crate::socklen_t = 1025; pub const NI_MAXSERV: crate::socklen_t = 32; pub const NI_NOFQDN: c_int = 0x00000001; pub const NI_NUMERICHOST: c_int = 0x00000002; pub const NI_NAMEREQD: c_int = 0x00000004; pub const NI_NUMERICSERV: c_int = 0x00000008; pub const NI_NUMERICSCOPE: c_int = 0x00000100; pub const NI_DGRAM: c_int = 0x00000010; pub const Q_GETQUOTA: c_int = 0x300; pub const Q_SETQUOTA: c_int = 0x400; pub const RENAME_SWAP: c_uint = 0x00000002; pub const RENAME_EXCL: c_uint = 0x00000004; pub const RTLD_LOCAL: c_int = 0x4; pub const RTLD_FIRST: c_int = 0x100; pub const RTLD_NODELETE: c_int = 0x80; pub const RTLD_NOLOAD: c_int = 0x10; pub const RTLD_GLOBAL: c_int = 0x8; pub const RTLD_MAIN_ONLY: *mut c_void = -5isize as *mut c_void; pub const _WSTOPPED: c_int = 0o177; pub const LOG_NETINFO: c_int = 12 << 3; pub const LOG_REMOTEAUTH: c_int = 13 << 3; pub const LOG_INSTALL: c_int = 14 << 3; pub const LOG_RAS: c_int = 15 << 3; pub const LOG_LAUNCHD: c_int = 24 << 3; pub const LOG_NFACILITIES: c_int = 25; pub const CTLTYPE: c_int = 0xf; pub const CTLTYPE_NODE: c_int = 1; pub const CTLTYPE_INT: c_int = 2; pub const CTLTYPE_STRING: c_int = 3; pub const CTLTYPE_QUAD: c_int = 4; pub const CTLTYPE_OPAQUE: c_int = 5; pub const CTLTYPE_STRUCT: c_int = CTLTYPE_OPAQUE; pub const CTLFLAG_RD: c_int = 0x80000000; pub const CTLFLAG_WR: c_int = 0x40000000; pub const CTLFLAG_RW: c_int = CTLFLAG_RD | CTLFLAG_WR; pub const CTLFLAG_NOLOCK: c_int = 0x20000000; pub const CTLFLAG_ANYBODY: c_int = 0x10000000; pub const CTLFLAG_SECURE: c_int = 0x08000000; pub const CTLFLAG_MASKED: c_int = 0x04000000; pub const CTLFLAG_NOAUTO: c_int = 0x02000000; pub const CTLFLAG_KERN: c_int = 0x01000000; pub const CTLFLAG_LOCKED: c_int = 0x00800000; pub const CTLFLAG_OID2: c_int = 0x00400000; pub const CTL_UNSPEC: c_int = 0; pub const CTL_KERN: c_int = 1; pub const CTL_VM: c_int = 2; pub const CTL_VFS: c_int = 3; pub const CTL_NET: c_int = 4; pub const CTL_DEBUG: c_int = 5; pub const CTL_HW: c_int = 6; pub const CTL_MACHDEP: c_int = 7; pub const CTL_USER: c_int = 8; pub const CTL_MAXID: c_int = 9; pub const KERN_OSTYPE: c_int = 1; pub const KERN_OSRELEASE: c_int = 2; pub const KERN_OSREV: c_int = 3; pub const KERN_VERSION: c_int = 4; pub const KERN_MAXVNODES: c_int = 5; pub const KERN_MAXPROC: c_int = 6; pub const KERN_MAXFILES: c_int = 7; pub const KERN_ARGMAX: c_int = 8; pub const KERN_SECURELVL: c_int = 9; pub const KERN_HOSTNAME: c_int = 10; pub const KERN_HOSTID: c_int = 11; pub const KERN_CLOCKRATE: c_int = 12; pub const KERN_VNODE: c_int = 13; pub const KERN_PROC: c_int = 14; pub const KERN_FILE: c_int = 15; pub const KERN_PROF: c_int = 16; pub const KERN_POSIX1: c_int = 17; pub const KERN_NGROUPS: c_int = 18; pub const KERN_JOB_CONTROL: c_int = 19; pub const KERN_SAVED_IDS: c_int = 20; pub const KERN_BOOTTIME: c_int = 21; pub const KERN_NISDOMAINNAME: c_int = 22; pub const KERN_DOMAINNAME: c_int = KERN_NISDOMAINNAME; pub const KERN_MAXPARTITIONS: c_int = 23; pub const KERN_KDEBUG: c_int = 24; pub const KERN_UPDATEINTERVAL: c_int = 25; pub const KERN_OSRELDATE: c_int = 26; pub const KERN_NTP_PLL: c_int = 27; pub const KERN_BOOTFILE: c_int = 28; pub const KERN_MAXFILESPERPROC: c_int = 29; pub const KERN_MAXPROCPERUID: c_int = 30; pub const KERN_DUMPDEV: c_int = 31; pub const KERN_IPC: c_int = 32; pub const KERN_DUMMY: c_int = 33; pub const KERN_PS_STRINGS: c_int = 34; pub const KERN_USRSTACK32: c_int = 35; pub const KERN_LOGSIGEXIT: c_int = 36; pub const KERN_SYMFILE: c_int = 37; pub const KERN_PROCARGS: c_int = 38; pub const KERN_NETBOOT: c_int = 40; pub const KERN_SYSV: c_int = 42; pub const KERN_AFFINITY: c_int = 43; pub const KERN_TRANSLATE: c_int = 44; pub const KERN_CLASSIC: c_int = KERN_TRANSLATE; pub const KERN_EXEC: c_int = 45; pub const KERN_CLASSICHANDLER: c_int = KERN_EXEC; pub const KERN_AIOMAX: c_int = 46; pub const KERN_AIOPROCMAX: c_int = 47; pub const KERN_AIOTHREADS: c_int = 48; pub const KERN_COREFILE: c_int = 50; pub const KERN_COREDUMP: c_int = 51; pub const KERN_SUGID_COREDUMP: c_int = 52; pub const KERN_PROCDELAYTERM: c_int = 53; pub const KERN_SHREG_PRIVATIZABLE: c_int = 54; pub const KERN_LOW_PRI_WINDOW: c_int = 56; pub const KERN_LOW_PRI_DELAY: c_int = 57; pub const KERN_POSIX: c_int = 58; pub const KERN_USRSTACK64: c_int = 59; pub const KERN_NX_PROTECTION: c_int = 60; pub const KERN_TFP: c_int = 61; pub const KERN_PROCNAME: c_int = 62; pub const KERN_THALTSTACK: c_int = 63; pub const KERN_SPECULATIVE_READS: c_int = 64; pub const KERN_OSVERSION: c_int = 65; pub const KERN_SAFEBOOT: c_int = 66; pub const KERN_RAGEVNODE: c_int = 68; pub const KERN_TTY: c_int = 69; pub const KERN_CHECKOPENEVT: c_int = 70; pub const KERN_THREADNAME: c_int = 71; pub const KERN_MAXID: c_int = 72; pub const KERN_RAGE_PROC: c_int = 1; pub const KERN_RAGE_THREAD: c_int = 2; pub const KERN_UNRAGE_PROC: c_int = 3; pub const KERN_UNRAGE_THREAD: c_int = 4; pub const KERN_OPENEVT_PROC: c_int = 1; pub const KERN_UNOPENEVT_PROC: c_int = 2; pub const KERN_TFP_POLICY: c_int = 1; pub const KERN_TFP_POLICY_DENY: c_int = 0; pub const KERN_TFP_POLICY_DEFAULT: c_int = 2; pub const KERN_KDEFLAGS: c_int = 1; pub const KERN_KDDFLAGS: c_int = 2; pub const KERN_KDENABLE: c_int = 3; pub const KERN_KDSETBUF: c_int = 4; pub const KERN_KDGETBUF: c_int = 5; pub const KERN_KDSETUP: c_int = 6; pub const KERN_KDREMOVE: c_int = 7; pub const KERN_KDSETREG: c_int = 8; pub const KERN_KDGETREG: c_int = 9; pub const KERN_KDREADTR: c_int = 10; pub const KERN_KDPIDTR: c_int = 11; pub const KERN_KDTHRMAP: c_int = 12; pub const KERN_KDPIDEX: c_int = 14; pub const KERN_KDSETRTCDEC: c_int = 15; pub const KERN_KDGETENTROPY: c_int = 16; pub const KERN_KDWRITETR: c_int = 17; pub const KERN_KDWRITEMAP: c_int = 18; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Removed in MacOSX 10.12")] pub const KERN_KDENABLE_BG_TRACE: c_int = 19; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Removed in MacOSX 10.12")] pub const KERN_KDDISABLE_BG_TRACE: c_int = 20; pub const KERN_KDREADCURTHRMAP: c_int = 21; pub const KERN_KDSET_TYPEFILTER: c_int = 22; pub const KERN_KDBUFWAIT: c_int = 23; pub const KERN_KDCPUMAP: c_int = 24; pub const KERN_PROC_ALL: c_int = 0; pub const KERN_PROC_PID: c_int = 1; pub const KERN_PROC_PGRP: c_int = 2; pub const KERN_PROC_SESSION: c_int = 3; pub const KERN_PROC_TTY: c_int = 4; pub const KERN_PROC_UID: c_int = 5; pub const KERN_PROC_RUID: c_int = 6; pub const KERN_PROC_LCID: c_int = 7; pub const KERN_SUCCESS: c_int = 0; pub const KERN_INVALID_ADDRESS: c_int = 1; pub const KERN_PROTECTION_FAILURE: c_int = 2; pub const KERN_NO_SPACE: c_int = 3; pub const KERN_INVALID_ARGUMENT: c_int = 4; pub const KERN_FAILURE: c_int = 5; pub const KERN_RESOURCE_SHORTAGE: c_int = 6; pub const KERN_NOT_RECEIVER: c_int = 7; pub const KERN_NO_ACCESS: c_int = 8; pub const KERN_MEMORY_FAILURE: c_int = 9; pub const KERN_MEMORY_ERROR: c_int = 10; pub const KERN_ALREADY_IN_SET: c_int = 11; pub const KERN_NOT_IN_SET: c_int = 12; pub const KERN_NAME_EXISTS: c_int = 13; pub const KERN_ABORTED: c_int = 14; pub const KERN_INVALID_NAME: c_int = 15; pub const KERN_INVALID_TASK: c_int = 16; pub const KERN_INVALID_RIGHT: c_int = 17; pub const KERN_INVALID_VALUE: c_int = 18; pub const KERN_UREFS_OVERFLOW: c_int = 19; pub const KERN_INVALID_CAPABILITY: c_int = 20; pub const KERN_RIGHT_EXISTS: c_int = 21; pub const KERN_INVALID_HOST: c_int = 22; pub const KERN_MEMORY_PRESENT: c_int = 23; pub const KERN_MEMORY_DATA_MOVED: c_int = 24; pub const KERN_MEMORY_RESTART_COPY: c_int = 25; pub const KERN_INVALID_PROCESSOR_SET: c_int = 26; pub const KERN_POLICY_LIMIT: c_int = 27; pub const KERN_INVALID_POLICY: c_int = 28; pub const KERN_INVALID_OBJECT: c_int = 29; pub const KERN_ALREADY_WAITING: c_int = 30; pub const KERN_DEFAULT_SET: c_int = 31; pub const KERN_EXCEPTION_PROTECTED: c_int = 32; pub const KERN_INVALID_LEDGER: c_int = 33; pub const KERN_INVALID_MEMORY_CONTROL: c_int = 34; pub const KERN_INVALID_SECURITY: c_int = 35; pub const KERN_NOT_DEPRESSED: c_int = 36; pub const KERN_TERMINATED: c_int = 37; pub const KERN_LOCK_SET_DESTROYED: c_int = 38; pub const KERN_LOCK_UNSTABLE: c_int = 39; pub const KERN_LOCK_OWNED: c_int = 40; pub const KERN_LOCK_OWNED_SELF: c_int = 41; pub const KERN_SEMAPHORE_DESTROYED: c_int = 42; pub const KERN_RPC_SERVER_TERMINATED: c_int = 43; pub const KERN_RPC_TERMINATE_ORPHAN: c_int = 44; pub const KERN_RPC_CONTINUE_ORPHAN: c_int = 45; pub const KERN_NOT_SUPPORTED: c_int = 46; pub const KERN_NODE_DOWN: c_int = 47; pub const KERN_NOT_WAITING: c_int = 48; pub const KERN_OPERATION_TIMED_OUT: c_int = 49; pub const KERN_CODESIGN_ERROR: c_int = 50; pub const KERN_POLICY_STATIC: c_int = 51; pub const KERN_INSUFFICIENT_BUFFER_SIZE: c_int = 52; pub const KIPC_MAXSOCKBUF: c_int = 1; pub const KIPC_SOCKBUF_WASTE: c_int = 2; pub const KIPC_SOMAXCONN: c_int = 3; pub const KIPC_MAX_LINKHDR: c_int = 4; pub const KIPC_MAX_PROTOHDR: c_int = 5; pub const KIPC_MAX_HDR: c_int = 6; pub const KIPC_MAX_DATALEN: c_int = 7; pub const KIPC_MBSTAT: c_int = 8; pub const KIPC_NMBCLUSTERS: c_int = 9; pub const KIPC_SOQLIMITCOMPAT: c_int = 10; pub const VM_METER: c_int = 1; pub const VM_LOADAVG: c_int = 2; pub const VM_MACHFACTOR: c_int = 4; pub const VM_SWAPUSAGE: c_int = 5; pub const VM_MAXID: c_int = 6; pub const VM_PROT_NONE: crate::vm_prot_t = 0x00; pub const VM_PROT_READ: crate::vm_prot_t = 0x01; pub const VM_PROT_WRITE: crate::vm_prot_t = 0x02; pub const VM_PROT_EXECUTE: crate::vm_prot_t = 0x04; pub const MEMORY_OBJECT_NULL: crate::memory_object_t = 0; pub const HW_MACHINE: c_int = 1; pub const HW_MODEL: c_int = 2; pub const HW_NCPU: c_int = 3; pub const HW_BYTEORDER: c_int = 4; pub const HW_PHYSMEM: c_int = 5; pub const HW_USERMEM: c_int = 6; pub const HW_PAGESIZE: c_int = 7; pub const HW_DISKNAMES: c_int = 8; pub const HW_DISKSTATS: c_int = 9; pub const HW_EPOCH: c_int = 10; pub const HW_FLOATINGPT: c_int = 11; pub const HW_MACHINE_ARCH: c_int = 12; pub const HW_VECTORUNIT: c_int = 13; pub const HW_BUS_FREQ: c_int = 14; pub const HW_CPU_FREQ: c_int = 15; pub const HW_CACHELINE: c_int = 16; pub const HW_L1ICACHESIZE: c_int = 17; pub const HW_L1DCACHESIZE: c_int = 18; pub const HW_L2SETTINGS: c_int = 19; pub const HW_L2CACHESIZE: c_int = 20; pub const HW_L3SETTINGS: c_int = 21; pub const HW_L3CACHESIZE: c_int = 22; pub const HW_TB_FREQ: c_int = 23; pub const HW_MEMSIZE: c_int = 24; pub const HW_AVAILCPU: c_int = 25; pub const HW_TARGET: c_int = 26; pub const HW_PRODUCT: c_int = 27; pub const HW_MAXID: c_int = 28; pub const USER_CS_PATH: c_int = 1; pub const USER_BC_BASE_MAX: c_int = 2; pub const USER_BC_DIM_MAX: c_int = 3; pub const USER_BC_SCALE_MAX: c_int = 4; pub const USER_BC_STRING_MAX: c_int = 5; pub const USER_COLL_WEIGHTS_MAX: c_int = 6; pub const USER_EXPR_NEST_MAX: c_int = 7; pub const USER_LINE_MAX: c_int = 8; pub const USER_RE_DUP_MAX: c_int = 9; pub const USER_POSIX2_VERSION: c_int = 10; pub const USER_POSIX2_C_BIND: c_int = 11; pub const USER_POSIX2_C_DEV: c_int = 12; pub const USER_POSIX2_CHAR_TERM: c_int = 13; pub const USER_POSIX2_FORT_DEV: c_int = 14; pub const USER_POSIX2_FORT_RUN: c_int = 15; pub const USER_POSIX2_LOCALEDEF: c_int = 16; pub const USER_POSIX2_SW_DEV: c_int = 17; pub const USER_POSIX2_UPE: c_int = 18; pub const USER_STREAM_MAX: c_int = 19; pub const USER_TZNAME_MAX: c_int = 20; pub const USER_MAXID: c_int = 21; pub const CTL_DEBUG_NAME: c_int = 0; pub const CTL_DEBUG_VALUE: c_int = 1; pub const CTL_DEBUG_MAXID: c_int = 20; pub const PRIO_DARWIN_THREAD: c_int = 3; pub const PRIO_DARWIN_PROCESS: c_int = 4; pub const PRIO_DARWIN_BG: c_int = 0x1000; pub const PRIO_DARWIN_NONUI: c_int = 0x1001; pub const SEM_FAILED: *mut sem_t = -1isize as *mut crate::sem_t; pub const AI_PASSIVE: c_int = 0x00000001; pub const AI_CANONNAME: c_int = 0x00000002; pub const AI_NUMERICHOST: c_int = 0x00000004; pub const AI_NUMERICSERV: c_int = 0x00001000; pub const AI_MASK: c_int = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG; pub const AI_ALL: c_int = 0x00000100; pub const AI_V4MAPPED_CFG: c_int = 0x00000200; pub const AI_ADDRCONFIG: c_int = 0x00000400; pub const AI_V4MAPPED: c_int = 0x00000800; pub const AI_DEFAULT: c_int = AI_V4MAPPED_CFG | AI_ADDRCONFIG; pub const AI_UNUSABLE: c_int = 0x10000000; pub const SIGEV_NONE: c_int = 0; pub const SIGEV_SIGNAL: c_int = 1; pub const SIGEV_THREAD: c_int = 3; pub const AIO_CANCELED: c_int = 2; pub const AIO_NOTCANCELED: c_int = 4; pub const AIO_ALLDONE: c_int = 1; #[deprecated( since = "0.2.64", note = "Can vary at runtime. Use sysconf(3) instead" )] pub const AIO_LISTIO_MAX: c_int = 16; pub const LIO_NOP: c_int = 0; pub const LIO_WRITE: c_int = 2; pub const LIO_READ: c_int = 1; pub const LIO_WAIT: c_int = 2; pub const LIO_NOWAIT: c_int = 1; pub const WEXITED: c_int = 0x00000004; pub const WSTOPPED: c_int = 0x00000008; pub const WCONTINUED: c_int = 0x00000010; pub const WNOWAIT: c_int = 0x00000020; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; pub const XATTR_NOFOLLOW: c_int = 0x0001; pub const XATTR_CREATE: c_int = 0x0002; pub const XATTR_REPLACE: c_int = 0x0004; pub const XATTR_NOSECURITY: c_int = 0x0008; pub const XATTR_NODEFAULT: c_int = 0x0010; pub const XATTR_SHOWCOMPRESSION: c_int = 0x0020; pub const NET_RT_IFLIST2: c_int = 0x0006; // net/route.h pub const RTF_DELCLONE: c_int = 0x80; pub const RTF_CLONING: c_int = 0x100; pub const RTF_XRESOLVE: c_int = 0x200; pub const RTF_LLINFO: c_int = 0x400; pub const RTF_NOIFREF: c_int = 0x2000; pub const RTF_PRCLONING: c_int = 0x10000; pub const RTF_WASCLONED: c_int = 0x20000; pub const RTF_PROTO3: c_int = 0x40000; pub const RTF_PINNED: c_int = 0x100000; pub const RTF_LOCAL: c_int = 0x200000; pub const RTF_BROADCAST: c_int = 0x400000; pub const RTF_MULTICAST: c_int = 0x800000; pub const RTF_IFSCOPE: c_int = 0x1000000; pub const RTF_CONDEMNED: c_int = 0x2000000; pub const RTF_IFREF: c_int = 0x4000000; pub const RTF_PROXY: c_int = 0x8000000; pub const RTF_ROUTER: c_int = 0x10000000; pub const RTF_DEAD: c_int = 0x20000000; pub const RTF_GLOBAL: c_int = 0x40000000; pub const RTM_VERSION: c_int = 5; // Message types pub const RTM_LOCK: c_int = 0x8; pub const RTM_OLDADD: c_int = 0x9; pub const RTM_OLDDEL: c_int = 0xa; pub const RTM_RESOLVE: c_int = 0xb; pub const RTM_NEWADDR: c_int = 0xc; pub const RTM_DELADDR: c_int = 0xd; pub const RTM_IFINFO: c_int = 0xe; pub const RTM_NEWMADDR: c_int = 0xf; pub const RTM_DELMADDR: c_int = 0x10; pub const RTM_IFINFO2: c_int = 0x12; pub const RTM_NEWMADDR2: c_int = 0x13; pub const RTM_GET2: c_int = 0x14; // Bitmask values for rtm_inits and rmx_locks. pub const RTV_MTU: c_int = 0x1; pub const RTV_HOPCOUNT: c_int = 0x2; pub const RTV_EXPIRE: c_int = 0x4; pub const RTV_RPIPE: c_int = 0x8; pub const RTV_SPIPE: c_int = 0x10; pub const RTV_SSTHRESH: c_int = 0x20; pub const RTV_RTT: c_int = 0x40; pub const RTV_RTTVAR: c_int = 0x80; pub const RTAX_MAX: c_int = 8; pub const KERN_PROCARGS2: c_int = 49; pub const PROC_PIDTASKALLINFO: c_int = 2; pub const PROC_PIDTBSDINFO: c_int = 3; pub const PROC_PIDTASKINFO: c_int = 4; pub const PROC_PIDTHREADINFO: c_int = 5; pub const PROC_PIDVNODEPATHINFO: c_int = 9; pub const PROC_PIDPATHINFO_MAXSIZE: c_int = 4096; pub const PROC_PIDLISTFDS: c_int = 1; pub const PROC_PIDLISTFD_SIZE: c_int = mem::size_of::() as c_int; pub const PROX_FDTYPE_ATALK: c_int = 0; pub const PROX_FDTYPE_VNODE: c_int = 1; pub const PROX_FDTYPE_SOCKET: c_int = 2; pub const PROX_FDTYPE_PSHM: c_int = 3; pub const PROX_FDTYPE_PSEM: c_int = 4; pub const PROX_FDTYPE_KQUEUE: c_int = 5; pub const PROX_FDTYPE_PIPE: c_int = 6; pub const PROX_FDTYPE_FSEVENTS: c_int = 7; pub const PROX_FDTYPE_NETPOLICY: c_int = 9; pub const PROX_FDTYPE_CHANNEL: c_int = 10; pub const PROX_FDTYPE_NEXUS: c_int = 11; pub const PROC_CSM_ALL: c_uint = 0x0001; pub const PROC_CSM_NOSMT: c_uint = 0x0002; pub const PROC_CSM_TECS: c_uint = 0x0004; pub const MAXCOMLEN: usize = 16; pub const MAXTHREADNAMESIZE: usize = 64; pub const XUCRED_VERSION: c_uint = 0; pub const LC_SEGMENT: u32 = 0x1; pub const LC_SEGMENT_64: u32 = 0x19; pub const MH_MAGIC: u32 = 0xfeedface; pub const MH_MAGIC_64: u32 = 0xfeedfacf; // net/if_utun.h pub const UTUN_OPT_FLAGS: c_int = 1; pub const UTUN_OPT_IFNAME: c_int = 2; // net/bpf.h pub const DLT_NULL: c_uint = 0; // no link-layer encapsulation pub const DLT_EN10MB: c_uint = 1; // Ethernet (10Mb) pub const DLT_EN3MB: c_uint = 2; // Experimental Ethernet (3Mb) pub const DLT_AX25: c_uint = 3; // Amateur Radio AX.25 pub const DLT_PRONET: c_uint = 4; // Proteon ProNET Token Ring pub const DLT_CHAOS: c_uint = 5; // Chaos pub const DLT_IEEE802: c_uint = 6; // IEEE 802 Networks pub const DLT_ARCNET: c_uint = 7; // ARCNET pub const DLT_SLIP: c_uint = 8; // Serial Line IP pub const DLT_PPP: c_uint = 9; // Point-to-point Protocol pub const DLT_FDDI: c_uint = 10; // FDDI pub const DLT_ATM_RFC1483: c_uint = 11; // LLC/SNAP encapsulated atm pub const DLT_RAW: c_uint = 12; // raw IP pub const DLT_LOOP: c_uint = 108; // https://github.com/apple/darwin-xnu/blob/HEAD/bsd/net/bpf.h#L100 // sizeof(i32) pub const BPF_ALIGNMENT: c_int = 4; // sys/mount.h pub const MNT_NODEV: c_int = 0x00000010; pub const MNT_UNION: c_int = 0x00000020; pub const MNT_CPROTECT: c_int = 0x00000080; // MAC labeled / "quarantined" flag pub const MNT_QUARANTINE: c_int = 0x00000400; // Flags set by internal operations. pub const MNT_LOCAL: c_int = 0x00001000; pub const MNT_QUOTA: c_int = 0x00002000; pub const MNT_ROOTFS: c_int = 0x00004000; pub const MNT_DOVOLFS: c_int = 0x00008000; pub const MNT_DONTBROWSE: c_int = 0x00100000; pub const MNT_IGNORE_OWNERSHIP: c_int = 0x00200000; pub const MNT_AUTOMOUNTED: c_int = 0x00400000; pub const MNT_JOURNALED: c_int = 0x00800000; pub const MNT_NOUSERXATTR: c_int = 0x01000000; pub const MNT_DEFWRITE: c_int = 0x02000000; pub const MNT_MULTILABEL: c_int = 0x04000000; pub const MNT_NOATIME: c_int = 0x10000000; pub const MNT_SNAPSHOT: c_int = 0x40000000; // External filesystem command modifier flags. pub const MNT_NOBLOCK: c_int = 0x00020000; // sys/spawn.h: // DIFF(main): changed to `c_short` in f62eb023ab pub const POSIX_SPAWN_RESETIDS: c_int = 0x0001; pub const POSIX_SPAWN_SETPGROUP: c_int = 0x0002; pub const POSIX_SPAWN_SETSIGDEF: c_int = 0x0004; pub const POSIX_SPAWN_SETSIGMASK: c_int = 0x0008; pub const POSIX_SPAWN_SETEXEC: c_int = 0x0040; pub const POSIX_SPAWN_START_SUSPENDED: c_int = 0x0080; pub const POSIX_SPAWN_CLOEXEC_DEFAULT: c_int = 0x4000; // sys/ipc.h: pub const IPC_CREAT: c_int = 0x200; pub const IPC_EXCL: c_int = 0x400; pub const IPC_NOWAIT: c_int = 0x800; pub const IPC_PRIVATE: key_t = 0; pub const IPC_RMID: c_int = 0; pub const IPC_SET: c_int = 1; pub const IPC_STAT: c_int = 2; pub const IPC_R: c_int = 0x100; pub const IPC_W: c_int = 0x80; pub const IPC_M: c_int = 0x1000; // sys/sem.h pub const SEM_UNDO: c_int = 0o10000; pub const GETNCNT: c_int = 3; pub const GETPID: c_int = 4; pub const GETVAL: c_int = 5; pub const GETALL: c_int = 6; pub const GETZCNT: c_int = 7; pub const SETVAL: c_int = 8; pub const SETALL: c_int = 9; // sys/shm.h pub const SHM_RDONLY: c_int = 0x1000; pub const SHM_RND: c_int = 0x2000; #[cfg(target_arch = "aarch64")] pub const SHMLBA: c_int = 16 * 1024; #[cfg(not(target_arch = "aarch64"))] pub const SHMLBA: c_int = 4096; pub const SHM_R: c_int = IPC_R; pub const SHM_W: c_int = IPC_W; // Flags for chflags(2) pub const UF_SETTABLE: c_uint = 0x0000ffff; pub const UF_NODUMP: c_uint = 0x00000001; pub const UF_IMMUTABLE: c_uint = 0x00000002; pub const UF_APPEND: c_uint = 0x00000004; pub const UF_OPAQUE: c_uint = 0x00000008; pub const UF_COMPRESSED: c_uint = 0x00000020; pub const UF_TRACKED: c_uint = 0x00000040; pub const SF_SETTABLE: c_uint = 0xffff0000; pub const SF_ARCHIVED: c_uint = 0x00010000; pub const SF_IMMUTABLE: c_uint = 0x00020000; pub const SF_APPEND: c_uint = 0x00040000; pub const UF_HIDDEN: c_uint = 0x00008000; // pub const NTP_API: c_int = 4; pub const MAXPHASE: c_long = 500000000; pub const MAXFREQ: c_long = 500000; pub const MINSEC: c_int = 256; pub const MAXSEC: c_int = 2048; pub const NANOSECOND: c_long = 1000000000; pub const SCALE_PPM: c_int = 65; pub const MAXTC: c_int = 10; pub const MOD_OFFSET: c_uint = 0x0001; pub const MOD_FREQUENCY: c_uint = 0x0002; pub const MOD_MAXERROR: c_uint = 0x0004; pub const MOD_ESTERROR: c_uint = 0x0008; pub const MOD_STATUS: c_uint = 0x0010; pub const MOD_TIMECONST: c_uint = 0x0020; pub const MOD_PPSMAX: c_uint = 0x0040; pub const MOD_TAI: c_uint = 0x0080; pub const MOD_MICRO: c_uint = 0x1000; pub const MOD_NANO: c_uint = 0x2000; pub const MOD_CLKB: c_uint = 0x4000; pub const MOD_CLKA: c_uint = 0x8000; pub const STA_PLL: c_int = 0x0001; pub const STA_PPSFREQ: c_int = 0x0002; pub const STA_PPSTIME: c_int = 0x0004; pub const STA_FLL: c_int = 0x0008; pub const STA_INS: c_int = 0x0010; pub const STA_DEL: c_int = 0x0020; pub const STA_UNSYNC: c_int = 0x0040; pub const STA_FREQHOLD: c_int = 0x0080; pub const STA_PPSSIGNAL: c_int = 0x0100; pub const STA_PPSJITTER: c_int = 0x0200; pub const STA_PPSWANDER: c_int = 0x0400; pub const STA_PPSERROR: c_int = 0x0800; pub const STA_CLOCKERR: c_int = 0x1000; pub const STA_NANO: c_int = 0x2000; pub const STA_MODE: c_int = 0x4000; pub const STA_CLK: c_int = 0x8000; pub const STA_RONLY: c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const TIME_OK: c_int = 0; pub const TIME_INS: c_int = 1; pub const TIME_DEL: c_int = 2; pub const TIME_OOP: c_int = 3; pub const TIME_WAIT: c_int = 4; pub const TIME_ERROR: c_int = 5; // pub const MNT_WAIT: c_int = 1; pub const MNT_NOWAIT: c_int = 2; // pub const THREAD_STANDARD_POLICY: c_int = 1; pub const THREAD_STANDARD_POLICY_COUNT: c_int = 0; pub const THREAD_EXTENDED_POLICY: c_int = 1; pub const THREAD_TIME_CONSTRAINT_POLICY: c_int = 2; pub const THREAD_PRECEDENCE_POLICY: c_int = 3; pub const THREAD_AFFINITY_POLICY: c_int = 4; pub const THREAD_AFFINITY_TAG_NULL: c_int = 0; pub const THREAD_BACKGROUND_POLICY: c_int = 5; pub const THREAD_BACKGROUND_POLICY_DARWIN_BG: c_int = 0x1000; pub const THREAD_LATENCY_QOS_POLICY: c_int = 7; pub const THREAD_THROUGHPUT_QOS_POLICY: c_int = 8; // pub const TH_STATE_RUNNING: c_int = 1; pub const TH_STATE_STOPPED: c_int = 2; pub const TH_STATE_WAITING: c_int = 3; pub const TH_STATE_UNINTERRUPTIBLE: c_int = 4; pub const TH_STATE_HALTED: c_int = 5; pub const TH_FLAGS_SWAPPED: c_int = 0x1; pub const TH_FLAGS_IDLE: c_int = 0x2; pub const TH_FLAGS_GLOBAL_FORCED_IDLE: c_int = 0x4; pub const THREAD_BASIC_INFO: c_int = 3; pub const THREAD_IDENTIFIER_INFO: c_int = 4; pub const THREAD_EXTENDED_INFO: c_int = 5; // CommonCrypto/CommonCryptoError.h pub const kCCSuccess: i32 = 0; pub const kCCParamError: i32 = -4300; pub const kCCBufferTooSmall: i32 = -4301; pub const kCCMemoryFailure: i32 = -4302; pub const kCCAlignmentError: i32 = -4303; pub const kCCDecodeError: i32 = -4304; pub const kCCUnimplemented: i32 = -4305; pub const kCCOverflow: i32 = -4306; pub const kCCRNGFailure: i32 = -4307; pub const kCCUnspecifiedError: i32 = -4308; pub const kCCCallSequenceError: i32 = -4309; pub const kCCKeySizeError: i32 = -4310; pub const kCCInvalidKey: i32 = -4311; // mach/host_info.h pub const HOST_LOAD_INFO: i32 = 1; pub const HOST_VM_INFO: i32 = 2; pub const HOST_CPU_LOAD_INFO: i32 = 3; pub const HOST_VM_INFO64: i32 = 4; pub const HOST_EXTMOD_INFO64: i32 = 5; pub const HOST_EXPIRED_TASK_INFO: i32 = 6; // mach/vm_statistics.h pub const VM_PAGE_QUERY_PAGE_PRESENT: i32 = 0x1; pub const VM_PAGE_QUERY_PAGE_FICTITIOUS: i32 = 0x2; pub const VM_PAGE_QUERY_PAGE_REF: i32 = 0x4; pub const VM_PAGE_QUERY_PAGE_DIRTY: i32 = 0x8; pub const VM_PAGE_QUERY_PAGE_PAGED_OUT: i32 = 0x10; pub const VM_PAGE_QUERY_PAGE_COPIED: i32 = 0x20; pub const VM_PAGE_QUERY_PAGE_SPECULATIVE: i32 = 0x40; pub const VM_PAGE_QUERY_PAGE_EXTERNAL: i32 = 0x80; pub const VM_PAGE_QUERY_PAGE_CS_VALIDATED: i32 = 0x100; pub const VM_PAGE_QUERY_PAGE_CS_TAINTED: i32 = 0x200; pub const VM_PAGE_QUERY_PAGE_CS_NX: i32 = 0x400; // mach/task_info.h pub const TASK_THREAD_TIMES_INFO: u32 = 3; pub const HOST_CPU_LOAD_INFO_COUNT: u32 = 4; pub const MACH_TASK_BASIC_INFO: u32 = 20; pub const MACH_PORT_NULL: i32 = 0; pub const RUSAGE_INFO_V0: c_int = 0; pub const RUSAGE_INFO_V1: c_int = 1; pub const RUSAGE_INFO_V2: c_int = 2; pub const RUSAGE_INFO_V3: c_int = 3; pub const RUSAGE_INFO_V4: c_int = 4; // copyfile.h pub const COPYFILE_ACL: crate::copyfile_flags_t = 1 << 0; pub const COPYFILE_STAT: crate::copyfile_flags_t = 1 << 1; pub const COPYFILE_XATTR: crate::copyfile_flags_t = 1 << 2; pub const COPYFILE_DATA: crate::copyfile_flags_t = 1 << 3; pub const COPYFILE_SECURITY: crate::copyfile_flags_t = COPYFILE_STAT | COPYFILE_ACL; pub const COPYFILE_METADATA: crate::copyfile_flags_t = COPYFILE_SECURITY | COPYFILE_XATTR; pub const COPYFILE_RECURSIVE: crate::copyfile_flags_t = 1 << 15; pub const COPYFILE_CHECK: crate::copyfile_flags_t = 1 << 16; pub const COPYFILE_EXCL: crate::copyfile_flags_t = 1 << 17; pub const COPYFILE_NOFOLLOW_SRC: crate::copyfile_flags_t = 1 << 18; pub const COPYFILE_NOFOLLOW_DST: crate::copyfile_flags_t = 1 << 19; pub const COPYFILE_MOVE: crate::copyfile_flags_t = 1 << 20; pub const COPYFILE_UNLINK: crate::copyfile_flags_t = 1 << 21; pub const COPYFILE_NOFOLLOW: crate::copyfile_flags_t = COPYFILE_NOFOLLOW_SRC | COPYFILE_NOFOLLOW_DST; pub const COPYFILE_PACK: crate::copyfile_flags_t = 1 << 22; pub const COPYFILE_UNPACK: crate::copyfile_flags_t = 1 << 23; pub const COPYFILE_CLONE: crate::copyfile_flags_t = 1 << 24; pub const COPYFILE_CLONE_FORCE: crate::copyfile_flags_t = 1 << 25; pub const COPYFILE_RUN_IN_PLACE: crate::copyfile_flags_t = 1 << 26; pub const COPYFILE_DATA_SPARSE: crate::copyfile_flags_t = 1 << 27; pub const COPYFILE_PRESERVE_DST_TRACKED: crate::copyfile_flags_t = 1 << 28; pub const COPYFILE_VERBOSE: crate::copyfile_flags_t = 1 << 30; pub const COPYFILE_RECURSE_ERROR: c_int = 0; pub const COPYFILE_RECURSE_FILE: c_int = 1; pub const COPYFILE_RECURSE_DIR: c_int = 2; pub const COPYFILE_RECURSE_DIR_CLEANUP: c_int = 3; pub const COPYFILE_COPY_DATA: c_int = 4; pub const COPYFILE_COPY_XATTR: c_int = 5; pub const COPYFILE_START: c_int = 1; pub const COPYFILE_FINISH: c_int = 2; pub const COPYFILE_ERR: c_int = 3; pub const COPYFILE_PROGRESS: c_int = 4; pub const COPYFILE_CONTINUE: c_int = 0; pub const COPYFILE_SKIP: c_int = 1; pub const COPYFILE_QUIT: c_int = 2; pub const COPYFILE_STATE_SRC_FD: c_int = 1; pub const COPYFILE_STATE_SRC_FILENAME: c_int = 2; pub const COPYFILE_STATE_DST_FD: c_int = 3; pub const COPYFILE_STATE_DST_FILENAME: c_int = 4; pub const COPYFILE_STATE_QUARANTINE: c_int = 5; pub const COPYFILE_STATE_STATUS_CB: c_int = 6; pub const COPYFILE_STATE_STATUS_CTX: c_int = 7; pub const COPYFILE_STATE_COPIED: c_int = 8; pub const COPYFILE_STATE_XATTRNAME: c_int = 9; pub const COPYFILE_STATE_WAS_CLONED: c_int = 10; pub const COPYFILE_STATE_SRC_BSIZE: c_int = 11; pub const COPYFILE_STATE_DST_BSIZE: c_int = 12; pub const COPYFILE_STATE_BSIZE: c_int = 13; // pub const ATTR_BIT_MAP_COUNT: c_ushort = 5; pub const FSOPT_NOFOLLOW: u32 = 0x1; pub const FSOPT_NOFOLLOW_ANY: u32 = 0x800; pub const FSOPT_REPORT_FULLSIZE: u32 = 0x4; pub const FSOPT_PACK_INVAL_ATTRS: u32 = 0x8; pub const FSOPT_ATTR_CMN_EXTENDED: u32 = 0x20; pub const FSOPT_RETURN_REALDEV: u32 = 0x200; pub const ATTR_CMN_NAME: attrgroup_t = 0x00000001; pub const ATTR_CMN_DEVID: attrgroup_t = 0x00000002; pub const ATTR_CMN_FSID: attrgroup_t = 0x00000004; pub const ATTR_CMN_OBJTYPE: attrgroup_t = 0x00000008; pub const ATTR_CMN_OBJTAG: attrgroup_t = 0x00000010; pub const ATTR_CMN_OBJID: attrgroup_t = 0x00000020; pub const ATTR_CMN_OBJPERMANENTID: attrgroup_t = 0x00000040; pub const ATTR_CMN_PAROBJID: attrgroup_t = 0x00000080; pub const ATTR_CMN_SCRIPT: attrgroup_t = 0x00000100; pub const ATTR_CMN_CRTIME: attrgroup_t = 0x00000200; pub const ATTR_CMN_MODTIME: attrgroup_t = 0x00000400; pub const ATTR_CMN_CHGTIME: attrgroup_t = 0x00000800; pub const ATTR_CMN_ACCTIME: attrgroup_t = 0x00001000; pub const ATTR_CMN_BKUPTIME: attrgroup_t = 0x00002000; pub const ATTR_CMN_FNDRINFO: attrgroup_t = 0x00004000; pub const ATTR_CMN_OWNERID: attrgroup_t = 0x00008000; pub const ATTR_CMN_GRPID: attrgroup_t = 0x00010000; pub const ATTR_CMN_ACCESSMASK: attrgroup_t = 0x00020000; pub const ATTR_CMN_FLAGS: attrgroup_t = 0x00040000; pub const ATTR_CMN_GEN_COUNT: attrgroup_t = 0x00080000; pub const ATTR_CMN_DOCUMENT_ID: attrgroup_t = 0x00100000; pub const ATTR_CMN_USERACCESS: attrgroup_t = 0x00200000; pub const ATTR_CMN_EXTENDED_SECURITY: attrgroup_t = 0x00400000; pub const ATTR_CMN_UUID: attrgroup_t = 0x00800000; pub const ATTR_CMN_GRPUUID: attrgroup_t = 0x01000000; pub const ATTR_CMN_FILEID: attrgroup_t = 0x02000000; pub const ATTR_CMN_PARENTID: attrgroup_t = 0x04000000; pub const ATTR_CMN_FULLPATH: attrgroup_t = 0x08000000; pub const ATTR_CMN_ADDEDTIME: attrgroup_t = 0x10000000; pub const ATTR_CMN_DATA_PROTECT_FLAGS: attrgroup_t = 0x40000000; pub const ATTR_CMN_RETURNED_ATTRS: attrgroup_t = 0x80000000; pub const ATTR_VOL_FSTYPE: attrgroup_t = 0x00000001; pub const ATTR_VOL_SIGNATURE: attrgroup_t = 0x00000002; pub const ATTR_VOL_SIZE: attrgroup_t = 0x00000004; pub const ATTR_VOL_SPACEFREE: attrgroup_t = 0x00000008; pub const ATTR_VOL_SPACEAVAIL: attrgroup_t = 0x00000010; pub const ATTR_VOL_MINALLOCATION: attrgroup_t = 0x00000020; pub const ATTR_VOL_ALLOCATIONCLUMP: attrgroup_t = 0x00000040; pub const ATTR_VOL_IOBLOCKSIZE: attrgroup_t = 0x00000080; pub const ATTR_VOL_OBJCOUNT: attrgroup_t = 0x00000100; pub const ATTR_VOL_FILECOUNT: attrgroup_t = 0x00000200; pub const ATTR_VOL_DIRCOUNT: attrgroup_t = 0x00000400; pub const ATTR_VOL_MAXOBJCOUNT: attrgroup_t = 0x00000800; pub const ATTR_VOL_MOUNTPOINT: attrgroup_t = 0x00001000; pub const ATTR_VOL_NAME: attrgroup_t = 0x00002000; pub const ATTR_VOL_MOUNTFLAGS: attrgroup_t = 0x00004000; pub const ATTR_VOL_MOUNTEDDEVICE: attrgroup_t = 0x00008000; pub const ATTR_VOL_ENCODINGSUSED: attrgroup_t = 0x00010000; pub const ATTR_VOL_CAPABILITIES: attrgroup_t = 0x00020000; pub const ATTR_VOL_UUID: attrgroup_t = 0x00040000; pub const ATTR_VOL_SPACEUSED: attrgroup_t = 0x00800000; pub const ATTR_VOL_QUOTA_SIZE: attrgroup_t = 0x10000000; pub const ATTR_VOL_RESERVED_SIZE: attrgroup_t = 0x20000000; pub const ATTR_VOL_ATTRIBUTES: attrgroup_t = 0x40000000; pub const ATTR_VOL_INFO: attrgroup_t = 0x80000000; pub const ATTR_DIR_LINKCOUNT: attrgroup_t = 0x00000001; pub const ATTR_DIR_ENTRYCOUNT: attrgroup_t = 0x00000002; pub const ATTR_DIR_MOUNTSTATUS: attrgroup_t = 0x00000004; pub const ATTR_DIR_ALLOCSIZE: attrgroup_t = 0x00000008; pub const ATTR_DIR_IOBLOCKSIZE: attrgroup_t = 0x00000010; pub const ATTR_DIR_DATALENGTH: attrgroup_t = 0x00000020; pub const ATTR_FILE_LINKCOUNT: attrgroup_t = 0x00000001; pub const ATTR_FILE_TOTALSIZE: attrgroup_t = 0x00000002; pub const ATTR_FILE_ALLOCSIZE: attrgroup_t = 0x00000004; pub const ATTR_FILE_IOBLOCKSIZE: attrgroup_t = 0x00000008; pub const ATTR_FILE_DEVTYPE: attrgroup_t = 0x00000020; pub const ATTR_FILE_FORKCOUNT: attrgroup_t = 0x00000080; pub const ATTR_FILE_FORKLIST: attrgroup_t = 0x00000100; pub const ATTR_FILE_DATALENGTH: attrgroup_t = 0x00000200; pub const ATTR_FILE_DATAALLOCSIZE: attrgroup_t = 0x00000400; pub const ATTR_FILE_RSRCLENGTH: attrgroup_t = 0x00001000; pub const ATTR_FILE_RSRCALLOCSIZE: attrgroup_t = 0x00002000; pub const ATTR_CMNEXT_RELPATH: attrgroup_t = 0x00000004; pub const ATTR_CMNEXT_PRIVATESIZE: attrgroup_t = 0x00000008; pub const ATTR_CMNEXT_LINKID: attrgroup_t = 0x00000010; pub const ATTR_CMNEXT_NOFIRMLINKPATH: attrgroup_t = 0x00000020; pub const ATTR_CMNEXT_REALDEVID: attrgroup_t = 0x00000040; pub const ATTR_CMNEXT_REALFSID: attrgroup_t = 0x00000080; pub const ATTR_CMNEXT_CLONEID: attrgroup_t = 0x00000100; pub const ATTR_CMNEXT_EXT_FLAGS: attrgroup_t = 0x00000200; pub const ATTR_CMNEXT_RECURSIVE_GENCOUNT: attrgroup_t = 0x00000400; pub const DIR_MNTSTATUS_MNTPOINT: u32 = 0x1; pub const VOL_CAPABILITIES_FORMAT: usize = 0; pub const VOL_CAPABILITIES_INTERFACES: usize = 1; pub const VOL_CAP_FMT_PERSISTENTOBJECTIDS: attrgroup_t = 0x00000001; pub const VOL_CAP_FMT_SYMBOLICLINKS: attrgroup_t = 0x00000002; pub const VOL_CAP_FMT_HARDLINKS: attrgroup_t = 0x00000004; pub const VOL_CAP_FMT_JOURNAL: attrgroup_t = 0x00000008; pub const VOL_CAP_FMT_JOURNAL_ACTIVE: attrgroup_t = 0x00000010; pub const VOL_CAP_FMT_NO_ROOT_TIMES: attrgroup_t = 0x00000020; pub const VOL_CAP_FMT_SPARSE_FILES: attrgroup_t = 0x00000040; pub const VOL_CAP_FMT_ZERO_RUNS: attrgroup_t = 0x00000080; pub const VOL_CAP_FMT_CASE_SENSITIVE: attrgroup_t = 0x00000100; pub const VOL_CAP_FMT_CASE_PRESERVING: attrgroup_t = 0x00000200; pub const VOL_CAP_FMT_FAST_STATFS: attrgroup_t = 0x00000400; pub const VOL_CAP_FMT_2TB_FILESIZE: attrgroup_t = 0x00000800; pub const VOL_CAP_FMT_OPENDENYMODES: attrgroup_t = 0x00001000; pub const VOL_CAP_FMT_HIDDEN_FILES: attrgroup_t = 0x00002000; pub const VOL_CAP_FMT_PATH_FROM_ID: attrgroup_t = 0x00004000; pub const VOL_CAP_FMT_NO_VOLUME_SIZES: attrgroup_t = 0x00008000; pub const VOL_CAP_FMT_DECMPFS_COMPRESSION: attrgroup_t = 0x00010000; pub const VOL_CAP_FMT_64BIT_OBJECT_IDS: attrgroup_t = 0x00020000; pub const VOL_CAP_FMT_DIR_HARDLINKS: attrgroup_t = 0x00040000; pub const VOL_CAP_FMT_DOCUMENT_ID: attrgroup_t = 0x00080000; pub const VOL_CAP_FMT_WRITE_GENERATION_COUNT: attrgroup_t = 0x00100000; pub const VOL_CAP_FMT_NO_IMMUTABLE_FILES: attrgroup_t = 0x00200000; pub const VOL_CAP_FMT_NO_PERMISSIONS: attrgroup_t = 0x00400000; pub const VOL_CAP_FMT_SHARED_SPACE: attrgroup_t = 0x00800000; pub const VOL_CAP_FMT_VOL_GROUPS: attrgroup_t = 0x01000000; pub const VOL_CAP_FMT_SEALED: attrgroup_t = 0x02000000; pub const VOL_CAP_INT_SEARCHFS: attrgroup_t = 0x00000001; pub const VOL_CAP_INT_ATTRLIST: attrgroup_t = 0x00000002; pub const VOL_CAP_INT_NFSEXPORT: attrgroup_t = 0x00000004; pub const VOL_CAP_INT_READDIRATTR: attrgroup_t = 0x00000008; pub const VOL_CAP_INT_EXCHANGEDATA: attrgroup_t = 0x00000010; pub const VOL_CAP_INT_COPYFILE: attrgroup_t = 0x00000020; pub const VOL_CAP_INT_ALLOCATE: attrgroup_t = 0x00000040; pub const VOL_CAP_INT_VOL_RENAME: attrgroup_t = 0x00000080; pub const VOL_CAP_INT_ADVLOCK: attrgroup_t = 0x00000100; pub const VOL_CAP_INT_FLOCK: attrgroup_t = 0x00000200; pub const VOL_CAP_INT_EXTENDED_SECURITY: attrgroup_t = 0x00000400; pub const VOL_CAP_INT_USERACCESS: attrgroup_t = 0x00000800; pub const VOL_CAP_INT_MANLOCK: attrgroup_t = 0x00001000; pub const VOL_CAP_INT_NAMEDSTREAMS: attrgroup_t = 0x00002000; pub const VOL_CAP_INT_EXTENDED_ATTR: attrgroup_t = 0x00004000; pub const VOL_CAP_INT_CLONE: attrgroup_t = 0x00010000; pub const VOL_CAP_INT_SNAPSHOT: attrgroup_t = 0x00020000; pub const VOL_CAP_INT_RENAME_SWAP: attrgroup_t = 0x00040000; pub const VOL_CAP_INT_RENAME_EXCL: attrgroup_t = 0x00080000; pub const VOL_CAP_INT_RENAME_OPENFAIL: attrgroup_t = 0x00100000; // os/clock.h pub const OS_CLOCK_MACH_ABSOLUTE_TIME: os_clockid_t = 32; // os/os_sync_wait_on_address.h pub const OS_SYNC_WAIT_ON_ADDRESS_NONE: os_sync_wait_on_address_flags_t = 0x00000000; pub const OS_SYNC_WAIT_ON_ADDRESS_SHARED: os_sync_wait_on_address_flags_t = 0x00000001; pub const OS_SYNC_WAKE_BY_ADDRESS_NONE: os_sync_wake_by_address_flags_t = 0x00000000; pub const OS_SYNC_WAKE_BY_ADDRESS_SHARED: os_sync_wake_by_address_flags_t = 0x00000001; // /// Process being created by fork. pub const SIDL: u32 = 1; /// Currently runnable. pub const SRUN: u32 = 2; /// Sleeping on an address. pub const SSLEEP: u32 = 3; /// Process debugging or suspension. pub const SSTOP: u32 = 4; /// Awaiting collection by parent. pub const SZOMB: u32 = 5; // sys/vsock.h pub const VMADDR_CID_ANY: c_uint = 0xFFFFFFFF; pub const VMADDR_CID_HYPERVISOR: c_uint = 0; pub const VMADDR_CID_RESERVED: c_uint = 1; pub const VMADDR_CID_HOST: c_uint = 2; pub const VMADDR_PORT_ANY: c_uint = 0xFFFFFFFF; const fn __DARWIN_ALIGN32(p: usize) -> usize { const __DARWIN_ALIGNBYTES32: usize = mem::size_of::() - 1; p + __DARWIN_ALIGNBYTES32 & !__DARWIN_ALIGNBYTES32 } pub const THREAD_EXTENDED_POLICY_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_TIME_CONSTRAINT_POLICY_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_PRECEDENCE_POLICY_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_AFFINITY_POLICY_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_BACKGROUND_POLICY_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_LATENCY_QOS_POLICY_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_THROUGHPUT_QOS_POLICY_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_BASIC_INFO_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_IDENTIFIER_INFO_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_EXTENDED_INFO_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; pub const TASK_THREAD_TIMES_INFO_COUNT: u32 = (mem::size_of::() / mem::size_of::()) as u32; pub const MACH_TASK_BASIC_INFO_COUNT: u32 = (mem::size_of::() / mem::size_of::()) as u32; pub const HOST_VM_INFO64_COUNT: mach_msg_type_number_t = (mem::size_of::() / mem::size_of::()) as mach_msg_type_number_t; // bsd/net/if_mib.h /// Non-interface-specific pub const IFMIB_SYSTEM: c_int = 1; /// Per-interface data table pub const IFMIB_IFDATA: c_int = 2; /// All interfaces data at once pub const IFMIB_IFALLDATA: c_int = 3; /// Generic stats for all kinds of ifaces pub const IFDATA_GENERAL: c_int = 1; /// Specific to the type of interface pub const IFDATA_LINKSPECIFIC: c_int = 2; /// Addresses assigned to interface pub const IFDATA_ADDRS: c_int = 3; /// Multicast addresses assigned to interface pub const IFDATA_MULTIADDRS: c_int = 4; /// Number of interfaces configured pub const IFMIB_IFCOUNT: c_int = 1; /// Functions not specific to a type of iface pub const NETLINK_GENERIC: c_int = 0; pub const DOT3COMPLIANCE_STATS: c_int = 1; pub const DOT3COMPLIANCE_COLLS: c_int = 2; // kern_control.h pub const MAX_KCTL_NAME: usize = 96; f! { pub fn CMSG_NXTHDR(mhdr: *const crate::msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { return crate::CMSG_FIRSTHDR(mhdr); }; let cmsg_len = (*cmsg).cmsg_len as usize; let next = cmsg as usize + __DARWIN_ALIGN32(cmsg_len); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next + __DARWIN_ALIGN32(mem::size_of::()) > max { core::ptr::null_mut() } else { next as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { (cmsg as *mut c_uchar).add(__DARWIN_ALIGN32(mem::size_of::())) } pub {const} fn CMSG_SPACE(length: c_uint) -> c_uint { (__DARWIN_ALIGN32(mem::size_of::()) + __DARWIN_ALIGN32(length as usize)) as c_uint } pub {const} fn CMSG_LEN(length: c_uint) -> c_uint { (__DARWIN_ALIGN32(mem::size_of::()) + length as usize) as c_uint } pub {const} fn VM_MAKE_TAG(id: u8) -> u32 { (id as u32) << 24u32 } } safe_f! { pub {const} fn WSTOPSIG(status: c_int) -> c_int { status >> 8 } pub {const} fn _WSTATUS(status: c_int) -> c_int { status & 0x7f } pub {const} fn WIFCONTINUED(status: c_int) -> bool { _WSTATUS(status) == _WSTOPPED && WSTOPSIG(status) == 0x13 } pub {const} fn WIFSIGNALED(status: c_int) -> bool { _WSTATUS(status) != _WSTOPPED && _WSTATUS(status) != 0 } pub {const} fn WIFSTOPPED(status: c_int) -> bool { _WSTATUS(status) == _WSTOPPED && WSTOPSIG(status) != 0x13 } pub {const} fn makedev(major: i32, minor: i32) -> dev_t { (major << 24) | minor } pub {const} fn major(dev: dev_t) -> i32 { (dev >> 24) & 0xff } pub {const} fn minor(dev: dev_t) -> i32 { dev & 0xffffff } } extern "C" { pub fn setgrent(); #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated in MacOSX 10.5")] #[cfg_attr(not(target_arch = "aarch64"), link_name = "daemon$1050")] pub fn daemon(nochdir: c_int, noclose: c_int) -> c_int; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated in MacOSX 10.10")] pub fn sem_destroy(sem: *mut sem_t) -> c_int; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated in MacOSX 10.10")] pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn aio_read(aiocbp: *mut aiocb) -> c_int; pub fn aio_write(aiocbp: *mut aiocb) -> c_int; pub fn aio_fsync(op: c_int, aiocbp: *mut aiocb) -> c_int; pub fn aio_error(aiocbp: *const aiocb) -> c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "aio_suspend$UNIX2003" )] pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn aio_cancel(fd: c_int, aiocbp: *mut aiocb) -> c_int; pub fn chflags(path: *const c_char, flags: c_uint) -> c_int; pub fn fchflags(fd: c_int, flags: c_uint) -> c_int; pub fn clock_getres(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn clock_gettime(clk_id: crate::clockid_t, tp: *mut crate::timespec) -> c_int; pub fn lio_listio( mode: c_int, aiocb_list: *const *mut aiocb, nitems: c_int, sevp: *mut sigevent, ) -> c_int; pub fn dirfd(dirp: *mut crate::DIR) -> c_int; pub fn lutimes(file: *const c_char, times: *const crate::timeval) -> c_int; pub fn gettimeofday(tp: *mut crate::timeval, tz: *mut c_void) -> c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn utmpxname(file: *const c_char) -> c_int; pub fn asctime(tm: *const crate::tm) -> *mut c_char; pub fn ctime(clock: *const time_t) -> *mut c_char; pub fn getdate(datestr: *const c_char) -> *mut crate::tm; pub fn strptime( buf: *const c_char, format: *const c_char, timeptr: *mut crate::tm, ) -> *mut c_char; pub fn asctime_r(tm: *const crate::tm, result: *mut c_char) -> *mut c_char; pub fn ctime_r(clock: *const time_t, result: *mut c_char) -> *mut c_char; pub fn getnameinfo( sa: *const crate::sockaddr, salen: crate::socklen_t, host: *mut c_char, hostlen: crate::socklen_t, serv: *mut c_char, servlen: crate::socklen_t, flags: c_int, ) -> c_int; pub fn mincore(addr: *const c_void, len: size_t, vec: *mut c_char) -> c_int; pub fn sysctlnametomib(name: *const c_char, mibp: *mut c_int, sizep: *mut size_t) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "mprotect$UNIX2003" )] pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int; pub fn semget(key: key_t, nsems: c_int, semflg: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "semctl$UNIX2003" )] pub fn semctl(semid: c_int, semnum: c_int, cmd: c_int, ...) -> c_int; pub fn semop(semid: c_int, sops: *mut sembuf, nsops: size_t) -> c_int; pub fn shm_open(name: *const c_char, oflag: c_int, ...) -> c_int; pub fn ftok(pathname: *const c_char, proj_id: c_int) -> key_t; pub fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void; pub fn shmdt(shmaddr: *const c_void) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "shmctl$UNIX2003" )] pub fn shmctl(shmid: c_int, cmd: c_int, buf: *mut crate::shmid_ds) -> c_int; pub fn shmget(key: key_t, size: size_t, shmflg: c_int) -> c_int; pub fn sysctl( name: *mut c_int, namelen: c_uint, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; pub fn sysctlbyname( name: *const c_char, oldp: *mut c_void, oldlenp: *mut size_t, newp: *mut c_void, newlen: size_t, ) -> c_int; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn mach_absolute_time() -> u64; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] #[allow(deprecated)] pub fn mach_timebase_info(info: *mut crate::mach_timebase_info) -> c_int; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn mach_host_self() -> mach_port_t; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn mach_thread_self() -> mach_port_t; pub fn pthread_once( once_control: *mut crate::pthread_once_t, init_routine: Option, ) -> c_int; pub fn pthread_attr_getinheritsched( attr: *const crate::pthread_attr_t, inheritsched: *mut c_int, ) -> c_int; pub fn pthread_attr_getschedpolicy( attr: *const crate::pthread_attr_t, policy: *mut c_int, ) -> c_int; pub fn pthread_attr_getscope( attr: *const crate::pthread_attr_t, contentionscope: *mut c_int, ) -> c_int; pub fn pthread_attr_getstackaddr( attr: *const crate::pthread_attr_t, stackaddr: *mut *mut c_void, ) -> c_int; pub fn pthread_attr_getdetachstate( attr: *const crate::pthread_attr_t, detachstate: *mut c_int, ) -> c_int; pub fn pthread_attr_setinheritsched( attr: *mut crate::pthread_attr_t, inheritsched: c_int, ) -> c_int; pub fn pthread_attr_setschedpolicy(attr: *mut crate::pthread_attr_t, policy: c_int) -> c_int; pub fn pthread_attr_setscope(attr: *mut crate::pthread_attr_t, contentionscope: c_int) -> c_int; pub fn pthread_attr_setstackaddr( attr: *mut crate::pthread_attr_t, stackaddr: *mut c_void, ) -> c_int; pub fn pthread_setname_np(name: *const c_char) -> c_int; pub fn pthread_getname_np(thread: crate::pthread_t, name: *mut c_char, len: size_t) -> c_int; pub fn pthread_mach_thread_np(thread: crate::pthread_t) -> crate::mach_port_t; pub fn pthread_from_mach_thread_np(port: crate::mach_port_t) -> crate::pthread_t; pub fn pthread_create_from_mach_thread( thread: *mut crate::pthread_t, attr: *const crate::pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_stack_frame_decode_np( frame_addr: crate::uintptr_t, return_addr: *mut crate::uintptr_t, ) -> crate::uintptr_t; pub fn pthread_get_stackaddr_np(thread: crate::pthread_t) -> *mut c_void; pub fn pthread_get_stacksize_np(thread: crate::pthread_t) -> size_t; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: c_int) -> c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_main_np() -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut c_int, ) -> c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: c_int) -> c_int; pub fn pthread_threadid_np(thread: crate::pthread_t, thread_id: *mut u64) -> c_int; pub fn pthread_attr_set_qos_class_np( attr: *mut pthread_attr_t, class: qos_class_t, priority: c_int, ) -> c_int; pub fn pthread_attr_get_qos_class_np( attr: *mut pthread_attr_t, class: *mut qos_class_t, priority: *mut c_int, ) -> c_int; pub fn pthread_set_qos_class_self_np(class: qos_class_t, priority: c_int) -> c_int; pub fn pthread_get_qos_class_np( thread: crate::pthread_t, class: *mut qos_class_t, priority: *mut c_int, ) -> c_int; pub fn pthread_attr_getschedparam( attr: *const crate::pthread_attr_t, param: *mut sched_param, ) -> c_int; pub fn pthread_attr_setschedparam( attr: *mut crate::pthread_attr_t, param: *const sched_param, ) -> c_int; pub fn pthread_getschedparam( thread: crate::pthread_t, policy: *mut c_int, param: *mut sched_param, ) -> c_int; pub fn pthread_setschedparam( thread: crate::pthread_t, policy: c_int, param: *const sched_param, ) -> c_int; // Available from Big Sur pub fn pthread_introspection_hook_install( hook: crate::pthread_introspection_hook_t, ) -> crate::pthread_introspection_hook_t; pub fn pthread_introspection_setspecific_np( thread: crate::pthread_t, key: crate::pthread_key_t, value: *const c_void, ) -> c_int; pub fn pthread_introspection_getspecific_np( thread: crate::pthread_t, key: crate::pthread_key_t, ) -> *mut c_void; pub fn pthread_jit_write_protect_np(enabled: c_int); pub fn pthread_jit_write_protect_supported_np() -> c_int; // An array of pthread_jit_write_with_callback_np must declare // the list of callbacks e.g. // #[link_section = "__DATA_CONST,__pth_jit_func"] // static callbacks: [libc::pthread_jit_write_callback_t; 2] = [native_jit_write_cb, // std::mem::transmute::(std::ptr::null())]; // (a handy PTHREAD_JIT_WRITE_CALLBACK_NP macro for other languages). pub fn pthread_jit_write_with_callback_np( callback: crate::pthread_jit_write_callback_t, ctx: *mut c_void, ) -> c_int; pub fn pthread_jit_write_freeze_callbacks_np(); pub fn pthread_cpu_number_np(cpu_number_out: *mut size_t) -> c_int; // Available starting with macOS 14.4. pub fn os_sync_wait_on_address( addr: *mut c_void, value: u64, size: size_t, flags: os_sync_wait_on_address_flags_t, ) -> c_int; pub fn os_sync_wait_on_address_with_deadline( addr: *mut c_void, value: u64, size: size_t, flags: os_sync_wait_on_address_flags_t, clockid: os_clockid_t, deadline: u64, ) -> c_int; pub fn os_sync_wait_on_address_with_timeout( addr: *mut c_void, value: u64, size: size_t, flags: os_sync_wait_on_address_flags_t, clockid: os_clockid_t, timeout_ns: u64, ) -> c_int; pub fn os_sync_wake_by_address_any( addr: *mut c_void, size: size_t, flags: os_sync_wake_by_address_flags_t, ) -> c_int; pub fn os_sync_wake_by_address_all( addr: *mut c_void, size: size_t, flags: os_sync_wake_by_address_flags_t, ) -> c_int; pub fn os_unfair_lock_lock(lock: os_unfair_lock_t); pub fn os_unfair_lock_trylock(lock: os_unfair_lock_t) -> bool; pub fn os_unfair_lock_unlock(lock: os_unfair_lock_t); pub fn os_unfair_lock_assert_owner(lock: os_unfair_lock_t); pub fn os_unfair_lock_assert_not_owner(lock: os_unfair_lock_t); pub fn os_log_create(subsystem: *const c_char, category: *const c_char) -> crate::os_log_t; pub fn os_log_type_enabled(oslog: crate::os_log_t, tpe: crate::os_log_type_t) -> bool; pub fn os_signpost_id_make_with_pointer( log: crate::os_log_t, ptr: *const c_void, ) -> crate::os_signpost_id_t; pub fn os_signpost_id_generate(log: crate::os_log_t) -> crate::os_signpost_id_t; pub fn os_signpost_enabled(log: crate::os_log_t) -> bool; pub fn thread_policy_set( thread: thread_t, flavor: thread_policy_flavor_t, policy_info: thread_policy_t, count: mach_msg_type_number_t, ) -> kern_return_t; pub fn thread_policy_get( thread: thread_t, flavor: thread_policy_flavor_t, policy_info: thread_policy_t, count: *mut mach_msg_type_number_t, get_default: *mut boolean_t, ) -> kern_return_t; pub fn thread_info( target_act: thread_inspect_t, flavor: thread_flavor_t, thread_info_out: thread_info_t, thread_info_outCnt: *mut mach_msg_type_number_t, ) -> kern_return_t; #[cfg_attr(doc, doc(alias = "__errno_location"))] #[cfg_attr(doc, doc(alias = "errno"))] pub fn __error() -> *mut c_int; pub fn backtrace(buf: *mut *mut c_void, sz: c_int) -> c_int; pub fn backtrace_symbols(addrs: *const *mut c_void, sz: c_int) -> *mut *mut c_char; pub fn backtrace_symbols_fd(addrs: *const *mut c_void, sz: c_int, fd: c_int); pub fn backtrace_from_fp(startfp: *mut c_void, array: *mut *mut c_void, size: c_int) -> c_int; pub fn backtrace_image_offsets( array: *const *mut c_void, image_offsets: *mut image_offset, size: c_int, ); pub fn backtrace_async(array: *mut *mut c_void, length: size_t, task_id: *mut u32) -> size_t; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "statfs$INODE64" )] pub fn statfs(path: *const c_char, buf: *mut statfs) -> c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "fstatfs$INODE64" )] pub fn fstatfs(fd: c_int, buf: *mut statfs) -> c_int; pub fn kevent( kq: c_int, changelist: *const crate::kevent, nchanges: c_int, eventlist: *mut crate::kevent, nevents: c_int, timeout: *const crate::timespec, ) -> c_int; pub fn kevent64( kq: c_int, changelist: *const crate::kevent64_s, nchanges: c_int, eventlist: *mut crate::kevent64_s, nevents: c_int, flags: c_uint, timeout: *const crate::timespec, ) -> c_int; pub fn mount( src: *const c_char, target: *const c_char, flags: c_int, data: *mut c_void, ) -> c_int; pub fn fmount(src: *const c_char, fd: c_int, flags: c_int, data: *mut c_void) -> c_int; pub fn ptrace(request: c_int, pid: crate::pid_t, addr: *mut c_char, data: c_int) -> c_int; pub fn quotactl(special: *const c_char, cmd: c_int, id: c_int, data: *mut c_char) -> c_int; pub fn sethostname(name: *const c_char, len: c_int) -> c_int; pub fn sendfile( fd: c_int, s: c_int, offset: off_t, len: *mut off_t, hdtr: *mut crate::sf_hdtr, flags: c_int, ) -> c_int; pub fn futimens(fd: c_int, times: *const crate::timespec) -> c_int; pub fn utimensat( dirfd: c_int, path: *const c_char, times: *const crate::timespec, flag: c_int, ) -> c_int; pub fn openpty( amaster: *mut c_int, aslave: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> c_int; pub fn forkpty( amaster: *mut c_int, name: *mut c_char, termp: *mut termios, winp: *mut crate::winsize, ) -> crate::pid_t; pub fn login_tty(fd: c_int) -> c_int; pub fn duplocale(base: crate::locale_t) -> crate::locale_t; pub fn freelocale(loc: crate::locale_t) -> c_int; pub fn localeconv_l(loc: crate::locale_t) -> *mut lconv; pub fn newlocale(mask: c_int, locale: *const c_char, base: crate::locale_t) -> crate::locale_t; pub fn uselocale(loc: crate::locale_t) -> crate::locale_t; pub fn querylocale(mask: c_int, loc: crate::locale_t) -> *const c_char; pub fn getpriority(which: c_int, who: crate::id_t) -> c_int; pub fn setpriority(which: c_int, who: crate::id_t, prio: c_int) -> c_int; pub fn getdomainname(name: *mut c_char, len: c_int) -> c_int; pub fn setdomainname(name: *const c_char, len: c_int) -> c_int; pub fn preadv(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn pwritev(fd: c_int, iov: *const crate::iovec, iovcnt: c_int, offset: off_t) -> ssize_t; pub fn getxattr( path: *const c_char, name: *const c_char, value: *mut c_void, size: size_t, position: u32, flags: c_int, ) -> ssize_t; pub fn fgetxattr( filedes: c_int, name: *const c_char, value: *mut c_void, size: size_t, position: u32, flags: c_int, ) -> ssize_t; pub fn setxattr( path: *const c_char, name: *const c_char, value: *const c_void, size: size_t, position: u32, flags: c_int, ) -> c_int; pub fn fsetxattr( filedes: c_int, name: *const c_char, value: *const c_void, size: size_t, position: u32, flags: c_int, ) -> c_int; pub fn listxattr(path: *const c_char, list: *mut c_char, size: size_t, flags: c_int) -> ssize_t; pub fn flistxattr(filedes: c_int, list: *mut c_char, size: size_t, flags: c_int) -> ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char, flags: c_int) -> c_int; pub fn renamex_np(from: *const c_char, to: *const c_char, flags: c_uint) -> c_int; pub fn renameatx_np( fromfd: c_int, from: *const c_char, tofd: c_int, to: *const c_char, flags: c_uint, ) -> c_int; pub fn fremovexattr(filedes: c_int, name: *const c_char, flags: c_int) -> c_int; pub fn getgrouplist( name: *const c_char, basegid: c_int, groups: *mut c_int, ngroups: *mut c_int, ) -> c_int; pub fn initgroups(user: *const c_char, basegroup: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "waitid$UNIX2003" )] pub fn waitid( idtype: idtype_t, id: id_t, infop: *mut crate::siginfo_t, options: c_int, ) -> c_int; pub fn brk(addr: *const c_void) -> *mut c_void; pub fn sbrk(increment: c_int) -> *mut c_void; pub fn settimeofday(tv: *const crate::timeval, tz: *const crate::timezone) -> c_int; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn _dyld_image_count() -> u32; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] #[allow(deprecated)] pub fn _dyld_get_image_header(image_index: u32) -> *const mach_header; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn _dyld_get_image_vmaddr_slide(image_index: u32) -> intptr_t; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn _dyld_get_image_name(image_index: u32) -> *const c_char; pub fn posix_spawn( pid: *mut crate::pid_t, path: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnp( pid: *mut crate::pid_t, file: *const c_char, file_actions: *const crate::posix_spawn_file_actions_t, attrp: *const crate::posix_spawnattr_t, argv: *const *mut c_char, envp: *const *mut c_char, ) -> c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const crate::sigset_t, ) -> c_int; pub fn posix_spawnattr_getflags(attr: *const posix_spawnattr_t, flags: *mut c_short) -> c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: c_short) -> c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut crate::pid_t, ) -> c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: crate::pid_t) -> c_int; pub fn posix_spawnattr_setarchpref_np( attr: *mut posix_spawnattr_t, count: size_t, pref: *mut crate::cpu_type_t, subpref: *mut crate::cpu_subtype_t, ocount: *mut size_t, ) -> c_int; pub fn posix_spawnattr_getarchpref_np( attr: *const posix_spawnattr_t, count: size_t, pref: *mut crate::cpu_type_t, subpref: *mut crate::cpu_subtype_t, ocount: *mut size_t, ) -> c_int; pub fn posix_spawnattr_getbinpref_np( attr: *const posix_spawnattr_t, count: size_t, pref: *mut crate::cpu_type_t, ocount: *mut size_t, ) -> c_int; pub fn posix_spawnattr_setbinpref_np( attr: *mut posix_spawnattr_t, count: size_t, pref: *mut crate::cpu_type_t, ocount: *mut size_t, ) -> c_int; pub fn posix_spawnattr_set_qos_class_np( attr: *mut posix_spawnattr_t, qos_class: crate::qos_class_t, ) -> c_int; pub fn posix_spawnattr_get_qos_class_np( attr: *const posix_spawnattr_t, qos_class: *mut crate::qos_class_t, ) -> c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: c_int, path: *const c_char, oflag: c_int, mode: crate::mode_t, ) -> c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: c_int, ) -> c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: c_int, newfd: c_int, ) -> c_int; pub fn uname(buf: *mut crate::utsname) -> c_int; pub fn connectx( socket: c_int, endpoints: *const sa_endpoints_t, associd: sae_associd_t, flags: c_uint, iov: *const crate::iovec, iovcnt: c_uint, len: *mut size_t, connid: *mut sae_connid_t, ) -> c_int; pub fn disconnectx(socket: c_int, associd: sae_associd_t, connid: sae_connid_t) -> c_int; pub fn ntp_adjtime(buf: *mut timex) -> c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "getmntinfo$INODE64" )] pub fn getmntinfo(mntbufp: *mut *mut statfs, flags: c_int) -> c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "getfsstat$INODE64" )] pub fn getfsstat(mntbufp: *mut statfs, bufsize: c_int, flags: c_int) -> c_int; // Copy-on-write functions. // According to the man page `flags` is an `int` but in the header // this is a `uint32_t`. pub fn clonefile(src: *const c_char, dst: *const c_char, flags: u32) -> c_int; pub fn clonefileat( src_dirfd: c_int, src: *const c_char, dst_dirfd: c_int, dst: *const c_char, flags: u32, ) -> c_int; pub fn fclonefileat(srcfd: c_int, dst_dirfd: c_int, dst: *const c_char, flags: u32) -> c_int; pub fn copyfile( from: *const c_char, to: *const c_char, state: copyfile_state_t, flags: copyfile_flags_t, ) -> c_int; pub fn fcopyfile( from: c_int, to: c_int, state: copyfile_state_t, flags: copyfile_flags_t, ) -> c_int; pub fn copyfile_state_free(s: copyfile_state_t) -> c_int; pub fn copyfile_state_alloc() -> copyfile_state_t; pub fn copyfile_state_get(s: copyfile_state_t, flags: u32, dst: *mut c_void) -> c_int; pub fn copyfile_state_set(s: copyfile_state_t, flags: u32, src: *const c_void) -> c_int; pub fn mach_error_string(error_value: crate::mach_error_t) -> *mut c_char; // Added in macOS 10.13 // ISO/IEC 9899:2011 ("ISO C11") K.3.7.4.1 pub fn memset_s(s: *mut c_void, smax: size_t, c: c_int, n: size_t) -> c_int; // Added in macOS 10.5 pub fn memset_pattern4(b: *mut c_void, pattern4: *const c_void, len: size_t); pub fn memset_pattern8(b: *mut c_void, pattern8: *const c_void, len: size_t); pub fn memset_pattern16(b: *mut c_void, pattern16: *const c_void, len: size_t); // Inherited from BSD but available from Big Sur only pub fn strtonum( __numstr: *const c_char, __minval: c_longlong, __maxval: c_longlong, errstrp: *mut *const c_char, ) -> c_longlong; pub fn mstats() -> mstats; pub fn malloc_printf(format: *const c_char, ...); pub fn malloc_zone_check(zone: *mut crate::malloc_zone_t) -> crate::boolean_t; pub fn malloc_zone_print(zone: *mut crate::malloc_zone_t, verbose: crate::boolean_t); pub fn malloc_zone_statistics(zone: *mut crate::malloc_zone_t, stats: *mut malloc_statistics_t); pub fn malloc_zone_log(zone: *mut crate::malloc_zone_t, address: *mut c_void); pub fn malloc_zone_print_ptr_info(ptr: *mut c_void); pub fn malloc_default_zone() -> *mut crate::malloc_zone_t; pub fn malloc_zone_from_ptr(ptr: *const c_void) -> *mut crate::malloc_zone_t; pub fn malloc_zone_malloc(zone: *mut crate::malloc_zone_t, size: size_t) -> *mut c_void; pub fn malloc_zone_valloc(zone: *mut crate::malloc_zone_t, size: size_t) -> *mut c_void; pub fn malloc_zone_calloc( zone: *mut crate::malloc_zone_t, num_items: size_t, size: size_t, ) -> *mut c_void; pub fn malloc_zone_realloc( zone: *mut crate::malloc_zone_t, ptr: *mut c_void, size: size_t, ) -> *mut c_void; pub fn malloc_zone_free(zone: *mut crate::malloc_zone_t, ptr: *mut c_void); pub fn proc_listpids(t: u32, typeinfo: u32, buffer: *mut c_void, buffersize: c_int) -> c_int; pub fn proc_listallpids(buffer: *mut c_void, buffersize: c_int) -> c_int; pub fn proc_listpgrppids(pgrpid: crate::pid_t, buffer: *mut c_void, buffersize: c_int) -> c_int; pub fn proc_listchildpids(ppid: crate::pid_t, buffer: *mut c_void, buffersize: c_int) -> c_int; pub fn proc_pidinfo( pid: c_int, flavor: c_int, arg: u64, buffer: *mut c_void, buffersize: c_int, ) -> c_int; pub fn proc_pidfdinfo( pid: c_int, fd: c_int, flavor: c_int, buffer: *mut c_void, buffersize: c_int, ) -> c_int; pub fn proc_pidfileportinfo( pid: c_int, fileport: u32, flavor: c_int, buffer: *mut c_void, buffersize: c_int, ) -> c_int; pub fn proc_pidpath(pid: c_int, buffer: *mut c_void, buffersize: u32) -> c_int; pub fn proc_name(pid: c_int, buffer: *mut c_void, buffersize: u32) -> c_int; pub fn proc_regionfilename( pid: c_int, address: u64, buffer: *mut c_void, buffersize: u32, ) -> c_int; pub fn proc_kmsgbuf(buffer: *mut c_void, buffersize: u32) -> c_int; pub fn proc_libversion(major: *mut c_int, minor: *mut c_int) -> c_int; pub fn proc_pid_rusage(pid: c_int, flavor: c_int, buffer: *mut rusage_info_t) -> c_int; // Available from Big Sur pub fn proc_set_no_smt() -> c_int; pub fn proc_setthread_no_smt() -> c_int; pub fn proc_set_csm(flags: u32) -> c_int; pub fn proc_setthread_csm(flags: u32) -> c_int; /// # Notes /// /// `id` is of type [`uuid_t`]. pub fn gethostuuid(id: *mut u8, timeout: *const crate::timespec) -> c_int; pub fn gethostid() -> c_long; pub fn sethostid(hostid: c_long); pub fn CCRandomGenerateBytes(bytes: *mut c_void, size: size_t) -> crate::CCRNGStatus; pub fn getentropy(buf: *mut c_void, buflen: size_t) -> c_int; // FIXME(1.0): should this actually be deprecated? #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn _NSGetExecutablePath(buf: *mut c_char, bufsize: *mut u32) -> c_int; // crt_externs.h pub fn _NSGetArgv() -> *mut *mut *mut c_char; pub fn _NSGetArgc() -> *mut c_int; pub fn _NSGetEnviron() -> *mut *mut *mut c_char; pub fn _NSGetProgname() -> *mut *mut c_char; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn mach_vm_map( target_task: crate::vm_map_t, address: *mut crate::mach_vm_address_t, size: crate::mach_vm_size_t, mask: crate::mach_vm_offset_t, flags: c_int, object: crate::mem_entry_name_port_t, offset: crate::memory_object_offset_t, copy: crate::boolean_t, cur_protection: crate::vm_prot_t, max_protection: crate::vm_prot_t, inheritance: crate::vm_inherit_t, ) -> crate::kern_return_t; pub fn vm_allocate( target_task: vm_map_t, address: *mut vm_address_t, size: vm_size_t, flags: c_int, ) -> crate::kern_return_t; pub fn vm_deallocate( target_task: vm_map_t, address: vm_address_t, size: vm_size_t, ) -> crate::kern_return_t; pub fn host_statistics64( host_priv: host_t, flavor: host_flavor_t, host_info64_out: host_info64_t, host_info64_outCnt: *mut mach_msg_type_number_t, ) -> crate::kern_return_t; pub fn host_processor_info( host: host_t, flavor: processor_flavor_t, out_processor_count: *mut natural_t, out_processor_info: *mut processor_info_array_t, out_processor_infoCnt: *mut mach_msg_type_number_t, ) -> crate::kern_return_t; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub static mut mach_task_self_: crate::mach_port_t; pub fn task_for_pid( host: crate::mach_port_t, pid: crate::pid_t, task: *mut crate::mach_port_t, ) -> crate::kern_return_t; pub fn task_info( host: crate::mach_port_t, flavor: task_flavor_t, task_info_out: task_info_t, task_info_count: *mut mach_msg_type_number_t, ) -> crate::kern_return_t; pub fn task_create( target_task: crate::task_t, ledgers: crate::ledger_array_t, ledgersCnt: crate::mach_msg_type_number_t, inherit_memory: crate::boolean_t, child_task: *mut crate::task_t, ) -> crate::kern_return_t; pub fn task_terminate(target_task: crate::task_t) -> crate::kern_return_t; pub fn task_threads( target_task: crate::task_inspect_t, act_list: *mut crate::thread_act_array_t, act_listCnt: *mut crate::mach_msg_type_number_t, ) -> crate::kern_return_t; pub fn host_statistics( host_priv: host_t, flavor: host_flavor_t, host_info_out: host_info_t, host_info_outCnt: *mut mach_msg_type_number_t, ) -> crate::kern_return_t; // sysdir.h pub fn sysdir_start_search_path_enumeration( dir: sysdir_search_path_directory_t, domainMask: sysdir_search_path_domain_mask_t, ) -> crate::sysdir_search_path_enumeration_state; pub fn sysdir_get_next_search_path_enumeration( state: crate::sysdir_search_path_enumeration_state, path: *mut c_char, ) -> crate::sysdir_search_path_enumeration_state; pub static vm_page_size: vm_size_t; pub fn getattrlist( path: *const c_char, attrList: *mut c_void, attrBuf: *mut c_void, attrBufSize: size_t, options: u32, ) -> c_int; pub fn fgetattrlist( fd: c_int, attrList: *mut c_void, attrBuf: *mut c_void, attrBufSize: size_t, options: u32, ) -> c_int; pub fn getattrlistat( fd: c_int, path: *const c_char, attrList: *mut c_void, attrBuf: *mut c_void, attrBufSize: size_t, options: c_ulong, ) -> c_int; pub fn setattrlist( path: *const c_char, attrList: *mut c_void, attrBuf: *mut c_void, attrBufSize: size_t, options: u32, ) -> c_int; pub fn fsetattrlist( fd: c_int, attrList: *mut c_void, attrBuf: *mut c_void, attrBufSize: size_t, options: u32, ) -> c_int; pub fn setattrlistat( dir_fd: c_int, path: *const c_char, attrList: *mut c_void, attrBuf: *mut c_void, attrBufSize: size_t, options: u32, ) -> c_int; pub fn getattrlistbulk( dirfd: c_int, attrList: *mut c_void, attrBuf: *mut c_void, attrBufSize: size_t, options: u64, ) -> c_int; pub fn malloc_size(ptr: *const c_void) -> size_t; pub fn malloc_good_size(size: size_t) -> size_t; pub fn dirname(path: *mut c_char) -> *mut c_char; pub fn basename(path: *mut c_char) -> *mut c_char; pub fn mkfifoat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t) -> c_int; pub fn mknodat(dirfd: c_int, pathname: *const c_char, mode: crate::mode_t, dev: dev_t) -> c_int; pub fn freadlink(fd: c_int, buf: *mut c_char, size: size_t) -> c_int; pub fn execvP( file: *const c_char, search_path: *const c_char, argv: *const *mut c_char, ) -> c_int; } #[allow(deprecated)] #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub unsafe fn mach_task_self() -> crate::mach_port_t { mach_task_self_ } cfg_if! { if #[cfg(target_os = "macos")] { extern "C" { pub fn clock_settime(clock_id: crate::clockid_t, tp: *const crate::timespec) -> c_int; } } } cfg_if! { if #[cfg(any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "visionos" ))] { extern "C" { pub fn memmem( haystack: *const c_void, haystacklen: size_t, needle: *const c_void, needlelen: size_t, ) -> *mut c_void; pub fn task_set_info( target_task: crate::task_t, flavor: crate::task_flavor_t, task_info_in: crate::task_info_t, task_info_inCnt: crate::mach_msg_type_number_t, ) -> crate::kern_return_t; } } } // These require a dependency on `libiconv`, and including this when built as // part of `std` means every Rust program gets it. Ideally we would have a link // modifier to only include these if they are used, but we do not. #[deprecated(note = "Will be removed in 1.0 to avoid the `iconv` dependency")] #[cfg_attr(not(feature = "rustc-dep-of-std"), link(name = "iconv"))] extern "C" { pub fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut c_char, inbytesleft: *mut size_t, outbuf: *mut *mut c_char, outbytesleft: *mut size_t, ) -> size_t; pub fn iconv_close(cd: iconv_t) -> c_int; } cfg_if! { if #[cfg(target_pointer_width = "32")] { mod b32; pub use self::b32::*; } else if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/apple/b32/0000775000175000017500000000000015105742312015326 5ustar bdrungbdrunglibc/src/unix/bsd/apple/b32/mod.rs0000644000175000017500000001070615105742312016455 0ustar bdrungbdrung//! 32-bit specific Apple (ios/darwin) definitions use crate::prelude::*; pub type boolean_t = c_int; s! { pub struct if_data { pub ifi_type: c_uchar, pub ifi_typelen: c_uchar, pub ifi_physical: c_uchar, pub ifi_addrlen: c_uchar, pub ifi_hdrlen: c_uchar, pub ifi_recvquota: c_uchar, pub ifi_xmitquota: c_uchar, pub ifi_unused1: c_uchar, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_baudrate: u32, pub ifi_ipackets: u32, pub ifi_ierrors: u32, pub ifi_opackets: u32, pub ifi_oerrors: u32, pub ifi_collisions: u32, pub ifi_ibytes: u32, pub ifi_obytes: u32, pub ifi_imcasts: u32, pub ifi_omcasts: u32, pub ifi_iqdrops: u32, pub ifi_noproto: u32, pub ifi_recvtiming: u32, pub ifi_xmittiming: u32, pub ifi_lastchange: crate::timeval, pub ifi_unused2: u32, pub ifi_hwassist: u32, pub ifi_reserved1: u32, pub ifi_reserved2: u32, } pub struct bpf_hdr { pub bh_tstamp: crate::timeval, pub bh_caplen: u32, pub bh_datalen: u32, pub bh_hdrlen: c_ushort, } pub struct malloc_zone_t { __private: [crate::uintptr_t; 18], // FIXME(macos): keeping private for now } } s_no_extra_traits! { pub struct pthread_attr_t { __sig: c_long, __opaque: [c_char; 36], } pub struct pthread_once_t { __sig: c_long, __opaque: [c_char; crate::__PTHREAD_ONCE_SIZE__], } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 2], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_attr_t { fn eq(&self, other: &pthread_attr_t) -> bool { self.__sig == other.__sig && self .__opaque .iter() .zip(other.__opaque.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_attr_t {} impl fmt::Debug for pthread_attr_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_attr_t") .field("__sig", &self.__sig) // FIXME(debug): .field("__opaque", &self.__opaque) .finish() } } impl hash::Hash for pthread_attr_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } impl PartialEq for pthread_once_t { fn eq(&self, other: &pthread_once_t) -> bool { self.__sig == other.__sig && self .__opaque .iter() .zip(other.__opaque.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_once_t {} impl fmt::Debug for pthread_once_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_once_t") .field("__sig", &self.__sig) .finish() } } impl hash::Hash for pthread_once_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } } } #[doc(hidden)] #[deprecated(since = "0.2.55")] pub const NET_RT_MAXID: c_int = 10; pub const __PTHREAD_MUTEX_SIZE__: usize = 40; pub const __PTHREAD_COND_SIZE__: usize = 24; pub const __PTHREAD_CONDATTR_SIZE__: usize = 4; pub const __PTHREAD_ONCE_SIZE__: usize = 4; pub const __PTHREAD_RWLOCK_SIZE__: usize = 124; pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 12; pub const TIOCTIMESTAMP: c_ulong = 0x40087459; pub const TIOCDCDTIMESTAMP: c_ulong = 0x40087458; pub const BIOCSETF: c_ulong = 0x80084267; pub const BIOCSRTIMEOUT: c_ulong = 0x8008426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4008426e; pub const BIOCSETFNR: c_ulong = 0x8008427e; const _PTHREAD_ONCE_SIG_INIT: c_long = 0x30B1BCBA; pub const PTHREAD_ONCE_INIT: crate::pthread_once_t = crate::pthread_once_t { __sig: _PTHREAD_ONCE_SIG_INIT, __opaque: [0; 4], }; extern "C" { pub fn exchangedata(path1: *const c_char, path2: *const c_char, options: c_ulong) -> c_int; } libc/src/unix/bsd/apple/b64/0000775000175000017500000000000015105742312015333 5ustar bdrungbdrunglibc/src/unix/bsd/apple/b64/mod.rs0000644000175000017500000001077415105742312016467 0ustar bdrungbdrung//! 64-bit specific Apple (ios/darwin) definitions use crate::prelude::*; s! { pub struct timeval32 { pub tv_sec: i32, pub tv_usec: i32, } pub struct if_data { pub ifi_type: c_uchar, pub ifi_typelen: c_uchar, pub ifi_physical: c_uchar, pub ifi_addrlen: c_uchar, pub ifi_hdrlen: c_uchar, pub ifi_recvquota: c_uchar, pub ifi_xmitquota: c_uchar, pub ifi_unused1: c_uchar, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_baudrate: u32, pub ifi_ipackets: u32, pub ifi_ierrors: u32, pub ifi_opackets: u32, pub ifi_oerrors: u32, pub ifi_collisions: u32, pub ifi_ibytes: u32, pub ifi_obytes: u32, pub ifi_imcasts: u32, pub ifi_omcasts: u32, pub ifi_iqdrops: u32, pub ifi_noproto: u32, pub ifi_recvtiming: u32, pub ifi_xmittiming: u32, pub ifi_lastchange: timeval32, pub ifi_unused2: u32, pub ifi_hwassist: u32, pub ifi_reserved1: u32, pub ifi_reserved2: u32, } pub struct bpf_hdr { pub bh_tstamp: crate::timeval32, pub bh_caplen: u32, pub bh_datalen: u32, pub bh_hdrlen: c_ushort, } } s_no_extra_traits! { pub struct pthread_attr_t { __sig: c_long, __opaque: [c_char; 56], } pub struct pthread_once_t { __sig: c_long, __opaque: [c_char; __PTHREAD_ONCE_SIZE__], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_attr_t { fn eq(&self, other: &pthread_attr_t) -> bool { self.__sig == other.__sig && self .__opaque .iter() .zip(other.__opaque.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_attr_t {} impl fmt::Debug for pthread_attr_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_attr_t") .field("__sig", &self.__sig) // FIXME(debug): .field("__opaque", &self.__opaque) .finish() } } impl hash::Hash for pthread_attr_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } impl PartialEq for pthread_once_t { fn eq(&self, other: &pthread_once_t) -> bool { self.__sig == other.__sig && self .__opaque .iter() .zip(other.__opaque.iter()) .all(|(a, b)| a == b) } } impl Eq for pthread_once_t {} impl fmt::Debug for pthread_once_t { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("pthread_once_t") .field("__sig", &self.__sig) .finish() } } impl hash::Hash for pthread_once_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } } } #[doc(hidden)] #[deprecated(since = "0.2.55")] pub const NET_RT_MAXID: c_int = 11; pub const __PTHREAD_MUTEX_SIZE__: usize = 56; pub const __PTHREAD_COND_SIZE__: usize = 40; pub const __PTHREAD_CONDATTR_SIZE__: usize = 8; pub const __PTHREAD_ONCE_SIZE__: usize = 8; pub const __PTHREAD_RWLOCK_SIZE__: usize = 192; pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 16; pub const TIOCTIMESTAMP: c_ulong = 0x40107459; pub const TIOCDCDTIMESTAMP: c_ulong = 0x40107458; pub const BIOCSETF: c_ulong = 0x80104267; pub const BIOCSRTIMEOUT: c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: c_ulong = 0x4010426e; pub const BIOCSETFNR: c_ulong = 0x8010427e; const _PTHREAD_ONCE_SIG_INIT: c_long = 0x30B1BCBA; pub const PTHREAD_ONCE_INIT: crate::pthread_once_t = crate::pthread_once_t { __sig: _PTHREAD_ONCE_SIG_INIT, __opaque: [0; 8], }; extern "C" { pub fn exchangedata(path1: *const c_char, path2: *const c_char, options: c_uint) -> c_int; } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/apple/b64/x86_64/0000775000175000017500000000000015105742312016271 5ustar bdrungbdrunglibc/src/unix/bsd/apple/b64/x86_64/mod.rs0000644000175000017500000001316415105742312017421 0ustar bdrungbdrunguse crate::prelude::*; pub type boolean_t = c_uint; pub type mcontext_t = *mut __darwin_mcontext64; s! { pub struct ucontext_t { pub uc_onstack: c_int, pub uc_sigmask: crate::sigset_t, pub uc_stack: crate::stack_t, pub uc_link: *mut crate::ucontext_t, pub uc_mcsize: usize, pub uc_mcontext: mcontext_t, } pub struct __darwin_mcontext64 { pub __es: __darwin_x86_exception_state64, pub __ss: __darwin_x86_thread_state64, pub __fs: __darwin_x86_float_state64, } pub struct __darwin_x86_exception_state64 { pub __trapno: u16, pub __cpu: u16, pub __err: u32, pub __faultvaddr: u64, } pub struct __darwin_x86_thread_state64 { pub __rax: u64, pub __rbx: u64, pub __rcx: u64, pub __rdx: u64, pub __rdi: u64, pub __rsi: u64, pub __rbp: u64, pub __rsp: u64, pub __r8: u64, pub __r9: u64, pub __r10: u64, pub __r11: u64, pub __r12: u64, pub __r13: u64, pub __r14: u64, pub __r15: u64, pub __rip: u64, pub __rflags: u64, pub __cs: u64, pub __fs: u64, pub __gs: u64, } pub struct __darwin_x86_float_state64 { pub __fpu_reserved: [c_int; 2], __fpu_fcw: c_short, __fpu_fsw: c_short, pub __fpu_ftw: u8, pub __fpu_rsrv1: u8, pub __fpu_fop: u16, pub __fpu_ip: u32, pub __fpu_cs: u16, pub __fpu_rsrv2: u16, pub __fpu_dp: u32, pub __fpu_ds: u16, pub __fpu_rsrv3: u16, pub __fpu_mxcsr: u32, pub __fpu_mxcsrmask: u32, pub __fpu_stmm0: __darwin_mmst_reg, pub __fpu_stmm1: __darwin_mmst_reg, pub __fpu_stmm2: __darwin_mmst_reg, pub __fpu_stmm3: __darwin_mmst_reg, pub __fpu_stmm4: __darwin_mmst_reg, pub __fpu_stmm5: __darwin_mmst_reg, pub __fpu_stmm6: __darwin_mmst_reg, pub __fpu_stmm7: __darwin_mmst_reg, pub __fpu_xmm0: __darwin_xmm_reg, pub __fpu_xmm1: __darwin_xmm_reg, pub __fpu_xmm2: __darwin_xmm_reg, pub __fpu_xmm3: __darwin_xmm_reg, pub __fpu_xmm4: __darwin_xmm_reg, pub __fpu_xmm5: __darwin_xmm_reg, pub __fpu_xmm6: __darwin_xmm_reg, pub __fpu_xmm7: __darwin_xmm_reg, pub __fpu_xmm8: __darwin_xmm_reg, pub __fpu_xmm9: __darwin_xmm_reg, pub __fpu_xmm10: __darwin_xmm_reg, pub __fpu_xmm11: __darwin_xmm_reg, pub __fpu_xmm12: __darwin_xmm_reg, pub __fpu_xmm13: __darwin_xmm_reg, pub __fpu_xmm14: __darwin_xmm_reg, pub __fpu_xmm15: __darwin_xmm_reg, // this field is actually [u8; 96], but defining it with a bigger type // allows us to auto-implement traits for it since the length of the // array is less than 32 __fpu_rsrv4: [u32; 24], pub __fpu_reserved1: c_int, } pub struct __darwin_mmst_reg { pub __mmst_reg: [c_char; 10], pub __mmst_rsrv: [c_char; 6], } pub struct __darwin_xmm_reg { pub __xmm_reg: [c_char; 16], } pub struct malloc_introspection_t { _private: [crate::uintptr_t; 16], // FIXME(macos): keeping private for now } pub struct malloc_zone_t { _reserved1: *mut c_void, _reserved2: *mut c_void, pub size: Option size_t>, pub malloc: Option *mut c_void>, pub calloc: Option< unsafe extern "C" fn( zone: *mut malloc_zone_t, num_items: size_t, size: size_t, ) -> *mut c_void, >, pub valloc: Option *mut c_void>, pub free: Option, pub realloc: Option< unsafe extern "C" fn( zone: *mut malloc_zone_t, ptr: *mut c_void, size: size_t, ) -> *mut c_void, >, pub destroy: Option, pub zone_name: *const c_char, pub batch_malloc: Option< unsafe extern "C" fn( zone: *mut malloc_zone_t, size: size_t, results: *mut *mut c_void, num_requested: c_uint, ) -> c_uint, >, pub batch_free: Option< unsafe extern "C" fn( zone: *mut malloc_zone_t, to_be_freed: *mut *mut c_void, num_to_be_freed: c_uint, ), >, pub introspect: *mut malloc_introspection_t, pub version: c_uint, pub memalign: Option< unsafe extern "C" fn( zone: *mut malloc_zone_t, alignment: size_t, size: size_t, ) -> *mut c_void, >, pub free_definite_size: Option, pub pressure_relief: Option size_t>, pub claimed_address: Option< unsafe extern "C" fn(zone: *mut malloc_zone_t, ptr: *mut c_void) -> crate::boolean_t, >, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 2], } } libc/src/unix/bsd/apple/b64/aarch64/0000775000175000017500000000000015105742312016563 5ustar bdrungbdrunglibc/src/unix/bsd/apple/b64/aarch64/mod.rs0000644000175000017500000000242615105742312017712 0ustar bdrungbdrunguse crate::prelude::*; pub type boolean_t = c_int; pub type mcontext_t = *mut __darwin_mcontext64; s! { pub struct malloc_zone_t { __private: [crate::uintptr_t; 18], // FIXME(macos): needs arm64 auth pointers support } pub struct ucontext_t { pub uc_onstack: c_int, pub uc_sigmask: crate::sigset_t, pub uc_stack: crate::stack_t, pub uc_link: *mut crate::ucontext_t, pub uc_mcsize: usize, pub uc_mcontext: mcontext_t, } pub struct __darwin_mcontext64 { pub __es: __darwin_arm_exception_state64, pub __ss: __darwin_arm_thread_state64, pub __ns: __darwin_arm_neon_state64, } pub struct __darwin_arm_exception_state64 { pub __far: u64, pub __esr: u32, pub __exception: u32, } pub struct __darwin_arm_thread_state64 { pub __x: [u64; 29], pub __fp: u64, pub __lr: u64, pub __sp: u64, pub __pc: u64, pub __cpsr: u32, pub __pad: u32, } pub struct __darwin_arm_neon_state64 { pub __v: [crate::__uint128_t; 32], pub __fpsr: u32, pub __fpcr: u32, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct max_align_t { priv_: f64, } } libc/src/primitives.rs0000644000175000017500000001464615105742312014656 0ustar bdrungbdrung//! This module contains type aliases for C's platform-specific types //! and fixed-width integer types. //! //! The platform-specific types definitions were taken from rust-lang/rust in //! library/core/src/ffi/primitives.rs //! //! The fixed-width integer aliases are deprecated: use the Rust types instead. pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type c_float = f32; pub type c_double = f64; cfg_if! { if #[cfg(all( not(windows), // FIXME(ctest): just use `target_vendor` = "apple"` once `ctest` supports it not(any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", )), not(target_os = "vita"), any( target_arch = "aarch64", target_arch = "arm", target_arch = "csky", target_arch = "hexagon", target_arch = "msp430", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "riscv32", target_arch = "riscv64", target_arch = "s390x", target_arch = "xtensa", ) ))] { pub type c_char = u8; } else { // On every other target, c_char is signed. pub type c_char = i8; } } cfg_if! { if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { pub type c_int = i16; pub type c_uint = u16; } else { pub type c_int = i32; pub type c_uint = u32; } } cfg_if! { if #[cfg(all(target_pointer_width = "64", not(windows)))] { pub type c_long = i64; pub type c_ulong = u64; } else { // The minimal size of `long` in the C standard is 32 bits pub type c_long = i32; pub type c_ulong = u32; } } #[deprecated(since = "0.2.55", note = "Use i8 instead.")] pub type int8_t = i8; #[deprecated(since = "0.2.55", note = "Use i16 instead.")] pub type int16_t = i16; #[deprecated(since = "0.2.55", note = "Use i32 instead.")] pub type int32_t = i32; #[deprecated(since = "0.2.55", note = "Use i64 instead.")] pub type int64_t = i64; #[deprecated(since = "0.2.55", note = "Use u8 instead.")] pub type uint8_t = u8; #[deprecated(since = "0.2.55", note = "Use u16 instead.")] pub type uint16_t = u16; #[deprecated(since = "0.2.55", note = "Use u32 instead.")] pub type uint32_t = u32; #[deprecated(since = "0.2.55", note = "Use u64 instead.")] pub type uint64_t = u64; cfg_if! { if #[cfg(all(target_arch = "aarch64", not(target_os = "windows")))] { // This introduces partial support for FFI with __int128 and // equivalent types on platforms where Rust's definition is validated // to match the standard C ABI of that platform. // // Rust does not guarantee u128/i128 are sound for FFI, and its // definitions are in fact known to be incompatible. [0] // // However these problems aren't fundamental, and are just platform // inconsistencies. Specifically at the time of this writing: // // * For x64 SysV ABIs (everything but Windows), the types are underaligned. // * For all Windows ABIs, Microsoft doesn't actually officially define __int128, // and as a result different implementations don't actually agree on its ABI. // // But on the other major aarch64 platforms (android, linux, ios, macos) we have // validated that rustc has the right ABI for these types. This is important because // aarch64 uses these types in some fundamental OS types like user_fpsimd_struct, // which represents saved simd registers. // // Any API which uses these types will need to `#[ignore(improper_ctypes)]` // until the upstream rust issue is resolved, but this at least lets us make // progress on platforms where this type is important. // // The list of supported architectures and OSes is intentionally very restricted, // as careful work needs to be done to verify that a particular platform // has a conformant ABI. // // [0]: https://github.com/rust-lang/rust/issues/54341 /// C `__int128` (a GCC extension that's part of many ABIs) pub type __int128 = i128; /// C `unsigned __int128` (a GCC extension that's part of many ABIs) pub type __uint128 = u128; /// C __int128_t (alternate name for [__int128][]) pub type __int128_t = i128; /// C __uint128_t (alternate name for [__uint128][]) pub type __uint128_t = u128; // NOTE: if you add more platforms to here, you may need to cfg // these consts. They should always match the platform's values // for `sizeof(__int128)` and `_Alignof(__int128)`. const _SIZE_128: usize = 16; const _ALIGN_128: usize = 16; // FIXME(ctest): ctest doesn't handle `_` as an identifier so these tests are temporarily // disabled. // macro_rules! static_assert_eq { // ($a:expr, $b:expr) => { // const _: [(); $a] = [(); $b]; // }; // } // // // Since Rust doesn't officially guarantee that these types // // have compatible ABIs, we const assert that these values have the // // known size/align of the target platform's libc. If rustc ever // // tries to regress things, it will cause a compilation error. // // // // This isn't a bullet-proof solution because e.g. it doesn't // // catch the fact that llvm and gcc disagree on how x64 __int128 // // is actually *passed* on the stack (clang underaligns it for // // the same reason that rustc *never* properly aligns it). // static_assert_eq!(core::mem::size_of::<__int128>(), _SIZE_128); // static_assert_eq!(core::mem::align_of::<__int128>(), _ALIGN_128); // static_assert_eq!(core::mem::size_of::<__uint128>(), _SIZE_128); // static_assert_eq!(core::mem::align_of::<__uint128>(), _ALIGN_128); // static_assert_eq!(core::mem::size_of::<__int128_t>(), _SIZE_128); // static_assert_eq!(core::mem::align_of::<__int128_t>(), _ALIGN_128); // static_assert_eq!(core::mem::size_of::<__uint128_t>(), _SIZE_128); // static_assert_eq!(core::mem::align_of::<__uint128_t>(), _ALIGN_128); } } memoffset/0000775000175000017500000000000015105742312012371 5ustar bdrungbdrungmemoffset/build.rs0000644000175000017500000000142015105742312014031 0ustar bdrungbdrungextern crate autocfg; fn main() { let ac = autocfg::new(); // Check for a minimum version for a few features if ac.probe_rustc_version(1, 20) { println!("cargo:rustc-cfg=tuple_ty"); } if ac.probe_rustc_version(1, 31) { println!("cargo:rustc-cfg=allow_clippy"); } if ac.probe_rustc_version(1, 36) { println!("cargo:rustc-cfg=maybe_uninit"); } if ac.probe_rustc_version(1, 40) { println!("cargo:rustc-cfg=doctests"); } 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"); } if ac.probe_rustc_version(1, 77) { println!("cargo:rustc-cfg=stable_offset_of"); } } memoffset/LICENSE0000644000175000017500000000203715105742312013376 0ustar bdrungbdrungCopyright (c) 2017 Gilad Naaman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.memoffset/Cargo.toml0000644000175000017500000000171215105742312014320 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "memoffset" version = "0.9.1" authors = ["Gilad Naaman "] description = "offset_of functionality for Rust structs." readme = "README.md" keywords = [ "mem", "offset", "offset_of", "offsetof", ] categories = ["no-std"] license = "MIT" repository = "https://github.com/Gilnaa/memoffset" [dev-dependencies.doc-comment] version = "0.3" [build-dependencies.autocfg] version = "1" [features] default = [] unstable_const = [] unstable_offset_of = [] memoffset/.cargo-checksum.json0000664000175000017500000000013115105742312016230 0ustar bdrungbdrung{"files":{},"package":"488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"}memoffset/README.md0000644000175000017500000000324215105742312013647 0ustar bdrungbdrung# memoffset # [![](https://img.shields.io/crates/v/memoffset.svg)](https://crates.io/crates/memoffset) 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. If you're using a rustc version greater or equal to 1.77, this crate's `offset_of!()` macro simply forwards to `core::mem::offset_of!()`. ## Usage ## Add the following dependency to your `Cargo.toml`: ```toml [dependencies] memoffset = "0.9" ``` These versions will compile fine with rustc versions greater or equal to 1.19. ## Examples ## ```rust use memoffset::{offset_of, span_of}; #[repr(C, packed)] struct Foo { a: u32, b: u32, c: [u8; 5], d: u32, } fn main() { assert_eq!(offset_of!(Foo, b), 4); assert_eq!(offset_of!(Foo, d), 4+4+5); assert_eq!(span_of!(Foo, a), 0..4); assert_eq!(span_of!(Foo, a .. c), 0..8); assert_eq!(span_of!(Foo, a ..= c), 0..13); assert_eq!(span_of!(Foo, ..= d), 0..17); assert_eq!(span_of!(Foo, b ..), 4..17); } ``` ## Usage in constants ## `memoffset` has support for compile-time `offset_of!` on rust>=1.65. On versions below 1.77, 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. memoffset/CHANGELOG.md0000644000175000017500000000134615105742312014204 0ustar bdrungbdrung# Changelog ## Unreleased ## v0.9.1 (26/03/2024) ### Added - Added changelog ### Changed - Clarify documentation about macro indirection - Turn the crate into a thin stdlib wrapper on rustc>=1.77 - Turn `unstable_offset_of` and `unstable_const` into NOPs; they are not needed any more on recent nightlies ## v0.9.0 (18/05/2023) ### Added - Cargo feature `unstable_offset_of` which turns the crate into a stdlib polyfill ## v0.8.0 (15/12/2022) ### Changed - Constant-evaluation is automatically enabled ## v0.7.1 (17/10/2022) ### Changed - Version in `README.md` ## v0.7.0 (17/10/2022) ### Added - `offset_of_union!` ## v0.6.5 (03/12/2021) ### Removed - [nightly] `#![feature(const_raw_ptr_deref, const_maybe_uninit_as_ptr)]` memoffset/src/0000775000175000017500000000000015105742312013160 5ustar bdrungbdrungmemoffset/src/span_of.rs0000644000175000017500000002064015105742312015153 0ustar bdrungbdrung// Copyright (c) 2017 Gilad Naaman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /// Reexport for `local_inner_macros`; see /// . #[doc(hidden)] #[macro_export] macro_rules! _memoffset__compile_error { ($($inner:tt)*) => { compile_error! { $($inner)* } } } /// Produces a range instance representing the sub-slice containing the specified member. /// /// This macro provides 2 forms of differing functionalities. /// /// The first form is identical to the appearance of the `offset_of!` macro. /// /// ```ignore /// span_of!(Struct, member) /// ``` /// /// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another. /// The general pattern of this form is: /// /// ```ignore /// // Exclusive /// span_of!(Struct, member_a .. member_b) /// // Inclusive /// span_of!(Struct, member_a ..= member_b) /// /// // Open-ended ranges /// span_of!(Struct, .. end) /// span_of!(Struct, start ..) /// ``` /// /// ### Note /// This macro uses recursion in order to resolve the range expressions, so there is a limit to /// the complexity of the expression. /// In order to raise the limit, the compiler's recursion limit should be lifted. /// /// ### Safety /// The inter-field form mentioned above assumes that the first field is positioned before the /// second. /// This is only guaranteed for `repr(C)` structs. /// Usage with `repr(Rust)` structs may yield unexpected results, like downward-going ranges, /// spans that include unexpected fields, empty spans, or spans that include *unexpected* padding bytes. /// /// ## Examples /// ``` /// use memoffset::span_of; /// /// #[repr(C)] /// struct Florp { /// a: u32 /// } /// /// #[repr(C)] /// struct Blarg { /// x: [u32; 2], /// y: [u8; 56], /// z: Florp, /// egg: [[u8; 4]; 4] /// } /// /// assert_eq!(0..84, span_of!(Blarg, ..)); /// assert_eq!(0..8, span_of!(Blarg, .. y)); /// assert_eq!(0..64, span_of!(Blarg, ..= y)); /// assert_eq!(0..8, span_of!(Blarg, x)); /// assert_eq!(8..84, span_of!(Blarg, y ..)); /// assert_eq!(0..8, span_of!(Blarg, x .. y)); /// assert_eq!(0..64, span_of!(Blarg, x ..= y)); /// ``` #[macro_export(local_inner_macros)] macro_rules! span_of { (@helper $root:ident, [] ..=) => { _memoffset__compile_error!("Expected a range, found '..='") }; (@helper $root:ident, [] ..) => { _memoffset__compile_error!("Expected a range, found '..'") }; // No explicit begin for range. (@helper $root:ident, $parent:path, [] ..) => {{ ($root as usize, $root as usize + $crate::__priv::size_of_pointee($root)) }}; (@helper $root:ident, $parent:path, [] ..= $end:tt) => {{ let end = raw_field!($root, $parent, $end); ($root as usize, end as usize + $crate::__priv::size_of_pointee(end)) }}; (@helper $root:ident, $parent:path, [] .. $end:tt) => {{ ($root as usize, raw_field!($root, $parent, $end) as usize) }}; // Explicit begin and end for range. (@helper $root:ident, $parent:path, # $begin:tt [] ..= $end:tt) => {{ let begin = raw_field!($root, $parent, $begin); let end = raw_field!($root, $parent, $end); (begin as usize, end as usize + $crate::__priv::size_of_pointee(end)) }}; (@helper $root:ident, $parent:path, # $begin:tt [] .. $end:tt) => {{ (raw_field!($root, $parent, $begin) as usize, raw_field!($root, $parent, $end) as usize) }}; // No explicit end for range. (@helper $root:ident, $parent:path, # $begin:tt [] ..) => {{ (raw_field!($root, $parent, $begin) as usize, $root as usize + $crate::__priv::size_of_pointee($root)) }}; (@helper $root:ident, $parent:path, # $begin:tt [] ..=) => {{ _memoffset__compile_error!( "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?") }}; // Just one field. (@helper $root:ident, $parent:path, # $field:tt []) => {{ let field = raw_field!($root, $parent, $field); (field as usize, field as usize + $crate::__priv::size_of_pointee(field)) }}; // Parsing. (@helper $root:ident, $parent:path, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {{ span_of!(@helper $root, $parent, $(#$begin)* #$tt [] $($rest)*) }}; (@helper $root:ident, $parent:path, [] $tt:tt $($rest:tt)*) => {{ span_of!(@helper $root, $parent, #$tt [] $($rest)*) }}; // Entry point. ($sty:path, $($exp:tt)+) => ({ // Get a base pointer. _memoffset__let_base_ptr!(root, $sty); let base = root as usize; let (begin, end) = span_of!(@helper root, $sty, [] $($exp)*); begin-base..end-base }); } #[cfg(test)] mod tests { use core::mem; #[test] fn span_simple() { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(span_of!(Foo, a), 0..4); assert_eq!(span_of!(Foo, b), 4..6); assert_eq!(span_of!(Foo, c), 8..8 + 8); } #[test] #[cfg_attr(miri, ignore)] // this creates unaligned references fn span_simple_packed() { #[repr(C, packed)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(span_of!(Foo, a), 0..4); assert_eq!(span_of!(Foo, b), 4..6); assert_eq!(span_of!(Foo, c), 6..6 + 8); } #[test] fn span_forms() { #[repr(C)] struct Florp { a: u32, } #[repr(C)] struct Blarg { x: u64, y: [u8; 56], z: Florp, egg: [[u8; 4]; 5], } // Love me some brute force assert_eq!(0..8, span_of!(Blarg, x)); assert_eq!(64..68, span_of!(Blarg, z)); assert_eq!(68..mem::size_of::(), span_of!(Blarg, egg)); assert_eq!(8..64, span_of!(Blarg, y..z)); assert_eq!(0..64, span_of!(Blarg, x..=y)); } #[test] fn ig_test() { #[repr(C)] struct Member { foo: u32, } #[repr(C)] struct Test { x: u64, y: [u8; 56], z: Member, egg: [[u8; 4]; 4], } assert_eq!(span_of!(Test, ..x), 0..0); assert_eq!(span_of!(Test, ..=x), 0..8); assert_eq!(span_of!(Test, ..y), 0..8); assert_eq!(span_of!(Test, ..=y), 0..64); assert_eq!(span_of!(Test, ..z), 0..64); assert_eq!(span_of!(Test, ..=z), 0..68); assert_eq!(span_of!(Test, ..egg), 0..68); assert_eq!(span_of!(Test, ..=egg), 0..84); assert_eq!(span_of!(Test, ..), 0..mem::size_of::()); assert_eq!( span_of!(Test, x..), offset_of!(Test, x)..mem::size_of::() ); assert_eq!( span_of!(Test, y..), offset_of!(Test, y)..mem::size_of::() ); assert_eq!( span_of!(Test, z..), offset_of!(Test, z)..mem::size_of::() ); assert_eq!( span_of!(Test, egg..), offset_of!(Test, egg)..mem::size_of::() ); assert_eq!( span_of!(Test, x..y), offset_of!(Test, x)..offset_of!(Test, y) ); assert_eq!( span_of!(Test, x..=y), offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 56]>() ); } } memoffset/src/lib.rs0000644000175000017500000000533115105742312014274 0ustar bdrungbdrung// Copyright (c) 2017 Gilad Naaman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. //! A crate used for calculating offsets of struct members and their spans. //! //! This functionality currently can not be used in compile time code such as `const` or `const fn` definitions. //! //! ## Examples //! ``` //! use memoffset::{offset_of, span_of}; //! //! #[repr(C, packed)] //! struct HelpMeIAmTrappedInAStructFactory { //! help_me_before_they_: [u8; 15], //! a: u32 //! } //! //! assert_eq!(offset_of!(HelpMeIAmTrappedInAStructFactory, a), 15); //! assert_eq!(span_of!(HelpMeIAmTrappedInAStructFactory, a), 15..19); //! assert_eq!(span_of!(HelpMeIAmTrappedInAStructFactory, help_me_before_they_ .. a), 0..15); //! ``` //! //! This functionality can be useful, for example, for checksum calculations: //! //! ```ignore //! #[repr(C, packed)] //! struct Message { //! header: MessageHeader, //! fragment_index: u32, //! fragment_count: u32, //! payload: [u8; 1024], //! checksum: u16 //! } //! //! let checksum_range = &raw[span_of!(Message, header..checksum)]; //! let checksum = crc16(checksum_range); //! ``` #![no_std] #[macro_use] #[cfg(doctests)] #[cfg(doctest)] extern crate doc_comment; #[cfg(doctests)] #[cfg(doctest)] doctest!("../README.md"); /// Hidden module for things the macros need to access. #[doc(hidden)] pub mod __priv { #[doc(hidden)] pub use core::mem; #[doc(hidden)] pub use core::ptr; /// Use type inference to obtain the size of the pointee (without actually using the pointer). #[doc(hidden)] pub fn size_of_pointee(_ptr: *const T) -> usize { mem::size_of::() } } #[macro_use] mod raw_field; #[macro_use] mod offset_of; #[macro_use] mod span_of; memoffset/src/raw_field.rs0000644000175000017500000001702315105742312015463 0ustar bdrungbdrung// Copyright (c) 2020 Gilad Naaman, Ralf Jung // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /// `addr_of!`, or just ref-then-cast when that is not available. #[cfg(raw_ref_macros)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__addr_of { ($path:expr) => {{ $crate::__priv::ptr::addr_of!($path) }}; } #[cfg(not(raw_ref_macros))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__addr_of { ($path:expr) => {{ // This is UB because we create an intermediate reference to uninitialized memory. // Nothing we can do about that without `addr_of!` though. &$path as *const _ }}; } /// Deref-coercion protection macro. /// /// Prevents compilation if the specified field name is not a part of the /// struct definition. /// /// ```compile_fail /// use memoffset::_memoffset__field_check; /// /// struct Foo { /// foo: i32, /// } /// /// type BoxedFoo = Box; /// /// _memoffset__field_check!(BoxedFoo, foo); /// ``` #[cfg(allow_clippy)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check { ($type:path, $field:tt) => { // Make sure the field actually exists. This line ensures that a // compile-time error is generated if $field is accessed through a // Deref impl. #[allow(clippy::unneeded_field_pattern)] let $type { $field: _, .. }; }; } #[cfg(not(allow_clippy))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check { ($type:path, $field:tt) => { // Make sure the field actually exists. This line ensures that a // compile-time error is generated if $field is accessed through a // Deref impl. let $type { $field: _, .. }; }; } /// Deref-coercion protection macro. /// /// Prevents compilation if the specified type is not a tuple. /// /// ```compile_fail /// use memoffset::_memoffset__field_check_tuple; /// /// _memoffset__field_check_tuple!(i32, 0); /// ``` #[cfg(allow_clippy)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_tuple { ($type:ty, $field:tt) => { // Make sure the type argument is a tuple #[allow(clippy::unneeded_wildcard_pattern)] let (_, ..): $type; }; } #[cfg(not(allow_clippy))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_tuple { ($type:ty, $field:tt) => { // Make sure the type argument is a tuple let (_, ..): $type; }; } /// Deref-coercion protection macro for unions. /// Unfortunately accepts single-field structs as well, which is not ideal, /// but ultimately pretty harmless. /// /// ```compile_fail /// use memoffset::_memoffset__field_check_union; /// /// union Foo { /// variant_a: i32, /// } /// /// type BoxedFoo = Box; /// /// _memoffset__field_check_union!(BoxedFoo, variant_a); /// ``` #[cfg(allow_clippy)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_union { ($type:path, $field:tt) => { // Make sure the field actually exists. This line ensures that a // compile-time error is generated if $field is accessed through a // Deref impl. #[allow(clippy::unneeded_wildcard_pattern)] // rustc1.19 requires unsafe here for the pattern; not needed in newer versions #[allow(unused_unsafe)] unsafe { let $type { $field: _ }; } }; } #[cfg(not(allow_clippy))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_union { ($type:path, $field:tt) => { // Make sure the field actually exists. This line ensures that a // compile-time error is generated if $field is accessed through a // Deref impl. // rustc1.19 requires unsafe here for the pattern; not needed in newer versions #[allow(unused_unsafe)] unsafe { let $type { $field: _ }; } }; } /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent type. /// /// The `base` pointer *must not* be dangling, but it *may* point to /// uninitialized memory. #[macro_export(local_inner_macros)] macro_rules! raw_field { ($base:expr, $parent:path, $field:tt) => {{ _memoffset__field_check!($parent, $field); let base = $base; // evaluate $base outside the `unsafe` block // Get the field address. // Crucially, we know that this will not trigger a deref coercion because // of the field check we did above. #[allow(unused_unsafe)] // for when the macro is used in an unsafe block unsafe { _memoffset__addr_of!((*(base as *const $parent)).$field) } }}; } /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent tuple type. /// /// The `base` pointer *must not* be dangling, but it *may* point to /// uninitialized memory. #[cfg(tuple_ty)] #[macro_export(local_inner_macros)] macro_rules! raw_field_tuple { ($base:expr, $parent:ty, $field:tt) => {{ _memoffset__field_check_tuple!($parent, $field); let base = $base; // evaluate $base outside the `unsafe` block // Get the field address. // Crucially, we know that this will not trigger a deref coercion because // of the field check we did above. #[allow(unused_unsafe)] // for when the macro is used in an unsafe block unsafe { _memoffset__addr_of!((*(base as *const $parent)).$field) } }}; } /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent tuple type. /// /// The `base` pointer *must not* be dangling, but it *may* point to /// uninitialized memory. /// /// ## Note /// This macro is the same as `raw_field`, except for a different Deref-coercion check that /// supports unions. /// Due to `macro_rules!` limitations, this check will accept structs with a single field as well as unions. /// This is not a stable guarantee, and future versions of this crate might fail /// on any use of this macro with a struct, without a semver bump. #[macro_export(local_inner_macros)] macro_rules! raw_field_union { ($base:expr, $parent:path, $field:tt) => {{ _memoffset__field_check_union!($parent, $field); let base = $base; // evaluate $base outside the `unsafe` block // Get the field address. // Crucially, we know that this will not trigger a deref coercion because // of the field check we did above. #[allow(unused_unsafe)] // for when the macro is used in an unsafe block unsafe { _memoffset__addr_of!((*(base as *const $parent)).$field) } }}; } memoffset/src/offset_of.rs0000644000175000017500000002774015105742312015510 0ustar bdrungbdrung// Copyright (c) 2017 Gilad Naaman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /// Macro to create a local `base_ptr` raw pointer of the given type, avoiding UB as /// much as is possible currently. #[cfg(maybe_uninit)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__let_base_ptr { ($name:ident, $type:ty) => { // No UB here, and the pointer does not dangle, either. // But we have to make sure that `uninit` lives long enough, // so it has to be in the same scope as `$name`. That's why // `let_base_ptr` declares a variable (several, actually) // instead of returning one. let uninit = $crate::__priv::mem::MaybeUninit::<$type>::uninit(); let $name: *const $type = uninit.as_ptr(); }; } #[cfg(not(maybe_uninit))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__let_base_ptr { ($name:ident, $type:ty) => { // No UB right here, but we will later dereference this pointer to // offset into a field, and that is UB because the pointer is dangling. let $name = $crate::__priv::mem::align_of::<$type>() as *const $type; }; } /// Macro to compute the distance between two pointers. #[cfg(stable_const)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset_offset_from_unsafe { ($field:expr, $base:expr) => {{ let field = $field; // evaluate $field outside the `unsafe` block let base = $base; // evaluate $base outside the `unsafe` block // Compute offset, with unstable `offset_from` for const-compatibility. // (Requires the pointers to not dangle, but we already need that for `raw_field!` anyway.) unsafe { (field as *const u8).offset_from(base as *const u8) as usize } }}; } #[cfg(not(stable_const))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset_offset_from_unsafe { ($field:expr, $base:expr) => { // Compute offset. ($field as usize) - ($base as usize) }; } #[cfg(not(stable_offset_of))] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_impl { ($parent:path, $field:tt) => {{ // Get a base pointer (non-dangling if rustc supports `MaybeUninit`). _memoffset__let_base_ptr!(base_ptr, $parent); // Get field pointer. let field_ptr = raw_field!(base_ptr, $parent, $field); // Compute offset. _memoffset_offset_from_unsafe!(field_ptr, base_ptr) }}; } #[cfg(stable_offset_of)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__offset_of_impl { ($parent:path, $field:tt) => {{ $crate::__priv::mem::offset_of!($parent, $field) }}; } /// Calculates the offset of the specified field from the start of the named struct. /// /// ## Examples /// ``` /// use memoffset::offset_of; /// /// #[repr(C, packed)] /// struct Foo { /// a: u32, /// b: u64, /// c: [u8; 5] /// } /// /// assert_eq!(offset_of!(Foo, a), 0); /// assert_eq!(offset_of!(Foo, b), 4); /// ``` /// /// ## Notes /// Rust's ABI is unstable, and [type layout can be changed with each /// compilation](https://doc.rust-lang.org/reference/type-layout.html). /// /// Using `offset_of!` with a `repr(Rust)` struct will return the correct offset of the /// specified `field` for a particular compilation, but the exact value may change /// based on the compiler version, concrete struct type, time of day, or rustc's mood. /// /// As a result, the value should not be retained and used between different compilations. #[macro_export(local_inner_macros)] macro_rules! offset_of { ($parent:path, $field:tt) => { // Macro implementation is delegated to another macro to have a // single top-level macro to attach documentation to. _memoffset__offset_of_impl!($parent, $field) }; } #[cfg(tuple_ty)] #[cfg(not(stable_offset_of))] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_tuple_impl { ($parent:ty, $field:tt) => {{ // Get a base pointer (non-dangling if rustc supports `MaybeUninit`). _memoffset__let_base_ptr!(base_ptr, $parent); // Get field pointer. let field_ptr = raw_field_tuple!(base_ptr, $parent, $field); // Compute offset. _memoffset_offset_from_unsafe!(field_ptr, base_ptr) }}; } #[cfg(tuple_ty)] #[cfg(stable_offset_of)] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_tuple_impl { ($parent:ty, $field:tt) => {{ $crate::__priv::mem::offset_of!($parent, $field) }}; } /// Calculates the offset of the specified field from the start of the tuple. /// /// ## Examples /// ``` /// use memoffset::offset_of_tuple; /// /// assert!(offset_of_tuple!((u8, u32), 1) >= 0, "Tuples do not have a defined layout"); /// ``` #[cfg(tuple_ty)] #[macro_export(local_inner_macros)] macro_rules! offset_of_tuple { ($parent:ty, $field:tt) => {{ // Macro implementation is delegated to another macro to have a // single top-level macro to attach documentation to. _memoffset__offset_of_tuple_impl!($parent, $field) }}; } #[cfg(not(stable_offset_of))] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_union_impl { ($parent:path, $field:tt) => {{ // Get a base pointer (non-dangling if rustc supports `MaybeUninit`). _memoffset__let_base_ptr!(base_ptr, $parent); // Get field pointer. let field_ptr = raw_field_union!(base_ptr, $parent, $field); // Compute offset. _memoffset_offset_from_unsafe!(field_ptr, base_ptr) }}; } #[cfg(stable_offset_of)] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_union_impl { ($parent:path, $field:tt) => {{ $crate::__priv::mem::offset_of!($parent, $field) }}; } /// Calculates the offset of the specified union member from the start of the union. /// /// ## Examples /// ``` /// use memoffset::offset_of_union; /// /// #[repr(C, packed)] /// union Foo { /// foo32: i32, /// foo64: i64, /// } /// /// assert!(offset_of_union!(Foo, foo64) == 0); /// ``` /// /// ## Note /// Due to `macro_rules!` limitations, this macro will accept structs with a single field as well as unions. /// This is not a stable guarantee, and future versions of this crate might fail /// on any use of this macro with a struct, without a semver bump. #[macro_export(local_inner_macros)] macro_rules! offset_of_union { ($parent:path, $field:tt) => {{ // Macro implementation is delegated to another macro to have a // single top-level macro to attach documentation to. _memoffset__offset_of_union_impl!($parent, $field) }}; } #[cfg(test)] mod tests { #![cfg_attr(allow_clippy, allow(clippy::identity_op))] // For `... + 0` constructs below. #[test] fn offset_simple() { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(offset_of!(Foo, a), 0); assert_eq!(offset_of!(Foo, b), 4); assert_eq!(offset_of!(Foo, c), 8); } #[test] fn offset_simple_packed() { #[repr(C, packed)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(offset_of!(Foo, a), 0); assert_eq!(offset_of!(Foo, b), 4); assert_eq!(offset_of!(Foo, c), 6); } #[test] fn tuple_struct() { #[repr(C)] struct Tup(i32, i32); assert_eq!(offset_of!(Tup, 0), 0); assert_eq!(offset_of!(Tup, 1), 4); } #[test] fn offset_union() { // Since we're specifying repr(C), all fields are supposed to be at offset 0 #[repr(C)] union Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(offset_of_union!(Foo, a), 0); assert_eq!(offset_of_union!(Foo, b), 0); assert_eq!(offset_of_union!(Foo, c), 0); } #[test] fn path() { mod sub { #[repr(C)] pub struct Foo { pub x: u32, } } assert_eq!(offset_of!(sub::Foo, x), 0); } #[test] fn inside_generic_method() { struct Pair(T, U); fn foo(_: Pair) -> usize { offset_of!(Pair, 1) } assert_eq!(foo(Pair(0, 0)), 4); } #[cfg(tuple_ty)] #[test] fn test_tuple_offset() { let f = (0i32, 0.0f32, 0u8); let f_ptr = &f as *const _; let f1_ptr = &f.1 as *const _; assert_eq!( f1_ptr as usize - f_ptr as usize, offset_of_tuple!((i32, f32, u8), 1) ); } #[test] fn test_raw_field() { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } let f: Foo = Foo { a: 0, b: [0, 0], c: 0, }; let f_ptr = &f as *const _; assert_eq!(f_ptr as usize + 0, raw_field!(f_ptr, Foo, a) as usize); assert_eq!(f_ptr as usize + 4, raw_field!(f_ptr, Foo, b) as usize); assert_eq!(f_ptr as usize + 8, raw_field!(f_ptr, Foo, c) as usize); } #[cfg(tuple_ty)] #[test] fn test_raw_field_tuple() { let t = (0u32, 0u8, false); let t_ptr = &t as *const _; let t_addr = t_ptr as usize; assert_eq!( &t.0 as *const _ as usize - t_addr, raw_field_tuple!(t_ptr, (u32, u8, bool), 0) as usize - t_addr ); assert_eq!( &t.1 as *const _ as usize - t_addr, raw_field_tuple!(t_ptr, (u32, u8, bool), 1) as usize - t_addr ); assert_eq!( &t.2 as *const _ as usize - t_addr, raw_field_tuple!(t_ptr, (u32, u8, bool), 2) as usize - t_addr ); } #[test] fn test_raw_field_union() { #[repr(C)] union Foo { a: u32, b: [u8; 2], c: i64, } let f = Foo { a: 0 }; let f_ptr = &f as *const _; assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, a) as usize); assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, b) as usize); assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, c) as usize); } #[cfg(any(stable_offset_of, stable_const))] #[test] fn const_offset() { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!([0; offset_of!(Foo, b)].len(), 4); } #[cfg(stable_offset_of)] #[test] fn const_offset_interior_mutable() { #[repr(C)] struct Foo { a: u32, b: core::cell::Cell, } assert_eq!([0; offset_of!(Foo, b)].len(), 4); } #[cfg(any(stable_offset_of, stable_const))] #[test] fn const_fn_offset() { const fn test_fn() -> usize { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } offset_of!(Foo, b) } assert_eq!([0; test_fn()].len(), 4); } } once_cell/0000775000175000017500000000000015105742312012327 5ustar bdrungbdrungonce_cell/bors.toml0000644000175000017500000000006215105742312014165 0ustar bdrungbdrungstatus = [ "Rust" ] delete_merged_branches = true once_cell/tests/0000775000175000017500000000000015105742312013471 5ustar bdrungbdrungonce_cell/tests/it/0000775000175000017500000000000015105742312014105 5ustar bdrungbdrungonce_cell/tests/it/sync_once_cell.rs0000644000175000017500000001675715105742312017450 0ustar bdrungbdrunguse std::{ sync::atomic::{AtomicUsize, Ordering::SeqCst}, thread::scope, }; #[cfg(feature = "std")] use std::sync::Barrier; #[cfg(not(feature = "std"))] use core::cell::Cell; use once_cell::sync::{Lazy, OnceCell}; #[test] fn once_cell() { let c = OnceCell::new(); assert!(c.get().is_none()); scope(|s| { s.spawn(|| { c.get_or_init(|| 92); assert_eq!(c.get(), Some(&92)); }); }); c.get_or_init(|| panic!("Kabom!")); assert_eq!(c.get(), Some(&92)); } #[test] fn once_cell_with_value() { static CELL: OnceCell = OnceCell::with_value(12); assert_eq!(CELL.get(), Some(&12)); } #[test] fn once_cell_get_mut() { let mut c = OnceCell::new(); assert!(c.get_mut().is_none()); c.set(90).unwrap(); *c.get_mut().unwrap() += 2; assert_eq!(c.get_mut(), Some(&mut 92)); } #[test] fn once_cell_get_unchecked() { let c = OnceCell::new(); c.set(92).unwrap(); unsafe { assert_eq!(c.get_unchecked(), &92); } } #[test] fn once_cell_drop() { static DROP_CNT: AtomicUsize = AtomicUsize::new(0); struct Dropper; impl Drop for Dropper { fn drop(&mut self) { DROP_CNT.fetch_add(1, SeqCst); } } let x = OnceCell::new(); scope(|s| { s.spawn(|| { x.get_or_init(|| Dropper); assert_eq!(DROP_CNT.load(SeqCst), 0); drop(x); }); }); assert_eq!(DROP_CNT.load(SeqCst), 1); } #[test] fn once_cell_drop_empty() { let x = OnceCell::::new(); drop(x); } #[test] fn clone() { let s = OnceCell::new(); let c = s.clone(); assert!(c.get().is_none()); s.set("hello".to_string()).unwrap(); let c = s.clone(); assert_eq!(c.get().map(String::as_str), Some("hello")); } #[test] fn get_or_try_init() { let cell: OnceCell = OnceCell::new(); assert!(cell.get().is_none()); let res = std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); assert!(res.is_err()); assert!(cell.get().is_none()); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); assert_eq!(cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), Ok(&"hello".to_string())); assert_eq!(cell.get(), Some(&"hello".to_string())); } #[cfg(feature = "std")] #[test] fn wait() { let cell: OnceCell = OnceCell::new(); scope(|s| { s.spawn(|| cell.set("hello".to_string())); let greeting = cell.wait(); assert_eq!(greeting, "hello") }); } #[cfg(feature = "std")] #[test] fn get_or_init_stress() { let n_threads = if cfg!(miri) { 30 } else { 1_000 }; let n_cells = if cfg!(miri) { 30 } else { 1_000 }; let cells: Vec<_> = std::iter::repeat_with(|| (Barrier::new(n_threads), OnceCell::new())) .take(n_cells) .collect(); scope(|s| { for t in 0..n_threads { let cells = &cells; s.spawn(move || { for (i, (b, s)) in cells.iter().enumerate() { b.wait(); let j = if t % 2 == 0 { s.wait() } else { s.get_or_init(|| i) }; assert_eq!(*j, i); } }); } }); } #[test] fn from_impl() { assert_eq!(OnceCell::from("value").get(), Some(&"value")); assert_ne!(OnceCell::from("foo").get(), Some(&"bar")); } #[test] fn partialeq_impl() { assert!(OnceCell::from("value") == OnceCell::from("value")); assert!(OnceCell::from("foo") != OnceCell::from("bar")); assert!(OnceCell::::new() == OnceCell::new()); assert!(OnceCell::::new() != OnceCell::from("value".to_owned())); } #[test] fn into_inner() { let cell: OnceCell = OnceCell::new(); assert_eq!(cell.into_inner(), None); let cell = OnceCell::new(); cell.set("hello".to_string()).unwrap(); assert_eq!(cell.into_inner(), Some("hello".to_string())); } #[test] fn debug_impl() { let cell = OnceCell::new(); assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)"); cell.set(vec!["hello", "world"]).unwrap(); assert_eq!( format!("{:#?}", cell), r#"OnceCell( [ "hello", "world", ], )"# ); } #[test] #[cfg_attr(miri, ignore)] // miri doesn't support processes #[cfg(feature = "std")] fn reentrant_init() { let examples_dir = { let mut exe = std::env::current_exe().unwrap(); exe.pop(); exe.pop(); exe.push("examples"); exe }; let bin = examples_dir .join("reentrant_init_deadlocks") .with_extension(std::env::consts::EXE_EXTENSION); let mut guard = Guard { child: std::process::Command::new(bin).spawn().unwrap() }; std::thread::sleep(std::time::Duration::from_secs(2)); let status = guard.child.try_wait().unwrap(); assert!(status.is_none()); struct Guard { child: std::process::Child, } impl Drop for Guard { fn drop(&mut self) { let _ = self.child.kill(); } } } #[cfg(not(feature = "std"))] #[test] #[should_panic(expected = "reentrant init")] fn reentrant_init() { let x: OnceCell> = OnceCell::new(); let dangling_ref: Cell> = Cell::new(None); x.get_or_init(|| { let r = x.get_or_init(|| Box::new(92)); dangling_ref.set(Some(r)); Box::new(62) }); eprintln!("use after free: {:?}", dangling_ref.get().unwrap()); } #[test] fn eval_once_macro() { macro_rules! eval_once { (|| -> $ty:ty { $($body:tt)* }) => {{ static ONCE_CELL: OnceCell<$ty> = OnceCell::new(); fn init() -> $ty { $($body)* } ONCE_CELL.get_or_init(init) }}; } let fib: &'static Vec = eval_once! { || -> Vec { let mut res = vec![1, 1]; for i in 0..10 { let next = res[i] + res[i + 1]; res.push(next); } res } }; assert_eq!(fib[5], 8) } #[test] fn once_cell_does_not_leak_partially_constructed_boxes() { let n_tries = if cfg!(miri) { 10 } else { 100 }; let n_readers = 10; let n_writers = 3; const MSG: &str = "Hello, World"; for _ in 0..n_tries { let cell: OnceCell = OnceCell::new(); scope(|scope| { for _ in 0..n_readers { scope.spawn(|| loop { if let Some(msg) = cell.get() { assert_eq!(msg, MSG); break; } }); } for _ in 0..n_writers { let _ = scope.spawn(|| cell.set(MSG.to_owned())); } }); } } #[cfg(feature = "std")] #[test] fn get_does_not_block() { let cell = OnceCell::new(); let barrier = Barrier::new(2); scope(|scope| { scope.spawn(|| { cell.get_or_init(|| { barrier.wait(); barrier.wait(); "hello".to_string() }); }); barrier.wait(); assert_eq!(cell.get(), None); barrier.wait(); }); assert_eq!(cell.get(), Some(&"hello".to_string())); } #[test] // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669 fn arrrrrrrrrrrrrrrrrrrrrr() { let cell = OnceCell::new(); { let s = String::new(); cell.set(&s).unwrap(); } } #[test] fn once_cell_is_sync_send() { fn assert_traits() {} assert_traits::>(); assert_traits::>(); } once_cell/tests/it/race_once_box.rs0000644000175000017500000000732615105742312017247 0ustar bdrungbdrung#[cfg(feature = "std")] use std::sync::Barrier; use std::sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, Arc, }; use once_cell::race::OnceBox; #[derive(Default)] struct Heap { total: Arc, } #[derive(Debug)] struct Pebble { val: T, total: Arc, } impl Drop for Pebble { fn drop(&mut self) { self.total.fetch_sub(1, SeqCst); } } impl Heap { fn total(&self) -> usize { self.total.load(SeqCst) } fn new_pebble(&self, val: T) -> Pebble { self.total.fetch_add(1, SeqCst); Pebble { val, total: Arc::clone(&self.total) } } } #[cfg(feature = "std")] #[test] fn once_box_smoke_test() { use std::thread::scope; let heap = Heap::default(); let global_cnt = AtomicUsize::new(0); let cell = OnceBox::new(); let b = Barrier::new(128); scope(|s| { for _ in 0..128 { s.spawn(|| { let local_cnt = AtomicUsize::new(0); cell.get_or_init(|| { global_cnt.fetch_add(1, SeqCst); local_cnt.fetch_add(1, SeqCst); b.wait(); Box::new(heap.new_pebble(())) }); assert_eq!(local_cnt.load(SeqCst), 1); cell.get_or_init(|| { global_cnt.fetch_add(1, SeqCst); local_cnt.fetch_add(1, SeqCst); Box::new(heap.new_pebble(())) }); assert_eq!(local_cnt.load(SeqCst), 1); }); } }); assert!(cell.get().is_some()); assert!(global_cnt.load(SeqCst) > 10); assert_eq!(heap.total(), 1); drop(cell); assert_eq!(heap.total(), 0); } #[test] fn once_box_set() { let heap = Heap::default(); let cell = OnceBox::new(); assert!(cell.get().is_none()); assert!(cell.set(Box::new(heap.new_pebble("hello"))).is_ok()); assert_eq!(cell.get().unwrap().val, "hello"); assert_eq!(heap.total(), 1); assert!(cell.set(Box::new(heap.new_pebble("world"))).is_err()); assert_eq!(cell.get().unwrap().val, "hello"); assert_eq!(heap.total(), 1); drop(cell); assert_eq!(heap.total(), 0); } #[cfg(feature = "std")] #[test] fn once_box_first_wins() { use std::thread::scope; let cell = OnceBox::new(); let val1 = 92; let val2 = 62; let b1 = Barrier::new(2); let b2 = Barrier::new(2); let b3 = Barrier::new(2); scope(|s| { s.spawn(|| { let r1 = cell.get_or_init(|| { b1.wait(); b2.wait(); Box::new(val1) }); assert_eq!(*r1, val1); b3.wait(); }); b1.wait(); s.spawn(|| { let r2 = cell.get_or_init(|| { b2.wait(); b3.wait(); Box::new(val2) }); assert_eq!(*r2, val1); }); }); assert_eq!(cell.get(), Some(&val1)); } #[test] fn once_box_reentrant() { let cell = OnceBox::new(); let res = cell.get_or_init(|| { cell.get_or_init(|| Box::new("hello".to_string())); Box::new("world".to_string()) }); assert_eq!(res, "hello"); } #[test] fn once_box_default() { struct Foo; let cell: OnceBox = Default::default(); assert!(cell.get().is_none()); } #[test] fn onece_box_with_value() { let cell = OnceBox::with_value(Box::new(92)); assert_eq!(cell.get(), Some(&92)); } #[test] fn onece_box_clone() { let cell1 = OnceBox::new(); let cell2 = cell1.clone(); cell1.set(Box::new(92)).unwrap(); let cell3 = cell1.clone(); assert_eq!(cell1.get(), Some(&92)); assert_eq!(cell2.get(), None); assert_eq!(cell3.get(), Some(&92)); } once_cell/tests/it/race.rs0000644000175000017500000000632615105742312015372 0ustar bdrungbdrung#[cfg(feature = "std")] use std::sync::Barrier; use std::{ num::NonZeroUsize, sync::atomic::{AtomicUsize, Ordering::SeqCst}, thread::scope, }; use once_cell::race::{OnceBool, OnceNonZeroUsize}; #[test] fn once_non_zero_usize_smoke_test() { let cnt = AtomicUsize::new(0); let cell = OnceNonZeroUsize::new(); let val = NonZeroUsize::new(92).unwrap(); scope(|s| { s.spawn(|| { assert_eq!( cell.get_or_init(|| { cnt.fetch_add(1, SeqCst); val }), val ); assert_eq!(cnt.load(SeqCst), 1); assert_eq!( cell.get_or_init(|| { cnt.fetch_add(1, SeqCst); val }), val ); assert_eq!(cnt.load(SeqCst), 1); }); }); assert_eq!(cell.get(), Some(val)); assert_eq!(cnt.load(SeqCst), 1); } #[test] fn once_non_zero_usize_set() { let val1 = NonZeroUsize::new(92).unwrap(); let val2 = NonZeroUsize::new(62).unwrap(); let cell = OnceNonZeroUsize::new(); assert!(cell.set(val1).is_ok()); assert_eq!(cell.get(), Some(val1)); assert!(cell.set(val2).is_err()); assert_eq!(cell.get(), Some(val1)); } #[cfg(feature = "std")] #[test] fn once_non_zero_usize_first_wins() { let val1 = NonZeroUsize::new(92).unwrap(); let val2 = NonZeroUsize::new(62).unwrap(); let cell = OnceNonZeroUsize::new(); let b1 = Barrier::new(2); let b2 = Barrier::new(2); let b3 = Barrier::new(2); scope(|s| { s.spawn(|| { let r1 = cell.get_or_init(|| { b1.wait(); b2.wait(); val1 }); assert_eq!(r1, val1); b3.wait(); }); b1.wait(); s.spawn(|| { let r2 = cell.get_or_init(|| { b2.wait(); b3.wait(); val2 }); assert_eq!(r2, val1); }); }); assert_eq!(cell.get(), Some(val1)); } #[test] fn once_bool_smoke_test() { let cnt = AtomicUsize::new(0); let cell = OnceBool::new(); scope(|s| { s.spawn(|| { assert_eq!( cell.get_or_init(|| { cnt.fetch_add(1, SeqCst); false }), false ); assert_eq!(cnt.load(SeqCst), 1); assert_eq!( cell.get_or_init(|| { cnt.fetch_add(1, SeqCst); false }), false ); assert_eq!(cnt.load(SeqCst), 1); }); }); assert_eq!(cell.get(), Some(false)); assert_eq!(cnt.load(SeqCst), 1); } #[test] fn once_bool_set() { let cell = OnceBool::new(); assert!(cell.set(false).is_ok()); assert_eq!(cell.get(), Some(false)); assert!(cell.set(true).is_err()); assert_eq!(cell.get(), Some(false)); } #[test] fn get_unchecked() { let cell = OnceNonZeroUsize::new(); cell.set(NonZeroUsize::new(92).unwrap()).unwrap(); let value = unsafe { cell.get_unchecked() }; assert_eq!(value, NonZeroUsize::new(92).unwrap()); } once_cell/tests/it/main.rs0000644000175000017500000000045115105742312015375 0ustar bdrungbdrungmod unsync_once_cell; #[cfg(any(feature = "std", feature = "critical-section"))] mod sync_once_cell; mod unsync_lazy; #[cfg(any(feature = "std", feature = "critical-section"))] mod sync_lazy; #[cfg(feature = "race")] mod race; #[cfg(all(feature = "race", feature = "alloc"))] mod race_once_box; once_cell/tests/it/sync_lazy.rs0000644000175000017500000000714515105742312016473 0ustar bdrungbdrunguse std::{ cell::Cell, sync::atomic::{AtomicUsize, Ordering::SeqCst}, thread::scope, }; use once_cell::sync::{Lazy, OnceCell}; #[test] fn lazy_new() { let called = AtomicUsize::new(0); let x = Lazy::new(|| { called.fetch_add(1, SeqCst); 92 }); assert_eq!(called.load(SeqCst), 0); scope(|s| { s.spawn(|| { let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.load(SeqCst), 1); }); }); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.load(SeqCst), 1); } #[test] fn lazy_deref_mut() { let called = AtomicUsize::new(0); let mut x = Lazy::new(|| { called.fetch_add(1, SeqCst); 92 }); assert_eq!(called.load(SeqCst), 0); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.load(SeqCst), 1); *x /= 2; assert_eq!(*x, 46); assert_eq!(called.load(SeqCst), 1); } #[test] fn lazy_force_mut() { let called = Cell::new(0); let mut x = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); let v = Lazy::force_mut(&mut x); assert_eq!(called.get(), 1); *v /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_get_mut() { let called = Cell::new(0); let mut x: Lazy = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); assert_eq!(*x, 92); let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap(); assert_eq!(called.get(), 1); *mut_ref /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_default() { static CALLED: AtomicUsize = AtomicUsize::new(0); struct Foo(u8); impl Default for Foo { fn default() -> Self { CALLED.fetch_add(1, SeqCst); Foo(42) } } let lazy: Lazy> = <_>::default(); assert_eq!(CALLED.load(SeqCst), 0); assert_eq!(lazy.lock().unwrap().0, 42); assert_eq!(CALLED.load(SeqCst), 1); lazy.lock().unwrap().0 = 21; assert_eq!(lazy.lock().unwrap().0, 21); assert_eq!(CALLED.load(SeqCst), 1); } #[test] fn static_lazy() { static XS: Lazy> = Lazy::new(|| { let mut xs = Vec::new(); xs.push(1); xs.push(2); xs.push(3); xs }); scope(|s| { s.spawn(|| { assert_eq!(&*XS, &vec![1, 2, 3]); }); }); assert_eq!(&*XS, &vec![1, 2, 3]); } #[test] fn static_lazy_via_fn() { fn xs() -> &'static Vec { static XS: OnceCell> = OnceCell::new(); XS.get_or_init(|| { let mut xs = Vec::new(); xs.push(1); xs.push(2); xs.push(3); xs }) } assert_eq!(xs(), &vec![1, 2, 3]); } #[test] fn lazy_into_value() { let l: Lazy = Lazy::new(|| panic!()); assert!(matches!(Lazy::into_value(l), Err(_))); let l = Lazy::new(|| -> i32 { 92 }); Lazy::force(&l); assert!(matches!(Lazy::into_value(l), Ok(92))); } #[test] fn lazy_poisoning() { let x: Lazy = Lazy::new(|| panic!("kaboom")); for _ in 0..2 { let res = std::panic::catch_unwind(|| x.len()); assert!(res.is_err()); } } #[test] // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669 fn arrrrrrrrrrrrrrrrrrrrrr() { let lazy: Lazy<&String, _>; { let s = String::new(); lazy = Lazy::new(|| &s); _ = *lazy; } } #[test] fn lazy_is_sync_send() { fn assert_traits() {} assert_traits::>(); } once_cell/tests/it/unsync_lazy.rs0000644000175000017500000000531515105742312017033 0ustar bdrungbdrunguse core::{ cell::Cell, sync::atomic::{AtomicUsize, Ordering::SeqCst}, }; use once_cell::unsync::Lazy; #[test] fn lazy_new() { let called = Cell::new(0); let x = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.get(), 1); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.get(), 1); } #[test] fn lazy_deref_mut() { let called = Cell::new(0); let mut x = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.get(), 1); *x /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_force_mut() { let called = Cell::new(0); let mut x = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); let v = Lazy::force_mut(&mut x); assert_eq!(called.get(), 1); *v /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_get_mut() { let called = Cell::new(0); let mut x: Lazy = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); assert_eq!(*x, 92); let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap(); assert_eq!(called.get(), 1); *mut_ref /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_default() { static CALLED: AtomicUsize = AtomicUsize::new(0); struct Foo(u8); impl Default for Foo { fn default() -> Self { CALLED.fetch_add(1, SeqCst); Foo(42) } } let lazy: Lazy> = <_>::default(); assert_eq!(CALLED.load(SeqCst), 0); assert_eq!(lazy.lock().unwrap().0, 42); assert_eq!(CALLED.load(SeqCst), 1); lazy.lock().unwrap().0 = 21; assert_eq!(lazy.lock().unwrap().0, 21); assert_eq!(CALLED.load(SeqCst), 1); } #[test] fn lazy_into_value() { let l: Lazy = Lazy::new(|| panic!()); assert!(matches!(Lazy::into_value(l), Err(_))); let l = Lazy::new(|| -> i32 { 92 }); Lazy::force(&l); assert!(matches!(Lazy::into_value(l), Ok(92))); } #[test] #[cfg(feature = "std")] fn lazy_poisoning() { let x: Lazy = Lazy::new(|| panic!("kaboom")); for _ in 0..2 { let res = std::panic::catch_unwind(|| x.len()); assert!(res.is_err()); } } #[test] // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669 fn arrrrrrrrrrrrrrrrrrrrrr() { let lazy: Lazy<&String, _>; { let s = String::new(); lazy = Lazy::new(|| &s); _ = *lazy; } } once_cell/tests/it/unsync_once_cell.rs0000644000175000017500000000741515105742312020002 0ustar bdrungbdrunguse core::{ cell::Cell, sync::atomic::{AtomicUsize, Ordering::SeqCst}, }; use once_cell::unsync::OnceCell; #[test] fn once_cell() { let c = OnceCell::new(); assert!(c.get().is_none()); c.get_or_init(|| 92); assert_eq!(c.get(), Some(&92)); c.get_or_init(|| panic!("Kabom!")); assert_eq!(c.get(), Some(&92)); } #[test] fn once_cell_with_value() { const CELL: OnceCell = OnceCell::with_value(12); let cell = CELL; assert_eq!(cell.get(), Some(&12)); } #[test] fn once_cell_get_mut() { let mut c = OnceCell::new(); assert!(c.get_mut().is_none()); c.set(90).unwrap(); *c.get_mut().unwrap() += 2; assert_eq!(c.get_mut(), Some(&mut 92)); } #[test] fn once_cell_drop() { static DROP_CNT: AtomicUsize = AtomicUsize::new(0); struct Dropper; impl Drop for Dropper { fn drop(&mut self) { DROP_CNT.fetch_add(1, SeqCst); } } let x = OnceCell::new(); x.get_or_init(|| Dropper); assert_eq!(DROP_CNT.load(SeqCst), 0); drop(x); assert_eq!(DROP_CNT.load(SeqCst), 1); } #[test] fn once_cell_drop_empty() { let x = OnceCell::::new(); drop(x); } #[test] fn clone() { let s = OnceCell::new(); let c = s.clone(); assert!(c.get().is_none()); s.set("hello".to_string()).unwrap(); let c = s.clone(); assert_eq!(c.get().map(String::as_str), Some("hello")); } #[test] fn get_or_try_init() { let cell: OnceCell = OnceCell::new(); assert!(cell.get().is_none()); let res = std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); assert!(res.is_err()); assert!(cell.get().is_none()); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); assert_eq!(cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), Ok(&"hello".to_string())); assert_eq!(cell.get(), Some(&"hello".to_string())); } #[test] fn from_impl() { assert_eq!(OnceCell::from("value").get(), Some(&"value")); assert_ne!(OnceCell::from("foo").get(), Some(&"bar")); } #[test] fn partialeq_impl() { assert!(OnceCell::from("value") == OnceCell::from("value")); assert!(OnceCell::from("foo") != OnceCell::from("bar")); assert!(OnceCell::::new() == OnceCell::new()); assert!(OnceCell::::new() != OnceCell::from("value".to_owned())); } #[test] fn into_inner() { let cell: OnceCell = OnceCell::new(); assert_eq!(cell.into_inner(), None); let cell = OnceCell::new(); cell.set("hello".to_string()).unwrap(); assert_eq!(cell.into_inner(), Some("hello".to_string())); } #[test] fn debug_impl() { let cell = OnceCell::new(); assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)"); cell.set(vec!["hello", "world"]).unwrap(); assert_eq!( format!("{:#?}", cell), r#"OnceCell( [ "hello", "world", ], )"# ); } #[test] #[should_panic(expected = "reentrant init")] fn reentrant_init() { let x: OnceCell> = OnceCell::new(); let dangling_ref: Cell> = Cell::new(None); x.get_or_init(|| { let r = x.get_or_init(|| Box::new(92)); dangling_ref.set(Some(r)); Box::new(62) }); eprintln!("use after free: {:?}", dangling_ref.get().unwrap()); } #[test] fn aliasing_in_get() { let x = OnceCell::new(); x.set(42).unwrap(); let at_x = x.get().unwrap(); // --- (shared) borrow of inner `Option` --+ let _ = x.set(27); // <-- temporary (unique) borrow of inner `Option` | println!("{}", at_x); // <------- up until here ---------------------------+ } #[test] // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669 fn arrrrrrrrrrrrrrrrrrrrrr() { let cell = OnceCell::new(); { let s = String::new(); cell.set(&s).unwrap(); } } once_cell/LICENSE-MIT0000644000175000017500000000177715105742312013775 0ustar bdrungbdrungPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. once_cell/Cargo.lock0000644000175000017500000001200515105742312014230 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "critical-section" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" [[package]] name = "libc" version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "once_cell" version = "1.21.3" dependencies = [ "critical-section", "parking_lot_core", "portable-atomic", "regex", ] [[package]] name = "parking_lot_core" version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets", ] [[package]] name = "portable-atomic" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "redox_syscall" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ "bitflags", ] [[package]] name = "regex" version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" once_cell/Cargo.toml0000644000175000017500000000475615105742312014271 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.65" name = "once_cell" version = "1.21.3" authors = ["Aleksey Kladov "] build = false exclude = [ "*.png", "*.svg", "/Cargo.lock.msrv", "rustfmt.toml", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Single assignment cells and lazy values." documentation = "https://docs.rs/once_cell" readme = "README.md" keywords = [ "lazy", "static", ] categories = [ "rust-patterns", "memory-management", ] license = "MIT OR Apache-2.0" repository = "https://github.com/matklad/once_cell" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--generate-link-to-definition"] [features] alloc = ["race"] atomic-polyfill = ["critical-section"] critical-section = [ "dep:critical-section", "portable-atomic", ] default = ["std"] parking_lot = ["dep:parking_lot_core"] portable-atomic = ["dep:portable-atomic"] race = [] std = ["alloc"] unstable = [] [lib] name = "once_cell" path = "src/lib.rs" [[example]] name = "bench" path = "examples/bench.rs" required-features = ["std"] [[example]] name = "bench_acquire" path = "examples/bench_acquire.rs" required-features = ["std"] [[example]] name = "lazy_static" path = "examples/lazy_static.rs" required-features = ["std"] [[example]] name = "reentrant_init_deadlocks" path = "examples/reentrant_init_deadlocks.rs" required-features = ["std"] [[example]] name = "regex" path = "examples/regex.rs" required-features = ["std"] [[example]] name = "test_synchronization" path = "examples/test_synchronization.rs" required-features = ["std"] [[test]] name = "it" path = "tests/it/main.rs" [dependencies.critical-section] version = "1.1.3" optional = true [dependencies.parking_lot_core] version = "0.9.10" optional = true default-features = false [dependencies.portable-atomic] version = "1.8" optional = true default-features = false [dev-dependencies.critical-section] version = "1.1.3" features = ["std"] [dev-dependencies.regex] version = "1.10.6" once_cell/.cargo-checksum.json0000664000175000017500000000013115105742312016166 0ustar bdrungbdrung{"files":{},"package":"42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"}once_cell/LICENSE-APACHE0000644000175000017500000002513715105742312014261 0ustar bdrungbdrung Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. once_cell/examples/0000775000175000017500000000000015105742312014145 5ustar bdrungbdrungonce_cell/examples/reentrant_init_deadlocks.rs0000644000175000017500000000053715105742312021554 0ustar bdrungbdrungfn main() { let cell = once_cell::sync::OnceCell::::new(); cell.get_or_init(|| { cell.get_or_init(|| 1); 2 }); } /// Dummy test to make it seem hang when compiled as `--test` /// See https://github.com/matklad/once_cell/issues/79 #[test] fn dummy_test() { std::thread::sleep(std::time::Duration::from_secs(4)); } once_cell/examples/test_synchronization.rs0000644000175000017500000000231115105742312021006 0ustar bdrungbdrung//! Test if the OnceCell properly synchronizes. //! Needs to be run in release mode. //! //! We create a `Vec` with `N_ROUNDS` of `OnceCell`s. All threads will walk the `Vec`, and race to //! be the first one to initialize a cell. //! Every thread adds the results of the cells it sees to an accumulator, which is compared at the //! end. //! All threads should end up with the same result. use once_cell::sync::OnceCell; const N_THREADS: usize = 32; const N_ROUNDS: usize = 1_000_000; static CELLS: OnceCell>> = OnceCell::new(); static RESULT: OnceCell = OnceCell::new(); fn main() { let start = std::time::Instant::now(); CELLS.get_or_init(|| vec![OnceCell::new(); N_ROUNDS]); let threads = (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::>(); for thread in threads { thread.join().unwrap(); } println!("{:?}", start.elapsed()); println!("No races detected"); } fn thread_main(i: usize) { let cells = CELLS.get().unwrap(); let mut accum = 0; for cell in cells.iter() { let &value = cell.get_or_init(|| i); accum += value; } assert_eq!(RESULT.get_or_init(|| accum), &accum); } once_cell/examples/bench.rs0000644000175000017500000000147715105742312015601 0ustar bdrungbdrunguse std::mem::size_of; use once_cell::sync::OnceCell; const N_THREADS: usize = 32; const N_ROUNDS: usize = 100_000_000; static CELL: OnceCell = OnceCell::new(); fn main() { let start = std::time::Instant::now(); let threads = (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::>(); for thread in threads { thread.join().unwrap(); } println!("{:?}", start.elapsed()); println!("size_of::>() = {:?}", size_of::>()); println!("size_of::>() = {:?}", size_of::>()); println!("size_of::>() = {:?}", size_of::>()); } fn thread_main(i: usize) { for _ in 0..N_ROUNDS { let &value = CELL.get_or_init(|| i); assert!(value < N_THREADS) } } once_cell/examples/bench_acquire.rs0000644000175000017500000000250015105742312017276 0ustar bdrungbdrung//! Benchmark the overhead that the synchronization of `OnceCell::get` causes. //! We do some other operations that write to memory to get an imprecise but somewhat realistic //! measurement. use once_cell::sync::OnceCell; use std::sync::atomic::{AtomicUsize, Ordering}; const N_THREADS: usize = 16; const N_ROUNDS: usize = 1_000_000; static CELL: OnceCell = OnceCell::new(); static OTHER: AtomicUsize = AtomicUsize::new(0); fn main() { let start = std::time::Instant::now(); let threads = (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::>(); for thread in threads { thread.join().unwrap(); } println!("{:?}", start.elapsed()); println!("{:?}", OTHER.load(Ordering::Relaxed)); } #[inline(never)] fn thread_main(i: usize) { // The operations we do here don't really matter, as long as we do multiple writes, and // everything is messy enough to prevent the compiler from optimizing the loop away. let mut data = [i; 128]; let mut accum = 0usize; for _ in 0..N_ROUNDS { let _value = CELL.get_or_init(|| i + 1); let k = OTHER.fetch_add(data[accum & 0x7F] as usize, Ordering::Relaxed); for j in data.iter_mut() { *j = (*j).wrapping_add(accum); accum = accum.wrapping_add(k); } } } once_cell/examples/lazy_static.rs0000644000175000017500000000201415105742312017034 0ustar bdrungbdrungextern crate once_cell; use once_cell::sync::{Lazy, OnceCell}; use std::collections::HashMap; static HASHMAP: Lazy> = Lazy::new(|| { let mut m = HashMap::new(); m.insert(0, "foo"); m.insert(1, "bar"); m.insert(2, "baz"); m }); // Same, but completely without macros fn hashmap() -> &'static HashMap { static INSTANCE: OnceCell> = OnceCell::new(); INSTANCE.get_or_init(|| { let mut m = HashMap::new(); m.insert(0, "foo"); m.insert(1, "bar"); m.insert(2, "baz"); m }) } fn main() { // First access to `HASHMAP` initializes it println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap()); // Any further access to `HASHMAP` just returns the computed value println!("The entry for `1` is \"{}\".", HASHMAP.get(&1).unwrap()); // The same works for function-style: assert_eq!(hashmap().get(&0), Some(&"foo")); assert_eq!(hashmap().get(&1), Some(&"bar")); } once_cell/examples/regex.rs0000644000175000017500000000317715105742312015633 0ustar bdrungbdrunguse std::{str::FromStr, time::Instant}; use regex::Regex; macro_rules! regex { ($re:literal $(,)?) => {{ static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); RE.get_or_init(|| regex::Regex::new($re).unwrap()) }}; } fn slow() { let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##; let mut total = 0; for _ in 0..1000 { let re = Regex::new( r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##, ) .unwrap(); let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap(); total += size; } println!("{}", total); } fn fast() { let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##; let mut total = 0; for _ in 0..1000 { let re: &Regex = regex!( r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##, ); let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap(); total += size; } println!("{}", total); } fn main() { let t = Instant::now(); slow(); println!("slow: {:?}", t.elapsed()); let t = Instant::now(); fast(); println!("fast: {:?}", t.elapsed()); } once_cell/README.md0000644000175000017500000000421715105742312013610 0ustar bdrungbdrung

once_cell

[![Build Status](https://github.com/matklad/once_cell/actions/workflows/ci.yaml/badge.svg)](https://github.com/matklad/once_cell/actions) [![Crates.io](https://img.shields.io/crates/v/once_cell.svg)](https://crates.io/crates/once_cell) [![API reference](https://docs.rs/once_cell/badge.svg)](https://docs.rs/once_cell/) # Overview `once_cell` provides two new cell-like types, `unsync::OnceCell` and `sync::OnceCell`. `OnceCell` might store arbitrary non-`Copy` types, can be assigned to at most once and provide direct access to the stored contents. In a nutshell, API looks *roughly* like this: ```rust impl OnceCell { fn new() -> OnceCell { ... } fn set(&self, value: T) -> Result<(), T> { ... } fn get(&self) -> Option<&T> { ... } } ``` Note that, like with `RefCell` and `Mutex`, the `set` method requires only a shared reference. Because of the single assignment restriction `get` can return an `&T` instead of `Ref` or `MutexGuard`. `once_cell` also has a `Lazy` type, build on top of `OnceCell` which provides the same API as the `lazy_static!` macro, but without using any macros: ```rust use std::{sync::Mutex, collections::HashMap}; use once_cell::sync::Lazy; static GLOBAL_DATA: Lazy>> = Lazy::new(|| { let mut m = HashMap::new(); m.insert(13, "Spica".to_string()); m.insert(74, "Hoyten".to_string()); Mutex::new(m) }); fn main() { println!("{:?}", GLOBAL_DATA.lock().unwrap()); } ``` More patterns and use-cases are in the [docs](https://docs.rs/once_cell/)! # Related crates * [double-checked-cell](https://github.com/niklasf/double-checked-cell) * [lazy-init](https://crates.io/crates/lazy-init) * [lazycell](https://crates.io/crates/lazycell) * [mitochondria](https://crates.io/crates/mitochondria) * [lazy_static](https://crates.io/crates/lazy_static) * [async_once_cell](https://crates.io/crates/async_once_cell) * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring your own mutex) Parts of `once_cell` API are included into `std` [as of Rust 1.70.0](https://github.com/rust-lang/rust/pull/105587). once_cell/CHANGELOG.md0000644000175000017500000001621515105742312014143 0ustar bdrungbdrung# Changelog ## 1.21.3 - Outline more initialization in `race`: [#284](https://github.com/matklad/once_cell/pull/284), [#285](https://github.com/matklad/once_cell/pull/285). ## 1.21.2 - Relax success ordering from AcqRel to Release in `race`: [#278](https://github.com/matklad/once_cell/pull/278). ## 1.21.1 - Reduce MSRV to 1.65: [#277](https://github.com/matklad/once_cell/pull/277). ## 1.21.0 - Outline initialization in `race`: [#273](https://github.com/matklad/once_cell/pull/273). - Add `OnceNonZereUsize::get_unchecked`: [#274](https://github.com/matklad/once_cell/pull/274). - Add `OnceBox::clone` and `OnceBox::with_value`: [#275](https://github.com/matklad/once_cell/pull/275). - Increase MSRV to 1.70 ## 1.20.2 - Remove `portable_atomic` from Cargo.lock if it is not, in fact, used: [#267](https://github.com/matklad/once_cell/pull/267) This is a work-around for this cargo bug: https://github.com/rust-lang/cargo/issues/10801. ## 1.20.1 - Allow using `race` module using just `portable_atomic`, without `critical_section` and provide better error messages on targets without atomic CAS instruction, [#265](https://github.com/matklad/once_cell/pull/265). ## 1.19.0 - Use `portable-atomic` instead of `atomic-polyfill`, [#251](https://github.com/matklad/once_cell/pull/251). ## 1.18.0 - `MSRV` is updated to 1.60.0 to take advantage of `dep:` syntax for cargo features, removing "implementation details" from publicly visible surface. ## 1.17.2 - Avoid unnecessary synchronization in `Lazy::{force,deref}_mut()`, [#231](https://github.com/matklad/once_cell/pull/231). ## 1.17.1 - Make `OnceRef` implementation compliant with [strict provenance](https://github.com/rust-lang/rust/issues/95228). ## 1.17.0 - Add `race::OnceRef` for storing a `&'a T`. ## 1.16.0 - Add `no_std` implementation based on `critical-section`, [#195](https://github.com/matklad/once_cell/pull/195). - Deprecate `atomic-polyfill` feature (use the new `critical-section` instead) ## 1.15.0 - Increase minimal supported Rust version to 1.56.0. - Implement `UnwindSafe` even if the `std` feature is disabled. ## 1.14.0 - Add extension to `unsync` and `sync` `Lazy` mut API: - `force_mut` - `get_mut` ## 1.13.1 - Make implementation compliant with [strict provenance](https://github.com/rust-lang/rust/issues/95228). - Upgrade `atomic-polyfill` to `1.0` ## 1.13.0 - Add `Lazy::get`, similar to `OnceCell::get`. ## 1.12.1 - Remove incorrect `debug_assert`. ## 1.12.0 - Add `OnceCell::wait`, a blocking variant of `get`. ## 1.11.0 - Add `OnceCell::with_value` to create initialized `OnceCell` in `const` context. - Improve `Clone` implementation for `OnceCell`. - Rewrite `parking_lot` version on top of `parking_lot_core`, for even smaller cells! ## 1.10.0 - upgrade `parking_lot` to `0.12.0` (note that this bumps MSRV with `parking_lot` feature enabled to `1.49.0`). ## 1.9.0 - Added an `atomic-polyfill` optional dependency to compile `race` on platforms without atomics ## 1.8.0 - Add `try_insert` API -- a version of `set` that returns a reference. ## 1.7.2 - Improve code size when using parking_lot feature. ## 1.7.1 - Fix `race::OnceBox` to also impl `Default` even if `T` doesn't impl `Default`. ## 1.7.0 - Hide the `race` module behind (default) `race` feature. Turns out that adding `race` by default was a breaking change on some platforms without atomics. In this release, we make the module opt-out. Technically, this is a breaking change for those who use `race` with `no_default_features`. Given that the `race` module itself only several days old, the breakage is deemed acceptable. ## 1.6.0 - Add `Lazy::into_value` - Stabilize `once_cell::race` module for "first one wins" no_std-compatible initialization flavor. - Migrate from deprecated `compare_and_swap` to `compare_exchange`. ## 1.5.2 - `OnceBox` API uses `Box`. This a breaking change to unstable API. ## 1.5.1 - MSRV is increased to `1.36.0`. - document `once_cell::race` module. - introduce `alloc` feature for `OnceBox`. - fix `OnceBox::set`. ## 1.5.0 - add new `once_cell::race` module for "first one wins" no_std-compatible initialization flavor. The API is provisional, subject to change and is gated by the `unstable` cargo feature. ## 1.4.1 - upgrade `parking_lot` to `0.11.0` - make `sync::OnceCell` pass https://doc.rust-lang.org/nomicon/dropck.html#an-escape-hatch[dropck] with `parking_lot` feature enabled. This fixes a (minor) semver-incompatible changed introduced in `1.4.0` ## 1.4.0 - upgrade `parking_lot` to `0.10` (note that this bumps MSRV with `parking_lot` feature enabled to `1.36.0`). - add `OnceCell::take`. - upgrade crossbeam utils (private dependency) to `0.7`. ## 1.3.1 - remove unnecessary `F: fmt::Debug` bound from `impl fmt::Debug for Lazy`. ## 1.3.0 - `Lazy` now implements `DerefMut`. - update implementation according to the latest changes in `std`. ## 1.2.0 - add `sync::OnceCell::get_unchecked`. ## 1.1.0 - implement `Default` for `Lazy`: it creates an empty `Lazy` which is initialized with `T::default` on first access. - add `OnceCell::get_mut`. ## 1.0.2 - actually add `#![no_std]` attribute if std feature is not enabled. ## 1.0.1 - fix unsoundness in `Lazy` if the initializing function panics. Thanks [@xfix](https://github.com/xfix)! - implement `RefUnwindSafe` for `Lazy`. - share more code between `std` and `parking_lot` implementations. - add F.A.Q section to the docs. ## 1.0.0 - remove `parking_lot` from the list of default features. - add `std` default feature. Without `std`, only `unsync` module is supported. - implement `Eq` for `OnceCell`. - fix wrong `Sync` bound on `sync::Lazy`. - run the whole test suite with miri. ## 0.2.7 - New implementation of `sync::OnceCell` if `parking_lot` feature is disabled. It now employs a hand-rolled variant of `std::sync::Once`. - `sync::OnceCell::get_or_try_init` works without `parking_lot` as well! - document the effects of `parking_lot` feature: same performance but smaller types. ## 0.2.6 - Updated `Lazy`'s `Deref` impl to requires only `FnOnce` instead of `Fn` ## 0.2.5 - `Lazy` requires only `FnOnce` instead of `Fn` ## 0.2.4 - nicer `fmt::Debug` implementation ## 0.2.3 - update `parking_lot` to `0.9.0` - fix stacked borrows violation in `unsync::OnceCell::get` - implement `Clone` for `sync::OnceCell where T: Clone` ## 0.2.2 - add `OnceCell::into_inner` which consumes a cell and returns an option ## 0.2.1 - implement `sync::OnceCell::get_or_try_init` if `parking_lot` feature is enabled - switch internal `unsafe` implementation of `sync::OnceCell` from `Once` to `Mutex` - `sync::OnceCell::get_or_init` is twice as fast if cell is already initialized - implement `std::panic::RefUnwindSafe` and `std::panic::UnwindSafe` for `OnceCell` - better document behavior around panics ## 0.2.0 - MSRV is now 1.31.1 - `Lazy::new` and `OnceCell::new` are now const-fns - `unsync_lazy` and `sync_lazy` macros are removed ## 0.1.8 - update crossbeam-utils to 0.6 - enable bors-ng ## 0.1.7 - cells implement `PartialEq` and `From` - MSRV is down to 1.24.1 - update `parking_lot` to `0.7.1` ## 0.1.6 - `unsync::OnceCell` is `Clone` if `T` is `Clone`. ## 0.1.5 - No changelog until this point :( once_cell/src/0000775000175000017500000000000015105742312013116 5ustar bdrungbdrungonce_cell/src/lib.rs0000644000175000017500000013354515105742312014243 0ustar bdrungbdrung//! # Overview //! //! `once_cell` provides two new cell-like types, [`unsync::OnceCell`] and //! [`sync::OnceCell`]. A `OnceCell` might store arbitrary non-`Copy` types, can //! be assigned to at most once and provides direct access to the stored //! contents. The core API looks *roughly* like this (and there's much more //! inside, read on!): //! //! ```rust,ignore //! impl OnceCell { //! const fn new() -> OnceCell { ... } //! fn set(&self, value: T) -> Result<(), T> { ... } //! fn get(&self) -> Option<&T> { ... } //! } //! ``` //! //! Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires //! only a shared reference. Because of the single assignment restriction `get` //! can return a `&T` instead of `Ref` or `MutexGuard`. //! //! The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait), //! while the `unsync` one is not. //! //! [`unsync::OnceCell`]: unsync/struct.OnceCell.html //! [`sync::OnceCell`]: sync/struct.OnceCell.html //! [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html //! [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html //! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html //! //! # Recipes //! //! `OnceCell` might be useful for a variety of patterns. //! //! ## Safe Initialization of Global Data //! //! ```rust //! use std::{env, io}; //! //! use once_cell::sync::OnceCell; //! //! #[derive(Debug)] //! pub struct Logger { //! // ... //! } //! static INSTANCE: OnceCell = OnceCell::new(); //! //! impl Logger { //! pub fn global() -> &'static Logger { //! INSTANCE.get().expect("logger is not initialized") //! } //! //! fn from_cli(args: env::Args) -> Result { //! // ... //! # Ok(Logger {}) //! } //! } //! //! fn main() { //! let logger = Logger::from_cli(env::args()).unwrap(); //! INSTANCE.set(logger).unwrap(); //! // use `Logger::global()` from now on //! } //! ``` //! //! ## Lazy Initialized Global Data //! //! This is essentially the `lazy_static!` macro, but without a macro. //! //! ```rust //! use std::{sync::Mutex, collections::HashMap}; //! //! use once_cell::sync::OnceCell; //! //! fn global_data() -> &'static Mutex> { //! static INSTANCE: OnceCell>> = OnceCell::new(); //! INSTANCE.get_or_init(|| { //! let mut m = HashMap::new(); //! m.insert(13, "Spica".to_string()); //! m.insert(74, "Hoyten".to_string()); //! Mutex::new(m) //! }) //! } //! ``` //! //! There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to //! streamline this pattern: //! //! ```rust //! use std::{sync::Mutex, collections::HashMap}; //! use once_cell::sync::Lazy; //! //! static GLOBAL_DATA: Lazy>> = Lazy::new(|| { //! let mut m = HashMap::new(); //! m.insert(13, "Spica".to_string()); //! m.insert(74, "Hoyten".to_string()); //! Mutex::new(m) //! }); //! //! fn main() { //! println!("{:?}", GLOBAL_DATA.lock().unwrap()); //! } //! ``` //! //! Note that the variable that holds `Lazy` is declared as `static`, *not* //! `const`. This is important: using `const` instead compiles, but works wrong. //! //! [`sync::Lazy`]: sync/struct.Lazy.html //! [`unsync::Lazy`]: unsync/struct.Lazy.html //! //! ## General purpose lazy evaluation //! //! Unlike `lazy_static!`, `Lazy` works with local variables. //! //! ```rust //! use once_cell::unsync::Lazy; //! //! fn main() { //! let ctx = vec![1, 2, 3]; //! let thunk = Lazy::new(|| { //! ctx.iter().sum::() //! }); //! assert_eq!(*thunk, 6); //! } //! ``` //! //! If you need a lazy field in a struct, you probably should use `OnceCell` //! directly, because that will allow you to access `self` during //! initialization. //! //! ```rust //! use std::{fs, path::PathBuf}; //! //! use once_cell::unsync::OnceCell; //! //! struct Ctx { //! config_path: PathBuf, //! config: OnceCell, //! } //! //! impl Ctx { //! pub fn get_config(&self) -> Result<&str, std::io::Error> { //! let cfg = self.config.get_or_try_init(|| { //! fs::read_to_string(&self.config_path) //! })?; //! Ok(cfg.as_str()) //! } //! } //! ``` //! //! ## Lazily Compiled Regex //! //! This is a `regex!` macro which takes a string literal and returns an //! *expression* that evaluates to a `&'static Regex`: //! //! ``` //! macro_rules! regex { //! ($re:literal $(,)?) => {{ //! static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); //! RE.get_or_init(|| regex::Regex::new($re).unwrap()) //! }}; //! } //! ``` //! //! This macro can be useful to avoid the "compile regex on every loop //! iteration" problem. //! //! ## Runtime `include_bytes!` //! //! The `include_bytes` macro is useful to include test resources, but it slows //! down test compilation a lot. An alternative is to load the resources at //! runtime: //! //! ``` //! use std::path::Path; //! //! use once_cell::sync::OnceCell; //! //! pub struct TestResource { //! path: &'static str, //! cell: OnceCell>, //! } //! //! impl TestResource { //! pub const fn new(path: &'static str) -> TestResource { //! TestResource { path, cell: OnceCell::new() } //! } //! pub fn bytes(&self) -> &[u8] { //! self.cell.get_or_init(|| { //! let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); //! let path = Path::new(dir.as_str()).join(self.path); //! std::fs::read(&path).unwrap_or_else(|_err| { //! panic!("failed to load test resource: {}", path.display()) //! }) //! }).as_slice() //! } //! } //! //! static TEST_IMAGE: TestResource = TestResource::new("test_data/lena.png"); //! //! #[test] //! fn test_sobel_filter() { //! let rgb: &[u8] = TEST_IMAGE.bytes(); //! // ... //! # drop(rgb); //! } //! ``` //! //! ## `lateinit` //! //! `LateInit` type for delayed initialization. It is reminiscent of Kotlin's //! `lateinit` keyword and allows construction of cyclic data structures: //! //! //! ``` //! use once_cell::sync::OnceCell; //! //! pub struct LateInit { cell: OnceCell } //! //! impl LateInit { //! pub fn init(&self, value: T) { //! assert!(self.cell.set(value).is_ok()) //! } //! } //! //! impl Default for LateInit { //! fn default() -> Self { LateInit { cell: OnceCell::default() } } //! } //! //! impl std::ops::Deref for LateInit { //! type Target = T; //! fn deref(&self) -> &T { //! self.cell.get().unwrap() //! } //! } //! //! #[derive(Default)] //! struct A<'a> { //! b: LateInit<&'a B<'a>>, //! } //! //! #[derive(Default)] //! struct B<'a> { //! a: LateInit<&'a A<'a>> //! } //! //! //! fn build_cycle() { //! let a = A::default(); //! let b = B::default(); //! a.b.init(&b); //! b.a.init(&a); //! //! let _a = &a.b.a.b.a; //! } //! ``` //! //! # Comparison with std //! //! |`!Sync` types | Access Mode | Drawbacks | //! |----------------------|------------------------|-----------------------------------------------| //! |`Cell` | `T` | requires `T: Copy` for `get` | //! |`RefCell` | `RefMut` / `Ref` | may panic at runtime | //! |`unsync::OnceCell` | `&T` | assignable only once | //! //! |`Sync` types | Access Mode | Drawbacks | //! |----------------------|------------------------|-----------------------------------------------| //! |`AtomicT` | `T` | works only with certain `Copy` types | //! |`Mutex` | `MutexGuard` | may deadlock at runtime, may block the thread | //! |`sync::OnceCell` | `&T` | assignable only once, may block the thread | //! //! Technically, calling `get_or_init` will also cause a panic or a deadlock if //! it recursively calls itself. However, because the assignment can happen only //! once, such cases should be more rare than equivalents with `RefCell` and //! `Mutex`. //! //! # Minimum Supported `rustc` Version //! //! If only the `std`, `alloc`, or `race` features are enabled, MSRV will be //! updated conservatively, supporting at least latest 8 versions of the compiler. //! When using other features, like `parking_lot`, MSRV might be updated more //! frequently, up to the latest stable. In both cases, increasing MSRV is *not* //! considered a semver-breaking change and requires only a minor version bump. //! //! # Implementation details //! //! The implementation is based on the //! [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) and //! [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and //! [`std::sync::Once`]. In some sense, `once_cell` just streamlines and unifies //! those APIs. //! //! To implement a sync flavor of `OnceCell`, this crates uses either a custom //! re-implementation of `std::sync::Once` or `parking_lot::Mutex`. This is //! controlled by the `parking_lot` feature (disabled by default). Performance //! is the same for both cases, but the `parking_lot` based `OnceCell` is //! smaller by up to 16 bytes. //! //! This crate uses `unsafe`. //! //! [`std::sync::Once`]: https://doc.rust-lang.org/std/sync/struct.Once.html //! //! # F.A.Q. //! //! **Should I use the sync or unsync flavor?** //! //! Because Rust compiler checks thread safety for you, it's impossible to //! accidentally use `unsync` where `sync` is required. So, use `unsync` in //! single-threaded code and `sync` in multi-threaded. It's easy to switch //! between the two if code becomes multi-threaded later. //! //! At the moment, `unsync` has an additional benefit that reentrant //! initialization causes a panic, which might be easier to debug than a //! deadlock. //! //! **Does this crate support async?** //! //! No, but you can use //! [`async_once_cell`](https://crates.io/crates/async_once_cell) instead. //! //! **Does this crate support `no_std`?** //! //! Yes, but with caveats. `OnceCell` is a synchronization primitive which //! _semantically_ relies on blocking. `OnceCell` guarantees that at most one //! `f` will be called to compute the value. If two threads of execution call //! `get_or_init` concurrently, one of them has to wait. //! //! Waiting fundamentally requires OS support. Execution environment needs to //! understand who waits on whom to prevent deadlocks due to priority inversion. //! You _could_ make code to compile by blindly using pure spinlocks, but the //! runtime behavior would be subtly wrong. //! //! Given these constraints, `once_cell` provides the following options: //! //! - The `race` module provides similar, but distinct synchronization primitive //! which is compatible with `no_std`. With `race`, the `f` function can be //! called multiple times by different threads, but only one thread will win //! to install the value. //! - `critical-section` feature (with a `-`, not `_`) uses `critical_section` //! to implement blocking. //! //! **Can I bring my own mutex?** //! //! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to //! allow just that. //! //! **Should I use `std::cell::OnceCell`, `once_cell`, or `lazy_static`?** //! //! If you can use `std` version (your MSRV is at least 1.70, and you don't need //! extra features `once_cell` provides), use `std`. Otherwise, use `once_cell`. //! Don't use `lazy_static`. //! //! # Related crates //! //! * Most of this crate's functionality is available in `std` starting with //! Rust 1.70. See `std::cell::OnceCell` and `std::sync::OnceLock`. //! * [double-checked-cell](https://github.com/niklasf/double-checked-cell) //! * [lazy-init](https://crates.io/crates/lazy-init) //! * [lazycell](https://crates.io/crates/lazycell) //! * [mitochondria](https://crates.io/crates/mitochondria) //! * [lazy_static](https://crates.io/crates/lazy_static) //! * [async_once_cell](https://crates.io/crates/async_once_cell) //! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring //! your own mutex) #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "alloc")] extern crate alloc; #[cfg(all(feature = "critical-section", not(feature = "std")))] #[path = "imp_cs.rs"] mod imp; #[cfg(all(feature = "std", feature = "parking_lot"))] #[path = "imp_pl.rs"] mod imp; #[cfg(all(feature = "std", not(feature = "parking_lot")))] #[path = "imp_std.rs"] mod imp; /// Single-threaded version of `OnceCell`. pub mod unsync { use core::{ cell::{Cell, UnsafeCell}, fmt, mem, ops::{Deref, DerefMut}, panic::{RefUnwindSafe, UnwindSafe}, }; /// A cell which can be written to only once. It is not thread safe. /// /// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&` /// references to the contents. /// /// [`std::cell::RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// let value: &String = cell.get_or_init(|| { /// "Hello, World!".to_string() /// }); /// assert_eq!(value, "Hello, World!"); /// assert!(cell.get().is_some()); /// ``` pub struct OnceCell { // Invariant: written to at most once. inner: UnsafeCell>, } // Similarly to a `Sync` bound on `sync::OnceCell`, we can use // `&unsync::OnceCell` to sneak a `T` through `catch_unwind`, // by initializing the cell in closure and extracting the value in the // `Drop`. impl RefUnwindSafe for OnceCell {} impl UnwindSafe for OnceCell {} impl Default for OnceCell { fn default() -> Self { Self::new() } } impl fmt::Debug for OnceCell { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.get() { Some(v) => f.debug_tuple("OnceCell").field(v).finish(), None => f.write_str("OnceCell(Uninit)"), } } } impl Clone for OnceCell { fn clone(&self) -> OnceCell { match self.get() { Some(value) => OnceCell::with_value(value.clone()), None => OnceCell::new(), } } fn clone_from(&mut self, source: &Self) { match (self.get_mut(), source.get()) { (Some(this), Some(source)) => this.clone_from(source), _ => *self = source.clone(), } } } impl PartialEq for OnceCell { fn eq(&self, other: &Self) -> bool { self.get() == other.get() } } impl Eq for OnceCell {} impl From for OnceCell { fn from(value: T) -> Self { OnceCell::with_value(value) } } impl OnceCell { /// Creates a new empty cell. pub const fn new() -> OnceCell { OnceCell { inner: UnsafeCell::new(None) } } /// Creates a new initialized cell. pub const fn with_value(value: T) -> OnceCell { OnceCell { inner: UnsafeCell::new(Some(value)) } } /// Gets a reference to the underlying value. /// /// Returns `None` if the cell is empty. #[inline] pub fn get(&self) -> Option<&T> { // Safe due to `inner`'s invariant of being written to at most once. // Had multiple writes to `inner` been allowed, a reference to the // value we return now would become dangling by a write of a // different value later. unsafe { &*self.inner.get() }.as_ref() } /// Gets a mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. /// /// This method is allowed to violate the invariant of writing to a `OnceCell` /// at most once because it requires `&mut` access to `self`. As with all /// interior mutability, `&mut` access permits arbitrary modification: /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// cell.set(92).unwrap(); /// *cell.get_mut().unwrap() = 93; /// assert_eq!(cell.get(), Some(&93)); /// ``` #[inline] pub fn get_mut(&mut self) -> Option<&mut T> { // Safe because we have unique access unsafe { &mut *self.inner.get() }.as_mut() } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was /// full. /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// assert_eq!(cell.set(92), Ok(())); /// assert_eq!(cell.set(62), Err(62)); /// /// assert!(cell.get().is_some()); /// ``` pub fn set(&self, value: T) -> Result<(), T> { match self.try_insert(value) { Ok(_) => Ok(()), Err((_, value)) => Err(value), } } /// Like [`set`](Self::set), but also returns a reference to the final cell value. /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// assert_eq!(cell.try_insert(92), Ok(&92)); /// assert_eq!(cell.try_insert(62), Err((&92, 62))); /// /// assert!(cell.get().is_some()); /// ``` pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { if let Some(old) = self.get() { return Err((old, value)); } let slot = unsafe { &mut *self.inner.get() }; // This is the only place where we set the slot, no races // due to reentrancy/concurrency are possible, and we've // checked that slot is currently `None`, so this write // maintains the `inner`'s invariant. *slot = Some(value); Ok(unsafe { slot.as_ref().unwrap_unchecked() }) } /// Gets the contents of the cell, initializing it with `f` /// if the cell was empty. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and the cell /// remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. Doing /// so results in a panic. /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// let value = cell.get_or_init(|| 92); /// assert_eq!(value, &92); /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, { enum Void {} match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and the cell /// remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. Doing /// so results in a panic. /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); /// assert!(cell.get().is_none()); /// let value = cell.get_or_try_init(|| -> Result { /// Ok(92) /// }); /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { if let Some(val) = self.get() { return Ok(val); } let val = f()?; // Note that *some* forms of reentrant initialization might lead to // UB (see `reentrant_init` test). I believe that just removing this // `assert`, while keeping `set/get` would be sound, but it seems // better to panic, rather than to silently use an old value. assert!(self.set(val).is_ok(), "reentrant init"); Ok(unsafe { self.get().unwrap_unchecked() }) } /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. /// /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. /// /// # Examples /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.take(), None); /// /// let mut cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` /// /// This method is allowed to violate the invariant of writing to a `OnceCell` /// at most once because it requires `&mut` access to `self`. As with all /// interior mutability, `&mut` access permits arbitrary modification: /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// cell.set(92).unwrap(); /// cell = OnceCell::new(); /// ``` pub fn take(&mut self) -> Option { mem::take(self).into_inner() } /// Consumes the `OnceCell`, returning the wrapped value. /// /// Returns `None` if the cell was empty. /// /// # Examples /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.into_inner(), None); /// /// let cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` pub fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies // that it is not currently borrowed. So it is safe to move out `Option`. self.inner.into_inner() } } /// A value which is initialized on the first access. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let lazy: Lazy = Lazy::new(|| { /// println!("initializing"); /// 92 /// }); /// println!("ready"); /// println!("{}", *lazy); /// println!("{}", *lazy); /// /// // Prints: /// // ready /// // initializing /// // 92 /// // 92 /// ``` pub struct Lazy T> { cell: OnceCell, init: Cell>, } impl RefUnwindSafe for Lazy where OnceCell: RefUnwindSafe {} impl fmt::Debug for Lazy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() } } impl Lazy { /// Creates a new lazy value with the given initializing function. /// /// # Example /// ``` /// # fn main() { /// use once_cell::unsync::Lazy; /// /// let hello = "Hello, World!".to_string(); /// /// let lazy = Lazy::new(|| hello.to_uppercase()); /// /// assert_eq!(&*lazy, "HELLO, WORLD!"); /// # } /// ``` pub const fn new(init: F) -> Lazy { Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) } } /// Consumes this `Lazy` returning the stored value. /// /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. pub fn into_value(this: Lazy) -> Result { let cell = this.cell; let init = this.init; cell.into_inner().ok_or_else(|| { init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) }) } } impl T> Lazy { /// Forces the evaluation of this lazy value and returns a reference to /// the result. /// /// This is equivalent to the `Deref` impl, but is explicit. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` pub fn force(this: &Lazy) -> &T { this.cell.get_or_init(|| match this.init.take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }) } /// Forces the evaluation of this lazy value and returns a mutable reference to /// the result. /// /// This is equivalent to the `DerefMut` impl, but is explicit. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let mut lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::force_mut(&mut lazy), &92); /// assert_eq!(*lazy, 92); /// ``` pub fn force_mut(this: &mut Lazy) -> &mut T { if this.cell.get_mut().is_none() { let value = match this.init.get_mut().take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }; this.cell = OnceCell::with_value(value); } this.cell.get_mut().unwrap_or_else(|| unreachable!()) } /// Gets the reference to the result of this lazy value if /// it was initialized, otherwise returns `None`. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::get(&lazy), None); /// assert_eq!(&*lazy, &92); /// assert_eq!(Lazy::get(&lazy), Some(&92)); /// ``` pub fn get(this: &Lazy) -> Option<&T> { this.cell.get() } /// Gets the mutable reference to the result of this lazy value if /// it was initialized, otherwise returns `None`. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let mut lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::get_mut(&mut lazy), None); /// assert_eq!(*lazy, 92); /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92)); /// ``` pub fn get_mut(this: &mut Lazy) -> Option<&mut T> { this.cell.get_mut() } } impl T> Deref for Lazy { type Target = T; fn deref(&self) -> &T { Lazy::force(self) } } impl T> DerefMut for Lazy { fn deref_mut(&mut self) -> &mut T { Lazy::force_mut(self) } } impl Default for Lazy { /// Creates a new lazy value using `Default` as the initializing function. fn default() -> Lazy { Lazy::new(T::default) } } } /// Thread-safe, blocking version of `OnceCell`. #[cfg(any(feature = "std", feature = "critical-section"))] pub mod sync { use core::{ cell::Cell, fmt, mem, ops::{Deref, DerefMut}, panic::RefUnwindSafe, }; use super::imp::OnceCell as Imp; /// A thread-safe cell which can be written to only once. /// /// `OnceCell` provides `&` references to the contents without RAII guards. /// /// Reading a non-`None` value out of `OnceCell` establishes a /// happens-before relationship with a corresponding write. For example, if /// thread A initializes the cell with `get_or_init(f)`, and thread B /// subsequently reads the result of this call, B also observes all the side /// effects of `f`. /// /// # Example /// ``` /// use once_cell::sync::OnceCell; /// /// static CELL: OnceCell = OnceCell::new(); /// assert!(CELL.get().is_none()); /// /// std::thread::spawn(|| { /// let value: &String = CELL.get_or_init(|| { /// "Hello, World!".to_string() /// }); /// assert_eq!(value, "Hello, World!"); /// }).join().unwrap(); /// /// let value: Option<&String> = CELL.get(); /// assert!(value.is_some()); /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); /// ``` pub struct OnceCell(Imp); impl Default for OnceCell { fn default() -> OnceCell { OnceCell::new() } } impl fmt::Debug for OnceCell { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.get() { Some(v) => f.debug_tuple("OnceCell").field(v).finish(), None => f.write_str("OnceCell(Uninit)"), } } } impl Clone for OnceCell { fn clone(&self) -> OnceCell { match self.get() { Some(value) => Self::with_value(value.clone()), None => Self::new(), } } fn clone_from(&mut self, source: &Self) { match (self.get_mut(), source.get()) { (Some(this), Some(source)) => this.clone_from(source), _ => *self = source.clone(), } } } impl From for OnceCell { fn from(value: T) -> Self { Self::with_value(value) } } impl PartialEq for OnceCell { fn eq(&self, other: &OnceCell) -> bool { self.get() == other.get() } } impl Eq for OnceCell {} impl OnceCell { /// Creates a new empty cell. pub const fn new() -> OnceCell { OnceCell(Imp::new()) } /// Creates a new initialized cell. pub const fn with_value(value: T) -> OnceCell { OnceCell(Imp::with_value(value)) } /// Gets the reference to the underlying value. /// /// Returns `None` if the cell is empty, or being initialized. This /// method never blocks. pub fn get(&self) -> Option<&T> { if self.0.is_initialized() { // Safe b/c value is initialized. Some(unsafe { self.get_unchecked() }) } else { None } } /// Gets the reference to the underlying value, blocking the current /// thread until it is set. /// /// ``` /// use once_cell::sync::OnceCell; /// /// let mut cell = std::sync::Arc::new(OnceCell::new()); /// let t = std::thread::spawn({ /// let cell = std::sync::Arc::clone(&cell); /// move || cell.set(92).unwrap() /// }); /// /// // Returns immediately, but might return None. /// let _value_or_none = cell.get(); /// /// // Will return 92, but might block until the other thread does `.set`. /// let value: &u32 = cell.wait(); /// assert_eq!(*value, 92); /// t.join().unwrap(); /// ``` #[cfg(feature = "std")] pub fn wait(&self) -> &T { if !self.0.is_initialized() { self.0.wait() } debug_assert!(self.0.is_initialized()); // Safe b/c of the wait call above and the fact that we didn't // relinquish our borrow. unsafe { self.get_unchecked() } } /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. /// /// This method is allowed to violate the invariant of writing to a `OnceCell` /// at most once because it requires `&mut` access to `self`. As with all /// interior mutability, `&mut` access permits arbitrary modification: /// /// ``` /// use once_cell::sync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// cell.set(92).unwrap(); /// cell = OnceCell::new(); /// ``` #[inline] pub fn get_mut(&mut self) -> Option<&mut T> { self.0.get_mut() } /// Get the reference to the underlying value, without checking if the /// cell is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. #[inline] pub unsafe fn get_unchecked(&self) -> &T { self.0.get_unchecked() } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was /// full. /// /// # Example /// /// ``` /// use once_cell::sync::OnceCell; /// /// static CELL: OnceCell = OnceCell::new(); /// /// fn main() { /// assert!(CELL.get().is_none()); /// /// std::thread::spawn(|| { /// assert_eq!(CELL.set(92), Ok(())); /// }).join().unwrap(); /// /// assert_eq!(CELL.set(62), Err(62)); /// assert_eq!(CELL.get(), Some(&92)); /// } /// ``` pub fn set(&self, value: T) -> Result<(), T> { match self.try_insert(value) { Ok(_) => Ok(()), Err((_, value)) => Err(value), } } /// Like [`set`](Self::set), but also returns a reference to the final cell value. /// /// # Example /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// assert_eq!(cell.try_insert(92), Ok(&92)); /// assert_eq!(cell.try_insert(62), Err((&92, 62))); /// /// assert!(cell.get().is_some()); /// ``` pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { let mut value = Some(value); let res = self.get_or_init(|| unsafe { value.take().unwrap_unchecked() }); match value { None => Ok(res), Some(value) => Err((res, value)), } } /// Gets the contents of the cell, initializing it with `f` if the cell /// was empty. /// /// Many threads may call `get_or_init` concurrently with different /// initializing functions, but it is guaranteed that only one function /// will be executed. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and the cell /// remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. The /// exact outcome is unspecified. Current implementation deadlocks, but /// this may be changed to a panic in the future. /// /// # Example /// ``` /// use once_cell::sync::OnceCell; /// /// let cell = OnceCell::new(); /// let value = cell.get_or_init(|| 92); /// assert_eq!(value, &92); /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, { enum Void {} match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and /// the cell remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. /// The exact outcome is unspecified. Current implementation /// deadlocks, but this may be changed to a panic in the future. /// /// # Example /// ``` /// use once_cell::sync::OnceCell; /// /// let cell = OnceCell::new(); /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); /// assert!(cell.get().is_none()); /// let value = cell.get_or_try_init(|| -> Result { /// Ok(92) /// }); /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { // Fast path check if let Some(value) = self.get() { return Ok(value); } self.0.initialize(f)?; // Safe b/c value is initialized. debug_assert!(self.0.is_initialized()); Ok(unsafe { self.get_unchecked() }) } /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. /// /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. /// /// # Examples /// /// ``` /// use once_cell::sync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.take(), None); /// /// let mut cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` /// /// This method is allowed to violate the invariant of writing to a `OnceCell` /// at most once because it requires `&mut` access to `self`. As with all /// interior mutability, `&mut` access permits arbitrary modification: /// /// ``` /// use once_cell::sync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// cell.set(92).unwrap(); /// cell = OnceCell::new(); /// ``` pub fn take(&mut self) -> Option { mem::take(self).into_inner() } /// Consumes the `OnceCell`, returning the wrapped value. Returns /// `None` if the cell was empty. /// /// # Examples /// /// ``` /// use once_cell::sync::OnceCell; /// /// let cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.into_inner(), None); /// /// let cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[inline] pub fn into_inner(self) -> Option { self.0.into_inner() } } /// A value which is initialized on the first access. /// /// This type is thread-safe and can be used in statics. /// /// # Example /// /// ``` /// use std::collections::HashMap; /// /// use once_cell::sync::Lazy; /// /// static HASHMAP: Lazy> = Lazy::new(|| { /// println!("initializing"); /// let mut m = HashMap::new(); /// m.insert(13, "Spica".to_string()); /// m.insert(74, "Hoyten".to_string()); /// m /// }); /// /// fn main() { /// println!("ready"); /// std::thread::spawn(|| { /// println!("{:?}", HASHMAP.get(&13)); /// }).join().unwrap(); /// println!("{:?}", HASHMAP.get(&74)); /// /// // Prints: /// // ready /// // initializing /// // Some("Spica") /// // Some("Hoyten") /// } /// ``` pub struct Lazy T> { cell: OnceCell, init: Cell>, } impl fmt::Debug for Lazy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() } } // We never create a `&F` from a `&Lazy` so it is fine to not impl // `Sync` for `F`. We do create a `&mut Option` in `force`, but this is // properly synchronized, so it only happens once so it also does not // contribute to this impl. unsafe impl Sync for Lazy where OnceCell: Sync {} // auto-derived `Send` impl is OK. impl RefUnwindSafe for Lazy where OnceCell: RefUnwindSafe {} impl Lazy { /// Creates a new lazy value with the given initializing /// function. pub const fn new(f: F) -> Lazy { Lazy { cell: OnceCell::new(), init: Cell::new(Some(f)) } } /// Consumes this `Lazy` returning the stored value. /// /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. pub fn into_value(this: Lazy) -> Result { let cell = this.cell; let init = this.init; cell.into_inner().ok_or_else(|| { init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) }) } } impl T> Lazy { /// Forces the evaluation of this lazy value and /// returns a reference to the result. This is equivalent /// to the `Deref` impl, but is explicit. /// /// # Example /// ``` /// use once_cell::sync::Lazy; /// /// let lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` pub fn force(this: &Lazy) -> &T { this.cell.get_or_init(|| match this.init.take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }) } /// Forces the evaluation of this lazy value and /// returns a mutable reference to the result. This is equivalent /// to the `Deref` impl, but is explicit. /// /// # Example /// ``` /// use once_cell::sync::Lazy; /// /// let mut lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92); /// ``` pub fn force_mut(this: &mut Lazy) -> &mut T { if this.cell.get_mut().is_none() { let value = match this.init.get_mut().take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }; this.cell = OnceCell::with_value(value); } this.cell.get_mut().unwrap_or_else(|| unreachable!()) } /// Gets the reference to the result of this lazy value if /// it was initialized, otherwise returns `None`. /// /// # Example /// ``` /// use once_cell::sync::Lazy; /// /// let lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::get(&lazy), None); /// assert_eq!(&*lazy, &92); /// assert_eq!(Lazy::get(&lazy), Some(&92)); /// ``` pub fn get(this: &Lazy) -> Option<&T> { this.cell.get() } /// Gets the reference to the result of this lazy value if /// it was initialized, otherwise returns `None`. /// /// # Example /// ``` /// use once_cell::sync::Lazy; /// /// let mut lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::get_mut(&mut lazy), None); /// assert_eq!(&*lazy, &92); /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92)); /// ``` pub fn get_mut(this: &mut Lazy) -> Option<&mut T> { this.cell.get_mut() } } impl T> Deref for Lazy { type Target = T; fn deref(&self) -> &T { Lazy::force(self) } } impl T> DerefMut for Lazy { fn deref_mut(&mut self) -> &mut T { Lazy::force_mut(self) } } impl Default for Lazy { /// Creates a new lazy value using `Default` as the initializing function. fn default() -> Lazy { Lazy::new(T::default) } } /// ```compile_fail /// struct S(*mut ()); /// unsafe impl Sync for S {} /// /// fn share(_: &T) {} /// share(&once_cell::sync::OnceCell::::new()); /// ``` /// /// ```compile_fail /// struct S(*mut ()); /// unsafe impl Sync for S {} /// /// fn share(_: &T) {} /// share(&once_cell::sync::Lazy::::new(|| unimplemented!())); /// ``` fn _dummy() {} } #[cfg(feature = "race")] pub mod race; once_cell/src/race.rs0000644000175000017500000003761215105742312014405 0ustar bdrungbdrung//! Thread-safe, non-blocking, "first one wins" flavor of `OnceCell`. //! //! If two threads race to initialize a type from the `race` module, they //! don't block, execute initialization function together, but only one of //! them stores the result. //! //! This module does not require `std` feature. //! //! # Atomic orderings //! //! All types in this module use `Acquire` and `Release` //! [atomic orderings](Ordering) for all their operations. While this is not //! strictly necessary for types other than `OnceBox`, it is useful for users as //! it allows them to be certain that after `get` or `get_or_init` returns on //! one thread, any side-effects caused by the setter thread prior to them //! calling `set` or `get_or_init` will be made visible to that thread; without //! it, it's possible for it to appear as if they haven't happened yet from the //! getter thread's perspective. This is an acceptable tradeoff to make since //! `Acquire` and `Release` have very little performance overhead on most //! architectures versus `Relaxed`. // The "atomic orderings" section of the documentation above promises // "happens-before" semantics. This drives the choice of orderings in the uses // of `compare_exchange` below. On success, the value was zero/null, so there // was nothing to acquire (there is never any `Ordering::Release` store of 0). // On failure, the value was nonzero, so it was initialized previously (perhaps // on another thread) using `Ordering::Release`, so we must use // `Ordering::Acquire` to ensure that store "happens-before" this load. #[cfg(not(feature = "portable-atomic"))] use core::sync::atomic; #[cfg(feature = "portable-atomic")] use portable_atomic as atomic; use atomic::{AtomicPtr, AtomicUsize, Ordering}; use core::cell::UnsafeCell; use core::marker::PhantomData; use core::num::NonZeroUsize; use core::ptr; /// A thread-safe cell which can be written to only once. #[derive(Default, Debug)] pub struct OnceNonZeroUsize { inner: AtomicUsize, } impl OnceNonZeroUsize { /// Creates a new empty cell. #[inline] pub const fn new() -> Self { Self { inner: AtomicUsize::new(0) } } /// Gets the underlying value. #[inline] pub fn get(&self) -> Option { let val = self.inner.load(Ordering::Acquire); NonZeroUsize::new(val) } /// Get the reference to the underlying value, without checking if the cell /// is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. pub unsafe fn get_unchecked(&self) -> NonZeroUsize { #[inline(always)] fn as_const_ptr(r: &AtomicUsize) -> *const usize { use core::mem::align_of; let p: *const AtomicUsize = r; // SAFETY: "This type has the same size and bit validity as // the underlying integer type, usize. However, the alignment of // this type is always equal to its size, even on targets where // usize has a lesser alignment." const _ALIGNMENT_COMPATIBLE: () = assert!(align_of::() % align_of::() == 0); p.cast::() } // TODO(MSRV-1.70): Use `AtomicUsize::as_ptr().cast_const()` // See https://github.com/rust-lang/rust/issues/138246. let p = as_const_ptr(&self.inner); // SAFETY: The caller is responsible for ensuring that the value // was initialized and that the contents have been acquired by // this thread. Assuming that, we can assume there will be no // conflicting writes to the value since the value will never // change once initialized. This relies on the statement in // https://doc.rust-lang.org/1.83.0/core/sync/atomic/ that "(A // `compare_exchange` or `compare_exchange_weak` that does not // succeed is not considered a write." let val = unsafe { p.read() }; // SAFETY: The caller is responsible for ensuring the value is // initialized and thus not zero. unsafe { NonZeroUsize::new_unchecked(val) } } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(())` if it was /// full. #[inline] pub fn set(&self, value: NonZeroUsize) -> Result<(), ()> { match self.compare_exchange(value) { Ok(_) => Ok(()), Err(_) => Err(()), } } /// Gets the contents of the cell, initializing it with `f` if the cell was /// empty. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_init(&self, f: F) -> NonZeroUsize where F: FnOnce() -> NonZeroUsize, { enum Void {} match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_try_init(&self, f: F) -> Result where F: FnOnce() -> Result, { match self.get() { Some(it) => Ok(it), None => self.init(f), } } #[cold] #[inline(never)] fn init(&self, f: impl FnOnce() -> Result) -> Result { let nz = f()?; let mut val = nz.get(); if let Err(old) = self.compare_exchange(nz) { val = old; } Ok(unsafe { NonZeroUsize::new_unchecked(val) }) } #[inline(always)] fn compare_exchange(&self, val: NonZeroUsize) -> Result { self.inner.compare_exchange(0, val.get(), Ordering::Release, Ordering::Acquire) } } /// A thread-safe cell which can be written to only once. #[derive(Default, Debug)] pub struct OnceBool { inner: OnceNonZeroUsize, } impl OnceBool { /// Creates a new empty cell. #[inline] pub const fn new() -> Self { Self { inner: OnceNonZeroUsize::new() } } /// Gets the underlying value. #[inline] pub fn get(&self) -> Option { self.inner.get().map(Self::from_usize) } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(())` if it was /// full. #[inline] pub fn set(&self, value: bool) -> Result<(), ()> { self.inner.set(Self::to_usize(value)) } /// Gets the contents of the cell, initializing it with `f` if the cell was /// empty. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_init(&self, f: F) -> bool where F: FnOnce() -> bool, { Self::from_usize(self.inner.get_or_init(|| Self::to_usize(f()))) } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_try_init(&self, f: F) -> Result where F: FnOnce() -> Result, { self.inner.get_or_try_init(|| f().map(Self::to_usize)).map(Self::from_usize) } #[inline] fn from_usize(value: NonZeroUsize) -> bool { value.get() == 1 } #[inline] fn to_usize(value: bool) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(if value { 1 } else { 2 }) } } } /// A thread-safe cell which can be written to only once. pub struct OnceRef<'a, T> { inner: AtomicPtr, ghost: PhantomData>, } // TODO: Replace UnsafeCell with SyncUnsafeCell once stabilized unsafe impl<'a, T: Sync> Sync for OnceRef<'a, T> {} impl<'a, T> core::fmt::Debug for OnceRef<'a, T> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "OnceRef({:?})", self.inner) } } impl<'a, T> Default for OnceRef<'a, T> { fn default() -> Self { Self::new() } } impl<'a, T> OnceRef<'a, T> { /// Creates a new empty cell. pub const fn new() -> Self { Self { inner: AtomicPtr::new(ptr::null_mut()), ghost: PhantomData } } /// Gets a reference to the underlying value. pub fn get(&self) -> Option<&'a T> { let ptr = self.inner.load(Ordering::Acquire); unsafe { ptr.as_ref() } } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was /// full. pub fn set(&self, value: &'a T) -> Result<(), ()> { match self.compare_exchange(value) { Ok(_) => Ok(()), Err(_) => Err(()), } } /// Gets the contents of the cell, initializing it with `f` if the cell was /// empty. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_init(&self, f: F) -> &'a T where F: FnOnce() -> &'a T, { enum Void {} match self.get_or_try_init(|| Ok::<&'a T, Void>(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_try_init(&self, f: F) -> Result<&'a T, E> where F: FnOnce() -> Result<&'a T, E>, { match self.get() { Some(val) => Ok(val), None => self.init(f), } } #[cold] #[inline(never)] fn init(&self, f: impl FnOnce() -> Result<&'a T, E>) -> Result<&'a T, E> { let mut value: &'a T = f()?; if let Err(old) = self.compare_exchange(value) { value = unsafe { &*old }; } Ok(value) } #[inline(always)] fn compare_exchange(&self, value: &'a T) -> Result<(), *const T> { self.inner .compare_exchange( ptr::null_mut(), <*const T>::cast_mut(value), Ordering::Release, Ordering::Acquire, ) .map(|_: *mut T| ()) .map_err(<*mut T>::cast_const) } /// ```compile_fail /// use once_cell::race::OnceRef; /// /// let mut l = OnceRef::new(); /// /// { /// let y = 2; /// let mut r = OnceRef::new(); /// r.set(&y).unwrap(); /// core::mem::swap(&mut l, &mut r); /// } /// /// // l now contains a dangling reference to y /// eprintln!("uaf: {}", l.get().unwrap()); /// ``` fn _dummy() {} } #[cfg(feature = "alloc")] pub use self::once_box::OnceBox; #[cfg(feature = "alloc")] mod once_box { use super::atomic::{AtomicPtr, Ordering}; use core::{marker::PhantomData, ptr}; use alloc::boxed::Box; /// A thread-safe cell which can be written to only once. pub struct OnceBox { inner: AtomicPtr, ghost: PhantomData>>, } impl core::fmt::Debug for OnceBox { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "OnceBox({:?})", self.inner.load(Ordering::Relaxed)) } } impl Default for OnceBox { fn default() -> Self { Self::new() } } impl Drop for OnceBox { fn drop(&mut self) { let ptr = *self.inner.get_mut(); if !ptr.is_null() { drop(unsafe { Box::from_raw(ptr) }) } } } impl OnceBox { /// Creates a new empty cell. pub const fn new() -> Self { Self { inner: AtomicPtr::new(ptr::null_mut()), ghost: PhantomData } } /// Creates a new cell with the given value. pub fn with_value(value: Box) -> Self { Self { inner: AtomicPtr::new(Box::into_raw(value)), ghost: PhantomData } } /// Gets a reference to the underlying value. pub fn get(&self) -> Option<&T> { let ptr = self.inner.load(Ordering::Acquire); if ptr.is_null() { return None; } Some(unsafe { &*ptr }) } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was /// full. pub fn set(&self, value: Box) -> Result<(), Box> { let ptr = Box::into_raw(value); let exchange = self.inner.compare_exchange( ptr::null_mut(), ptr, Ordering::Release, Ordering::Acquire, ); if exchange.is_err() { let value = unsafe { Box::from_raw(ptr) }; return Err(value); } Ok(()) } /// Gets the contents of the cell, initializing it with `f` if the cell was /// empty. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> Box, { enum Void {} match self.get_or_try_init(|| Ok::, Void>(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, E>, { match self.get() { Some(val) => Ok(val), None => self.init(f) } } #[cold] #[inline(never)] fn init(&self, f: impl FnOnce() -> Result, E>) -> Result<&T, E> { let val = f()?; let mut ptr = Box::into_raw(val); let exchange = self.inner.compare_exchange( ptr::null_mut(), ptr, Ordering::Release, Ordering::Acquire, ); if let Err(old) = exchange { drop(unsafe { Box::from_raw(ptr) }); ptr = old; } Ok(unsafe { &*ptr }) } } unsafe impl Sync for OnceBox {} impl Clone for OnceBox { fn clone(&self) -> Self { match self.get() { Some(value) => OnceBox::with_value(Box::new(value.clone())), None => OnceBox::new(), } } } /// ```compile_fail /// struct S(*mut ()); /// unsafe impl Sync for S {} /// /// fn share(_: &T) {} /// share(&once_cell::race::OnceBox::::new()); /// ``` fn _dummy() {} } once_cell/src/imp_std.rs0000644000175000017500000003070715105742312015130 0ustar bdrungbdrung// There's a lot of scary concurrent code in this module, but it is copied from // `std::sync::Once` with two changes: // * no poisoning // * init function can fail use std::{ cell::{Cell, UnsafeCell}, panic::{RefUnwindSafe, UnwindSafe}, sync::atomic::{AtomicBool, AtomicPtr, Ordering}, thread::{self, Thread}, }; #[derive(Debug)] pub(crate) struct OnceCell { // This `queue` field is the core of the implementation. It encodes two // pieces of information: // // * The current state of the cell (`INCOMPLETE`, `RUNNING`, `COMPLETE`) // * Linked list of threads waiting for the current cell. // // State is encoded in two low bits. Only `INCOMPLETE` and `RUNNING` states // allow waiters. queue: AtomicPtr, value: UnsafeCell>, } // Why do we need `T: Send`? // Thread A creates a `OnceCell` and shares it with // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. unsafe impl Sync for OnceCell {} unsafe impl Send for OnceCell {} impl RefUnwindSafe for OnceCell {} impl UnwindSafe for OnceCell {} impl OnceCell { pub(crate) const fn new() -> OnceCell { OnceCell { queue: AtomicPtr::new(INCOMPLETE_PTR), value: UnsafeCell::new(None) } } pub(crate) const fn with_value(value: T) -> OnceCell { OnceCell { queue: AtomicPtr::new(COMPLETE_PTR), value: UnsafeCell::new(Some(value)) } } /// Safety: synchronizes with store to value via Release/(Acquire|SeqCst). #[inline] pub(crate) fn is_initialized(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization // operations visible to us, and, this being a fast path, weaker // ordering helps with performance. This `Acquire` synchronizes with // `SeqCst` operations on the slow path. self.queue.load(Ordering::Acquire) == COMPLETE_PTR } /// Safety: synchronizes with store to value via SeqCst read from state, /// writes value only once because we never get to INCOMPLETE state after a /// successful write. #[cold] pub(crate) fn initialize(&self, f: F) -> Result<(), E> where F: FnOnce() -> Result, { let mut f = Some(f); let mut res: Result<(), E> = Ok(()); let slot: *mut Option = self.value.get(); initialize_or_wait( &self.queue, Some(&mut || { let f = unsafe { f.take().unwrap_unchecked() }; match f() { Ok(value) => { unsafe { *slot = Some(value) }; true } Err(err) => { res = Err(err); false } } }), ); res } #[cold] pub(crate) fn wait(&self) { initialize_or_wait(&self.queue, None); } /// Get the reference to the underlying value, without checking if the cell /// is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); let slot = &*self.value.get(); slot.as_ref().unwrap_unchecked() } /// Gets the mutable reference to the underlying value. /// Returns `None` if the cell is empty. pub(crate) fn get_mut(&mut self) -> Option<&mut T> { // Safe b/c we have a unique access. unsafe { &mut *self.value.get() }.as_mut() } /// Consumes this `OnceCell`, returning the wrapped value. /// Returns `None` if the cell was empty. #[inline] pub(crate) fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically // verifies that it is not currently borrowed. // So, it is safe to move out `Option`. self.value.into_inner() } } // Three states that a OnceCell can be in, encoded into the lower bits of `queue` in // the OnceCell structure. const INCOMPLETE: usize = 0x0; const RUNNING: usize = 0x1; const COMPLETE: usize = 0x2; const INCOMPLETE_PTR: *mut Waiter = INCOMPLETE as *mut Waiter; const COMPLETE_PTR: *mut Waiter = COMPLETE as *mut Waiter; // Mask to learn about the state. All other bits are the queue of waiters if // this is in the RUNNING state. const STATE_MASK: usize = 0x3; /// Representation of a node in the linked list of waiters in the RUNNING state. /// A waiters is stored on the stack of the waiting threads. #[repr(align(4))] // Ensure the two lower bits are free to use as state bits. struct Waiter { thread: Cell>, signaled: AtomicBool, next: *mut Waiter, } /// Drains and notifies the queue of waiters on drop. struct Guard<'a> { queue: &'a AtomicPtr, new_queue: *mut Waiter, } impl Drop for Guard<'_> { fn drop(&mut self) { let queue = self.queue.swap(self.new_queue, Ordering::AcqRel); let state = strict::addr(queue) & STATE_MASK; assert_eq!(state, RUNNING); unsafe { let mut waiter = strict::map_addr(queue, |q| q & !STATE_MASK); while !waiter.is_null() { let next = (*waiter).next; let thread = (*waiter).thread.take().unwrap(); (*waiter).signaled.store(true, Ordering::Release); waiter = next; thread.unpark(); } } } } // Corresponds to `std::sync::Once::call_inner`. // // Originally copied from std, but since modified to remove poisoning and to // support wait. // // Note: this is intentionally monomorphic #[inline(never)] fn initialize_or_wait(queue: &AtomicPtr, mut init: Option<&mut dyn FnMut() -> bool>) { let mut curr_queue = queue.load(Ordering::Acquire); loop { let curr_state = strict::addr(curr_queue) & STATE_MASK; match (curr_state, &mut init) { (COMPLETE, _) => return, (INCOMPLETE, Some(init)) => { let exchange = queue.compare_exchange( curr_queue, strict::map_addr(curr_queue, |q| (q & !STATE_MASK) | RUNNING), Ordering::Acquire, Ordering::Acquire, ); if let Err(new_queue) = exchange { curr_queue = new_queue; continue; } let mut guard = Guard { queue, new_queue: INCOMPLETE_PTR }; if init() { guard.new_queue = COMPLETE_PTR; } return; } (INCOMPLETE, None) | (RUNNING, _) => { wait(queue, curr_queue); curr_queue = queue.load(Ordering::Acquire); } _ => debug_assert!(false), } } } fn wait(queue: &AtomicPtr, mut curr_queue: *mut Waiter) { let curr_state = strict::addr(curr_queue) & STATE_MASK; loop { let node = Waiter { thread: Cell::new(Some(thread::current())), signaled: AtomicBool::new(false), next: strict::map_addr(curr_queue, |q| q & !STATE_MASK), }; let me = &node as *const Waiter as *mut Waiter; let exchange = queue.compare_exchange( curr_queue, strict::map_addr(me, |q| q | curr_state), Ordering::Release, Ordering::Relaxed, ); if let Err(new_queue) = exchange { if strict::addr(new_queue) & STATE_MASK != curr_state { return; } curr_queue = new_queue; continue; } while !node.signaled.load(Ordering::Acquire) { thread::park(); } break; } } // Polyfill of strict provenance from https://crates.io/crates/sptr. // // Use free-standing function rather than a trait to keep things simple and // avoid any potential conflicts with future stabile std API. mod strict { #[must_use] #[inline] pub(crate) fn addr(ptr: *mut T) -> usize where T: Sized, { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the // provenance). unsafe { core::mem::transmute(ptr) } } #[must_use] #[inline] pub(crate) fn with_addr(ptr: *mut T, addr: usize) -> *mut T where T: Sized, { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. // // In the mean-time, this operation is defined to be "as if" it was // a wrapping_offset, so we can emulate it as such. This should properly // restore pointer provenance even under today's compiler. let self_addr = self::addr(ptr) as isize; let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); // This is the canonical desugarring of this operation, // but `pointer::cast` was only stabilized in 1.38. // self.cast::().wrapping_offset(offset).cast::() (ptr as *mut u8).wrapping_offset(offset) as *mut T } #[must_use] #[inline] pub(crate) fn map_addr(ptr: *mut T, f: impl FnOnce(usize) -> usize) -> *mut T where T: Sized, { self::with_addr(ptr, f(addr(ptr))) } } // These test are snatched from std as well. #[cfg(test)] mod tests { use std::panic; use std::{sync::mpsc::channel, thread}; use super::OnceCell; impl OnceCell { fn init(&self, f: impl FnOnce() -> T) { enum Void {} let _ = self.initialize(|| Ok::(f())); } } #[test] fn smoke_once() { static O: OnceCell<()> = OnceCell::new(); let mut a = 0; O.init(|| a += 1); assert_eq!(a, 1); O.init(|| a += 1); assert_eq!(a, 1); } #[test] fn stampede_once() { static O: OnceCell<()> = OnceCell::new(); static mut RUN: bool = false; let (tx, rx) = channel(); for _ in 0..10 { let tx = tx.clone(); thread::spawn(move || { for _ in 0..4 { thread::yield_now() } unsafe { O.init(|| { assert!(!RUN); RUN = true; }); assert!(RUN); } tx.send(()).unwrap(); }); } unsafe { O.init(|| { assert!(!RUN); RUN = true; }); assert!(RUN); } for _ in 0..10 { rx.recv().unwrap(); } } #[test] fn poison_bad() { static O: OnceCell<()> = OnceCell::new(); // poison the once let t = panic::catch_unwind(|| { O.init(|| panic!()); }); assert!(t.is_err()); // we can subvert poisoning, however let mut called = false; O.init(|| { called = true; }); assert!(called); // once any success happens, we stop propagating the poison O.init(|| {}); } #[test] fn wait_for_force_to_finish() { static O: OnceCell<()> = OnceCell::new(); // poison the once let t = panic::catch_unwind(|| { O.init(|| panic!()); }); assert!(t.is_err()); // make sure someone's waiting inside the once via a force let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); let t1 = thread::spawn(move || { O.init(|| { tx1.send(()).unwrap(); rx2.recv().unwrap(); }); }); rx1.recv().unwrap(); // put another waiter on the once let t2 = thread::spawn(|| { let mut called = false; O.init(|| { called = true; }); assert!(!called); }); tx2.send(()).unwrap(); assert!(t1.join().is_ok()); assert!(t2.join().is_ok()); } #[test] #[cfg(target_pointer_width = "64")] fn test_size() { use std::mem::size_of; assert_eq!(size_of::>(), 4 * size_of::()); } } once_cell/src/imp_cs.rs0000644000175000017500000000466515105742312014747 0ustar bdrungbdrunguse core::panic::{RefUnwindSafe, UnwindSafe}; use critical_section::{CriticalSection, Mutex}; use portable_atomic::{AtomicBool, Ordering}; use crate::unsync; pub(crate) struct OnceCell { initialized: AtomicBool, // Use `unsync::OnceCell` internally since `Mutex` does not provide // interior mutability and to be able to re-use `get_or_try_init`. value: Mutex>, } // Why do we need `T: Send`? // Thread A creates a `OnceCell` and shares it with // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. unsafe impl Sync for OnceCell {} unsafe impl Send for OnceCell {} impl RefUnwindSafe for OnceCell {} impl UnwindSafe for OnceCell {} impl OnceCell { pub(crate) const fn new() -> OnceCell { OnceCell { initialized: AtomicBool::new(false), value: Mutex::new(unsync::OnceCell::new()) } } pub(crate) const fn with_value(value: T) -> OnceCell { OnceCell { initialized: AtomicBool::new(true), value: Mutex::new(unsync::OnceCell::with_value(value)), } } #[inline] pub(crate) fn is_initialized(&self) -> bool { self.initialized.load(Ordering::Acquire) } #[cold] pub(crate) fn initialize(&self, f: F) -> Result<(), E> where F: FnOnce() -> Result, { critical_section::with(|cs| { let cell = self.value.borrow(cs); cell.get_or_try_init(f).map(|_| { self.initialized.store(true, Ordering::Release); }) }) } /// Get the reference to the underlying value, without checking if the cell /// is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); // SAFETY: The caller ensures that the value is initialized and access synchronized. self.value.borrow(CriticalSection::new()).get().unwrap_unchecked() } #[inline] pub(crate) fn get_mut(&mut self) -> Option<&mut T> { self.value.get_mut().get_mut() } #[inline] pub(crate) fn into_inner(self) -> Option { self.value.into_inner().into_inner() } } once_cell/src/imp_pl.rs0000644000175000017500000001325315105742312014746 0ustar bdrungbdrunguse std::{ cell::UnsafeCell, panic::{RefUnwindSafe, UnwindSafe}, sync::atomic::{AtomicU8, Ordering}, }; pub(crate) struct OnceCell { state: AtomicU8, value: UnsafeCell>, } const INCOMPLETE: u8 = 0x0; const RUNNING: u8 = 0x1; const COMPLETE: u8 = 0x2; // Why do we need `T: Send`? // Thread A creates a `OnceCell` and shares it with // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. unsafe impl Sync for OnceCell {} unsafe impl Send for OnceCell {} impl RefUnwindSafe for OnceCell {} impl UnwindSafe for OnceCell {} impl OnceCell { pub(crate) const fn new() -> OnceCell { OnceCell { state: AtomicU8::new(INCOMPLETE), value: UnsafeCell::new(None) } } pub(crate) const fn with_value(value: T) -> OnceCell { OnceCell { state: AtomicU8::new(COMPLETE), value: UnsafeCell::new(Some(value)) } } /// Safety: synchronizes with store to value via Release/Acquire. #[inline] pub(crate) fn is_initialized(&self) -> bool { self.state.load(Ordering::Acquire) == COMPLETE } /// Safety: synchronizes with store to value via `is_initialized` or mutex /// lock/unlock, writes value only once because of the mutex. #[cold] pub(crate) fn initialize(&self, f: F) -> Result<(), E> where F: FnOnce() -> Result, { let mut f = Some(f); let mut res: Result<(), E> = Ok(()); let slot: *mut Option = self.value.get(); initialize_inner(&self.state, &mut || { // We are calling user-supplied function and need to be careful. // - if it returns Err, we unlock mutex and return without touching anything // - if it panics, we unlock mutex and propagate panic without touching anything // - if it calls `set` or `get_or_try_init` re-entrantly, we get a deadlock on // mutex, which is important for safety. We *could* detect this and panic, // but that is more complicated // - finally, if it returns Ok, we store the value and store the flag with // `Release`, which synchronizes with `Acquire`s. let f = unsafe { f.take().unwrap_unchecked() }; match f() { Ok(value) => unsafe { // Safe b/c we have a unique access and no panic may happen // until the cell is marked as initialized. debug_assert!((*slot).is_none()); *slot = Some(value); true }, Err(err) => { res = Err(err); false } } }); res } #[cold] pub(crate) fn wait(&self) { let key = &self.state as *const _ as usize; unsafe { parking_lot_core::park( key, || self.state.load(Ordering::Acquire) != COMPLETE, || (), |_, _| (), parking_lot_core::DEFAULT_PARK_TOKEN, None, ); } } /// Get the reference to the underlying value, without checking if the cell /// is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); let slot = &*self.value.get(); slot.as_ref().unwrap_unchecked() } /// Gets the mutable reference to the underlying value. /// Returns `None` if the cell is empty. pub(crate) fn get_mut(&mut self) -> Option<&mut T> { // Safe b/c we have an exclusive access let slot: &mut Option = unsafe { &mut *self.value.get() }; slot.as_mut() } /// Consumes this `OnceCell`, returning the wrapped value. /// Returns `None` if the cell was empty. pub(crate) fn into_inner(self) -> Option { self.value.into_inner() } } struct Guard<'a> { state: &'a AtomicU8, new_state: u8, } impl<'a> Drop for Guard<'a> { fn drop(&mut self) { self.state.store(self.new_state, Ordering::Release); unsafe { let key = self.state as *const AtomicU8 as usize; parking_lot_core::unpark_all(key, parking_lot_core::DEFAULT_UNPARK_TOKEN); } } } // Note: this is intentionally monomorphic #[inline(never)] fn initialize_inner(state: &AtomicU8, init: &mut dyn FnMut() -> bool) { loop { let exchange = state.compare_exchange_weak(INCOMPLETE, RUNNING, Ordering::Acquire, Ordering::Acquire); match exchange { Ok(_) => { let mut guard = Guard { state, new_state: INCOMPLETE }; if init() { guard.new_state = COMPLETE; } return; } Err(COMPLETE) => return, Err(RUNNING) => unsafe { let key = state as *const AtomicU8 as usize; parking_lot_core::park( key, || state.load(Ordering::Relaxed) == RUNNING, || (), |_, _| (), parking_lot_core::DEFAULT_PARK_TOKEN, None, ); }, Err(INCOMPLETE) => (), Err(_) => debug_assert!(false), } } } #[test] fn test_size() { use std::mem::size_of; assert_eq!(size_of::>(), 1 * size_of::() + size_of::()); } portable-atomic/0000775000175000017500000000000015105742312013466 5ustar bdrungbdrungportable-atomic/build.rs0000644000175000017500000007570315105742312015145 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT // The rustc-cfg emitted by the build script are *not* public API. #![allow(clippy::match_same_arms)] // https://github.com/rust-lang/rust-clippy/issues/12044 #[path = "version.rs"] mod version; use self::version::{Version, rustc_version}; #[path = "src/gen/build.rs"] mod generated; use std::{env, str}; fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=src/gen/build.rs"); println!("cargo:rerun-if-changed=version.rs"); #[cfg(feature = "unsafe-assume-single-core")] println!("cargo:rustc-cfg=portable_atomic_unsafe_assume_single_core"); #[cfg(feature = "s-mode")] println!("cargo:rustc-cfg=portable_atomic_s_mode"); #[cfg(feature = "force-amo")] println!("cargo:rustc-cfg=portable_atomic_force_amo"); #[cfg(feature = "disable-fiq")] println!("cargo:rustc-cfg=portable_atomic_disable_fiq"); let target = &*env::var("TARGET").expect("TARGET not set"); let target_arch = &*env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH not set"); let target_os = &*env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS not set"); let version = match rustc_version() { Some(version) => version, None => { if env::var_os("PORTABLE_ATOMIC_DENY_WARNINGS").is_some() { panic!("unable to determine rustc version") } println!( "cargo:warning={}: unable to determine rustc version; assuming latest stable rustc (1.{})", env!("CARGO_PKG_NAME"), Version::LATEST.minor ); Version::LATEST } }; if version.minor >= 80 { println!( r#"cargo:rustc-check-cfg=cfg(target_feature,values("zacas","fast-serialization","load-store-on-cond","distinct-ops","miscellaneous-extensions-3"))"# ); // Custom cfgs set by build script. Not public API. // grep -F 'cargo:rustc-cfg=' build.rs | grep -Ev '^ *//' | sed -E 's/^.*cargo:rustc-cfg=//; s/(=\\)?".*$//' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/' println!( "cargo:rustc-check-cfg=cfg(portable_atomic_disable_fiq,portable_atomic_force_amo,portable_atomic_ll_sc_rmw,portable_atomic_new_atomic_intrinsics,portable_atomic_no_asm,portable_atomic_no_asm_maybe_uninit,portable_atomic_no_atomic_64,portable_atomic_no_atomic_cas,portable_atomic_no_atomic_load_store,portable_atomic_no_atomic_min_max,portable_atomic_no_cfg_target_has_atomic,portable_atomic_no_cmpxchg16b_intrinsic,portable_atomic_no_cmpxchg16b_target_feature,portable_atomic_no_const_mut_refs,portable_atomic_no_const_raw_ptr_deref,portable_atomic_no_const_transmute,portable_atomic_no_core_unwind_safe,portable_atomic_no_diagnostic_namespace,portable_atomic_no_offset_of,portable_atomic_no_strict_provenance,portable_atomic_no_stronger_failure_ordering,portable_atomic_no_track_caller,portable_atomic_no_unsafe_op_in_unsafe_fn,portable_atomic_pre_llvm_15,portable_atomic_pre_llvm_16,portable_atomic_pre_llvm_18,portable_atomic_pre_llvm_20,portable_atomic_s_mode,portable_atomic_sanitize_thread,portable_atomic_target_feature,portable_atomic_unsafe_assume_single_core,portable_atomic_unstable_asm,portable_atomic_unstable_asm_experimental_arch,portable_atomic_unstable_cfg_target_has_atomic,portable_atomic_unstable_isa_attribute)" ); // TODO: handle multi-line target_feature_fallback // grep -F 'target_feature_fallback("' build.rs | grep -Ev '^ *//' | sed -E 's/^.*target_feature_fallback\(//; s/",.*$/"/' | LC_ALL=C sort -u | tr '\n' ',' | sed -E 's/,$/\n/' println!( r#"cargo:rustc-check-cfg=cfg(portable_atomic_target_feature,values("cmpxchg16b","distinct-ops","fast-serialization","load-store-on-cond","lse","lse128","lse2","mclass","miscellaneous-extensions-3","quadword-atomics","rcpc3","v6","zaamo","zabha","zacas"))"# ); } // https://github.com/rust-lang/rust/pull/123745 (includes https://github.com/rust-lang/cargo/pull/13560) merged in Rust 1.79 (nightly-2024-04-11). if !version.probe(79, 2024, 4, 10) { // HACK: If --target is specified, rustflags is not applied to the build // script itself, so the build script will not be recompiled when rustflags // is changed. That in itself is not a problem, but the old Cargo does // not rerun the build script as well, which can be problematic. // https://github.com/rust-lang/cargo/issues/13003 // This problem has been fixed in 1.79 so only older versions need a workaround. println!("cargo:rerun-if-env-changed=CARGO_ENCODED_RUSTFLAGS"); println!("cargo:rerun-if-env-changed=RUSTFLAGS"); println!("cargo:rerun-if-env-changed=CARGO_BUILD_RUSTFLAGS"); let mut target_upper = target.replace(|c: char| c == '-' || c == '.', "_"); target_upper.make_ascii_uppercase(); println!("cargo:rerun-if-env-changed=CARGO_TARGET_{}_RUSTFLAGS", target_upper); } // Note that cfgs are `no_`*, not `has_*`. This allows treating as the latest // stable rustc is used when the build script doesn't run. This is useful // for non-cargo build systems that don't run the build script. // atomic_min_max stabilized in Rust 1.45 (nightly-2020-05-30): https://github.com/rust-lang/rust/pull/72324 if !version.probe(45, 2020, 5, 29) { println!("cargo:rustc-cfg=portable_atomic_no_atomic_min_max"); } // track_caller stabilized in Rust 1.46 (nightly-2020-07-02): https://github.com/rust-lang/rust/pull/72445 if !version.probe(46, 2020, 7, 1) { println!("cargo:rustc-cfg=portable_atomic_no_track_caller"); } // unsafe_op_in_unsafe_fn stabilized in Rust 1.52 (nightly-2021-03-11): https://github.com/rust-lang/rust/pull/79208 if !version.probe(52, 2021, 3, 10) { println!("cargo:rustc-cfg=portable_atomic_no_unsafe_op_in_unsafe_fn"); } // const_transmute stabilized in Rust 1.56 (nightly-2021-07-29): https://github.com/rust-lang/rust/pull/85769 if !version.probe(56, 2021, 7, 28) { println!("cargo:rustc-cfg=portable_atomic_no_const_transmute"); } // https://github.com/rust-lang/rust/pull/84662 merged in Rust 1.56 (nightly-2021-08-02). if !version.probe(56, 2021, 8, 1) { println!("cargo:rustc-cfg=portable_atomic_no_core_unwind_safe"); } // const_raw_ptr_deref stabilized in Rust 1.58 (nightly-2021-11-15): https://github.com/rust-lang/rust/pull/89551 if !version.probe(58, 2021, 11, 14) { println!("cargo:rustc-cfg=portable_atomic_no_const_raw_ptr_deref"); } // https://github.com/rust-lang/rust/pull/98383 merged in Rust 1.64 (nightly-2022-07-19). if !version.probe(64, 2022, 7, 18) { println!("cargo:rustc-cfg=portable_atomic_no_stronger_failure_ordering"); } // https://github.com/rust-lang/rust/pull/114790 merged in nightly-2023-08-24 if !version.probe(74, 2023, 8, 23) { println!("cargo:rustc-cfg=portable_atomic_no_asm_maybe_uninit"); } // For test if version.minor < 77 { println!("cargo:rustc-cfg=portable_atomic_no_offset_of"); } // #[diagnostic] stabilized in Rust 1.78 (nightly-2024-03-09): https://github.com/rust-lang/rust/pull/119888 if !version.probe(78, 2024, 3, 8) { println!("cargo:rustc-cfg=portable_atomic_no_diagnostic_namespace"); } // const_mut_refs/const_refs_to_cell stabilized in Rust 1.83 (nightly-2024-09-16): https://github.com/rust-lang/rust/pull/129195 if !version.probe(83, 2024, 9, 15) { println!("cargo:rustc-cfg=portable_atomic_no_const_mut_refs"); } // strict_provenance/exposed_provenance APIs stabilized in Rust 1.84 (nightly-2024-10-22): https://github.com/rust-lang/rust/pull/130350 if !version.probe(84, 2024, 10, 21) { println!("cargo:rustc-cfg=portable_atomic_no_strict_provenance"); } // asm! on AArch64, Arm, RISC-V, x86, and x86_64 stabilized in Rust 1.59 (nightly-2021-12-16): https://github.com/rust-lang/rust/pull/91728 let no_asm = !version.probe(59, 2021, 12, 15); if no_asm { if version.nightly && version.probe(46, 2020, 6, 20) && ((target_arch != "x86" && target_arch != "x86_64") || version.llvm >= 10) && is_allowed_feature("asm") { // This feature was added in Rust 1.45 (nightly-2020-05-20), but // concat! in asm! requires Rust 1.46 (nightly-2020-06-21). // x86 intel syntax requires LLVM 10 (since Rust 1.53, the minimum // external LLVM version is 10+: https://github.com/rust-lang/rust/pull/83387). // The part of this feature we use has not been changed since nightly-2020-06-21 // until it was stabilized, so it can safely be enabled in nightly for that period. println!("cargo:rustc-cfg=portable_atomic_unstable_asm"); } println!("cargo:rustc-cfg=portable_atomic_no_asm"); } else { match target_arch { "arm64ec" | "s390x" => { // asm! on Arm64EC and s390x stabilized in Rust 1.84 (nightly-2024-11-11): https://github.com/rust-lang/rust/pull/131781, https://github.com/rust-lang/rust/pull/131258 if !version.probe(84, 2024, 11, 10) { if version.nightly && (target_arch != "s390x" || version.probe(71, 2023, 5, 8)) && is_allowed_feature("asm_experimental_arch") { // https://github.com/rust-lang/rust/pull/111331 merged in Rust 1.71 (nightly-2023-05-09). // The part of this feature we use has not been changed since nightly-2023-05-09 // until it was stabilized, so it can safely be enabled in nightly for that period. println!("cargo:rustc-cfg=portable_atomic_unstable_asm_experimental_arch"); } else { println!("cargo:rustc-cfg=portable_atomic_no_asm"); } } } "powerpc64" => { // https://github.com/rust-lang/rust/pull/93868 merged in Rust 1.60 (nightly-2022-02-13). if version.nightly && version.probe(60, 2022, 2, 12) && is_allowed_feature("asm_experimental_arch") { println!("cargo:rustc-cfg=portable_atomic_unstable_asm_experimental_arch"); } } _ => {} } } // feature(cfg_target_has_atomic) stabilized in Rust 1.60 (nightly-2022-02-11): https://github.com/rust-lang/rust/pull/93824 if !version.probe(60, 2022, 2, 10) { if version.nightly && version.probe(40, 2019, 10, 13) && is_allowed_feature("cfg_target_has_atomic") { // The part of this feature we use has not been changed since nightly-2019-10-14 // until it was stabilized, so it can safely be enabled in nightly for that period. println!("cargo:rustc-cfg=portable_atomic_unstable_cfg_target_has_atomic"); } else { println!("cargo:rustc-cfg=portable_atomic_no_cfg_target_has_atomic"); let target = &*convert_custom_linux_target(target); if generated::NO_ATOMIC_CAS.contains(&target) { println!("cargo:rustc-cfg=portable_atomic_no_atomic_cas"); } if generated::NO_ATOMIC_64.contains(&target) { println!("cargo:rustc-cfg=portable_atomic_no_atomic_64"); } else { // Otherwise, assuming `"max-atomic-width" == 64` or `"max-atomic-width" == 128`. } } } // We don't need to use convert_custom_linux_target here because all linux targets have atomics. if generated::NO_ATOMIC.contains(&target) { println!("cargo:rustc-cfg=portable_atomic_no_atomic_load_store"); } if version.llvm < 20 { println!("cargo:rustc-cfg=portable_atomic_pre_llvm_20"); if version.llvm < 18 { println!("cargo:rustc-cfg=portable_atomic_pre_llvm_18"); if version.llvm < 16 { println!("cargo:rustc-cfg=portable_atomic_pre_llvm_16"); if version.llvm < 15 { println!("cargo:rustc-cfg=portable_atomic_pre_llvm_15"); } } } } if version.nightly { // `cfg(sanitize = "..")` is not stabilized. let sanitize = env::var("CARGO_CFG_SANITIZE").unwrap_or_default(); if sanitize.contains("thread") { // Most kinds of sanitizers are not compatible with asm // (https://github.com/google/sanitizers/issues/192), // but it seems that ThreadSanitizer is the only one that can cause // false positives in our code. println!("cargo:rustc-cfg=portable_atomic_sanitize_thread"); } } match target_arch { "x86_64" => { // cmpxchg16b_target_feature stabilized in Rust 1.69 (nightly-2023-03-01): https://github.com/rust-lang/rust/pull/106774 if !version.probe(69, 2023, 2, 28) { println!("cargo:rustc-cfg=portable_atomic_no_cmpxchg16b_target_feature"); } // For Miri and ThreadSanitizer. // https://github.com/rust-lang/rust/pull/109359 (includes https://github.com/rust-lang/stdarch/pull/1358) merged in Rust 1.70 (nightly-2023-03-24). if version.nightly && !version.probe(70, 2023, 3, 23) { println!("cargo:rustc-cfg=portable_atomic_no_cmpxchg16b_intrinsic"); } // cmpxchg16b_target_feature stabilized in Rust 1.69. if needs_target_feature_fallback(&version, Some(69)) { // x86_64 Apple targets always support CMPXCHG16B: // https://github.com/rust-lang/rust/blob/1.68.0/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs#L8 // https://github.com/rust-lang/rust/blob/1.68.0/compiler/rustc_target/src/spec/apple_base.rs#L69-L70 // (Since Rust 1.78, Windows (except Windows 7) targets also enable CMPXCHG16B, but // this branch is only used on pre-1.69 that cmpxchg16b_target_feature is unstable.) // Script to get builtin targets that support CMPXCHG16B by default: // $ (for target in $(rustc -Z unstable-options --print all-target-specs-json | jq -r '. | to_entries[] | if .value.arch == "x86_64" then .key else empty end'); do rustc --print cfg --target "${target}" | grep -Fq '"cmpxchg16b"' && printf '%s\n' "${target}"; done) let is_apple = env::var("CARGO_CFG_TARGET_VENDOR").unwrap_or_default() == "apple"; let cmpxchg16b = is_apple; // LLVM recognizes this also as cx16 target feature: https://godbolt.org/z/KM3jz616j // However, it is unlikely that rustc will support that name, so we ignore it. target_feature_fallback("cmpxchg16b", cmpxchg16b); } } "aarch64" | "arm64ec" => { // For Miri and ThreadSanitizer. // https://github.com/rust-lang/rust/pull/97423 merged in Rust 1.64 (nightly-2022-06-30). if version.nightly && version.probe(64, 2022, 6, 29) { println!("cargo:rustc-cfg=portable_atomic_new_atomic_intrinsics"); } // target_feature "lse2"/"lse128"/"rcpc3" is unstable and available on rustc side since nightly-2024-08-30: https://github.com/rust-lang/rust/pull/128192 if !version.probe(82, 2024, 8, 29) || needs_target_feature_fallback(&version, None) { // FEAT_LSE2 doesn't imply FEAT_LSE. FEAT_LSE128 implies FEAT_LSE but not FEAT_LSE2. // AArch64 macOS always supports FEAT_LSE and FEAT_LSE2 because M1 is Armv8.4 with all features of Armv8.5 except FEAT_BTI: // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/AArch64/AArch64Processors.td#L1230 // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/AArch64/AArch64Processors.td#L891 // Script to get builtin targets that support FEAT_LSE/FEAT_LSE2 by default: // $ (for target in $(rustc -Z unstable-options --print all-target-specs-json | jq -r '. | to_entries[] | if .value.arch == "aarch64" or .value.arch == "arm64ec" then .key else empty end'); do rustc --print cfg --target "${target}" | grep -Fq '"lse"' && printf '%s\n' "${target}"; done) // $ (for target in $(rustc -Z unstable-options --print all-target-specs-json | jq -r '. | to_entries[] | if .value.arch == "aarch64" or .value.arch == "arm64ec" then .key else empty end'); do rustc --print cfg --target "${target}" | grep -Fq '"lse2"' && printf '%s\n' "${target}"; done) let is_macos = target_os == "macos"; let mut lse = is_macos; target_feature_fallback("lse2", is_macos); lse |= target_feature_fallback("lse128", false); target_feature_fallback("rcpc3", false); // aarch64_target_feature stabilized in Rust 1.61. if needs_target_feature_fallback(&version, Some(61)) { target_feature_fallback("lse", lse); } } // As of Apple M1/M1 Pro, on Apple hardware, CAS-loop-based RMW is much slower than // LL/SC-loop-based RMW: https://github.com/taiki-e/portable-atomic/pull/89 let is_apple = env::var("CARGO_CFG_TARGET_VENDOR").unwrap_or_default() == "apple"; if is_apple || target_cpu().map_or(false, |cpu| cpu.starts_with("apple-")) { println!("cargo:rustc-cfg=portable_atomic_ll_sc_rmw"); } } "arm" => { // For non-Linux/Android pre-v6 Arm (tier 3) with unsafe_assume_single_core enabled. // feature(isa_attribute) stabilized in Rust 1.67 (nightly-2022-11-06): https://github.com/rust-lang/rust/pull/102458 if version.nightly && !version.probe(67, 2022, 11, 5) { println!("cargo:rustc-cfg=portable_atomic_unstable_isa_attribute"); } if needs_target_feature_fallback(&version, None) { // #[cfg(target_feature = "v7")] and others don't work on stable. // armv7-unknown-linux-gnueabihf // ^^ let mut subarch = strip_prefix(target, "arm").or_else(|| strip_prefix(target, "thumb")).unwrap(); subarch = strip_prefix(subarch, "eb").unwrap_or(subarch); // ignore endianness subarch = subarch.split('-').next().unwrap(); // ignore vender/os/env subarch = subarch.split('.').next().unwrap(); // ignore .base/.main suffix let mut known = true; // See https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/build.rs for details let mut mclass = false; match subarch { "v7" | "v7a" | "v7neon" | "v7s" | "v7k" | "v8" | "v8a" | "v9" | "v9a" => {} // aclass "v7r" | "v8r" | "v9r" => {} // rclass "v6m" | "v7em" | "v7m" | "v8m" => mclass = true, // arm-linux-androideabi is v5te // https://github.com/rust-lang/rust/blob/1.84.0/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs#L18 _ if target == "arm-linux-androideabi" => subarch = "v5te", // armeb-unknown-linux-gnueabi is v8 & aclass // https://github.com/rust-lang/rust/blob/1.84.0/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs#L18 _ if target == "armeb-unknown-linux-gnueabi" => subarch = "v8", // Legacy Arm architectures (pre-v7 except v6m) don't have *class target feature. "" => subarch = "v6", "v4t" | "v5te" | "v6" | "v6k" => {} _ => { known = false; if env::var_os("PORTABLE_ATOMIC_DENY_WARNINGS").is_some() { panic!("unrecognized Arm subarch: {}", target) } println!( "cargo:warning={}: unrecognized Arm subarch: {}", env!("CARGO_PKG_NAME"), target ); } } let v6 = known && (subarch.starts_with("v6") || subarch.starts_with("v7") || subarch.starts_with("v8") || subarch.starts_with("v9")); target_feature_fallback("v6", v6); target_feature_fallback("mclass", mclass); } } "riscv32" | "riscv64" => { // zabha and zacas imply zaamo in GCC, LLVM 20+, and Rust, but do not in LLVM 19. // However, enabling them without zaamo or a is not allowed in LLVM 19, so we can assume // zaamo is available when zabha is enabled). // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/RISCV/RISCVFeatures.td#L233-L247 // https://github.com/llvm/llvm-project/commit/956361ca080a689a96b6552d28681aaf0ad2f494 // https://github.com/gcc-mirror/gcc/blob/08693e29ec186fd7941d0b73d4d466388971fe2f/gcc/config/riscv/arch-canonicalize#L45-L46 // https://github.com/rust-lang/rust/pull/130877 let mut zaamo = false; // As of rustc 1.84, target_feature "zacas" is not available on rustc side: // https://github.com/rust-lang/rust/blob/1.84.0/compiler/rustc_target/src/target_features.rs#L425 // amocas.{w,d,q} (and amocas.{b,h} if zabha is also available) // available as experimental since LLVM 17 https://github.com/llvm/llvm-project/commit/29f630a1ddcbb03caa31b5002f0cbc105ff3a869 // available non-experimental since LLVM 20 https://github.com/llvm/llvm-project/commit/614aeda93b2225c6eb42b00ba189ba7ca2585c60 zaamo |= target_feature_fallback("zacas", false); // target_feature "zaamo"/"zabha" is unstable and available on rustc side since nightly-2024-10-02: https://github.com/rust-lang/rust/pull/130877 if !version.probe(83, 2024, 10, 1) || needs_target_feature_fallback(&version, None) { if version.llvm >= 19 { // amo*.{b,h} // available since LLVM 19 https://github.com/llvm/llvm-project/commit/89f87c387627150d342722b79c78cea2311cddf7 / https://github.com/llvm/llvm-project/commit/6b7444964a8d028989beee554a1f5c61d16a1cac zaamo |= target_feature_fallback("zabha", false); } // amo*.{w,d} target_feature_fallback("zaamo", zaamo); } } "powerpc64" => { // target_feature "quadword-atomics" is unstable and available on rustc side since nightly-2024-09-28: https://github.com/rust-lang/rust/pull/130873 if !version.probe(83, 2024, 9, 27) || needs_target_feature_fallback(&version, None) { let mut pwr8_features = false; if let Some(cpu) = target_cpu() { if let Some(mut cpu_version) = strip_prefix(&cpu, "pwr") { cpu_version = strip_suffix(cpu_version, "x").unwrap_or(cpu_version); // for pwr5x and pwr6x if let Ok(cpu_version) = cpu_version.parse::() { pwr8_features = cpu_version >= 8; } } else { // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/PowerPC/PPC.td#L714 // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/PowerPC/PPC.td#L483 // On the minimum external LLVM version of the oldest rustc version which we can use asm_experimental_arch // on this target (see CI config for more), "future" is based on pwr10 features. // https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/llvm/lib/Target/PowerPC/PPC.td#L370 pwr8_features = cpu == "future" || cpu == "ppc64le"; } } else { // powerpc64le is pwr8 by default https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/PowerPC/PPC.td#L714 // See also https://github.com/rust-lang/rust/issues/59932 pwr8_features = env::var("CARGO_CFG_TARGET_ENDIAN") .expect("CARGO_CFG_TARGET_ENDIAN not set") == "little"; } // power8 features: https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/PowerPC/PPC.td#L409 // lqarx and stqcx. target_feature_fallback("quadword-atomics", pwr8_features); } } "s390x" => { let mut arch9_features = false; // z196+ let mut arch13_features = false; // z15+ if let Some(cpu) = target_cpu() { // LLVM and GCC recognize the same names: // https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/SystemZ/SystemZProcessors.td // https://github.com/gcc-mirror/gcc/blob/releases/gcc-14.2.0/gcc/config/s390/s390.opt#L58-L125 if let Some(arch_version) = strip_prefix(&cpu, "arch") { if let Ok(arch_version) = arch_version.parse::() { arch9_features = arch_version >= 9; arch13_features = arch_version >= 13; } } else { match &*cpu { "z196" | "zEC12" | "z13" | "z14" => arch9_features = true, "z15" | "z16" => { arch9_features = true; arch13_features = true; } _ => {} } } } // As of rustc 1.84, target_feature "fast-serialization"/"load-store-on-cond"/"distinct-ops"/"miscellaneous-extensions-3" is not available on rustc side: // https://github.com/rust-lang/rust/blob/1.84.0/compiler/rustc_target/src/target_features.rs#L547 // arch9 features: https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/SystemZ/SystemZFeatures.td#L103 // bcr 14,0 target_feature_fallback("fast-serialization", arch9_features); // {l,st}oc{,g}{,r} target_feature_fallback("load-store-on-cond", arch9_features); // {al,sl,n,o,x}{,g}rk target_feature_fallback("distinct-ops", arch9_features); // arch13 features: https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/SystemZ/SystemZFeatures.td#L301 // nand (nnr{,g}k), select (sel{,g}r), etc. target_feature_fallback("miscellaneous-extensions-3", arch13_features); } _ => {} } } // HACK: Currently, it seems that the only way to handle unstable target // features on the stable is to parse the `-C target-feature` in RUSTFLAGS. // // - #[cfg(target_feature = "unstable_target_feature")] doesn't work on stable. // - CARGO_CFG_TARGET_FEATURE excludes unstable target features on stable. // // As mentioned in the [RFC2045], unstable target features are also passed to LLVM // (e.g., https://godbolt.org/z/4rr7rMcfG), so this hack works properly on stable. // // [RFC2045]: https://rust-lang.github.io/rfcs/2045-target-feature.html#backend-compilation-options fn needs_target_feature_fallback(version: &Version, stable: Option) -> bool { match stable { // In these cases, cfg(target_feature = "...") would work, so skip emitting our own fallback target_feature cfg. _ if version.nightly => false, Some(stabilized) if version.minor >= stabilized => false, _ => true, } } fn target_feature_fallback(name: &str, mut has_target_feature: bool) -> bool { if let Some(rustflags) = env::var_os("CARGO_ENCODED_RUSTFLAGS") { for mut flag in rustflags.to_string_lossy().split('\x1f') { flag = strip_prefix(flag, "-C").unwrap_or(flag); if let Some(flag) = strip_prefix(flag, "target-feature=") { for s in flag.split(',') { // TODO: Handles cases where a specific target feature // implicitly enables another target feature. match (s.as_bytes().first(), s.as_bytes().get(1..)) { (Some(b'+'), Some(f)) if f == name.as_bytes() => has_target_feature = true, (Some(b'-'), Some(f)) if f == name.as_bytes() => has_target_feature = false, _ => {} } } } } } if has_target_feature { println!("cargo:rustc-cfg=portable_atomic_target_feature=\"{}\"", name); } has_target_feature } fn target_cpu() -> Option { let rustflags = env::var_os("CARGO_ENCODED_RUSTFLAGS")?; let rustflags = rustflags.to_string_lossy(); let mut cpu = None; for mut flag in rustflags.split('\x1f') { flag = strip_prefix(flag, "-C").unwrap_or(flag); if let Some(flag) = strip_prefix(flag, "target-cpu=") { cpu = Some(flag); } } cpu.map(str::to_owned) } fn is_allowed_feature(name: &str) -> bool { // https://github.com/dtolnay/thiserror/pull/248 if env::var_os("RUSTC_STAGE").is_some() { return false; } // allowed by default let mut allowed = true; if let Some(rustflags) = env::var_os("CARGO_ENCODED_RUSTFLAGS") { for mut flag in rustflags.to_string_lossy().split('\x1f') { flag = strip_prefix(flag, "-Z").unwrap_or(flag); if let Some(flag) = strip_prefix(flag, "allow-features=") { // If it is specified multiple times, the last value will be preferred. allowed = flag.split(',').any(|allowed| allowed == name); } } } allowed } // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.14/build-common.rs. // // The target triplets have the form of 'arch-vendor-system'. // // When building for Linux (e.g. the 'system' part is // 'linux-something'), replace the vendor with 'unknown' // so that mapping to rust standard targets happens correctly. fn convert_custom_linux_target(target: &str) -> String { let mut parts: Vec<&str> = target.split('-').collect(); let system = parts.get(2); if system == Some(&"linux") { parts[1] = "unknown"; } parts.join("-") } // str::strip_prefix requires Rust 1.45 #[must_use] fn strip_prefix<'a>(s: &'a str, pat: &str) -> Option<&'a str> { if s.starts_with(pat) { Some(&s[pat.len()..]) } else { None } } // str::strip_suffix requires Rust 1.45 #[must_use] fn strip_suffix<'a>(s: &'a str, pat: &str) -> Option<&'a str> { if s.ends_with(pat) { Some(&s[..s.len() - pat.len()]) } else { None } } portable-atomic/version.rs0000644000175000017500000001243315105742312015522 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT use std::{env, iter, process::Command, str}; pub(crate) fn rustc_version() -> Option { let rustc = env::var_os("RUSTC")?; let rustc_wrapper = if env::var_os("CARGO_ENCODED_RUSTFLAGS").is_some() { env::var_os("RUSTC_WRAPPER").filter(|v| !v.is_empty()) } else { // Cargo sets environment variables for wrappers correctly only since https://github.com/rust-lang/cargo/pull/9601. None }; // Do not apply RUSTC_WORKSPACE_WRAPPER: https://github.com/cuviper/autocfg/issues/58#issuecomment-2067625980 let mut rustc = rustc_wrapper.into_iter().chain(iter::once(rustc)); let mut cmd = Command::new(rustc.next().unwrap()); cmd.args(rustc); // Use verbose version output because the packagers add extra strings to the normal version output. // Do not use long flags (--version --verbose) because clippy-deriver doesn't handle them properly. // -vV is also matched with that cargo internally uses: https://github.com/rust-lang/cargo/blob/0.80.0/src/cargo/util/rustc.rs#L65 let output = cmd.arg("-vV").output().ok()?; let verbose_version = str::from_utf8(&output.stdout).ok()?; Version::parse(verbose_version) } #[cfg_attr(test, derive(Debug, PartialEq))] pub(crate) struct Version { pub(crate) minor: u32, pub(crate) nightly: bool, commit_date: Date, pub(crate) llvm: u32, } impl Version { // The known latest stable version. If we unable to determine // the rustc version, we assume this is the current version. // It is no problem if this is older than the actual latest stable. // LLVM version is assumed to be the minimum external LLVM version: // https://github.com/rust-lang/rust/blob/1.85.0/src/bootstrap/src/core/build_steps/llvm.rs#L618 pub(crate) const LATEST: Self = Self::stable(85, 18); pub(crate) const fn stable(rustc_minor: u32, llvm_major: u32) -> Self { Self { minor: rustc_minor, nightly: false, commit_date: Date::UNKNOWN, llvm: llvm_major } } pub(crate) fn probe(&self, minor: u32, year: u16, month: u8, day: u8) -> bool { if self.nightly { self.minor > minor || self.minor == minor && self.commit_date >= Date::new(year, month, day) } else { self.minor >= minor } } #[cfg(test)] pub(crate) fn commit_date(&self) -> &Date { &self.commit_date } pub(crate) fn parse(verbose_version: &str) -> Option { let mut release = verbose_version .lines() .find(|line| line.starts_with("release: ")) .map(|line| &line["release: ".len()..])? .splitn(2, '-'); let version = release.next().unwrap(); let channel = release.next().unwrap_or_default(); let mut digits = version.splitn(3, '.'); let major = digits.next()?; if major != "1" { return None; } let minor = digits.next()?.parse::().ok()?; let _patch = digits.next().unwrap_or("0").parse::().ok()?; let nightly = match env::var_os("RUSTC_BOOTSTRAP") { // When -1 is passed rustc works like stable, e.g., cfg(target_feature = "unstable_target_feature") will never be set. https://github.com/rust-lang/rust/pull/132993 Some(ref v) if v == "-1" => false, _ => channel == "nightly" || channel == "dev", }; // Note that rustc 1.49-1.50 (and 1.13 or older) don't print LLVM version. let llvm_major = (|| { let version = verbose_version .lines() .find(|line| line.starts_with("LLVM version: ")) .map(|line| &line["LLVM version: ".len()..])?; let mut digits = version.splitn(3, '.'); let major = digits.next()?.parse::().ok()?; let _minor = digits.next()?.parse::().ok()?; let _patch = digits.next().unwrap_or("0").parse::().ok()?; Some(major) })() .unwrap_or(0); // we don't refer commit date on stable/beta. if nightly { let commit_date = (|| { let mut commit_date = verbose_version .lines() .find(|line| line.starts_with("commit-date: ")) .map(|line| &line["commit-date: ".len()..])? .splitn(3, '-'); let year = commit_date.next()?.parse::().ok()?; let month = commit_date.next()?.parse::().ok()?; let day = commit_date.next()?.parse::().ok()?; if month > 12 || day > 31 { return None; } Some(Date::new(year, month, day)) })(); Some(Self { minor, nightly, commit_date: commit_date.unwrap_or(Date::UNKNOWN), llvm: llvm_major, }) } else { Some(Self::stable(minor, llvm_major)) } } } #[derive(PartialEq, PartialOrd)] #[cfg_attr(test, derive(Debug))] pub(crate) struct Date { pub(crate) year: u16, pub(crate) month: u8, pub(crate) day: u8, } impl Date { const UNKNOWN: Self = Self::new(0, 0, 0); const fn new(year: u16, month: u8, day: u8) -> Self { Self { year, month, day } } } portable-atomic/LICENSE-MIT0000644000175000017500000000177715105742312015134 0ustar bdrungbdrungPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. portable-atomic/Cargo.lock0000644000175000017500000001540015105742312015371 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "build-context" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86610cb1e9d45d65a31b574f9d69de003a76b6bb0b7d882396a5153fc547c935" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "critical-section" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-utils" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", "wasi", ] [[package]] name = "libc" version = "0.2.163" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fdaeca4cf44ed4ac623e86ef41f056e848dbeab7ec043ecb7326ba300b36fd0" [[package]] name = "paste" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "portable-atomic" version = "1.11.0" dependencies = [ "build-context", "critical-section", "crossbeam-utils", "fastrand", "libc", "paste", "quickcheck", "serde", "sptr", "static_assertions", "windows-sys", ] [[package]] name = "proc-macro2" version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quickcheck" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ "rand", ] [[package]] name = "quote" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] name = "serde" version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "sptr" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "unicode-ident" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" portable-atomic/Cargo.toml0000644000175000017500000001201415105742312015412 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.34" name = "portable-atomic" version = "1.11.0" build = "build.rs" exclude = [ "/.*", "/tools", "/target-specs", "/DEVELOPMENT.md", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = """ Portable atomic types including support for 128-bit atomics, atomic float, etc. """ readme = "README.md" keywords = ["atomic"] categories = [ "concurrency", "embedded", "hardware-support", "no-std", "no-std::no-alloc", ] license = "Apache-2.0 OR MIT" repository = "https://github.com/taiki-e/portable-atomic" [package.metadata.cargo_check_external_types] allowed_external_types = ["serde::*"] [package.metadata.docs.rs] features = [ "float", "std", "serde", "critical-section", ] rustdoc-args = [ "--cfg", "portable_atomic_unstable_f16", "--cfg", "portable_atomic_unstable_f128", ] targets = ["x86_64-unknown-linux-gnu"] [features] default = ["fallback"] disable-fiq = [] fallback = [] float = [] force-amo = [] require-cas = [] s-mode = [] std = [] unsafe-assume-single-core = [] [lib] name = "portable_atomic" path = "src/lib.rs" doc-scrape-examples = false [dependencies.critical-section] version = "1" optional = true [dependencies.serde] version = "1.0.60" optional = true default-features = false [dev-dependencies.build-context] version = "0.1" [dev-dependencies.crossbeam-utils] version = "=0.8.16" [dev-dependencies.fastrand] version = "2" [dev-dependencies.paste] version = "1" [dev-dependencies.quickcheck] version = "1" default-features = false [dev-dependencies.sptr] version = "0.3" [dev-dependencies.static_assertions] version = "1" [target."cfg(unix)".dev-dependencies.libc] version = "=0.2.163" [target."cfg(windows)".dev-dependencies.windows-sys] version = "0.59" features = [ "Win32_Foundation", "Win32_System_Threading", ] [lints.clippy] all = "warn" as_ptr_cast_mut = "warn" as_underscore = "warn" default_union_representation = "warn" inline_asm_x86_att_syntax = "warn" pedantic = "warn" trailing_empty_array = "warn" transmute_undefined_repr = "warn" undocumented_unsafe_blocks = "warn" unused_trait_names = "warn" [lints.clippy.bool_assert_comparison] level = "allow" priority = 1 [lints.clippy.borrow_as_ptr] level = "allow" priority = 1 [lints.clippy.cast_lossless] level = "allow" priority = 1 [lints.clippy.declare_interior_mutable_const] level = "allow" priority = 1 [lints.clippy.doc_markdown] level = "allow" priority = 1 [lints.clippy.float_cmp] level = "allow" priority = 1 [lints.clippy.incompatible_msrv] level = "allow" priority = 1 [lints.clippy.lint_groups_priority] level = "allow" priority = 1 [lints.clippy.manual_assert] level = "allow" priority = 1 [lints.clippy.manual_range_contains] level = "allow" priority = 1 [lints.clippy.missing_errors_doc] level = "allow" priority = 1 [lints.clippy.module_name_repetitions] level = "allow" priority = 1 [lints.clippy.naive_bytecount] level = "allow" priority = 1 [lints.clippy.nonminimal_bool] level = "allow" priority = 1 [lints.clippy.range_plus_one] level = "allow" priority = 1 [lints.clippy.similar_names] level = "allow" priority = 1 [lints.clippy.single_match] level = "allow" priority = 1 [lints.clippy.single_match_else] level = "allow" priority = 1 [lints.clippy.struct_excessive_bools] level = "allow" priority = 1 [lints.clippy.struct_field_names] level = "allow" priority = 1 [lints.clippy.too_many_arguments] level = "allow" priority = 1 [lints.clippy.too_many_lines] level = "allow" priority = 1 [lints.clippy.type_complexity] level = "allow" priority = 1 [lints.clippy.unreadable_literal] level = "allow" priority = 1 [lints.rust] deprecated_safe = "warn" improper_ctypes = "warn" improper_ctypes_definitions = "warn" non_ascii_idents = "warn" rust_2018_idioms = "warn" single_use_lifetimes = "warn" unnameable_types = "warn" unreachable_pub = "warn" [lints.rust.unexpected_cfgs] level = "warn" priority = 0 check-cfg = [ 'cfg(target_arch,values("xtensa"))', 'cfg(target_arch,values("amdgpu"))', 'cfg(target_os,values("psx"))', 'cfg(target_env,values("psx"))', 'cfg(target_feature,values("lse2","lse128","rcpc3"))', 'cfg(target_feature,values("quadword-atomics"))', 'cfg(target_feature,values("zaamo","zabha"))', 'cfg(target_pointer_width,values("128"))', "cfg(portable_atomic_test_outline_atomics_detect_false,qemu,valgrind)", "cfg(portable_atomic_no_outline_atomics,portable_atomic_outline_atomics,portable_atomic_unstable_f16,portable_atomic_unstable_f128)", "cfg(portable_atomic_unstable_coerce_unsized)", ] portable-atomic/.cargo-checksum.json0000664000175000017500000000013115105742312017325 0ustar bdrungbdrung{"files":{},"package":"350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"}portable-atomic/LICENSE-APACHE0000644000175000017500000002367615105742312015426 0ustar bdrungbdrung Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS portable-atomic/README.md0000644000175000017500000003507115105742312014751 0ustar bdrungbdrung# portable-atomic [![crates.io](https://img.shields.io/crates/v/portable-atomic?style=flat-square&logo=rust)](https://crates.io/crates/portable-atomic) [![docs.rs](https://img.shields.io/badge/docs.rs-portable--atomic-blue?style=flat-square&logo=docs.rs)](https://docs.rs/portable-atomic) [![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue?style=flat-square)](#license) [![msrv](https://img.shields.io/badge/msrv-1.34-blue?style=flat-square&logo=rust)](https://www.rust-lang.org) [![github actions](https://img.shields.io/github/actions/workflow/status/taiki-e/portable-atomic/ci.yml?branch=main&style=flat-square&logo=github)](https://github.com/taiki-e/portable-atomic/actions) Portable atomic types including support for 128-bit atomics, atomic float, etc. - Provide all atomic integer types (`Atomic{I,U}{8,16,32,64}`) for all targets that can use atomic CAS. (i.e., all targets that can use `std`, and most no-std targets) - Provide `AtomicI128` and `AtomicU128`. - Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float)) - Provide `AtomicF16` and `AtomicF128` for [unstable `f16` and `f128`](https://github.com/rust-lang/rust/issues/116909). ([optional, requires the `float` feature and unstable cfgs](#optional-features-float)) - Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR) - Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 Arm, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise) - Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108). - Make features that require newer compilers, such as [`fetch_{max,min}`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [`fetch_update`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_update), [`as_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.as_ptr), [`from_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.from_ptr), [`AtomicBool::fetch_not`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.fetch_not) and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+. - Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc. portable-atomic version of `std::sync::Arc` is provided by the [portable-atomic-util](https://github.com/taiki-e/portable-atomic/tree/HEAD/portable-atomic-util) crate. ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] portable-atomic = "1" ``` The default features are mainly for users who use atomics larger than the pointer width. If you don't need them, disabling the default features may reduce code size and compile time slightly. ```toml [dependencies] portable-atomic = { version = "1", default-features = false } ``` If your crate supports no-std environment and requires atomic CAS, enabling the `require-cas` feature will allow the `portable-atomic` to display a [helpful error message](https://github.com/taiki-e/portable-atomic/pull/100) to users on targets requiring additional action on the user side to provide atomic CAS. ```toml [dependencies] portable-atomic = { version = "1.3", default-features = false, features = ["require-cas"] } ``` ## 128-bit atomics support Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), Arm64EC (Rust 1.84+), s390x (Rust 1.84+), and powerpc64 (nightly only), otherwise the fallback implementation is used. On x86_64, even if `cmpxchg16b` is not available at compile-time (note: `cmpxchg16b` target feature is enabled by default only on Apple and Windows (except Windows 7) targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg. They are usually implemented using inline assembly, and when using Miri or ThreadSanitizer that do not support inline assembly, core intrinsics are used instead of inline assembly if possible. See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md) for details. ## Optional features - **`fallback`** *(enabled by default)*
Enable fallback implementations. Disabling this allows only atomic types for which the platform natively supports atomic operations. - **`float`**
Provide `AtomicF{32,64}`. - When unstable `--cfg portable_atomic_unstable_f16` is also enabled, `AtomicF16` for [unstable `f16`](https://github.com/rust-lang/rust/issues/116909) is also provided. - When unstable `--cfg portable_atomic_unstable_f128` is also enabled, `AtomicF128` for [unstable `f128`](https://github.com/rust-lang/rust/issues/116909) is also provided. Note: - Most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. (AArch64 with FEAT_LSFE and GPU targets have atomic instructions for float, [so we plan to use these instructions for them in the future.](https://github.com/taiki-e/portable-atomic/issues/34)) - Unstable cfgs are outside of the normal semver guarantees and minor or patch versions of portable-atomic may make breaking changes to them at any time. - **`std`**
Use `std`. - **`require-cas`**
Emit compile error if atomic CAS is not available. See [Usage](#usage) section and [#100](https://github.com/taiki-e/portable-atomic/pull/100) for more. - **`serde`**
Implement `serde::{Serialize,Deserialize}` for atomic types. Note: - The MSRV when this feature is enabled depends on the MSRV of [serde]. - **`critical-section`**
When this feature is enabled, this crate uses [critical-section] to provide atomic CAS for targets where it is not natively available. When enabling it, you should provide a suitable critical section implementation for the current target, see the [critical-section] documentation for details on how to do so. `critical-section` support is useful to get atomic CAS when the [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) can't be used, such as multi-core targets, unprivileged code running under some RTOS, or environments where disabling interrupts needs extra care due to e.g. real-time requirements. Note that with the `critical-section` feature, critical sections are taken for all atomic operations, while with [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) some operations don't require disabling interrupts (loads and stores, but additionally on MSP430 `add`, `sub`, `and`, `or`, `xor`, `not`). Therefore, for better performance, if all the `critical-section` implementation for your target does is disable interrupts, prefer using `unsafe-assume-single-core` feature instead. Note: - The MSRV when this feature is enabled depends on the MSRV of [critical-section]. - It is usually *not* recommended to always enable this feature in dependencies of the library. Enabling this feature will prevent the end user from having the chance to take advantage of other (potentially) efficient implementations ([Implementations provided by `unsafe-assume-single-core` feature, default implementations on MSP430 and AVR](#optional-features-unsafe-assume-single-core), implementation proposed in [#60], etc. Other systems may also be supported in the future). The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where other implementations are known not to work.) As an example, the end-user's `Cargo.toml` that uses a crate that provides a critical-section implementation and a crate that depends on portable-atomic as an option would be expected to look like this: ```toml [dependencies] portable-atomic = { version = "1", default-features = false, features = ["critical-section"] } crate-provides-critical-section-impl = "..." crate-uses-portable-atomic-as-feature = { version = "...", features = ["portable-atomic"] } ``` - **`unsafe-assume-single-core`**
Assume that the target is single-core. When this feature is enabled, this crate provides atomic CAS for targets where atomic CAS is not available in the standard library by disabling interrupts. This feature is `unsafe`, and note the following safety requirements: - Enabling this feature for multi-core systems is always **unsound**. - This uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode. Enabling this feature in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent. The following are known cases: - On pre-v6 Arm, this disables only IRQs by default. For many systems (e.g., GBA) this is enough. If the system need to disable both IRQs and FIQs, you need to enable the `disable-fiq` feature together. - On RISC-V without A-extension, this generates code for machine-mode (M-mode) by default. If you enable the `s-mode` together, this generates code for supervisor-mode (S-mode). In particular, `qemu-system-riscv*` uses [OpenSBI](https://github.com/riscv-software-src/opensbi) as the default firmware. See also the [`interrupt` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/interrupt/README.md). Consider using the [`critical-section` feature](#optional-features-critical-section) for systems that cannot use this feature. It is **very strongly discouraged** to enable this feature in libraries that depend on `portable-atomic`. The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where it is guaranteed to always be sound, for example in a hardware abstraction layer targeting a single-core chip.) Armv6-M (thumbv6m), pre-v6 Arm (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa are currently supported. Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this feature. Enabling this feature for targets that have atomic CAS will result in a compile error. Feel free to submit an issue if your target is not supported yet. ## Optional cfg One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags): ```toml # .cargo/config.toml [target.] rustflags = ["--cfg", "portable_atomic_no_outline_atomics"] ``` Or set environment variable: ```sh RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... ``` - **`--cfg portable_atomic_unsafe_assume_single_core`**
Since 1.4.0, this cfg is an alias of [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core). Originally, we were providing these as cfgs instead of features, but based on a strong request from the embedded ecosystem, we have agreed to provide them as features as well. See [#94](https://github.com/taiki-e/portable-atomic/pull/94) for more. - **`--cfg portable_atomic_no_outline_atomics`**
Disable dynamic dispatching by run-time CPU feature detection. If dynamic dispatching by run-time CPU feature detection is enabled, it allows maintaining support for older CPUs while using features that are not supported on older CPUs, such as CMPXCHG16B (x86_64) and FEAT_LSE/FEAT_LSE2 (AArch64). Note: - Dynamic detection is currently only supported in x86_64, AArch64, Arm, RISC-V, Arm64EC, and powerpc64, otherwise it works the same as when this cfg is set. - If the required target features are enabled at compile-time, the atomic operations are inlined. - This is compatible with no-std (as with all features except `std`). - On some targets, run-time detection is disabled by default mainly for compatibility with incomplete build environments or support for it is experimental, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.) - Some AArch64 targets enable LLVM's `outline-atomics` target feature by default, so if you set this cfg, you may want to disable that as well. (portable-atomic's outline-atomics does not depend on the compiler-rt symbols, so even if you need to disable LLVM's outline-atomics, you may not need to disable portable-atomic's outline-atomics.) See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md). ## Related Projects - [atomic-maybe-uninit]: Atomic operations on potentially uninitialized integers. - [atomic-memcpy]: Byte-wise atomic memcpy. [#60]: https://github.com/taiki-e/portable-atomic/issues/60 [atomic-maybe-uninit]: https://github.com/taiki-e/atomic-maybe-uninit [atomic-memcpy]: https://github.com/taiki-e/atomic-memcpy [critical-section]: https://github.com/rust-embedded/critical-section [rust-lang/rust#100650]: https://github.com/rust-lang/rust/issues/100650 [serde]: https://github.com/serde-rs/serde ## License Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. portable-atomic/CHANGELOG.md0000644000175000017500000010660315105742312015303 0ustar bdrungbdrung# Changelog All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org). Releases may yanked if there is a security bug, a soundness bug, or a regression. ## [Unreleased] ## [1.11.0] - 2025-02-24 - Work around [nightly-2025-02-24 rustc regression causing "cannot use value of type `*mut T` for inline assembly" error](https://github.com/rust-lang/rust/issues/137512) on RISC-V without A extension, MSP430, and pre-v6 no-std Arm targets. ([eeb0235](https://github.com/taiki-e/portable-atomic/commit/eeb0235b9fda4c28a56ee5a9ffe0d7fb884a50ab)) - Support `AtomicF16` and `AtomicF128` for [unstable `f16` and `f128`](https://github.com/rust-lang/rust/issues/116909) under unstable cfgs. ([582a915](https://github.com/taiki-e/portable-atomic/commit/582a9156368d9a4e19be0c724d3635efde4d25a2)) - RISC-V Zacas extension support is no longer experimental. ([#206](https://github.com/taiki-e/portable-atomic/pull/206)) - Improve support of run-time detection and outline-atomics: - riscv: Enable run-time detection of Zacas extension by default on Linux/Android. ([#207](https://github.com/taiki-e/portable-atomic/pull/207)) - aarch64: Support run-time detection of FEAT_LRCPC3/FEAT_LSE128 on FreeBSD. ([6a5075d](https://github.com/taiki-e/portable-atomic/commit/6a5075d43543875cf38d6114f2951047e2e64f1a)) - powerpc64: Support run-time detection of quadword-atomics on AIX (currently disabled by default because detection support for AIX is experimental). ([#102](https://github.com/taiki-e/portable-atomic/pull/102)) ## [1.10.0] - 2024-11-23 - Update to stabilized [s390x](https://github.com/rust-lang/rust/pull/131258) and [Arm64EC](https://github.com/rust-lang/rust/pull/131781) inline assembly. ([97645c1](https://github.com/taiki-e/portable-atomic/commit/97645c1b2b938249f16eacb0fe696d4c7bb96754), [e1d1a97](https://github.com/taiki-e/portable-atomic/commit/e1d1a97cd1ab4bd04b45962c44ca1e9f0f9e1456)) - Make `get_mut` `const fn` on Rust 1.83+. ([0dea68c](https://github.com/taiki-e/portable-atomic/commit/0dea68c26e2bba3a83a849e2f137a2da445fc014)) - Make `from_ptr` `const fn` on Rust 1.83+. (align to the [std atomic change in Rust 1.84](https://github.com/rust-lang/rust/pull/131717)) ([50532d8](https://github.com/taiki-e/portable-atomic/commit/50532d8ce92408976307431a2f1a94000c630b23)) - Various optimizations: - RISC-V without A-extension: Optimize 16-bit fetch_not when Zabha enabled. ([a487a09](https://github.com/taiki-e/portable-atomic/commit/a487a094ab99fdf8ef3413b943c9c154a352d8c4)) - s390x: Optimize 128-bit CAS/RMW. ([fba028d](https://github.com/taiki-e/portable-atomic/commit/fba028d7618e47b3de5b352c1789ea52f45298b4), [33ab2c1](https://github.com/taiki-e/portable-atomic/commit/33ab2c19719b29c0a30df8d011d0cd4003495dc8)) - PowerPC64: Optimize 128-bit Acquire/AcqRel/SeqCst CAS/RMW and 128-bit CAS with Relaxed failure ordering. ([33ab2c1](https://github.com/taiki-e/portable-atomic/commit/33ab2c19719b29c0a30df8d011d0cd4003495dc8)) - AVR: Optimize 8-bit load/store. ([33ab2c1](https://github.com/taiki-e/portable-atomic/commit/33ab2c19719b29c0a30df8d011d0cd4003495dc8)) - Improve support of run-time detection and outline-atomics: - Enable run-time detection by default on powerpc64 and aarch64 linux-uclibc. ([#193](https://github.com/taiki-e/portable-atomic/pull/193)) - Improve run-time detection of powerpc64 quadword-atomics. ([1e3bfda](https://github.com/taiki-e/portable-atomic/commit/1e3bfda29bf6eb06a359f24554f19fc080ae57eb)) - Improve run-time detection of Zhaoxin CPU. ([f283d2a](https://github.com/taiki-e/portable-atomic/commit/f283d2a1deb94e84676a2c1ee678439f507482db)) - Support RISC-V Zacas extension on pre-1.82 rustc. ([#194](https://github.com/taiki-e/portable-atomic/pull/194)) - Improve compile-time detection of RISC-V Zaamo/Zabha extensions. ([673137a](https://github.com/taiki-e/portable-atomic/commit/673137afb87b731ed19a1b0717059468712fad1d)) - Respect [`RUSTC_BOOTSTRAP=-1` recently added in nightly](https://github.com/rust-lang/rust/pull/132993) in rustc version detection. ([5b2847a](https://github.com/taiki-e/portable-atomic/commit/5b2847a8b99aa2a57a6c80f5a47327b2764f08cc)) ## [1.9.0] - 2024-09-28 - RISC-V without A-extension: Support RMW when Zaamo extension enabled (even when `unsafe-assume-single-core` disabled). ([#185](https://github.com/taiki-e/portable-atomic/pull/185), [9983a8b](https://github.com/taiki-e/portable-atomic/commit/9983a8b9ad66efe4303b95678014369a56839aef)) See "operations don't require disabling interrupts" list in [`interrupt` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/interrupt/README.md) for the operations provided. - Support run-time detection of RISC-V Zacas extension (currently disabled by default). ([#183](https://github.com/taiki-e/portable-atomic/pull/183)) - Support 128-bit atomics on Arm64EC (currently nightly-only) ([#184](https://github.com/taiki-e/portable-atomic/pull/184)) - Improve compile-time detection of powerpc64 quadword-atomics. ([3eb8507](https://github.com/taiki-e/portable-atomic/commit/3eb8507f91c1ab382d9f455b2311a8664a4c33ff)) ## [1.8.0] - 2024-09-20 - Improve diagnostics when method that requires CAS is unavailable. ([#181](https://github.com/taiki-e/portable-atomic/pull/181)) Before: ```text error[E0599]: no method named `compare_exchange` found for struct `portable_atomic::AtomicUsize` in the current scope --> src/race.rs:60:24 | 60 | self.inner.compare_exchange(0, value.get(), Ordering::AcqRel, Ordering::Acquire); | ^^^^^^^^^^^^^^^^ method not found in `AtomicUsize` ``` After: ```text error[E0277]: `compare_exchange` requires atomic CAS but not available on this target by default --> src/race.rs:60:24 | 60 | self.inner.compare_exchange(0, value.get(), Ordering::AcqRel, Ordering::Acquire); | ^^^^^^^^^^^^^^^^ this associated function is not available on this target by default | = help: the trait `HasCompareExchange` is not implemented for `&portable_atomic::AtomicUsize` = note: consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features = note: see for more. ``` - Improve compile error messages for some other cases ([19716ac](https://github.com/taiki-e/portable-atomic/commit/19716ac1d3b6082a8cb838af532ccab871041249), [61dcaaa](https://github.com/taiki-e/portable-atomic/commit/61dcaaa320cb347ab799c6c4f4480600692de2ad)) - Various improvements to RISC-V. - riscv64: Support 128-bit atomics when Zacas extension enabled. ([173](https://github.com/taiki-e/portable-atomic/pull/173)) This is currently marked as experimental because LLVM marking the corresponding target feature as experimental. - riscv32: Support 64-bit atomics when Zacas extension enabled. ([173](https://github.com/taiki-e/portable-atomic/pull/173)) This is currently marked as experimental because LLVM marking the corresponding target feature as experimental. - Improvements for RISC-V without A-extension: - Support zaamo target feature. When building for single-core RISC-V without A-extension, this is equivalent to force-amo feature ([8abba4b](https://github.com/taiki-e/portable-atomic/commit/8abba4b0ea920d23799c2d7b6985617e6392d176)) - Support zabha target feature. ([694364a](https://github.com/taiki-e/portable-atomic/commit/694364a179441f723e429516132436c46f5857b4)) - Strengthen SeqCst store to improve compatibility with code that uses atomic instruction mapping that differs from LLVM and GCC. ([5b10b15](https://github.com/taiki-e/portable-atomic/commit/5b10b1516e056b16b851e498a271f751152feed9)) - Improve support of run-time detection and outline-atomics: - aarch64: Support run-time detection of FEAT_LRCPC3/FEAT_LSE128 for load/store. ([#174](https://github.com/taiki-e/portable-atomic/pull/174)) - aarch64: Support run-time detection of FEAT_LSE2 on OpenBSD. ([4f8c735](https://github.com/taiki-e/portable-atomic/commit/4f8c7350fd80d005233d85191707e4329a5ef484)) - aarch64: Support run-time detection of FEAT_LSE/FEAT_LSE2 on illumos (currently disabled by default because illumos AArch64 port is experimental). ([#175](https://github.com/taiki-e/portable-atomic/pull/175)) - powerpc64: Support run-time detection on OpenBSD 7.6+ (currently disabled by default for compatibility with old versions). ([09a967b](https://github.com/taiki-e/portable-atomic/commit/09a967b59c217dc9ebb4d78ec114758ef9941fc8)) - Support AArch64 FEAT_LRCPC3/FEAT_LSE128 with pre-16 LLVM. ([#178](https://github.com/taiki-e/portable-atomic/pull/178)) - Improve compile-time detection of AArch64 FEAT_LSE2/FEAT_LRCPC3/FEAT_LSE128. ([10d47de](https://github.com/taiki-e/portable-atomic/commit/10d47def74b9c13fd864436d6118e902f118c028)) - Relax minimal version of `serde` (supported via optional feature) to 1.0.60. ## [1.7.0] - 2024-07-19 - Support run-time detection for cmpxchg16b on x86_64 on pre-1.69 rustc. ([#154](https://github.com/taiki-e/portable-atomic/pull/154)) - Make `into_inner` `const fn` on Rust 1.56+. (align to the [std atomic change in Rust 1.79](https://github.com/rust-lang/rust/pull/123522)) ([dee1f89](https://github.com/taiki-e/portable-atomic/commit/dee1f89739594271e4f5b5d3f122d2762fcbbd7d)) - Work around [rustc_codegen_gcc bug on x86_64](https://github.com/rust-lang/rustc_codegen_gcc/issues/485). ([d938f77](https://github.com/taiki-e/portable-atomic/commit/d938f77f3f2f353cbfb525ac23e63e880cd583df)) - Optimize x86_64 atomics. - Optimize 128-bit load/store on Zhaoxin CPU with AVX. ([86cee8f](https://github.com/taiki-e/portable-atomic/commit/86cee8fccf7deedb5b8cbcb3868ec2e43aca575f)) - Optimize 128-bit SeqCst store on Intel/AMD/Zhaoxin CPU with AVX. ([#156](https://github.com/taiki-e/portable-atomic/pull/156), [0483042](https://github.com/taiki-e/portable-atomic/commit/0483042671fad4ccd0bdb691424a967fc2a5cb8e)) - Remove needless test in CAS. ([573e025](https://github.com/taiki-e/portable-atomic/commit/573e02586f933a257c8e7383dcf64408b4708b85)) - Make rustc version detection robust for custom toolchains. ([f8ea85e](https://github.com/taiki-e/portable-atomic/commit/f8ea85e1aa46fa00bc865633fb40b05f8a0c823b)) - Respect `RUSTC_WRAPPER` in rustc version detection. - Our build script is now less likely to be [re-run unnecessarily](https://github.com/taiki-e/portable-atomic/issues/151) in versions where the cargo bug fix is available (cargo 1.79+). ([52c277b](https://github.com/taiki-e/portable-atomic/commit/52c277bc9a9a8031175aaed54987260da1750af4)) ## [1.6.0] - 2023-12-06 - Add `cfg_{has,no}_atomic_{8,16,32,64,128,ptr}` macros to enable code when the corresponding atomic implementation is available/unavailable. - Add `cfg_{has,no}_atomic_cas` macros to enable code when atomic CAS/RMW implementation is available/unavailable. - Improve support for RISC-V targets without atomic CAS. ## [1.5.1] - 2023-10-29 - Fix bug in `i{8,16}` `fetch_{or,xor}` on RISC-V without A-extension where `unsafe-assume-single-core` and `force-amo` are enabled. - Optimize `swap` for targets that do not have native atomic CAS instructions. ## [1.5.0] - 2023-10-23 **Note:** This release has been yanked due to a bug fixed in 1.5.1. - Add `from_ptr`. - Add `force-amo` feature (`portable_atomic_force_amo` cfg) for single-core RISC-V without A-extension. ([#124](https://github.com/taiki-e/portable-atomic/pull/124)) - Support run-time detection on AArch64 on pre-1.61 rustc. ([#98](https://github.com/taiki-e/portable-atomic/pull/98)) This also solves [a compatibility issue with rustc_codegen_cranelift](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1400). - Support run-time detection of FEAT_LSE2. ([#126](https://github.com/taiki-e/portable-atomic/pull/126)) - Support run-time detection of FEAT_LSE on AArch64 NetBSD. ([#66](https://github.com/taiki-e/portable-atomic/pull/66)) - Acknowledge ESP-IDF targets' 64-bit atomics are not lock-free. See [#122](https://github.com/taiki-e/portable-atomic/issues/122) for more. - Optimize 128-bit weak CAS on powerpc64. - Optimize interrupt disable on no-std pre-v6 Arm where `unsafe-assume-single-core` and `disable-fiq` are enabled. ([771c45d](https://github.com/taiki-e/portable-atomic/commit/771c45da2d2afc4f83df033dd4bdf3f976d14a74)) - Improve detection of Apple hardware. ([5c3a43b](https://github.com/taiki-e/portable-atomic/commit/5c3a43b53f1c4188f9dd597599633bc1a315bf44)) - Improve compatibility with the future version of Miri. ## [1.4.3] - 2023-08-25 - Optimize AArch64 128-bit atomic store/swap/fetch_and/fetch_or when the `lse128` target feature is enabled at compile-time. ([#68](https://github.com/taiki-e/portable-atomic/pull/68)) - Optimize AArch64 128-bit atomic load/store when the `rcpc3` target feature is enabled at compile-time. ([#68](https://github.com/taiki-e/portable-atomic/pull/68)) - Optimize inline assemblies on Arm, AArch64, and MSP430. ## [1.4.2] - 2023-07-27 - Optimize `AtomicBool` on RISC-V/LoongArch64. This is the same as [rust-lang/rust#114034](https://github.com/rust-lang/rust/pull/114034), but is available for all rustc versions. ## [1.4.1] - 2023-07-15 - Improve compatibility with the future version of Miri. ## [1.4.0] - 2023-07-11 - Allow using embedded-related cfgs as Cargo features. ([#94](https://github.com/taiki-e/portable-atomic/pull/94), thanks @Dirbaio) Originally, we were providing these as cfgs instead of features, but based on a strong request from the embedded ecosystem, we have agreed to provide them as features as well. See [#94](https://github.com/taiki-e/portable-atomic/pull/94) for more. cfgs are kept and can be used as aliases for features. - Acknowledge all x86_64 Apple targets support 128-bit atomics. Our code already recognizes this via `cfg(target_feature)`, so this only affects docs and users using pre-1.69 stable rustc. See also [rust-lang/rust#112150](https://github.com/rust-lang/rust/pull/112150). - Optimize 128-bit atomics on AArch64/s390x. ## [1.3.3] - 2023-05-31 - Fix build error on AArch64 ILP32 ABI targets (tier 3). - Optimize 128-bit atomics on s390x. ## [1.3.2] - 2023-05-09 - Fix bug in powerpc64/s390x 128-bit atomic RMWs on old nightly. - Optimize 128-bit atomics on powerpc64/s390x. ## [1.3.1] - 2023-05-07 - Documentation improvements. ## [1.3.0] - 2023-05-06 - Add `require-cas` feature. ([#100](https://github.com/taiki-e/portable-atomic/pull/100)) If your crate supports no-std environment and requires atomic CAS, enabling this feature will allow the `portable-atomic` to display helpful error messages to users on targets requiring additional action on the user side to provide atomic CAS. ```toml [dependencies] portable-atomic = { version = "1.3", default-features = false, features = ["require-cas"] } ``` See [#100](https://github.com/taiki-e/portable-atomic/pull/100) for more. - Support `portable_atomic_unsafe_assume_single_core` cfg on Xtensa targets without atomic CAS. ([#86](https://github.com/taiki-e/portable-atomic/pull/86)) - Fix bug in AArch64 128-bit SeqCst load when FEAT_LSE2 is enabled at compile-time. This is [the same bug that was fixed in the recently released GCC 13.1](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108891). LLVM also has the same bug, which had not yet been fixed when the patch was created; I will open a bug report if necessary after looking into the situation in LLVM. ([a29154b](https://github.com/taiki-e/portable-atomic/commit/a29154b21da270e90cb86f6865b591ab36eade7d)) - Fix compile error on `bpf{eb,el}-unknown-none` (tier 3) and `mipsel-sony-psx` (tier 3) when `critical-section` feature is disabled. - Various optimizations - Optimize x86_64 128-bit outline-atomics. This improves performance by up to 15% in concurrent RMW/store for cases where the `cmpxchg16b` target feature is not available at compile-time. ([40c4cd4](https://github.com/taiki-e/portable-atomic/commit/40c4cd4f682f1cb153f18d4d6a88795bafaf5667)) - Optimize x86_64 128-bit load that uses cmpxchg16b. ([40c4cd4](https://github.com/taiki-e/portable-atomic/commit/40c4cd4f682f1cb153f18d4d6a88795bafaf5667)) - Optimize AArch64 128-bit load that uses FEAT_LSE. ([40c4cd4](https://github.com/taiki-e/portable-atomic/commit/40c4cd4f682f1cb153f18d4d6a88795bafaf5667)) - Optimize pre-Armv6 Linux/Android 64-bit atomics. ([efacc89](https://github.com/taiki-e/portable-atomic/commit/efacc89c210d7a34ef5e879821112189da5d1901)) - Support outline-atomics for powerpc64 128-bit atomics. This is currently disabled by default, and can be enabled by `--cfg portable_atomic_outline_atomics`. ([#90](https://github.com/taiki-e/portable-atomic/pull/90)) - Optimize AArch64 outline-atomics on linux-musl. On linux-musl, outline-atomics is enabled by default only when dynamic linking is enabled. When static linking is enabled, this can be enabled by `--cfg portable_atomic_outline_atomics`. See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md#run-time-feature-detection) for more. ([8418235](https://github.com/taiki-e/portable-atomic/commit/84182354e4a149074e28bda4683d538e5fb617ce), [31d0862](https://github.com/taiki-e/portable-atomic/commit/31d08623d4e21af207ff2343f5553b9b5a030452)) ## [1.2.0] - 2023-03-25 - Make 64-bit atomics lock-free on Arm Linux/Android targets that do not have 64-bit atomics (e.g., armv5te-unknown-linux-gnueabi, arm-linux-androideabi, etc.) when the kernel version is 3.1 or later. ([#82](https://github.com/taiki-e/portable-atomic/pull/82)) - Fix AArch64 128-bit atomics performance regression on Apple hardware. ([#89](https://github.com/taiki-e/portable-atomic/pull/89)) - Optimize 128-bit atomics on AArch64, x86_64, powerpc64, and s390x. ## [1.1.0] - 2023-03-24 - Add `Atomic{I,U}*::bit_{set,clear,toggle}` and `AtomicPtr::bit_{set,clear,toggle}`. ([#72](https://github.com/taiki-e/portable-atomic/pull/72)) They correspond to x86's `lock bt{s,r,c}`, and the implementation calls them on x86/x86_64. - Add `AtomicU*::{fetch_neg,neg}` methods. Previously it was only available on `AtomicI*` and `AtomicF*`. - Add `as_ptr` method to all atomic types. ([#79](https://github.com/taiki-e/portable-atomic/pull/79)) - Make `AtomicF{32,64}::as_bits` `const fn` on Rust 1.58+. ([#79](https://github.com/taiki-e/portable-atomic/pull/79)) - Relax ordering in `Serialize` impl to reflect the [upstream change](https://github.com/serde-rs/serde/pull/2263). - Optimize x86_64 outline-atomics for 128-bit atomics. - Support outline-atomics for cmpxchg16b on Rust 1.69+ (i.e., on Rust 1.69+, x86_64 128-bit atomics is lock-free on all Intel chips and almost all AMD chips, even if cmpxchg16b is not available at compile-time.). Previously it was only nightly. ([#80](https://github.com/taiki-e/portable-atomic/pull/80)) - portable-atomic no longer enables outline-atomics on target where run-time CPU feature detection is not available. ([#80](https://github.com/taiki-e/portable-atomic/pull/80)) - Optimize AArch64 outline-atomics for 128-bit atomics. - Support more targets and improve performance. ([#63](https://github.com/taiki-e/portable-atomic/pull/63), [#64](https://github.com/taiki-e/portable-atomic/pull/64), [#67](https://github.com/taiki-e/portable-atomic/pull/67), [#69](https://github.com/taiki-e/portable-atomic/pull/69), [#75](https://github.com/taiki-e/portable-atomic/pull/75), [#76](https://github.com/taiki-e/portable-atomic/pull/76), [#77](https://github.com/taiki-e/portable-atomic/pull/77)) See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md#run-time-feature-detection) for a list of platforms that support outline-atomics. Most of these improvements have already been [submitted and accepted in rust-lang/stdarch](https://github.com/rust-lang/stdarch/pulls?q=is%3Apr+author%3Ataiki-e+std_detect) and will soon be available in `std::arch::is_aarch64_feature_detected`. - portable-atomic no longer enables outline-atomics on target where run-time CPU feature detection is not available. - Performance improvements. ([#70](https://github.com/taiki-e/portable-atomic/pull/70), [#81](https://github.com/taiki-e/portable-atomic/pull/81), [6c189ae](https://github.com/taiki-e/portable-atomic/commit/6c189ae1792ce0c08b4f56b6e6c256c223475ce2), [13c92b0](https://github.com/taiki-e/portable-atomic/commit/13c92b015a8e8646a4b885229157547354d03b9e), etc.) - Improve support for old nightly. ([#73](https://github.com/taiki-e/portable-atomic/pull/73), [872feb9](https://github.com/taiki-e/portable-atomic/commit/872feb9d7f3a4ca7cf9b63935265d46498fcae99)) - Documentation improvements. ## [1.0.1] - 2023-01-21 - Optimize `Atomic{I,U}*::{fetch_not,not}` methods. ([#62](https://github.com/taiki-e/portable-atomic/pull/62)) ## [1.0.0] - 2023-01-15 - Add `critical-section` feature to use [critical-section](https://github.com/rust-embedded/critical-section) on targets where atomic CAS is not natively available. ([#51](https://github.com/taiki-e/portable-atomic/pull/51), thanks @Dirbaio) This is useful to get atomic CAS when `--cfg portable_atomic_unsafe_assume_single_core` can't be used, such as multi-core targets, unprivileged code running under some RTOS, or environments where disabling interrupts needs extra care due to e.g. real-time requirements. See [documentation](https://github.com/taiki-e/portable-atomic#optional-features-critical-section) for more. - Remove `outline-atomics` feature. This was no-op since 0.3.19. - Documentation improvements. ## [0.3.20] - 2023-05-07 The latest version of portable-atomic is 1.x. This release makes portable-atomic 0.3 is built on top of portable-atomic 1.x to make bug fixes and improvements such as [support for new targets](https://github.com/taiki-e/portable-atomic/pull/86) in 1.x available to the ecosystem that depends on older portable-atomic. portable-atomic 0.3 is still maintained passively, but upgrading to portable-atomic 1.x is recommended. (There are no breaking changes from 0.3, except that a deprecated no-op `outline-atomics` Cargo feature has been removed.) ([#99](https://github.com/taiki-e/portable-atomic/pull/99)) ## [0.3.19] - 2022-12-25 - Add `AtomicI*::{fetch_neg,neg}` and `AtomicF*::fetch_neg` methods. ([#54](https://github.com/taiki-e/portable-atomic/pull/54)) `AtomicI*::neg` are equivalent to the corresponding `fetch_*` methods, but do not return the previous value. They are intended for optimization on platforms that have atomic instructions for the corresponding operation, such as x86's `lock neg`. Currently, optimizations by these methods (`neg`) are only guaranteed for x86/x86_64. - Add `Atomic{I,U}*::{fetch_not,not}` methods. ([#54](https://github.com/taiki-e/portable-atomic/pull/54)) `Atomic{I,U}*::not` are equivalent to the corresponding `fetch_*` methods, but do not return the previous value. They are intended for optimization on platforms that have atomic instructions for the corresponding operation, such as x86's `lock not`, MSP430's `inv`. Currently, optimizations by these methods (`not`) are only guaranteed for x86/x86_64 and MSP430. (Note: `AtomicBool` already has `fetch_not` and `not` methods.) - Enable outline-atomics for 128-bit atomics by default. ([#57](https://github.com/taiki-e/portable-atomic/pull/57)) See [#57](https://github.com/taiki-e/portable-atomic/pull/57) for more. - Improve support for old nightly compilers. ## [0.3.18] - 2022-12-15 - Fix build error when not using `portable_atomic_unsafe_assume_single_core` cfg on AVR and MSP430 custom targets. ([#50](https://github.com/taiki-e/portable-atomic/pull/50)) Since 0.3.11, atomic CAS was supported without the cfg on AVR and MSP430 builtin targets, but that change was not applied to custom targets. ## [0.3.17] - 2022-12-14 - Optimize x86_64 128-bit atomic load/store on AMD CPU with AVX. ([#49](https://github.com/taiki-e/portable-atomic/pull/49)) - Improve support for custom targets on old rustc. ## [0.3.16] - 2022-12-09 - Add `Atomic{I,U}*::{add,sub,and,or,xor}` and `AtomicBool::{and,or,xor}` methods. ([#47](https://github.com/taiki-e/portable-atomic/pull/47)) They are equivalent to the corresponding `fetch_*` methods, but do not return the previous value. They are intended for optimization on platforms that implement atomics using inline assembly, such as the MSP430. Currently, optimizations by these methods (`add`,`sub`,`and`,`or`,`xor`) are only guaranteed for MSP430; on x86/x86_64, LLVM can optimize in most cases, so cases, where this would improve things, should be rare. - Various improvements to `portable_atomic_unsafe_assume_single_core` cfg. ([#44](https://github.com/taiki-e/portable-atomic/pull/44), [#40](https://github.com/taiki-e/portable-atomic/pull/40)) - Support disabling FIQs on pre-v6 Arm under `portable_atomic_disable_fiq` cfg. - Support RISC-V supervisor mode under `portable_atomic_s_mode` cfg. - Optimize interrupt restore on AVR and MSP430. ([#40](https://github.com/taiki-e/portable-atomic/pull/40)) - Documentation improvements. See [#44](https://github.com/taiki-e/portable-atomic/pull/44) for more. ## [0.3.15] - 2022-09-09 - Implement workaround for std cpuid bug due to LLVM bug ([rust-lang/rust#101346](https://github.com/rust-lang/rust/issues/101346), [llvm/llvm-project#57550](https://github.com/llvm/llvm-project/issues/57550)). - Our use case is likely not affected, but we implement this just in case. - We've confirmed that the uses of inline assembly in this crate are not affected by this LLVM bug. ## [0.3.14] - 2022-09-04 - Optimize atomic load/store on no-std pre-v6 Arm when `portable_atomic_unsafe_assume_single_core` cfg is used. ([#36](https://github.com/taiki-e/portable-atomic/pull/36)) - Support pre-power8 powerpc64le. powerpc64le's default cpu version is power8, but you can technically compile it for the old cpu using the unsafe `-C target-cpu` rustc flag. ## [0.3.13] - 2022-08-15 - Use track_caller when debug assertions are enabled on Rust 1.46+. - Make powerpc64 128-bit atomics compatible with Miri and ThreadSanitizer on LLVM 15+. - Document that 128-bit atomics are compatible with Miri and ThreadSanitizer on recent nightly. ## [0.3.12] - 2022-08-13 - Support atomic CAS on no-std pre-v6 Arm targets (e.g., thumbv4t-none-eabi) under unsafe cfg `portable_atomic_unsafe_assume_single_core`. ([#28](https://github.com/taiki-e/portable-atomic/pull/28)) ## [0.3.11] - 2022-08-12 - Always provide atomic CAS for MSP430 and AVR. ([#31](https://github.com/taiki-e/portable-atomic/pull/31)) This previously required unsafe cfg `portable_atomic_unsafe_assume_single_core`, but since all MSP430 and AVR are single-core, we can safely provide atomic CAS based on disabling interrupts. - Support `fence` and `compiler_fence` on MSP430. (On MSP430, the standard library's fences are currently unavailable due to LLVM errors.) - Update safety requirements for unsafe cfg `portable_atomic_unsafe_assume_single_core` to mention use of privileged instructions to disable interrupts. - Atomic operations based on disabling interrupts on single-core systems are now considered lock-free. The previous behavior was inconsistent because we consider the pre-v6 Arm Linux's atomic operations provided in a similar way by the Linux kernel to be lock-free. - Respect `-Z allow-features`. ## [0.3.10] - 2022-08-03 - Optimize AArch64 128-bit atomic load when the `lse` target feature is enabled at compile-time. ([#20](https://github.com/taiki-e/portable-atomic/pull/20)) ## [0.3.9] - 2022-08-03 - Fix build error on old Miri. - Documentation improvements. ## [0.3.8] - 2022-08-02 - Make AArch64 and s390x 128-bit atomics compatible with Miri and ThreadSanitizer. ## [0.3.7] - 2022-07-31 - Provide stable equivalent of [`#![feature(strict_provenance_atomic_ptr)]`](https://github.com/rust-lang/rust/issues/99108). ([#23](https://github.com/taiki-e/portable-atomic/pull/23)) - `AtomicPtr::fetch_ptr_{add,sub}` - `AtomicPtr::fetch_byte_{add,sub}` - `AtomicPtr::fetch_{or,and,xor}` These APIs are compatible with strict-provenance on `cfg(miri)`. Otherwise, they are compatible with permissive-provenance. Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, these APIs will be strict-provenance compatible in all cases from the version in which it is stabilized. - Provide stable equivalent of [`#![feature(atomic_bool_fetch_not)]`](https://github.com/rust-lang/rust/issues/98485). ([#24](https://github.com/taiki-e/portable-atomic/pull/24)) - `AtomicBool::fetch_not` - Optimize x86_64 128-bit RMWs. ([#22](https://github.com/taiki-e/portable-atomic/pull/22)) - Optimize x86_64 outline-atomics. - Optimize inline assemblies on Arm and AArch64. - Revert [thumbv6m atomic load/store changes made in 0.3.5](https://github.com/taiki-e/portable-atomic/pull/18). This is because [rust-lang/rust#99595](https://github.com/rust-lang/rust/pull/99595) has been reverted, so this is no longer needed. ## [0.3.6] - 2022-07-26 - Fix build failure due to the existence of the `specs` directory. - Documentation improvements. - Optimize inline assemblies on x86_64, RISC-V, and MSP430. ## [0.3.5] - 2022-07-23 **Note:** This release has been yanked due to a bug fixed in 0.3.6. - Provide thumbv6m atomic load/store which is planned to be removed from the standard library in [rust-lang/rust#99595](https://github.com/rust-lang/rust/pull/99595). ([#18](https://github.com/taiki-e/portable-atomic/pull/18)) - Optimize inline assemblies on AArch64, RISC-V, and powerpc64. ## [0.3.4] - 2022-06-25 - Optimize x86_64 128-bit atomic store. ## [0.3.3] - 2022-06-24 - Allow CAS failure ordering stronger than success ordering. ([#17](https://github.com/taiki-e/portable-atomic/pull/17)) ## [0.3.2] - 2022-06-19 - Optimize x86_64 128-bit atomic load/store on Intel CPU with AVX. ([#16](https://github.com/taiki-e/portable-atomic/pull/16)) - Support native 128-bit atomic operations for powerpc64 (le or pwr8+, currently nightly-only). - Fix behavior differences between stable and nightly. ([#15](https://github.com/taiki-e/portable-atomic/pull/15)) ## [0.3.1] - 2022-06-16 - Optimize AArch64 128-bit atomic load/store when the `lse2` target feature is enabled at compile-time. ([#11](https://github.com/taiki-e/portable-atomic/pull/11)) - Relax ordering in `Debug` impl to reflect std changes. ([#12](https://github.com/taiki-e/portable-atomic/pull/12)) ## [0.3.0] - 2022-03-25 - Support native 128-bit atomic operations for s390x (currently nightly-only). - Add `AtomicF{32,64}::fetch_abs`. - Add `#[must_use]` to constructors. - Use 128-bit atomic operation mappings same as LLVM on AArch64. - Remove `parking_lot` optional feature to allow the use of this crate within global allocators. ## [0.2.1] - 2022-03-17 - Implement AArch64 outline-atomics. ## [0.2.0] - 2022-03-10 - Remove `i128` feature. `Atomic{I,U}128` are now always enabled. - Add `outline-atomics` feature. Currently, this is the same as the 0.1's `i128-dynamic`, except that `fallback` feature is not implicitly enabled. - Remove `i128-dynamic` feature in favor of `outline-atomics` feature. - Add `AtomicF{32,64}::as_bits`. ## [0.1.4] - 2022-03-02 - Support native 128-bit atomic operations for AArch64 at Rust 1.59+. This was previously supported only on nightly. ([#6](https://github.com/taiki-e/portable-atomic/pull/6)) ## [0.1.3] - 2022-02-28 - Fix inline assembly for RISC-V without A-extension. ## [0.1.2] - 2022-02-26 **Note:** This release has been yanked due to a bug fixed in 0.1.3. - Add `parking_lot` feature to use parking_lot in global locks of fallback implementation. - Fix bug in cmpxchg16b support. ([#5](https://github.com/taiki-e/portable-atomic/pull/5)) ## [0.1.1] - 2022-02-25 **Note:** This release has been yanked due to a bug fixed in 0.1.3. - Fix doc cfg on `Atomic{I,U}128`. ## [0.1.0] - 2022-02-24 **Note:** This release has been yanked due to a bug fixed in 0.1.3. Initial release [Unreleased]: https://github.com/taiki-e/portable-atomic/compare/v1.11.0...HEAD [1.11.0]: https://github.com/taiki-e/portable-atomic/compare/v1.10.0...v1.11.0 [1.10.0]: https://github.com/taiki-e/portable-atomic/compare/v1.9.0...v1.10.0 [1.9.0]: https://github.com/taiki-e/portable-atomic/compare/v1.8.0...v1.9.0 [1.8.0]: https://github.com/taiki-e/portable-atomic/compare/v1.7.0...v1.8.0 [1.7.0]: https://github.com/taiki-e/portable-atomic/compare/v1.6.0...v1.7.0 [1.6.0]: https://github.com/taiki-e/portable-atomic/compare/v1.5.1...v1.6.0 [1.5.1]: https://github.com/taiki-e/portable-atomic/compare/v1.5.0...v1.5.1 [1.5.0]: https://github.com/taiki-e/portable-atomic/compare/v1.4.3...v1.5.0 [1.4.3]: https://github.com/taiki-e/portable-atomic/compare/v1.4.2...v1.4.3 [1.4.2]: https://github.com/taiki-e/portable-atomic/compare/v1.4.1...v1.4.2 [1.4.1]: https://github.com/taiki-e/portable-atomic/compare/v1.4.0...v1.4.1 [1.4.0]: https://github.com/taiki-e/portable-atomic/compare/v1.3.3...v1.4.0 [1.3.3]: https://github.com/taiki-e/portable-atomic/compare/v1.3.2...v1.3.3 [1.3.2]: https://github.com/taiki-e/portable-atomic/compare/v1.3.1...v1.3.2 [1.3.1]: https://github.com/taiki-e/portable-atomic/compare/v1.3.0...v1.3.1 [1.3.0]: https://github.com/taiki-e/portable-atomic/compare/v1.2.0...v1.3.0 [1.2.0]: https://github.com/taiki-e/portable-atomic/compare/v1.1.0...v1.2.0 [1.1.0]: https://github.com/taiki-e/portable-atomic/compare/v1.0.1...v1.1.0 [1.0.1]: https://github.com/taiki-e/portable-atomic/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/taiki-e/portable-atomic/compare/v0.3.19...v1.0.0 [0.3.20]: https://github.com/taiki-e/portable-atomic/compare/v0.3.19...v0.3.20 [0.3.19]: https://github.com/taiki-e/portable-atomic/compare/v0.3.18...v0.3.19 [0.3.18]: https://github.com/taiki-e/portable-atomic/compare/v0.3.17...v0.3.18 [0.3.17]: https://github.com/taiki-e/portable-atomic/compare/v0.3.16...v0.3.17 [0.3.16]: https://github.com/taiki-e/portable-atomic/compare/v0.3.15...v0.3.16 [0.3.15]: https://github.com/taiki-e/portable-atomic/compare/v0.3.14...v0.3.15 [0.3.14]: https://github.com/taiki-e/portable-atomic/compare/v0.3.13...v0.3.14 [0.3.13]: https://github.com/taiki-e/portable-atomic/compare/v0.3.12...v0.3.13 [0.3.12]: https://github.com/taiki-e/portable-atomic/compare/v0.3.11...v0.3.12 [0.3.11]: https://github.com/taiki-e/portable-atomic/compare/v0.3.10...v0.3.11 [0.3.10]: https://github.com/taiki-e/portable-atomic/compare/v0.3.9...v0.3.10 [0.3.9]: https://github.com/taiki-e/portable-atomic/compare/v0.3.8...v0.3.9 [0.3.8]: https://github.com/taiki-e/portable-atomic/compare/v0.3.7...v0.3.8 [0.3.7]: https://github.com/taiki-e/portable-atomic/compare/v0.3.6...v0.3.7 [0.3.6]: https://github.com/taiki-e/portable-atomic/compare/v0.3.5...v0.3.6 [0.3.5]: https://github.com/taiki-e/portable-atomic/compare/v0.3.4...v0.3.5 [0.3.4]: https://github.com/taiki-e/portable-atomic/compare/v0.3.3...v0.3.4 [0.3.3]: https://github.com/taiki-e/portable-atomic/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/taiki-e/portable-atomic/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/taiki-e/portable-atomic/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/taiki-e/portable-atomic/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/taiki-e/portable-atomic/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/taiki-e/portable-atomic/compare/v0.1.4...v0.2.0 [0.1.4]: https://github.com/taiki-e/portable-atomic/compare/v0.1.3...v0.1.4 [0.1.3]: https://github.com/taiki-e/portable-atomic/compare/v0.1.2...v0.1.3 [0.1.2]: https://github.com/taiki-e/portable-atomic/compare/v0.1.1...v0.1.2 [0.1.1]: https://github.com/taiki-e/portable-atomic/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/taiki-e/portable-atomic/releases/tag/v0.1.0 portable-atomic/src/0000775000175000017500000000000015105742312014255 5ustar bdrungbdrungportable-atomic/src/lib.rs0000644000175000017500000063706215105742312015405 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /*! Portable atomic types including support for 128-bit atomics, atomic float, etc. - Provide all atomic integer types (`Atomic{I,U}{8,16,32,64}`) for all targets that can use atomic CAS. (i.e., all targets that can use `std`, and most no-std targets) - Provide `AtomicI128` and `AtomicU128`. - Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float)) - Provide `AtomicF16` and `AtomicF128` for [unstable `f16` and `f128`](https://github.com/rust-lang/rust/issues/116909). ([optional, requires the `float` feature and unstable cfgs](#optional-features-float)) - Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR) - Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 Arm, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise) - Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108). - Make features that require newer compilers, such as [`fetch_{max,min}`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [`fetch_update`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_update), [`as_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.as_ptr), [`from_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.from_ptr), [`AtomicBool::fetch_not`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.fetch_not) and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+. - Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc. portable-atomic version of `std::sync::Arc` is provided by the [portable-atomic-util](https://github.com/taiki-e/portable-atomic/tree/HEAD/portable-atomic-util) crate. ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] portable-atomic = "1" ``` The default features are mainly for users who use atomics larger than the pointer width. If you don't need them, disabling the default features may reduce code size and compile time slightly. ```toml [dependencies] portable-atomic = { version = "1", default-features = false } ``` If your crate supports no-std environment and requires atomic CAS, enabling the `require-cas` feature will allow the `portable-atomic` to display a [helpful error message](https://github.com/taiki-e/portable-atomic/pull/100) to users on targets requiring additional action on the user side to provide atomic CAS. ```toml [dependencies] portable-atomic = { version = "1.3", default-features = false, features = ["require-cas"] } ``` ## 128-bit atomics support Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), Arm64EC (Rust 1.84+), s390x (Rust 1.84+), and powerpc64 (nightly only), otherwise the fallback implementation is used. On x86_64, even if `cmpxchg16b` is not available at compile-time (note: `cmpxchg16b` target feature is enabled by default only on Apple and Windows (except Windows 7) targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg. They are usually implemented using inline assembly, and when using Miri or ThreadSanitizer that do not support inline assembly, core intrinsics are used instead of inline assembly if possible. See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md) for details. ## Optional features - **`fallback`** *(enabled by default)*
Enable fallback implementations. Disabling this allows only atomic types for which the platform natively supports atomic operations. - **`float`**
Provide `AtomicF{32,64}`. - When unstable `--cfg portable_atomic_unstable_f16` is also enabled, `AtomicF16` for [unstable `f16`](https://github.com/rust-lang/rust/issues/116909) is also provided. - When unstable `--cfg portable_atomic_unstable_f128` is also enabled, `AtomicF128` for [unstable `f128`](https://github.com/rust-lang/rust/issues/116909) is also provided. Note: - Most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. (AArch64 with FEAT_LSFE and GPU targets have atomic instructions for float, [so we plan to use these instructions for them in the future.](https://github.com/taiki-e/portable-atomic/issues/34)) - Unstable cfgs are outside of the normal semver guarantees and minor or patch versions of portable-atomic may make breaking changes to them at any time. - **`std`**
Use `std`. - **`require-cas`**
Emit compile error if atomic CAS is not available. See [Usage](#usage) section and [#100](https://github.com/taiki-e/portable-atomic/pull/100) for more. - **`serde`**
Implement `serde::{Serialize,Deserialize}` for atomic types. Note: - The MSRV when this feature is enabled depends on the MSRV of [serde]. - **`critical-section`**
When this feature is enabled, this crate uses [critical-section] to provide atomic CAS for targets where it is not natively available. When enabling it, you should provide a suitable critical section implementation for the current target, see the [critical-section] documentation for details on how to do so. `critical-section` support is useful to get atomic CAS when the [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) can't be used, such as multi-core targets, unprivileged code running under some RTOS, or environments where disabling interrupts needs extra care due to e.g. real-time requirements. Note that with the `critical-section` feature, critical sections are taken for all atomic operations, while with [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) some operations don't require disabling interrupts (loads and stores, but additionally on MSP430 `add`, `sub`, `and`, `or`, `xor`, `not`). Therefore, for better performance, if all the `critical-section` implementation for your target does is disable interrupts, prefer using `unsafe-assume-single-core` feature instead. Note: - The MSRV when this feature is enabled depends on the MSRV of [critical-section]. - It is usually *not* recommended to always enable this feature in dependencies of the library. Enabling this feature will prevent the end user from having the chance to take advantage of other (potentially) efficient implementations ([Implementations provided by `unsafe-assume-single-core` feature, default implementations on MSP430 and AVR](#optional-features-unsafe-assume-single-core), implementation proposed in [#60], etc. Other systems may also be supported in the future). The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where other implementations are known not to work.) As an example, the end-user's `Cargo.toml` that uses a crate that provides a critical-section implementation and a crate that depends on portable-atomic as an option would be expected to look like this: ```toml [dependencies] portable-atomic = { version = "1", default-features = false, features = ["critical-section"] } crate-provides-critical-section-impl = "..." crate-uses-portable-atomic-as-feature = { version = "...", features = ["portable-atomic"] } ``` - **`unsafe-assume-single-core`**
Assume that the target is single-core. When this feature is enabled, this crate provides atomic CAS for targets where atomic CAS is not available in the standard library by disabling interrupts. This feature is `unsafe`, and note the following safety requirements: - Enabling this feature for multi-core systems is always **unsound**. - This uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode. Enabling this feature in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent. The following are known cases: - On pre-v6 Arm, this disables only IRQs by default. For many systems (e.g., GBA) this is enough. If the system need to disable both IRQs and FIQs, you need to enable the `disable-fiq` feature together. - On RISC-V without A-extension, this generates code for machine-mode (M-mode) by default. If you enable the `s-mode` together, this generates code for supervisor-mode (S-mode). In particular, `qemu-system-riscv*` uses [OpenSBI](https://github.com/riscv-software-src/opensbi) as the default firmware. See also the [`interrupt` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/interrupt/README.md). Consider using the [`critical-section` feature](#optional-features-critical-section) for systems that cannot use this feature. It is **very strongly discouraged** to enable this feature in libraries that depend on `portable-atomic`. The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where it is guaranteed to always be sound, for example in a hardware abstraction layer targeting a single-core chip.) Armv6-M (thumbv6m), pre-v6 Arm (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa are currently supported. Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this feature. Enabling this feature for targets that have atomic CAS will result in a compile error. Feel free to submit an issue if your target is not supported yet. ## Optional cfg One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags): ```toml # .cargo/config.toml [target.] rustflags = ["--cfg", "portable_atomic_no_outline_atomics"] ``` Or set environment variable: ```sh RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... ``` - **`--cfg portable_atomic_unsafe_assume_single_core`**
Since 1.4.0, this cfg is an alias of [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core). Originally, we were providing these as cfgs instead of features, but based on a strong request from the embedded ecosystem, we have agreed to provide them as features as well. See [#94](https://github.com/taiki-e/portable-atomic/pull/94) for more. - **`--cfg portable_atomic_no_outline_atomics`**
Disable dynamic dispatching by run-time CPU feature detection. If dynamic dispatching by run-time CPU feature detection is enabled, it allows maintaining support for older CPUs while using features that are not supported on older CPUs, such as CMPXCHG16B (x86_64) and FEAT_LSE/FEAT_LSE2 (AArch64). Note: - Dynamic detection is currently only supported in x86_64, AArch64, Arm, RISC-V, Arm64EC, and powerpc64, otherwise it works the same as when this cfg is set. - If the required target features are enabled at compile-time, the atomic operations are inlined. - This is compatible with no-std (as with all features except `std`). - On some targets, run-time detection is disabled by default mainly for compatibility with incomplete build environments or support for it is experimental, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.) - Some AArch64 targets enable LLVM's `outline-atomics` target feature by default, so if you set this cfg, you may want to disable that as well. (portable-atomic's outline-atomics does not depend on the compiler-rt symbols, so even if you need to disable LLVM's outline-atomics, you may not need to disable portable-atomic's outline-atomics.) See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md). ## Related Projects - [atomic-maybe-uninit]: Atomic operations on potentially uninitialized integers. - [atomic-memcpy]: Byte-wise atomic memcpy. [#60]: https://github.com/taiki-e/portable-atomic/issues/60 [atomic-maybe-uninit]: https://github.com/taiki-e/atomic-maybe-uninit [atomic-memcpy]: https://github.com/taiki-e/atomic-memcpy [critical-section]: https://github.com/rust-embedded/critical-section [rust-lang/rust#100650]: https://github.com/rust-lang/rust/issues/100650 [serde]: https://github.com/serde-rs/serde */ #![no_std] #![doc(test( no_crate_inject, attr( deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code, unused_variables) ) ))] #![cfg_attr(not(portable_atomic_no_unsafe_op_in_unsafe_fn), warn(unsafe_op_in_unsafe_fn))] // unsafe_op_in_unsafe_fn requires Rust 1.52 #![cfg_attr(portable_atomic_no_unsafe_op_in_unsafe_fn, allow(unused_unsafe))] #![warn( // Lints that may help when writing public library. missing_debug_implementations, // missing_docs, clippy::alloc_instead_of_core, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::impl_trait_in_params, clippy::missing_inline_in_public_items, clippy::std_instead_of_alloc, clippy::std_instead_of_core, // Code outside of cfg(feature = "float") shouldn't use float. clippy::float_arithmetic, )] #![cfg_attr(not(portable_atomic_no_asm), warn(missing_docs))] // module-level #![allow(missing_docs)] doesn't work for macros on old rustc #![cfg_attr(portable_atomic_no_strict_provenance, allow(unstable_name_collisions))] #![allow(clippy::inline_always, clippy::used_underscore_items)] // asm_experimental_arch // AVR, MSP430, and Xtensa are tier 3 platforms and require nightly anyway. // On tier 2 platforms (powerpc64), we use cfg set by build script to // determine whether this feature is available or not. #![cfg_attr( all( not(portable_atomic_no_asm), any( target_arch = "avr", target_arch = "msp430", all(target_arch = "xtensa", portable_atomic_unsafe_assume_single_core), all(target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch), ), ), feature(asm_experimental_arch) )] // f16/f128 // cfg is unstable and explicitly enabled by the user #![cfg_attr(portable_atomic_unstable_f16, feature(f16))] #![cfg_attr(portable_atomic_unstable_f128, feature(f128))] // Old nightly only // These features are already stabilized or have already been removed from compilers, // and can safely be enabled for old nightly as long as version detection works. // - cfg(target_has_atomic) // - asm! on AArch64, Arm, RISC-V, x86, x86_64, Arm64EC, s390x // - llvm_asm! on AVR (tier 3) and MSP430 (tier 3) // - #[instruction_set] on non-Linux/Android pre-v6 Arm (tier 3) // This also helps us test that our assembly code works with the minimum external // LLVM version of the first rustc version that inline assembly stabilized. #![cfg_attr(portable_atomic_unstable_cfg_target_has_atomic, feature(cfg_target_has_atomic))] #![cfg_attr( all( portable_atomic_unstable_asm, any( target_arch = "aarch64", target_arch = "arm", target_arch = "riscv32", target_arch = "riscv64", target_arch = "x86", target_arch = "x86_64", ), ), feature(asm) )] #![cfg_attr( all( portable_atomic_unstable_asm_experimental_arch, any(target_arch = "arm64ec", target_arch = "s390x"), ), feature(asm_experimental_arch) )] #![cfg_attr( all(any(target_arch = "avr", target_arch = "msp430"), portable_atomic_no_asm), feature(llvm_asm) )] #![cfg_attr( all( target_arch = "arm", portable_atomic_unstable_isa_attribute, any(test, portable_atomic_unsafe_assume_single_core), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(target_has_atomic = "ptr"), ), feature(isa_attribute) )] // Miri and/or ThreadSanitizer only // They do not support inline assembly, so we need to use unstable features instead. // Since they require nightly compilers anyway, we can use the unstable features. // This is not an ideal situation, but it is still better than always using lock-based // fallback and causing memory ordering problems to be missed by these checkers. #![cfg_attr( all( any( target_arch = "aarch64", target_arch = "arm64ec", target_arch = "powerpc64", target_arch = "s390x", ), any(miri, portable_atomic_sanitize_thread), ), allow(internal_features) )] #![cfg_attr( all( any( target_arch = "aarch64", target_arch = "arm64ec", target_arch = "powerpc64", target_arch = "s390x", ), any(miri, portable_atomic_sanitize_thread), ), feature(core_intrinsics) )] // docs.rs only (cfg is enabled by docs.rs, not build script) #![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr( all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "bpf", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), ), allow(unused_imports, unused_macros, clippy::unused_trait_names) )] // There are currently no 128-bit or higher builtin targets. // (Although some of our generic code is written with the future // addition of 128-bit targets in mind.) // Note that Rust (and C99) pointers must be at least 16-bit (i.e., 8-bit targets are impossible): https://github.com/rust-lang/rust/pull/49305 #[cfg(not(any( target_pointer_width = "16", target_pointer_width = "32", target_pointer_width = "64", )))] compile_error!( "portable-atomic currently only supports targets with {16,32,64}-bit pointer width; \ if you need support for others, \ please submit an issue at " ); #[cfg(portable_atomic_unsafe_assume_single_core)] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] compile_error!( "`portable_atomic_unsafe_assume_single_core` cfg (`unsafe-assume-single-core` feature) \ is not compatible with target that supports atomic CAS;\n\ see also for troubleshooting" ); #[cfg(portable_atomic_unsafe_assume_single_core)] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))] #[cfg(not(any( target_arch = "arm", target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", target_arch = "xtensa", )))] compile_error!( "`portable_atomic_unsafe_assume_single_core` cfg (`unsafe-assume-single-core` feature) \ is not supported yet on this target;\n\ if you need unsafe-assume-single-core support for this target,\n\ please submit an issue at " ); #[cfg(portable_atomic_no_outline_atomics)] #[cfg(not(any( target_arch = "aarch64", target_arch = "arm", target_arch = "arm64ec", target_arch = "powerpc64", target_arch = "riscv32", target_arch = "riscv64", target_arch = "x86_64", )))] compile_error!("`portable_atomic_no_outline_atomics` cfg does not compatible with this target"); #[cfg(portable_atomic_outline_atomics)] #[cfg(not(any( target_arch = "aarch64", target_arch = "powerpc64", target_arch = "riscv32", target_arch = "riscv64", )))] compile_error!("`portable_atomic_outline_atomics` cfg does not compatible with this target"); #[cfg(portable_atomic_disable_fiq)] #[cfg(not(all( target_arch = "arm", not(any(target_feature = "mclass", portable_atomic_target_feature = "mclass")), )))] compile_error!( "`portable_atomic_disable_fiq` cfg (`disable-fiq` feature) is only available on pre-v6 Arm" ); #[cfg(portable_atomic_s_mode)] #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] compile_error!("`portable_atomic_s_mode` cfg (`s-mode` feature) is only available on RISC-V"); #[cfg(portable_atomic_force_amo)] #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] compile_error!("`portable_atomic_force_amo` cfg (`force-amo` feature) is only available on RISC-V"); #[cfg(portable_atomic_disable_fiq)] #[cfg(not(portable_atomic_unsafe_assume_single_core))] compile_error!( "`portable_atomic_disable_fiq` cfg (`disable-fiq` feature) may only be used together with `portable_atomic_unsafe_assume_single_core` cfg (`unsafe-assume-single-core` feature)" ); #[cfg(portable_atomic_s_mode)] #[cfg(not(portable_atomic_unsafe_assume_single_core))] compile_error!( "`portable_atomic_s_mode` cfg (`s-mode` feature) may only be used together with `portable_atomic_unsafe_assume_single_core` cfg (`unsafe-assume-single-core` feature)" ); #[cfg(portable_atomic_force_amo)] #[cfg(not(portable_atomic_unsafe_assume_single_core))] compile_error!( "`portable_atomic_force_amo` cfg (`force-amo` feature) may only be used together with `portable_atomic_unsafe_assume_single_core` cfg (`unsafe-assume-single-core` feature)" ); #[cfg(all(portable_atomic_unsafe_assume_single_core, feature = "critical-section"))] compile_error!( "you may not enable `critical-section` feature and `portable_atomic_unsafe_assume_single_core` cfg (`unsafe-assume-single-core` feature) at the same time" ); #[cfg(feature = "require-cas")] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] compile_error!( "dependents require atomic CAS but not available on this target by default;\n\ consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features.\n\ see for more." ); #[cfg(any(test, feature = "std"))] extern crate std; #[macro_use] mod cfgs; #[cfg(target_pointer_width = "16")] pub use self::{cfg_has_atomic_16 as cfg_has_atomic_ptr, cfg_no_atomic_16 as cfg_no_atomic_ptr}; #[cfg(target_pointer_width = "32")] pub use self::{cfg_has_atomic_32 as cfg_has_atomic_ptr, cfg_no_atomic_32 as cfg_no_atomic_ptr}; #[cfg(target_pointer_width = "64")] pub use self::{cfg_has_atomic_64 as cfg_has_atomic_ptr, cfg_no_atomic_64 as cfg_no_atomic_ptr}; #[cfg(target_pointer_width = "128")] pub use self::{cfg_has_atomic_128 as cfg_has_atomic_ptr, cfg_no_atomic_128 as cfg_no_atomic_ptr}; #[macro_use] mod utils; #[cfg(test)] #[macro_use] mod tests; #[doc(no_inline)] pub use core::sync::atomic::Ordering; // LLVM doesn't support fence/compiler_fence for MSP430. #[cfg(target_arch = "msp430")] pub use self::imp::msp430::{compiler_fence, fence}; #[doc(no_inline)] #[cfg(not(target_arch = "msp430"))] pub use core::sync::atomic::{compiler_fence, fence}; mod imp; pub mod hint { //! Re-export of the [`core::hint`] module. //! //! The only difference from the [`core::hint`] module is that [`spin_loop`] //! is available in all rust versions that this crate supports. //! //! ``` //! use portable_atomic::hint; //! //! hint::spin_loop(); //! ``` #[doc(no_inline)] pub use core::hint::*; /// Emits a machine instruction to signal the processor that it is running in /// a busy-wait spin-loop ("spin lock"). /// /// Upon receiving the spin-loop signal the processor can optimize its behavior by, /// for example, saving power or switching hyper-threads. /// /// This function is different from [`thread::yield_now`] which directly /// yields to the system's scheduler, whereas `spin_loop` does not interact /// with the operating system. /// /// A common use case for `spin_loop` is implementing bounded optimistic /// spinning in a CAS loop in synchronization primitives. To avoid problems /// like priority inversion, it is strongly recommended that the spin loop is /// terminated after a finite amount of iterations and an appropriate blocking /// syscall is made. /// /// **Note:** On platforms that do not support receiving spin-loop hints this /// function does not do anything at all. /// /// [`thread::yield_now`]: https://doc.rust-lang.org/std/thread/fn.yield_now.html #[inline] pub fn spin_loop() { #[allow(deprecated)] core::sync::atomic::spin_loop_hint(); } } #[cfg(doc)] use core::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release, SeqCst}; use core::{fmt, ptr}; #[cfg(portable_atomic_no_strict_provenance)] #[cfg(miri)] use crate::utils::ptr::PtrExt as _; cfg_has_atomic_8! { /// A boolean type which can be safely shared between threads. /// /// This type has the same in-memory representation as a [`bool`]. /// /// If the compiler and the platform support atomic loads and stores of `u8`, /// this type is a wrapper for the standard library's /// [`AtomicBool`](core::sync::atomic::AtomicBool). If the platform supports it /// but the compiler does not, atomic operations are implemented using inline /// assembly. #[repr(C, align(1))] pub struct AtomicBool { v: core::cell::UnsafeCell, } impl Default for AtomicBool { /// Creates an `AtomicBool` initialized to `false`. #[inline] fn default() -> Self { Self::new(false) } } impl From for AtomicBool { /// Converts a `bool` into an `AtomicBool`. #[inline] fn from(b: bool) -> Self { Self::new(b) } } // Send is implicitly implemented. // SAFETY: any data races are prevented by disabling interrupts or // atomic intrinsics (see module-level comments). unsafe impl Sync for AtomicBool {} // UnwindSafe is implicitly implemented. #[cfg(not(portable_atomic_no_core_unwind_safe))] impl core::panic::RefUnwindSafe for AtomicBool {} #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))] impl std::panic::RefUnwindSafe for AtomicBool {} impl_debug_and_serde!(AtomicBool); impl AtomicBool { /// Creates a new `AtomicBool`. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicBool; /// /// let atomic_true = AtomicBool::new(true); /// let atomic_false = AtomicBool::new(false); /// ``` #[inline] #[must_use] pub const fn new(v: bool) -> Self { static_assert_layout!(AtomicBool, bool); Self { v: core::cell::UnsafeCell::new(v as u8) } } // TODO: update docs based on https://github.com/rust-lang/rust/pull/116762 const_fn! { const_if: #[cfg(not(portable_atomic_no_const_mut_refs))]; /// Creates a new `AtomicBool` from a pointer. /// /// This is `const fn` on Rust 1.83+. /// /// # Safety /// /// * `ptr` must be aligned to `align_of::()` (note that on some platforms this can /// be bigger than `align_of::()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. /// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value /// behind `ptr` must have a happens-before relationship with atomic accesses via the returned /// value (or vice-versa). /// * In other words, time periods where the value is accessed atomically may not overlap /// with periods where the value is accessed non-atomically. /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done /// from the same thread. /// * If this atomic type is *not* lock-free: /// * Any accesses to the value behind `ptr` must have a happens-before relationship /// with accesses via the returned value (or vice-versa). /// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must /// be compatible with operations performed by this atomic type. /// * This method must not be used to create overlapping or mixed-size atomic accesses, as /// these are not supported by the memory model. /// /// [valid]: core::ptr#safety #[inline] #[must_use] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicBool; /// /// let is_lock_free = AtomicBool::is_lock_free(); /// ``` #[inline] #[must_use] pub fn is_lock_free() -> bool { imp::AtomicU8::is_lock_free() } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// **Note:** If the atomic operation relies on dynamic CPU feature detection, /// this type may be lock-free even if the function returns false. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicBool; /// /// const IS_ALWAYS_LOCK_FREE: bool = AtomicBool::is_always_lock_free(); /// ``` #[inline] #[must_use] pub const fn is_always_lock_free() -> bool { imp::AtomicU8::IS_ALWAYS_LOCK_FREE } #[cfg(test)] const IS_ALWAYS_LOCK_FREE: bool = Self::is_always_lock_free(); const_fn! { const_if: #[cfg(not(portable_atomic_no_const_mut_refs))]; /// Returns a mutable reference to the underlying [`bool`]. /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. /// /// This is `const fn` on Rust 1.83+. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let mut some_bool = AtomicBool::new(true); /// assert_eq!(*some_bool.get_mut(), true); /// *some_bool.get_mut() = false; /// assert_eq!(some_bool.load(Ordering::SeqCst), false); /// ``` #[inline] pub const fn get_mut(&mut self) -> &mut bool { // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *self.as_ptr() } } } // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 const_fn! { const_if: #[cfg(not(portable_atomic_no_const_transmute))]; /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are /// concurrently accessing the atomic data. /// /// This is `const fn` on Rust 1.56+. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicBool; /// /// let some_bool = AtomicBool::new(true); /// assert_eq!(some_bool.into_inner(), true); /// ``` #[inline] pub const fn into_inner(self) -> bool { // SAFETY: AtomicBool and u8 have the same size and in-memory representations, // so they can be safely transmuted. // (const UnsafeCell::into_inner is unstable) unsafe { core::mem::transmute::(self) != 0 } } } /// Loads a value from the bool. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Release`] or [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); /// /// assert_eq!(some_bool.load(Ordering::Relaxed), true); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn load(&self, order: Ordering) -> bool { self.as_atomic_u8().load(order) != 0 } /// Stores a value into the bool. /// /// `store` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Acquire`] or [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); /// /// some_bool.store(false, Ordering::Relaxed); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn store(&self, val: bool, order: Ordering) { self.as_atomic_u8().store(val as u8, order); } cfg_has_atomic_cas_or_amo32! { /// Stores a value into the bool, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); /// /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn swap(&self, val: bool, order: Ordering) -> bool { #[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64"))] { // See https://github.com/rust-lang/rust/pull/114034 for details. // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L249 // https://godbolt.org/z/ofbGGdx44 if val { self.fetch_or(true, order) } else { self.fetch_and(false, order) } } #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64")))] { self.as_atomic_u8().swap(val as u8, order) != 0 } } /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// The return value is a result indicating whether the new value was written and containing /// the previous value. On success this value is guaranteed to be equal to `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); /// /// assert_eq!( /// some_bool.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed), /// Ok(true) /// ); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// /// assert_eq!( /// some_bool.compare_exchange(true, true, Ordering::SeqCst, Ordering::Acquire), /// Err(false) /// ); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// ``` #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))] #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange( &self, current: bool, new: bool, success: Ordering, failure: Ordering, ) -> Result { #[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64"))] { // See https://github.com/rust-lang/rust/pull/114034 for details. // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L249 // https://godbolt.org/z/ofbGGdx44 crate::utils::assert_compare_exchange_ordering(success, failure); let order = crate::utils::upgrade_success_ordering(success, failure); let old = if current == new { // This is a no-op, but we still need to perform the operation // for memory ordering reasons. self.fetch_or(false, order) } else { // This sets the value to the new one and returns the old one. self.swap(new, order) }; if old == current { Ok(old) } else { Err(old) } } #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64")))] { match self.as_atomic_u8().compare_exchange(current as u8, new as u8, success, failure) { Ok(x) => Ok(x != 0), Err(x) => Err(x != 0), } } } /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// Unlike [`AtomicBool::compare_exchange`], this function is allowed to spuriously fail even when the /// comparison succeeds, which can result in more efficient code on some platforms. The /// return value is a result indicating whether the new value was written and containing the /// previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let val = AtomicBool::new(false); /// /// let new = true; /// let mut old = val.load(Ordering::Relaxed); /// loop { /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { /// Ok(_) => break, /// Err(x) => old = x, /// } /// } /// ``` #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))] #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange_weak( &self, current: bool, new: bool, success: Ordering, failure: Ordering, ) -> Result { #[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64"))] { // See https://github.com/rust-lang/rust/pull/114034 for details. // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L249 // https://godbolt.org/z/ofbGGdx44 self.compare_exchange(current, new, success, failure) } #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64")))] { match self .as_atomic_u8() .compare_exchange_weak(current as u8, new as u8, success, failure) { Ok(x) => Ok(x != 0), Err(x) => Err(x != 0), } } } /// Logical "and" with a boolean value. /// /// Performs a logical "and" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Returns the previous value. /// /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { self.as_atomic_u8().fetch_and(val as u8, order) != 0 } /// Logical "and" with a boolean value. /// /// Performs a logical "and" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Unlike `fetch_and`, this does not return the previous value. /// /// `and` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This function may generate more efficient code than `fetch_and` on some platforms. /// /// - x86/x86_64: `lock and` instead of `cmpxchg` loop /// - MSP430: `and` instead of disabling interrupts /// /// Note: On x86/x86_64, the use of either function should not usually /// affect the generated code, because LLVM can properly optimize the case /// where the result is unused. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// foo.and(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(true); /// foo.and(true, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); /// foo.and(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn and(&self, val: bool, order: Ordering) { self.as_atomic_u8().and(val as u8, order); } /// Logical "nand" with a boolean value. /// /// Performs a logical "nand" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Returns the previous value. /// /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L973-L985 if val { // !(x & true) == !x // We must invert the bool. self.fetch_xor(true, order) } else { // !(x & false) == true // We must set the bool to true. self.swap(true, order) } } /// Logical "or" with a boolean value. /// /// Performs a logical "or" operation on the current value and the argument `val`, and sets the /// new value to the result. /// /// Returns the previous value. /// /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { self.as_atomic_u8().fetch_or(val as u8, order) != 0 } /// Logical "or" with a boolean value. /// /// Performs a logical "or" operation on the current value and the argument `val`, and sets the /// new value to the result. /// /// Unlike `fetch_or`, this does not return the previous value. /// /// `or` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This function may generate more efficient code than `fetch_or` on some platforms. /// /// - x86/x86_64: `lock or` instead of `cmpxchg` loop /// - MSP430: `bis` instead of disabling interrupts /// /// Note: On x86/x86_64, the use of either function should not usually /// affect the generated code, because LLVM can properly optimize the case /// where the result is unused. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// foo.or(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// foo.or(true, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); /// foo.or(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn or(&self, val: bool, order: Ordering) { self.as_atomic_u8().or(val as u8, order); } /// Logical "xor" with a boolean value. /// /// Performs a logical "xor" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Returns the previous value. /// /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { self.as_atomic_u8().fetch_xor(val as u8, order) != 0 } /// Logical "xor" with a boolean value. /// /// Performs a logical "xor" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Unlike `fetch_xor`, this does not return the previous value. /// /// `xor` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This function may generate more efficient code than `fetch_xor` on some platforms. /// /// - x86/x86_64: `lock xor` instead of `cmpxchg` loop /// - MSP430: `xor` instead of disabling interrupts /// /// Note: On x86/x86_64, the use of either function should not usually /// affect the generated code, because LLVM can properly optimize the case /// where the result is unused. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// foo.xor(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// foo.xor(true, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// foo.xor(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn xor(&self, val: bool, order: Ordering) { self.as_atomic_u8().xor(val as u8, order); } /// Logical "not" with a boolean value. /// /// Performs a logical "not" operation on the current value, and sets /// the new value to the result. /// /// Returns the previous value. /// /// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_not(Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_not(Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_not(&self, order: Ordering) -> bool { self.fetch_xor(true, order) } /// Logical "not" with a boolean value. /// /// Performs a logical "not" operation on the current value, and sets /// the new value to the result. /// /// Unlike `fetch_not`, this does not return the previous value. /// /// `not` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This function may generate more efficient code than `fetch_not` on some platforms. /// /// - x86/x86_64: `lock xor` instead of `cmpxchg` loop /// - MSP430: `xor` instead of disabling interrupts /// /// Note: On x86/x86_64, the use of either function should not usually /// affect the generated code, because LLVM can properly optimize the case /// where the result is unused. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// foo.not(Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// foo.not(Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn not(&self, order: Ordering) { self.xor(true, order); } /// Fetches the value, and applies a function to it that returns an optional /// new value. Returns a `Result` of `Ok(previous_value)` if the function /// returned `Some(_)`, else `Err(previous_value)`. /// /// Note: This may call the function multiple times if the value has been /// changed from other threads in the meantime, as long as the function /// returns `Some(_)`, but the function will have been applied only once to /// the stored value. /// /// `fetch_update` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. The first describes the required ordering for /// when the operation finally succeeds while the second describes the /// required ordering for loads. These correspond to the success and failure /// orderings of [`compare_exchange`](Self::compare_exchange) respectively. /// /// Using [`Acquire`] as success ordering makes the store part of this /// operation [`Relaxed`], and using [`Release`] makes the final successful /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], /// [`Acquire`] or [`Relaxed`]. /// /// # Considerations /// /// This method is not magic; it is not provided by the hardware. /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak), /// and suffers from the same drawbacks. /// In particular, this method will not circumvent the [ABA Problem]. /// /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem /// /// # Panics /// /// Panics if `fetch_order` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let x = AtomicBool::new(false); /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false)); /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false)); /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true)); /// assert_eq!(x.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, mut f: F, ) -> Result where F: FnMut(bool) -> Option, { let mut prev = self.load(fetch_order); while let Some(next) = f(prev) { match self.compare_exchange_weak(prev, next, set_order, fetch_order) { x @ Ok(_) => return x, Err(next_prev) => prev = next_prev, } } Err(prev) } } // cfg_has_atomic_cas_or_amo32! const_fn! { // This function is actually `const fn`-compatible on Rust 1.32+, // but makes `const fn` only on Rust 1.58+ to match other atomic types. const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; /// Returns a mutable pointer to the underlying [`bool`]. /// /// Returning an `*mut` pointer from a shared reference to this atomic is /// safe because the atomic types work with interior mutability. Any use of /// the returned raw pointer requires an `unsafe` block and has to uphold /// the safety requirements. If there is concurrent access, note the following /// additional safety requirements: /// /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent /// operations on it must be atomic. /// - Otherwise, any concurrent operations on it must be compatible with /// operations performed by this atomic type. /// /// This is `const fn` on Rust 1.58+. #[inline] pub const fn as_ptr(&self) -> *mut bool { self.v.get() as *mut bool } } #[inline(always)] fn as_atomic_u8(&self) -> &imp::AtomicU8 { // SAFETY: AtomicBool and imp::AtomicU8 have the same layout, // and both access data in the same way. unsafe { &*(self as *const Self as *const imp::AtomicU8) } } } // See https://github.com/taiki-e/portable-atomic/issues/180 #[cfg(not(feature = "require-cas"))] cfg_no_atomic_cas! { #[doc(hidden)] #[allow(unused_variables, clippy::unused_self, clippy::extra_unused_lifetimes)] impl<'a> AtomicBool { cfg_no_atomic_cas_or_amo32! { #[inline] pub fn swap(&self, val: bool, order: Ordering) -> bool where &'a Self: HasSwap, { unimplemented!() } #[inline] pub fn compare_exchange( &self, current: bool, new: bool, success: Ordering, failure: Ordering, ) -> Result where &'a Self: HasCompareExchange, { unimplemented!() } #[inline] pub fn compare_exchange_weak( &self, current: bool, new: bool, success: Ordering, failure: Ordering, ) -> Result where &'a Self: HasCompareExchangeWeak, { unimplemented!() } #[inline] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool where &'a Self: HasFetchAnd, { unimplemented!() } #[inline] pub fn and(&self, val: bool, order: Ordering) where &'a Self: HasAnd, { unimplemented!() } #[inline] pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool where &'a Self: HasFetchNand, { unimplemented!() } #[inline] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool where &'a Self: HasFetchOr, { unimplemented!() } #[inline] pub fn or(&self, val: bool, order: Ordering) where &'a Self: HasOr, { unimplemented!() } #[inline] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool where &'a Self: HasFetchXor, { unimplemented!() } #[inline] pub fn xor(&self, val: bool, order: Ordering) where &'a Self: HasXor, { unimplemented!() } #[inline] pub fn fetch_not(&self, order: Ordering) -> bool where &'a Self: HasFetchNot, { unimplemented!() } #[inline] pub fn not(&self, order: Ordering) where &'a Self: HasNot, { unimplemented!() } #[inline] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, f: F, ) -> Result where F: FnMut(bool) -> Option, &'a Self: HasFetchUpdate, { unimplemented!() } } // cfg_no_atomic_cas_or_amo32! } } // cfg_no_atomic_cas! } // cfg_has_atomic_8! cfg_has_atomic_ptr! { /// A raw pointer type which can be safely shared between threads. /// /// This type has the same in-memory representation as a `*mut T`. /// /// If the compiler and the platform support atomic loads and stores of pointers, /// this type is a wrapper for the standard library's /// [`AtomicPtr`](core::sync::atomic::AtomicPtr). If the platform supports it /// but the compiler does not, atomic operations are implemented using inline /// assembly. // We can use #[repr(transparent)] here, but #[repr(C, align(N))] // will show clearer docs. #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] #[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] #[cfg_attr(target_pointer_width = "128", repr(C, align(16)))] pub struct AtomicPtr { inner: imp::AtomicPtr, } impl Default for AtomicPtr { /// Creates a null `AtomicPtr`. #[inline] fn default() -> Self { Self::new(ptr::null_mut()) } } impl From<*mut T> for AtomicPtr { #[inline] fn from(p: *mut T) -> Self { Self::new(p) } } impl fmt::Debug for AtomicPtr { #[inline] // fmt is not hot path, but #[inline] on fmt seems to still be useful: https://github.com/rust-lang/rust/pull/117727 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L2188 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f) } } impl fmt::Pointer for AtomicPtr { #[inline] // fmt is not hot path, but #[inline] on fmt seems to still be useful: https://github.com/rust-lang/rust/pull/117727 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L2188 fmt::Pointer::fmt(&self.load(Ordering::Relaxed), f) } } // UnwindSafe is implicitly implemented. #[cfg(not(portable_atomic_no_core_unwind_safe))] impl core::panic::RefUnwindSafe for AtomicPtr {} #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))] impl std::panic::RefUnwindSafe for AtomicPtr {} impl AtomicPtr { /// Creates a new `AtomicPtr`. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicPtr; /// /// let ptr = &mut 5; /// let atomic_ptr = AtomicPtr::new(ptr); /// ``` #[inline] #[must_use] pub const fn new(p: *mut T) -> Self { static_assert_layout!(AtomicPtr<()>, *mut ()); Self { inner: imp::AtomicPtr::new(p) } } // TODO: update docs based on https://github.com/rust-lang/rust/pull/116762 const_fn! { const_if: #[cfg(not(portable_atomic_no_const_mut_refs))]; /// Creates a new `AtomicPtr` from a pointer. /// /// This is `const fn` on Rust 1.83+. /// /// # Safety /// /// * `ptr` must be aligned to `align_of::>()` (note that on some platforms this /// can be bigger than `align_of::<*mut T>()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. /// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value /// behind `ptr` must have a happens-before relationship with atomic accesses via the returned /// value (or vice-versa). /// * In other words, time periods where the value is accessed atomically may not overlap /// with periods where the value is accessed non-atomically. /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done /// from the same thread. /// * If this atomic type is *not* lock-free: /// * Any accesses to the value behind `ptr` must have a happens-before relationship /// with accesses via the returned value (or vice-versa). /// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must /// be compatible with operations performed by this atomic type. /// * This method must not be used to create overlapping or mixed-size atomic accesses, as /// these are not supported by the memory model. /// /// [valid]: core::ptr#safety #[inline] #[must_use] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicPtr; /// /// let is_lock_free = AtomicPtr::<()>::is_lock_free(); /// ``` #[inline] #[must_use] pub fn is_lock_free() -> bool { >::is_lock_free() } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// **Note:** If the atomic operation relies on dynamic CPU feature detection, /// this type may be lock-free even if the function returns false. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicPtr; /// /// const IS_ALWAYS_LOCK_FREE: bool = AtomicPtr::<()>::is_always_lock_free(); /// ``` #[inline] #[must_use] pub const fn is_always_lock_free() -> bool { >::IS_ALWAYS_LOCK_FREE } #[cfg(test)] const IS_ALWAYS_LOCK_FREE: bool = Self::is_always_lock_free(); const_fn! { const_if: #[cfg(not(portable_atomic_no_const_mut_refs))]; /// Returns a mutable reference to the underlying pointer. /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. /// /// This is `const fn` on Rust 1.83+. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let mut data = 10; /// let mut atomic_ptr = AtomicPtr::new(&mut data); /// let mut other_data = 5; /// *atomic_ptr.get_mut() = &mut other_data; /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5); /// ``` #[inline] pub const fn get_mut(&mut self) -> &mut *mut T { // SAFETY: the mutable reference guarantees unique ownership. // (core::sync::atomic::Atomic*::get_mut is not const yet) unsafe { &mut *self.as_ptr() } } } // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 const_fn! { const_if: #[cfg(not(portable_atomic_no_const_transmute))]; /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are /// concurrently accessing the atomic data. /// /// This is `const fn` on Rust 1.56+. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicPtr; /// /// let mut data = 5; /// let atomic_ptr = AtomicPtr::new(&mut data); /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5); /// ``` #[inline] pub const fn into_inner(self) -> *mut T { // SAFETY: AtomicPtr and *mut T have the same size and in-memory representations, // so they can be safely transmuted. // (const UnsafeCell::into_inner is unstable) unsafe { core::mem::transmute(self) } } } /// Loads a value from the pointer. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Release`] or [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let value = some_ptr.load(Ordering::Relaxed); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn load(&self, order: Ordering) -> *mut T { self.inner.load(order) } /// Stores a value into the pointer. /// /// `store` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Acquire`] or [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let other_ptr = &mut 10; /// /// some_ptr.store(other_ptr, Ordering::Relaxed); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn store(&self, ptr: *mut T, order: Ordering) { self.inner.store(ptr, order); } cfg_has_atomic_cas_or_amo32! { /// Stores a value into the pointer, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let other_ptr = &mut 10; /// /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { self.inner.swap(ptr, order) } cfg_has_atomic_cas! { /// Stores a value into the pointer if the current value is the same as the `current` value. /// /// The return value is a result indicating whether the new value was written and containing /// the previous value. On success this value is guaranteed to be equal to `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let other_ptr = &mut 10; /// /// let value = some_ptr.compare_exchange(ptr, other_ptr, Ordering::SeqCst, Ordering::Relaxed); /// ``` #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))] #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { self.inner.compare_exchange(current, new, success, failure) } /// Stores a value into the pointer if the current value is the same as the `current` value. /// /// Unlike [`AtomicPtr::compare_exchange`], this function is allowed to spuriously fail even when the /// comparison succeeds, which can result in more efficient code on some platforms. The /// return value is a result indicating whether the new value was written and containing the /// previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let some_ptr = AtomicPtr::new(&mut 5); /// /// let new = &mut 10; /// let mut old = some_ptr.load(Ordering::Relaxed); /// loop { /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { /// Ok(_) => break, /// Err(x) => old = x, /// } /// } /// ``` #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))] #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange_weak( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { self.inner.compare_exchange_weak(current, new, success, failure) } /// Fetches the value, and applies a function to it that returns an optional /// new value. Returns a `Result` of `Ok(previous_value)` if the function /// returned `Some(_)`, else `Err(previous_value)`. /// /// Note: This may call the function multiple times if the value has been /// changed from other threads in the meantime, as long as the function /// returns `Some(_)`, but the function will have been applied only once to /// the stored value. /// /// `fetch_update` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. The first describes the required ordering for /// when the operation finally succeeds while the second describes the /// required ordering for loads. These correspond to the success and failure /// orderings of [`compare_exchange`](Self::compare_exchange) respectively. /// /// Using [`Acquire`] as success ordering makes the store part of this /// operation [`Relaxed`], and using [`Release`] makes the final successful /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], /// [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `fetch_order` is [`Release`], [`AcqRel`]. /// /// # Considerations /// /// This method is not magic; it is not provided by the hardware. /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak), /// and suffers from the same drawbacks. /// In particular, this method will not circumvent the [ABA Problem]. /// /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr: *mut _ = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let new: *mut _ = &mut 10; /// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr)); /// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { /// if x == ptr { /// Some(new) /// } else { /// None /// } /// }); /// assert_eq!(result, Ok(ptr)); /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, mut f: F, ) -> Result<*mut T, *mut T> where F: FnMut(*mut T) -> Option<*mut T>, { let mut prev = self.load(fetch_order); while let Some(next) = f(prev) { match self.compare_exchange_weak(prev, next, set_order, fetch_order) { x @ Ok(_) => return x, Err(next_prev) => prev = next_prev, } } Err(prev) } #[cfg(miri)] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn fetch_update_(&self, order: Ordering, mut f: F) -> *mut T where F: FnMut(*mut T) -> *mut T, { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = self.load(Ordering::Relaxed); loop { let next = f(prev); match self.compare_exchange_weak(prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(next_prev) => prev = next_prev, } } } } // cfg_has_atomic_cas! /// Offsets the pointer's address by adding `val` (in units of `T`), /// returning the previous pointer. /// /// This is equivalent to using [`wrapping_add`] to atomically perform the /// equivalent of `ptr = ptr.wrapping_add(val);`. /// /// This method operates in units of `T`, which means that it cannot be used /// to offset the pointer by an amount which is not a multiple of /// `size_of::()`. This can sometimes be inconvenient, as you may want to /// work with a deliberately misaligned pointer. In such cases, you may use /// the [`fetch_byte_add`](Self::fetch_byte_add) method instead. /// /// `fetch_ptr_add` takes an [`Ordering`] argument which describes the /// memory ordering of this operation. All ordering modes are possible. Note /// that using [`Acquire`] makes the store part of this operation /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. /// /// [`wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::::new(core::ptr::null_mut()); /// assert_eq!(atom.fetch_ptr_add(1, Ordering::Relaxed).addr(), 0); /// // Note: units of `size_of::()`. /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 8); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_add(val.wrapping_mul(core::mem::size_of::()), order) } /// Offsets the pointer's address by subtracting `val` (in units of `T`), /// returning the previous pointer. /// /// This is equivalent to using [`wrapping_sub`] to atomically perform the /// equivalent of `ptr = ptr.wrapping_sub(val);`. /// /// This method operates in units of `T`, which means that it cannot be used /// to offset the pointer by an amount which is not a multiple of /// `size_of::()`. This can sometimes be inconvenient, as you may want to /// work with a deliberately misaligned pointer. In such cases, you may use /// the [`fetch_byte_sub`](Self::fetch_byte_sub) method instead. /// /// `fetch_ptr_sub` takes an [`Ordering`] argument which describes the memory /// ordering of this operation. All ordering modes are possible. Note that /// using [`Acquire`] makes the store part of this operation [`Relaxed`], /// and using [`Release`] makes the load part [`Relaxed`]. /// /// [`wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let array = [1i32, 2i32]; /// let atom = AtomicPtr::new(array.as_ptr().wrapping_add(1) as *mut _); /// /// assert!(core::ptr::eq(atom.fetch_ptr_sub(1, Ordering::Relaxed), &array[1])); /// assert!(core::ptr::eq(atom.load(Ordering::Relaxed), &array[0])); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_sub(val.wrapping_mul(core::mem::size_of::()), order) } /// Offsets the pointer's address by adding `val` *bytes*, returning the /// previous pointer. /// /// This is equivalent to using [`wrapping_add`] and [`cast`] to atomically /// perform `ptr = ptr.cast::().wrapping_add(val).cast::()`. /// /// `fetch_byte_add` takes an [`Ordering`] argument which describes the /// memory ordering of this operation. All ordering modes are possible. Note /// that using [`Acquire`] makes the store part of this operation /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. /// /// [`wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add /// [`cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::::new(core::ptr::null_mut()); /// assert_eq!(atom.fetch_byte_add(1, Ordering::Relaxed).addr(), 0); /// // Note: in units of bytes, not `size_of::()`. /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 1); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| x.with_addr(x.addr().wrapping_add(val))) } #[cfg(not(miri))] { crate::utils::ptr::with_exposed_provenance_mut( self.as_atomic_usize().fetch_add(val, order) ) } } /// Offsets the pointer's address by subtracting `val` *bytes*, returning the /// previous pointer. /// /// This is equivalent to using [`wrapping_sub`] and [`cast`] to atomically /// perform `ptr = ptr.cast::().wrapping_sub(val).cast::()`. /// /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the /// memory ordering of this operation. All ordering modes are possible. Note /// that using [`Acquire`] makes the store part of this operation /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. /// /// [`wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub /// [`cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let atom = AtomicPtr::::new(sptr::invalid_mut(1)); /// assert_eq!(atom.fetch_byte_sub(1, Ordering::Relaxed).addr(), 1); /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 0); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| x.with_addr(x.addr().wrapping_sub(val))) } #[cfg(not(miri))] { crate::utils::ptr::with_exposed_provenance_mut( self.as_atomic_usize().fetch_sub(val, order) ) } } /// Performs a bitwise "or" operation on the address of the current pointer, /// and the argument `val`, and stores a pointer with provenance of the /// current pointer and the resulting address. /// /// This is equivalent to using [`map_addr`] to atomically perform /// `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged /// pointer schemes to atomically set tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the /// stored value without losing provenance, you may use [`map_addr`]. For /// example: `a.fetch_or(val).map_addr(|a| a | val)`. /// /// `fetch_or` takes an [`Ordering`] argument which describes the memory /// ordering of this operation. All ordering modes are possible. Note that /// using [`Acquire`] makes the store part of this operation [`Relaxed`], /// and using [`Release`] makes the load part [`Relaxed`]. /// /// This API and its claimed semantics are part of the Strict Provenance /// experiment, see the [module documentation for `ptr`][core::ptr] for /// details. /// /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; /// /// let atom = AtomicPtr::::new(pointer); /// // Tag the bottom bit of the pointer. /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 0); /// // Extract and untag. /// let tagged = atom.load(Ordering::Relaxed); /// assert_eq!(tagged.addr() & 1, 1); /// assert_eq!(tagged.map_addr(|p| p & !1), pointer); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| x.with_addr(x.addr() | val)) } #[cfg(not(miri))] { crate::utils::ptr::with_exposed_provenance_mut( self.as_atomic_usize().fetch_or(val, order) ) } } /// Performs a bitwise "and" operation on the address of the current /// pointer, and the argument `val`, and stores a pointer with provenance of /// the current pointer and the resulting address. /// /// This is equivalent to using [`map_addr`] to atomically perform /// `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged /// pointer schemes to atomically unset tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the /// stored value without losing provenance, you may use [`map_addr`]. For /// example: `a.fetch_and(val).map_addr(|a| a & val)`. /// /// `fetch_and` takes an [`Ordering`] argument which describes the memory /// ordering of this operation. All ordering modes are possible. Note that /// using [`Acquire`] makes the store part of this operation [`Relaxed`], /// and using [`Release`] makes the load part [`Relaxed`]. /// /// This API and its claimed semantics are part of the Strict Provenance /// experiment, see the [module documentation for `ptr`][core::ptr] for /// details. /// /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; /// // A tagged pointer /// let atom = AtomicPtr::::new(pointer.map_addr(|a| a | 1)); /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 1); /// // Untag, and extract the previously tagged pointer. /// let untagged = atom.fetch_and(!1, Ordering::Relaxed).map_addr(|a| a & !1); /// assert_eq!(untagged, pointer); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| x.with_addr(x.addr() & val)) } #[cfg(not(miri))] { crate::utils::ptr::with_exposed_provenance_mut( self.as_atomic_usize().fetch_and(val, order) ) } } /// Performs a bitwise "xor" operation on the address of the current /// pointer, and the argument `val`, and stores a pointer with provenance of /// the current pointer and the resulting address. /// /// This is equivalent to using [`map_addr`] to atomically perform /// `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged /// pointer schemes to atomically toggle tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the /// stored value without losing provenance, you may use [`map_addr`]. For /// example: `a.fetch_xor(val).map_addr(|a| a ^ val)`. /// /// `fetch_xor` takes an [`Ordering`] argument which describes the memory /// ordering of this operation. All ordering modes are possible. Note that /// using [`Acquire`] makes the store part of this operation [`Relaxed`], /// and using [`Release`] makes the load part [`Relaxed`]. /// /// This API and its claimed semantics are part of the Strict Provenance /// experiment, see the [module documentation for `ptr`][core::ptr] for /// details. /// /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; /// let atom = AtomicPtr::::new(pointer); /// /// // Toggle a tag bit on the pointer. /// atom.fetch_xor(1, Ordering::Relaxed); /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| x.with_addr(x.addr() ^ val)) } #[cfg(not(miri))] { crate::utils::ptr::with_exposed_provenance_mut( self.as_atomic_usize().fetch_xor(val, order) ) } } /// Sets the bit at the specified bit-position to 1. /// /// Returns `true` if the specified bit was previously set to 1. /// /// `bit_set` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This corresponds to x86's `lock bts`, and the implementation calls them on x86/x86_64. /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; /// /// let atom = AtomicPtr::::new(pointer); /// // Tag the bottom bit of the pointer. /// assert!(!atom.bit_set(0, Ordering::Relaxed)); /// // Extract and untag. /// let tagged = atom.load(Ordering::Relaxed); /// assert_eq!(tagged.addr() & 1, 1); /// assert_eq!(tagged.map_addr(|p| p & !1), pointer); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_set(&self, bit: u32, order: Ordering) -> bool { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); self.fetch_or(mask, order).addr() & mask != 0 } #[cfg(not(miri))] { self.as_atomic_usize().bit_set(bit, order) } } /// Clears the bit at the specified bit-position to 1. /// /// Returns `true` if the specified bit was previously set to 1. /// /// `bit_clear` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This corresponds to x86's `lock btr`, and the implementation calls them on x86/x86_64. /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; /// // A tagged pointer /// let atom = AtomicPtr::::new(pointer.map_addr(|a| a | 1)); /// assert!(atom.bit_set(0, Ordering::Relaxed)); /// // Untag /// assert!(atom.bit_clear(0, Ordering::Relaxed)); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); self.fetch_and(!mask, order).addr() & mask != 0 } #[cfg(not(miri))] { self.as_atomic_usize().bit_clear(bit, order) } } /// Toggles the bit at the specified bit-position. /// /// Returns `true` if the specified bit was previously set to 1. /// /// `bit_toggle` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This corresponds to x86's `lock btc`, and the implementation calls them on x86/x86_64. /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let pointer = &mut 3i64 as *mut i64; /// let atom = AtomicPtr::::new(pointer); /// /// // Toggle a tag bit on the pointer. /// atom.bit_toggle(0, Ordering::Relaxed); /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); self.fetch_xor(mask, order).addr() & mask != 0 } #[cfg(not(miri))] { self.as_atomic_usize().bit_toggle(bit, order) } } #[cfg(not(miri))] #[inline(always)] fn as_atomic_usize(&self) -> &AtomicUsize { static_assert!( core::mem::size_of::>() == core::mem::size_of::() ); static_assert!( core::mem::align_of::>() == core::mem::align_of::() ); // SAFETY: AtomicPtr and AtomicUsize have the same layout, // and both access data in the same way. unsafe { &*(self as *const Self as *const AtomicUsize) } } } // cfg_has_atomic_cas_or_amo32! const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; /// Returns a mutable pointer to the underlying pointer. /// /// Returning an `*mut` pointer from a shared reference to this atomic is /// safe because the atomic types work with interior mutability. Any use of /// the returned raw pointer requires an `unsafe` block and has to uphold /// the safety requirements. If there is concurrent access, note the following /// additional safety requirements: /// /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent /// operations on it must be atomic. /// - Otherwise, any concurrent operations on it must be compatible with /// operations performed by this atomic type. /// /// This is `const fn` on Rust 1.58+. #[inline] pub const fn as_ptr(&self) -> *mut *mut T { self.inner.as_ptr() } } } // See https://github.com/taiki-e/portable-atomic/issues/180 #[cfg(not(feature = "require-cas"))] cfg_no_atomic_cas! { #[doc(hidden)] #[allow(unused_variables, clippy::unused_self, clippy::extra_unused_lifetimes)] impl<'a, T: 'a> AtomicPtr { cfg_no_atomic_cas_or_amo32! { #[inline] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T where &'a Self: HasSwap, { unimplemented!() } } // cfg_no_atomic_cas_or_amo32! #[inline] pub fn compare_exchange( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> where &'a Self: HasCompareExchange, { unimplemented!() } #[inline] pub fn compare_exchange_weak( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> where &'a Self: HasCompareExchangeWeak, { unimplemented!() } #[inline] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, f: F, ) -> Result<*mut T, *mut T> where F: FnMut(*mut T) -> Option<*mut T>, &'a Self: HasFetchUpdate, { unimplemented!() } cfg_no_atomic_cas_or_amo32! { #[inline] pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T where &'a Self: HasFetchPtrAdd, { unimplemented!() } #[inline] pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T where &'a Self: HasFetchPtrSub, { unimplemented!() } #[inline] pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T where &'a Self: HasFetchByteAdd, { unimplemented!() } #[inline] pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T where &'a Self: HasFetchByteSub, { unimplemented!() } #[inline] pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T where &'a Self: HasFetchOr, { unimplemented!() } #[inline] pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T where &'a Self: HasFetchAnd, { unimplemented!() } #[inline] pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T where &'a Self: HasFetchXor, { unimplemented!() } #[inline] pub fn bit_set(&self, bit: u32, order: Ordering) -> bool where &'a Self: HasBitSet, { unimplemented!() } #[inline] pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool where &'a Self: HasBitClear, { unimplemented!() } #[inline] pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool where &'a Self: HasBitToggle, { unimplemented!() } } // cfg_no_atomic_cas_or_amo32! } } // cfg_no_atomic_cas! } // cfg_has_atomic_ptr! macro_rules! atomic_int { // Atomic{I,U}* impls ($atomic_type:ident, $int_type:ident, $align:literal, $cfg_has_atomic_cas_or_amo32_or_8:ident, $cfg_no_atomic_cas_or_amo32_or_8:ident $(, #[$cfg_float:meta] $atomic_float_type:ident, $float_type:ident)? ) => { doc_comment! { concat!("An integer type which can be safely shared between threads. This type has the same in-memory representation as the underlying integer type, [`", stringify!($int_type), "`]. If the compiler and the platform support atomic loads and stores of [`", stringify!($int_type), "`], this type is a wrapper for the standard library's `", stringify!($atomic_type), "`. If the platform supports it but the compiler does not, atomic operations are implemented using inline assembly. Otherwise synchronizes using global locks. You can call [`", stringify!($atomic_type), "::is_lock_free()`] to check whether atomic instructions or locks will be used. " ), // We can use #[repr(transparent)] here, but #[repr(C, align(N))] // will show clearer docs. #[repr(C, align($align))] pub struct $atomic_type { inner: imp::$atomic_type, } } impl Default for $atomic_type { #[inline] fn default() -> Self { Self::new($int_type::default()) } } impl From<$int_type> for $atomic_type { #[inline] fn from(v: $int_type) -> Self { Self::new(v) } } // UnwindSafe is implicitly implemented. #[cfg(not(portable_atomic_no_core_unwind_safe))] impl core::panic::RefUnwindSafe for $atomic_type {} #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))] impl std::panic::RefUnwindSafe for $atomic_type {} impl_debug_and_serde!($atomic_type); impl $atomic_type { doc_comment! { concat!( "Creates a new atomic integer. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; let atomic_forty_two = ", stringify!($atomic_type), "::new(42); ```" ), #[inline] #[must_use] pub const fn new(v: $int_type) -> Self { static_assert_layout!($atomic_type, $int_type); Self { inner: imp::$atomic_type::new(v) } } } // TODO: update docs based on https://github.com/rust-lang/rust/pull/116762 #[cfg(not(portable_atomic_no_const_mut_refs))] doc_comment! { concat!("Creates a new reference to an atomic integer from a pointer. This is `const fn` on Rust 1.83+. # Safety * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`). * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value behind `ptr` must have a happens-before relationship with atomic accesses via the returned value (or vice-versa). * In other words, time periods where the value is accessed atomically may not overlap with periods where the value is accessed non-atomically. * This requirement is trivially satisfied if `ptr` is never used non-atomically for the duration of lifetime `'a`. Most use cases should be able to follow this guideline. * This requirement is also trivially satisfied if all accesses (atomic or not) are done from the same thread. * If this atomic type is *not* lock-free: * Any accesses to the value behind `ptr` must have a happens-before relationship with accesses via the returned value (or vice-versa). * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must be compatible with operations performed by this atomic type. * This method must not be used to create overlapping or mixed-size atomic accesses, as these are not supported by the memory model. [valid]: core::ptr#safety"), #[inline] #[must_use] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } } #[cfg(portable_atomic_no_const_mut_refs)] doc_comment! { concat!("Creates a new reference to an atomic integer from a pointer. This is `const fn` on Rust 1.83+. # Safety * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`). * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value behind `ptr` must have a happens-before relationship with atomic accesses via the returned value (or vice-versa). * In other words, time periods where the value is accessed atomically may not overlap with periods where the value is accessed non-atomically. * This requirement is trivially satisfied if `ptr` is never used non-atomically for the duration of lifetime `'a`. Most use cases should be able to follow this guideline. * This requirement is also trivially satisfied if all accesses (atomic or not) are done from the same thread. * If this atomic type is *not* lock-free: * Any accesses to the value behind `ptr` must have a happens-before relationship with accesses via the returned value (or vice-versa). * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must be compatible with operations performed by this atomic type. * This method must not be used to create overlapping or mixed-size atomic accesses, as these are not supported by the memory model. [valid]: core::ptr#safety"), #[inline] #[must_use] pub unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } } doc_comment! { concat!("Returns `true` if operations on values of this type are lock-free. If the compiler or the platform doesn't support the necessary atomic instructions, global locks for every potentially concurrent atomic operation will be used. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; let is_lock_free = ", stringify!($atomic_type), "::is_lock_free(); ```"), #[inline] #[must_use] pub fn is_lock_free() -> bool { ::is_lock_free() } } doc_comment! { concat!("Returns `true` if operations on values of this type are lock-free. If the compiler or the platform doesn't support the necessary atomic instructions, global locks for every potentially concurrent atomic operation will be used. **Note:** If the atomic operation relies on dynamic CPU feature detection, this type may be lock-free even if the function returns false. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; const IS_ALWAYS_LOCK_FREE: bool = ", stringify!($atomic_type), "::is_always_lock_free(); ```"), #[inline] #[must_use] pub const fn is_always_lock_free() -> bool { ::IS_ALWAYS_LOCK_FREE } } #[cfg(test)] const IS_ALWAYS_LOCK_FREE: bool = Self::is_always_lock_free(); #[cfg(not(portable_atomic_no_const_mut_refs))] doc_comment! { concat!("Returns a mutable reference to the underlying integer.\n This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data. This is `const fn` on Rust 1.83+. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let mut some_var = ", stringify!($atomic_type), "::new(10); assert_eq!(*some_var.get_mut(), 10); *some_var.get_mut() = 5; assert_eq!(some_var.load(Ordering::SeqCst), 5); ```"), #[inline] pub const fn get_mut(&mut self) -> &mut $int_type { // SAFETY: the mutable reference guarantees unique ownership. // (core::sync::atomic::Atomic*::get_mut is not const yet) unsafe { &mut *self.as_ptr() } } } #[cfg(portable_atomic_no_const_mut_refs)] doc_comment! { concat!("Returns a mutable reference to the underlying integer.\n This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data. This is `const fn` on Rust 1.83+. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let mut some_var = ", stringify!($atomic_type), "::new(10); assert_eq!(*some_var.get_mut(), 10); *some_var.get_mut() = 5; assert_eq!(some_var.load(Ordering::SeqCst), 5); ```"), #[inline] pub fn get_mut(&mut self) -> &mut $int_type { // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *self.as_ptr() } } } // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 #[cfg(not(portable_atomic_no_const_transmute))] doc_comment! { concat!("Consumes the atomic and returns the contained value. This is safe because passing `self` by value guarantees that no other threads are concurrently accessing the atomic data. This is `const fn` on Rust 1.56+. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!(some_var.into_inner(), 5); ```"), #[inline] pub const fn into_inner(self) -> $int_type { // SAFETY: $atomic_type and $int_type have the same size and in-memory representations, // so they can be safely transmuted. // (const UnsafeCell::into_inner is unstable) unsafe { core::mem::transmute(self) } } } #[cfg(portable_atomic_no_const_transmute)] doc_comment! { concat!("Consumes the atomic and returns the contained value. This is safe because passing `self` by value guarantees that no other threads are concurrently accessing the atomic data. This is `const fn` on Rust 1.56+. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!(some_var.into_inner(), 5); ```"), #[inline] pub fn into_inner(self) -> $int_type { // SAFETY: $atomic_type and $int_type have the same size and in-memory representations, // so they can be safely transmuted. // (const UnsafeCell::into_inner is unstable) unsafe { core::mem::transmute(self) } } } doc_comment! { concat!("Loads a value from the atomic integer. `load` takes an [`Ordering`] argument which describes the memory ordering of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. # Panics Panics if `order` is [`Release`] or [`AcqRel`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!(some_var.load(Ordering::Relaxed), 5); ```"), #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn load(&self, order: Ordering) -> $int_type { self.inner.load(order) } } doc_comment! { concat!("Stores a value into the atomic integer. `store` takes an [`Ordering`] argument which describes the memory ordering of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. # Panics Panics if `order` is [`Acquire`] or [`AcqRel`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let some_var = ", stringify!($atomic_type), "::new(5); some_var.store(10, Ordering::Relaxed); assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn store(&self, val: $int_type, order: Ordering) { self.inner.store(val, order) } } cfg_has_atomic_cas_or_amo32! { $cfg_has_atomic_cas_or_amo32_or_8! { doc_comment! { concat!("Stores a value into the atomic integer, returning the previous value. `swap` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.swap(val, order) } } } // $cfg_has_atomic_cas_or_amo32_or_8! cfg_has_atomic_cas! { doc_comment! { concat!("Stores a value into the atomic integer if the current value is the same as the `current` value. The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to `current`. `compare_exchange` takes two [`Ordering`] arguments to describe the memory ordering of this operation. `success` describes the required ordering for the read-modify-write operation that takes place if the comparison with `current` succeeds. `failure` describes the required ordering for the load operation that takes place when the comparison fails. Using [`Acquire`] as success ordering makes the store part of this operation [`Relaxed`], and using [`Release`] makes the successful load [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. # Panics Panics if `failure` is [`Release`], [`AcqRel`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!( some_var.compare_exchange(5, 10, Ordering::Acquire, Ordering::Relaxed), Ok(5), ); assert_eq!(some_var.load(Ordering::Relaxed), 10); assert_eq!( some_var.compare_exchange(6, 12, Ordering::SeqCst, Ordering::Acquire), Err(10), ); assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))] #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.inner.compare_exchange(current, new, success, failure) } } doc_comment! { concat!("Stores a value into the atomic integer if the current value is the same as the `current` value. Unlike [`compare_exchange`](Self::compare_exchange) this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value. `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory ordering of this operation. `success` describes the required ordering for the read-modify-write operation that takes place if the comparison with `current` succeeds. `failure` describes the required ordering for the load operation that takes place when the comparison fails. Using [`Acquire`] as success ordering makes the store part of this operation [`Relaxed`], and using [`Release`] makes the successful load [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. # Panics Panics if `failure` is [`Release`], [`AcqRel`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let val = ", stringify!($atomic_type), "::new(4); let mut old = val.load(Ordering::Relaxed); loop { let new = old * 2; match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { Ok(_) => break, Err(x) => old = x, } } ```"), #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))] #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.inner.compare_exchange_weak(current, new, success, failure) } } } // cfg_has_atomic_cas! $cfg_has_atomic_cas_or_amo32_or_8! { doc_comment! { concat!("Adds to the current value, returning the previous value. This operation wraps around on overflow. `fetch_add` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0); assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_add(val, order) } } doc_comment! { concat!("Adds to the current value. This operation wraps around on overflow. Unlike `fetch_add`, this does not return the previous value. `add` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_add` on some platforms. - MSP430: `add` instead of disabling interrupts ({8,16}-bit atomics) # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0); foo.add(10, Ordering::SeqCst); assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn add(&self, val: $int_type, order: Ordering) { self.inner.add(val, order); } } doc_comment! { concat!("Subtracts from the current value, returning the previous value. This operation wraps around on overflow. `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(20); assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20); assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_sub(val, order) } } doc_comment! { concat!("Subtracts from the current value. This operation wraps around on overflow. Unlike `fetch_sub`, this does not return the previous value. `sub` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_sub` on some platforms. - MSP430: `sub` instead of disabling interrupts ({8,16}-bit atomics) # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(20); foo.sub(10, Ordering::SeqCst); assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn sub(&self, val: $int_type, order: Ordering) { self.inner.sub(val, order); } } } // $cfg_has_atomic_cas_or_amo32_or_8! doc_comment! { concat!("Bitwise \"and\" with the current value. Performs a bitwise \"and\" operation on the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_and` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b100001); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_and(val, order) } } doc_comment! { concat!("Bitwise \"and\" with the current value. Performs a bitwise \"and\" operation on the current value and the argument `val`, and sets the new value to the result. Unlike `fetch_and`, this does not return the previous value. `and` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_and` on some platforms. - x86/x86_64: `lock and` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) - MSP430: `and` instead of disabling interrupts ({8,16}-bit atomics) Note: On x86/x86_64, the use of either function should not usually affect the generated code, because LLVM can properly optimize the case where the result is unused. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b100001); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn and(&self, val: $int_type, order: Ordering) { self.inner.and(val, order); } } cfg_has_atomic_cas! { doc_comment! { concat!("Bitwise \"nand\" with the current value. Performs a bitwise \"nand\" operation on the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0x13); assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13); assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_nand(val, order) } } } // cfg_has_atomic_cas! doc_comment! { concat!("Bitwise \"or\" with the current value. Performs a bitwise \"or\" operation on the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_or` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b111111); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_or(val, order) } } doc_comment! { concat!("Bitwise \"or\" with the current value. Performs a bitwise \"or\" operation on the current value and the argument `val`, and sets the new value to the result. Unlike `fetch_or`, this does not return the previous value. `or` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_or` on some platforms. - x86/x86_64: `lock or` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) - MSP430: `or` instead of disabling interrupts ({8,16}-bit atomics) Note: On x86/x86_64, the use of either function should not usually affect the generated code, because LLVM can properly optimize the case where the result is unused. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b111111); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn or(&self, val: $int_type, order: Ordering) { self.inner.or(val, order); } } doc_comment! { concat!("Bitwise \"xor\" with the current value. Performs a bitwise \"xor\" operation on the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b011110); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_xor(val, order) } } doc_comment! { concat!("Bitwise \"xor\" with the current value. Performs a bitwise \"xor\" operation on the current value and the argument `val`, and sets the new value to the result. Unlike `fetch_xor`, this does not return the previous value. `xor` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_xor` on some platforms. - x86/x86_64: `lock xor` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) - MSP430: `xor` instead of disabling interrupts ({8,16}-bit atomics) Note: On x86/x86_64, the use of either function should not usually affect the generated code, because LLVM can properly optimize the case where the result is unused. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); foo.xor(0b110011, Ordering::SeqCst); assert_eq!(foo.load(Ordering::SeqCst), 0b011110); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn xor(&self, val: $int_type, order: Ordering) { self.inner.xor(val, order); } } cfg_has_atomic_cas! { doc_comment! { concat!("Fetches the value, and applies a function to it that returns an optional new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else `Err(previous_value)`. Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns `Some(_)`, but the function will have been applied only once to the stored value. `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. The first describes the required ordering for when the operation finally succeeds while the second describes the required ordering for loads. These correspond to the success and failure orderings of [`compare_exchange`](Self::compare_exchange) respectively. Using [`Acquire`] as success ordering makes the store part of this operation [`Relaxed`], and using [`Release`] makes the final successful load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. # Panics Panics if `fetch_order` is [`Release`], [`AcqRel`]. # Considerations This method is not magic; it is not provided by the hardware. It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak), and suffers from the same drawbacks. In particular, this method will not circumvent the [ABA Problem]. [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let x = ", stringify!($atomic_type), "::new(7); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7)); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7)); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); assert_eq!(x.load(Ordering::SeqCst), 9); ```"), #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, mut f: F, ) -> Result<$int_type, $int_type> where F: FnMut($int_type) -> Option<$int_type>, { let mut prev = self.load(fetch_order); while let Some(next) = f(prev) { match self.compare_exchange_weak(prev, next, set_order, fetch_order) { x @ Ok(_) => return x, Err(next_prev) => prev = next_prev, } } Err(prev) } } } // cfg_has_atomic_cas! $cfg_has_atomic_cas_or_amo32_or_8! { doc_comment! { concat!("Maximum with the current value. Finds the maximum of the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_max` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(23); assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23); assert_eq!(foo.load(Ordering::SeqCst), 42); ``` If you want to obtain the maximum value in one step, you can use the following: ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(23); let bar = 42; let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar); assert!(max_foo == 42); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_max(val, order) } } doc_comment! { concat!("Minimum with the current value. Finds the minimum of the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_min` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(23); assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23); assert_eq!(foo.load(Ordering::Relaxed), 23); assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23); assert_eq!(foo.load(Ordering::Relaxed), 22); ``` If you want to obtain the minimum value in one step, you can use the following: ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(23); let bar = 12; let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar); assert_eq!(min_foo, 12); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_min(val, order) } } } // $cfg_has_atomic_cas_or_amo32_or_8! doc_comment! { concat!("Sets the bit at the specified bit-position to 1. Returns `true` if the specified bit was previously set to 1. `bit_set` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This corresponds to x86's `lock bts`, and the implementation calls them on x86/x86_64. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b0000); assert!(!foo.bit_set(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0001); assert!(foo.bit_set(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0001); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_set(&self, bit: u32, order: Ordering) -> bool { self.inner.bit_set(bit, order) } } doc_comment! { concat!("Clears the bit at the specified bit-position to 1. Returns `true` if the specified bit was previously set to 1. `bit_clear` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This corresponds to x86's `lock btr`, and the implementation calls them on x86/x86_64. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b0001); assert!(foo.bit_clear(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0000); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool { self.inner.bit_clear(bit, order) } } doc_comment! { concat!("Toggles the bit at the specified bit-position. Returns `true` if the specified bit was previously set to 1. `bit_toggle` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This corresponds to x86's `lock btc`, and the implementation calls them on x86/x86_64. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b0000); assert!(!foo.bit_toggle(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0001); assert!(foo.bit_toggle(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0000); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool { self.inner.bit_toggle(bit, order) } } doc_comment! { concat!("Logical negates the current value, and sets the new value to the result. Returns the previous value. `fetch_not` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0); assert_eq!(foo.fetch_not(Ordering::Relaxed), 0); assert_eq!(foo.load(Ordering::Relaxed), !0); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_not(&self, order: Ordering) -> $int_type { self.inner.fetch_not(order) } } doc_comment! { concat!("Logical negates the current value, and sets the new value to the result. Unlike `fetch_not`, this does not return the previous value. `not` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_not` on some platforms. - x86/x86_64: `lock not` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) - MSP430: `inv` instead of disabling interrupts ({8,16}-bit atomics) # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0); foo.not(Ordering::Relaxed); assert_eq!(foo.load(Ordering::Relaxed), !0); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn not(&self, order: Ordering) { self.inner.not(order); } } cfg_has_atomic_cas! { doc_comment! { concat!("Negates the current value, and sets the new value to the result. Returns the previous value. `fetch_neg` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(5); assert_eq!(foo.fetch_neg(Ordering::Relaxed), 5); assert_eq!(foo.load(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg()); assert_eq!(foo.fetch_neg(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg()); assert_eq!(foo.load(Ordering::Relaxed), 5); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_neg(&self, order: Ordering) -> $int_type { self.inner.fetch_neg(order) } } doc_comment! { concat!("Negates the current value, and sets the new value to the result. Unlike `fetch_neg`, this does not return the previous value. `neg` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_neg` on some platforms. - x86/x86_64: `lock neg` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(5); foo.neg(Ordering::Relaxed); assert_eq!(foo.load(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg()); foo.neg(Ordering::Relaxed); assert_eq!(foo.load(Ordering::Relaxed), 5); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn neg(&self, order: Ordering) { self.inner.neg(order); } } } // cfg_has_atomic_cas! } // cfg_has_atomic_cas_or_amo32! const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; /// Returns a mutable pointer to the underlying integer. /// /// Returning an `*mut` pointer from a shared reference to this atomic is /// safe because the atomic types work with interior mutability. Any use of /// the returned raw pointer requires an `unsafe` block and has to uphold /// the safety requirements. If there is concurrent access, note the following /// additional safety requirements: /// /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent /// operations on it must be atomic. /// - Otherwise, any concurrent operations on it must be compatible with /// operations performed by this atomic type. /// /// This is `const fn` on Rust 1.58+. #[inline] pub const fn as_ptr(&self) -> *mut $int_type { self.inner.as_ptr() } } } // See https://github.com/taiki-e/portable-atomic/issues/180 #[cfg(not(feature = "require-cas"))] cfg_no_atomic_cas! { #[doc(hidden)] #[allow(unused_variables, clippy::unused_self, clippy::extra_unused_lifetimes)] impl<'a> $atomic_type { $cfg_no_atomic_cas_or_amo32_or_8! { #[inline] pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasSwap, { unimplemented!() } } // $cfg_no_atomic_cas_or_amo32_or_8! #[inline] pub fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> where &'a Self: HasCompareExchange, { unimplemented!() } #[inline] pub fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> where &'a Self: HasCompareExchangeWeak, { unimplemented!() } $cfg_no_atomic_cas_or_amo32_or_8! { #[inline] pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasFetchAdd, { unimplemented!() } #[inline] pub fn add(&self, val: $int_type, order: Ordering) where &'a Self: HasAdd, { unimplemented!() } #[inline] pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasFetchSub, { unimplemented!() } #[inline] pub fn sub(&self, val: $int_type, order: Ordering) where &'a Self: HasSub, { unimplemented!() } } // $cfg_no_atomic_cas_or_amo32_or_8! cfg_no_atomic_cas_or_amo32! { #[inline] pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasFetchAnd, { unimplemented!() } #[inline] pub fn and(&self, val: $int_type, order: Ordering) where &'a Self: HasAnd, { unimplemented!() } } // cfg_no_atomic_cas_or_amo32! #[inline] pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasFetchNand, { unimplemented!() } cfg_no_atomic_cas_or_amo32! { #[inline] pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasFetchOr, { unimplemented!() } #[inline] pub fn or(&self, val: $int_type, order: Ordering) where &'a Self: HasOr, { unimplemented!() } #[inline] pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasFetchXor, { unimplemented!() } #[inline] pub fn xor(&self, val: $int_type, order: Ordering) where &'a Self: HasXor, { unimplemented!() } } // cfg_no_atomic_cas_or_amo32! #[inline] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, f: F, ) -> Result<$int_type, $int_type> where F: FnMut($int_type) -> Option<$int_type>, &'a Self: HasFetchUpdate, { unimplemented!() } $cfg_no_atomic_cas_or_amo32_or_8! { #[inline] pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasFetchMax, { unimplemented!() } #[inline] pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type where &'a Self: HasFetchMin, { unimplemented!() } } // $cfg_no_atomic_cas_or_amo32_or_8! cfg_no_atomic_cas_or_amo32! { #[inline] pub fn bit_set(&self, bit: u32, order: Ordering) -> bool where &'a Self: HasBitSet, { unimplemented!() } #[inline] pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool where &'a Self: HasBitClear, { unimplemented!() } #[inline] pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool where &'a Self: HasBitToggle, { unimplemented!() } #[inline] pub fn fetch_not(&self, order: Ordering) -> $int_type where &'a Self: HasFetchNot, { unimplemented!() } #[inline] pub fn not(&self, order: Ordering) where &'a Self: HasNot, { unimplemented!() } } // cfg_no_atomic_cas_or_amo32! #[inline] pub fn fetch_neg(&self, order: Ordering) -> $int_type where &'a Self: HasFetchNeg, { unimplemented!() } #[inline] pub fn neg(&self, order: Ordering) where &'a Self: HasNeg, { unimplemented!() } } } // cfg_no_atomic_cas! $( #[$cfg_float] atomic_int!(float, #[$cfg_float] $atomic_float_type, $float_type, $atomic_type, $int_type, $align ); )? }; // AtomicF* impls (float, #[$cfg_float:meta] $atomic_type:ident, $float_type:ident, $atomic_int_type:ident, $int_type:ident, $align:literal ) => { doc_comment! { concat!("A floating point type which can be safely shared between threads. This type has the same in-memory representation as the underlying floating point type, [`", stringify!($float_type), "`]. " ), #[cfg_attr(docsrs, doc($cfg_float))] // We can use #[repr(transparent)] here, but #[repr(C, align(N))] // will show clearer docs. #[repr(C, align($align))] pub struct $atomic_type { inner: imp::float::$atomic_type, } } impl Default for $atomic_type { #[inline] fn default() -> Self { Self::new($float_type::default()) } } impl From<$float_type> for $atomic_type { #[inline] fn from(v: $float_type) -> Self { Self::new(v) } } // UnwindSafe is implicitly implemented. #[cfg(not(portable_atomic_no_core_unwind_safe))] impl core::panic::RefUnwindSafe for $atomic_type {} #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))] impl std::panic::RefUnwindSafe for $atomic_type {} impl_debug_and_serde!($atomic_type); impl $atomic_type { /// Creates a new atomic float. #[inline] #[must_use] pub const fn new(v: $float_type) -> Self { static_assert_layout!($atomic_type, $float_type); Self { inner: imp::float::$atomic_type::new(v) } } // TODO: update docs based on https://github.com/rust-lang/rust/pull/116762 #[cfg(not(portable_atomic_no_const_mut_refs))] doc_comment! { concat!("Creates a new reference to an atomic float from a pointer. This is `const fn` on Rust 1.83+. # Safety * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($float_type), ">()`). * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value behind `ptr` must have a happens-before relationship with atomic accesses via the returned value (or vice-versa). * In other words, time periods where the value is accessed atomically may not overlap with periods where the value is accessed non-atomically. * This requirement is trivially satisfied if `ptr` is never used non-atomically for the duration of lifetime `'a`. Most use cases should be able to follow this guideline. * This requirement is also trivially satisfied if all accesses (atomic or not) are done from the same thread. * If this atomic type is *not* lock-free: * Any accesses to the value behind `ptr` must have a happens-before relationship with accesses via the returned value (or vice-versa). * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must be compatible with operations performed by this atomic type. * This method must not be used to create overlapping or mixed-size atomic accesses, as these are not supported by the memory model. [valid]: core::ptr#safety"), #[inline] #[must_use] pub const unsafe fn from_ptr<'a>(ptr: *mut $float_type) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } } #[cfg(portable_atomic_no_const_mut_refs)] doc_comment! { concat!("Creates a new reference to an atomic float from a pointer. This is `const fn` on Rust 1.83+. # Safety * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($float_type), ">()`). * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value behind `ptr` must have a happens-before relationship with atomic accesses via the returned value (or vice-versa). * In other words, time periods where the value is accessed atomically may not overlap with periods where the value is accessed non-atomically. * This requirement is trivially satisfied if `ptr` is never used non-atomically for the duration of lifetime `'a`. Most use cases should be able to follow this guideline. * This requirement is also trivially satisfied if all accesses (atomic or not) are done from the same thread. * If this atomic type is *not* lock-free: * Any accesses to the value behind `ptr` must have a happens-before relationship with accesses via the returned value (or vice-versa). * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must be compatible with operations performed by this atomic type. * This method must not be used to create overlapping or mixed-size atomic accesses, as these are not supported by the memory model. [valid]: core::ptr#safety"), #[inline] #[must_use] pub unsafe fn from_ptr<'a>(ptr: *mut $float_type) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. #[inline] #[must_use] pub fn is_lock_free() -> bool { ::is_lock_free() } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// **Note:** If the atomic operation relies on dynamic CPU feature detection, /// this type may be lock-free even if the function returns false. #[inline] #[must_use] pub const fn is_always_lock_free() -> bool { ::IS_ALWAYS_LOCK_FREE } #[cfg(test)] const IS_ALWAYS_LOCK_FREE: bool = Self::is_always_lock_free(); const_fn! { const_if: #[cfg(not(portable_atomic_no_const_mut_refs))]; /// Returns a mutable reference to the underlying float. /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. /// /// This is `const fn` on Rust 1.83+. #[inline] pub const fn get_mut(&mut self) -> &mut $float_type { // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *self.as_ptr() } } } // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 const_fn! { const_if: #[cfg(not(portable_atomic_no_const_transmute))]; /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are /// concurrently accessing the atomic data. /// /// This is `const fn` on Rust 1.56+. #[inline] pub const fn into_inner(self) -> $float_type { // SAFETY: $atomic_type and $float_type have the same size and in-memory representations, // so they can be safely transmuted. // (const UnsafeCell::into_inner is unstable) unsafe { core::mem::transmute(self) } } } /// Loads a value from the atomic float. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation. /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Release`] or [`AcqRel`]. #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn load(&self, order: Ordering) -> $float_type { self.inner.load(order) } /// Stores a value into the atomic float. /// /// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation. /// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Acquire`] or [`AcqRel`]. #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn store(&self, val: $float_type, order: Ordering) { self.inner.store(val, order) } cfg_has_atomic_cas_or_amo32! { /// Stores a value into the atomic float, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn swap(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.swap(val, order) } cfg_has_atomic_cas! { /// Stores a value into the atomic float if the current value is the same as /// the `current` value. /// /// The return value is a result indicating whether the new value was written and /// containing the previous value. On success this value is guaranteed to be equal to /// `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))] #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> { self.inner.compare_exchange(current, new, success, failure) } /// Stores a value into the atomic float if the current value is the same as /// the `current` value. /// Unlike [`compare_exchange`](Self::compare_exchange) /// this function is allowed to spuriously fail even /// when the comparison succeeds, which can result in more efficient code on some /// platforms. The return value is a result indicating whether the new value was /// written and containing the previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))] #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange_weak( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> { self.inner.compare_exchange_weak(current, new, success, failure) } /// Adds to the current value, returning the previous value. /// /// This operation wraps around on overflow. /// /// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_add(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.fetch_add(val, order) } /// Subtracts from the current value, returning the previous value. /// /// This operation wraps around on overflow. /// /// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_sub(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.fetch_sub(val, order) } /// Fetches the value, and applies a function to it that returns an optional /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else /// `Err(previous_value)`. /// /// Note: This may call the function multiple times if the value has been changed from other threads in /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied /// only once to the stored value. /// /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. /// The first describes the required ordering for when the operation finally succeeds while the second /// describes the required ordering for loads. These correspond to the success and failure orderings of /// [`compare_exchange`](Self::compare_exchange) respectively. /// /// Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `fetch_order` is [`Release`], [`AcqRel`]. /// /// # Considerations /// /// This method is not magic; it is not provided by the hardware. /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak), /// and suffers from the same drawbacks. /// In particular, this method will not circumvent the [ABA Problem]. /// /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, mut f: F, ) -> Result<$float_type, $float_type> where F: FnMut($float_type) -> Option<$float_type>, { let mut prev = self.load(fetch_order); while let Some(next) = f(prev) { match self.compare_exchange_weak(prev, next, set_order, fetch_order) { x @ Ok(_) => return x, Err(next_prev) => prev = next_prev, } } Err(prev) } /// Maximum with the current value. /// /// Finds the maximum of the current value and the argument `val`, and /// sets the new value to the result. /// /// Returns the previous value. /// /// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_max(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.fetch_max(val, order) } /// Minimum with the current value. /// /// Finds the minimum of the current value and the argument `val`, and /// sets the new value to the result. /// /// Returns the previous value. /// /// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_min(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.fetch_min(val, order) } } // cfg_has_atomic_cas! /// Negates the current value, and sets the new value to the result. /// /// Returns the previous value. /// /// `fetch_neg` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_neg(&self, order: Ordering) -> $float_type { self.inner.fetch_neg(order) } /// Computes the absolute value of the current value, and sets the /// new value to the result. /// /// Returns the previous value. /// /// `fetch_abs` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_abs(&self, order: Ordering) -> $float_type { self.inner.fetch_abs(order) } } // cfg_has_atomic_cas_or_amo32! #[cfg(not(portable_atomic_no_const_raw_ptr_deref))] doc_comment! { concat!("Raw transmutation to `&", stringify!($atomic_int_type), "`. See [`", stringify!($float_type) ,"::from_bits`] for some discussion of the portability of this operation (there are almost no issues). This is `const fn` on Rust 1.58+."), #[inline] pub const fn as_bits(&self) -> &$atomic_int_type { self.inner.as_bits() } } #[cfg(portable_atomic_no_const_raw_ptr_deref)] doc_comment! { concat!("Raw transmutation to `&", stringify!($atomic_int_type), "`. See [`", stringify!($float_type) ,"::from_bits`] for some discussion of the portability of this operation (there are almost no issues). This is `const fn` on Rust 1.58+."), #[inline] pub fn as_bits(&self) -> &$atomic_int_type { self.inner.as_bits() } } const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; /// Returns a mutable pointer to the underlying float. /// /// Returning an `*mut` pointer from a shared reference to this atomic is /// safe because the atomic types work with interior mutability. Any use of /// the returned raw pointer requires an `unsafe` block and has to uphold /// the safety requirements. If there is concurrent access, note the following /// additional safety requirements: /// /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent /// operations on it must be atomic. /// - Otherwise, any concurrent operations on it must be compatible with /// operations performed by this atomic type. /// /// This is `const fn` on Rust 1.58+. #[inline] pub const fn as_ptr(&self) -> *mut $float_type { self.inner.as_ptr() } } } // See https://github.com/taiki-e/portable-atomic/issues/180 #[cfg(not(feature = "require-cas"))] cfg_no_atomic_cas! { #[doc(hidden)] #[allow(unused_variables, clippy::unused_self, clippy::extra_unused_lifetimes)] impl<'a> $atomic_type { cfg_no_atomic_cas_or_amo32! { #[inline] pub fn swap(&self, val: $float_type, order: Ordering) -> $float_type where &'a Self: HasSwap, { unimplemented!() } } // cfg_no_atomic_cas_or_amo32! #[inline] pub fn compare_exchange( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> where &'a Self: HasCompareExchange, { unimplemented!() } #[inline] pub fn compare_exchange_weak( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> where &'a Self: HasCompareExchangeWeak, { unimplemented!() } #[inline] pub fn fetch_add(&self, val: $float_type, order: Ordering) -> $float_type where &'a Self: HasFetchAdd, { unimplemented!() } #[inline] pub fn fetch_sub(&self, val: $float_type, order: Ordering) -> $float_type where &'a Self: HasFetchSub, { unimplemented!() } #[inline] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, f: F, ) -> Result<$float_type, $float_type> where F: FnMut($float_type) -> Option<$float_type>, &'a Self: HasFetchUpdate, { unimplemented!() } #[inline] pub fn fetch_max(&self, val: $float_type, order: Ordering) -> $float_type where &'a Self: HasFetchMax, { unimplemented!() } #[inline] pub fn fetch_min(&self, val: $float_type, order: Ordering) -> $float_type where &'a Self: HasFetchMin, { unimplemented!() } cfg_no_atomic_cas_or_amo32! { #[inline] pub fn fetch_neg(&self, order: Ordering) -> $float_type where &'a Self: HasFetchNeg, { unimplemented!() } #[inline] pub fn fetch_abs(&self, order: Ordering) -> $float_type where &'a Self: HasFetchAbs, { unimplemented!() } } // cfg_no_atomic_cas_or_amo32! } } // cfg_no_atomic_cas! }; } cfg_has_atomic_ptr! { #[cfg(target_pointer_width = "16")] atomic_int!(AtomicIsize, isize, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8); #[cfg(target_pointer_width = "16")] atomic_int!(AtomicUsize, usize, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8); #[cfg(target_pointer_width = "32")] atomic_int!(AtomicIsize, isize, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); #[cfg(target_pointer_width = "32")] atomic_int!(AtomicUsize, usize, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); #[cfg(target_pointer_width = "64")] atomic_int!(AtomicIsize, isize, 8, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); #[cfg(target_pointer_width = "64")] atomic_int!(AtomicUsize, usize, 8, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); #[cfg(target_pointer_width = "128")] atomic_int!(AtomicIsize, isize, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); #[cfg(target_pointer_width = "128")] atomic_int!(AtomicUsize, usize, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); } cfg_has_atomic_8! { atomic_int!(AtomicI8, i8, 1, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8); atomic_int!(AtomicU8, u8, 1, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8); } cfg_has_atomic_16! { atomic_int!(AtomicI16, i16, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8); atomic_int!(AtomicU16, u16, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8, #[cfg(all(feature = "float", portable_atomic_unstable_f16))] AtomicF16, f16); } cfg_has_atomic_32! { atomic_int!(AtomicI32, i32, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); atomic_int!(AtomicU32, u32, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32, #[cfg(feature = "float")] AtomicF32, f32); } cfg_has_atomic_64! { atomic_int!(AtomicI64, i64, 8, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); atomic_int!(AtomicU64, u64, 8, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32, #[cfg(feature = "float")] AtomicF64, f64); } cfg_has_atomic_128! { atomic_int!(AtomicI128, i128, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32); atomic_int!(AtomicU128, u128, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32, #[cfg(all(feature = "float", portable_atomic_unstable_f128))] AtomicF128, f128); } // See https://github.com/taiki-e/portable-atomic/issues/180 #[cfg(not(feature = "require-cas"))] cfg_no_atomic_cas! { cfg_no_atomic_cas_or_amo32! { #[cfg(feature = "float")] use self::diagnostic_helper::HasFetchAbs; use self::diagnostic_helper::{ HasAnd, HasBitClear, HasBitSet, HasBitToggle, HasFetchAnd, HasFetchByteAdd, HasFetchByteSub, HasFetchNot, HasFetchOr, HasFetchPtrAdd, HasFetchPtrSub, HasFetchXor, HasNot, HasOr, HasXor, }; } // cfg_no_atomic_cas_or_amo32! cfg_no_atomic_cas_or_amo8! { use self::diagnostic_helper::{HasAdd, HasSub, HasSwap}; } // cfg_no_atomic_cas_or_amo8! #[cfg_attr(not(feature = "float"), allow(unused_imports))] use self::diagnostic_helper::{ HasCompareExchange, HasCompareExchangeWeak, HasFetchAdd, HasFetchMax, HasFetchMin, HasFetchNand, HasFetchNeg, HasFetchSub, HasFetchUpdate, HasNeg, }; #[cfg_attr( any( all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "bpf", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), ), not(feature = "float"), ), allow(dead_code, unreachable_pub) )] #[allow(unknown_lints, unnameable_types)] // Not public API. unnameable_types is available on Rust 1.79+ mod diagnostic_helper { cfg_no_atomic_cas_or_amo8! { #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`swap` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasSwap {} } // cfg_no_atomic_cas_or_amo8! #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`compare_exchange` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasCompareExchange {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`compare_exchange_weak` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasCompareExchangeWeak {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_add` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchAdd {} cfg_no_atomic_cas_or_amo8! { #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`add` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasAdd {} } // cfg_no_atomic_cas_or_amo8! #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_sub` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchSub {} cfg_no_atomic_cas_or_amo8! { #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`sub` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasSub {} } // cfg_no_atomic_cas_or_amo8! cfg_no_atomic_cas_or_amo32! { #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_ptr_add` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchPtrAdd {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_ptr_sub` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchPtrSub {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_byte_add` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchByteAdd {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_byte_sub` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchByteSub {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_and` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchAnd {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`and` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasAnd {} } // cfg_no_atomic_cas_or_amo32! #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_nand` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchNand {} cfg_no_atomic_cas_or_amo32! { #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_or` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchOr {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`or` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasOr {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_xor` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchXor {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`xor` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasXor {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_not` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchNot {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`not` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasNot {} } // cfg_no_atomic_cas_or_amo32! #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_neg` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchNeg {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`neg` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasNeg {} cfg_no_atomic_cas_or_amo32! { #[cfg(feature = "float")] #[cfg_attr(target_pointer_width = "16", allow(dead_code, unreachable_pub))] #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_abs` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchAbs {} } // cfg_no_atomic_cas_or_amo32! #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_min` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchMin {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_max` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchMax {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`fetch_update` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasFetchUpdate {} cfg_no_atomic_cas_or_amo32! { #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`bit_set` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasBitSet {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`bit_clear` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasBitClear {} #[doc(hidden)] #[cfg_attr( not(portable_atomic_no_diagnostic_namespace), diagnostic::on_unimplemented( message = "`bit_toggle` requires atomic CAS but not available on this target by default", label = "this associated function is not available on this target by default", note = "consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features", note = "see for more." ) )] pub trait HasBitToggle {} } // cfg_no_atomic_cas_or_amo32! } } // cfg_no_atomic_cas! portable-atomic/src/utils.rs0000644000175000017500000007036415105742312015773 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT #![cfg_attr(not(all(test, feature = "float")), allow(dead_code, unused_macros))] #[macro_use] #[path = "gen/utils.rs"] mod generated; use core::sync::atomic::Ordering; macro_rules! static_assert { ($cond:expr $(,)?) => {{ let [] = [(); true as usize - $crate::utils::_assert_is_bool($cond) as usize]; }}; } pub(crate) const fn _assert_is_bool(v: bool) -> bool { v } macro_rules! static_assert_layout { ($atomic_type:ty, $value_type:ty) => { static_assert!( core::mem::align_of::<$atomic_type>() == core::mem::size_of::<$atomic_type>() ); static_assert!(core::mem::size_of::<$atomic_type>() == core::mem::size_of::<$value_type>()); }; } // #[doc = concat!(...)] requires Rust 1.54 macro_rules! doc_comment { ($doc:expr, $($tt:tt)*) => { #[doc = $doc] $($tt)* }; } // Adapted from https://github.com/BurntSushi/memchr/blob/2.4.1/src/memchr/x86/mod.rs#L9-L71. /// # Safety /// /// - the caller must uphold the safety contract for the function returned by $detect_body. /// - the memory pointed by the function pointer returned by $detect_body must be visible from any threads. /// /// The second requirement is always met if the function pointer is to the function definition. /// (Currently, all uses of this macro in our code are in this case.) #[allow(unused_macros)] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( target_arch = "aarch64", target_arch = "arm", target_arch = "arm64ec", target_arch = "powerpc64", target_arch = "riscv32", target_arch = "riscv64", all(target_arch = "x86_64", not(any(target_env = "sgx", miri))), ))] macro_rules! ifunc { (unsafe fn($($arg_pat:ident: $arg_ty:ty),*) $(-> $ret_ty:ty)? { $($detect_body:tt)* }) => {{ type FnTy = unsafe fn($($arg_ty),*) $(-> $ret_ty)?; static FUNC: core::sync::atomic::AtomicPtr<()> = core::sync::atomic::AtomicPtr::new(detect as *mut ()); #[cold] unsafe fn detect($($arg_pat: $arg_ty),*) $(-> $ret_ty)? { let func: FnTy = { $($detect_body)* }; FUNC.store(func as *mut (), core::sync::atomic::Ordering::Relaxed); // SAFETY: the caller must uphold the safety contract for the function returned by $detect_body. unsafe { func($($arg_pat),*) } } // SAFETY: `FnTy` is a function pointer, which is always safe to transmute with a `*mut ()`. // (To force the caller to use unsafe block for this macro, do not use // unsafe block here.) let func = { core::mem::transmute::<*mut (), FnTy>(FUNC.load(core::sync::atomic::Ordering::Relaxed)) }; // SAFETY: the caller must uphold the safety contract for the function returned by $detect_body. // (To force the caller to use unsafe block for this macro, do not use // unsafe block here.) func($($arg_pat),*) }}; } #[allow(unused_macros)] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( target_arch = "aarch64", target_arch = "arm", target_arch = "arm64ec", target_arch = "powerpc64", target_arch = "riscv32", target_arch = "riscv64", all(target_arch = "x86_64", not(any(target_env = "sgx", miri))), ))] macro_rules! fn_alias { ( $(#[$($fn_attr:tt)*])* $vis:vis unsafe fn($($arg_pat:ident: $arg_ty:ty),*) $(-> $ret_ty:ty)?; $(#[$($alias_attr:tt)*])* $new:ident = $from:ident($($last_args:tt)*); $($rest:tt)* ) => { $(#[$($fn_attr)*])* $(#[$($alias_attr)*])* $vis unsafe fn $new($($arg_pat: $arg_ty),*) $(-> $ret_ty)? { // SAFETY: the caller must uphold the safety contract. unsafe { $from($($arg_pat,)* $($last_args)*) } } fn_alias! { $(#[$($fn_attr)*])* $vis unsafe fn($($arg_pat: $arg_ty),*) $(-> $ret_ty)?; $($rest)* } }; ( $(#[$($attr:tt)*])* $vis:vis unsafe fn($($arg_pat:ident: $arg_ty:ty),*) $(-> $ret_ty:ty)?; ) => {} } /// Make the given function const if the given condition is true. macro_rules! const_fn { ( const_if: #[cfg($($cfg:tt)+)]; $(#[$($attr:tt)*])* $vis:vis const $($rest:tt)* ) => { #[cfg($($cfg)+)] $(#[$($attr)*])* $vis const $($rest)* #[cfg(not($($cfg)+))] $(#[$($attr)*])* $vis $($rest)* }; } /// Implements `core::fmt::Debug` and `serde::{Serialize, Deserialize}` (when serde /// feature is enabled) for atomic bool, integer, or float. macro_rules! impl_debug_and_serde { // TODO(f16_and_f128): Implement serde traits for f16 & f128 once stabilized. (AtomicF16) => { impl_debug!(AtomicF16); }; (AtomicF128) => { impl_debug!(AtomicF128); }; ($atomic_type:ident) => { impl_debug!($atomic_type); #[cfg(feature = "serde")] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl serde::ser::Serialize for $atomic_type { #[allow(clippy::missing_inline_in_public_items)] // serde doesn't use inline on std atomic's Serialize/Deserialize impl fn serialize(&self, serializer: S) -> Result where S: serde::ser::Serializer, { // https://github.com/serde-rs/serde/blob/v1.0.152/serde/src/ser/impls.rs#L958-L959 self.load(Ordering::Relaxed).serialize(serializer) } } #[cfg(feature = "serde")] #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl<'de> serde::de::Deserialize<'de> for $atomic_type { #[allow(clippy::missing_inline_in_public_items)] // serde doesn't use inline on std atomic's Serialize/Deserialize impl fn deserialize(deserializer: D) -> Result where D: serde::de::Deserializer<'de>, { serde::de::Deserialize::deserialize(deserializer).map(Self::new) } } }; } macro_rules! impl_debug { ($atomic_type:ident) => { impl fmt::Debug for $atomic_type { #[inline] // fmt is not hot path, but #[inline] on fmt seems to still be useful: https://github.com/rust-lang/rust/pull/117727 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L2188 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f) } } }; } // We do not provide `nand` because it cannot be optimized on neither x86 nor MSP430. // https://godbolt.org/z/ahWejchbT macro_rules! impl_default_no_fetch_ops { ($atomic_type:ident, bool) => { impl $atomic_type { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn and(&self, val: bool, order: Ordering) { self.fetch_and(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn or(&self, val: bool, order: Ordering) { self.fetch_or(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn xor(&self, val: bool, order: Ordering) { self.fetch_xor(val, order); } } }; ($atomic_type:ident, $int_type:ty) => { impl $atomic_type { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn add(&self, val: $int_type, order: Ordering) { self.fetch_add(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn sub(&self, val: $int_type, order: Ordering) { self.fetch_sub(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn and(&self, val: $int_type, order: Ordering) { self.fetch_and(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn or(&self, val: $int_type, order: Ordering) { self.fetch_or(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn xor(&self, val: $int_type, order: Ordering) { self.fetch_xor(val, order); } } }; } macro_rules! impl_default_bit_opts { ($atomic_type:ident, $int_type:ty) => { impl $atomic_type { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn bit_set(&self, bit: u32, order: Ordering) -> bool { let mask = <$int_type>::wrapping_shl(1, bit); self.fetch_or(mask, order) & mask != 0 } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn bit_clear(&self, bit: u32, order: Ordering) -> bool { let mask = <$int_type>::wrapping_shl(1, bit); self.fetch_and(!mask, order) & mask != 0 } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn bit_toggle(&self, bit: u32, order: Ordering) -> bool { let mask = <$int_type>::wrapping_shl(1, bit); self.fetch_xor(mask, order) & mask != 0 } } }; } // This just outputs the input as is, but can be used like an item-level block by using it with cfg. macro_rules! items { ($($tt:tt)*) => { $($tt)* }; } #[allow(dead_code)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] // Stable version of https://doc.rust-lang.org/nightly/std/hint/fn.assert_unchecked.html. // TODO: use real core::hint::assert_unchecked on 1.81+ https://github.com/rust-lang/rust/pull/123588 #[inline(always)] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) unsafe fn assert_unchecked(cond: bool) { if !cond { if cfg!(debug_assertions) { unreachable!() } else { // SAFETY: the caller promised `cond` is true. unsafe { core::hint::unreachable_unchecked() } } } } // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L3338 #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn assert_load_ordering(order: Ordering) { match order { Ordering::Acquire | Ordering::Relaxed | Ordering::SeqCst => {} Ordering::Release => panic!("there is no such thing as a release load"), Ordering::AcqRel => panic!("there is no such thing as an acquire-release load"), _ => unreachable!(), } } // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L3323 #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn assert_store_ordering(order: Ordering) { match order { Ordering::Release | Ordering::Relaxed | Ordering::SeqCst => {} Ordering::Acquire => panic!("there is no such thing as an acquire store"), Ordering::AcqRel => panic!("there is no such thing as an acquire-release store"), _ => unreachable!(), } } // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L3404 #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn assert_compare_exchange_ordering(success: Ordering, failure: Ordering) { match success { Ordering::AcqRel | Ordering::Acquire | Ordering::Relaxed | Ordering::Release | Ordering::SeqCst => {} _ => unreachable!(), } match failure { Ordering::Acquire | Ordering::Relaxed | Ordering::SeqCst => {} Ordering::Release => panic!("there is no such thing as a release failure ordering"), Ordering::AcqRel => panic!("there is no such thing as an acquire-release failure ordering"), _ => unreachable!(), } } // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0418r2.html // https://github.com/rust-lang/rust/pull/98383 #[allow(dead_code)] #[inline] pub(crate) fn upgrade_success_ordering(success: Ordering, failure: Ordering) -> Ordering { match (success, failure) { (Ordering::Relaxed, Ordering::Acquire) => Ordering::Acquire, (Ordering::Release, Ordering::Acquire) => Ordering::AcqRel, (_, Ordering::SeqCst) => Ordering::SeqCst, _ => success, } } /// Zero-extends the given 32-bit pointer to `MaybeUninit`. /// This is used for 64-bit architecture's 32-bit ABI (e.g., AArch64 ILP32 ABI). /// See ptr_reg! macro in src/gen/utils.rs for details. #[cfg(not(portable_atomic_no_asm_maybe_uninit))] #[cfg(target_pointer_width = "32")] #[allow(dead_code)] #[inline] pub(crate) fn zero_extend64_ptr(v: *mut ()) -> core::mem::MaybeUninit { #[repr(C)] struct ZeroExtended { #[cfg(target_endian = "big")] pad: *mut (), v: *mut (), #[cfg(target_endian = "little")] pad: *mut (), } // SAFETY: we can safely transmute any 64-bit value to MaybeUninit. unsafe { core::mem::transmute(ZeroExtended { v, pad: core::ptr::null_mut() }) } } #[allow(dead_code)] #[cfg(any( target_arch = "aarch64", target_arch = "arm64ec", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "x86_64", ))] /// A 128-bit value represented as a pair of 64-bit values. /// /// This type is `#[repr(C)]`, both fields have the same in-memory representation /// and are plain old data types, so access to the fields is always safe. #[derive(Clone, Copy)] #[repr(C)] pub(crate) union U128 { pub(crate) whole: u128, pub(crate) pair: Pair, } #[allow(dead_code)] #[cfg(any(target_arch = "arm", target_arch = "riscv32"))] /// A 64-bit value represented as a pair of 32-bit values. /// /// This type is `#[repr(C)]`, both fields have the same in-memory representation /// and are plain old data types, so access to the fields is always safe. #[derive(Clone, Copy)] #[repr(C)] pub(crate) union U64 { pub(crate) whole: u64, pub(crate) pair: Pair, } #[allow(dead_code)] #[derive(Clone, Copy)] #[repr(C)] pub(crate) struct Pair { // little endian order #[cfg(any( target_endian = "little", target_arch = "aarch64", target_arch = "arm", target_arch = "arm64ec", ))] pub(crate) lo: T, pub(crate) hi: T, // big endian order #[cfg(not(any( target_endian = "little", target_arch = "aarch64", target_arch = "arm", target_arch = "arm64ec", )))] pub(crate) lo: T, } #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] type MinWord = u32; #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] type RetInt = u32; // Adapted from https://github.com/taiki-e/atomic-maybe-uninit/blob/v0.3.6/src/utils.rs#L255. // Helper for implementing sub-word atomic operations using word-sized LL/SC loop or CAS loop. // // Refs: https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/CodeGen/AtomicExpandPass.cpp#L799 // (aligned_ptr, shift, mask) #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] #[allow(dead_code)] #[inline] pub(crate) fn create_sub_word_mask_values(ptr: *mut T) -> (*mut MinWord, RetInt, RetInt) { #[cfg(portable_atomic_no_strict_provenance)] use self::ptr::PtrExt as _; use core::mem; // RISC-V, MIPS, SPARC, LoongArch, Xtensa, BPF: shift amount of 32-bit shift instructions is 5 bits unsigned (0-31). // PowerPC, C-SKY: shift amount of 32-bit shift instructions is 6 bits unsigned (0-63) and shift amount 32-63 means "clear". // Arm: shift amount of 32-bit shift instructions is 8 bits unsigned (0-255). // Hexagon: shift amount of 32-bit shift instructions is 7 bits signed (-64-63) and negative shift amount means "reverse the direction of the shift". // (On s390x, we don't use the mask returned from this function.) // (See also https://devblogs.microsoft.com/oldnewthing/20230904-00/?p=108704 for others) const SHIFT_MASK: bool = !cfg!(any( target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "riscv32", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc", target_arch = "sparc64", target_arch = "xtensa", )); let ptr_mask = mem::size_of::() - 1; let aligned_ptr = ptr.with_addr(ptr.addr() & !ptr_mask) as *mut MinWord; let ptr_lsb = if SHIFT_MASK { ptr.addr() & ptr_mask } else { // We use 32-bit wrapping shift instructions in asm on these platforms. ptr.addr() }; let shift = if cfg!(any(target_endian = "little", target_arch = "s390x")) { ptr_lsb.wrapping_mul(8) } else { (ptr_lsb ^ (mem::size_of::() - mem::size_of::())).wrapping_mul(8) }; let mut mask: RetInt = (1 << (mem::size_of::() * 8)) - 1; // !(0 as T) as RetInt if SHIFT_MASK { mask <<= shift; } (aligned_ptr, shift as RetInt, mask) } // This module provides core::ptr strict_provenance/exposed_provenance polyfill for pre-1.84 rustc. #[allow(dead_code)] pub(crate) mod ptr { #[cfg(portable_atomic_no_strict_provenance)] use core::mem; #[cfg(not(portable_atomic_no_strict_provenance))] #[allow(unused_imports)] pub(crate) use core::ptr::{with_exposed_provenance, with_exposed_provenance_mut}; #[cfg(portable_atomic_no_strict_provenance)] #[inline(always)] #[must_use] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn with_exposed_provenance(addr: usize) -> *const T { addr as *const T } #[cfg(portable_atomic_no_strict_provenance)] #[inline(always)] #[must_use] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn with_exposed_provenance_mut(addr: usize) -> *mut T { addr as *mut T } #[cfg(portable_atomic_no_strict_provenance)] pub(crate) trait PtrExt: Copy { #[must_use] fn addr(self) -> usize; #[must_use] fn with_addr(self, addr: usize) -> Self where T: Sized; } #[cfg(portable_atomic_no_strict_provenance)] impl PtrExt for *mut T { #[inline(always)] #[must_use] fn addr(self) -> usize { // A pointer-to-integer transmute currently has exactly the right semantics: it returns the // address without exposing the provenance. Note that this is *not* a stable guarantee about // transmute semantics, it relies on sysroot crates having special status. // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the // provenance). #[allow(clippy::transmutes_expressible_as_ptr_casts)] unsafe { mem::transmute(self as *mut ()) } } #[allow(clippy::cast_possible_wrap)] #[inline] #[must_use] fn with_addr(self, addr: usize) -> Self where T: Sized, { // This should probably be an intrinsic to avoid doing any sort of arithmetic, but // meanwhile, we can implement it with `wrapping_offset`, which preserves the pointer's // provenance. let self_addr = self.addr() as isize; let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); (self as *mut u8).wrapping_offset(offset) as *mut T } } } // This module provides: // - core::ffi polyfill (c_* type aliases and CStr) for pre-1.64 rustc compatibility. // (core::ffi::* (except c_void) requires Rust 1.64) // - safe abstraction (c! macro) for creating static C strings without runtime checks. // (c"..." requires Rust 1.77) #[cfg(any(test, not(any(windows, target_arch = "x86", target_arch = "x86_64"))))] #[cfg(any(not(portable_atomic_no_asm), portable_atomic_unstable_asm))] #[allow(dead_code, non_camel_case_types, unused_macros)] #[macro_use] pub(crate) mod ffi { pub(crate) type c_void = core::ffi::c_void; // c_{,u}int is {i,u}16 on 16-bit targets, otherwise {i,u}32. // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/ffi/mod.rs#L156 #[cfg(target_pointer_width = "16")] pub(crate) type c_int = i16; #[cfg(target_pointer_width = "16")] pub(crate) type c_uint = u16; #[cfg(not(target_pointer_width = "16"))] pub(crate) type c_int = i32; #[cfg(not(target_pointer_width = "16"))] pub(crate) type c_uint = u32; // c_{,u}long is {i,u}64 on non-Windows 64-bit targets, otherwise {i,u}32. // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/ffi/mod.rs#L168 #[cfg(all(target_pointer_width = "64", not(windows)))] pub(crate) type c_long = i64; #[cfg(all(target_pointer_width = "64", not(windows)))] pub(crate) type c_ulong = u64; #[cfg(not(all(target_pointer_width = "64", not(windows))))] pub(crate) type c_long = i32; #[cfg(not(all(target_pointer_width = "64", not(windows))))] pub(crate) type c_ulong = u32; // c_size_t is currently always usize. // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/ffi/mod.rs#L76 pub(crate) type c_size_t = usize; // c_char is u8 by default on non-Apple/non-Windows Arm/C-SKY/Hexagon/MSP430/PowerPC/RISC-V/s390x/Xtensa targets, otherwise i8 by default. // See references in https://github.com/rust-lang/rust/issues/129945 for details. #[cfg(all( not(any(target_vendor = "apple", windows)), any( target_arch = "aarch64", target_arch = "arm", target_arch = "csky", target_arch = "hexagon", target_arch = "msp430", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "riscv32", target_arch = "riscv64", target_arch = "s390x", target_arch = "xtensa", ), ))] pub(crate) type c_char = u8; #[cfg(not(all( not(any(target_vendor = "apple", windows)), any( target_arch = "aarch64", target_arch = "arm", target_arch = "csky", target_arch = "hexagon", target_arch = "msp430", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "riscv32", target_arch = "riscv64", target_arch = "s390x", target_arch = "xtensa", ), )))] pub(crate) type c_char = i8; // Static assertions for C type definitions. #[cfg(test)] const _: fn() = || { let _: c_int = 0 as std::os::raw::c_int; let _: c_uint = 0 as std::os::raw::c_uint; let _: c_long = 0 as std::os::raw::c_long; let _: c_ulong = 0 as std::os::raw::c_ulong; #[cfg(unix)] let _: c_size_t = 0 as libc::size_t; // std::os::raw::c_size_t is unstable let _: c_char = 0 as std::os::raw::c_char; }; #[repr(transparent)] pub(crate) struct CStr([c_char]); impl CStr { #[inline] #[must_use] pub(crate) const fn as_ptr(&self) -> *const c_char { self.0.as_ptr() } /// # Safety /// /// The provided slice **must** be nul-terminated and not contain any interior /// nul bytes. #[inline] #[must_use] pub(crate) unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { // SAFETY: Casting to CStr is safe because *our* CStr is #[repr(transparent)] // and its internal representation is a [u8] too. (Note that std's CStr // is not #[repr(transparent)].) // Dereferencing the obtained pointer is safe because it comes from a // reference. Making a reference is then safe because its lifetime // is bound by the lifetime of the given `bytes`. unsafe { &*(bytes as *const [u8] as *const CStr) } } #[cfg(test)] #[inline] #[must_use] pub(crate) fn to_bytes_with_nul(&self) -> &[u8] { // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s // is safe on all supported targets. #[allow(clippy::unnecessary_cast)] // triggered for targets that c_char is u8 unsafe { &*(&self.0 as *const [c_char] as *const [u8]) } } } macro_rules! c { ($s:expr) => {{ const BYTES: &[u8] = concat!($s, "\0").as_bytes(); const _: () = static_assert!(crate::utils::ffi::_const_is_c_str(BYTES)); #[allow(unused_unsafe)] // SAFETY: we've checked `BYTES` is a valid C string unsafe { crate::utils::ffi::CStr::from_bytes_with_nul_unchecked(BYTES) } }}; } #[must_use] pub(crate) const fn _const_is_c_str(bytes: &[u8]) -> bool { #[cfg(portable_atomic_no_track_caller)] { // const_if_match/const_loop was stabilized (nightly-2020-06-30) 2 days before // track_caller was stabilized (nightly-2020-07-02), so we reuse the cfg for // track_caller here instead of emitting a cfg for const_if_match/const_loop. // https://github.com/rust-lang/rust/pull/72437 // track_caller was stabilized 11 days after the oldest nightly version // that uses this module, and is included in the same 1.46 stable release. // The check here is insufficient in this case, but this is fine because this function // is internal code that is not used to process input from the user and our CI checks // all builtin targets and some custom targets with some versions of newer compilers. !bytes.is_empty() } #[cfg(not(portable_atomic_no_track_caller))] { // Based on https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/ffi/c_str.rs#L417 // - bytes must be nul-terminated. // - bytes must not contain any interior nul bytes. if bytes.is_empty() { return false; } let mut i = bytes.len() - 1; if bytes[i] != 0 { return false; } // Ending null byte exists, skip to the rest. while i != 0 { i -= 1; if bytes[i] == 0 { return false; } } true } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { #[test] fn test_c_macro() { #[track_caller] fn t(s: &crate::utils::ffi::CStr, raw: &[u8]) { assert_eq!(s.to_bytes_with_nul(), raw); } t(c!(""), b"\0"); t(c!("a"), b"a\0"); t(c!("abc"), b"abc\0"); t(c!(concat!("abc", "d")), b"abcd\0"); } #[test] fn test_is_c_str() { #[track_caller] fn t(bytes: &[u8]) { assert_eq!( super::_const_is_c_str(bytes), std::ffi::CStr::from_bytes_with_nul(bytes).is_ok() ); } t(b"\0"); t(b"a\0"); t(b"abc\0"); t(b""); t(b"a"); t(b"abc"); t(b"\0a"); t(b"\0a\0"); t(b"ab\0c\0"); t(b"\0\0"); } } } portable-atomic/src/imp/0000775000175000017500000000000015105742312015042 5ustar bdrungbdrungportable-atomic/src/imp/mod.rs0000644000175000017500000004221115105742312016165 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT // ----------------------------------------------------------------------------- // Lock-free implementations #[cfg(not(any( all( portable_atomic_no_atomic_load_store, not(all(target_arch = "bpf", not(feature = "critical-section"))), ), target_arch = "avr", target_arch = "msp430", )))] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(all( any( target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", portable_atomic_unsafe_assume_single_core, ), portable_atomic_no_atomic_cas, ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(all( any( target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", portable_atomic_unsafe_assume_single_core, ), not(target_has_atomic = "ptr"), ))) )] mod core_atomic; // AVR #[cfg(target_arch = "avr")] #[cfg(not(portable_atomic_no_asm))] #[cfg(not(feature = "critical-section"))] mod avr; // MSP430 #[cfg(target_arch = "msp430")] pub(crate) mod msp430; // RISC-V without A-extension #[cfg(any(test, not(feature = "critical-section")))] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( all(test, not(any(miri, portable_atomic_sanitize_thread))), portable_atomic_no_atomic_cas, )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( all(test, not(any(miri, portable_atomic_sanitize_thread))), not(target_has_atomic = "ptr"), )) )] #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] mod riscv; // x86-specific optimizations // Miri and Sanitizer do not support inline assembly. #[cfg(all( any(target_arch = "x86", target_arch = "x86_64"), not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ))] mod x86; // 64-bit atomic implementations on 32-bit architectures #[cfg(any(target_arch = "arm", target_arch = "riscv32"))] mod atomic64; // 128-bit atomic implementations on 64-bit architectures #[cfg(any( target_arch = "aarch64", target_arch = "arm64ec", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "x86_64", ))] mod atomic128; // ----------------------------------------------------------------------------- // Lock-based fallback implementations #[cfg(feature = "fallback")] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] #[cfg(any( test, not(any( all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ), all(target_arch = "arm64ec", not(portable_atomic_no_asm)), all( target_arch = "x86_64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), ), all( target_arch = "riscv64", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ), ), all(target_arch = "s390x", not(portable_atomic_no_asm)), )) ))] mod fallback; // ----------------------------------------------------------------------------- // Critical section based fallback implementations // On AVR, we always use critical section based fallback implementation. // AVR can be safely assumed to be single-core, so this is sound. // MSP430 as well. // See the module-level comments of interrupt module for more. #[cfg(any( all(test, target_os = "none"), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_cas)))] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any(test, not(target_has_atomic = "ptr"))) )] #[cfg(any( target_arch = "arm", target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", target_arch = "xtensa", feature = "critical-section", ))] mod interrupt; // ----------------------------------------------------------------------------- // Atomic float implementations #[cfg(feature = "float")] pub(crate) mod float; // ----------------------------------------------------------------------------- // has CAS | (has core atomic & !(avr | msp430 | critical section)) => core atomic #[cfg(not(any( portable_atomic_no_atomic_load_store, target_arch = "avr", target_arch = "msp430", )))] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(all( any( target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", portable_atomic_unsafe_assume_single_core, ), portable_atomic_no_atomic_cas, ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(all( any( target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", portable_atomic_unsafe_assume_single_core, ), not(target_has_atomic = "ptr"), ))) )] items! { pub(crate) use self::core_atomic::{ AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, }; #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( not(portable_atomic_no_atomic_64), not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] pub(crate) use self::core_atomic::{AtomicI64, AtomicU64}; } // bpf & !(critical section) => core atomic #[cfg(all( target_arch = "bpf", portable_atomic_no_atomic_load_store, not(feature = "critical-section"), ))] pub(crate) use self::core_atomic::{AtomicI64, AtomicIsize, AtomicPtr, AtomicU64, AtomicUsize}; // RISC-V without A-extension & !(assume single core | critical section) #[cfg(not(any(portable_atomic_unsafe_assume_single_core, feature = "critical-section")))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))] #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] items! { pub(crate) use self::riscv::{ AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, }; #[cfg(target_arch = "riscv64")] pub(crate) use self::riscv::{AtomicI64, AtomicU64}; } // no core atomic CAS & (assume single core | critical section) => critical section based fallback #[cfg(any( portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))] items! { pub(crate) use self::interrupt::{ AtomicI16, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU8, AtomicUsize, }; #[cfg(any(not(target_pointer_width = "16"), feature = "fallback"))] pub(crate) use self::interrupt::{AtomicI32, AtomicU32}; #[cfg(any( not(any(target_pointer_width = "16", target_pointer_width = "32")), feature = "fallback", ))] pub(crate) use self::interrupt::{AtomicI64, AtomicU64}; #[cfg(feature = "fallback")] pub(crate) use self::interrupt::{AtomicI128, AtomicU128}; } // no core (64-bit | 128-bit) atomic & has CAS => use lock-base fallback #[cfg(feature = "fallback")] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] items! { #[cfg(not(any( all( target_arch = "arm", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_os = "linux", target_os = "android"), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(portable_atomic_no_outline_atomics), ), all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "zacas", portable_atomic_target_feature = "zacas", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(target_os = "linux", target_os = "android"), ), ), ), )))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))] pub(crate) use self::fallback::{AtomicI64, AtomicU64}; #[cfg(not(any( all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ), all(target_arch = "arm64ec", not(portable_atomic_no_asm)), all( target_arch = "x86_64", not(all( any(miri, portable_atomic_sanitize_thread), portable_atomic_no_cmpxchg16b_intrinsic, )), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", all( feature = "fallback", not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), ), ), all( target_arch = "riscv64", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "zacas", portable_atomic_target_feature = "zacas", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(target_os = "linux", target_os = "android"), ), ), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( all( target_env = "gnu", any(target_endian = "little", not(target_feature = "crt-static")), ), all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "openbsd", all( target_os = "aix", not(portable_atomic_pre_llvm_20), portable_atomic_outline_atomics, // TODO(aix): currently disabled by default ), ), not(any(miri, portable_atomic_sanitize_thread)), ), ), ), all(target_arch = "s390x", not(portable_atomic_no_asm)), )))] pub(crate) use self::fallback::{AtomicI128, AtomicU128}; } // 64-bit atomics (platform-specific) // pre-v6 Arm Linux #[cfg(feature = "fallback")] #[cfg(all( target_arch = "arm", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_os = "linux", target_os = "android"), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(portable_atomic_no_outline_atomics), ))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))] pub(crate) use self::atomic64::arm_linux::{AtomicI64, AtomicU64}; // riscv32 & (zacas | outline-atomics) #[cfg(all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "zacas", portable_atomic_target_feature = "zacas", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(target_os = "linux", target_os = "android"), ), ), ))] pub(crate) use self::atomic64::riscv32::{AtomicI64, AtomicU64}; // 128-bit atomics (platform-specific) // AArch64 #[cfg(any( all(target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm)), all(target_arch = "arm64ec", not(portable_atomic_no_asm)) ))] pub(crate) use self::atomic128::aarch64::{AtomicI128, AtomicU128}; // x86_64 & (cmpxchg16b | outline-atomics) #[cfg(all( target_arch = "x86_64", not(all(any(miri, portable_atomic_sanitize_thread), portable_atomic_no_cmpxchg16b_intrinsic)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", all( feature = "fallback", not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), ), ))] pub(crate) use self::atomic128::x86_64::{AtomicI128, AtomicU128}; // riscv64 & (zacas | outline-atomics) #[cfg(all( target_arch = "riscv64", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "zacas", portable_atomic_target_feature = "zacas", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(target_os = "linux", target_os = "android"), ), ), ))] pub(crate) use self::atomic128::riscv64::{AtomicI128, AtomicU128}; // powerpc64 & (pwr8 | outline-atomics) #[cfg(all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( all( target_env = "gnu", any(target_endian = "little", not(target_feature = "crt-static")), ), all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "openbsd", all( target_os = "aix", not(portable_atomic_pre_llvm_20), portable_atomic_outline_atomics, // TODO(aix): currently disabled by default ), ), not(any(miri, portable_atomic_sanitize_thread)), ), ), ))] pub(crate) use self::atomic128::powerpc64::{AtomicI128, AtomicU128}; // s390x #[cfg(all(target_arch = "s390x", not(portable_atomic_no_asm)))] pub(crate) use self::atomic128::s390x::{AtomicI128, AtomicU128}; portable-atomic/src/imp/interrupt/0000775000175000017500000000000015105742312017076 5ustar bdrungbdrungportable-atomic/src/imp/interrupt/mod.rs0000644000175000017500000011206515105742312020226 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Critical section based fallback implementations This module supports two different critical section implementations: - Built-in "disable all interrupts". - Call into the `critical-section` crate (which allows the user to plug any implementation). The `critical-section`-based fallback is enabled when the user asks for it with the `critical-section` Cargo feature. The "disable interrupts" fallback is not sound on multi-core systems. Also, this uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode. Using this fallback in an environment where privileged instructions are not available is also usually considered **unsound**, although the details are system-dependent. Therefore, this implementation will only be enabled in one of the following cases: - When the user explicitly declares that the system is single-core and that privileged instructions are available using an unsafe cfg. - When we can safely assume that the system is single-core and that privileged instructions are available on the system. AVR, which is single core[^avr1] and LLVM also generates code that disables interrupts [^avr2] in atomic ops by default, is considered the latter. MSP430 as well. See also README.md of this directory. [^avr1]: https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp#L1074 [^avr2]: https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/test/CodeGen/AVR/atomics/load16.ll#L5 */ // On some platforms, atomic load/store can be implemented in a more efficient // way than disabling interrupts. On MSP430, some RMWs that do not return the // previous value can also be optimized. // // Note: On single-core systems, it is okay to use critical session-based // CAS together with atomic load/store. The load/store will not be // called while interrupts are disabled, and since the load/store is // atomic, it is not affected by interrupts even if interrupts are enabled. #[cfg(not(any( all(target_arch = "avr", portable_atomic_no_asm), feature = "critical-section", )))] use self::arch::atomic; #[cfg(not(feature = "critical-section"))] #[cfg_attr( all( target_arch = "arm", any(target_feature = "mclass", portable_atomic_target_feature = "mclass"), ), path = "armv6m.rs" )] #[cfg_attr( all( target_arch = "arm", not(any(target_feature = "mclass", portable_atomic_target_feature = "mclass")), ), path = "armv4t.rs" )] #[cfg_attr(target_arch = "avr", path = "avr.rs")] #[cfg_attr(target_arch = "msp430", path = "msp430.rs")] #[cfg_attr(any(target_arch = "riscv32", target_arch = "riscv64"), path = "riscv.rs")] #[cfg_attr(target_arch = "xtensa", path = "xtensa.rs")] mod arch; use core::{cell::UnsafeCell, sync::atomic::Ordering}; // Critical section implementations might use locks internally. #[cfg(feature = "critical-section")] const IS_ALWAYS_LOCK_FREE: bool = false; // Consider atomic operations based on disabling interrupts on single-core // systems are lock-free. (We consider the pre-v6 Arm Linux's atomic operations // provided in a similar way by the Linux kernel to be lock-free.) #[cfg(not(feature = "critical-section"))] const IS_ALWAYS_LOCK_FREE: bool = true; #[cfg(feature = "critical-section")] #[inline] fn with(f: F) -> R where F: FnOnce() -> R, { critical_section::with(|_| f()) } #[cfg(not(feature = "critical-section"))] #[inline(always)] fn with(f: F) -> R where F: FnOnce() -> R, { // Get current interrupt state and disable interrupts let state = arch::disable(); let r = f(); // Restore interrupt state // SAFETY: the state was retrieved by the previous `disable`. unsafe { arch::restore(state) } r } #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] #[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] #[cfg_attr(target_pointer_width = "128", repr(C, align(16)))] pub(crate) struct AtomicPtr { p: UnsafeCell<*mut T>, } // SAFETY: any data races are prevented by disabling interrupts or // atomic intrinsics (see module-level comments). unsafe impl Send for AtomicPtr {} // SAFETY: any data races are prevented by disabling interrupts or // atomic intrinsics (see module-level comments). unsafe impl Sync for AtomicPtr {} impl AtomicPtr { #[inline] pub(crate) const fn new(p: *mut T) -> Self { Self { p: UnsafeCell::new(p) } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::IS_ALWAYS_LOCK_FREE } pub(crate) const IS_ALWAYS_LOCK_FREE: bool = IS_ALWAYS_LOCK_FREE; #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> *mut T { crate::utils::assert_load_ordering(order); #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] { self.as_native().load(order) } #[cfg(any(target_arch = "avr", feature = "critical-section"))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.p.get().read() }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, ptr: *mut T, order: Ordering) { crate::utils::assert_store_ordering(order); #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] { self.as_native().store(ptr, order); } #[cfg(any(target_arch = "avr", feature = "critical-section"))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.p.get().write(ptr) }); } #[inline] pub(crate) fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { let _ = order; #[cfg(all( any(target_arch = "riscv32", target_arch = "riscv64"), not(feature = "critical-section"), any( portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ), ))] { self.as_native().swap(ptr, order) } #[cfg(not(all( any(target_arch = "riscv32", target_arch = "riscv64"), not(feature = "critical-section"), any( portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ), )))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.p.get().read(); self.p.get().write(ptr); prev }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.p.get().read(); if prev == current { self.p.get().write(new); Ok(prev) } else { Err(prev) } }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) const fn as_ptr(&self) -> *mut *mut T { self.p.get() } #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] #[inline(always)] fn as_native(&self) -> &atomic::AtomicPtr { // SAFETY: AtomicPtr and atomic::AtomicPtr have the same layout and // guarantee atomicity in a compatible way. (see module-level comments) unsafe { &*(self as *const Self as *const atomic::AtomicPtr) } } } macro_rules! atomic_int { (base, $atomic_type:ident, $int_type:ident, $align:literal) => { #[repr(C, align($align))] pub(crate) struct $atomic_type { v: UnsafeCell<$int_type>, } // Send is implicitly implemented. // SAFETY: any data races are prevented by disabling interrupts or // atomic intrinsics (see module-level comments). unsafe impl Sync for $atomic_type {} impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::IS_ALWAYS_LOCK_FREE } pub(crate) const IS_ALWAYS_LOCK_FREE: bool = IS_ALWAYS_LOCK_FREE; #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } }; (load_store_atomic $([$kind:ident])?, $atomic_type:ident, $int_type:ident, $align:literal) => { atomic_int!(base, $atomic_type, $int_type, $align); #[cfg(all( any(target_arch = "riscv32", target_arch = "riscv64"), not(feature = "critical-section"), any( portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ), ))] atomic_int!(cas $([$kind])?, $atomic_type, $int_type); #[cfg(not(all( any(target_arch = "riscv32", target_arch = "riscv64"), not(feature = "critical-section"), any( portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ), )))] atomic_int!(cas[emulate], $atomic_type, $int_type); impl $atomic_type { #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); #[cfg(not(any( all(target_arch = "avr", portable_atomic_no_asm), feature = "critical-section", )))] { self.as_native().load(order) } #[cfg(any( all(target_arch = "avr", portable_atomic_no_asm), feature = "critical-section", ))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.v.get().read() }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); #[cfg(not(any( all(target_arch = "avr", portable_atomic_no_asm), feature = "critical-section", )))] { self.as_native().store(val, order); } #[cfg(any( all(target_arch = "avr", portable_atomic_no_asm), feature = "critical-section", ))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.v.get().write(val) }); } #[cfg(not(any( all(target_arch = "avr", portable_atomic_no_asm), feature = "critical-section", )))] #[inline(always)] fn as_native(&self) -> &atomic::$atomic_type { // SAFETY: $atomic_type and atomic::$atomic_type have the same layout and // guarantee atomicity in a compatible way. (see module-level comments) unsafe { &*(self as *const Self as *const atomic::$atomic_type) } } } #[cfg(not(all(target_arch = "msp430", not(feature = "critical-section"))))] impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); #[cfg(not(all(target_arch = "msp430", not(feature = "critical-section"))))] impl $atomic_type { #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } } #[cfg(all(target_arch = "msp430", not(feature = "critical-section")))] impl $atomic_type { #[inline] pub(crate) fn add(&self, val: $int_type, order: Ordering) { self.as_native().add(val, order); } #[inline] pub(crate) fn sub(&self, val: $int_type, order: Ordering) { self.as_native().sub(val, order); } #[inline] pub(crate) fn and(&self, val: $int_type, order: Ordering) { self.as_native().and(val, order); } #[inline] pub(crate) fn or(&self, val: $int_type, order: Ordering) { self.as_native().or(val, order); } #[inline] pub(crate) fn xor(&self, val: $int_type, order: Ordering) { self.as_native().xor(val, order); } #[inline] pub(crate) fn not(&self, order: Ordering) { self.as_native().not(order); } } }; (all_critical_session, $atomic_type:ident, $int_type:ident, $align:literal) => { atomic_int!(base, $atomic_type, $int_type, $align); atomic_int!(cas[emulate], $atomic_type, $int_type); impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.v.get().read() }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.v.get().write(val) }); } #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } } }; (cas[emulate], $atomic_type:ident, $int_type:ident) => { impl $atomic_type { #[inline] pub(crate) fn swap(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(val); prev }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); if prev == current { self.v.get().write(new); Ok(prev) } else { Err(prev) } }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_add(val)); prev }) } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_sub(val)); prev }) } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev & val); prev }) } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(!(prev & val)); prev }) } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev | val); prev }) } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev ^ val); prev }) } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(core::cmp::max(prev, val)); prev }) } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(core::cmp::min(prev, val)); prev }) } #[inline] pub(crate) fn fetch_not(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(!prev); prev }) } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_neg()); prev }) } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } }; // RISC-V 32-bit(RV32)/{32,64}-bit(RV64) RMW with Zaamo extension // RISC-V 8-bit/16-bit RMW with Zabha extension (cas, $atomic_type:ident, $int_type:ident) => { impl $atomic_type { #[inline] pub(crate) fn swap(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().swap(val, order) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); if prev == current { self.v.get().write(new); Ok(prev) } else { Err(prev) } }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_add(val, order) } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_sub(val, order) } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_and(val, order) } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(!(prev & val)); prev }) } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_or(val, order) } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_xor(val, order) } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_max(val, order) } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_min(val, order) } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { self.as_native().fetch_not(order) } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_neg()); prev }) } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } }; // RISC-V 8-bit/16-bit RMW with Zaamo extension (cas[sub_word], $atomic_type:ident, $int_type:ident) => { #[cfg(any(target_feature = "zabha", portable_atomic_target_feature = "zabha"))] atomic_int!(cas, $atomic_type, $int_type); #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] impl $atomic_type { #[inline] pub(crate) fn swap(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(val); prev }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); if prev == current { self.v.get().write(new); Ok(prev) } else { Err(prev) } }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_add(val)); prev }) } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_sub(val)); prev }) } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_and(val, order) } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(!(prev & val)); prev }) } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_or(val, order) } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_xor(val, order) } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(core::cmp::max(prev, val)); prev }) } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(core::cmp::min(prev, val)); prev }) } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { self.as_native().fetch_not(order) } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_neg()); prev }) } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } }; } #[cfg(target_pointer_width = "16")] #[cfg(not(target_arch = "avr"))] atomic_int!(load_store_atomic, AtomicIsize, isize, 2); #[cfg(target_pointer_width = "16")] #[cfg(not(target_arch = "avr"))] atomic_int!(load_store_atomic, AtomicUsize, usize, 2); #[cfg(target_arch = "avr")] atomic_int!(all_critical_session, AtomicIsize, isize, 2); #[cfg(target_arch = "avr")] atomic_int!(all_critical_session, AtomicUsize, usize, 2); #[cfg(target_pointer_width = "32")] atomic_int!(load_store_atomic, AtomicIsize, isize, 4); #[cfg(target_pointer_width = "32")] atomic_int!(load_store_atomic, AtomicUsize, usize, 4); #[cfg(target_pointer_width = "64")] atomic_int!(load_store_atomic, AtomicIsize, isize, 8); #[cfg(target_pointer_width = "64")] atomic_int!(load_store_atomic, AtomicUsize, usize, 8); #[cfg(target_pointer_width = "128")] atomic_int!(load_store_atomic, AtomicIsize, isize, 16); #[cfg(target_pointer_width = "128")] atomic_int!(load_store_atomic, AtomicUsize, usize, 16); #[cfg(not(all(target_arch = "avr", portable_atomic_no_asm)))] atomic_int!(load_store_atomic[sub_word], AtomicI8, i8, 1); #[cfg(not(all(target_arch = "avr", portable_atomic_no_asm)))] atomic_int!(load_store_atomic[sub_word], AtomicU8, u8, 1); #[cfg(all(target_arch = "avr", portable_atomic_no_asm))] atomic_int!(all_critical_session, AtomicI8, i8, 1); #[cfg(all(target_arch = "avr", portable_atomic_no_asm))] atomic_int!(all_critical_session, AtomicU8, u8, 1); #[cfg(not(target_arch = "avr"))] atomic_int!(load_store_atomic[sub_word], AtomicI16, i16, 2); #[cfg(not(target_arch = "avr"))] atomic_int!(load_store_atomic[sub_word], AtomicU16, u16, 2); #[cfg(target_arch = "avr")] atomic_int!(all_critical_session, AtomicI16, i16, 2); #[cfg(target_arch = "avr")] atomic_int!(all_critical_session, AtomicU16, u16, 2); #[cfg(not(target_pointer_width = "16"))] atomic_int!(load_store_atomic, AtomicI32, i32, 4); #[cfg(not(target_pointer_width = "16"))] atomic_int!(load_store_atomic, AtomicU32, u32, 4); #[cfg(target_pointer_width = "16")] #[cfg(any(test, feature = "fallback"))] atomic_int!(all_critical_session, AtomicI32, i32, 4); #[cfg(target_pointer_width = "16")] #[cfg(any(test, feature = "fallback"))] atomic_int!(all_critical_session, AtomicU32, u32, 4); cfg_has_fast_atomic_64! { atomic_int!(load_store_atomic, AtomicI64, i64, 8); atomic_int!(load_store_atomic, AtomicU64, u64, 8); } #[cfg(any(test, feature = "fallback"))] cfg_no_fast_atomic_64! { atomic_int!(all_critical_session, AtomicI64, i64, 8); atomic_int!(all_critical_session, AtomicU64, u64, 8); } #[cfg(any(test, feature = "fallback"))] atomic_int!(all_critical_session, AtomicI128, i128, 16); #[cfg(any(test, feature = "fallback"))] atomic_int!(all_critical_session, AtomicU128, u128, 16); #[cfg(test)] mod tests { use super::*; test_atomic_ptr_single_thread!(); test_atomic_int_single_thread!(i8); test_atomic_int_single_thread!(u8); test_atomic_int_single_thread!(i16); test_atomic_int_single_thread!(u16); test_atomic_int_single_thread!(i32); test_atomic_int_single_thread!(u32); test_atomic_int_single_thread!(i64); test_atomic_int_single_thread!(u64); test_atomic_int_single_thread!(i128); test_atomic_int_single_thread!(u128); test_atomic_int_single_thread!(isize); test_atomic_int_single_thread!(usize); } portable-atomic/src/imp/interrupt/msp430.rs0000644000175000017500000000575415105742312020503 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Adapted from https://github.com/rust-embedded/msp430. See also src/imp/msp430.rs. Refs: - MSP430x5xx and MSP430x6xx Family User's Guide, Rev. Q https://www.ti.com/lit/ug/slau208q/slau208q.pdf Generated asm: - msp430 https://godbolt.org/z/fc6h89xac */ #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; pub(super) use super::super::msp430 as atomic; pub(super) type State = u16; /// Disables interrupts and returns the previous interrupt state. #[inline(always)] pub(super) fn disable() -> State { let sr: State; // SAFETY: reading the status register and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. // Do not use `preserves_flags` because DINT modifies the GIE (global interrupt enable) bit of the status register. // See "NOTE: Enable and Disable Interrupt" of User's Guide for NOP: https://www.ti.com/lit/ug/slau208q/slau208q.pdf#page=60 #[cfg(not(portable_atomic_no_asm))] asm!( "mov r2, {sr}", // sr = SR "dint {{ nop", // SR.GIE = 0 sr = out(reg) sr, options(nostack), ); #[cfg(portable_atomic_no_asm)] { llvm_asm!("mov r2, $0" : "=r"(sr) ::: "volatile"); llvm_asm!("dint { nop" ::: "memory" : "volatile"); } } sr } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline(always)] pub(super) unsafe fn restore(prev_sr: State) { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, unsafe { // This clobbers the entire status register, but we never explicitly modify // flags within a critical session, and the only flags that may be changed // within a critical session are the arithmetic flags that are changed as // a side effect of arithmetic operations, etc., which LLVM recognizes, // so it is safe to clobber them here. // See also the discussion at https://github.com/taiki-e/portable-atomic/pull/40. // // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. // Do not use `preserves_flags` because MOV modifies the status register. // See "NOTE: Enable and Disable Interrupt" of User's Guide for NOP: https://www.ti.com/lit/ug/slau208q/slau208q.pdf#page=60 #[cfg(not(portable_atomic_no_asm))] asm!( "nop {{ mov {prev_sr}, r2 {{ nop", // SR = prev_sr prev_sr = in(reg) prev_sr, options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!("nop { mov $0, r2 { nop" :: "r"(prev_sr) : "memory" : "volatile"); } } portable-atomic/src/imp/interrupt/armv4t.rs0000644000175000017500000001351615105742312020665 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Refs: https://developer.arm.com/documentation/ddi0406/cb/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-ARM-core-registers/Program-Status-Registers--PSRs- Generated asm: - armv5te https://godbolt.org/z/fhaW3d9Kv */ #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; // - 0x80 - I (IRQ mask) bit (1 << 7) // - 0x40 - F (FIQ mask) bit (1 << 6) // We disable only IRQs by default. See also https://github.com/taiki-e/portable-atomic/pull/28#issuecomment-1214146912. #[cfg(not(portable_atomic_disable_fiq))] macro_rules! mask { () => { "0x80" }; } #[cfg(portable_atomic_disable_fiq)] macro_rules! mask { () => { "0xC0" // 0x80 | 0x40 }; } pub(super) type State = u32; /// Disables interrupts and returns the previous interrupt state. #[inline] #[instruction_set(arm::a32)] pub(super) fn disable() -> State { let cpsr: State; // SAFETY: reading CPSR and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { asm!( "mrs {prev}, cpsr", concat!("orr {new}, {prev}, ", mask!()), "msr cpsr_c, {new}", prev = out(reg) cpsr, new = out(reg) _, // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. options(nostack, preserves_flags), ); } cpsr } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline] #[instruction_set(arm::a32)] pub(super) unsafe fn restore(cpsr: State) { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, // // This clobbers the control field mask byte of CPSR. See msp430.rs to safety on this. // (preserves_flags is fine because we only clobber the I, F, T, and M bits of CPSR.) // // Refs: https://developer.arm.com/documentation/dui0473/m/arm-and-thumb-instructions/msr--general-purpose-register-to-psr- unsafe { // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. asm!("msr cpsr_c, {0}", in(reg) cpsr, options(nostack, preserves_flags)); } } // On pre-v6 Arm, we cannot use core::sync::atomic here because they call the // `__sync_*` builtins for non-relaxed load/store (because pre-v6 Arm doesn't // have Data Memory Barrier). // // Generated asm: // - armv5te https://godbolt.org/z/deqTqPzqz pub(crate) mod atomic { #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::{cell::UnsafeCell, sync::atomic::Ordering}; macro_rules! atomic { ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty $(as $cast:ty)?, $suffix:tt) => { #[repr(transparent)] pub(crate) struct $atomic_type $(<$($generics)*>)? { v: UnsafeCell<$value_type>, } // Send is implicitly implemented for atomic integers, but not for atomic pointers. // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Send for $atomic_type $(<$($generics)*>)? {} // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Sync for $atomic_type $(<$($generics)*>)? {} impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] pub(crate) fn load(&self, _order: Ordering) -> $value_type { let src = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { let out $(: $cast)?; // inline asm without nomem/readonly implies compiler fence. // And compiler fence is fine because the user explicitly declares that // the system is single-core by using an unsafe cfg. asm!( concat!("ldr", $suffix, " {out}, [{src}]"), src = in(reg) src, out = lateout(reg) out, options(nostack, preserves_flags), ); out $(as $cast as $value_type)? } } #[inline] pub(crate) fn store(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { // inline asm without nomem/readonly implies compiler fence. // And compiler fence is fine because the user explicitly declares that // the system is single-core by using an unsafe cfg. asm!( concat!("str", $suffix, " {val}, [{dst}]"), dst = in(reg) dst, val = in(reg) val $(as $cast)?, options(nostack, preserves_flags), ); } } } }; } atomic!(AtomicI8, i8, "b"); atomic!(AtomicU8, u8, "b"); atomic!(AtomicI16, i16, "h"); atomic!(AtomicU16, u16, "h"); atomic!(AtomicI32, i32, ""); atomic!(AtomicU32, u32, ""); atomic!(AtomicIsize, isize, ""); atomic!(AtomicUsize, usize, ""); atomic!([T] AtomicPtr, *mut T as *mut u8, ""); } portable-atomic/src/imp/interrupt/riscv.rs0000644000175000017500000000550115105742312020571 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Refs: - RISC-V Instruction Set Manual Machine Status (mstatus and mstatush) Registers https://github.com/riscv/riscv-isa-manual/blob/riscv-isa-release-8b9dc50-2024-08-30/src/machine.adoc#machine-status-mstatus-and-mstatush-registers Supervisor Status (sstatus) Register https://github.com/riscv/riscv-isa-manual/blob/riscv-isa-release-8b9dc50-2024-08-30/src/supervisor.adoc#supervisor-status-sstatus-register See also src/imp/riscv.rs. Generated asm: - riscv64gc https://godbolt.org/z/zTrzT1Ee7 */ #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; pub(super) use super::super::riscv as atomic; // Status register #[cfg(not(portable_atomic_s_mode))] macro_rules! status { () => { "mstatus" }; } #[cfg(portable_atomic_s_mode)] macro_rules! status { () => { "sstatus" }; } // MIE (Machine Interrupt Enable) bit (1 << 3) #[cfg(not(portable_atomic_s_mode))] const MASK: State = 0x8; #[cfg(not(portable_atomic_s_mode))] macro_rules! mask { () => { "0x8" }; } // SIE (Supervisor Interrupt Enable) bit (1 << 1) #[cfg(portable_atomic_s_mode)] const MASK: State = 0x2; #[cfg(portable_atomic_s_mode)] macro_rules! mask { () => { "0x2" }; } #[cfg(target_arch = "riscv32")] pub(super) type State = u32; #[cfg(target_arch = "riscv64")] pub(super) type State = u64; /// Disables interrupts and returns the previous interrupt state. #[inline(always)] pub(super) fn disable() -> State { let status: State; // SAFETY: reading mstatus/sstatus and disabling interrupts is safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. asm!( concat!("csrrci {status}, ", status!(), ", ", mask!()), // atomic { status = status!(); status!() &= !mask!() } status = out(reg) status, options(nostack, preserves_flags), ); } status } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline(always)] pub(super) unsafe fn restore(status: State) { if status & MASK != 0 { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, // and we've checked that interrupts were enabled before disabling interrupts. unsafe { // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. asm!( concat!("csrsi ", status!(), ", ", mask!()), // atomic { status!() |= mask!() } options(nostack, preserves_flags), ); } } } portable-atomic/src/imp/interrupt/avr.rs0000644000175000017500000000502015105742312020227 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Adapted from https://github.com/Rahix/avr-device. See also src/imp/avr.rs. Refs: - AVR® Instruction Set Manual, Rev. DS40002198B https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-InstructionSet-Manual-DS40002198.pdf Generated asm: - avr https://godbolt.org/z/W5jxGsToc */ #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; #[cfg(not(portable_atomic_no_asm))] pub(super) use super::super::avr as atomic; pub(super) type State = u8; /// Disables interrupts and returns the previous interrupt state. #[inline(always)] pub(super) fn disable() -> State { let sreg: State; // SAFETY: reading the status register (SREG) and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. // Do not use `preserves_flags` because CLI modifies the I bit of the status register (SREG). // Refs: https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-InstructionSet-Manual-DS40002198.pdf#page=58 #[cfg(not(portable_atomic_no_asm))] asm!( "in {sreg}, 0x3F", // sreg = SREG "cli", // SREG.I = 0 sreg = out(reg) sreg, options(nostack), ); #[cfg(portable_atomic_no_asm)] { llvm_asm!("in $0, 0x3F" : "=r"(sreg) ::: "volatile"); llvm_asm!("cli" ::: "memory" : "volatile"); } } sreg } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline(always)] pub(super) unsafe fn restore(prev_sreg: State) { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, unsafe { // This clobbers the entire status register. See msp430.rs to safety on this. // // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. // Do not use `preserves_flags` because OUT modifies the status register (SREG). #[cfg(not(portable_atomic_no_asm))] asm!( "out 0x3F, {prev_sreg}", // SREG = prev_sreg prev_sreg = in(reg) prev_sreg, options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!("out 0x3F, $0" :: "r"(prev_sreg) : "memory" : "volatile"); } } portable-atomic/src/imp/interrupt/xtensa.rs0000644000175000017500000000354015105742312020746 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Refs: - Xtensa Instruction Set Architecture (ISA) Summary for all Xtensa LX Processors https://www.cadence.com/content/dam/cadence-www/global/en_US/documents/tools/silicon-solutions/compute-ip/isa-summary.pdf - Linux kernel's Xtensa atomic implementation https://github.com/torvalds/linux/blob/v6.13/arch/xtensa/include/asm/atomic.h */ use core::arch::asm; pub(super) use core::sync::atomic; pub(super) type State = u32; /// Disables interrupts and returns the previous interrupt state. #[inline(always)] pub(super) fn disable() -> State { let ps: State; // SAFETY: reading the PS special register and disabling all interrupts is safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. // Interrupt level 15 to disable all interrupts. // SYNC after RSIL is not required. asm!("rsil {0}, 15", out(reg) ps, options(nostack)); } ps } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline(always)] pub(super) unsafe fn restore(ps: State) { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, // and we've checked that interrupts were enabled before disabling interrupts. unsafe { // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. // SYNC after WSR is required to guarantee that subsequent RSIL read the written value. asm!( "wsr.ps {0}", "rsync", in(reg) ps, options(nostack), ); } } portable-atomic/src/imp/interrupt/README.md0000644000175000017500000000650315105742312020357 0ustar bdrungbdrung# Implementation of disabling interrupts This module is used to provide atomic CAS for targets where atomic CAS is not available in the standard library. - On MSP430 and AVR, they are always single-core and has no unprivileged mode, so this module is always used. - On Armv6-M (thumbv6m), pre-v6 Arm (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa, they could be multi-core, so this module is used when the `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg) is enabled. The `unsafe-assume-single-core` implementation uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode. Enabling this feature in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent. Consider using the [`critical-section` feature](../../../README.md#optional-features-critical-section) for systems that cannot use the `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg). For some targets, the implementation can be changed by explicitly enabling features. - On Armv6-M, this disables interrupts by modifying the PRIMASK register. - On pre-v6 Arm, this disables interrupts by modifying the I (IRQ mask) bit of the CPSR. - On pre-v6 Arm with the `disable-fiq` feature (or `portable_atomic_disable_fiq` cfg), this disables interrupts by modifying the I (IRQ mask) bit and F (FIQ mask) bit of the CPSR. - On RISC-V (without A-extension), this disables interrupts by modifying the MIE (Machine Interrupt Enable) bit of the `mstatus` register. - On RISC-V (without A-extension) with the `s-mode` feature (or `portable_atomic_s_mode` cfg), this disables interrupts by modifying the SIE (Supervisor Interrupt Enable) bit of the `sstatus` register. - On RISC-V (without A-extension) with the `zaamo` target feature (or `force-amo` feature or `portable_atomic_force_amo` cfg), this uses AMO instructions for RMWs that have corresponding AMO instructions even if A-extension is disabled. For other RMWs, this disables interrupts as usual. - On MSP430, this disables interrupts by modifying the GIE (Global Interrupt Enable) bit of the status register (SR). - On AVR, this disables interrupts by modifying the I (Global Interrupt Enable) bit of the status register (SREG). - On Xtensa, this disables interrupts by modifying the PS special register. Some operations don't require disabling interrupts: - On architectures except for AVR: loads and stores with pointer size or smaller - On AVR: 8-bit loads and stores - On MSP430 additionally: {8,16}-bit `add,sub,and,or,xor,not` - On RISC-V with the `zaamo` target feature (or `portable_atomic_target_feature="zaamo"` cfg or `force-amo` feature or `portable_atomic_force_amo` cfg) additionally: 32-bit(RV32)/{32,64}-bit(RV64) `swap,fetch_{add,sub,and,or,xor,not,max,min},add,sub,and,or,xor,not`, {8,16}-bit `fetch_{and,or,xor,not},and,or,xor,not`[^1], and all operations of `AtomicBool` However, when the `critical-section` feature is enabled, critical sections are taken for all atomic operations. Feel free to submit an issue if your target is not supported yet. [^1]: With the `zabha` target feature, {8,16}-bit `swap,fetch_{add,sub,max,min},add,sub` too. portable-atomic/src/imp/interrupt/armv6m.rs0000644000175000017500000000310715105742312020653 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Adapted from https://github.com/rust-embedded/cortex-m. Generated asm: - armv6-m https://godbolt.org/z/1sqKnsY6n */ #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; pub(super) use core::sync::atomic; pub(super) type State = u32; /// Disables interrupts and returns the previous interrupt state. #[inline(always)] pub(super) fn disable() -> State { let primask: State; // SAFETY: reading the priority mask register and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. asm!( "mrs {0}, PRIMASK", "cpsid i", out(reg) primask, options(nostack, preserves_flags), ); } primask } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline(always)] pub(super) unsafe fn restore(primask: State) { if primask & 0x1 == 0 { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, // and we've checked that interrupts were enabled before disabling interrupts. unsafe { // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. asm!("cpsie i", options(nostack, preserves_flags)); } } } portable-atomic/src/imp/msp430.rs0000644000175000017500000002765615105742312016454 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Atomic implementation on MSP430. Adapted from https://github.com/pftbest/msp430-atomic. Operations not supported here are provided by disabling interrupts. See also src/imp/interrupt/msp430.rs. See "Atomic operation overview by architecture" in atomic-maybe-uninit for a more comprehensive and detailed description of the atomic and synchronize instructions in this architecture: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/README.md#msp430 Note: Ordering is always SeqCst. Refs: - MSP430x5xx and MSP430x6xx Family User's Guide, Rev. Q https://www.ti.com/lit/ug/slau208q/slau208q.pdf - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit Generated asm: - msp430 https://godbolt.org/z/MGrd4jPoq */ #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; #[cfg(not(feature = "critical-section"))] use core::cell::UnsafeCell; use core::sync::atomic::Ordering; /// An atomic fence. /// /// # Panics /// /// Panics if `order` is [`Relaxed`](Ordering::Relaxed). #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub fn fence(order: Ordering) { match order { Ordering::Relaxed => panic!("there is no such thing as a relaxed fence"), // MSP430 is single-core and a compiler fence works as an atomic fence. _ => compiler_fence(order), } } /// A compiler memory fence. /// /// # Panics /// /// Panics if `order` is [`Relaxed`](Ordering::Relaxed). #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub fn compiler_fence(order: Ordering) { match order { Ordering::Relaxed => panic!("there is no such thing as a relaxed compiler fence"), _ => {} } // SAFETY: using an empty asm is safe. unsafe { // Do not use `nomem` and `readonly` because prevent preceding and subsequent memory accesses from being reordered. #[cfg(not(portable_atomic_no_asm))] asm!("", options(nostack, preserves_flags)); #[cfg(portable_atomic_no_asm)] llvm_asm!("" ::: "memory" : "volatile"); } } macro_rules! atomic { (load_store, $([$($generics:tt)*])? $atomic_type:ident, $value_type:ty $(as $cast:ty)?, $size:tt ) => { #[cfg(not(feature = "critical-section"))] #[repr(transparent)] pub(crate) struct $atomic_type $(<$($generics)*>)? { v: UnsafeCell<$value_type>, } #[cfg(not(feature = "critical-section"))] // Send is implicitly implemented for atomic integers, but not for atomic pointers. // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Send for $atomic_type $(<$($generics)*>)? {} #[cfg(not(feature = "critical-section"))] // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Sync for $atomic_type $(<$($generics)*>)? {} #[cfg(not(feature = "critical-section"))] impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $value_type { crate::utils::assert_load_ordering(order); let src = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { let out $(: $cast)?; #[cfg(not(portable_atomic_no_asm))] asm!( concat!("mov.", $size, " @{src}, {out}"), // atomic { out = *src } src = in(reg) src, out = lateout(reg) out, options(nostack, preserves_flags), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("mov.", $size, " $1, $0") : "=r"(out) : "*m"(src) : "memory" : "volatile" ); out $(as $cast as $value_type)? } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $value_type, order: Ordering) { crate::utils::assert_store_ordering(order); let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("mov.", $size, " {val}, 0({dst})"), // atomic { *dst = val } dst = in(reg) dst, val = in(reg) val $(as $cast)?, options(nostack, preserves_flags), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("mov.", $size, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } } }; ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty $(as $cast:ty)?, $size:tt) => { atomic!(load_store, $([$($generics)*])? $atomic_type, $value_type $(as $cast)?, $size); #[cfg(not(feature = "critical-section"))] impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] pub(crate) fn add(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("add.", $size, " {val}, 0({dst})"), // atomic { *dst += val } dst = in(reg) dst, val = in(reg) val $(as $cast)?, // Do not use `preserves_flags` because ADD modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("add.", $size, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn sub(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("sub.", $size, " {val}, 0({dst})"), // atomic { *dst -= val } dst = in(reg) dst, val = in(reg) val $(as $cast)?, // Do not use `preserves_flags` because SUB modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("sub.", $size, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn and(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("and.", $size, " {val}, 0({dst})"), // atomic { *dst &= val } dst = in(reg) dst, val = in(reg) val $(as $cast)?, // Do not use `preserves_flags` because AND modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("and.", $size, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn or(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("bis.", $size, " {val}, 0({dst})"), // atomic { *dst |= val } dst = in(reg) dst, val = in(reg) val $(as $cast)?, options(nostack, preserves_flags), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("bis.", $size, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn xor(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("xor.", $size, " {val}, 0({dst})"), // atomic { *dst ^= val } dst = in(reg) dst, val = in(reg) val $(as $cast)?, // Do not use `preserves_flags` because XOR modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("xor.", $size, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn not(&self, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("inv.", $size, " 0({dst})"), // atomic { *dst = !*dst } dst = in(reg) dst, // Do not use `preserves_flags` because INV modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("inv.", $size, " $0") :: "*m"(dst) : "memory" : "volatile" ); } } } }; } atomic!(AtomicI8, i8, "b"); atomic!(AtomicU8, u8, "b"); atomic!(AtomicI16, i16, "w"); atomic!(AtomicU16, u16, "w"); atomic!(AtomicIsize, isize, "w"); atomic!(AtomicUsize, usize, "w"); atomic!(load_store, [T] AtomicPtr, *mut T as *mut u8, "w"); portable-atomic/src/imp/x86.rs0000644000175000017500000002207215105742312016036 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Atomic operations implementation on x86/x86_64. This module provides atomic operations not supported by LLVM or optimizes cases where LLVM code generation is not optimal. Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use this module and use CAS loop instead. Refs: - x86 and amd64 instruction reference https://www.felixcloutier.com/x86 Generated asm: - x86_64 https://godbolt.org/z/ETa1MGTP3 */ #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::sync::atomic::Ordering; use super::core_atomic::{ AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize, AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize, }; #[cfg(target_pointer_width = "32")] macro_rules! ptr_modifier { () => { ":e" }; } #[cfg(target_pointer_width = "64")] macro_rules! ptr_modifier { () => { "" }; } macro_rules! atomic_int { ($atomic_type:ident, $ptr_size:tt) => { impl $atomic_type { #[inline] pub(crate) fn not(&self, _order: Ordering) { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // // https://www.felixcloutier.com/x86/not unsafe { // atomic RMW is always SeqCst. asm!( concat!("lock not ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}]"), dst = in(reg) dst, options(nostack, preserves_flags), ); } } #[inline] pub(crate) fn neg(&self, _order: Ordering) { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // // https://www.felixcloutier.com/x86/neg unsafe { // atomic RMW is always SeqCst. asm!( concat!("lock neg ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}]"), dst = in(reg) dst, // Do not use `preserves_flags` because NEG modifies the CF, OF, SF, ZF, AF, and PF flag. options(nostack), ); } } } }; } atomic_int!(AtomicI8, "byte"); atomic_int!(AtomicU8, "byte"); atomic_int!(AtomicI16, "word"); atomic_int!(AtomicU16, "word"); atomic_int!(AtomicI32, "dword"); atomic_int!(AtomicU32, "dword"); #[cfg(target_arch = "x86_64")] atomic_int!(AtomicI64, "qword"); #[cfg(target_arch = "x86_64")] atomic_int!(AtomicU64, "qword"); #[cfg(target_pointer_width = "32")] atomic_int!(AtomicIsize, "dword"); #[cfg(target_pointer_width = "32")] atomic_int!(AtomicUsize, "dword"); #[cfg(target_pointer_width = "64")] atomic_int!(AtomicIsize, "qword"); #[cfg(target_pointer_width = "64")] atomic_int!(AtomicUsize, "qword"); #[cfg(target_arch = "x86")] impl AtomicI64 { #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } #[cfg(target_arch = "x86")] impl AtomicU64 { #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } macro_rules! atomic_bit_opts { ($atomic_type:ident, $int_type:ident, $val_modifier:tt, $ptr_size:tt) => { // LLVM 14 and older don't support generating `lock bt{s,r,c}`. // LLVM 15 only supports generating `lock bt{s,r,c}` for immediate bit offsets. // LLVM 16+ can generate `lock bt{s,r,c}` for both immediate and register bit offsets. // https://godbolt.org/z/TGhr5z4ds // So, use fetch_* based implementations on LLVM 16+, otherwise use asm based implementations. #[cfg(not(portable_atomic_pre_llvm_16))] impl_default_bit_opts!($atomic_type, $int_type); #[cfg(portable_atomic_pre_llvm_16)] impl $atomic_type { // `::BITS` requires Rust 1.53 const BITS: u32 = (core::mem::size_of::<$int_type>() * 8) as u32; #[inline] pub(crate) fn bit_set(&self, bit: u32, _order: Ordering) -> bool { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // the masking by the bit size of the type ensures that we do not shift // out of bounds. // // https://www.felixcloutier.com/x86/bts unsafe { let r: u8; // atomic RMW is always SeqCst. asm!( concat!("lock bts ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"), "setb {r}", dst = in(reg) dst, bit = in(reg) (bit & (Self::BITS - 1)) as $int_type, r = out(reg_byte) r, // Do not use `preserves_flags` because BTS modifies the CF flag. options(nostack), ); crate::utils::assert_unchecked(r == 0 || r == 1); // may help remove extra test r != 0 } } #[inline] pub(crate) fn bit_clear(&self, bit: u32, _order: Ordering) -> bool { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // the masking by the bit size of the type ensures that we do not shift // out of bounds. // // https://www.felixcloutier.com/x86/btr unsafe { let r: u8; // atomic RMW is always SeqCst. asm!( concat!("lock btr ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"), "setb {r}", dst = in(reg) dst, bit = in(reg) (bit & (Self::BITS - 1)) as $int_type, r = out(reg_byte) r, // Do not use `preserves_flags` because BTR modifies the CF flag. options(nostack), ); crate::utils::assert_unchecked(r == 0 || r == 1); // may help remove extra test r != 0 } } #[inline] pub(crate) fn bit_toggle(&self, bit: u32, _order: Ordering) -> bool { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // the masking by the bit size of the type ensures that we do not shift // out of bounds. // // https://www.felixcloutier.com/x86/btc unsafe { let r: u8; // atomic RMW is always SeqCst. asm!( concat!("lock btc ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"), "setb {r}", dst = in(reg) dst, bit = in(reg) (bit & (Self::BITS - 1)) as $int_type, r = out(reg_byte) r, // Do not use `preserves_flags` because BTC modifies the CF flag. options(nostack), ); crate::utils::assert_unchecked(r == 0 || r == 1); // may help remove extra test r != 0 } } } }; } impl_default_bit_opts!(AtomicI8, i8); impl_default_bit_opts!(AtomicU8, u8); atomic_bit_opts!(AtomicI16, i16, ":x", "word"); atomic_bit_opts!(AtomicU16, u16, ":x", "word"); atomic_bit_opts!(AtomicI32, i32, ":e", "dword"); atomic_bit_opts!(AtomicU32, u32, ":e", "dword"); #[cfg(target_arch = "x86_64")] atomic_bit_opts!(AtomicI64, i64, "", "qword"); #[cfg(target_arch = "x86_64")] atomic_bit_opts!(AtomicU64, u64, "", "qword"); #[cfg(target_arch = "x86")] impl_default_bit_opts!(AtomicI64, i64); #[cfg(target_arch = "x86")] impl_default_bit_opts!(AtomicU64, u64); #[cfg(target_pointer_width = "32")] atomic_bit_opts!(AtomicIsize, isize, ":e", "dword"); #[cfg(target_pointer_width = "32")] atomic_bit_opts!(AtomicUsize, usize, ":e", "dword"); #[cfg(target_pointer_width = "64")] atomic_bit_opts!(AtomicIsize, isize, "", "qword"); #[cfg(target_pointer_width = "64")] atomic_bit_opts!(AtomicUsize, usize, "", "qword"); portable-atomic/src/imp/atomic64/0000775000175000017500000000000015105742312016470 5ustar bdrungbdrungportable-atomic/src/imp/atomic64/mod.rs0000644000175000017500000000243715105742312017621 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 64-bit atomic implementations on 32-bit architectures See README.md for details. */ // pre-v6 Arm Linux #[cfg(feature = "fallback")] // Miri and Sanitizer do not support inline assembly. #[cfg(all( target_arch = "arm", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_os = "linux", target_os = "android"), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(portable_atomic_no_outline_atomics), ))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))] pub(super) mod arm_linux; // riscv32 // Miri and Sanitizer do not support inline assembly. #[cfg(all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "zacas", portable_atomic_target_feature = "zacas", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(target_os = "linux", target_os = "android"), ), ), ))] pub(super) mod riscv32; portable-atomic/src/imp/atomic64/arm_linux.rs0000644000175000017500000002427315105742312021042 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 64-bit atomic implementation using kuser_cmpxchg64 on pre-v6 Arm Linux/Android. Refs: - https://github.com/torvalds/linux/blob/v6.13/Documentation/arch/arm/kernel_user_helpers.rst - https://github.com/rust-lang/compiler-builtins/blob/compiler_builtins-v0.1.124/src/arm_linux.rs Note: __kuser_cmpxchg64 is always SeqCst. https://github.com/torvalds/linux/blob/v6.13/arch/arm/kernel/entry-armv.S#L700-L707 Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use this module and use fallback implementation instead. */ // TODO: Since Rust 1.64, the Linux kernel requirement for Rust when using std is 3.2+, so it should // be possible to omit the dynamic kernel version check if the std feature is enabled on Rust 1.64+. // https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html include!("macros.rs"); #[path = "../fallback/outline_atomics.rs"] mod fallback; #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::{mem, sync::atomic::Ordering}; use crate::utils::{Pair, U64}; // https://github.com/torvalds/linux/blob/v6.13/Documentation/arch/arm/kernel_user_helpers.rst const KUSER_HELPER_VERSION: usize = 0xFFFF0FFC; // __kuser_helper_version >= 5 (kernel version 3.1+) const KUSER_CMPXCHG64: usize = 0xFFFF0F60; #[inline] fn __kuser_helper_version() -> i32 { use core::sync::atomic::AtomicI32; static CACHE: AtomicI32 = AtomicI32::new(0); let mut v = CACHE.load(Ordering::Relaxed); if v != 0 { return v; } // SAFETY: core assumes that at least __kuser_memory_barrier (__kuser_helper_version >= 3, // kernel version 2.6.15+) is available on this platform. __kuser_helper_version // is always available on such a platform. v = unsafe { crate::utils::ptr::with_exposed_provenance::(KUSER_HELPER_VERSION).read() }; CACHE.store(v, Ordering::Relaxed); v } #[inline] fn has_kuser_cmpxchg64() -> bool { // Note: detect_false cfg is intended to make it easy for portable-atomic developers to // test cases such as has_cmpxchg16b == false, has_lse == false, // __kuser_helper_version < 5, etc., and is not a public API. if cfg!(portable_atomic_test_outline_atomics_detect_false) { return false; } __kuser_helper_version() >= 5 } #[inline] unsafe fn __kuser_cmpxchg64(old_val: *const u64, new_val: *const u64, ptr: *mut u64) -> bool { // SAFETY: the caller must uphold the safety contract. unsafe { let f: extern "C" fn(*const u64, *const u64, *mut u64) -> u32 = mem::transmute(crate::utils::ptr::with_exposed_provenance::<()>(KUSER_CMPXCHG64)); f(old_val, new_val, ptr) == 0 } } // 64-bit atomic load by two 32-bit atomic loads. #[inline] unsafe fn byte_wise_atomic_load(src: *const u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { let (out_lo, out_hi); asm!( "ldr {out_lo}, [{src}]", "ldr {out_hi}, [{src}, #4]", src = in(reg) src, out_lo = out(reg) out_lo, out_hi = out(reg) out_hi, options(pure, nostack, preserves_flags, readonly), ); U64 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } macro_rules! select_atomic { ( unsafe fn $name:ident($dst:ident: *mut u64 $(, $($arg:tt)*)?) $(-> $ret_ty:ty)? { |$kuser_cmpxchg64_fn_binding:ident| $($kuser_cmpxchg64_fn_body:tt)* } fallback = $seqcst_fallback_fn:ident ) => { #[inline] unsafe fn $name($dst: *mut u64 $(, $($arg)*)?, _: Ordering) $(-> $ret_ty)? { unsafe fn kuser_cmpxchg64_fn($dst: *mut u64 $(, $($arg)*)?) $(-> $ret_ty)? { debug_assert!($dst as usize % 8 == 0); debug_assert!(has_kuser_cmpxchg64()); // SAFETY: the caller must uphold the safety contract. unsafe { loop { // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // Arm's memory model allow mixed-sized atomic access. // https://github.com/rust-lang/unsafe-code-guidelines/issues/345#issuecomment-1172891466 // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement byte_wise_atomic_load. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). let prev = byte_wise_atomic_load($dst); let next = { let $kuser_cmpxchg64_fn_binding = prev; $($kuser_cmpxchg64_fn_body)* }; if __kuser_cmpxchg64(&prev, &next, $dst) { return prev; } } } } // SAFETY: the caller must uphold the safety contract. // we only calls __kuser_cmpxchg64 if it is available. unsafe { ifunc!(unsafe fn($dst: *mut u64 $(, $($arg)*)?) $(-> $ret_ty)? { if has_kuser_cmpxchg64() { kuser_cmpxchg64_fn } else { // Use SeqCst because __kuser_cmpxchg64 is always SeqCst. fallback::$seqcst_fallback_fn } }) } } }; } select_atomic! { unsafe fn atomic_load(src: *mut u64) -> u64 { |old| old } fallback = atomic_load_seqcst } #[inline] unsafe fn atomic_store(dst: *mut u64, val: u64, order: Ordering) { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_swap(dst, val, order); } } select_atomic! { unsafe fn atomic_swap(dst: *mut u64, val: u64) -> u64 { |_x| val } fallback = atomic_swap_seqcst } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u64, old: u64, new: u64, _: Ordering, _: Ordering, ) -> Result { unsafe fn kuser_cmpxchg64_fn(dst: *mut u64, old: u64, new: u64) -> (u64, bool) { debug_assert!(dst as usize % 8 == 0); debug_assert!(has_kuser_cmpxchg64()); // SAFETY: the caller must uphold the safety contract. unsafe { loop { // See select_atomic! for more. let prev = byte_wise_atomic_load(dst); let next = if prev == old { new } else { prev }; if __kuser_cmpxchg64(&prev, &next, dst) { return (prev, prev == old); } } } } // SAFETY: the caller must uphold the safety contract. // we only calls __kuser_cmpxchg64 if it is available. let (prev, ok) = unsafe { ifunc!(unsafe fn(dst: *mut u64, old: u64, new: u64) -> (u64, bool) { if has_kuser_cmpxchg64() { kuser_cmpxchg64_fn } else { // Use SeqCst because __kuser_cmpxchg64 is always SeqCst. fallback::atomic_compare_exchange_seqcst } }) }; if ok { Ok(prev) } else { Err(prev) } } use self::atomic_compare_exchange as atomic_compare_exchange_weak; select_atomic! { unsafe fn atomic_add(dst: *mut u64, val: u64) -> u64 { |x| x.wrapping_add(val) } fallback = atomic_add_seqcst } select_atomic! { unsafe fn atomic_sub(dst: *mut u64, val: u64) -> u64 { |x| x.wrapping_sub(val) } fallback = atomic_sub_seqcst } select_atomic! { unsafe fn atomic_and(dst: *mut u64, val: u64) -> u64 { |x| x & val } fallback = atomic_and_seqcst } select_atomic! { unsafe fn atomic_nand(dst: *mut u64, val: u64) -> u64 { |x| !(x & val) } fallback = atomic_nand_seqcst } select_atomic! { unsafe fn atomic_or(dst: *mut u64, val: u64) -> u64 { |x| x | val } fallback = atomic_or_seqcst } select_atomic! { unsafe fn atomic_xor(dst: *mut u64, val: u64) -> u64 { |x| x ^ val } fallback = atomic_xor_seqcst } select_atomic! { unsafe fn atomic_max(dst: *mut u64, val: u64) -> u64 { |x| { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] { core::cmp::max(x as i64, val as i64) as u64 } } } fallback = atomic_max_seqcst } select_atomic! { unsafe fn atomic_umax(dst: *mut u64, val: u64) -> u64 { |x| core::cmp::max(x, val) } fallback = atomic_umax_seqcst } select_atomic! { unsafe fn atomic_min(dst: *mut u64, val: u64) -> u64 { |x| { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] { core::cmp::min(x as i64, val as i64) as u64 } } } fallback = atomic_min_seqcst } select_atomic! { unsafe fn atomic_umin(dst: *mut u64, val: u64) -> u64 { |x| core::cmp::min(x, val) } fallback = atomic_umin_seqcst } select_atomic! { unsafe fn atomic_not(dst: *mut u64) -> u64 { |x| !x } fallback = atomic_not_seqcst } select_atomic! { unsafe fn atomic_neg(dst: *mut u64) -> u64 { |x| x.wrapping_neg() } fallback = atomic_neg_seqcst } #[inline] fn is_lock_free() -> bool { has_kuser_cmpxchg64() } const IS_ALWAYS_LOCK_FREE: bool = false; atomic64!(AtomicI64, i64, atomic_max, atomic_min); atomic64!(AtomicU64, u64, atomic_umax, atomic_umin); #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; #[test] fn kuser_helper_version() { let version = __kuser_helper_version(); assert!(version >= 5, "{:?}", version); assert_eq!(version, unsafe { crate::utils::ptr::with_exposed_provenance::(KUSER_HELPER_VERSION).read() }); } test_atomic_int!(i64); test_atomic_int!(u64); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u64); } portable-atomic/src/imp/atomic64/riscv32.rs0000644000175000017500000005724415105742312020343 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 64-bit atomic implementation on riscv32. This architecture provides the following 64-bit atomic instructions: - amocas.d: CAS (Zacas extension) See "Atomic operation overview by architecture" in atomic-maybe-uninit for a more comprehensive and detailed description of the atomic and synchronize instructions in this architecture: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/README.md#risc-v Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use this module and use fallback implementation instead. Refs: - RISC-V Instruction Set Manual "Zacas" Extension for Atomic Compare-and-Swap (CAS) Instructions https://github.com/riscv/riscv-isa-manual/blob/riscv-isa-release-8b9dc50-2024-08-30/src/zacas.adoc - RISC-V Atomics ABI Specification https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-atomic.adoc Generated asm: - riscv32imac (+zacas) https://godbolt.org/z/9bTdfhKre */ // TODO: merge duplicated code with atomic128/riscv64.rs include!("macros.rs"); #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] #[path = "../fallback/outline_atomics.rs"] mod fallback; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))))] #[cfg(any(target_os = "linux", target_os = "android"))] #[path = "../detect/riscv_linux.rs"] mod detect; #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::sync::atomic::Ordering; use crate::utils::{Pair, U64}; macro_rules! debug_assert_zacas { () => { #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] { debug_assert!(detect::detect().has_zacas()); } }; } // `.option arch, +zacas` directive requires LLVM 20, so we use .4byte directive for old LLVM. // Note that `.insn ` directive requires LLVM 19. // https://github.com/llvm/llvm-project/commit/2a086dce691e3cc34a2fc27f4fb255bb2cbbfac9 // https://github.com/riscv-non-isa/riscv-asm-manual/blob/ad0de8c004e29c9a7ac33cfd054f4d4f9392f2fb/src/asm-manual.adoc#arch #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! start_zacas { () => { ".option push\n.option arch, +zacas" }; } #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! end_zacas { () => { ".option pop" }; } #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! atomic_rmw_amocas_order { ($op:ident, $order:ident) => { atomic_rmw_amocas_order!($op, $order, failure = $order) }; ($op:ident, $order:ident, failure = $failure:ident) => { match $order { Ordering::Relaxed => $op!("", ""), Ordering::Acquire => $op!("", ".aq"), Ordering::Release => $op!("", ".rl"), Ordering::AcqRel => $op!("", ".aqrl"), Ordering::SeqCst if $failure == Ordering::SeqCst => $op!("fence rw,rw", ".aqrl"), Ordering::SeqCst => $op!("", ".aqrl"), _ => unreachable!(), } }; } #[cfg(portable_atomic_pre_llvm_20)] macro_rules! atomic_rmw_amocas_order_insn { ($op:ident, $order:ident) => { atomic_rmw_amocas_order_insn!($op, $order, failure = $order) }; ($op:ident, $order:ident, failure = $failure:ident) => { match $order { Ordering::Relaxed => $op!("", "8"), Ordering::Acquire => $op!("", "c"), Ordering::Release => $op!("", "a"), Ordering::AcqRel => $op!("", "e"), Ordering::SeqCst if $failure == Ordering::SeqCst => $op!("fence rw,rw", "e"), Ordering::SeqCst => $op!("", "e"), _ => unreachable!(), } }; } // If zacas is available at compile-time, we can always use zacas_fn. #[cfg(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))] use self::atomic_load_zacas as atomic_load; // Otherwise, we need to do run-time detection and can use zacas_fn only if zacas is available. #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] #[inline] unsafe fn atomic_load(src: *mut u64, order: Ordering) -> u64 { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(src: *mut u64) -> u64; atomic_load_zacas_relaxed = atomic_load_zacas(Ordering::Relaxed); atomic_load_zacas_acquire = atomic_load_zacas(Ordering::Acquire); atomic_load_zacas_seqcst = atomic_load_zacas(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls atomic_load_zacas if zacas is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(src: *mut u64) -> u64 { if detect::detect().has_zacas() { atomic_load_zacas_relaxed } else { fallback::atomic_load_non_seqcst } }) } Ordering::Acquire => { ifunc!(unsafe fn(src: *mut u64) -> u64 { if detect::detect().has_zacas() { atomic_load_zacas_acquire } else { fallback::atomic_load_non_seqcst } }) } Ordering::SeqCst => { ifunc!(unsafe fn(src: *mut u64) -> u64 { if detect::detect().has_zacas() { atomic_load_zacas_seqcst } else { fallback::atomic_load_seqcst } }) } _ => unreachable!(), } } } #[inline] unsafe fn atomic_load_zacas(src: *mut u64, order: Ordering) -> u64 { debug_assert!(src as usize % 8 == 0); debug_assert_zacas!(); let (out_lo, out_hi); // SAFETY: the caller must uphold the safety contract. unsafe { #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! load { ($fence:tt, $asm_order:tt) => { asm!( start_zacas!(), $fence, // fence concat!("amocas.d", $asm_order, " a2, a2, 0({src})"), // atomic { if *dst == a2:a3 { *dst = a2:a3 } else { a2:a3 = *dst } } end_zacas!(), src = in(reg) ptr_reg!(src), inout("a2") 0_u32 => out_lo, inout("a3") 0_u32 => out_hi, options(nostack, preserves_flags), ) }; } #[cfg(not(portable_atomic_pre_llvm_20))] atomic_rmw_amocas_order!(load, order); #[cfg(portable_atomic_pre_llvm_20)] macro_rules! load { ($fence:tt, $insn_order:tt) => { asm!( $fence, // fence // amocas.d{,.aq,.rl,.aqrl} a2, a2, (a0) // atomic { if *a0 == a2:a3 { *a0 = a2:a3 } else { a2:a3 = *a0 } } concat!(".4byte 0x2", $insn_order, "c5362f"), in("a0") ptr_reg!(src), inout("a2") 0_u32 => out_lo, inout("a3") 0_u32 => out_hi, options(nostack, preserves_flags), ) }; } #[cfg(portable_atomic_pre_llvm_20)] atomic_rmw_amocas_order_insn!(load, order); U64 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } #[inline] unsafe fn atomic_store(dst: *mut u64, val: u64, order: Ordering) { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_swap(dst, val, order); } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u64, old: u64, new: u64, success: Ordering, failure: Ordering, ) -> Result { #[cfg(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))] // SAFETY: the caller must uphold the safety contract. // cfg guarantees that zacas instructions are available at compile-time. let (prev, ok) = unsafe { atomic_compare_exchange_zacas(dst, old, new, success, failure) }; #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] let (prev, ok) = { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u64, old: u64, new: u64) -> (u64, bool); zacas_relaxed_fn = atomic_compare_exchange_zacas(Ordering::Relaxed, Ordering::Relaxed); zacas_acquire_fn = atomic_compare_exchange_zacas(Ordering::Acquire, Ordering::Acquire); zacas_release_fn = atomic_compare_exchange_zacas(Ordering::Release, Ordering::Relaxed); zacas_acqrel_fn = atomic_compare_exchange_zacas(Ordering::AcqRel, Ordering::Acquire); zacas_seqcst_fn = atomic_compare_exchange_zacas(Ordering::SeqCst, Ordering::SeqCst); } let order = crate::utils::upgrade_success_ordering(success, failure); // SAFETY: the caller must uphold the safety contract. // we only calls atomic_compare_exchange_zacas if zacas is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u64, old: u64, new: u64) -> (u64, bool) { if detect::detect().has_zacas() { zacas_relaxed_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::Acquire => { ifunc!(unsafe fn(dst: *mut u64, old: u64, new: u64) -> (u64, bool) { if detect::detect().has_zacas() { zacas_acquire_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u64, old: u64, new: u64) -> (u64, bool) { if detect::detect().has_zacas() { zacas_release_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::AcqRel => { ifunc!(unsafe fn(dst: *mut u64, old: u64, new: u64) -> (u64, bool) { if detect::detect().has_zacas() { zacas_acqrel_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u64, old: u64, new: u64) -> (u64, bool) { if detect::detect().has_zacas() { zacas_seqcst_fn } else { fallback::atomic_compare_exchange_seqcst } }) } _ => unreachable!(), } } }; if ok { Ok(prev) } else { Err(prev) } } #[inline] unsafe fn atomic_compare_exchange_zacas( dst: *mut u64, old: u64, new: u64, success: Ordering, failure: Ordering, ) -> (u64, bool) { debug_assert!(dst as usize % 8 == 0); debug_assert_zacas!(); let order = crate::utils::upgrade_success_ordering(success, failure); let old = U64 { whole: old }; let new = U64 { whole: new }; let (prev_lo, prev_hi); // SAFETY: the caller must uphold the safety contract. unsafe { #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! cmpxchg { ($fence:tt, $asm_order:tt) => { asm!( start_zacas!(), $fence, // fence concat!("amocas.d", $asm_order, " a4, a2, 0({dst})"), // atomic { if *dst == a4:a5 { *dst = a2:a3 } else { a4:a5 = *dst } } end_zacas!(), dst = in(reg) ptr_reg!(dst), // must be allocated to even/odd register pair inout("a4") old.pair.lo => prev_lo, inout("a5") old.pair.hi => prev_hi, // must be allocated to even/odd register pair in("a2") new.pair.lo, in("a3") new.pair.hi, options(nostack, preserves_flags), ) }; } #[cfg(not(portable_atomic_pre_llvm_20))] atomic_rmw_amocas_order!(cmpxchg, order, failure = failure); #[cfg(portable_atomic_pre_llvm_20)] macro_rules! cmpxchg { ($fence:tt, $insn_order:tt) => { asm!( $fence, // fence // amocas.d{,.aq,.rl,.aqrl} a4, a2, (a0) // atomic { if *a0 == a4:a5 { *a0 = a2:a3 } else { a4:a5 = *a0 } } concat!(".4byte 0x2", $insn_order, "c5372f"), in("a0") ptr_reg!(dst), // must be allocated to even/odd register pair inout("a4") old.pair.lo => prev_lo, inout("a5") old.pair.hi => prev_hi, // must be allocated to even/odd register pair in("a2") new.pair.lo, in("a3") new.pair.hi, options(nostack, preserves_flags), ) }; } #[cfg(portable_atomic_pre_llvm_20)] atomic_rmw_amocas_order_insn!(cmpxchg, order, failure = failure); let prev = U64 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole; (prev, prev == old.whole) } } // amocas is always strong. use self::atomic_compare_exchange as atomic_compare_exchange_weak; // 64-bit atomic load by two 32-bit atomic loads. #[inline] unsafe fn byte_wise_atomic_load(src: *const u64) -> u64 { let (out_lo, out_hi); // SAFETY: the caller must uphold the safety contract. unsafe { asm!( "lw {out_lo}, ({src})", // atomic { out_lo = *src } "lw {out_hi}, 4({src})", // atomic { out_hi = *src.add(4) } src = in(reg) ptr_reg!(src), out_lo = out(reg) out_lo, out_hi = out(reg) out_hi, options(pure, nostack, preserves_flags, readonly), ); U64 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } macro_rules! select_atomic_rmw { ( unsafe fn $name:ident(dst: *mut u64 $(, $($arg:tt)*)?) $(-> $ret_ty:ty)? { |$zacas_fn_binding:ident| $($zacas_fn_body:tt)* } zacas = $zacas_fn:ident; non_seqcst_fallback = $non_seqcst_fallback_fn:ident; seqcst_fallback = $seqcst_fallback_fn:ident; ) => { #[inline] unsafe fn $zacas_fn(dst: *mut u64 $(, $($arg)*)?, order: Ordering) $(-> $ret_ty)? { // SAFETY: the caller must uphold the safety contract. unsafe { // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement byte_wise_atomic_load. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). let mut prev = byte_wise_atomic_load(dst); loop { let next = { let $zacas_fn_binding = prev; $($zacas_fn_body)* }; match atomic_compare_exchange_weak(dst, prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(x) => prev = x, } } } } // If zacas is available at compile-time, we can always use zacas_fn. #[cfg(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))] use self::$zacas_fn as $name; // Otherwise, we need to do run-time detection and can use zacas_fn only if zacas is available. #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] #[inline] unsafe fn $name(dst: *mut u64 $(, $($arg)*)?, order: Ordering) $(-> $ret_ty)? { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u64 $(, $($arg)*)?) $(-> $ret_ty)?; zacas_relaxed_fn = $zacas_fn(Ordering::Relaxed); zacas_acquire_fn = $zacas_fn(Ordering::Acquire); zacas_release_fn = $zacas_fn(Ordering::Release); zacas_acqrel_fn = $zacas_fn(Ordering::AcqRel); zacas_seqcst_fn = $zacas_fn(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls zacas_fn if zacas is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u64 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_relaxed_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::Acquire => { ifunc!(unsafe fn(dst: *mut u64 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_acquire_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u64 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_release_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::AcqRel => { ifunc!(unsafe fn(dst: *mut u64 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_acqrel_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u64 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_seqcst_fn } else { fallback::$seqcst_fallback_fn } }) } _ => unreachable!(), } } } }; } select_atomic_rmw! { unsafe fn atomic_swap(dst: *mut u64, val: u64) -> u64 { |_x| val } zacas = atomic_swap_zacas; non_seqcst_fallback = atomic_swap_non_seqcst; seqcst_fallback = atomic_swap_seqcst; } select_atomic_rmw! { unsafe fn atomic_add(dst: *mut u64, val: u64) -> u64 { |x| x.wrapping_add(val) } zacas = atomic_add_zacas; non_seqcst_fallback = atomic_add_non_seqcst; seqcst_fallback = atomic_add_seqcst; } select_atomic_rmw! { unsafe fn atomic_sub(dst: *mut u64, val: u64) -> u64 { |x| x.wrapping_sub(val) } zacas = atomic_sub_zacas; non_seqcst_fallback = atomic_sub_non_seqcst; seqcst_fallback = atomic_sub_seqcst; } select_atomic_rmw! { unsafe fn atomic_and(dst: *mut u64, val: u64) -> u64 { |x| x & val } zacas = atomic_and_zacas; non_seqcst_fallback = atomic_and_non_seqcst; seqcst_fallback = atomic_and_seqcst; } select_atomic_rmw! { unsafe fn atomic_nand(dst: *mut u64, val: u64) -> u64 { |x| !(x & val) } zacas = atomic_nand_zacas; non_seqcst_fallback = atomic_nand_non_seqcst; seqcst_fallback = atomic_nand_seqcst; } select_atomic_rmw! { unsafe fn atomic_or(dst: *mut u64, val: u64) -> u64 { |x| x | val } zacas = atomic_or_zacas; non_seqcst_fallback = atomic_or_non_seqcst; seqcst_fallback = atomic_or_seqcst; } select_atomic_rmw! { unsafe fn atomic_xor(dst: *mut u64, val: u64) -> u64 { |x| x ^ val } zacas = atomic_xor_zacas; non_seqcst_fallback = atomic_xor_non_seqcst; seqcst_fallback = atomic_xor_seqcst; } select_atomic_rmw! { unsafe fn atomic_max(dst: *mut u64, val: u64) -> u64 { |x| { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] { core::cmp::max(x as i64, val as i64) as u64 } } } zacas = atomic_max_zacas; non_seqcst_fallback = atomic_max_non_seqcst; seqcst_fallback = atomic_max_seqcst; } select_atomic_rmw! { unsafe fn atomic_umax(dst: *mut u64, val: u64) -> u64 { |x| core::cmp::max(x, val) } zacas = atomic_umax_zacas; non_seqcst_fallback = atomic_umax_non_seqcst; seqcst_fallback = atomic_umax_seqcst; } select_atomic_rmw! { unsafe fn atomic_min(dst: *mut u64, val: u64) -> u64 { |x| { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] { core::cmp::min(x as i64, val as i64) as u64 } } } zacas = atomic_min_zacas; non_seqcst_fallback = atomic_min_non_seqcst; seqcst_fallback = atomic_min_seqcst; } select_atomic_rmw! { unsafe fn atomic_umin(dst: *mut u64, val: u64) -> u64 { |x| core::cmp::min(x, val) } zacas = atomic_umin_zacas; non_seqcst_fallback = atomic_umin_non_seqcst; seqcst_fallback = atomic_umin_seqcst; } select_atomic_rmw! { unsafe fn atomic_not(dst: *mut u64) -> u64 { |x| !x } zacas = atomic_not_zacas; non_seqcst_fallback = atomic_not_non_seqcst; seqcst_fallback = atomic_not_seqcst; } select_atomic_rmw! { unsafe fn atomic_neg(dst: *mut u64) -> u64 { |x| x.wrapping_neg() } zacas = atomic_neg_zacas; non_seqcst_fallback = atomic_neg_non_seqcst; seqcst_fallback = atomic_neg_seqcst; } #[inline] fn is_lock_free() -> bool { #[cfg(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))] { // zacas is available at compile-time. true } #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] { detect::detect().has_zacas() } } const IS_ALWAYS_LOCK_FREE: bool = cfg!(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")); atomic64!(AtomicI64, i64, atomic_max, atomic_min); atomic64!(AtomicU64, u64, atomic_umax, atomic_umin); #[allow(clippy::undocumented_unsafe_blocks, clippy::wildcard_imports)] #[cfg(test)] mod tests { use super::*; test_atomic_int!(i64); test_atomic_int!(u64); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u64); } portable-atomic/src/imp/atomic64/README.md0000644000175000017500000000324515105742312017751 0ustar bdrungbdrung# 64-bit atomic implementations on 32-bit architectures (See the [`atomic128` module](../atomic128) for 128-bit atomic implementations on 64-bit architectures.) ## 64-bit atomic instructions Here is the table of targets that support 64-bit atomics and the instructions used: | target_arch | load | store | CAS | RMW | note | | ----------- | ---- | ----- | --- | --- | ---- | | x86 | cmpxchg8b or fild or movlps or movq | cmpxchg8b or fistp or movlps | cmpxchg8b | cmpxchg8b | provided by `core::sync::atomic` | | arm | ldrexd | ldrexd/strexd | ldrexd/strexd | ldrexd/strexd | provided by `core::sync::atomic` for Armv6+, otherwise provided by us for Linux/Android using kuser_cmpxchg64 (see [arm_linux.rs](arm_linux.rs) for more) | | riscv32 | amocas.d | amocas.d | amocas.d | amocas.d | Requires `zacas` target feature. Both compile-time and run-time detection are supported.
Requires rustc 1.59+ | | hexagon | memd | memd | memd_locked | memd_locked | Unimplemented | | sparc | ldx | stx | casx | casx | Unimplemented (unsupported in LLVM). Requires `v8plus` and `v9` target feature (Linux is v8plus+v9 by default) | | m68k | cas2 | cas2 | cas2 | cas2 | Unimplemented (unsupported in LLVM). Requires M68020 or later (Linux is M68020 by default) | | mips32r6 | llwp | llwp/scwp | llwp/scwp | llwp/scwp | Unimplemented (unsupported in LLVM). Requires Release 6 Paired LL/SC family of instructions | If `core::sync::atomic` provides 64-bit atomics, we use them. On compiler versions or platforms where these are not supported, the fallback implementation is used. ## Run-time CPU feature detection See the [`detect` module's readme](../detect/README.md) for run-time CPU feature detection. portable-atomic/src/imp/atomic64/macros.rs0000644000175000017500000002554615105742312020334 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT macro_rules! atomic64 { ($atomic_type:ident, $int_type:ident, $atomic_max:ident, $atomic_min:ident) => { #[repr(C, align(8))] pub(crate) struct $atomic_type { v: core::cell::UnsafeCell<$int_type>, } // Send is implicitly implemented. // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock. unsafe impl Sync for $atomic_type {} impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { v: core::cell::UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { is_lock_free() } pub(crate) const IS_ALWAYS_LOCK_FREE: bool = IS_ALWAYS_LOCK_FREE; #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_load(self.v.get().cast::(), order) as $int_type } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_store(self.v.get().cast::(), val as u64, order) } } #[inline] pub(crate) fn swap(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_swap(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { match atomic_compare_exchange( self.v.get().cast::(), current as u64, new as u64, success, failure, ) { Ok(v) => Ok(v as $int_type), Err(v) => Err(v as $int_type), } } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { match atomic_compare_exchange_weak( self.v.get().cast::(), current as u64, new as u64, success, failure, ) { Ok(v) => Ok(v as $int_type), Err(v) => Err(v as $int_type), } } } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_add(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_sub(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_and(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_nand(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_or(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_xor(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { $atomic_max(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { $atomic_min(self.v.get().cast::(), val as u64, order) as $int_type } } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_not(self.v.get().cast::(), order) as $int_type } } #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn fetch_neg(&self, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics, the kernel user helper, or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_neg(self.v.get().cast::(), order) as $int_type } } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } }; } portable-atomic/src/imp/riscv.rs0000644000175000017500000012041515105742312016537 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Atomic load/store implementation on RISC-V. This is for RISC-V targets without A extension. (pre-1.76 rustc doesn't provide atomics at all on such targets. https://github.com/rust-lang/rust/pull/114499) Also, optionally provides RMW implementation when Zaamo extension or force-amo feature is enabled. See "Atomic operation overview by architecture" in atomic-maybe-uninit for a more comprehensive and detailed description of the atomic and synchronize instructions in this architecture: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/README.md#risc-v Refs: - RISC-V Instruction Set Manual "Zaamo" Extension for Atomic Memory Operations https://github.com/riscv/riscv-isa-manual/blob/riscv-isa-release-8b9dc50-2024-08-30/src/a-st-ext.adoc#zaamo-extension-for-atomic-memory-operations "Zabha" Extension for Byte and Halfword Atomic Memory Operations https://github.com/riscv/riscv-isa-manual/blob/riscv-isa-release-8b9dc50-2024-08-30/src/zabha.adoc - RISC-V Atomics ABI Specification https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-atomic.adoc - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit Generated asm: - riscv64gc https://godbolt.org/z/Ws933n9jE - riscv64gc (+zabha) https://godbolt.org/z/zEKPPW11f - riscv32imac https://godbolt.org/z/TKbYdbaE9 - riscv32imac (+zabha) https://godbolt.org/z/TnePfK6co */ // TODO: Zacas/Zalrsc extension #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::{cell::UnsafeCell, sync::atomic::Ordering}; #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] #[cfg(target_arch = "riscv32")] macro_rules! w { () => { "" }; } #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] #[cfg(target_arch = "riscv64")] macro_rules! w { () => { "w" }; } #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] macro_rules! atomic_rmw_amo_ext { ("w") => { // Use +a also for zaamo because `option arch +zaamo` requires LLVM 19 https://github.com/llvm/llvm-project/commit/8be079cdddfd628d356d9ddb5ab397ea95fb1030 "+a" }; ("d") => { "+a" }; ("b") => { "+a,+zabha" }; ("h") => { "+a,+zabha" }; } #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] macro_rules! atomic_rmw_amo { ($op:ident, $dst:ident, $val:ident $(as $cast:ty)?, $order:ident, $size:tt) => {{ let out $(: $cast)?; macro_rules! op { ($asm_order:tt) => { // SAFETY: The user guaranteed that the AMO instruction is available in this // system by setting the portable_atomic_force_amo/target_feature and // portable_atomic_unsafe_assume_single_core. // The caller of this macro must guarantee the validity of the pointer. asm!( ".option push", // https://github.com/riscv-non-isa/riscv-asm-manual/blob/ad0de8c004e29c9a7ac33cfd054f4d4f9392f2fb/src/asm-manual.adoc#arch // LLVM supports `.option arch` directive on LLVM 17+. // https://github.com/llvm/llvm-project/commit/9e8ed3403c191ab9c4903e8eeb8f732ff8a43cb4 // Note that `.insn ` directive requires LLVM 19. // https://github.com/llvm/llvm-project/commit/2a086dce691e3cc34a2fc27f4fb255bb2cbbfac9 concat!(".option arch, ", atomic_rmw_amo_ext!($size)), concat!("amo", stringify!($op), ".", $size, $asm_order, " {out}, {val}, 0({dst})"), // atomic { _x = *dst; *dst = op(_x, val); out = _x } ".option pop", dst = in(reg) ptr_reg!($dst), val = in(reg) $val $(as $cast)?, out = lateout(reg) out, options(nostack, preserves_flags), ) }; } match $order { Ordering::Relaxed => op!(""), Ordering::Acquire => op!(".aq"), Ordering::Release => op!(".rl"), // AcqRel and SeqCst RMWs are equivalent. Ordering::AcqRel | Ordering::SeqCst => op!(".aqrl"), _ => unreachable!(), } out }}; } // 32-bit val.wrapping_shl(shift) but no extra `& (u32::BITS - 1)` #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] #[inline(always)] fn sllw(val: u32, shift: u32) -> u32 { // SAFETY: Calling sll{,w} is safe. unsafe { let out; asm!( concat!("sll", w!(), " {out}, {val}, {shift}"), // out = val << shift & 31 out = lateout(reg) out, val = in(reg) val, shift = in(reg) shift, options(pure, nomem, nostack, preserves_flags), ); out } } // 32-bit val.wrapping_shr(shift) but no extra `& (u32::BITS - 1)` #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] macro_rules! srlw { ($val:expr, $shift:expr) => { // SAFETY: Calling srl{,w} is safe. unsafe { let val: u32 = $val; let shift: u32 = $shift; let out; asm!( concat!("srl", w!(), " {out}, {val}, {shift}"), // out = val >> shift & 31 out = lateout(reg) out, val = in(reg) val, shift = in(reg) shift, options(pure, nomem, nostack, preserves_flags), ); out } }; } macro_rules! atomic_load_store { ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty $(as $cast:ty)?, $size:tt) => { #[repr(transparent)] pub(crate) struct $atomic_type $(<$($generics)*>)? { v: UnsafeCell<$value_type>, } // Send is implicitly implemented for atomic integers, but not for atomic pointers. // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Send for $atomic_type $(<$($generics)*>)? {} // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Sync for $atomic_type $(<$($generics)*>)? {} #[cfg(any(test, not(portable_atomic_unsafe_assume_single_core)))] impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] pub(crate) const fn new(v: $value_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::IS_ALWAYS_LOCK_FREE } pub(crate) const IS_ALWAYS_LOCK_FREE: bool = true; #[inline] pub(crate) const fn as_ptr(&self) -> *mut $value_type { self.v.get() } } impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $value_type { crate::utils::assert_load_ordering(order); let src = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { let out $(: $cast)?; macro_rules! atomic_load { ($acquire:tt, $release:tt) => { asm!( $release, // fence concat!("l", $size, " {out}, 0({src})"), // atomic { out = *src } $acquire, // fence src = in(reg) ptr_reg!(src), out = lateout(reg) out, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => atomic_load!("", ""), Ordering::Acquire => atomic_load!("fence r, rw", ""), Ordering::SeqCst => atomic_load!("fence r, rw", "fence rw, rw"), _ => unreachable!(), } out $(as $cast as $value_type)? } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $value_type, order: Ordering) { crate::utils::assert_store_ordering(order); let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { macro_rules! atomic_store { ($acquire:tt, $release:tt) => { asm!( $release, // fence concat!("s", $size, " {val}, 0({dst})"), // atomic { *dst = val } $acquire, // fence dst = in(reg) ptr_reg!(dst), val = in(reg) val $(as $cast)?, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => atomic_store!("", ""), Ordering::Release => atomic_store!("", "fence rw, w"), // https://github.com/llvm/llvm-project/commit/3ea8f2526541884e03d5bd4f4e46f4eb190990b6 Ordering::SeqCst => atomic_store!("fence rw, rw", "fence rw, w"), _ => unreachable!(), } } } } }; } macro_rules! atomic_ptr { ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty $(as $cast:ty)?, $size:tt) => { atomic_load_store!($([$($generics)*])? $atomic_type, $value_type $(as $cast)?, $size); #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] pub(crate) fn swap(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(swap, dst, val $(as $cast)?, order, $size) $(as $cast as $value_type)? } } } }; } macro_rules! atomic { ($atomic_type:ident, $value_type:ty, $size:tt, $max:tt, $min:tt) => { atomic_load_store!($atomic_type, $value_type, $size); #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(portable_atomic_unsafe_assume_single_core, feature = "critical-section")))] impl_default_no_fetch_ops!($atomic_type, $value_type); #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(portable_atomic_unsafe_assume_single_core, feature = "critical-section")))] impl_default_bit_opts!($atomic_type, $value_type); // There is no amo{sub,nand,neg}. #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] impl $atomic_type { #[inline] pub(crate) fn swap(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(swap, dst, val, order, $size) } } #[inline] pub(crate) fn fetch_add(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(add, dst, val, order, $size) } } #[inline] pub(crate) fn fetch_sub(&self, val: $value_type, order: Ordering) -> $value_type { self.fetch_add(val.wrapping_neg(), order) } #[inline] pub(crate) fn fetch_and(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(and, dst, val, order, $size) } } #[inline] pub(crate) fn fetch_or(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(or, dst, val, order, $size) } } #[inline] pub(crate) fn fetch_xor(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(xor, dst, val, order, $size) } } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $value_type { let dst = self.v.get(); #[cfg(target_arch = "riscv32")] let val: u32 = !0; #[cfg(target_arch = "riscv64")] let val: u64 = !0; // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(xor, dst, val, order, $size) } } #[cfg(not(any( portable_atomic_unsafe_assume_single_core, feature = "critical-section", )))] #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn fetch_max(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!($max, dst, val, order, $size) } } #[inline] pub(crate) fn fetch_min(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!($min, dst, val, order, $size) } } } }; } #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] trait ZeroExtend: Copy { /// Zero-extends `self` to `u32` if it is smaller than 32-bit. fn zero_extend(self) -> u32; } macro_rules! zero_extend { ($int:ident, $uint:ident) => { #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] impl ZeroExtend for $uint { #[inline(always)] fn zero_extend(self) -> u32 { self as u32 } } #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] impl ZeroExtend for $int { #[allow(clippy::cast_sign_loss)] #[inline(always)] fn zero_extend(self) -> u32 { self as $uint as u32 } } }; } zero_extend!(i8, u8); zero_extend!(i16, u16); macro_rules! atomic_sub_word { ($atomic_type:ident, $value_type:ty, $size:tt, $max:tt, $min:tt) => { #[cfg(any(target_feature = "zabha", portable_atomic_target_feature = "zabha"))] atomic!($atomic_type, $value_type, $size, $max, $min); #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] atomic_load_store!($atomic_type, $value_type, $size); #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] #[cfg(not(any(portable_atomic_unsafe_assume_single_core, feature = "critical-section")))] impl_default_bit_opts!($atomic_type, $value_type); #[cfg(any( test, portable_atomic_force_amo, target_feature = "zaamo", portable_atomic_target_feature = "zaamo", ))] #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] impl $atomic_type { #[inline] pub(crate) fn fetch_and(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); let (dst, shift, mut mask) = crate::utils::create_sub_word_mask_values(dst); mask = !sllw(mask, shift); let mut val = sllw(ZeroExtend::zero_extend(val), shift); val |= mask; // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. let out: u32 = unsafe { atomic_rmw_amo!(and, dst, val, order, "w") }; srlw!(out, shift) } #[cfg(not(any( portable_atomic_unsafe_assume_single_core, feature = "critical-section", )))] #[inline] pub(crate) fn and(&self, val: $value_type, order: Ordering) { self.fetch_and(val, order); } #[inline] pub(crate) fn fetch_or(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); let (dst, shift, _mask) = crate::utils::create_sub_word_mask_values(dst); let val = sllw(ZeroExtend::zero_extend(val), shift); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. let out: u32 = unsafe { atomic_rmw_amo!(or, dst, val, order, "w") }; srlw!(out, shift) } #[cfg(not(any( portable_atomic_unsafe_assume_single_core, feature = "critical-section", )))] #[inline] pub(crate) fn or(&self, val: $value_type, order: Ordering) { self.fetch_or(val, order); } #[inline] pub(crate) fn fetch_xor(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); let (dst, shift, _mask) = crate::utils::create_sub_word_mask_values(dst); let val = sllw(ZeroExtend::zero_extend(val), shift); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. let out: u32 = unsafe { atomic_rmw_amo!(xor, dst, val, order, "w") }; srlw!(out, shift) } #[cfg(not(any( portable_atomic_unsafe_assume_single_core, feature = "critical-section", )))] #[inline] pub(crate) fn xor(&self, val: $value_type, order: Ordering) { self.fetch_xor(val, order); } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $value_type { self.fetch_xor(!0, order) } #[cfg(not(any( portable_atomic_unsafe_assume_single_core, feature = "critical-section", )))] #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } } }; } atomic_sub_word!(AtomicI8, i8, "b", max, min); atomic_sub_word!(AtomicU8, u8, "b", maxu, minu); atomic_sub_word!(AtomicI16, i16, "h", max, min); atomic_sub_word!(AtomicU16, u16, "h", maxu, minu); atomic!(AtomicI32, i32, "w", max, min); atomic!(AtomicU32, u32, "w", maxu, minu); #[cfg(target_arch = "riscv64")] atomic!(AtomicI64, i64, "d", max, min); #[cfg(target_arch = "riscv64")] atomic!(AtomicU64, u64, "d", maxu, minu); #[cfg(target_pointer_width = "32")] atomic!(AtomicIsize, isize, "w", max, min); #[cfg(target_pointer_width = "32")] atomic!(AtomicUsize, usize, "w", maxu, minu); #[cfg(target_pointer_width = "32")] atomic_ptr!([T] AtomicPtr, *mut T as *mut u8, "w"); #[cfg(target_pointer_width = "64")] atomic!(AtomicIsize, isize, "d", max, min); #[cfg(target_pointer_width = "64")] atomic!(AtomicUsize, usize, "d", maxu, minu); #[cfg(target_pointer_width = "64")] atomic_ptr!([T] AtomicPtr, *mut T as *mut u8, "d"); #[cfg(test)] mod tests { use super::*; test_atomic_ptr_load_store!(); test_atomic_int_load_store!(i8); test_atomic_int_load_store!(u8); test_atomic_int_load_store!(i16); test_atomic_int_load_store!(u16); test_atomic_int_load_store!(i32); test_atomic_int_load_store!(u32); #[cfg(target_arch = "riscv64")] test_atomic_int_load_store!(i64); #[cfg(target_arch = "riscv64")] test_atomic_int_load_store!(u64); test_atomic_int_load_store!(isize); test_atomic_int_load_store!(usize); macro_rules! test_atomic_ptr_amo { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_ptr_amo { use super::*; test_atomic_ptr_amo!(AtomicPtr); } }; ($atomic_type:ty) => { use crate::tests::helper; ::quickcheck::quickcheck! { fn quickcheck_swap(x: usize, y: usize) -> bool { let x = sptr::invalid_mut(x); let y = sptr::invalid_mut(y); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.swap(y, order), x); assert_eq!(a.swap(x, order), y); } true } } }; } macro_rules! test_atomic_int_amo { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; test_atomic_int_amo!([], $int_type); } } }; ($atomic_type:ty, $int_type:ident) => { use crate::tests::helper; ::quickcheck::quickcheck! { fn quickcheck_swap(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.swap(y, order), x); assert_eq!(a.swap(x, order), y); } true } fn quickcheck_fetch_add(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_add(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_add(y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_add(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_add(x)); } true } fn quickcheck_fetch_sub(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_sub(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_sub(y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_sub(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_sub(x)); } true } fn quickcheck_fetch_and(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_and(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x & y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_and(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y & x); } true } fn quickcheck_fetch_or(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_or(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x | y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_or(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y | x); } true } fn quickcheck_fetch_xor(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_xor(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x ^ y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_xor(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y ^ x); } true } fn quickcheck_fetch_max(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_max(y, order), x); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(x, y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_max(x, order), y); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(y, x)); } true } fn quickcheck_fetch_min(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_min(y, order), x); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(x, y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_min(x, order), y); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(y, x)); } true } fn quickcheck_fetch_not(x: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_not(order), x); assert_eq!(a.load(Ordering::Relaxed), !x); assert_eq!(a.fetch_not(order), !x); assert_eq!(a.load(Ordering::Relaxed), x); } true } } }; } macro_rules! test_atomic_int_amo_sub_word { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; #[cfg(any(target_feature = "zabha", portable_atomic_target_feature = "zabha"))] test_atomic_int_amo!([], $int_type); #[cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha")))] test_atomic_int_amo_sub_word!([], $int_type); } } }; ($atomic_type:ty, $int_type:ident) => { use crate::tests::helper::{self, *}; ::quickcheck::quickcheck! { fn quickcheck_fetch_and(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { for base in [0, !0] { let mut arr = Align16([ <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), ]); let a_idx = fastrand::usize(3..=6); arr.0[a_idx] = <$atomic_type>::new(x); let a = &arr.0[a_idx]; assert_eq!(a.fetch_and(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x & y); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } arr.0[a_idx] = <$atomic_type>::new(y); let a = &arr.0[a_idx]; assert_eq!(a.fetch_and(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y & x); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } } } true } fn quickcheck_fetch_or(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { for base in [0, !0] { let mut arr = Align16([ <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), ]); let a_idx = fastrand::usize(3..=6); arr.0[a_idx] = <$atomic_type>::new(x); let a = &arr.0[a_idx]; assert_eq!(a.fetch_or(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x | y); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } arr.0[a_idx] = <$atomic_type>::new(y); let a = &arr.0[a_idx]; assert_eq!(a.fetch_or(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y | x); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } } } true } fn quickcheck_fetch_xor(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { for base in [0, !0] { let mut arr = Align16([ <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), ]); let a_idx = fastrand::usize(3..=6); arr.0[a_idx] = <$atomic_type>::new(x); let a = &arr.0[a_idx]; assert_eq!(a.fetch_xor(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x ^ y); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } arr.0[a_idx] = <$atomic_type>::new(y); let a = &arr.0[a_idx]; assert_eq!(a.fetch_xor(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y ^ x); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } } } true } fn quickcheck_fetch_not(x: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { for base in [0, !0] { let mut arr = Align16([ <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), ]); let a_idx = fastrand::usize(3..=6); arr.0[a_idx] = <$atomic_type>::new(x); let a = &arr.0[a_idx]; assert_eq!(a.fetch_not(order), x); assert_eq!(a.load(Ordering::Relaxed), !x); assert_eq!(a.fetch_not(order), !x); assert_eq!(a.load(Ordering::Relaxed), x); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } } } true } } }; } test_atomic_ptr_amo!(); test_atomic_int_amo_sub_word!(i8); test_atomic_int_amo_sub_word!(u8); test_atomic_int_amo_sub_word!(i16); test_atomic_int_amo_sub_word!(u16); test_atomic_int_amo!(i32); test_atomic_int_amo!(u32); #[cfg(target_arch = "riscv64")] test_atomic_int_amo!(i64); #[cfg(target_arch = "riscv64")] test_atomic_int_amo!(u64); test_atomic_int_amo!(isize); test_atomic_int_amo!(usize); } portable-atomic/src/imp/detect/0000775000175000017500000000000015105742312016312 5ustar bdrungbdrungportable-atomic/src/imp/detect/powerpc64_aix.rs0000644000175000017500000000646715105742312021365 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on PowerPC64 AIX by using getsystemcfg. Refs: - https://github.com/golang/go/blob/071aed2aaa0ed819582c5bff44b70d43c61f504a/src/internal/cpu/cpu_ppc64x_aix.go As of nightly-2024-09-07, is_powerpc_feature_detected doesn't support run-time detection on AIX. https://github.com/rust-lang/stdarch/blob/d9466edb4c53cece8686ee6e17b028436ddf4151/crates/std_detect/src/detect/mod.rs Run-time detection on PowerPC64 AIX is currently disabled by default as experimental because we cannot run tests on the VM or real machine. */ include!("common.rs"); // libc requires Rust 1.63 mod ffi { pub(crate) use crate::utils::ffi::{c_int, c_ulong}; // TODO: use sys_const! // https://github.com/rust-lang/libc/blob/0.2.158/src/unix/aix/mod.rs#L2058 // https://github.com/golang/go/blob/071aed2aaa0ed819582c5bff44b70d43c61f504a/src/internal/cpu/cpu_ppc64x_aix.go pub(crate) const SC_IMPL: c_int = 2; pub(crate) const POWER_8: c_ulong = 0x10000; pub(crate) const POWER_9: c_ulong = 0x20000; pub(crate) const POWER_10: c_ulong = 0x40000; // TODO: use sys_fn! extern "C" { // https://www.ibm.com/docs/en/aix/7.3?topic=g-getsystemcfg-subroutine // https://github.com/rust-lang/libc/blob/0.2.158/src/unix/aix/powerpc64.rs#L643 pub(crate) fn getsystemcfg(name: c_int) -> c_ulong; } } #[cold] fn _detect(info: &mut CpuInfo) { // SAFETY: calling getsystemcfg is safe. let impl_ = unsafe { ffi::getsystemcfg(ffi::SC_IMPL) }; if impl_ == ffi::c_ulong::MAX { return; } // Check both POWER_8 and later ISAs (which are superset of POWER_8) because // AIX currently doesn't set POWER_8 when POWER_9 is set. // https://github.com/golang/go/commit/51859ec2292d9c1d82a7054ec672ff551a0d7497 if impl_ & (ffi::POWER_8 | ffi::POWER_9 | ffi::POWER_10) != 0 { info.set(CpuInfo::HAS_QUADWORD_ATOMICS); } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate and FFI bindings defined // in libc compatible signatures (or the same values if constants). // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. // TODO: auto-generate this test #[allow( clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation, clippy::no_effect_underscore_binding )] const _: fn() = || { let mut _getsystemcfg: unsafe extern "C" fn(ffi::c_int) -> ffi::c_ulong = ffi::getsystemcfg; _getsystemcfg = libc::getsystemcfg; static_assert!(ffi::SC_IMPL == libc::SC_IMPL); static_assert!(ffi::POWER_8 == libc::POWER_8 as ffi::c_ulong); static_assert!(ffi::POWER_9 == libc::POWER_9 as ffi::c_ulong); // static_assert!(ffi::POWER_10 == libc::POWER_10 as ffi::c_ulong); // libc doesn't have this }; } portable-atomic/src/imp/detect/aarch64_windows.rs0000644000175000017500000000612315105742312021662 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on AArch64 Windows by using IsProcessorFeaturePresent. Run-time detection of FEAT_LSE on Windows by is_aarch64_feature_detected is supported on Rust 1.70+. https://github.com/rust-lang/stdarch/pull/1373 Refs: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent */ include!("common.rs"); // windows-sys requires Rust 1.60 #[allow(clippy::upper_case_acronyms)] mod ffi { pub(crate) type DWORD = u32; pub(crate) type BOOL = i32; pub(crate) const FALSE: BOOL = 0; // Defined in winnt.h of Windows SDK. pub(crate) const PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE: DWORD = 34; extern "system" { // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent pub(crate) fn IsProcessorFeaturePresent(ProcessorFeature: DWORD) -> BOOL; } } #[cold] fn _detect(info: &mut CpuInfo) { // SAFETY: calling IsProcessorFeaturePresent is safe, and FALSE is also // returned if the HAL does not support detection of the specified feature. if unsafe { ffi::IsProcessorFeaturePresent(ffi::PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE) != ffi::FALSE } { info.set(CpuInfo::HAS_LSE); } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate and FFI bindings defined // in windows-sys have compatible signatures (or the same values if constants). // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // (Unlike libc, windows-sys programmatically generates bindings from Windows // API metadata, so it should be enough to check compatibility with the // windows-sys' signatures/values.) // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation)] const _: fn() = || { let _: ffi::DWORD = 0 as windows_sys::Win32::System::Threading::PROCESSOR_FEATURE_ID; let _: ffi::BOOL = 0 as windows_sys::Win32::Foundation::BOOL; let mut _is_processor_feature_present: unsafe extern "system" fn(ffi::DWORD) -> ffi::BOOL = ffi::IsProcessorFeaturePresent; _is_processor_feature_present = windows_sys::Win32::System::Threading::IsProcessorFeaturePresent; static_assert!(ffi::FALSE == windows_sys::Win32::Foundation::FALSE); static_assert!( ffi::PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE == windows_sys::Win32::System::Threading::PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE ); }; } portable-atomic/src/imp/detect/riscv_linux.rs0000644000175000017500000001477415105742312021240 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on RISC-V Linux/Android by using riscv_hwprobe. On RISC-V, detection using auxv only supports single-letter extensions. So, we use riscv_hwprobe that supports multi-letter extensions. Refs: https://github.com/torvalds/linux/blob/v6.12/Documentation/arch/riscv/hwprobe.rst */ include!("common.rs"); use core::ptr; // libc requires Rust 1.63 #[allow(non_camel_case_types, non_upper_case_globals)] mod ffi { pub(crate) use crate::utils::ffi::{c_long, c_size_t, c_uint, c_ulong}; sys_struct!({ // https://github.com/torvalds/linux/blob/v6.12/arch/riscv/include/uapi/asm/hwprobe.h pub(crate) struct riscv_hwprobe { pub(crate) key: i64, pub(crate) value: u64, } }); sys_const!({ pub(crate) const __NR_riscv_hwprobe: c_long = 258; // https://github.com/torvalds/linux/blob/v6.12/arch/riscv/include/uapi/asm/hwprobe.h pub(crate) const RISCV_HWPROBE_KEY_IMA_EXT_0: i64 = 4; // Linux 6.8+ // https://github.com/torvalds/linux/commit/154a3706122978eeb34d8223d49285ed4f3c61fa pub(crate) const RISCV_HWPROBE_EXT_ZACAS: u64 = 1 << 34; }); // TODO: use sys_fn! #[cfg(not(all( target_os = "linux", any(target_arch = "riscv32", all(target_arch = "riscv64", target_pointer_width = "64")), )))] extern "C" { // https://man7.org/linux/man-pages/man2/syscall.2.html pub(crate) fn syscall(number: c_long, ...) -> c_long; } // Use asm-based syscall for compatibility with non-libc targets if possible. #[cfg(all( target_os = "linux", // https://github.com/bytecodealliance/rustix/issues/1095 any(target_arch = "riscv32", all(target_arch = "riscv64", target_pointer_width = "64")), ))] #[inline] pub(crate) unsafe fn syscall( number: c_long, a0: *mut riscv_hwprobe, a1: c_size_t, a2: c_size_t, a3: *mut c_ulong, a4: c_uint, ) -> c_long { #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; // arguments must be extended to 64-bit if RV64 let a4 = a4 as usize; let r; // SAFETY: the caller must uphold the safety contract. // Refs: // - https://github.com/bminor/musl/blob/v1.2.5/arch/riscv32/syscall_arch.h // - https://github.com/bminor/musl/blob/v1.2.5/arch/riscv64/syscall_arch.h unsafe { asm!( "ecall", in("a7") number, inout("a0") a0 => r, in("a1") a1, in("a2") a2, in("a3") a3, in("a4") a4, options(nostack, preserves_flags) ); } r } // https://github.com/torvalds/linux/blob/v6.12/Documentation/arch/riscv/hwprobe.rst pub(crate) unsafe fn __riscv_hwprobe( pairs: *mut riscv_hwprobe, pair_count: c_size_t, cpu_set_size: c_size_t, cpus: *mut c_ulong, flags: c_uint, ) -> c_long { // SAFETY: the caller must uphold the safety contract. unsafe { syscall(__NR_riscv_hwprobe, pairs, pair_count, cpu_set_size, cpus, flags) } } } // syscall returns an unsupported error if riscv_hwprobe is not supported, // so we can safely use this function on older versions of Linux. fn riscv_hwprobe(out: &mut ffi::riscv_hwprobe) -> bool { // SAFETY: We've passed the valid pointer and length, // passing null ptr for cpus is safe because cpu_set_size is zero. unsafe { ffi::__riscv_hwprobe(out, 1, 0, ptr::null_mut(), 0) == 0 } } #[cold] fn _detect(info: &mut CpuInfo) { let mut out = ffi::riscv_hwprobe { key: ffi::RISCV_HWPROBE_KEY_IMA_EXT_0, value: 0 }; if riscv_hwprobe(&mut out) && out.key != -1 { let value = out.value; if value & ffi::RISCV_HWPROBE_EXT_ZACAS != 0 { info.set(CpuInfo::HAS_ZACAS); } } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; // We use asm-based syscall for compatibility with non-libc targets. // This test tests that our ones and libc::syscall returns the same result. #[test] fn test_alternative() { unsafe fn __riscv_hwprobe_libc( pairs: *mut ffi::riscv_hwprobe, pair_count: ffi::c_size_t, cpu_set_size: ffi::c_size_t, cpus: *mut ffi::c_ulong, flags: ffi::c_uint, ) -> ffi::c_long { // SAFETY: the caller must uphold the safety contract. unsafe { libc::syscall(ffi::__NR_riscv_hwprobe, pairs, pair_count, cpu_set_size, cpus, flags) } } fn riscv_hwprobe_libc(out: &mut ffi::riscv_hwprobe) -> bool { unsafe { __riscv_hwprobe_libc(out, 1, 0, ptr::null_mut(), 0) == 0 } } let mut out = ffi::riscv_hwprobe { key: ffi::RISCV_HWPROBE_KEY_IMA_EXT_0, value: 0 }; let mut libc_out = ffi::riscv_hwprobe { key: ffi::RISCV_HWPROBE_KEY_IMA_EXT_0, value: 0 }; assert_eq!(riscv_hwprobe(&mut out), riscv_hwprobe_libc(&mut libc_out)); assert_eq!(out, libc_out); } // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate, FFI bindings defined // in libc, and FFI bindings generated for the platform's latest header file // using bindgen have compatible signatures. // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // As for constants, they are checked by static assertions generated by sys_const!. // As for structs, they are checked by static assertions generated by sys_struct!. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test const _: fn() = || { #[cfg(not(all( target_os = "linux", any( target_arch = "riscv32", all(target_arch = "riscv64", target_pointer_width = "64"), ), )))] { use test_helper::sys; let mut _syscall: unsafe extern "C" fn(num: ffi::c_long, ...) -> ffi::c_long = ffi::syscall; _syscall = libc::syscall; _syscall = sys::syscall; } }; } portable-atomic/src/imp/detect/auxv.rs0000644000175000017500000013712015105742312017645 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on AArch64/PowerPC64 Linux/Android/FreeBSD/OpenBSD by parsing ELF auxiliary vectors. Supported platforms: - Linux 6.4+ (through prctl) https://github.com/torvalds/linux/commit/ddc65971bb677aa9f6a4c21f76d3133e106f88eb prctl returns an unsupported error if operation is not supported, so we can safely use this on older versions. - glibc 2.16+ (through getauxval) https://github.com/bminor/glibc/commit/c7683a6d02f3ed59f5cd119b3e8547f45a15912f Always available on: - aarch64 (glibc 2.17+ https://github.com/bminor/glibc/blob/glibc-2.17/NEWS#L36) - powerpc64 (le) (glibc 2.19+ or RHEL/CentOS's patched glibc 2.17+ https://github.com/bminor/glibc/blob/glibc-2.19/NEWS#L108) Not always available on: - powerpc64 (be) (glibc 2.3+ https://github.com/bminor/glibc/blob/glibc-2.3/NEWS#L56) Since Rust 1.64, std requires glibc 2.17+ https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html - musl 1.1.0+ (through getauxval) https://github.com/bminor/musl/commit/21ada94c4b8c01589367cea300916d7db8461ae7 Always available on: - aarch64 (musl 1.1.7+ https://github.com/bminor/musl/blob/v1.1.7/WHATSNEW#L1422) - powerpc64 (musl 1.1.15+ https://github.com/bminor/musl/blob/v1.1.15/WHATSNEW#L1702) Since Rust 1.31, std requires musl 1.1.20+ https://github.com/rust-lang/rust/pull/54430 Since Rust 1.37, std requires musl 1.1.22+ https://github.com/rust-lang/rust/pull/61252 Since Rust 1.46, std requires musl 1.1.24+ https://github.com/rust-lang/rust/pull/73089 Since Rust 1.71, std requires musl 1.2.3+ https://blog.rust-lang.org/2023/05/09/Updating-musl-targets.html - uClibc-ng 1.0.43+ (through getauxval) https://github.com/wbx-github/uclibc-ng/commit/d869bb1600942c01a77539128f9ba5b5b55ad647 Not always available on: - aarch64 (uClibc-ng 1.0.22+ https://github.com/wbx-github/uclibc-ng/commit/dba942c80dc2cfa5768a856fff98e22a755fdd27) (powerpc64 is not supported https://github.com/wbx-github/uclibc-ng/commit/d4d4f37fda7fa57e57132ff2f0d735ce7cc2178e) - Picolibc 1.4.6+ (through getauxval) https://github.com/picolibc/picolibc/commit/19bfe51d62ad7e32533c7f664b5bca8e26286e31 - Android 4.3+ (API level 18+) (through getauxval) https://github.com/aosp-mirror/platform_bionic/commit/2c5153b043b44e9935a334ae9b2d5a4bc5258b40 https://github.com/aosp-mirror/platform_bionic/commit/655e430b28d7404f763e7ebefe84fba5a387666d Always available on: - 64-bit architectures (Android 5.0+ (API level 21+) https://android-developers.googleblog.com/2014/10/whats-new-in-android-50-lollipop.html) Since Rust 1.68, std requires API level 19+ https://blog.rust-lang.org/2023/01/09/android-ndk-update-r25.html Since Rust 1.82, std requires API level 21+ https://github.com/rust-lang/rust/pull/120593 - FreeBSD 12.0+ and 11.4+ (through elf_aux_info) https://github.com/freebsd/freebsd-src/commit/0b08ae2120cdd08c20a2b806e2fcef4d0a36c470 https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h Not always available on: - aarch64 (FreeBSD 11.0+ https://www.freebsd.org/releases/11.0R/announce) - powerpc64 (FreeBSD 9.0+ https://www.freebsd.org/releases/9.0R/announce) Since Rust 1.75, std requires FreeBSD 12+ https://github.com/rust-lang/rust/pull/114521 Dropping support for FreeBSD 12 in std was decided in https://github.com/rust-lang/rust/pull/120869, but the actual update to the FreeBSD 13 toolchain was attempted twice, but both times there were problems, so they were reverted: https://github.com/rust-lang/rust/pull/132228 https://github.com/rust-lang/rust/pull/136582 - OpenBSD 7.6+ (through elf_aux_info) https://github.com/openbsd/src/commit/ef873df06dac50249b2dd380dc6100eee3b0d23d Not always available on: - aarch64 (OpenBSD 6.1+ https://www.openbsd.org/61.html) - powerpc64 (OpenBSD 6.8+ https://www.openbsd.org/68.html) On platforms that we can assume that getauxval/elf_aux_info is always available, we directly call them on except for musl with static linking. (At this time, we also retain compatibility with versions that reached EoL or no longer supported by `std`, with the exception of AArch64 FreeBSD described below.) On musl with static linking, it seems that getauxval is not always available, independent of version requirements: https://github.com/rust-lang/rust/issues/89626 (That problem may have been fixed in https://github.com/rust-lang/rust/commit/9a04ae4997493e9260352064163285cddc43de3c, but even in the version containing that patch, [there is report](https://github.com/rust-lang/rust/issues/89626#issuecomment-1242636038) of the same error.) On platforms that we cannot assume that getauxval/elf_aux_info is always available, so we use dlsym instead of directly calling getauxval/elf_aux_info. (You can force getauxval/elf_aux_info to be called directly instead of using dlsym by `--cfg portable_atomic_outline_atomics`). Also, note that dlsym usually not working with static linking. # Linux/Android As of Rust 1.69, is_aarch64_feature_detected always uses dlsym by default on AArch64 Linux/Android, but on some platforms, we can safely assume getauxval is linked to the binary (see the above). See also https://github.com/rust-lang/stdarch/pull/1375 See tests::test_alternative and aarch64_aa64reg.rs for (test-only) alternative implementations. # FreeBSD As of nightly-2024-09-07, is_aarch64_feature_detected always uses mrs on AArch64 FreeBSD. However, they do not work on FreeBSD 12 on QEMU (confirmed on FreeBSD 12.{2,3,4}), and we got SIGILL (worked on FreeBSD 13 and 14). So use elf_aux_info instead of mrs like compiler-rt does. https://reviews.llvm.org/D109330 elf_aux_info is available on FreeBSD 12.0+ and 11.4+: https://github.com/freebsd/freebsd-src/commit/0b08ae2120cdd08c20a2b806e2fcef4d0a36c470 https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h On FreeBSD, [AArch64 support is available on FreeBSD 11.0+](https://www.freebsd.org/releases/11.0R/announce), but FreeBSD 11 (11.4) was EoL on 2021-09-30, and FreeBSD 11.3 was EoL on 2020-09-30: https://www.freebsd.org/security/unsupported See also https://github.com/rust-lang/stdarch/pull/611#issuecomment-445464613 See tests::test_alternative and aarch64_aa64reg.rs for (test-only) alternative implementations. # OpenBSD elf_aux_info is available on OpenBSD 7.6+: https://github.com/openbsd/src/commit/ef873df06dac50249b2dd380dc6100eee3b0d23d On AArch64, there is an alternative that available on older version, so we use it (see aarch64_aa64reg.rs). */ include!("common.rs"); use self::os::ffi; #[cfg(any(target_os = "linux", target_os = "android"))] mod os { // libc requires Rust 1.63 #[cfg_attr(test, allow(dead_code))] pub(super) mod ffi { pub(crate) use crate::utils::ffi::c_ulong; #[allow(unused_imports)] pub(crate) use crate::utils::ffi::{c_char, c_int, c_void}; sys_const!({ // https://github.com/torvalds/linux/blob/v6.12/include/uapi/linux/auxvec.h pub(crate) const AT_HWCAP: c_ulong = 16; #[cfg(any( test, all(target_arch = "aarch64", target_pointer_width = "64"), target_arch = "powerpc64", ))] pub(crate) const AT_HWCAP2: c_ulong = 26; // Defined in dlfcn.h. // https://github.com/bminor/glibc/blob/glibc-2.40/dlfcn/dlfcn.h // https://github.com/bminor/musl/blob/v1.2.5/include/dlfcn.h // https://github.com/wbx-github/uclibc-ng/blob/v1.0.47/include/dlfcn.h // https://github.com/aosp-mirror/platform_bionic/blob/android-15.0.0_r1/libc/include/dlfcn.h #[cfg(any( test, not(any( all( target_os = "linux", any( all( target_env = "gnu", any( target_arch = "aarch64", all(target_arch = "powerpc64", target_endian = "little"), ), ), target_env = "musl", target_env = "ohos", ), ), all(target_os = "android", target_pointer_width = "64"), portable_atomic_outline_atomics, )), ))] pub(crate) const RTLD_DEFAULT: *mut c_void = core::ptr::null_mut(); // Defined in sys/system_properties.h. // https://github.com/aosp-mirror/platform_bionic/blob/android-15.0.0_r1/libc/include/sys/system_properties.h #[cfg(all(target_arch = "aarch64", target_os = "android"))] pub(crate) const PROP_VALUE_MAX: c_int = 92; }); sys_fn!({ extern "C" { // Defined in sys/auxv.h. // https://man7.org/linux/man-pages/man3/getauxval.3.html // https://github.com/bminor/glibc/blob/glibc-2.40/misc/sys/auxv.h // https://github.com/bminor/musl/blob/v1.2.5/include/sys/auxv.h // https://github.com/wbx-github/uclibc-ng/blob/v1.0.47/include/sys/auxv.h // https://github.com/aosp-mirror/platform_bionic/blob/android-15.0.0_r1/libc/include/sys/auxv.h // https://github.com/picolibc/picolibc/blob/1.8.6/newlib/libc/include/sys/auxv.h #[cfg(any( test, all( target_os = "linux", any( all( target_env = "gnu", any( target_arch = "aarch64", all(target_arch = "powerpc64", target_endian = "little"), ), ), target_env = "musl", target_env = "ohos", ), ), all(target_os = "android", target_pointer_width = "64"), portable_atomic_outline_atomics, ))] pub(crate) fn getauxval(type_: c_ulong) -> c_ulong; // Defined in dlfcn.h. // https://man7.org/linux/man-pages/man3/dlsym.3.html // https://github.com/bminor/glibc/blob/glibc-2.40/dlfcn/dlfcn.h // https://github.com/bminor/musl/blob/v1.2.5/include/dlfcn.h // https://github.com/wbx-github/uclibc-ng/blob/v1.0.47/include/dlfcn.h // https://github.com/aosp-mirror/platform_bionic/blob/android-15.0.0_r1/libc/include/dlfcn.h #[cfg(any( test, not(any( all( target_os = "linux", any( all( target_env = "gnu", any( target_arch = "aarch64", all(target_arch = "powerpc64", target_endian = "little"), ), ), target_env = "musl", target_env = "ohos", ), ), all(target_os = "android", target_pointer_width = "64"), portable_atomic_outline_atomics, )), ))] pub(crate) fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void; // Defined in sys/system_properties.h. // https://github.com/aosp-mirror/platform_bionic/blob/android-15.0.0_r1/libc/include/sys/system_properties.h #[cfg(all(target_arch = "aarch64", target_os = "android"))] pub(crate) fn __system_property_get( name: *const c_char, value: *mut c_char, ) -> c_int; } }); } pub(super) type GetauxvalTy = unsafe extern "C" fn(ffi::c_ulong) -> ffi::c_ulong; pub(super) fn getauxval(type_: ffi::c_ulong) -> ffi::c_ulong { #[cfg(any( all( target_os = "linux", any( all( target_env = "gnu", any( target_arch = "aarch64", all(target_arch = "powerpc64", target_endian = "little"), ), ), target_env = "musl", target_env = "ohos", ), ), all(target_os = "android", target_pointer_width = "64"), portable_atomic_outline_atomics, ))] let getauxval: GetauxvalTy = ffi::getauxval; #[cfg(not(any( all( target_os = "linux", any( all( target_env = "gnu", any( target_arch = "aarch64", all(target_arch = "powerpc64", target_endian = "little"), ), ), target_env = "musl", target_env = "ohos", ), ), all(target_os = "android", target_pointer_width = "64"), portable_atomic_outline_atomics, )))] // SAFETY: we passed a valid C string to dlsym, and a pointer returned by dlsym // is a valid pointer to the function if it is non-null. let getauxval: GetauxvalTy = unsafe { let ptr = ffi::dlsym(ffi::RTLD_DEFAULT, c!("getauxval").as_ptr()); if ptr.is_null() { return 0; } core::mem::transmute::<*mut ffi::c_void, GetauxvalTy>(ptr) }; // SAFETY: `getauxval` is thread-safe. unsafe { getauxval(type_) } } } #[cfg(any(target_os = "freebsd", target_os = "openbsd"))] mod os { use core::mem; // libc requires Rust 1.63 #[cfg_attr(test, allow(dead_code))] pub(super) mod ffi { #[allow(unused_imports)] pub(crate) use crate::utils::ffi::c_char; pub(crate) use crate::utils::ffi::{c_int, c_ulong, c_void}; sys_const!({ // FreeBSD // Defined in sys/elf_common.h. // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/sys/elf_common.h // OpenBSD // Defined in sys/auxv.h. // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/sys/auxv.h pub(crate) const AT_HWCAP: c_int = 25; #[cfg(any( test, all(target_os = "freebsd", target_arch = "aarch64", target_pointer_width = "64"), target_arch = "powerpc64", ))] pub(crate) const AT_HWCAP2: c_int = 26; // FreeBSD // Defined in dlfcn.h. // https://man.freebsd.org/dlsym(3) // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/include/dlfcn.h // OpenBSD // Defined in dlfcn.h. // https://man.openbsd.org/dlsym.3 // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/include/dlfcn.h #[cfg(any( test, not(any( all(target_os = "freebsd", target_arch = "aarch64"), portable_atomic_outline_atomics, )), ))] #[allow(clippy::cast_sign_loss)] pub(crate) const RTLD_DEFAULT: *mut c_void = -2_isize as usize as *mut c_void; }); sys_fn!({ extern "C" { // FreeBSD // Defined in sys/auxv.h. // https://man.freebsd.org/elf_aux_info(3) // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/sys/auxv.h // OpenBSD // Defined in sys/auxv.h. // https://man.openbsd.org/elf_aux_info.3 // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/sys/auxv.h #[cfg(any( test, any( all(target_os = "freebsd", target_arch = "aarch64"), portable_atomic_outline_atomics, ), ))] pub(crate) fn elf_aux_info(aux: c_int, buf: *mut c_void, buf_len: c_int) -> c_int; // FreeBSD // Defined in dlfcn.h. // https://man.freebsd.org/dlsym(3) // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/include/dlfcn.h // OpenBSD // Defined in dlfcn.h. // https://man.openbsd.org/dlsym.3 // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/include/dlfcn.h #[cfg(any( test, not(any( all(target_os = "freebsd", target_arch = "aarch64"), portable_atomic_outline_atomics, )), ))] pub(crate) fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void; } }); } pub(super) type ElfAuxInfoTy = unsafe extern "C" fn(ffi::c_int, *mut ffi::c_void, ffi::c_int) -> ffi::c_int; pub(super) fn getauxval(aux: ffi::c_int) -> ffi::c_ulong { #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] const OUT_LEN: ffi::c_int = mem::size_of::() as ffi::c_int; #[cfg(any( all(target_os = "freebsd", target_arch = "aarch64"), portable_atomic_outline_atomics, ))] let elf_aux_info: ElfAuxInfoTy = ffi::elf_aux_info; #[cfg(not(any( all(target_os = "freebsd", target_arch = "aarch64"), portable_atomic_outline_atomics, )))] // SAFETY: we passed a valid C string to dlsym, and a pointer returned by dlsym // is a valid pointer to the function if it is non-null. let elf_aux_info: ElfAuxInfoTy = unsafe { let ptr = ffi::dlsym(ffi::RTLD_DEFAULT, c!("elf_aux_info").as_ptr()); if ptr.is_null() { return 0; } mem::transmute::<*mut ffi::c_void, ElfAuxInfoTy>(ptr) }; let mut out: ffi::c_ulong = 0; // SAFETY: // - the pointer is valid because we got it from a reference. // - `OUT_LEN` is the same as the size of `out`. // - `elf_aux_info` is thread-safe. let res = unsafe { elf_aux_info(aux, (&mut out as *mut ffi::c_ulong).cast::(), OUT_LEN) }; // If elf_aux_info fails, `out` will be left at zero (which is the proper default value). debug_assert!(res == 0 || out == 0); out } } // Basically, Linux/FreeBSD/OpenBSD use the same hwcap values. // FreeBSD and OpenBSD usually support a subset of the hwcap values supported by Linux. use self::arch::_detect; #[cfg(target_arch = "aarch64")] mod arch { use super::{CpuInfo, ffi, os}; sys_const!({ // Linux // https://github.com/torvalds/linux/blob/v6.12/arch/arm64/include/uapi/asm/hwcap.h // https://github.com/torvalds/linux/blob/v6.12/Documentation/arch/arm64/elf_hwcaps.rst // FreeBSD // Defined in machine/elf.h. // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/arm64/include/elf.h // OpenBSD // Defined in machine/elf.h. // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/arch/arm64/include/elf.h // Linux 4.3+ // https://github.com/torvalds/linux/commit/40a1db2434a1b62332b1af25cfa14d7b8c0301fe // FreeBSD 13.0+/12.2+ // https://github.com/freebsd/freebsd-src/blob/release/13.0.0/sys/arm64/include/elf.h // https://github.com/freebsd/freebsd-src/blob/release/12.2.0/sys/arm64/include/elf.h // OpenBSD 7.6+ // https://github.com/openbsd/src/commit/ef873df06dac50249b2dd380dc6100eee3b0d23d pub(super) const HWCAP_ATOMICS: ffi::c_ulong = 1 << 8; // Linux 4.17+ // https://github.com/torvalds/linux/commit/7206dc93a58fb76421c4411eefa3c003337bcb2d // FreeBSD 13.0+/12.2+ // https://github.com/freebsd/freebsd-src/blob/release/13.0.0/sys/arm64/include/elf.h // https://github.com/freebsd/freebsd-src/blob/release/12.2.0/sys/arm64/include/elf.h // OpenBSD 7.6+ // https://github.com/openbsd/src/commit/ef873df06dac50249b2dd380dc6100eee3b0d23d pub(super) const HWCAP_USCAT: ffi::c_ulong = 1 << 25; // Linux 6.7+ // https://github.com/torvalds/linux/commit/338a835f40a849cd89b993e342bd9fbd5684825c // FreeBSD 15.0+ // https://github.com/freebsd/freebsd-src/commit/94686b081fdb0c1bb0fc1dfeda14bd53f26ce7c5 #[cfg(not(target_os = "openbsd"))] #[cfg(target_pointer_width = "64")] pub(super) const HWCAP2_LRCPC3: ffi::c_ulong = 1 << 46; // Linux 6.7+ // https://github.com/torvalds/linux/commit/94d0657f9f0d311489606589133ebf49e28104d8 // FreeBSD 15.0+ // https://github.com/freebsd/freebsd-src/commit/94686b081fdb0c1bb0fc1dfeda14bd53f26ce7c5 #[cfg(not(target_os = "openbsd"))] #[cfg(target_pointer_width = "64")] pub(super) const HWCAP2_LSE128: ffi::c_ulong = 1 << 47; }); #[cold] pub(super) fn _detect(info: &mut CpuInfo) { #[cfg(target_os = "android")] { // Samsung Exynos 9810 has a bug that big and little cores have different // ISAs. And on older Android (pre-9), the kernel incorrectly reports // that features available only on some cores are available on all cores. // https://reviews.llvm.org/D114523 let mut arch = [0_u8; ffi::PROP_VALUE_MAX as usize]; // SAFETY: we've passed a valid C string and a buffer with max length. let len = unsafe { ffi::__system_property_get( c!("ro.arch").as_ptr(), arch.as_mut_ptr().cast::(), ) }; // On Exynos, ro.arch is not available on Android 12+, but it is fine // because Android 9+ includes the fix. if len > 0 && arch.starts_with(b"exynos9810") { return; } } let hwcap = os::getauxval(ffi::AT_HWCAP); if hwcap & HWCAP_ATOMICS != 0 { info.set(CpuInfo::HAS_LSE); } if hwcap & HWCAP_USCAT != 0 { info.set(CpuInfo::HAS_LSE2); } #[cfg(not(target_os = "openbsd"))] // HWCAP2 is not yet available on ILP32: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/tree/arch/arm64/include/uapi/asm/hwcap.h?h=staging/ilp32-5.1 #[cfg(target_pointer_width = "64")] { let hwcap2 = os::getauxval(ffi::AT_HWCAP2); if hwcap2 & HWCAP2_LRCPC3 != 0 { info.set(CpuInfo::HAS_RCPC3); } if hwcap2 & HWCAP2_LSE128 != 0 { info.set(CpuInfo::HAS_LSE128); } } } } #[cfg(target_arch = "powerpc64")] mod arch { use super::{CpuInfo, ffi, os}; sys_const!({ // Linux // https://github.com/torvalds/linux/blob/v6.12/arch/powerpc/include/uapi/asm/cputable.h // https://github.com/torvalds/linux/blob/v6.12/Documentation/arch/powerpc/elf_hwcaps.rst // FreeBSD // Defined in machine/cpu.h. // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/sys/powerpc/include/cpu.h // OpenBSD // Defined in machine/elf.h. // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/arch/powerpc64/include/elf.h // Linux 2.6.16+ // https://github.com/torvalds/linux/commit/80f15dc703b3677d0b025bafd215f1f3664c8978 // FreeBSD 11.0+ // https://github.com/freebsd/freebsd-src/commit/b0bf7fcd298133457991b27625bbed766e612730 // OpenBSD 7.6+ // https://github.com/openbsd/src/commit/0b0568a19fc4c197871ceafbabc91fabf17ca152 pub(super) const PPC_FEATURE_BOOKE: ffi::c_ulong = 0x00008000; // Linux 3.10+ // https://github.com/torvalds/linux/commit/cbbc6f1b1433ef553d57826eee87a84ca49645ce // FreeBSD 11.0+ // https://github.com/freebsd/freebsd-src/commit/b0bf7fcd298133457991b27625bbed766e612730 // OpenBSD 7.6+ // https://github.com/openbsd/src/commit/0b0568a19fc4c197871ceafbabc91fabf17ca152 pub(super) const PPC_FEATURE2_ARCH_2_07: ffi::c_ulong = 0x80000000; // Linux 4.5+ // https://github.com/torvalds/linux/commit/e708c24cd01ce80b1609d8baccee40ccc3608a01 // FreeBSD 12.0+ // https://github.com/freebsd/freebsd-src/commit/18f48e0c72f91bc2d4373078a3f1ab1bcab4d8b3 // OpenBSD 7.6+ // https://github.com/openbsd/src/commit/0b0568a19fc4c197871ceafbabc91fabf17ca152 pub(super) const PPC_FEATURE2_ARCH_3_00: ffi::c_ulong = 0x00800000; // Linux 5.8+ // https://github.com/torvalds/linux/commit/ee988c11acf6f9464b7b44e9a091bf6afb3b3a49 // FreeBSD 15.0+ // https://github.com/freebsd/freebsd-src/commit/1e434da3b065ef96b389e5e0b604ae05a51e794e // OpenBSD 7.7+ // https://github.com/openbsd/src/commit/483a78e15aaa23c010911940770c1c97db5c1287 pub(super) const PPC_FEATURE2_ARCH_3_1: ffi::c_ulong = 0x00040000; }); #[cold] pub(super) fn _detect(info: &mut CpuInfo) { let hwcap = os::getauxval(ffi::AT_HWCAP); if hwcap & PPC_FEATURE_BOOKE != 0 { // quadword-atomics (Load/Store Quadword category in ISA 2.07) is requirement of ISA 2.07 // server processors. It is always optional in ISA 2.07 BookE (embedded category) // processors and there is no corresponding HWCAP bit. (Although there are no ISA 2.07 // BookE processors that appear to be supported on these platforms.) // Refs: Appendix B "Platform Support Requirements" of Power ISA 2.07B // https://ibm.ent.box.com/s/jd5w15gz301s5b5dt375mshpq9c3lh4u return; } let hwcap2 = os::getauxval(ffi::AT_HWCAP2); // Check both 2_07 and later ISAs (which are superset of 2_07) because // OpenBSD currently doesn't set 2_07 even when 3_00 is set. // https://github.com/openbsd/src/blob/d8ec5edcdf1fb224619831ad90668c95e45c3e36/sys/arch/powerpc64/powerpc64/cpu.c#L222-L238 // Other OSes should be fine, but check all OSs in the same way just in case. let isa_2_07_or_later = PPC_FEATURE2_ARCH_2_07 | PPC_FEATURE2_ARCH_3_00 | PPC_FEATURE2_ARCH_3_1; if hwcap2 & isa_2_07_or_later != 0 { info.set(CpuInfo::HAS_QUADWORD_ATOMICS); } } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use std::mem; use super::*; #[allow(clippy::cast_sign_loss)] #[cfg(all(target_arch = "aarch64", target_os = "android"))] #[test] fn test_android() { use std::{eprintln, slice, str}; unsafe { let mut arch = [1; ffi::PROP_VALUE_MAX as usize]; let len = ffi::__system_property_get( c!("ro.arch").as_ptr(), arch.as_mut_ptr().cast::(), ); assert!(len >= 0); eprintln!("len={}", len); eprintln!("arch={:?}", arch); eprintln!( "arch={:?}", str::from_utf8(slice::from_raw_parts(arch.as_ptr(), len as usize)).unwrap() ); } } #[cfg(any(target_os = "linux", target_os = "android"))] #[test] fn test_dlsym_getauxval() { unsafe { let ptr = ffi::dlsym(ffi::RTLD_DEFAULT, c!("getauxval").as_ptr()); if cfg!(any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), ), ), target_os = "android", )) { assert!(!ptr.is_null()); } else if option_env!("CI").is_some() { assert!(ptr.is_null()); } if ptr.is_null() { return; } let dlsym_getauxval = mem::transmute::<*mut ffi::c_void, os::GetauxvalTy>(ptr); assert_eq!(dlsym_getauxval(ffi::AT_HWCAP), ffi::getauxval(ffi::AT_HWCAP)); assert_eq!(dlsym_getauxval(ffi::AT_HWCAP2), ffi::getauxval(ffi::AT_HWCAP2)); } } #[cfg(any(target_os = "freebsd", target_os = "openbsd"))] #[test] fn test_dlsym_elf_aux_info() { unsafe { let ptr = ffi::dlsym(ffi::RTLD_DEFAULT, c!("elf_aux_info").as_ptr()); if cfg!(target_os = "freebsd") || option_env!("CI").is_some() { assert!(!ptr.is_null()); } if ptr.is_null() { return; } let dlsym_elf_aux_info = mem::transmute::<*mut ffi::c_void, os::ElfAuxInfoTy>(ptr); let mut out: ffi::c_ulong = 0; let mut dlsym_out: ffi::c_ulong = 0; #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] let out_len = mem::size_of::() as ffi::c_int; assert_eq!( ffi::elf_aux_info( ffi::AT_HWCAP, (&mut out as *mut ffi::c_ulong).cast::(), out_len, ), dlsym_elf_aux_info( ffi::AT_HWCAP, (&mut dlsym_out as *mut ffi::c_ulong).cast::(), out_len, ), ); assert_eq!(out, dlsym_out); out = 0; dlsym_out = 0; assert_eq!( ffi::elf_aux_info( ffi::AT_HWCAP2, (&mut out as *mut ffi::c_ulong).cast::(), out_len, ), dlsym_elf_aux_info( ffi::AT_HWCAP2, (&mut dlsym_out as *mut ffi::c_ulong).cast::(), out_len, ), ); assert_eq!(out, dlsym_out); } } #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(not(all(target_arch = "aarch64", target_pointer_width = "32")))] #[test] fn test_alternative() { use crate::utils::ffi::*; #[cfg(not(portable_atomic_no_asm))] use std::arch::asm; use std::{str, vec}; #[cfg(target_pointer_width = "32")] use sys::Elf32_auxv_t as Elf_auxv_t; #[cfg(target_pointer_width = "64")] use sys::Elf64_auxv_t as Elf_auxv_t; use test_helper::sys; // Linux kernel 6.4 has added a way to read auxv without depending on either libc or mrs trap. // https://github.com/torvalds/linux/commit/ddc65971bb677aa9f6a4c21f76d3133e106f88eb // (Actually 6.5? https://github.com/torvalds/linux/commit/636e348353a7cc52609fdba5ff3270065da140d5) // // This is currently used only for testing. fn getauxval_pr_get_auxv_no_libc(type_: c_ulong) -> Result { #[cfg(target_arch = "aarch64")] unsafe fn prctl_get_auxv(out: *mut c_void, len: usize) -> Result { let r: i64; unsafe { asm!( "svc 0", in("x8") sys::__NR_prctl as u64, inout("x0") sys::PR_GET_AUXV as u64 => r, in("x1") ptr_reg!(out), in("x2") len as u64, // arg4 and arg5 must be zero. in("x3") 0_u64, in("x4") 0_u64, options(nostack, preserves_flags), ); } #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] if (r as c_int) < 0 { Err(r as c_int) } else { Ok(r as usize) } } #[cfg(target_arch = "powerpc64")] unsafe fn prctl_get_auxv(out: *mut c_void, len: usize) -> Result { let r: i64; unsafe { asm!( "sc", "bns+ 2f", "neg %r3, %r3", "2:", inout("r0") sys::__NR_prctl as u64 => _, inout("r3") sys::PR_GET_AUXV as u64 => r, inout("r4") ptr_reg!(out) => _, inout("r5") len as u64 => _, // arg4 and arg5 must be zero. inout("r6") 0_u64 => _, inout("r7") 0_u64 => _, out("r8") _, out("r9") _, out("r10") _, out("r11") _, out("r12") _, out("cr0") _, options(nostack, preserves_flags), ); } #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] if (r as c_int) < 0 { Err(r as c_int) } else { Ok(r as usize) } } let mut auxv = vec![unsafe { mem::zeroed::() }; 38]; let old_len = auxv.len() * mem::size_of::(); // SAFETY: // - `out_len` does not exceed the size of `auxv`. let _len = unsafe { prctl_get_auxv(auxv.as_mut_ptr().cast::(), old_len)? }; for aux in &auxv { if aux.a_type == type_ { // SAFETY: aux.a_un is #[repr(C)] union and all fields have // the same size and can be safely transmuted to integers. return Ok(unsafe { aux.a_un.a_val }); } } Err(0) } // Similar to the above, but call libc prctl instead of syscall using asm. // // This is currently used only for testing. fn getauxval_pr_get_auxv_libc(type_: c_ulong) -> Result { unsafe fn prctl_get_auxv(out: *mut c_void, len: usize) -> Result { // arg4 and arg5 must be zero. #[allow(clippy::cast_possible_wrap)] let r = unsafe { libc::prctl(sys::PR_GET_AUXV as c_int, out, len, 0, 0) }; #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] if (r as c_int) < 0 { Err(r as c_int) } else { Ok(r as usize) } } let mut auxv = vec![unsafe { mem::zeroed::() }; 38]; let old_len = auxv.len() * mem::size_of::(); // SAFETY: // - `out_len` does not exceed the size of `auxv`. let _len = unsafe { prctl_get_auxv(auxv.as_mut_ptr().cast::(), old_len)? }; for aux in &auxv { if aux.a_type == type_ { // SAFETY: aux.a_un is #[repr(C)] union and all fields have // the same size and can be safely transmuted to integers. return Ok(unsafe { aux.a_un.a_val }); } } Err(0) } unsafe { let mut u = mem::zeroed(); assert_eq!(libc::uname(&mut u), 0); let release = std::ffi::CStr::from_ptr(u.release.as_ptr()); let release = str::from_utf8(release.to_bytes()).unwrap(); let mut digits = release.split('.'); let major = digits.next().unwrap().parse::().unwrap(); let minor = digits.next().unwrap().parse::().unwrap(); // TODO: qemu-user bug? if (major, minor) < (6, 4) || cfg!(qemu) { std::eprintln!("kernel version: {}.{} (no pr_get_auxv)", major, minor); assert_eq!(getauxval_pr_get_auxv_libc(ffi::AT_HWCAP).unwrap_err(), -1); assert_eq!(getauxval_pr_get_auxv_libc(ffi::AT_HWCAP2).unwrap_err(), -1); assert_eq!( getauxval_pr_get_auxv_no_libc(ffi::AT_HWCAP).unwrap_err(), -libc::EINVAL ); assert_eq!( getauxval_pr_get_auxv_no_libc(ffi::AT_HWCAP2).unwrap_err(), -libc::EINVAL ); } else if cfg!(valgrind) { // TODO: valgrind bug } else { std::eprintln!("kernel version: {}.{} (has pr_get_auxv)", major, minor); assert_eq!( os::getauxval(ffi::AT_HWCAP), getauxval_pr_get_auxv_libc(ffi::AT_HWCAP).unwrap() ); assert_eq!( os::getauxval(ffi::AT_HWCAP2), getauxval_pr_get_auxv_libc(ffi::AT_HWCAP2).unwrap() ); assert_eq!( os::getauxval(ffi::AT_HWCAP), getauxval_pr_get_auxv_no_libc(ffi::AT_HWCAP).unwrap() ); assert_eq!( os::getauxval(ffi::AT_HWCAP2), getauxval_pr_get_auxv_no_libc(ffi::AT_HWCAP2).unwrap() ); } } } #[allow(clippy::cast_possible_wrap)] #[cfg(target_os = "freebsd")] #[test] fn test_alternative() { use crate::utils::ffi::*; #[cfg(not(portable_atomic_no_asm))] use std::arch::asm; use std::ptr; use test_helper::sys; // This is almost equivalent to what elf_aux_info does. // https://man.freebsd.org/elf_aux_info(3) // On FreeBSD, [AArch64 support is available on FreeBSD 11.0+](https://www.freebsd.org/releases/11.0R/announce), // but elf_aux_info is available on FreeBSD 12.0+ and 11.4+: // https://github.com/freebsd/freebsd-src/commit/0b08ae2120cdd08c20a2b806e2fcef4d0a36c470 // https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h // so use sysctl instead of elf_aux_info. // Note that FreeBSD 11 (11.4) was EoL on 2021-09-30, and FreeBSD 11.3 was EoL on 2020-09-30: // https://www.freebsd.org/security/unsupported // // This is currently used only for testing. // If you want us to use this implementation for compatibility with the older FreeBSD // version that came to EoL a few years ago, please open an issue. fn getauxval_sysctl_libc(type_: ffi::c_int) -> Result { let mut auxv: [sys::Elf_Auxinfo; sys::AT_COUNT as usize] = unsafe { mem::zeroed() }; let mut len = mem::size_of_val(&auxv) as c_size_t; // SAFETY: calling getpid is safe. let pid = unsafe { libc::getpid() }; let mib = [ sys::CTL_KERN as c_int, sys::KERN_PROC as c_int, sys::KERN_PROC_AUXV as c_int, pid, ]; #[allow(clippy::cast_possible_truncation)] // SAFETY: // - `mib.len()` does not exceed the size of `mib`. // - `len` does not exceed the size of `auxv`. // - `sysctl` is thread-safe. let res = unsafe { libc::sysctl( mib.as_ptr(), mib.len() as c_uint, auxv.as_mut_ptr().cast::(), &mut len, ptr::null_mut(), 0, ) }; if res == -1 { return Err(res); } for aux in &auxv { if aux.a_type == type_ as c_long { // SAFETY: aux.a_un is #[repr(C)] union and all fields have // the same size and can be safely transmuted to integers. return Ok(unsafe { aux.a_un.a_val as c_ulong }); } } Err(0) } // Similar to the above, but call syscall using asm instead of libc. // Note that FreeBSD does not guarantee the stability of raw syscall as // much as Linux does (It may actually be stable enough, though: // https://lists.llvm.org/pipermail/llvm-dev/2019-June/133393.html, // https://github.com/ziglang/zig/issues/16590). // // This is currently used only for testing. fn getauxval_sysctl_no_libc(type_: ffi::c_int) -> Result { #[allow(non_camel_case_types)] type pid_t = c_int; // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/lib/libc/aarch64/SYS.h // https://github.com/golang/go/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/src/syscall/asm_freebsd_arm64.s #[cfg(target_arch = "aarch64")] #[inline] fn getpid() -> pid_t { #[allow(clippy::cast_possible_truncation)] // SAFETY: calling getpid is safe. unsafe { let n = sys::SYS_getpid; let r: i64; asm!( "svc 0", in("x8") n as u64, out("x0") r, options(nostack, readonly), ); r as pid_t } } #[cfg(target_arch = "aarch64")] #[inline] unsafe fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> Result { #[allow(clippy::cast_possible_truncation)] // SAFETY: the caller must uphold the safety contract. unsafe { let mut n = sys::SYS___sysctl as u64; let r: i64; asm!( "svc 0", "b.cc 2f", "mov x8, x0", "mov x0, #-1", "2:", inout("x8") n, inout("x0") ptr_reg!(name) => r, inout("x1") name_len as u64 => _, in("x2") ptr_reg!(old_p), in("x3") ptr_reg!(old_len_p), in("x4") ptr_reg!(new_p), in("x5") new_len as u64, options(nostack), ); if r as c_int == -1 { Err(n as c_int) } else { Ok(r as c_int) } } } // https://github.com/freebsd/freebsd-src/blob/release/14.2.0/lib/libc/powerpc64/SYS.h #[cfg(target_arch = "powerpc64")] #[inline] fn getpid() -> pid_t { #[allow(clippy::cast_possible_truncation)] // SAFETY: calling getpid is safe. unsafe { let n = sys::SYS_getpid; let r: i64; asm!( "sc", inout("r0") n as u64 => _, out("r3") r, out("r4") _, out("r5") _, out("r6") _, out("r7") _, out("r8") _, out("r9") _, out("r10") _, out("r11") _, out("r12") _, out("cr0") _, options(nostack, preserves_flags, readonly), ); r as pid_t } } #[cfg(target_arch = "powerpc64")] #[inline] unsafe fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> Result { #[allow(clippy::cast_possible_truncation)] // SAFETY: the caller must uphold the safety contract. unsafe { let mut n = sys::SYS___sysctl as u64; let r: i64; asm!( "sc", "bns+ 2f", "mr %r0, %r3", "li %r3, -1", "2:", inout("r0") n, inout("r3") ptr_reg!(name) => r, inout("r4") name_len as u64 => _, inout("r5") ptr_reg!(old_p) => _, inout("r6") ptr_reg!(old_len_p) => _, inout("r7") ptr_reg!(new_p) => _, inout("r8") new_len as u64 => _, out("r9") _, out("r10") _, out("r11") _, out("r12") _, out("cr0") _, options(nostack, preserves_flags), ); if r as c_int == -1 { Err(n as c_int) } else { Ok(r as c_int) } } } let mut auxv: [sys::Elf_Auxinfo; sys::AT_COUNT as usize] = unsafe { mem::zeroed() }; let mut len = mem::size_of_val(&auxv) as c_size_t; let pid = getpid(); let mib = [ sys::CTL_KERN as c_int, sys::KERN_PROC as c_int, sys::KERN_PROC_AUXV as c_int, pid, ]; #[allow(clippy::cast_possible_truncation)] // SAFETY: // - `mib.len()` does not exceed the size of `mib`. // - `len` does not exceed the size of `auxv`. // - `sysctl` is thread-safe. unsafe { sysctl( mib.as_ptr(), mib.len() as c_uint, auxv.as_mut_ptr().cast::(), &mut len, ptr::null_mut(), 0, )?; } for aux in &auxv { if aux.a_type == type_ as c_long { // SAFETY: aux.a_un is #[repr(C)] union and all fields have // the same size and can be safely transmuted to integers. return Ok(unsafe { aux.a_un.a_val as c_ulong }); } } Err(0) } // AT_HWCAP2 is only available on FreeBSD 13+ on AArch64. let hwcap2_else = |e| if cfg!(target_arch = "aarch64") { 0 } else { panic!("{:?}", e) }; assert_eq!(os::getauxval(ffi::AT_HWCAP), getauxval_sysctl_libc(ffi::AT_HWCAP).unwrap()); assert_eq!( os::getauxval(ffi::AT_HWCAP2), getauxval_sysctl_libc(ffi::AT_HWCAP2).unwrap_or_else(hwcap2_else) ); assert_eq!(os::getauxval(ffi::AT_HWCAP), getauxval_sysctl_no_libc(ffi::AT_HWCAP).unwrap()); assert_eq!( os::getauxval(ffi::AT_HWCAP2), getauxval_sysctl_no_libc(ffi::AT_HWCAP2).unwrap_or_else(hwcap2_else) ); } } portable-atomic/src/imp/detect/aarch64_fuchsia.rs0000644000175000017500000000622115105742312021611 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on AArch64 Fuchsia by using zx_system_get_features. As of nightly-2024-09-07, is_aarch64_feature_detected doesn't support run-time detection on Fuchsia. https://github.com/rust-lang/stdarch/blob/d9466edb4c53cece8686ee6e17b028436ddf4151/crates/std_detect/src/detect/mod.rs Refs: - https://fuchsia.dev/reference/syscalls/system_get_features - https://github.com/llvm/llvm-project/commit/4e731abc55681751b5d736b613f7720e50eb1ad4 */ include!("common.rs"); #[allow(non_camel_case_types)] mod ffi { // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/types.h pub(crate) type zx_status_t = i32; sys_const!({ // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/errors.h pub(crate) const ZX_OK: zx_status_t = 0; // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/features.h pub(crate) const ZX_FEATURE_KIND_CPU: u32 = 0; pub(crate) const ZX_ARM64_FEATURE_ISA_ATOMICS: u32 = 1 << 8; }); // TODO: use sys_fn! #[link(name = "zircon")] extern "C" { // https://fuchsia.dev/reference/syscalls/system_get_features pub(crate) fn zx_system_get_features(kind: u32, features: *mut u32) -> zx_status_t; } } fn zx_system_get_features(kind: u32) -> u32 { let mut out = 0_u32; // SAFETY: the pointer is valid because we got it from a reference. let res = unsafe { ffi::zx_system_get_features(kind, &mut out) }; if res != ffi::ZX_OK { return 0; } out } #[cold] fn _detect(info: &mut CpuInfo) { let features = zx_system_get_features(ffi::ZX_FEATURE_KIND_CPU); if features & ffi::ZX_ARM64_FEATURE_ISA_ATOMICS != 0 { info.set(CpuInfo::HAS_LSE); } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; #[test] fn test_fuchsia() { let features = zx_system_get_features(ffi::ZX_FEATURE_KIND_CPU); assert_ne!(features, 0); std::eprintln!("features: {:b}", features); } // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate and FFI bindings // generated for the platform's latest header file using bindgen have // compatible signatures. // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // As for constants, they are checked by static assertions generated by sys_const!. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation)] const _: fn() = || { use test_helper::sys; // TODO(codegen): zx_system_get_features let _: ffi::zx_status_t = 0 as sys::zx_status_t; }; } portable-atomic/src/imp/detect/aarch64_illumos.rs0000644000175000017500000000321715105742312021655 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on AArch64 illumos by using getisax. As of nightly-2024-09-07, is_aarch64_feature_detected doesn't support run-time detection on illumos. https://github.com/rust-lang/stdarch/blob/d9466edb4c53cece8686ee6e17b028436ddf4151/crates/std_detect/src/detect/mod.rs Run-time detection on AArch64 illumos is currently disabled by default as experimental because illumos AArch64 port is experimental and we cannot run tests on the VM or real machine. */ include!("common.rs"); // libc requires Rust 1.63 mod ffi { pub(crate) use crate::utils::ffi::c_uint; sys_const!({ // Defined in sys/auxv_aarch64.h. // https://github.com/richlowe/illumos-gate/blob/arm64-gate/usr/src/uts/common/sys/auxv_aarch64.h pub(crate) const AV_AARCH64_LSE: u32 = 1 << 15; pub(crate) const AV_AARCH64_2_LSE2: u32 = 1 << 2; }); sys_fn!({ extern "C" { // Defined in sys/auxv.h. // https://illumos.org/man/2/getisax // https://github.com/richlowe/illumos-gate/blob/arm64-gate/usr/src/uts/common/sys/auxv.h pub(crate) fn getisax(array: *mut u32, n: c_uint) -> c_uint; } }); } #[cold] fn _detect(info: &mut CpuInfo) { const OUT_LEN: ffi::c_uint = 2; let mut out = [0_u32; OUT_LEN as usize]; // SAFETY: the pointer is valid because we got it from a reference. unsafe { ffi::getisax(out.as_mut_ptr(), OUT_LEN); } if out[0] & ffi::AV_AARCH64_LSE != 0 { info.set(CpuInfo::HAS_LSE); } if out[1] & ffi::AV_AARCH64_2_LSE2 != 0 { info.set(CpuInfo::HAS_LSE2); } } portable-atomic/src/imp/detect/x86_64.rs0000644000175000017500000001402315105742312017614 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on x86_64 by using CPUID. Adapted from https://github.com/rust-lang/stdarch. */ #![cfg_attr(portable_atomic_sanitize_thread, allow(dead_code))] // Miri doesn't support inline assembly used in __cpuid: https://github.com/rust-lang/miri/issues/932 // SGX doesn't support CPUID: https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/core_arch/src/x86/cpuid.rs#L102-L105 #[cfg(any(target_env = "sgx", miri))] compile_error!("internal error: this module is not supported on this environment"); include!("common.rs"); #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::arch::x86_64::CpuidResult; // Workaround for https://github.com/rust-lang/rust/issues/101346 // It is not clear if our use cases are affected, but we implement this just in case. // // Refs: // - https://www.felixcloutier.com/x86/cpuid // - https://en.wikipedia.org/wiki/CPUID // - https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/core_arch/src/x86/cpuid.rs #[cfg(not(target_env = "sgx"))] fn __cpuid(leaf: u32) -> CpuidResult { let eax; let mut ebx; let ecx; let edx; // SAFETY: Calling `__cpuid`` is safe on all x86_64 CPUs except for SGX, // which doesn't support `cpuid`. // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/core_arch/src/x86/cpuid.rs#L102-L109 unsafe { asm!( "mov {ebx_tmp:r}, rbx", // save rbx which is reserved by LLVM "cpuid", "xchg {ebx_tmp:r}, rbx", // restore rbx ebx_tmp = out(reg) ebx, inout("eax") leaf => eax, inout("ecx") 0 => ecx, out("edx") edx, options(nostack, preserves_flags), ); } CpuidResult { eax, ebx, ecx, edx } } // https://en.wikipedia.org/wiki/CPUID const _VENDOR_ID_INTEL: [u32; 3] = _vender(b"GenuineIntel"); // Intel const _VENDOR_ID_INTEL2: [u32; 3] = _vender(b"GenuineIotel"); // Intel https://github.com/InstLatx64/InstLatx64/commit/8fdd319884c67d2c6ec1ca0c595b42c1c4b8d803 const _VENDOR_ID_AMD: [u32; 3] = _vender(b"AuthenticAMD"); // AMD const _VENDOR_ID_CENTAUR: [u32; 3] = _vender(b"CentaurHauls"); // Centaur/VIA/Zhaoxin const _VENDOR_ID_ZHAOXIN: [u32; 3] = _vender(b" Shanghai "); // Zhaoxin const fn _vender(b: &[u8; 12]) -> [u32; 3] { [ u32::from_ne_bytes([b[0], b[1], b[2], b[3]]), u32::from_ne_bytes([b[4], b[5], b[6], b[7]]), u32::from_ne_bytes([b[8], b[9], b[10], b[11]]), ] } fn _vendor_id() -> [u32; 3] { let CpuidResult { ebx, ecx, edx, .. } = __cpuid(0); [ebx, edx, ecx] } fn _vendor_has_vmovdqa_atomic(vendor_id: [u32; 3], family: u32) -> bool { // VMOVDQA is atomic on Intel, AMD, and Zhaoxin CPUs with AVX. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 for details. vendor_id == _VENDOR_ID_INTEL || vendor_id == _VENDOR_ID_INTEL2 || vendor_id == _VENDOR_ID_AMD || vendor_id == _VENDOR_ID_ZHAOXIN || vendor_id == _VENDOR_ID_CENTAUR && family > 6 } #[cold] fn _detect(info: &mut CpuInfo) { let CpuidResult { #[cfg(target_feature = "sse")] eax: proc_info_eax, ecx: proc_info_ecx, .. } = __cpuid(1); // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L111 if test(proc_info_ecx, 13) { info.set(CpuInfo::HAS_CMPXCHG16B); } // We only use VMOVDQA when SSE is enabled. See atomic_load_vmovdqa() in atomic128/x86_64.rs for more. #[cfg(target_feature = "sse")] { use core::arch::x86_64::_xgetbv; // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L131-L224 let cpu_xsave = test(proc_info_ecx, 26); if cpu_xsave { let cpu_osxsave = test(proc_info_ecx, 27); if cpu_osxsave { // SAFETY: Calling `_xgetbv`` is safe because the CPU has `xsave` support // and OS has set `osxsave`. let xcr0 = unsafe { _xgetbv(0) }; let os_avx_support = xcr0 & 6 == 6; if os_avx_support && test(proc_info_ecx, 28) { let vendor_id = _vendor_id(); let family = (proc_info_eax >> 8) & 0x0F; if _vendor_has_vmovdqa_atomic(vendor_id, family) { info.set(CpuInfo::HAS_VMOVDQA_ATOMIC); } } } } } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use std::{ io::{self, Write as _}, mem, str, }; use super::*; #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_cpuid() { assert_eq!(std::is_x86_feature_detected!("cmpxchg16b"), detect().has_cmpxchg16b()); let vendor_id = _vendor_id(); { let stdout = io::stderr(); let mut stdout = stdout.lock(); let _ = writeln!( stdout, "\n vendor_id: {} (ebx: {:x}, edx: {:x}, ecx: {:x})", str::from_utf8(&unsafe { mem::transmute::<[u32; 3], [u8; 12]>(vendor_id) }) .unwrap(), vendor_id[0], vendor_id[1], vendor_id[2], ); } let CpuidResult { eax: proc_info_eax, .. } = __cpuid(1); let family = (proc_info_eax >> 8) & 0x0F; if _vendor_has_vmovdqa_atomic(vendor_id, family) { assert_eq!(std::is_x86_feature_detected!("avx"), detect().has_vmovdqa_atomic()); } else { assert!(!detect().has_vmovdqa_atomic()); } assert_eq!( unsafe { mem::transmute::<[u32; 3], [u8; 12]>(_VENDOR_ID_INTEL) }, *b"GenuineIntel" ); } } portable-atomic/src/imp/detect/common.rs0000644000175000017500000004237015105742312020154 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT #[derive(Clone, Copy)] #[repr(transparent)] pub(crate) struct CpuInfo(u32); impl CpuInfo { #[inline] fn set(&mut self, bit: u32) { self.0 = set(self.0, bit); } #[inline] fn test(self, bit: u32) -> bool { test(self.0, bit) } } #[inline] fn set(x: u32, bit: u32) -> u32 { x | (1 << bit) } #[inline] fn test(x: u32, bit: u32) -> bool { x & (1 << bit) != 0 } #[inline] pub(crate) fn detect() -> CpuInfo { use core::sync::atomic::{AtomicU32, Ordering}; static CACHE: AtomicU32 = AtomicU32::new(0); let mut info = CpuInfo(CACHE.load(Ordering::Relaxed)); if info.0 != 0 { return info; } info.set(CpuInfo::INIT); // Note: detect_false cfg is intended to make it easy for portable-atomic developers to // test cases such as has_cmpxchg16b == false, has_lse == false, // __kuser_helper_version < 5, etc., and is not a public API. if !cfg!(portable_atomic_test_outline_atomics_detect_false) { _detect(&mut info); } CACHE.store(info.0, Ordering::Relaxed); info } macro_rules! flags { ($( $(#[$attr:meta])* $flag:ident ($func:ident, $name:literal, any($($cfg:ident),*)), )*) => { #[allow(dead_code, non_camel_case_types)] #[repr(u32)] enum CpuInfoFlag { Init = 0, $($flag,)* } impl CpuInfo { const INIT: u32 = CpuInfoFlag::Init as u32; $( $(#[$attr])* const $flag: u32 = CpuInfoFlag::$flag as u32; $(#[$attr])* #[cfg(any(test, not(any($($cfg = $name),*))))] #[inline] pub(crate) fn $func(self) -> bool { self.test(Self::$flag) } )* #[cfg(test)] // for test const ALL_FLAGS: &'static [(&'static str, u32, bool)] = &[$( ($name, Self::$flag, cfg!(any($($cfg = $name),*))), )*]; } }; } #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] flags! { // FEAT_LSE, Large System Extensions // https://developer.arm.com/documentation/109697/2024_12/Feature-descriptions/The-Armv8-1-architecture-extension // > This feature is supported in AArch64 state only. // > FEAT_LSE is OPTIONAL from Armv8.0. // > FEAT_LSE is mandatory from Armv8.1. HAS_LSE(has_lse, "lse", any(target_feature, portable_atomic_target_feature)), // FEAT_LSE2, Large System Extensions version 2 // https://developer.arm.com/documentation/109697/2024_12/Feature-descriptions/The-Armv8-4-architecture-extension // > This feature is supported in AArch64 state only. // > FEAT_LSE2 is OPTIONAL from Armv8.2. // > FEAT_LSE2 is mandatory from Armv8.4. #[cfg_attr(not(test), allow(dead_code))] HAS_LSE2(has_lse2, "lse2", any(target_feature, portable_atomic_target_feature)), // FEAT_LRCPC3, Load-Acquire RCpc instructions version 3 // https://developer.arm.com/documentation/109697/2024_12/Feature-descriptions/The-Armv8-9-architecture-extension // > This feature is supported in AArch64 state only. // > FEAT_LRCPC3 is OPTIONAL from Armv8.2. // > If FEAT_LRCPC3 is implemented, then FEAT_LRCPC2 is implemented. #[cfg_attr(not(test), allow(dead_code))] HAS_RCPC3(has_rcpc3, "rcpc3", any(target_feature, portable_atomic_target_feature)), // FEAT_LSE128, 128-bit Atomics // https://developer.arm.com/documentation/109697/2024_12/Feature-descriptions/The-Armv9-4-architecture-extension // > This feature is supported in AArch64 state only. // > FEAT_LSE128 is OPTIONAL from Armv9.3. // > If FEAT_LSE128 is implemented, then FEAT_LSE is implemented. #[cfg_attr(not(test), allow(dead_code))] HAS_LSE128(has_lse128, "lse128", any(target_feature, portable_atomic_target_feature)), } #[cfg(target_arch = "powerpc64")] flags! { // lqarx and stqcx. HAS_QUADWORD_ATOMICS(has_quadword_atomics, "quadword-atomics", any(target_feature, portable_atomic_target_feature)), } #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] flags! { // amocas.{w,d,q} HAS_ZACAS(has_zacas, "zacas", any(target_feature, portable_atomic_target_feature)), } #[cfg(target_arch = "x86_64")] flags! { // cmpxchg16b HAS_CMPXCHG16B(has_cmpxchg16b, "cmpxchg16b", any(target_feature, portable_atomic_target_feature)), // atomic vmovdqa #[cfg(target_feature = "sse")] HAS_VMOVDQA_ATOMIC(has_vmovdqa_atomic, "vmovdqa-atomic", any(/* always false */)), } // Helper macros for defining FFI bindings. #[cfg(not(any(windows, target_arch = "x86", target_arch = "x86_64")))] #[allow(unused_macros)] #[macro_use] mod ffi_macros { /// Defines constants with #[cfg(test)] static assertions which checks /// values are the same as the platform's latest header files' ones. // Note: This macro is sys_const!({ }), not sys_const! { }. // An extra brace is used in input to make contents rustfmt-able:. macro_rules! sys_const { ({$( $(#[$attr:meta])* $vis:vis const $name:ident: $ty:ty = $val:expr; )*}) => { $( $(#[$attr])* $vis const $name: $ty = $val; )* // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate and FFI bindings generated for // the platform's latest header file using bindgen have the same values. // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. #[cfg(test)] #[allow( unused_attributes, // for #[allow(..)] in $(#[$attr])* clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation, )] const _: fn() = || {$( $(#[$attr])* sys_const_cmp!($name, $ty); )*}; }; } #[cfg(test)] macro_rules! sys_const_cmp { (RTLD_DEFAULT, $ty:ty) => { // ptr comparison and ptr-to-int cast are not stable on const context, so use ptr-to-int // transmute and compare its result. static_assert!( // SAFETY: Pointer-to-integer transmutes are valid (since we are okay with losing the // provenance here). (Same as ::addr().) unsafe { core::mem::transmute::<$ty, usize>(RTLD_DEFAULT) == core::mem::transmute::<$ty, usize>(test_helper::sys::RTLD_DEFAULT) } ); }; ($name:ident, $ty:ty) => { static_assert!($name == test_helper::sys::$name as $ty); }; } /// Defines functions with #[cfg(test)] static assertions which checks /// signatures are the same as the platform's latest header files' ones. // Note: This macro is sys_fn!({ }), not sys_fn! { }. // An extra brace is used in input to make contents rustfmt-able:. macro_rules! sys_fn { ({ $(#[$extern_attr:meta])* extern $abi:literal {$( $(#[$fn_attr:meta])* $vis:vis fn $name:ident($($arg_pat:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?; )*} }) => { $(#[$extern_attr])* extern $abi {$( $(#[$fn_attr])* $vis fn $name($($arg_pat: $arg_ty),*) $(-> $ret_ty)?; )*} // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate and FFI bindings generated for // the platform's latest header file using bindgen have the same signatures. // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. #[cfg(test)] const _: fn() = || {$( $(#[$fn_attr])* { let mut _f: unsafe extern $abi fn($($arg_ty),*) $(-> $ret_ty)? = $name; _f = test_helper::sys::$name; } )*}; }; } /// Defines #[repr(C)] structs with #[cfg(test)] static assertions which checks /// fields are the same as the platform's latest header files' ones. // Note: This macro is sys_struct!({ }), not sys_struct! { }. // An extra brace is used in input to make contents rustfmt-able:. macro_rules! sys_struct { ({$( $(#[$struct_attr:meta])* $struct_vis:vis struct $struct_name:ident {$( $(#[$field_attr:meta])* $field_vis:vis $field_name:ident: $field_ty:ty, )*} )*}) => { $( $(#[$struct_attr])* #[derive(Copy, Clone)] #[cfg_attr(test, derive(Debug, PartialEq))] #[repr(C)] $struct_vis struct $struct_name {$( $(#[$field_attr])* $field_vis $field_name: $field_ty, )*} )* // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate and FFI bindings generated for // the platform's latest header file using bindgen have the same fields. // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // See also https://github.com/taiki-e/test-helper/blob/HEAD/tools/codegen/src/ffi.rs. #[cfg(test)] #[allow(clippy::undocumented_unsafe_blocks)] const _: fn() = || {$( $(#[$struct_attr])* { static_assert!( core::mem::size_of::<$struct_name>() == core::mem::size_of::() ); let s: $struct_name = unsafe { core::mem::zeroed() }; // field names and types let _ = test_helper::sys::$struct_name {$( $(#[$field_attr])* $field_name: s.$field_name, )*}; // field offsets #[cfg(not(portable_atomic_no_offset_of))] {$( $(#[$field_attr])* static_assert!( core::mem::offset_of!($struct_name, $field_name) == core::mem::offset_of!(test_helper::sys::$struct_name, $field_name), ); )*} } )*}; }; } // Static assertions for C type definitions. // Assertions with core::ffi types are in crate::utils::ffi module. #[cfg(test)] const _: fn() = || { use test_helper::sys; let _: crate::utils::ffi::c_char = 0 as sys::c_char; }; } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests_common { use std::{collections::BTreeSet, vec}; use super::*; #[test] fn test_bit_flags() { let mut flags = vec![("init", CpuInfo::INIT)]; flags.extend(CpuInfo::ALL_FLAGS.iter().map(|&(name, flag, _)| (name, flag))); let flag_set = flags.iter().map(|(_, flag)| flag).collect::>(); let name_set = flags.iter().map(|(_, flag)| flag).collect::>(); if flag_set.len() != flags.len() { panic!("CpuInfo flag values must be unique") } if name_set.len() != flags.len() { panic!("CpuInfo flag names must be unique") } let mut x = CpuInfo(0); for &(_, f) in &flags { assert!(!x.test(f)); } for i in 0..flags.len() { x.set(flags[i].1); for &(_, f) in &flags[..i + 1] { assert!(x.test(f)); } for &(_, f) in &flags[i + 1..] { assert!(!x.test(f)); } } for &(_, f) in &flags { assert!(x.test(f)); } } #[test] fn print_features() { use std::{ fmt::Write as _, io::{self, Write as _}, string::String, }; let mut features = String::new(); features.push_str("\nfeatures:\n"); for &(name, flag, compile_time) in CpuInfo::ALL_FLAGS { let run_time = detect().test(flag); if run_time == compile_time { let _ = writeln!(features, " {}: {}", name, run_time); } else { let _ = writeln!( features, " {}: {} (compile-time), {} (run-time)", name, compile_time, run_time ); } } let stdout = io::stderr(); let mut stdout = stdout.lock(); let _ = stdout.write_all(features.as_bytes()); } #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_detect() { let proc_cpuinfo = test_helper::cpuinfo::ProcCpuinfo::new(); if detect().has_lse() { assert!(detect().test(CpuInfo::HAS_LSE)); if let Ok(proc_cpuinfo) = proc_cpuinfo { assert!(proc_cpuinfo.lse); } } else { assert!(!detect().test(CpuInfo::HAS_LSE)); if let Ok(proc_cpuinfo) = proc_cpuinfo { assert!(!proc_cpuinfo.lse); } } if detect().has_lse2() { assert!(detect().test(CpuInfo::HAS_LSE)); assert!(detect().test(CpuInfo::HAS_LSE2)); if let Ok(test_helper::cpuinfo::ProcCpuinfo { lse2: Some(lse2), .. }) = proc_cpuinfo { assert!(lse2); } } else { assert!(!detect().test(CpuInfo::HAS_LSE2)); if let Ok(test_helper::cpuinfo::ProcCpuinfo { lse2: Some(lse2), .. }) = proc_cpuinfo { // cpuinfo shows features of host, not valgrind if !cfg!(valgrind) { assert!(!lse2); } } } if detect().has_lse128() { assert!(detect().test(CpuInfo::HAS_LSE)); assert!(detect().test(CpuInfo::HAS_LSE2)); assert!(detect().test(CpuInfo::HAS_LSE128)); if let Ok(test_helper::cpuinfo::ProcCpuinfo { lse128: Some(lse128), .. }) = proc_cpuinfo { assert!(lse128); } } else { assert!(!detect().test(CpuInfo::HAS_LSE128)); if let Ok(test_helper::cpuinfo::ProcCpuinfo { lse128: Some(lse128), .. }) = proc_cpuinfo { assert!(!lse128); } } if detect().has_rcpc3() { assert!(detect().test(CpuInfo::HAS_RCPC3)); if let Ok(test_helper::cpuinfo::ProcCpuinfo { rcpc3: Some(rcpc3), .. }) = proc_cpuinfo { assert!(rcpc3); } } else { assert!(!detect().test(CpuInfo::HAS_RCPC3)); if let Ok(test_helper::cpuinfo::ProcCpuinfo { rcpc3: Some(rcpc3), .. }) = proc_cpuinfo { assert!(!rcpc3); } } } #[cfg(target_arch = "powerpc64")] #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_detect() { let proc_cpuinfo = test_helper::cpuinfo::ProcCpuinfo::new(); if detect().has_quadword_atomics() { assert!(detect().test(CpuInfo::HAS_QUADWORD_ATOMICS)); if let Ok(proc_cpuinfo) = proc_cpuinfo { assert!(proc_cpuinfo.power8); } } else { assert!(!detect().test(CpuInfo::HAS_QUADWORD_ATOMICS)); if let Ok(proc_cpuinfo) = proc_cpuinfo { assert!(!proc_cpuinfo.power8); } } } #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_detect() { if detect().has_zacas() { assert!(detect().test(CpuInfo::HAS_ZACAS)); } else { assert!(!detect().test(CpuInfo::HAS_ZACAS)); } } #[cfg(target_arch = "x86_64")] #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_detect() { if detect().has_cmpxchg16b() { assert!(detect().test(CpuInfo::HAS_CMPXCHG16B)); } else { assert!(!detect().test(CpuInfo::HAS_CMPXCHG16B)); } if detect().has_vmovdqa_atomic() { assert!(detect().test(CpuInfo::HAS_VMOVDQA_ATOMIC)); } else { assert!(!detect().test(CpuInfo::HAS_VMOVDQA_ATOMIC)); } } } portable-atomic/src/imp/detect/README.md0000644000175000017500000000612415105742312017572 0ustar bdrungbdrung# Run-time CPU feature detection This module has run-time CPU feature detection implementations. Here is the table of targets that support run-time CPU feature detection and the instruction or API used: | target_arch | target_os/target_env | instruction/API | features | note | | ----------- | -------------------- | --------------- | -------- | ---- | | x86_64 | all (except for sgx) | cpuid | all | Enabled by default | | aarch64 | linux | getauxval | all | Only enabled by default on `*-linux-gnu*` and `*-linux-{musl,ohos,uclibc}*` with dynamic linking enabled (musl is static linking by default). (dlsym is used by default if needed for compatibility with older versions) | | aarch64 | android | getauxval | all | Enabled by default | | aarch64 | freebsd | elf_aux_info | all | Enabled by default | | aarch64 | netbsd | sysctlbyname | all | Enabled by default | | aarch64 | openbsd | sysctl | all | Enabled by default | | aarch64 | macos/ios/tvos/watchos/visionos | sysctlbyname | all | Currently only used in tests (see [aarch64_apple.rs](aarch64_apple.rs)). | | aarch64 | illumos | getisax | lse, lse2 | Disabled by default (experimental) | | aarch64/arm64ec | windows | IsProcessorFeaturePresent | lse | Enabled by default | | aarch64 | fuchsia | zx_system_get_features | lse | Enabled by default | | riscv32/riscv64 | linux/android | riscv_hwprobe | all | Enabled by default | | powerpc64 | linux | getauxval | all | Only enabled by default on `*-linux-{gnu,musl,ohos,uclibc}*` with dynamic linking enabled (musl is static linking by default). (dlsym is used by default if needed for compatibility with older versions) | | powerpc64 | freebsd | elf_aux_info | all | Enabled by default (dlsym is used by default for compatibility with older versions) | | powerpc64 | openbsd | elf_aux_info | all | Enabled by default (dlsym is used by default for compatibility with older versions) | | powerpc64 | aix | getsystemcfg | all | Requires LLVM 20+. Disabled by default (experimental) | Run-time detection is enabled by default on most targets and can be disabled with `--cfg portable_atomic_no_outline_atomics`. On some targets, run-time detection is disabled by default mainly for compatibility with incomplete build environments or support for it is experimental, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.) For targets not included in the above table, run-time detection is always disabled and works the same as when `--cfg portable_atomic_no_outline_atomics` is set. See [auxv.rs](auxv.rs) module-level comments for more details on Linux/Android/FreeBSD/OpenBSD. See also [docs on `portable_atomic_no_outline_atomics`](https://github.com/taiki-e/portable-atomic/blob/HEAD/README.md#optional-cfg-no-outline-atomics) in the top-level readme. portable-atomic/src/imp/detect/aarch64_aa64reg.rs0000644000175000017500000004723415105742312021431 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on AArch64 Linux/Android/FreeBSD/NetBSD/OpenBSD by parsing system registers. As of nightly-2024-09-07, is_aarch64_feature_detected doesn't support run-time detection on NetBSD. https://github.com/rust-lang/stdarch/blob/d9466edb4c53cece8686ee6e17b028436ddf4151/crates/std_detect/src/detect/mod.rs Run-time detection on OpenBSD by is_aarch64_feature_detected is supported on Rust 1.70+. https://github.com/rust-lang/stdarch/pull/1374 Refs: - https://developer.arm.com/documentation/ddi0601/2024-12/AArch64-Registers - https://github.com/torvalds/linux/blob/v6.13/Documentation/arch/arm64/cpu-feature-registers.rst - https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/aarch64.rs Supported platforms: - Linux 4.11+ (emulate mrs instruction) https://github.com/torvalds/linux/commit/77c97b4ee21290f5f083173d957843b615abbff2 - FreeBSD 12.0+ (emulate mrs instruction) https://github.com/freebsd/freebsd-src/commit/398810619cb32abf349f8de23f29510b2ee0839b - NetBSD 9.0+ (through sysctl/sysctlbyname) https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb sysctl/sysctlbyname returns an unsupported error if operation is not supported, so we can safely use this on older versions. - OpenBSD 7.1+ (through sysctl) https://github.com/openbsd/src/commit/d335af936b9d7dd9cf655cae1ce19560c45de6c8 sysctl returns an unsupported error if operation is not supported, so we can safely use this on older versions. For now, this module is only used on NetBSD/OpenBSD. On Linux/Android/FreeBSD, we use auxv.rs and this module is test-only because: - On Linux/Android, this approach requires a higher kernel version than Rust supports, and also does not work with qemu-user (as of 7.2) and Valgrind (as of 3.19). (Looking into HWCAP_CPUID in auxvec, it appears that Valgrind is setting it to false correctly, but qemu-user is setting it to true.) - On FreeBSD, this approach does not work on FreeBSD 12 on QEMU (confirmed on FreeBSD 12.{2,3,4}), and we got SIGILL (worked on FreeBSD 13 and 14). */ include!("common.rs"); #[cfg_attr(test, derive(Debug, PartialEq))] struct AA64Reg { aa64isar0: u64, aa64isar1: u64, aa64mmfr2: u64, } #[cold] fn _detect(info: &mut CpuInfo) { let AA64Reg { aa64isar0, aa64isar1, aa64mmfr2 } = imp::aa64reg(); // ID_AA64ISAR0_EL1, AArch64 Instruction Set Attribute Register 0 // https://developer.arm.com/documentation/ddi0601/2024-12/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0 let atomic = extract(aa64isar0, 23, 20); if atomic >= 0b0010 { info.set(CpuInfo::HAS_LSE); if atomic >= 0b0011 { info.set(CpuInfo::HAS_LSE128); } } // ID_AA64ISAR1_EL1, AArch64 Instruction Set Attribute Register 1 // https://developer.arm.com/documentation/ddi0601/2024-12/AArch64-Registers/ID-AA64ISAR1-EL1--AArch64-Instruction-Set-Attribute-Register-1 if extract(aa64isar1, 23, 20) >= 0b0011 { info.set(CpuInfo::HAS_RCPC3); } // ID_AA64MMFR2_EL1, AArch64 Memory Model Feature Register 2 // https://developer.arm.com/documentation/ddi0601/2024-12/AArch64-Registers/ID-AA64MMFR2-EL1--AArch64-Memory-Model-Feature-Register-2 if extract(aa64mmfr2, 35, 32) >= 0b0001 { info.set(CpuInfo::HAS_LSE2); } } fn extract(x: u64, high: usize, low: usize) -> u64 { (x >> low) & ((1 << (high - low + 1)) - 1) } #[cfg(not(any(target_os = "netbsd", target_os = "openbsd")))] mod imp { // This module is test-only. See parent module docs for details. #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use super::AA64Reg; pub(super) fn aa64reg() -> AA64Reg { // SAFETY: This is safe on FreeBSD 12.0+. FreeBSD 11 was EoL on 2021-09-30. // Note that stdarch has been doing the same thing since before FreeBSD 11 was EoL. // https://github.com/rust-lang/stdarch/pull/611 unsafe { let aa64isar0: u64; asm!( "mrs {0}, ID_AA64ISAR0_EL1", out(reg) aa64isar0, options(pure, nomem, nostack, preserves_flags), ); let aa64isar1: u64; asm!( "mrs {0}, ID_AA64ISAR1_EL1", out(reg) aa64isar1, options(pure, nomem, nostack, preserves_flags), ); let aa64mmfr2: u64; asm!( "mrs {0}, ID_AA64MMFR2_EL1", out(reg) aa64mmfr2, options(pure, nomem, nostack, preserves_flags), ); AA64Reg { aa64isar0, aa64isar1, aa64mmfr2 } } } } #[cfg(target_os = "netbsd")] mod imp { // NetBSD doesn't trap the mrs instruction, but exposes the system registers through sysctl. // https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb // https://github.com/golang/sys/commit/ef9fd89ba245e184bdd308f7f2b4f3c551fa5b0f use core::{mem, ptr}; use super::AA64Reg; // libc requires Rust 1.63 #[allow(non_camel_case_types)] pub(super) mod ffi { pub(crate) use crate::utils::ffi::{CStr, c_char, c_int, c_size_t, c_void}; sys_struct!({ // Defined in machine/armreg.h. // https://github.com/NetBSD/src/blob/432a1357026b10c184d8a0ddb683008a23cc7cd9/sys/arch/aarch64/include/armreg.h#L1863 pub(crate) struct aarch64_sysctl_cpu_id { // NetBSD 9.0+ // https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb pub(crate) ac_midr: u64, pub(crate) ac_revidr: u64, pub(crate) ac_mpidr: u64, pub(crate) ac_aa64dfr0: u64, pub(crate) ac_aa64dfr1: u64, pub(crate) ac_aa64isar0: u64, pub(crate) ac_aa64isar1: u64, pub(crate) ac_aa64mmfr0: u64, pub(crate) ac_aa64mmfr1: u64, pub(crate) ac_aa64mmfr2: u64, pub(crate) ac_aa64pfr0: u64, pub(crate) ac_aa64pfr1: u64, pub(crate) ac_aa64zfr0: u64, pub(crate) ac_mvfr0: u32, pub(crate) ac_mvfr1: u32, pub(crate) ac_mvfr2: u32, // NetBSD 10.0+ // https://github.com/NetBSD/src/commit/0c7bdc13f0e332cccec56e307f023b4888638973 pub(crate) ac_pad: u32, pub(crate) ac_clidr: u64, pub(crate) ac_ctr: u64, } }); sys_fn!({ extern "C" { // Defined in sys/sysctl.h. // https://man.netbsd.org/sysctl.3 // https://github.com/NetBSD/src/blob/432a1357026b10c184d8a0ddb683008a23cc7cd9/sys/sys/sysctl.h pub(crate) fn sysctlbyname( name: *const c_char, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> c_int; } }); } pub(super) fn sysctl_cpu_id(name: &ffi::CStr) -> Option { const OUT_LEN: ffi::c_size_t = mem::size_of::() as ffi::c_size_t; // SAFETY: all fields of aarch64_sysctl_cpu_id are zero-able and we use // the result when machdep.cpuN.cpu_id sysctl was successful. let mut buf: ffi::aarch64_sysctl_cpu_id = unsafe { mem::zeroed() }; let mut out_len = OUT_LEN; // SAFETY: // - `name` a valid C string. // - `out_len` does not exceed the size of the value at `buf`. // - `sysctlbyname` is thread-safe. let res = unsafe { ffi::sysctlbyname( name.as_ptr(), (&mut buf as *mut ffi::aarch64_sysctl_cpu_id).cast::(), &mut out_len, ptr::null_mut(), 0, ) }; if res != 0 { return None; } Some(AA64Reg { aa64isar0: buf.ac_aa64isar0, aa64isar1: buf.ac_aa64isar1, aa64mmfr2: buf.ac_aa64mmfr2, }) } pub(super) fn aa64reg() -> AA64Reg { // Get system registers for cpu0. // If failed, returns default because machdep.cpuN.cpu_id sysctl is not available. // machdep.cpuN.cpu_id sysctl was added in NetBSD 9.0 so it is not available on older versions. // It is ok to check only cpu0, even if there are more CPUs. // https://github.com/NetBSD/src/commit/bd9707e06ea7d21b5c24df6dfc14cb37c2819416 // https://github.com/golang/sys/commit/ef9fd89ba245e184bdd308f7f2b4f3c551fa5b0f match sysctl_cpu_id(c!("machdep.cpu0.cpu_id")) { Some(cpu_id) => cpu_id, None => AA64Reg { aa64isar0: 0, aa64isar1: 0, aa64mmfr2: 0 }, } } } #[cfg(target_os = "openbsd")] mod imp { // OpenBSD doesn't trap the mrs instruction, but exposes the system registers through sysctl. // https://github.com/openbsd/src/commit/d335af936b9d7dd9cf655cae1ce19560c45de6c8 // https://github.com/golang/go/commit/cd54ef1f61945459486e9eea2f016d99ef1da925 use core::{mem, ptr}; use super::AA64Reg; // libc requires Rust 1.63 pub(super) mod ffi { pub(crate) use crate::utils::ffi::{c_int, c_size_t, c_uint, c_void}; sys_const!({ // Defined in sys/sysctl.h. // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/sys/sysctl.h#L82 pub(crate) const CTL_MACHDEP: c_int = 7; // Defined in machine/cpu.h. // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/arch/arm64/include/cpu.h#L25-L40 // OpenBSD 7.1+ // https://github.com/openbsd/src/commit/d335af936b9d7dd9cf655cae1ce19560c45de6c8 pub(crate) const CPU_ID_AA64ISAR0: c_int = 2; pub(crate) const CPU_ID_AA64ISAR1: c_int = 3; // OpenBSD 7.3+ // https://github.com/openbsd/src/commit/c7654cd65262d532212f65123ee3905ba200365c // However, on OpenBSD 7.3-7.5, querying CPU_ID_AA64MMFR2 always returns 0. // https://github.com/openbsd/src/commit/e8331b74e5c20302d4bd948c9db722af688ccfc1 pub(crate) const CPU_ID_AA64MMFR2: c_int = 7; }); sys_fn!({ extern "C" { // Defined in sys/sysctl.h. // https://man.openbsd.org/sysctl.2 // https://github.com/openbsd/src/blob/ed8f5e8d82ace15e4cefca2c82941b15cb1a7830/sys/sys/sysctl.h pub(crate) fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *mut c_void, new_len: c_size_t, ) -> c_int; } }); } // sysctl returns an unsupported error if operation is not supported, // so we can safely use this function on older versions of OpenBSD. pub(super) fn aa64reg() -> AA64Reg { let aa64isar0 = sysctl64(&[ffi::CTL_MACHDEP, ffi::CPU_ID_AA64ISAR0]).unwrap_or(0); let aa64isar1 = sysctl64(&[ffi::CTL_MACHDEP, ffi::CPU_ID_AA64ISAR1]).unwrap_or(0); let aa64mmfr2 = sysctl64(&[ffi::CTL_MACHDEP, ffi::CPU_ID_AA64MMFR2]).unwrap_or(0); AA64Reg { aa64isar0, aa64isar1, aa64mmfr2 } } fn sysctl64(mib: &[ffi::c_int]) -> Option { const OUT_LEN: ffi::c_size_t = mem::size_of::() as ffi::c_size_t; let mut out = 0_u64; let mut out_len = OUT_LEN; #[allow(clippy::cast_possible_truncation)] let mib_len = mib.len() as ffi::c_uint; // SAFETY: // - `mib.len()` does not exceed the size of `mib`. // - `out_len` does not exceed the size of `out`. // - `sysctl` is thread-safe. let res = unsafe { ffi::sysctl( mib.as_ptr(), mib_len, (&mut out as *mut u64).cast::(), &mut out_len, ptr::null_mut(), 0, ) }; if res == -1 { return None; } debug_assert_eq!(out_len, OUT_LEN); Some(out) } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use std::{ process::Command, string::{String, ToString as _}, }; use super::*; #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_aa64reg() { let AA64Reg { aa64isar0, aa64isar1, aa64mmfr2 } = imp::aa64reg(); std::eprintln!("aa64isar0={}", aa64isar0); std::eprintln!("aa64isar1={}", aa64isar1); std::eprintln!("aa64mmfr2={}", aa64mmfr2); if cfg!(target_os = "openbsd") { let output = Command::new("sysctl").arg("machdep").output().unwrap(); assert!(output.status.success()); let stdout = String::from_utf8(output.stdout).unwrap(); // OpenBSD 7.1+ assert_eq!( stdout.lines().find_map(|s| s.strip_prefix("machdep.id_aa64isar0=")).unwrap_or("0"), aa64isar0.to_string(), ); assert_eq!( stdout.lines().find_map(|s| s.strip_prefix("machdep.id_aa64isar1=")).unwrap_or("0"), aa64isar1.to_string(), ); // OpenBSD 7.3+ assert_eq!( stdout.lines().find_map(|s| s.strip_prefix("machdep.id_aa64mmfr2=")).unwrap_or("0"), aa64mmfr2.to_string(), ); } let atomic = extract(aa64isar0, 23, 20); if detect().test(CpuInfo::HAS_LSE) { if detect().test(CpuInfo::HAS_LSE128) { assert_eq!(atomic, 0b0011); } else { assert_eq!(atomic, 0b0010); } } else { assert_eq!(atomic, 0b0000); } let lrcpc = extract(aa64isar1, 23, 20); if detect().test(CpuInfo::HAS_RCPC3) { assert_eq!(lrcpc, 0b0011); } else { assert!(lrcpc < 0b0011, "{}", lrcpc); } let at = extract(aa64mmfr2, 35, 32); if detect().test(CpuInfo::HAS_LSE2) { assert_eq!(at, 0b0001); } else { assert_eq!(at, 0b0000); } } #[allow(clippy::cast_possible_wrap)] #[cfg(target_os = "netbsd")] #[test] fn test_alternative() { use crate::utils::ffi::*; use imp::ffi; #[cfg(not(portable_atomic_no_asm))] use std::arch::asm; use std::{mem, ptr, vec, vec::Vec}; use test_helper::sys; // Call syscall using asm instead of libc. // Note that NetBSD does not guarantee the stability of raw syscall as // much as Linux does (It may actually be stable enough, though: https://lists.llvm.org/pipermail/llvm-dev/2019-June/133393.html). // // This is currently used only for testing. fn sysctl_cpu_id_no_libc(name: &[&[u8]]) -> Result { // https://github.com/golang/go/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/src/syscall/asm_netbsd_arm64.s #[inline] unsafe fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> Result { // SAFETY: the caller must uphold the safety contract. unsafe { let mut n = sys::SYS___sysctl as u64; let r: i64; asm!( "svc 0", "b.cc 2f", "mov x17, x0", "mov x0, #-1", "2:", inout("x17") n, inout("x0") ptr_reg!(name) => r, inout("x1") name_len as u64 => _, in("x2") ptr_reg!(old_p), in("x3") ptr_reg!(old_len_p), in("x4") ptr_reg!(new_p), in("x5") new_len as u64, options(nostack), ); #[allow(clippy::cast_possible_truncation)] if r as c_int == -1 { Err(n as c_int) } else { Ok(r as c_int) } } } // https://github.com/golang/sys/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/cpu/cpu_netbsd_arm64.go. fn sysctl_nodes(mib: &mut Vec) -> Result, i32> { mib.push(sys::CTL_QUERY); let mut q_node = sys::sysctlnode { sysctl_flags: sys::SYSCTL_VERS_1, ..unsafe { mem::zeroed() } }; let qp = (&mut q_node as *mut sys::sysctlnode).cast::(); let sz = mem::size_of::(); let mut olen = 0; #[allow(clippy::cast_possible_truncation)] let mib_len = mib.len() as c_uint; unsafe { sysctl(mib.as_ptr(), mib_len, ptr::null_mut(), &mut olen, qp, sz)?; } let mut nodes = Vec::::with_capacity(olen / sz); let np = nodes.as_mut_ptr().cast::(); unsafe { sysctl(mib.as_ptr(), mib_len, np, &mut olen, qp, sz)?; nodes.set_len(olen / sz); } mib.pop(); // pop CTL_QUERY Ok(nodes) } fn name_to_mib(parts: &[&[u8]]) -> Result, i32> { let mut mib = vec![]; for (part_no, &part) in parts.iter().enumerate() { let nodes = sysctl_nodes(&mut mib)?; for node in nodes { let mut n = vec![]; for b in node.sysctl_name { if b != 0 { n.push(b); } } if n == part { mib.push(node.sysctl_num); break; } } if mib.len() != part_no + 1 { return Err(0); } } Ok(mib) } const OUT_LEN: ffi::c_size_t = mem::size_of::() as ffi::c_size_t; let mib = name_to_mib(name)?; let mut buf: ffi::aarch64_sysctl_cpu_id = unsafe { mem::zeroed() }; let mut out_len = OUT_LEN; #[allow(clippy::cast_possible_truncation)] let mib_len = mib.len() as c_uint; unsafe { sysctl( mib.as_ptr(), mib_len, (&mut buf as *mut ffi::aarch64_sysctl_cpu_id).cast::(), &mut out_len, ptr::null_mut(), 0, )?; } Ok(AA64Reg { aa64isar0: buf.ac_aa64isar0, aa64isar1: buf.ac_aa64isar1, aa64mmfr2: buf.ac_aa64mmfr2, }) } assert_eq!( imp::sysctl_cpu_id(c!("machdep.cpu0.cpu_id")).unwrap(), sysctl_cpu_id_no_libc(&[b"machdep", b"cpu0", b"cpu_id"]).unwrap() ); } } portable-atomic/src/imp/detect/aarch64_apple.rs0000644000175000017500000002316415105742312021275 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Run-time CPU feature detection on AArch64 Apple targets by using sysctlbyname. On macOS, this module is currently only enabled on tests because AArch64 macOS always supports FEAT_LSE and FEAT_LSE2 (see build script for more). If macOS supporting FEAT_LSE128/FEAT_LRCPC3 becomes popular in the future, this module will be used to support outline-atomics for FEAT_LSE128/FEAT_LRCPC3. M4 is Armv9.2 and it doesn't support FEAT_LSE128/FEAT_LRCPC3. Refs: https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics TODO: non-macOS targets doesn't always supports FEAT_LSE2, but sysctl on them on the App Store is...? - https://developer.apple.com/forums/thread/9440 - https://nabla-c0d3.github.io/blog/2015/06/16/ios9-security-privacy - https://github.com/rust-lang/stdarch/pull/1636 */ include!("common.rs"); use core::{mem, ptr}; // libc requires Rust 1.63 mod ffi { pub(crate) use crate::utils::ffi::{CStr, c_char, c_int, c_size_t, c_void}; sys_fn!({ extern "C" { // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname // https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/sys/sysctl.h pub(crate) fn sysctlbyname( name: *const c_char, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *mut c_void, new_len: c_size_t, ) -> c_int; } }); } fn sysctlbyname32(name: &ffi::CStr) -> Option { const OUT_LEN: ffi::c_size_t = mem::size_of::() as ffi::c_size_t; let mut out = 0_u32; let mut out_len = OUT_LEN; // SAFETY: // - `name` a valid C string. // - `out_len` does not exceed the size of `out`. // - `sysctlbyname` is thread-safe. let res = unsafe { ffi::sysctlbyname( name.as_ptr(), (&mut out as *mut u32).cast::(), &mut out_len, ptr::null_mut(), 0, ) }; if res != 0 { return None; } debug_assert_eq!(out_len, OUT_LEN); Some(out) } #[cold] fn _detect(info: &mut CpuInfo) { // hw.optional.armv8_1_atomics is available on macOS 11+ (note: AArch64 support was added in macOS 11), // hw.optional.arm.FEAT_* are only available on macOS 12+. // Query both names in case future versions of macOS remove the old name. // https://github.com/golang/go/commit/c15593197453b8bf90fc3a9080ba2afeaf7934ea // https://github.com/google/boringssl/commit/91e0b11eba517d83b910b20fe3740eeb39ecb37e if sysctlbyname32(c!("hw.optional.arm.FEAT_LSE")).unwrap_or(0) != 0 || sysctlbyname32(c!("hw.optional.armv8_1_atomics")).unwrap_or(0) != 0 { info.set(CpuInfo::HAS_LSE); } if sysctlbyname32(c!("hw.optional.arm.FEAT_LSE2")).unwrap_or(0) != 0 { info.set(CpuInfo::HAS_LSE2); } if sysctlbyname32(c!("hw.optional.arm.FEAT_LSE128")).unwrap_or(0) != 0 { info.set(CpuInfo::HAS_LSE128); } if sysctlbyname32(c!("hw.optional.arm.FEAT_LRCPC3")).unwrap_or(0) != 0 { info.set(CpuInfo::HAS_RCPC3); } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; #[test] fn test_macos() { assert_eq!(sysctlbyname32(c!("hw.optional.armv8_1_atomics")), Some(1)); assert_eq!(sysctlbyname32(c!("hw.optional.arm.FEAT_LSE")), Some(1)); assert_eq!(sysctlbyname32(c!("hw.optional.arm.FEAT_LSE2")), Some(1)); assert_eq!(sysctlbyname32(c!("hw.optional.arm.FEAT_LSE128")), None); assert_eq!(std::io::Error::last_os_error().kind(), std::io::ErrorKind::NotFound); assert_eq!(sysctlbyname32(c!("hw.optional.arm.FEAT_LRCPC")), Some(1)); assert_eq!(sysctlbyname32(c!("hw.optional.arm.FEAT_LRCPC2")), Some(1)); assert_eq!(sysctlbyname32(c!("hw.optional.arm.FEAT_LRCPC3")), None); assert_eq!(std::io::Error::last_os_error().kind(), std::io::ErrorKind::NotFound); } #[cfg(target_pointer_width = "64")] #[test] fn test_alternative() { use crate::utils::ffi::*; #[cfg(not(portable_atomic_no_asm))] use std::arch::asm; use std::mem; use test_helper::sys; // Call syscall using asm instead of libc. // Note that macOS does not guarantee the stability of raw syscall. // (And they actually changed it: https://go-review.googlesource.com/c/go/+/25495) // // This is currently used only for testing. fn sysctlbyname32_no_libc(name: &CStr) -> Result { // https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/kern/syscalls.master#L298 #[inline] unsafe fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> Result { // https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/osfmk/mach/i386/syscall_sw.h#L158 #[inline] const fn syscall_construct_unix(n: u64) -> u64 { const SYSCALL_CLASS_UNIX: u64 = 2; const SYSCALL_CLASS_SHIFT: u64 = 24; const SYSCALL_CLASS_MASK: u64 = 0xFF << SYSCALL_CLASS_SHIFT; const SYSCALL_NUMBER_MASK: u64 = !SYSCALL_CLASS_MASK; (SYSCALL_CLASS_UNIX << SYSCALL_CLASS_SHIFT) | (SYSCALL_NUMBER_MASK & n) } #[allow(clippy::cast_possible_truncation)] // SAFETY: the caller must uphold the safety contract. unsafe { // https://github.com/apple-oss-distributions/xnu/blob/8d741a5de7ff4191bf97d57b9f54c2f6d4a15585/bsd/kern/syscalls.master#L4 let mut n = syscall_construct_unix(202); let r: i64; asm!( "svc 0", "b.cc 2f", "mov x16, x0", "mov x0, #-1", "2:", inout("x16") n, inout("x0") ptr_reg!(name) => r, inout("x1") name_len as u64 => _, in("x2") ptr_reg!(old_p), in("x3") ptr_reg!(old_len_p), in("x4") ptr_reg!(new_p), in("x5") new_len as u64, options(nostack), ); if r as c_int == -1 { Err(n as c_int) } else { Ok(r as c_int) } } } // https://github.com/apple-oss-distributions/Libc/blob/af11da5ca9d527ea2f48bb7efbd0f0f2a4ea4812/gen/FreeBSD/sysctlbyname.c unsafe fn sysctlbyname( name: &CStr, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *mut c_void, new_len: c_size_t, ) -> Result { let mut real_oid: [c_int; sys::CTL_MAXNAME as usize + 2] = unsafe { mem::zeroed() }; // Note that this is undocumented API. // Although FreeBSD defined it in sys/sysctl.h since https://github.com/freebsd/freebsd-src/commit/382e01c8dc7f328f46c61c82a29222f432f510f7 let mut name2oid_oid: [c_int; 2] = [0, 3]; let mut oid_len = mem::size_of_val(&real_oid); unsafe { sysctl( name2oid_oid.as_mut_ptr(), 2, real_oid.as_mut_ptr().cast::(), &mut oid_len, name.as_ptr().cast::() as *mut c_void, name.to_bytes_with_nul().len() - 1, )?; } oid_len /= mem::size_of::(); #[allow(clippy::cast_possible_truncation)] unsafe { sysctl(real_oid.as_mut_ptr(), oid_len as u32, old_p, old_len_p, new_p, new_len) } } const OUT_LEN: ffi::c_size_t = mem::size_of::() as ffi::c_size_t; let mut out = 0_u32; let mut out_len = OUT_LEN; // SAFETY: // - `out_len` does not exceed the size of `out`. // - `sysctlbyname` is thread-safe. let res = unsafe { sysctlbyname( name, (&mut out as *mut u32).cast::(), &mut out_len, ptr::null_mut(), 0, )? }; debug_assert_eq!(res, 0); debug_assert_eq!(out_len, OUT_LEN); Ok(out) } for name in [ c!("hw.optional.armv8_1_atomics"), c!("hw.optional.arm.FEAT_LSE"), c!("hw.optional.arm.FEAT_LSE2"), c!("hw.optional.arm.FEAT_LSE128"), c!("hw.optional.arm.FEAT_LRCPC"), c!("hw.optional.arm.FEAT_LRCPC2"), c!("hw.optional.arm.FEAT_LRCPC3"), ] { if let Some(res) = sysctlbyname32(name) { assert_eq!(res, sysctlbyname32_no_libc(name).unwrap()); } else { assert_eq!(sysctlbyname32_no_libc(name).unwrap_err(), libc::ENOENT); } } } } portable-atomic/src/imp/core_atomic.rs0000644000175000017500000004740615105742312017705 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Wrap the standard library's atomic types in newtype. This is not a reexport, because we want to backport changes like https://github.com/rust-lang/rust/pull/98383 to old compilers. */ use core::{cell::UnsafeCell, marker::PhantomData, sync::atomic::Ordering}; // core::panic::RefUnwindSafe is only available on Rust 1.56+, so on pre-1.56 // Rust, we implement RefUnwindSafe when "std" feature is enabled. // However, on pre-1.56 Rust, the standard library's atomic types implement // RefUnwindSafe when "linked to std", and that's behavior that our other atomic // implementations can't emulate, so use PhantomData to match // conditions where our other atomic implementations implement RefUnwindSafe. // // If we do not do this, for example, downstream that is only tested on x86_64 // may incorrectly assume that AtomicU64 always implements RefUnwindSafe even on // older rustc, and may be broken on platforms where std AtomicU64 is not available. struct NotRefUnwindSafe(UnsafeCell<()>); // SAFETY: this is a marker type and we'll never access the value. unsafe impl Sync for NotRefUnwindSafe {} #[repr(transparent)] pub(crate) struct AtomicPtr { inner: core::sync::atomic::AtomicPtr, // Prevent RefUnwindSafe from being propagated from the std atomic type. See NotRefUnwindSafe for more. _not_ref_unwind_safe: PhantomData, } impl AtomicPtr { #[inline] pub(crate) const fn new(v: *mut T) -> Self { Self { inner: core::sync::atomic::AtomicPtr::new(v), _not_ref_unwind_safe: PhantomData } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::IS_ALWAYS_LOCK_FREE } pub(crate) const IS_ALWAYS_LOCK_FREE: bool = true; #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn load(&self, order: Ordering) -> *mut T { crate::utils::assert_load_ordering(order); // for track_caller (compiler can omit double check) self.inner.load(order) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn store(&self, ptr: *mut T, order: Ordering) { crate::utils::assert_store_ordering(order); // for track_caller (compiler can omit double check) self.inner.store(ptr, order); } const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; #[inline] pub(crate) const fn as_ptr(&self) -> *mut *mut T { // SAFETY: Self is #[repr(C)] and internally UnsafeCell<*mut T>. // See also https://github.com/rust-lang/rust/pull/66705 and // https://github.com/rust-lang/rust/issues/66136#issuecomment-557867116. unsafe { (*(self as *const Self as *const UnsafeCell<*mut T>)).get() } } } } #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] impl AtomicPtr { #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { crate::utils::assert_compare_exchange_ordering(success, failure); // for track_caller (compiler can omit double check) #[cfg(portable_atomic_no_stronger_failure_ordering)] let success = crate::utils::upgrade_success_ordering(success, failure); self.inner.compare_exchange(current, new, success, failure) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange_weak( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { crate::utils::assert_compare_exchange_ordering(success, failure); // for track_caller (compiler can omit double check) #[cfg(portable_atomic_no_stronger_failure_ordering)] let success = crate::utils::upgrade_success_ordering(success, failure); self.inner.compare_exchange_weak(current, new, success, failure) } } impl core::ops::Deref for AtomicPtr { type Target = core::sync::atomic::AtomicPtr; #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn deref(&self) -> &Self::Target { &self.inner } } macro_rules! atomic_int { ($atomic_type:ident, $int_type:ident) => { #[repr(transparent)] pub(crate) struct $atomic_type { inner: core::sync::atomic::$atomic_type, // Prevent RefUnwindSafe from being propagated from the std atomic type. See NotRefUnwindSafe for more. _not_ref_unwind_safe: PhantomData, } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)) )] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] impl_default_no_fetch_ops!($atomic_type, $int_type); #[cfg(not(all( any(target_arch = "x86", target_arch = "x86_64"), not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), )))] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)) )] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { inner: core::sync::atomic::$atomic_type::new(v), _not_ref_unwind_safe: PhantomData, } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::IS_ALWAYS_LOCK_FREE } // ESP-IDF targets' 64-bit atomics are not lock-free. // https://github.com/rust-lang/rust/pull/115577#issuecomment-1732259297 pub(crate) const IS_ALWAYS_LOCK_FREE: bool = cfg!(not(all( any(target_arch = "riscv32", target_arch = "xtensa"), target_os = "espidf", ))) | (core::mem::size_of::<$int_type>() < 8); #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); // for track_caller (compiler can omit double check) self.inner.load(order) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); // for track_caller (compiler can omit double check) self.inner.store(val, order); } const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { // SAFETY: Self is #[repr(C)] and internally UnsafeCell<$int_type>. // See also https://github.com/rust-lang/rust/pull/66705 and // https://github.com/rust-lang/rust/issues/66136#issuecomment-557867116. unsafe { (*(self as *const Self as *const UnsafeCell<$int_type>)).get() } } } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)) )] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] impl $atomic_type { #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // for track_caller (compiler can omit double check) #[cfg(portable_atomic_no_stronger_failure_ordering)] let success = crate::utils::upgrade_success_ordering(success, failure); self.inner.compare_exchange(current, new, success, failure) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // for track_caller (compiler can omit double check) #[cfg(portable_atomic_no_stronger_failure_ordering)] let success = crate::utils::upgrade_success_ordering(success, failure); self.inner.compare_exchange_weak(current, new, success, failure) } #[allow(dead_code)] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn fetch_update_(&self, order: Ordering, mut f: F) -> $int_type where F: FnMut($int_type) -> $int_type, { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = self.load(Ordering::Relaxed); loop { let next = f(prev); match self.compare_exchange_weak(prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(next_prev) => prev = next_prev, } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { #[cfg(not(portable_atomic_no_atomic_min_max))] { #[cfg(any( all( any(target_arch = "aarch64", target_arch = "arm64ec"), any(target_feature = "lse", portable_atomic_target_feature = "lse"), ), all( target_arch = "arm", not(any( target_feature = "v6", portable_atomic_target_feature = "v6", )), ), target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc", target_arch = "powerpc64", ))] { // HACK: the following operations are currently broken (at least on qemu-user): // - aarch64's `AtomicI{8,16}::fetch_{max,min}` (release mode + lse) // - armv5te's `Atomic{I,U}{8,16}::fetch_{max,min}` // - mips's `AtomicI8::fetch_{max,min}` (release mode) // - mipsel's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - mips64's `AtomicI8::fetch_{max,min}` (release mode) // - mips64el's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - powerpc's `AtomicI{8,16}::fetch_{max,min}` // - powerpc64's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - powerpc64le's `AtomicU{8,16}::fetch_{max,min}` (release mode + fat LTO) // See also: // https://github.com/llvm/llvm-project/issues/61880 // https://github.com/llvm/llvm-project/issues/61881 // https://github.com/llvm/llvm-project/issues/61882 // https://github.com/taiki-e/portable-atomic/issues/2 // https://github.com/rust-lang/rust/issues/100650 if core::mem::size_of::<$int_type>() <= 2 { return self.fetch_update_(order, |x| core::cmp::max(x, val)); } } self.inner.fetch_max(val, order) } #[cfg(portable_atomic_no_atomic_min_max)] { self.fetch_update_(order, |x| core::cmp::max(x, val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { #[cfg(not(portable_atomic_no_atomic_min_max))] { #[cfg(any( all( any(target_arch = "aarch64", target_arch = "arm64ec"), any(target_feature = "lse", portable_atomic_target_feature = "lse"), ), all( target_arch = "arm", not(any( target_feature = "v6", portable_atomic_target_feature = "v6", )), ), target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc", target_arch = "powerpc64", ))] { // HACK: the following operations are currently broken (at least on qemu-user): // - aarch64's `AtomicI{8,16}::fetch_{max,min}` (release mode + lse) // - armv5te's `Atomic{I,U}{8,16}::fetch_{max,min}` // - mips's `AtomicI8::fetch_{max,min}` (release mode) // - mipsel's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - mips64's `AtomicI8::fetch_{max,min}` (release mode) // - mips64el's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - powerpc's `AtomicI{8,16}::fetch_{max,min}` // - powerpc64's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - powerpc64le's `AtomicU{8,16}::fetch_{max,min}` (release mode + fat LTO) // See also: // https://github.com/llvm/llvm-project/issues/61880 // https://github.com/llvm/llvm-project/issues/61881 // https://github.com/llvm/llvm-project/issues/61882 // https://github.com/taiki-e/portable-atomic/issues/2 // https://github.com/rust-lang/rust/issues/100650 if core::mem::size_of::<$int_type>() <= 2 { return self.fetch_update_(order, |x| core::cmp::min(x, val)); } } self.inner.fetch_min(val, order) } #[cfg(portable_atomic_no_atomic_min_max)] { self.fetch_update_(order, |x| core::cmp::min(x, val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { self.fetch_xor(!0, order) } #[cfg(not(all( any(target_arch = "x86", target_arch = "x86_64"), not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), )))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } // TODO: provide asm-based implementation on AArch64 without FEAT_LSE, Armv7, RISC-V, etc. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_neg(&self, order: Ordering) -> $int_type { self.fetch_update_(order, $int_type::wrapping_neg) } #[cfg(not(all( any(target_arch = "x86", target_arch = "x86_64"), not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), )))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } impl core::ops::Deref for $atomic_type { type Target = core::sync::atomic::$atomic_type; #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn deref(&self) -> &Self::Target { &self.inner } } }; } atomic_int!(AtomicIsize, isize); atomic_int!(AtomicUsize, usize); #[cfg(not(portable_atomic_no_atomic_load_store))] atomic_int!(AtomicI8, i8); #[cfg(not(portable_atomic_no_atomic_load_store))] atomic_int!(AtomicU8, u8); #[cfg(not(portable_atomic_no_atomic_load_store))] atomic_int!(AtomicI16, i16); #[cfg(not(portable_atomic_no_atomic_load_store))] atomic_int!(AtomicU16, u16); #[cfg(not(portable_atomic_no_atomic_load_store))] #[cfg(not(target_pointer_width = "16"))] atomic_int!(AtomicI32, i32); #[cfg(not(portable_atomic_no_atomic_load_store))] #[cfg(not(target_pointer_width = "16"))] atomic_int!(AtomicU32, u32); #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_64)))] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] atomic_int!(AtomicI64, i64); #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_64)))] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] atomic_int!(AtomicU64, u64); portable-atomic/src/imp/atomic128/0000775000175000017500000000000015105742312016551 5ustar bdrungbdrungportable-atomic/src/imp/atomic128/mod.rs0000644000175000017500000000701515105742312017677 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 128-bit atomic implementations on 64-bit architectures See README.md for details. */ // AArch64 #[cfg(any( all(target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm)), all(target_arch = "arm64ec", not(portable_atomic_no_asm)) ))] // Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly. #[cfg_attr( all(any(miri, portable_atomic_sanitize_thread), portable_atomic_new_atomic_intrinsics), path = "intrinsics.rs" )] pub(super) mod aarch64; // powerpc64 #[cfg(all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( all( target_env = "gnu", any(target_endian = "little", not(target_feature = "crt-static")), ), all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "openbsd", all( target_os = "aix", not(portable_atomic_pre_llvm_20), any(test, portable_atomic_outline_atomics), // TODO(aix): currently disabled by default ), ), not(any(miri, portable_atomic_sanitize_thread)), ), ), ))] // Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly. #[cfg_attr( all(any(miri, portable_atomic_sanitize_thread), not(portable_atomic_pre_llvm_15)), path = "intrinsics.rs" )] pub(super) mod powerpc64; // riscv64 #[cfg(all( target_arch = "riscv64", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "zacas", portable_atomic_target_feature = "zacas", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(target_os = "linux", target_os = "android"), ), ), ))] pub(super) mod riscv64; // s390x #[cfg(all(target_arch = "s390x", not(portable_atomic_no_asm)))] // Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly. #[cfg_attr(any(miri, portable_atomic_sanitize_thread), path = "intrinsics.rs")] pub(super) mod s390x; // x86_64 #[cfg(all( target_arch = "x86_64", not(all(any(miri, portable_atomic_sanitize_thread), portable_atomic_no_cmpxchg16b_intrinsic)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", all( feature = "fallback", not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), ), ))] // Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly. #[cfg_attr(any(miri, portable_atomic_sanitize_thread), path = "intrinsics.rs")] pub(super) mod x86_64; portable-atomic/src/imp/atomic128/riscv64.rs0000644000175000017500000005734115105742312020427 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 128-bit atomic implementation on riscv64. This architecture provides the following 128-bit atomic instructions: - amocas.q: CAS (Zacas extension) See "Atomic operation overview by architecture" in atomic-maybe-uninit for a more comprehensive and detailed description of the atomic and synchronize instructions in this architecture: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/README.md#risc-v Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use this module and use fallback implementation instead. Refs: - RISC-V Instruction Set Manual "Zacas" Extension for Atomic Compare-and-Swap (CAS) Instructions https://github.com/riscv/riscv-isa-manual/blob/riscv-isa-release-8b9dc50-2024-08-30/src/zacas.adoc - RISC-V Atomics ABI Specification https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-atomic.adoc Generated asm: - riscv64gc (+zacas) https://godbolt.org/z/c59a9fs63 */ include!("macros.rs"); #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] #[path = "../fallback/outline_atomics.rs"] mod fallback; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))))] #[cfg(any(target_os = "linux", target_os = "android"))] #[path = "../detect/riscv_linux.rs"] mod detect; #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::sync::atomic::Ordering; use crate::utils::{Pair, U128}; macro_rules! debug_assert_zacas { () => { #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] { debug_assert!(detect::detect().has_zacas()); } }; } // `.option arch, +zacas` directive requires LLVM 20, so we use .4byte directive for old LLVM. // Note that `.insn ` directive requires LLVM 19. // https://github.com/llvm/llvm-project/commit/2a086dce691e3cc34a2fc27f4fb255bb2cbbfac9 // https://github.com/riscv-non-isa/riscv-asm-manual/blob/ad0de8c004e29c9a7ac33cfd054f4d4f9392f2fb/src/asm-manual.adoc#arch #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! start_zacas { () => { ".option push\n.option arch, +zacas" }; } #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! end_zacas { () => { ".option pop" }; } #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! atomic_rmw_amocas_order { ($op:ident, $order:ident) => { atomic_rmw_amocas_order!($op, $order, failure = $order) }; ($op:ident, $order:ident, failure = $failure:ident) => { match $order { Ordering::Relaxed => $op!("", ""), Ordering::Acquire => $op!("", ".aq"), Ordering::Release => $op!("", ".rl"), Ordering::AcqRel => $op!("", ".aqrl"), Ordering::SeqCst if $failure == Ordering::SeqCst => $op!("fence rw,rw", ".aqrl"), Ordering::SeqCst => $op!("", ".aqrl"), _ => unreachable!(), } }; } #[cfg(portable_atomic_pre_llvm_20)] macro_rules! atomic_rmw_amocas_order_insn { ($op:ident, $order:ident) => { atomic_rmw_amocas_order_insn!($op, $order, failure = $order) }; ($op:ident, $order:ident, failure = $failure:ident) => { match $order { Ordering::Relaxed => $op!("", "8"), Ordering::Acquire => $op!("", "c"), Ordering::Release => $op!("", "a"), Ordering::AcqRel => $op!("", "e"), Ordering::SeqCst if $failure == Ordering::SeqCst => $op!("fence rw,rw", "e"), Ordering::SeqCst => $op!("", "e"), _ => unreachable!(), } }; } // If zacas is available at compile-time, we can always use zacas_fn. #[cfg(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))] use self::atomic_load_zacas as atomic_load; // Otherwise, we need to do run-time detection and can use zacas_fn only if zacas is available. #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] #[inline] unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(src: *mut u128) -> u128; atomic_load_zacas_relaxed = atomic_load_zacas(Ordering::Relaxed); atomic_load_zacas_acquire = atomic_load_zacas(Ordering::Acquire); atomic_load_zacas_seqcst = atomic_load_zacas(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls atomic_load_zacas if zacas is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_zacas() { atomic_load_zacas_relaxed } else { fallback::atomic_load_non_seqcst } }) } Ordering::Acquire => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_zacas() { atomic_load_zacas_acquire } else { fallback::atomic_load_non_seqcst } }) } Ordering::SeqCst => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_zacas() { atomic_load_zacas_seqcst } else { fallback::atomic_load_seqcst } }) } _ => unreachable!(), } } } #[inline] unsafe fn atomic_load_zacas(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_zacas!(); let (out_lo, out_hi); // SAFETY: the caller must uphold the safety contract. unsafe { #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! load { ($fence:tt, $asm_order:tt) => { asm!( start_zacas!(), $fence, // fence concat!("amocas.q", $asm_order, " a2, a2, 0({src})"), // atomic { if *dst == a2:a3 { *dst = a2:a3 } else { a2:a3 = *dst } } end_zacas!(), src = in(reg) ptr_reg!(src), inout("a2") 0_u64 => out_lo, inout("a3") 0_u64 => out_hi, options(nostack, preserves_flags), ) }; } #[cfg(not(portable_atomic_pre_llvm_20))] atomic_rmw_amocas_order!(load, order); #[cfg(portable_atomic_pre_llvm_20)] macro_rules! load { ($fence:tt, $insn_order:tt) => { asm!( $fence, // fence // amocas.q{,.aq,.rl,.aqrl} a2, a2, (a0) // atomic { if *a0 == a2:a3 { *a0 = a2:a3 } else { a2:a3 = *a0 } } concat!(".4byte 0x2", $insn_order, "c5462f"), in("a0") ptr_reg!(src), inout("a2") 0_u64 => out_lo, inout("a3") 0_u64 => out_hi, options(nostack, preserves_flags), ) }; } #[cfg(portable_atomic_pre_llvm_20)] atomic_rmw_amocas_order_insn!(load, order); U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_swap(dst, val, order); } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { #[cfg(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))] // SAFETY: the caller must uphold the safety contract. // cfg guarantees that zacas instructions are available at compile-time. let (prev, ok) = unsafe { atomic_compare_exchange_zacas(dst, old, new, success, failure) }; #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] let (prev, ok) = { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool); zacas_relaxed_fn = atomic_compare_exchange_zacas(Ordering::Relaxed, Ordering::Relaxed); zacas_acquire_fn = atomic_compare_exchange_zacas(Ordering::Acquire, Ordering::Acquire); zacas_release_fn = atomic_compare_exchange_zacas(Ordering::Release, Ordering::Relaxed); zacas_acqrel_fn = atomic_compare_exchange_zacas(Ordering::AcqRel, Ordering::Acquire); zacas_seqcst_fn = atomic_compare_exchange_zacas(Ordering::SeqCst, Ordering::SeqCst); } let order = crate::utils::upgrade_success_ordering(success, failure); // SAFETY: the caller must uphold the safety contract. // we only calls atomic_compare_exchange_zacas if zacas is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_zacas() { zacas_relaxed_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::Acquire => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_zacas() { zacas_acquire_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_zacas() { zacas_release_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::AcqRel => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_zacas() { zacas_acqrel_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_zacas() { zacas_seqcst_fn } else { fallback::atomic_compare_exchange_seqcst } }) } _ => unreachable!(), } } }; if ok { Ok(prev) } else { Err(prev) } } #[inline] unsafe fn atomic_compare_exchange_zacas( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); debug_assert_zacas!(); let order = crate::utils::upgrade_success_ordering(success, failure); let old = U128 { whole: old }; let new = U128 { whole: new }; let (prev_lo, prev_hi); // SAFETY: the caller must uphold the safety contract. unsafe { #[cfg(not(portable_atomic_pre_llvm_20))] macro_rules! cmpxchg { ($fence:tt, $asm_order:tt) => { asm!( start_zacas!(), $fence, // fence concat!("amocas.q", $asm_order, " a4, a2, 0({dst})"), // atomic { if *dst == a4:a5 { *dst = a2:a3 } else { a4:a5 = *dst } } end_zacas!(), dst = in(reg) ptr_reg!(dst), // must be allocated to even/odd register pair inout("a4") old.pair.lo => prev_lo, inout("a5") old.pair.hi => prev_hi, // must be allocated to even/odd register pair in("a2") new.pair.lo, in("a3") new.pair.hi, options(nostack, preserves_flags), ) }; } #[cfg(not(portable_atomic_pre_llvm_20))] atomic_rmw_amocas_order!(cmpxchg, order, failure = failure); #[cfg(portable_atomic_pre_llvm_20)] macro_rules! cmpxchg { ($fence:tt, $insn_order:tt) => { asm!( $fence, // fence // amocas.q{,.aq,.rl,.aqrl} a4, a2, (a0) // atomic { if *a0 == a4:a5 { *a0 = a2:a3 } else { a4:a5 = *a0 } } concat!(".4byte 0x2", $insn_order, "c5472f"), in("a0") ptr_reg!(dst), // must be allocated to even/odd register pair inout("a4") old.pair.lo => prev_lo, inout("a5") old.pair.hi => prev_hi, // must be allocated to even/odd register pair in("a2") new.pair.lo, in("a3") new.pair.hi, options(nostack, preserves_flags), ) }; } #[cfg(portable_atomic_pre_llvm_20)] atomic_rmw_amocas_order_insn!(cmpxchg, order, failure = failure); let prev = U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole; (prev, prev == old.whole) } } // amocas is always strong. use self::atomic_compare_exchange as atomic_compare_exchange_weak; // 128-bit atomic load by two 64-bit atomic loads. #[inline] unsafe fn byte_wise_atomic_load(src: *const u128) -> u128 { let (out_lo, out_hi); // SAFETY: the caller must uphold the safety contract. unsafe { asm!( "ld {out_lo}, ({src})", // atomic { out_lo = *src } "ld {out_hi}, 8({src})", // atomic { out_hi = *src.add(8) } src = in(reg) ptr_reg!(src), out_lo = out(reg) out_lo, out_hi = out(reg) out_hi, options(pure, nostack, preserves_flags, readonly), ); U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } macro_rules! select_atomic_rmw { ( unsafe fn $name:ident(dst: *mut u128 $(, $($arg:tt)*)?) $(-> $ret_ty:ty)? { |$zacas_fn_binding:ident| $($zacas_fn_body:tt)* } zacas = $zacas_fn:ident; non_seqcst_fallback = $non_seqcst_fallback_fn:ident; seqcst_fallback = $seqcst_fallback_fn:ident; ) => { #[inline] unsafe fn $zacas_fn(dst: *mut u128 $(, $($arg)*)?, order: Ordering) $(-> $ret_ty)? { // SAFETY: the caller must uphold the safety contract. unsafe { // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement byte_wise_atomic_load. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). let mut prev = byte_wise_atomic_load(dst); loop { let next = { let $zacas_fn_binding = prev; $($zacas_fn_body)* }; match atomic_compare_exchange_weak(dst, prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(x) => prev = x, } } } } // If zacas is available at compile-time, we can always use zacas_fn. #[cfg(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))] use self::$zacas_fn as $name; // Otherwise, we need to do run-time detection and can use zacas_fn only if zacas is available. #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] #[inline] unsafe fn $name(dst: *mut u128 $(, $($arg)*)?, order: Ordering) $(-> $ret_ty)? { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128 $(, $($arg)*)?) $(-> $ret_ty)?; zacas_relaxed_fn = $zacas_fn(Ordering::Relaxed); zacas_acquire_fn = $zacas_fn(Ordering::Acquire); zacas_release_fn = $zacas_fn(Ordering::Release); zacas_acqrel_fn = $zacas_fn(Ordering::AcqRel); zacas_seqcst_fn = $zacas_fn(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls zacas_fn if zacas is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_relaxed_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::Acquire => { ifunc!(unsafe fn(dst: *mut u128 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_acquire_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_release_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::AcqRel => { ifunc!(unsafe fn(dst: *mut u128 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_acqrel_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128 $(, $($arg)*)?) $(-> $ret_ty)? { if detect::detect().has_zacas() { zacas_seqcst_fn } else { fallback::$seqcst_fallback_fn } }) } _ => unreachable!(), } } } }; } select_atomic_rmw! { unsafe fn atomic_swap(dst: *mut u128, val: u128) -> u128 { |_x| val } zacas = atomic_swap_zacas; non_seqcst_fallback = atomic_swap_non_seqcst; seqcst_fallback = atomic_swap_seqcst; } select_atomic_rmw! { unsafe fn atomic_add(dst: *mut u128, val: u128) -> u128 { |x| x.wrapping_add(val) } zacas = atomic_add_zacas; non_seqcst_fallback = atomic_add_non_seqcst; seqcst_fallback = atomic_add_seqcst; } select_atomic_rmw! { unsafe fn atomic_sub(dst: *mut u128, val: u128) -> u128 { |x| x.wrapping_sub(val) } zacas = atomic_sub_zacas; non_seqcst_fallback = atomic_sub_non_seqcst; seqcst_fallback = atomic_sub_seqcst; } select_atomic_rmw! { unsafe fn atomic_and(dst: *mut u128, val: u128) -> u128 { |x| x & val } zacas = atomic_and_zacas; non_seqcst_fallback = atomic_and_non_seqcst; seqcst_fallback = atomic_and_seqcst; } select_atomic_rmw! { unsafe fn atomic_nand(dst: *mut u128, val: u128) -> u128 { |x| !(x & val) } zacas = atomic_nand_zacas; non_seqcst_fallback = atomic_nand_non_seqcst; seqcst_fallback = atomic_nand_seqcst; } select_atomic_rmw! { unsafe fn atomic_or(dst: *mut u128, val: u128) -> u128 { |x| x | val } zacas = atomic_or_zacas; non_seqcst_fallback = atomic_or_non_seqcst; seqcst_fallback = atomic_or_seqcst; } select_atomic_rmw! { unsafe fn atomic_xor(dst: *mut u128, val: u128) -> u128 { |x| x ^ val } zacas = atomic_xor_zacas; non_seqcst_fallback = atomic_xor_non_seqcst; seqcst_fallback = atomic_xor_seqcst; } select_atomic_rmw! { unsafe fn atomic_max(dst: *mut u128, val: u128) -> u128 { |x| { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] { core::cmp::max(x as i128, val as i128) as u128 } } } zacas = atomic_max_zacas; non_seqcst_fallback = atomic_max_non_seqcst; seqcst_fallback = atomic_max_seqcst; } select_atomic_rmw! { unsafe fn atomic_umax(dst: *mut u128, val: u128) -> u128 { |x| core::cmp::max(x, val) } zacas = atomic_umax_zacas; non_seqcst_fallback = atomic_umax_non_seqcst; seqcst_fallback = atomic_umax_seqcst; } select_atomic_rmw! { unsafe fn atomic_min(dst: *mut u128, val: u128) -> u128 { |x| { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] { core::cmp::min(x as i128, val as i128) as u128 } } } zacas = atomic_min_zacas; non_seqcst_fallback = atomic_min_non_seqcst; seqcst_fallback = atomic_min_seqcst; } select_atomic_rmw! { unsafe fn atomic_umin(dst: *mut u128, val: u128) -> u128 { |x| core::cmp::min(x, val) } zacas = atomic_umin_zacas; non_seqcst_fallback = atomic_umin_non_seqcst; seqcst_fallback = atomic_umin_seqcst; } select_atomic_rmw! { unsafe fn atomic_not(dst: *mut u128) -> u128 { |x| !x } zacas = atomic_not_zacas; non_seqcst_fallback = atomic_not_non_seqcst; seqcst_fallback = atomic_not_seqcst; } select_atomic_rmw! { unsafe fn atomic_neg(dst: *mut u128) -> u128 { |x| x.wrapping_neg() } zacas = atomic_neg_zacas; non_seqcst_fallback = atomic_neg_non_seqcst; seqcst_fallback = atomic_neg_seqcst; } #[inline] fn is_lock_free() -> bool { #[cfg(any(target_feature = "zacas", portable_atomic_target_feature = "zacas"))] { // zacas is available at compile-time. true } #[cfg(not(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")))] { detect::detect().has_zacas() } } const IS_ALWAYS_LOCK_FREE: bool = cfg!(any(target_feature = "zacas", portable_atomic_target_feature = "zacas")); atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[allow(clippy::undocumented_unsafe_blocks, clippy::wildcard_imports)] #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/s390x.rs0000644000175000017500000005123215105742312020006 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 128-bit atomic implementation on s390x. This architecture provides the following 128-bit atomic instructions: - LPQ/STPQ: load/store (arch1 or later, i.e., baseline) - CDSG: CAS (arch1 or later, i.e., baseline) See "Atomic operation overview by architecture" in atomic-maybe-uninit for a more comprehensive and detailed description of the atomic and synchronize instructions in this architecture: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/README.md#s390x LLVM's minimal supported architecture level is arch8 (z10): https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0-rc1/llvm/lib/Target/SystemZ/SystemZProcessors.td#L16-L17 This does not appear to have changed since the current s390x backend was added in LLVM 3.3: https://github.com/llvm/llvm-project/commit/5f613dfd1f7edb0ae95d521b7107b582d9df5103#diff-cbaef692b3958312e80fd5507a7e2aff071f1acb086f10e8a96bc06a7bb289db Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use this module and use intrinsics.rs instead. Refs: - z/Architecture Principles of Operation, Fourteenth Edition (SA22-7832-13) https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit Generated asm: - s390x https://godbolt.org/z/oPxYYEvPG - s390x (z196) https://godbolt.org/z/M69KrKT7Y - s390x (z15,-vector) https://godbolt.org/z/Wec8b3ada - s390x (z15) https://godbolt.org/z/KxWcrbfYh */ include!("macros.rs"); use core::{arch::asm, sync::atomic::Ordering}; use crate::utils::{Pair, U128}; // bcr 14,0 requires fast-BCR-serialization facility added in arch9 (z196). #[cfg(any( target_feature = "fast-serialization", portable_atomic_target_feature = "fast-serialization", ))] macro_rules! serialization { () => { "bcr 14, 0" }; } #[cfg(not(any( target_feature = "fast-serialization", portable_atomic_target_feature = "fast-serialization", )))] macro_rules! serialization { () => { "bcr 15, 0" }; } // Use distinct operands on z196 or later, otherwise split to lgr and $op. #[cfg(any(target_feature = "distinct-ops", portable_atomic_target_feature = "distinct-ops"))] macro_rules! distinct_op { ($op:tt, $a0:tt, $a1:tt, $a2:tt) => { concat!($op, "k ", $a0, ", ", $a1, ", ", $a2) }; } #[cfg(not(any(target_feature = "distinct-ops", portable_atomic_target_feature = "distinct-ops")))] macro_rules! distinct_op { ($op:tt, $a0:tt, $a1:tt, $a2:tt) => { concat!("lgr ", $a0, ", ", $a1, "\n", $op, " ", $a0, ", ", $a2) }; } // Use selgr$cond on z15 or later, otherwise split to locgr$cond and $op. #[cfg(any( target_feature = "miscellaneous-extensions-3", portable_atomic_target_feature = "miscellaneous-extensions-3", ))] #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] macro_rules! select_op { ($cond:tt, $a0:tt, $a1:tt, $a2:tt) => { concat!("selgr", $cond, " ", $a0, ", ", $a1, ", ", $a2) }; } #[cfg(not(any( target_feature = "miscellaneous-extensions-3", portable_atomic_target_feature = "miscellaneous-extensions-3", )))] #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] macro_rules! select_op { ($cond:tt, $a0:tt, $a1:tt, $a2:tt) => { concat!("lgr ", $a0, ", ", $a2, "\n", "locgr", $cond, " ", $a0, ", ", $a1) }; } // Extracts and checks condition code. #[inline] fn extract_cc(r: i64) -> bool { r.wrapping_add(-268435456) & (1 << 31) != 0 } #[inline] unsafe fn atomic_load(src: *mut u128, _order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); let (out_hi, out_lo); // SAFETY: the caller must uphold the safety contract. unsafe { // atomic load is always SeqCst. asm!( "lpq %r0, 0({src})", // atomic { r0:r1 = *src } src = in(reg) ptr_reg!(src), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. out("r0") out_hi, out("r1") out_lo, options(nostack, preserves_flags), ); U128 { pair: Pair { hi: out_hi, lo: out_lo } }.whole } } #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); let val = U128 { whole: val }; // SAFETY: the caller must uphold the safety contract. unsafe { macro_rules! atomic_store { ($acquire:expr) => { asm!( "stpq %r0, 0({dst})", // atomic { *dst = r0:r1 } $acquire, // fence dst = in(reg) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. in("r0") val.pair.hi, in("r1") val.pair.lo, options(nostack, preserves_flags), ) }; } match order { // Relaxed and Release stores are equivalent. Ordering::Relaxed | Ordering::Release => atomic_store!(""), Ordering::SeqCst => atomic_store!(serialization!()), _ => unreachable!(), } } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, _success: Ordering, _failure: Ordering, ) -> Result { debug_assert!(dst as usize % 16 == 0); let old = U128 { whole: old }; let new = U128 { whole: new }; let (prev_hi, prev_lo); let r; // SAFETY: the caller must uphold the safety contract. let prev = unsafe { // atomic CAS is always SeqCst. asm!( "cdsg %r0, %r12, 0({dst})", // atomic { if *dst == r0:r1 { cc = 0; *dst = r12:13 } else { cc = 1; r0:r1 = *dst } } "ipm {r}", // r[:] = cc dst = in(reg) ptr_reg!(dst), r = lateout(reg) r, // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. inout("r0") old.pair.hi => prev_hi, inout("r1") old.pair.lo => prev_lo, in("r12") new.pair.hi, in("r13") new.pair.lo, // Do not use `preserves_flags` because CDSG modifies the condition code. options(nostack), ); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole }; if extract_cc(r) { Ok(prev) } else { Err(prev) } } // cdsg is always strong. use self::atomic_compare_exchange as atomic_compare_exchange_weak; // 128-bit atomic load by two 64-bit atomic loads. #[cfg(not(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", )))] #[inline] unsafe fn byte_wise_atomic_load(src: *const u128) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { let (out_hi, out_lo); asm!( "lg {out_hi}, 8({src})", // atomic { out_hi = *src.add(8) } "lg {out_lo}, 0({src})", // atomic { out_lo = *src } src = in(reg) src, out_hi = out(reg) out_hi, out_lo = out(reg) out_lo, options(pure, nostack, preserves_flags, readonly), ); U128 { pair: Pair { hi: out_hi, lo: out_lo } }.whole } } #[cfg(not(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", )))] #[inline(always)] unsafe fn atomic_update(dst: *mut u128, order: Ordering, mut f: F) -> u128 where F: FnMut(u128) -> u128, { // SAFETY: the caller must uphold the safety contract. unsafe { // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement byte_wise_atomic_load. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). let mut prev = byte_wise_atomic_load(dst); loop { let next = f(prev); match atomic_compare_exchange_weak(dst, prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(x) => prev = x, } } } } #[inline] unsafe fn atomic_swap(dst: *mut u128, val: u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); let val = U128 { whole: val }; let (mut prev_hi, mut prev_lo); // SAFETY: the caller must uphold the safety contract. // // We could use atomic_update here, but using an inline assembly allows omitting // the comparison of results and the storing/comparing of condition flags. // // Do not use atomic_rmw_cas_3 because it needs extra LGR to implement swap. unsafe { // atomic swap is always SeqCst. asm!( "lg %r0, 8({dst})", // atomic { r0 = *dst.add(8) } "lg %r1, 0({dst})", // atomic { r1 = *dst } "2:", // 'retry: "cdsg %r0, %r12, 0({dst})", // atomic { if *dst == r0:r1 { cc = 0; *dst = r12:r13 } else { cc = 1; r0:r1 = *dst } } "jl 2b", // if cc == 1 { jump 'retry } dst = in(reg) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. out("r0") prev_hi, out("r1") prev_lo, in("r12") val.pair.hi, in("r13") val.pair.lo, // Do not use `preserves_flags` because CDSG modifies the condition code. options(nostack), ); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } /// Atomic RMW by CAS loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - val_hi/val_lo pair: val argument (read-only for `$op`) /// - r0/r1 pair: previous value loaded (read-only for `$op`) /// - r12/r13 pair: new value that will be stored // We could use atomic_update here, but using an inline assembly allows omitting // the comparison of results and the storing/comparing of condition flags. macro_rules! atomic_rmw_cas_3 { ($name:ident, [$($reg:tt)*], $($op:tt)*) => { #[inline] unsafe fn $name(dst: *mut u128, val: u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); let val = U128 { whole: val }; let (mut prev_hi, mut prev_lo); // SAFETY: the caller must uphold the safety contract. unsafe { // atomic RMW is always SeqCst. asm!( "lg %r0, 8({dst})", // atomic { r0 = *dst.add(8) } "lg %r1, 0({dst})", // atomic { r1 = *dst } "2:", // 'retry: $($op)* "cdsg %r0, %r12, 0({dst})", // atomic { if *dst == r0:r1 { cc = 0; *dst = r12:r13 } else { cc = 1; r0:r1 = *dst } } "jl 2b", // if cc == 1 { jump 'retry } dst = in(reg) ptr_reg!(dst), val_hi = in(reg) val.pair.hi, val_lo = in(reg) val.pair.lo, $($reg)* // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. out("r0") prev_hi, out("r1") prev_lo, out("r12") _, out("r13") _, // Do not use `preserves_flags` because CDSG modifies the condition code. options(nostack), ); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } }; } /// Atomic RMW by CAS loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - r0/r1 pair: previous value loaded (read-only for `$op`) /// - r12/r13 pair: new value that will be stored // We could use atomic_update here, but using an inline assembly allows omitting // the comparison of results and the storing/comparing of condition flags. macro_rules! atomic_rmw_cas_2 { ($name:ident, [$($reg:tt)*], $($op:tt)*) => { #[inline] unsafe fn $name(dst: *mut u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); let (mut prev_hi, mut prev_lo); // SAFETY: the caller must uphold the safety contract. unsafe { // atomic RMW is always SeqCst. asm!( "lg %r0, 8({dst})", // atomic { r0 = *dst.add(8) } "lg %r1, 0({dst})", // atomic { r1 = *dst } "2:", // 'retry: $($op)* "cdsg %r0, %r12, 0({dst})", // atomic { if *dst == r0:r1 { cc = 0; *dst = r12:r13 } else { cc = 1; r0:r1 = *dst } } "jl 2b", // if cc == 1 { jump 'retry } dst = in(reg) ptr_reg!(dst), $($reg)* // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. out("r0") prev_hi, out("r1") prev_lo, out("r12") _, out("r13") _, // Do not use `preserves_flags` because CDSG modifies the condition code. options(nostack), ); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } }; } atomic_rmw_cas_3! { atomic_add, [], distinct_op!("algr", "%r13", "%r1", "{val_lo}"), // r13 = r1 + val_lo; cc = zero | carry "lgr %r12, %r0", // r12 = r0 "alcgr %r12, {val_hi}", // r12 += val_hi + carry } atomic_rmw_cas_3! { atomic_sub, [], distinct_op!("slgr", "%r13", "%r1", "{val_lo}"), // r13 = r1 - val_lo; cc = zero | borrow "lgr %r12, %r0", // r12 = r0 "slbgr %r12, {val_hi}", // r12 -= val_hi + borrow } atomic_rmw_cas_3! { atomic_and, [], distinct_op!("ngr", "%r13", "%r1", "{val_lo}"), // r13 = r1 & val_lo distinct_op!("ngr", "%r12", "%r0", "{val_hi}"), // r12 = r0 & val_hi } // Use nngrk on z15 or later. #[cfg(any( target_feature = "miscellaneous-extensions-3", portable_atomic_target_feature = "miscellaneous-extensions-3", ))] atomic_rmw_cas_3! { atomic_nand, [], "nngrk %r13, %r1, {val_lo}", // r13 = !(r1 & val_lo) "nngrk %r12, %r0, {val_hi}", // r12 = !(r0 & val_hi) } #[cfg(not(any( target_feature = "miscellaneous-extensions-3", portable_atomic_target_feature = "miscellaneous-extensions-3", )))] atomic_rmw_cas_3! { atomic_nand, [], distinct_op!("ngr", "%r13", "%r1", "{val_lo}"), // r13 = r1 & val_lo distinct_op!("ngr", "%r12", "%r0", "{val_hi}"), // r12 = r0 & val_hi "lcgr %r13, %r13", // r13 = !r13 + 1 "aghi %r13, -1", // r13 -= 1 "lcgr %r12, %r12", // r12 = !r12 + 1 "aghi %r12, -1", // r12 -= 1 } atomic_rmw_cas_3! { atomic_or, [], distinct_op!("ogr", "%r13", "%r1", "{val_lo}"), // r13 = r1 | val_lo distinct_op!("ogr", "%r12", "%r0", "{val_hi}"), // r12 = r0 | val_hi } atomic_rmw_cas_3! { atomic_xor, [], distinct_op!("xgr", "%r13", "%r1", "{val_lo}"), // r13 = r1 ^ val_lo distinct_op!("xgr", "%r12", "%r0", "{val_hi}"), // r12 = r0 ^ val_hi } #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] atomic_rmw_cas_3! { atomic_max, [], "clgr %r1, {val_lo}", // if r1(u) < val_lo(u) { cc = 1 } else if r1(u) > val_lo(u) { cc = 2 } else { cc = 0 } select_op!("h", "%r12", "%r1", "{val_lo}"), // if cc == 2 { r12 = r1 } else { r12 = val_lo } "cgr %r0, {val_hi}", // if r0(i) < val_hi(i) { cc = 1 } else if r0(i) > val_hi(i) { cc = 2 } else { cc = 0 } select_op!("h", "%r13", "%r1", "{val_lo}"), // if cc == 2 { r13 = r1 } else { r13 = val_lo } "locgre %r13, %r12", // if cc == 0 { r13 = r12 } select_op!("h", "%r12", "%r0", "{val_hi}"), // if cc == 2 { r12 = r0 } else { r12 = val_hi } } #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] atomic_rmw_cas_3! { atomic_umax, [tmp = out(reg) _,], "clgr %r1, {val_lo}", // if r1(u) < val_lo(u) { cc = 1 } else if r1(u) > val_lo(u) { cc = 2 } else { cc = 0 } select_op!("h", "{tmp}", "%r1", "{val_lo}"), // if cc == 2 { tmp = r1 } else { tmp = val_lo } "clgr %r0, {val_hi}", // if r0(u) < val_hi(u) { cc = 1 } else if r0(u) > val_hi(u) { cc = 2 } else { cc = 0 } select_op!("h", "%r12", "%r0", "{val_hi}"), // if cc == 2 { r12 = r0 } else { r12 = val_hi } select_op!("h", "%r13", "%r1", "{val_lo}"), // if cc == 2 { r13 = r1 } else { r13 = val_lo } "cgr %r0, {val_hi}", // if r0(i) < val_hi(i) { cc = 1 } else if r0(i) > val_hi(i) { cc = 2 } else { cc = 0 } "locgre %r13, {tmp}", // if cc == 0 { r13 = tmp } } #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] atomic_rmw_cas_3! { atomic_min, [], "clgr %r1, {val_lo}", // if r1(u) < val_lo(u) { cc = 1 } else if r1(u) > val_lo(u) { cc = 2 } else { cc = 0 } select_op!("l", "%r12", "%r1", "{val_lo}"), // if cc == 1 { r12 = r1 } else { r12 = val_lo } "cgr %r0, {val_hi}", // if r0(i) < val_hi(i) { cc = 1 } else if r0(i) > val_hi(i) { cc = 2 } else { cc = 0 } select_op!("l", "%r13", "%r1", "{val_lo}"), // if cc == 1 { r13 = r1 } else { r13 = val_lo } "locgre %r13, %r12", // if cc == 0 { r13 = r12 } select_op!("l", "%r12", "%r0", "{val_hi}"), // if cc == 1 { r12 = r0 } else { r12 = val_hi } } #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] atomic_rmw_cas_3! { atomic_umin, [tmp = out(reg) _,], "clgr %r1, {val_lo}", // if r1(u) < val_lo(u) { cc = 1 } else if r1(u) > val_lo(u) { cc = 2 } else { cc = 0 } select_op!("l", "{tmp}", "%r1", "{val_lo}"), // if cc == 1 { tmp = r1 } else { tmp = val_lo } "clgr %r0, {val_hi}", // if r0(u) < val_hi(u) { cc = 1 } else if r0(u) > val_hi(u) { cc = 2 } else { cc = 0 } select_op!("l", "%r12", "%r0", "{val_hi}"), // if cc == 1 { r12 = r0 } else { r12 = val_hi } select_op!("l", "%r13", "%r1", "{val_lo}"), // if cc == 1 { r13 = r1 } else { r13 = val_lo } "cgr %r0, {val_hi}", // if r0(i) < val_hi(i) { cc = 1 } else if r0(i) > val_hi(i) { cc = 2 } else { cc = 0 } "locgre %r13, {tmp}", // if cc == 0 { r13 = tmp } } // We use atomic_update for atomic min/max on pre-z196 because // z10 doesn't seem to have a good way to implement 128-bit min/max. // loc{,g}r requires z196 or later. // https://godbolt.org/z/EqoMEP8b3 #[cfg(not(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", )))] atomic_rmw_by_atomic_update!(cmp); atomic_rmw_cas_2! { atomic_not, [], "lcgr %r13, %r1", // r13 = !r1 + 1 "aghi %r13, -1", // r13 -= 1 "lcgr %r12, %r0", // r12 = !r0 + 1 "aghi %r12, -1", // r12 -= 1 } #[cfg(any(target_feature = "distinct-ops", portable_atomic_target_feature = "distinct-ops"))] atomic_rmw_cas_2! { atomic_neg, [zero = in(reg) 0_u64,], "slgrk %r13, {zero}, %r1", // r13 = 0 - r1; cc = zero | borrow "lghi %r12, 0", // r12 = 0 "slbgr %r12, %r0", // r12 -= r0 + borrow } #[cfg(not(any(target_feature = "distinct-ops", portable_atomic_target_feature = "distinct-ops")))] atomic_rmw_cas_2! { atomic_neg, [], "lghi %r13, 0", // r13 = 0 "slgr %r13, %r1", // r13 -= r1; cc = zero | borrow "lghi %r12, 0", // r12 = 0 "slbgr %r12, %r0", // r12 -= r0 + borrow } #[inline] const fn is_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } const IS_ALWAYS_LOCK_FREE: bool = true; atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/powerpc64.rs0000644000175000017500000012536115105742312020756 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 128-bit atomic implementation on PowerPC64. This architecture provides the following 128-bit atomic instructions: - lq/stq: load/store (ISA 2.07 or later, included in the Linux Compliancy subset and AIX Compliancy subset) - lqarx/stqcx.: LL/SC (ISA 2.07 or later, included in the Linux Compliancy subset and AIX Compliancy subset) - plq/pstq: load/store (ISA 3.1 or later, included in the Linux Compliancy subset and AIX Compliancy subset) See "Atomic operation overview by architecture" in atomic-maybe-uninit for a more comprehensive and detailed description of the atomic and synchronize instructions in this architecture: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/README.md#powerpc Note that we do not separate LL and SC into separate functions, but handle them within a single asm block. This is because it is theoretically possible for the compiler to insert operations that might clear the reservation between LL and SC. See aarch64.rs for details. Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use this module and use intrinsics.rs instead. Refs: - Power ISA https://openpowerfoundation.org/specifications/isa - AIX Assembler language reference https://www.ibm.com/docs/en/aix/7.3?topic=aix-assembler-language-reference - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit Generated asm: - powerpc64 (pwr8) https://godbolt.org/z/TjKsPbWc6 - powerpc64le https://godbolt.org/z/5WqPGhb3Y */ include!("macros.rs"); #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] #[path = "../fallback/outline_atomics.rs"] mod fallback; // On musl with static linking, it seems that getauxval is not always available. // See detect/auxv.rs for more. #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( test, not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )), ))] #[cfg(any( all( target_os = "linux", any( all( target_env = "gnu", any(target_endian = "little", not(target_feature = "crt-static")), ), all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "openbsd", ))] #[path = "../detect/auxv.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( test, not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )), ))] #[cfg(target_os = "aix")] #[cfg(not(portable_atomic_pre_llvm_20))] // SIGTRAP on LLVM 19 #[cfg(any(test, portable_atomic_outline_atomics))] // TODO(aix): currently disabled by default #[path = "../detect/powerpc64_aix.rs"] mod detect; use core::{arch::asm, sync::atomic::Ordering}; use crate::utils::{Pair, U128}; macro_rules! debug_assert_pwr8 { () => { #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] { debug_assert!(detect::detect().has_quadword_atomics()); } }; } // Refs: https://www.ibm.com/docs/en/aix/7.3?topic=ops-machine-pseudo-op // // This is similar to #[target_feature(enable = "quadword-atomics")], except that there are // no compiler guarantees regarding (un)inlining, and the scope is within an asm // block rather than a function. We use this directive because #[target_feature(enable = "quadword-atomics")] // is unstable and unavailable on old nightly and incompatible with rustc_codegen_cranelift: // https://github.com/rust-lang/rustc_codegen_cranelift/issues/1400#issuecomment-1774599775 // // Note: start_pwr8 and end_pwr8 must be used in pairs. // // Note: If power8 instructions are not available at compile-time, we must guarantee that // the function that uses it is not inlined into a function where it is not // clear whether power8 instructions are available. Otherwise, (even if we checked whether // power8 instructions are available at run-time) optimizations that reorder its // instructions across the if condition might introduce undefined behavior. // (see also https://rust-lang.github.io/rfcs/2045-target-feature.html#safely-inlining-target_feature-functions-on-more-contexts) // However, our code uses the ifunc helper macro that works with function pointers, // so we don't have to worry about this unless calling without helper macro. macro_rules! start_pwr8 { () => { ".machine push\n.machine power8" }; } macro_rules! end_pwr8 { () => { ".machine pop" }; } macro_rules! atomic_rmw { ($op:ident, $order:ident) => { match $order { Ordering::Relaxed => $op!("", ""), Ordering::Acquire => $op!("isync", ""), Ordering::Release => $op!("", "lwsync"), Ordering::AcqRel => $op!("isync", "lwsync"), Ordering::SeqCst => $op!("isync", "sync"), _ => unreachable!(), } }; } macro_rules! atomic_cas { ($op:ident, $success:ident, $failure:ident) => { if $failure == Ordering::Relaxed { match $success { Ordering::Relaxed => $op!("", "", ""), Ordering::Acquire => $op!("", "isync", ""), Ordering::Release => $op!("", "", "lwsync"), Ordering::AcqRel => $op!("", "isync", "lwsync"), Ordering::SeqCst => $op!("", "isync", "sync"), _ => unreachable!(), } } else { let order = crate::utils::upgrade_success_ordering($success, $failure); match order { // Relaxed and Release are covered in $failure == Relaxed branch. Ordering::Acquire => $op!("isync", "", ""), Ordering::AcqRel => $op!("isync", "", "lwsync"), Ordering::SeqCst => $op!("isync", "", "sync"), _ => unreachable!(), } } }; } // Extracts and checks the EQ bit of cr0. #[inline] fn test_cr0_eq(cr: u64) -> bool { cr & 0x20000000 != 0 } // If quadword-atomics is available at compile-time, we can always use pwr8_fn. #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use self::atomic_load_pwr8 as atomic_load; // Otherwise, we need to do run-time detection and can use pwr8_fn only if quadword-atomics is available. #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] #[inline] unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(src: *mut u128) -> u128; atomic_load_pwr8_relaxed = atomic_load_pwr8(Ordering::Relaxed); atomic_load_pwr8_acquire = atomic_load_pwr8(Ordering::Acquire); atomic_load_pwr8_seqcst = atomic_load_pwr8(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls atomic_load_pwr8 if quadword-atomics is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_quadword_atomics() { atomic_load_pwr8_relaxed } else { fallback::atomic_load_non_seqcst } }) } Ordering::Acquire => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_quadword_atomics() { atomic_load_pwr8_acquire } else { fallback::atomic_load_non_seqcst } }) } Ordering::SeqCst => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_quadword_atomics() { atomic_load_pwr8_seqcst } else { fallback::atomic_load_seqcst } }) } _ => unreachable!(), } } } #[inline] unsafe fn atomic_load_pwr8(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_pwr8!(); let (out_hi, out_lo); // SAFETY: the caller must uphold the safety contract. // // Refs: Section 3.3.4 "Fixed Point Load and Store Quadword Instructions" of Power ISA 3.1C Book I unsafe { macro_rules! atomic_load_acquire { ($release:tt) => { asm!( start_pwr8!(), $release, "lq %r4, 0({src})", // atomic { r4:r5 = *src } "cmpw %r4, %r4", // if r4 == r4 { cr0.EQ = 1 } else { cr0.EQ = 0 } "bne- %cr0, 2f", // if unlikely(cr0.EQ == 0) { jump 'never } "2:", // 'never: "isync", // fence (works in combination with a branch that depends on the loaded value) end_pwr8!(), src = in(reg_nonzero) ptr_reg!(src), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r4") out_hi, out("r5") out_lo, out("cr0") _, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => { asm!( start_pwr8!(), "lq %r4, 0({src})", // atomic { r4:r5 = *src } end_pwr8!(), src = in(reg_nonzero) ptr_reg!(src), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r4") out_hi, out("r5") out_lo, options(nostack, preserves_flags), ); } Ordering::Acquire => atomic_load_acquire!(""), Ordering::SeqCst => atomic_load_acquire!("sync"), _ => unreachable!(), } U128 { pair: Pair { hi: out_hi, lo: out_lo } }.whole } } // If quadword-atomics is available at compile-time, we can always use pwr8_fn. #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use self::atomic_store_pwr8 as atomic_store; // Otherwise, we need to do run-time detection and can use pwr8_fn only if quadword-atomics is available. #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128, val: u128); atomic_store_pwr8_relaxed = atomic_store_pwr8(Ordering::Relaxed); atomic_store_pwr8_release = atomic_store_pwr8(Ordering::Release); atomic_store_pwr8_seqcst = atomic_store_pwr8(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls atomic_store_pwr8 if quadword-atomics is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { if detect::detect().has_quadword_atomics() { atomic_store_pwr8_relaxed } else { fallback::atomic_store_non_seqcst } }); } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { if detect::detect().has_quadword_atomics() { atomic_store_pwr8_release } else { fallback::atomic_store_non_seqcst } }); } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { if detect::detect().has_quadword_atomics() { atomic_store_pwr8_seqcst } else { fallback::atomic_store_seqcst } }); } _ => unreachable!(), } } } #[inline] unsafe fn atomic_store_pwr8(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); let val = U128 { whole: val }; // SAFETY: the caller must uphold the safety contract. // // Refs: Section 3.3.4 "Fixed Point Load and Store Quadword Instructions" of Power ISA 3.1C Book I unsafe { macro_rules! atomic_store { ($release:tt) => { asm!( start_pwr8!(), $release, // fence "stq %r4, 0({dst})", // atomic { *dst = r4:r5 } end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. in("r4") val.pair.hi, in("r5") val.pair.lo, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => atomic_store!(""), Ordering::Release => atomic_store!("lwsync"), Ordering::SeqCst => atomic_store!("sync"), _ => unreachable!(), } } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] // SAFETY: the caller must uphold the safety contract. // cfg guarantees that quadword atomics instructions are available at compile-time. let (prev, ok) = unsafe { atomic_compare_exchange_pwr8(dst, old, new, success, failure) }; #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] // SAFETY: the caller must uphold the safety contract. let (prev, ok) = { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool); pwr8_relaxed_fn = atomic_compare_exchange_pwr8(Ordering::Relaxed, Ordering::Relaxed); pwr8_acquire_fn = atomic_compare_exchange_pwr8(Ordering::Acquire, Ordering::Acquire); pwr8_release_fn = atomic_compare_exchange_pwr8(Ordering::Release, Ordering::Relaxed); pwr8_acqrel_fn = atomic_compare_exchange_pwr8(Ordering::AcqRel, Ordering::Acquire); pwr8_seqcst_fn = atomic_compare_exchange_pwr8(Ordering::SeqCst, Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls pwr8_fn if quadword-atomics is available. unsafe { let success = crate::utils::upgrade_success_ordering(success, failure); match success { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_quadword_atomics() { pwr8_relaxed_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::Acquire => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_quadword_atomics() { pwr8_acquire_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_quadword_atomics() { pwr8_release_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::AcqRel => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_quadword_atomics() { pwr8_acqrel_fn } else { fallback::atomic_compare_exchange_non_seqcst } }) } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_quadword_atomics() { pwr8_seqcst_fn } else { fallback::atomic_compare_exchange_seqcst } }) } _ => unreachable!(), } } }; if ok { Ok(prev) } else { Err(prev) } } #[inline] unsafe fn atomic_compare_exchange_pwr8( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); let old = U128 { whole: old }; let new = U128 { whole: new }; let (mut prev_hi, mut prev_lo); let mut r; // SAFETY: the caller must uphold the safety contract. // // Refs: Section 4.6.2.2 "128-bit Load And Reserve and Store Conditional Instructions" of Power ISA 3.1C Book II unsafe { macro_rules! cmpxchg { ($acquire_always:tt, $acquire_success:tt, $release:tt) => { asm!( start_pwr8!(), $release, // fence "2:", // 'retry: "lqarx %r8, 0, {dst}", // atomic { RESERVE = (dst, 16); r8:r9 = *dst } "xor {tmp_lo}, %r9, {old_lo}", // tmp_lo = r9 ^ old_lo "xor {tmp_hi}, %r8, {old_hi}", // tmp_hi = r8 ^ old_hi "or. {tmp_lo}, {tmp_lo}, {tmp_hi}", // tmp_lo |= tmp_hi; if tmp_lo == 0 { cr0.EQ = 1 } else { cr0.EQ = 0 } "bne %cr0, 3f", // if cr0.EQ == 0 { jump 'cmp-fail } "stqcx. %r6, 0, {dst}", // atomic { if RESERVE == (dst, 16) { *dst = r6:r7; cr0.EQ = 1 } else { cr0.EQ = 0 }; RESERVE = None } "bne %cr0, 2b", // if cr0.EQ == 0 { jump 'retry } $acquire_success, // fence "3:", // 'cmp-fail: $acquire_always, // fence "mfcr {tmp_lo}", // tmp_lo = zero_extend(cr) end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), old_hi = in(reg) old.pair.hi, old_lo = in(reg) old.pair.lo, tmp_hi = out(reg) _, tmp_lo = out(reg) r, // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. in("r6") new.pair.hi, in("r7") new.pair.lo, out("r8") prev_hi, out("r9") prev_lo, out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_cas!(cmpxchg, success, failure); // if compare failed EQ bit is cleared, if store succeeds EQ bit is set. (U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole, test_cr0_eq(r)) } } // Always use strong CAS for outline-atomics. #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] use self::atomic_compare_exchange as atomic_compare_exchange_weak; #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] #[inline] unsafe fn atomic_compare_exchange_weak( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { // SAFETY: the caller must uphold the safety contract. // cfg guarantees that quadword atomics instructions are available at compile-time. let (prev, ok) = unsafe { atomic_compare_exchange_weak_pwr8(dst, old, new, success, failure) }; if ok { Ok(prev) } else { Err(prev) } } #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] #[inline] unsafe fn atomic_compare_exchange_weak_pwr8( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); let old = U128 { whole: old }; let new = U128 { whole: new }; let (mut prev_hi, mut prev_lo); let mut r; // SAFETY: the caller must uphold the safety contract. // // Refs: Section 4.6.2.2 "128-bit Load And Reserve and Store Conditional Instructions" of Power ISA 3.1C Book II unsafe { macro_rules! cmpxchg_weak { ($acquire_always:tt, $acquire_success:tt, $release:tt) => { asm!( start_pwr8!(), $release, // fence "lqarx %r8, 0, {dst}", // atomic { RESERVE = (dst, 16); r8:r9 = *dst } "xor {tmp_lo}, %r9, {old_lo}", // tmp_lo = r9 ^ old_lo "xor {tmp_hi}, %r8, {old_hi}", // tmp_hi = r8 ^ old_hi "or. {tmp_lo}, {tmp_lo}, {tmp_hi}", // tmp_lo |= tmp_hi; if tmp_lo == 0 { cr0.EQ = 1 } else { cr0.EQ = 0 } "bne %cr0, 3f", // if cr0.EQ == 0 { jump 'cmp-fail } "stqcx. %r6, 0, {dst}", // atomic { if RESERVE == (dst, 16) { *dst = r6:r7; cr0.EQ = 1 } else { cr0.EQ = 0 }; RESERVE = None } $acquire_success, // fence "3:", // 'cmp-fail: $acquire_always, // fence "mfcr {tmp_lo}", // tmp_lo = zero_extend(cr) end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), old_hi = in(reg) old.pair.hi, old_lo = in(reg) old.pair.lo, tmp_hi = out(reg) _, tmp_lo = out(reg) r, // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. in("r6") new.pair.hi, in("r7") new.pair.lo, out("r8") prev_hi, out("r9") prev_lo, out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_cas!(cmpxchg_weak, success, failure); // if compare or store failed EQ bit is cleared, if store succeeds EQ bit is set. (U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole, test_cr0_eq(r)) } } // Do not use atomic_rmw_ll_sc_3 because it needs extra MR to implement swap. #[inline] unsafe fn atomic_swap_pwr8(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); let val = U128 { whole: val }; let (mut prev_hi, mut prev_lo); // SAFETY: the caller must uphold the safety contract. unsafe { macro_rules! swap { ($acquire:tt, $release:tt) => { asm!( start_pwr8!(), $release, // fence "2:", // 'retry: "lqarx %r6, 0, {dst}", // atomic { RESERVE = (dst, 16); r6:r7 = *dst } "stqcx. %r8, 0, {dst}", // atomic { if RESERVE == (dst, 16) { *dst = r8:r9; cr0.EQ = 1 } else { cr0.EQ = 0 }; RESERVE = None } "bne %cr0, 2b", // if cr0.EQ == 0 { jump 'retry } $acquire, // fence end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r6") prev_hi, out("r7") prev_lo, in("r8") val.pair.hi, in("r9") val.pair.lo, out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_rmw!(swap, order); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } /// Atomic RMW by LL/SC loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// $op can use the following registers: /// - val_hi/val_lo pair: val argument (read-only for `$op`) /// - r6/r7 pair: previous value loaded by ll (read-only for `$op`) /// - r8/r9 pair: new value that will be stored by sc macro_rules! atomic_rmw_ll_sc_3 { ($name:ident, [$($reg:tt)*], $($op:tt)*) => { #[inline] unsafe fn $name(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); let val = U128 { whole: val }; let (mut prev_hi, mut prev_lo); // SAFETY: the caller must uphold the safety contract. unsafe { macro_rules! op { ($acquire:tt, $release:tt) => { asm!( start_pwr8!(), $release, // fence "2:", // 'retry: "lqarx %r6, 0, {dst}", // atomic { RESERVE = (dst, 16); r6:r7 = *dst } $($op)* "stqcx. %r8, 0, {dst}", // atomic { if RESERVE == (dst, 16) { *dst = r8:r9; cr0.EQ = 1 } else { cr0.EQ = 0 }; RESERVE = None } "bne %cr0, 2b", // if cr0.EQ == 0 { jump 'retry } $acquire, // fence end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), val_hi = in(reg) val.pair.hi, val_lo = in(reg) val.pair.lo, $($reg)* // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r6") prev_hi, out("r7") prev_lo, out("r8") _, // new (hi) out("r9") _, // new (lo) out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } }; } /// Atomic RMW by LL/SC loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// $op can use the following registers: /// - r6/r7 pair: previous value loaded by ll (read-only for `$op`) /// - r8/r9 pair: new value that will be stored by sc macro_rules! atomic_rmw_ll_sc_2 { ($name:ident, [$($reg:tt)*], $($op:tt)*) => { #[inline] unsafe fn $name(dst: *mut u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); let (mut prev_hi, mut prev_lo); // SAFETY: the caller must uphold the safety contract. unsafe { macro_rules! op { ($acquire:tt, $release:tt) => { asm!( start_pwr8!(), $release, // fence "2:", // 'retry: "lqarx %r6, 0, {dst}", // atomic { RESERVE = (dst, 16); r6:r7 = *dst } $($op)* "stqcx. %r8, 0, {dst}", // atomic { if RESERVE == (dst, 16) { *dst = r8:r9; cr0.EQ = 1 } else { cr0.EQ = 0 }; RESERVE = None } "bne %cr0, 2b", // if cr0.EQ == 0 { jump 'retry } $acquire, // fence end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), $($reg)* // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r6") prev_hi, out("r7") prev_lo, out("r8") _, // new (hi) out("r9") _, // new (lo) out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } }; } atomic_rmw_ll_sc_3! { atomic_add_pwr8, [out("xer") _,], "addc %r9, {val_lo}, %r7", // r9 = val_lo + r7; xer.CA = carry "adde %r8, {val_hi}, %r6", // r8 = val_hi + r6 + xer.CA } atomic_rmw_ll_sc_3! { atomic_sub_pwr8, [out("xer") _,], "subc %r9, %r7, {val_lo}", // r9 = val_lo - r7; xer.CA = borrow "subfe %r8, {val_hi}, %r6", // r8 = val_hi - r6 - xer.CA } atomic_rmw_ll_sc_3! { atomic_and_pwr8, [], "and %r9, {val_lo}, %r7", // r9 = val_lo & r7 "and %r8, {val_hi}, %r6", // r8 = val_hi & r6 } atomic_rmw_ll_sc_3! { atomic_nand_pwr8, [], "nand %r9, {val_lo}, %r7", // r9 = !(val_lo & r7) "nand %r8, {val_hi}, %r6", // r8 = !(val_hi & r6) } atomic_rmw_ll_sc_3! { atomic_or_pwr8, [], "or %r9, {val_lo}, %r7", // r9 = val_lo | r7 "or %r8, {val_hi}, %r6", // r8 = val_hi | r6 } atomic_rmw_ll_sc_3! { atomic_xor_pwr8, [], "xor %r9, {val_lo}, %r7", // r9 = val_lo ^ r7 "xor %r8, {val_hi}, %r6", // r8 = val_hi ^ r6 } atomic_rmw_ll_sc_3! { atomic_max_pwr8, [out("cr1") _,], "cmpld %r7, {val_lo}", // if r7(u) < val_lo(u) { cr0 = { LT: 1, ..0 } } else if r7(u) > val_lo(u) { cr0 = { GT: 1, ..0 } } else { cr0 = { EQ: 1, ..0 } } "iselgt %r9, %r7, {val_lo}", // if cr0.GT == 1 { r9 = r7 } else { r9 = val_lo } "cmpd %cr1, %r6, {val_hi}", // if r6(i) < val_hi(i) { cr1 = { LT: 1, ..0 } } else if r6(i) > val_hi(i) { cr1 = { GT: 1, ..0 } } else { cr1 = { EQ: 1, ..0 } } "isel %r8, %r7, {val_lo}, 5", // if cr1.GT == 1 { r8 = r7 } else { r8 = val_lo } "cmpld %r6, {val_hi}", // if r6(u) < val_hi(u) { cr0 = { LT: 1, ..0 } } else if r6(u) > val_hi(u) { cr0 = { GT: 1, ..0 } } else { cr0 = { EQ: 1, ..0 } } "iseleq %r9, %r9, %r8", // if cr0.EQ == 1 { r9 = r9 } else { r9 = r8 } "isel %r8, %r6, {val_hi}, 5", // if cr1.GT == 1 { r8 = r6 } else { r8 = val_hi } } atomic_rmw_ll_sc_3! { atomic_umax_pwr8, [], "cmpld %r7, {val_lo}", // if r7(u) < val_lo(u) { cr0 = { LT: 1, ..0 } } else if r7(u) > val_lo(u) { cr0 = { GT: 1, ..0 } } else { cr0 = { EQ: 1, ..0 } } "iselgt %r9, %r7, {val_lo}", // if cr0.GT == 1 { r9 = r7 } else { r9 = val_lo } "cmpld %r6, {val_hi}", // if r6(u) < val_hi(u) { cr0 = { LT: 1, ..0 } } else if r6(u) > val_hi(u) { cr0 = { GT: 1, ..0 } } else { cr0 = { EQ: 1, ..0 } } "iselgt %r8, %r7, {val_lo}", // if cr0.GT == 1 { r8 = r7 } else { r8 = val_lo } "iseleq %r9, %r9, %r8", // if cr0.EQ == 1 { r9 = r9 } else { r9 = r8 } "iselgt %r8, %r6, {val_hi}", // if cr0.GT == 1 { r8 = r6 } else { r8 = val_hi } } atomic_rmw_ll_sc_3! { atomic_min_pwr8, [out("cr1") _,], "cmpld %r7, {val_lo}", // if r7(u) < val_lo(u) { cr0 = { LT: 1, ..0 } } else if r7(u) > val_lo(u) { cr0 = { GT: 1, ..0 } } else { cr0 = { EQ: 1, ..0 } } "isellt %r9, %r7, {val_lo}", // if cr0.LT == 1 { r9 = r7 } else { r9 = val_lo } "cmpd %cr1, %r6, {val_hi}", // if r6(i) < val_hi(i) { cr1 = { LT: 1, ..0 } } else if r6(i) > val_hi(i) { cr1 = { GT: 1, ..0 } } else { cr1 = { EQ: 1, ..0 } } "isel %r8, %r7, {val_lo}, 4", // if cr1.LT == 1 { r8 = r7 } else { r8 = val_lo } "cmpld %r6, {val_hi}", // if r6(u) < val_hi(u) { cr0 = { LT: 1, ..0 } } else if r6(u) > val_hi(u) { cr0 = { GT: 1, ..0 } } else { cr0 = { EQ: 1, ..0 } } "iseleq %r9, %r9, %r8", // if cr0.EQ == 1 { r9 = r9 } else { r9 = r8 } "isel %r8, %r6, {val_hi}, 4", // if cr1.LT == 1 { r8 = r6 } else { r8 = val_hi } } atomic_rmw_ll_sc_3! { atomic_umin_pwr8, [], "cmpld %r7, {val_lo}", // if r7(u) < val_lo(u) { cr0 = { LT: 1, ..0 } } else if r7(u) > val_lo(u) { cr0 = { GT: 1, ..0 } } else { cr0 = { EQ: 1, ..0 } } "isellt %r9, %r7, {val_lo}", // if cr0.LT == 1 { r9 = r7 } else { r9 = val_lo } "cmpld %r6, {val_hi}", // if r6(u) < val_hi(u) { cr0 = { LT: 1, ..0 } } else if r6(u) > val_hi(u) { cr0 = { GT: 1, ..0 } } else { cr0 = { EQ: 1, ..0 } } "isellt %r8, %r7, {val_lo}", // if cr0.LT == 1 { r8 = r7 } else { r8 = val_lo } "iseleq %r9, %r9, %r8", // if cr0.EQ == 1 { r9 = r9 } else { r9 = r8 } "isellt %r8, %r6, {val_hi}", // if cr0.LT == 1 { r8 = r6 } else { r8 = val_hi } } #[inline] unsafe fn atomic_not_pwr8(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_xor_pwr8(dst, !0, order) } } #[cfg(not(portable_atomic_pre_llvm_16))] atomic_rmw_ll_sc_2! { atomic_neg_pwr8, [out("xer") _,], "subfic %r9, %r7, 0", // r9 = 0 - r7; xer.CA = borrow "subfze %r8, %r6", // r8 = 0 - r6 - xer.CA } // LLVM 15 miscompiles subfic. #[cfg(portable_atomic_pre_llvm_16)] atomic_rmw_ll_sc_2! { atomic_neg_pwr8, [zero = in(reg) 0_u64, out("xer") _,], "subc %r9, {zero}, %r7", // r9 = 0 - r7; xer.CA = borrow "subfze %r8, %r6", // r8 = 0 - r6 - xer.CA } macro_rules! select_atomic_rmw { ( unsafe fn $name:ident($($arg:tt)*) $(-> $ret_ty:ty)?; pwr8 = $pwr8_fn:ident; non_seqcst_fallback = $non_seqcst_fallback_fn:ident; seqcst_fallback = $seqcst_fallback_fn:ident; ) => { // If quadword-atomics is available at compile-time, we can always use pwr8_fn. #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use self::$pwr8_fn as $name; // Otherwise, we need to do run-time detection and can use pwr8_fn only if quadword-atomics is available. #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] #[inline] unsafe fn $name($($arg)*, order: Ordering) $(-> $ret_ty)? { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn($($arg)*) $(-> $ret_ty)?; pwr8_relaxed_fn = $pwr8_fn(Ordering::Relaxed); pwr8_acquire_fn = $pwr8_fn(Ordering::Acquire); pwr8_release_fn = $pwr8_fn(Ordering::Release); pwr8_acqrel_fn = $pwr8_fn(Ordering::AcqRel); pwr8_seqcst_fn = $pwr8_fn(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls pwr8_fn if quadword-atomics is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_relaxed_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::Acquire => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_acquire_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::Release => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_release_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::AcqRel => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_acqrel_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::SeqCst => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_seqcst_fn } else { fallback::$seqcst_fallback_fn } }) } _ => unreachable!(), } } } }; } select_atomic_rmw! { unsafe fn atomic_swap(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_swap_pwr8; non_seqcst_fallback = atomic_swap_non_seqcst; seqcst_fallback = atomic_swap_seqcst; } select_atomic_rmw! { unsafe fn atomic_add(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_add_pwr8; non_seqcst_fallback = atomic_add_non_seqcst; seqcst_fallback = atomic_add_seqcst; } select_atomic_rmw! { unsafe fn atomic_sub(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_sub_pwr8; non_seqcst_fallback = atomic_sub_non_seqcst; seqcst_fallback = atomic_sub_seqcst; } select_atomic_rmw! { unsafe fn atomic_and(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_and_pwr8; non_seqcst_fallback = atomic_and_non_seqcst; seqcst_fallback = atomic_and_seqcst; } select_atomic_rmw! { unsafe fn atomic_nand(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_nand_pwr8; non_seqcst_fallback = atomic_nand_non_seqcst; seqcst_fallback = atomic_nand_seqcst; } select_atomic_rmw! { unsafe fn atomic_or(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_or_pwr8; non_seqcst_fallback = atomic_or_non_seqcst; seqcst_fallback = atomic_or_seqcst; } select_atomic_rmw! { unsafe fn atomic_xor(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_xor_pwr8; non_seqcst_fallback = atomic_xor_non_seqcst; seqcst_fallback = atomic_xor_seqcst; } select_atomic_rmw! { unsafe fn atomic_max(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_max_pwr8; non_seqcst_fallback = atomic_max_non_seqcst; seqcst_fallback = atomic_max_seqcst; } select_atomic_rmw! { unsafe fn atomic_umax(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_umax_pwr8; non_seqcst_fallback = atomic_umax_non_seqcst; seqcst_fallback = atomic_umax_seqcst; } select_atomic_rmw! { unsafe fn atomic_min(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_min_pwr8; non_seqcst_fallback = atomic_min_non_seqcst; seqcst_fallback = atomic_min_seqcst; } select_atomic_rmw! { unsafe fn atomic_umin(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_umin_pwr8; non_seqcst_fallback = atomic_umin_non_seqcst; seqcst_fallback = atomic_umin_seqcst; } select_atomic_rmw! { unsafe fn atomic_not(dst: *mut u128) -> u128; pwr8 = atomic_not_pwr8; non_seqcst_fallback = atomic_not_non_seqcst; seqcst_fallback = atomic_not_seqcst; } select_atomic_rmw! { unsafe fn atomic_neg(dst: *mut u128) -> u128; pwr8 = atomic_neg_pwr8; non_seqcst_fallback = atomic_neg_non_seqcst; seqcst_fallback = atomic_neg_seqcst; } #[inline] fn is_lock_free() -> bool { #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] { // lqarx and stqcx. instructions are statically available. true } #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] { detect::detect().has_quadword_atomics() } } const IS_ALWAYS_LOCK_FREE: bool = cfg!(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )); atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/intrinsics.rs0000644000175000017500000005156015105742312021311 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 128-bit atomic implementation without inline assembly. Adapted from https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs. Note: This module is currently only enabled on Miri and ThreadSanitizer which do not support inline assembly. This uses `core::arch::x86_64::cmpxchg16b` on x86_64 and `core::intrinsics::atomic_*` on aarch64, powerpc64, and s390x. See README.md of this directory for performance comparison with the implementation with inline assembly. Note: - This currently needs Rust 1.70 on x86_64, otherwise nightly compilers. - On powerpc64, this requires LLVM 15+ and quadword-atomics target feature: https://github.com/llvm/llvm-project/commit/549e118e93c666914a1045fde38a2cac33e1e445 - On s390x, old LLVM (pre-18) generates libcalls for operations other than load/store/cmpxchg: https://github.com/llvm/llvm-project/commit/c568927f3e2e7d9804ea74ecbf11c16c014ddcbc - On aarch64 big-endian, LLVM (as of 17) generates broken code. (wrong result in stress test) (on cfg(miri)/cfg(sanitize) it may be fine though) - On powerpc64, LLVM (as of 17) doesn't support 128-bit atomic min/max: https://github.com/llvm/llvm-project/issues/68390 - On powerpc64le, LLVM (as of 17) generates broken code. (wrong result from fetch_add) - On riscv64, LLVM does not automatically use 128-bit atomic instructions even if zacas feature is enabled, because doing it changes the ABI. (If the ability to do that is provided by LLVM in the future, it should probably be controlled by another ABI feature similar to forced-atomics.) */ include!("macros.rs"); #[allow(dead_code)] // we only use compare_exchange. #[cfg(target_arch = "x86_64")] #[cfg(not(target_feature = "cmpxchg16b"))] #[path = "../fallback/outline_atomics.rs"] mod fallback; #[cfg(target_arch = "x86_64")] #[cfg(not(target_feature = "cmpxchg16b"))] #[path = "../detect/x86_64.rs"] mod detect; #[cfg(not(target_arch = "x86_64"))] use core::intrinsics; use core::sync::atomic::Ordering::{self, AcqRel, Acquire, Relaxed, Release, SeqCst}; #[cfg(target_arch = "x86_64")] #[inline] fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release | Relaxed => Relaxed, SeqCst => SeqCst, Acquire | AcqRel => Acquire, _ => unreachable!(), } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { #[cfg(target_arch = "x86_64")] // SAFETY: the caller must uphold the safety contract. unsafe { let fail_order = strongest_failure_ordering(order); match atomic_compare_exchange(src, 0, 0, order, fail_order) { Ok(v) | Err(v) => v, } } #[cfg(not(target_arch = "x86_64"))] // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_load_acquire(src), Relaxed => intrinsics::atomic_load_relaxed(src), SeqCst => intrinsics::atomic_load_seqcst(src), _ => unreachable!(), } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { #[cfg(target_arch = "x86_64")] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_swap(dst, val, order); } #[cfg(not(target_arch = "x86_64"))] // SAFETY: the caller must uphold the safety contract. unsafe { match order { Release => intrinsics::atomic_store_release(dst, val), Relaxed => intrinsics::atomic_store_relaxed(dst, val), SeqCst => intrinsics::atomic_store_seqcst(dst, val), _ => unreachable!(), } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { #[cfg(target_arch = "x86_64")] let (val, ok) = { #[target_feature(enable = "cmpxchg16b")] #[cfg_attr(target_feature = "cmpxchg16b", inline)] #[cfg_attr(not(target_feature = "cmpxchg16b"), inline(never))] unsafe fn cmpxchg16b( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); #[cfg(not(target_feature = "cmpxchg16b"))] { debug_assert!(detect::detect().has_cmpxchg16b()); } // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned (required by CMPXCHG16B), that there are no // concurrent non-atomic operations, and that the CPU supports CMPXCHG16B. let prev = unsafe { core::arch::x86_64::cmpxchg16b(dst, old, new, success, failure) }; (prev, prev == old) } #[cfg(target_feature = "cmpxchg16b")] // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and cfg guarantees that CMPXCHG16B is available at compile-time. unsafe { cmpxchg16b(dst, old, new, success, failure) } #[cfg(not(target_feature = "cmpxchg16b"))] // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no different kinds of concurrent accesses. unsafe { ifunc!(unsafe fn( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering ) -> (u128, bool) { if detect::detect().has_cmpxchg16b() { cmpxchg16b } else { fallback::atomic_compare_exchange } }) } }; #[cfg(not(target_arch = "x86_64"))] // SAFETY: the caller must uphold the safety contract. let (val, ok) = unsafe { match (success, failure) { (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed_relaxed(dst, old, new), (Relaxed, Acquire) => intrinsics::atomic_cxchg_relaxed_acquire(dst, old, new), (Relaxed, SeqCst) => intrinsics::atomic_cxchg_relaxed_seqcst(dst, old, new), (Acquire, Relaxed) => intrinsics::atomic_cxchg_acquire_relaxed(dst, old, new), (Acquire, Acquire) => intrinsics::atomic_cxchg_acquire_acquire(dst, old, new), (Acquire, SeqCst) => intrinsics::atomic_cxchg_acquire_seqcst(dst, old, new), (Release, Relaxed) => intrinsics::atomic_cxchg_release_relaxed(dst, old, new), (Release, Acquire) => intrinsics::atomic_cxchg_release_acquire(dst, old, new), (Release, SeqCst) => intrinsics::atomic_cxchg_release_seqcst(dst, old, new), (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_relaxed(dst, old, new), (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel_acquire(dst, old, new), (AcqRel, SeqCst) => intrinsics::atomic_cxchg_acqrel_seqcst(dst, old, new), (SeqCst, Relaxed) => intrinsics::atomic_cxchg_seqcst_relaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchg_seqcst_acquire(dst, old, new), (SeqCst, SeqCst) => intrinsics::atomic_cxchg_seqcst_seqcst(dst, old, new), _ => unreachable!(), } }; if ok { Ok(val) } else { Err(val) } } #[cfg(target_arch = "x86_64")] use self::atomic_compare_exchange as atomic_compare_exchange_weak; #[cfg(not(target_arch = "x86_64"))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_compare_exchange_weak( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { // SAFETY: the caller must uphold the safety contract. let (val, ok) = unsafe { match (success, failure) { (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed_relaxed(dst, old, new), (Relaxed, Acquire) => intrinsics::atomic_cxchgweak_relaxed_acquire(dst, old, new), (Relaxed, SeqCst) => intrinsics::atomic_cxchgweak_relaxed_seqcst(dst, old, new), (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acquire_relaxed(dst, old, new), (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acquire_acquire(dst, old, new), (Acquire, SeqCst) => intrinsics::atomic_cxchgweak_acquire_seqcst(dst, old, new), (Release, Relaxed) => intrinsics::atomic_cxchgweak_release_relaxed(dst, old, new), (Release, Acquire) => intrinsics::atomic_cxchgweak_release_acquire(dst, old, new), (Release, SeqCst) => intrinsics::atomic_cxchgweak_release_seqcst(dst, old, new), (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_relaxed(dst, old, new), (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel_acquire(dst, old, new), (AcqRel, SeqCst) => intrinsics::atomic_cxchgweak_acqrel_seqcst(dst, old, new), (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_seqcst_relaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_seqcst_acquire(dst, old, new), (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak_seqcst_seqcst(dst, old, new), _ => unreachable!(), } }; if ok { Ok(val) } else { Err(val) } } #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_update(dst: *mut u128, order: Ordering, mut f: F) -> u128 where F: FnMut(u128) -> u128, { // SAFETY: the caller must uphold the safety contract. unsafe { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = atomic_load(dst, Ordering::Relaxed); loop { let next = f(prev); match atomic_compare_exchange_weak(dst, prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(x) => prev = x, } } } } // On x86_64, we use core::arch::x86_64::cmpxchg16b instead of core::intrinsics. // - On s390x, old LLVM (pre-18) generates libcalls for operations other than load/store/cmpxchg (see also module-level comment). #[cfg(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18)))] atomic_rmw_by_atomic_update!(); // On powerpc64, LLVM doesn't support 128-bit atomic min/max (see also module-level comment). #[cfg(target_arch = "powerpc64")] atomic_rmw_by_atomic_update!(cmp); #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_swap(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_xchg_acquire(dst, val), Release => intrinsics::atomic_xchg_release(dst, val), AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), SeqCst => intrinsics::atomic_xchg_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_add(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_xadd_acquire(dst, val), Release => intrinsics::atomic_xadd_release(dst, val), AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), Relaxed => intrinsics::atomic_xadd_relaxed(dst, val), SeqCst => intrinsics::atomic_xadd_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_sub(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_xsub_acquire(dst, val), Release => intrinsics::atomic_xsub_release(dst, val), AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), Relaxed => intrinsics::atomic_xsub_relaxed(dst, val), SeqCst => intrinsics::atomic_xsub_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_and(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_and_acquire(dst, val), Release => intrinsics::atomic_and_release(dst, val), AcqRel => intrinsics::atomic_and_acqrel(dst, val), Relaxed => intrinsics::atomic_and_relaxed(dst, val), SeqCst => intrinsics::atomic_and_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_nand(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_nand_acquire(dst, val), Release => intrinsics::atomic_nand_release(dst, val), AcqRel => intrinsics::atomic_nand_acqrel(dst, val), Relaxed => intrinsics::atomic_nand_relaxed(dst, val), SeqCst => intrinsics::atomic_nand_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_or(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_or_acquire(dst, val), Release => intrinsics::atomic_or_release(dst, val), AcqRel => intrinsics::atomic_or_acqrel(dst, val), Relaxed => intrinsics::atomic_or_relaxed(dst, val), SeqCst => intrinsics::atomic_or_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_xor(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_xor_acquire(dst, val), Release => intrinsics::atomic_xor_release(dst, val), AcqRel => intrinsics::atomic_xor_acqrel(dst, val), Relaxed => intrinsics::atomic_xor_relaxed(dst, val), SeqCst => intrinsics::atomic_xor_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any( target_arch = "x86_64", target_arch = "powerpc64", all(target_arch = "s390x", portable_atomic_pre_llvm_18), )))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_max(dst: *mut u128, val: u128, order: Ordering) -> i128 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_max_acquire(dst.cast::(), val as i128), Release => intrinsics::atomic_max_release(dst.cast::(), val as i128), AcqRel => intrinsics::atomic_max_acqrel(dst.cast::(), val as i128), Relaxed => intrinsics::atomic_max_relaxed(dst.cast::(), val as i128), SeqCst => intrinsics::atomic_max_seqcst(dst.cast::(), val as i128), _ => unreachable!(), } } } #[cfg(not(any( target_arch = "x86_64", target_arch = "powerpc64", all(target_arch = "s390x", portable_atomic_pre_llvm_18), )))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_min(dst: *mut u128, val: u128, order: Ordering) -> i128 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_min_acquire(dst.cast::(), val as i128), Release => intrinsics::atomic_min_release(dst.cast::(), val as i128), AcqRel => intrinsics::atomic_min_acqrel(dst.cast::(), val as i128), Relaxed => intrinsics::atomic_min_relaxed(dst.cast::(), val as i128), SeqCst => intrinsics::atomic_min_seqcst(dst.cast::(), val as i128), _ => unreachable!(), } } } #[cfg(not(any( target_arch = "x86_64", target_arch = "powerpc64", all(target_arch = "s390x", portable_atomic_pre_llvm_18), )))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umax(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_umax_acquire(dst, val), Release => intrinsics::atomic_umax_release(dst, val), AcqRel => intrinsics::atomic_umax_acqrel(dst, val), Relaxed => intrinsics::atomic_umax_relaxed(dst, val), SeqCst => intrinsics::atomic_umax_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any( target_arch = "x86_64", target_arch = "powerpc64", all(target_arch = "s390x", portable_atomic_pre_llvm_18), )))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umin(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_umin_acquire(dst, val), Release => intrinsics::atomic_umin_release(dst, val), AcqRel => intrinsics::atomic_umin_acqrel(dst, val), Relaxed => intrinsics::atomic_umin_relaxed(dst, val), SeqCst => intrinsics::atomic_umin_seqcst(dst, val), _ => unreachable!(), } } } #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_not(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_xor(dst, !0, order) } } #[cfg(not(any(target_arch = "x86_64", all(target_arch = "s390x", portable_atomic_pre_llvm_18))))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_neg(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, u128::wrapping_neg) } } #[cfg(not(target_arch = "x86_64"))] #[inline] const fn is_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } #[cfg(not(target_arch = "x86_64"))] const IS_ALWAYS_LOCK_FREE: bool = true; #[cfg(target_arch = "x86_64")] #[inline] fn is_lock_free() -> bool { #[cfg(target_feature = "cmpxchg16b")] { // CMPXCHG16B is available at compile-time. true } #[cfg(not(target_feature = "cmpxchg16b"))] { detect::detect().has_cmpxchg16b() } } #[cfg(target_arch = "x86_64")] const IS_ALWAYS_LOCK_FREE: bool = cfg!(target_feature = "cmpxchg16b"); atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/x86_64.rs0000644000175000017500000010115615105742312020057 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 128-bit atomic implementation on x86_64. This architecture provides the following 128-bit atomic instructions: - CMPXCHG16B: CAS (CMPXCHG16B) - VMOVDQA: load/store (Intel, AMD, or Zhaoxin CPU with AVX) Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use this module and use intrinsics.rs instead. Refs: - x86 and amd64 instruction reference https://www.felixcloutier.com/x86 - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit Generated asm: - x86_64 (+cmpxchg16b) https://godbolt.org/z/rfs1jxd51 */ // TODO: use core::arch::x86_64::cmpxchg16b where available and efficient than asm include!("macros.rs"); #[cfg(not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")))] #[path = "../fallback/outline_atomics.rs"] mod fallback; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(not(target_env = "sgx"))] #[cfg_attr( not(target_feature = "sse"), cfg(not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))) )] #[path = "../detect/x86_64.rs"] mod detect; #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::sync::atomic::Ordering; use crate::utils::{Pair, U128}; // Asserts that the function is called in the correct context. macro_rules! debug_assert_cmpxchg16b { () => { #[cfg(not(any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", )))] { debug_assert!(detect::detect().has_cmpxchg16b()); } }; } #[cfg(not(any(portable_atomic_no_outline_atomics, target_env = "sgx")))] #[cfg(target_feature = "sse")] macro_rules! debug_assert_vmovdqa_atomic { () => {{ debug_assert_cmpxchg16b!(); debug_assert!(detect::detect().has_vmovdqa_atomic()); }}; } #[cfg(not(any(portable_atomic_no_outline_atomics, target_env = "sgx")))] #[cfg(target_feature = "sse")] #[cfg(target_pointer_width = "32")] macro_rules! ptr_modifier { () => { ":e" }; } #[cfg(not(any(portable_atomic_no_outline_atomics, target_env = "sgx")))] #[cfg(target_feature = "sse")] #[cfg(target_pointer_width = "64")] macro_rules! ptr_modifier { () => { "" }; } // Unlike AArch64 and RISC-V, x86's assembler doesn't check instruction // requirements for the currently enabled target features. In the first place, // there is no option in the x86 assembly for such case, like Arm .arch_extension, // RISC-V .option arch, PowerPC .machine, etc. // However, we set target_feature(enable) when available (Rust 1.69+) in case a // new codegen backend is added that checks for it in the future, or an option // is added to the assembler to check for it. #[cfg_attr( not(portable_atomic_no_cmpxchg16b_target_feature), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn cmpxchg16b(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned (required by CMPXCHG16B), that there are no // concurrent non-atomic operations, and that the CPU supports CMPXCHG16B. // // If the value at `dst` (destination operand) and rdx:rax are equal, the // 128-bit value in rcx:rbx is stored in the `dst`, otherwise the value at // `dst` is loaded to rdx:rax. // // The ZF flag is set if the value at `dst` and rdx:rax are equal, // otherwise it is cleared. Other flags are unaffected. // // Refs: https://www.felixcloutier.com/x86/cmpxchg8b:cmpxchg16b unsafe { // cmpxchg16b is always SeqCst. let r: u8; let old = U128 { whole: old }; let new = U128 { whole: new }; let (prev_lo, prev_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( "xchg {rbx_tmp}, rbx", // save rbx which is reserved by LLVM concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "sete cl", "mov rbx, {rbx_tmp}", // restore rbx rbx_tmp = inout(reg) new.pair.lo => _, in("rcx") new.pair.hi, inout("rax") old.pair.lo => prev_lo, inout("rdx") old.pair.hi => prev_hi, in($rdi) dst, lateout("cl") r, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); crate::utils::assert_unchecked(r == 0 || r == 1); // needed to remove extra test (U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole, r != 0) } } // VMOVDQA is atomic on Intel, AMD, and Zhaoxin CPUs with AVX. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 for details. // // Refs: https://www.felixcloutier.com/x86/movdqa:vmovdqa32:vmovdqa64 // // Use cfg(target_feature = "sse") here -- SSE is included in the x86_64 // baseline and is always available, but the SSE target feature is disabled for // use cases such as kernels and firmware that should not use vector registers. // So, do not use vector registers unless SSE target feature is enabled. // See also https://github.com/rust-lang/rust/blob/1.84.0/src/doc/rustc/src/platform-support/x86_64-unknown-none.md. #[cfg(not(any(portable_atomic_no_outline_atomics, target_env = "sgx")))] #[cfg(target_feature = "sse")] #[target_feature(enable = "avx")] #[inline] unsafe fn atomic_load_vmovdqa(src: *mut u128) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_vmovdqa_atomic!(); // SAFETY: the caller must uphold the safety contract. // // atomic load by vmovdqa is always SeqCst. unsafe { let out: core::arch::x86_64::__m128i; asm!( concat!("vmovdqa {out}, xmmword ptr [{src", ptr_modifier!(), "}]"), src = in(reg) src, out = out(xmm_reg) out, options(nostack, preserves_flags), ); core::mem::transmute(out) } } #[cfg(not(any(portable_atomic_no_outline_atomics, target_env = "sgx")))] #[cfg(target_feature = "sse")] #[target_feature(enable = "avx")] #[inline] unsafe fn atomic_store_vmovdqa(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); debug_assert_vmovdqa_atomic!(); // SAFETY: the caller must uphold the safety contract. unsafe { let val: core::arch::x86_64::__m128i = core::mem::transmute(val); match order { // Relaxed and Release stores are equivalent. Ordering::Relaxed | Ordering::Release => { asm!( concat!("vmovdqa xmmword ptr [{dst", ptr_modifier!(), "}], {val}"), dst = in(reg) dst, val = in(xmm_reg) val, options(nostack, preserves_flags), ); } Ordering::SeqCst => { let p = core::cell::UnsafeCell::new(core::mem::MaybeUninit::::uninit()); asm!( concat!("vmovdqa xmmword ptr [{dst", ptr_modifier!(), "}], {val}"), // Equivalent to mfence, but is up to 3.1x faster on Coffee Lake and up to 2.4x faster on Raptor Lake-H at least in simple cases. // - https://github.com/taiki-e/portable-atomic/pull/156 // - LLVM uses lock or for x86_32 64-bit atomic SeqCst store using SSE https://godbolt.org/z/9sKEr8YWc // - Windows uses xchg for x86_32 for MemoryBarrier https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-memorybarrier // - MSVC STL uses lock inc https://github.com/microsoft/STL/pull/740 // - boost uses lock or https://github.com/boostorg/atomic/commit/559eba81af71386cedd99f170dc6101c6ad7bf22 concat!("xchg qword ptr [{p", ptr_modifier!(), "}], {tmp}"), dst = in(reg) dst, val = in(xmm_reg) val, p = inout(reg) p.get() => _, tmp = lateout(reg) _, options(nostack, preserves_flags), ); } _ => unreachable!(), } } } #[cfg(not(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), )))] macro_rules! load_store_detect { ( vmovdqa = $vmovdqa:ident cmpxchg16b = $cmpxchg16b:ident fallback = $fallback:ident ) => {{ let cpuid = detect::detect(); #[cfg(not(any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", )))] { // Check CMPXCHG16B first to prevent mixing atomic and non-atomic access. if cpuid.has_cmpxchg16b() { // We only use VMOVDQA when SSE is enabled. See atomic_load_vmovdqa() for more. #[cfg(target_feature = "sse")] { if cpuid.has_vmovdqa_atomic() { $vmovdqa } else { $cmpxchg16b } } #[cfg(not(target_feature = "sse"))] { $cmpxchg16b } } else { fallback::$fallback } } #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] { if cpuid.has_vmovdqa_atomic() { $vmovdqa } else { $cmpxchg16b } } }}; } #[inline] unsafe fn atomic_load(src: *mut u128, _order: Ordering) -> u128 { // We only use VMOVDQA when SSE is enabled. See atomic_load_vmovdqa() for more. // SGX doesn't support CPUID. #[cfg(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), ))] // SAFETY: the caller must uphold the safety contract. // cfg guarantees that CMPXCHG16B is available at compile-time. unsafe { // cmpxchg16b is always SeqCst. atomic_load_cmpxchg16b(src) } #[cfg(not(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), )))] // SAFETY: the caller must uphold the safety contract. unsafe { ifunc!(unsafe fn(src: *mut u128) -> u128 { load_store_detect! { vmovdqa = atomic_load_vmovdqa cmpxchg16b = atomic_load_cmpxchg16b // Use SeqCst because cmpxchg16b and atomic load by vmovdqa is always SeqCst. fallback = atomic_load_seqcst } }) } } // See cmpxchg16b() for target_feature(enable). #[cfg_attr( not(portable_atomic_no_cmpxchg16b_target_feature), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn atomic_load_cmpxchg16b(src: *mut u128) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `src` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // cfg guarantees that the CPU supports CMPXCHG16B. // // See cmpxchg16b function for more. // // We could use CAS loop by atomic_compare_exchange here, but using an inline assembly allows // omitting the storing of condition flags and avoid use of xchg to handle rbx. unsafe { // cmpxchg16b is always SeqCst. let (out_lo, out_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( "mov {rbx_tmp}, rbx", // save rbx which is reserved by LLVM "xor rbx, rbx", // zeroed rbx concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "mov rbx, {rbx_tmp}", // restore rbx // set old/new args of cmpxchg16b to 0 (rbx is zeroed after saved to rbx_tmp, to avoid xchg) rbx_tmp = out(reg) _, in("rcx") 0_u64, inout("rax") 0_u64 => out_lo, inout("rdx") 0_u64 => out_hi, in($rdi) src, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { // We only use VMOVDQA when SSE is enabled. See atomic_load_vmovdqa() for more. // SGX doesn't support CPUID. #[cfg(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), ))] // SAFETY: the caller must uphold the safety contract. // cfg guarantees that CMPXCHG16B is available at compile-time. unsafe { // cmpxchg16b is always SeqCst. let _ = order; atomic_store_cmpxchg16b(dst, val); } #[cfg(not(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), )))] // SAFETY: the caller must uphold the safety contract. unsafe { #[cfg(target_feature = "sse")] fn_alias! { #[target_feature(enable = "avx")] unsafe fn(dst: *mut u128, val: u128); // atomic store by vmovdqa has at least release semantics. atomic_store_vmovdqa_non_seqcst = atomic_store_vmovdqa(Ordering::Release); atomic_store_vmovdqa_seqcst = atomic_store_vmovdqa(Ordering::SeqCst); } match order { // Relaxed and Release stores are equivalent in all implementations // that may be called here (vmovdqa, asm-based cmpxchg16b, and fallback). // core::arch's cmpxchg16b will never called here. Ordering::Relaxed | Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { load_store_detect! { vmovdqa = atomic_store_vmovdqa_non_seqcst cmpxchg16b = atomic_store_cmpxchg16b fallback = atomic_store_non_seqcst } }); } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { load_store_detect! { vmovdqa = atomic_store_vmovdqa_seqcst cmpxchg16b = atomic_store_cmpxchg16b fallback = atomic_store_seqcst } }); } _ => unreachable!(), } } } // See cmpxchg16b() for target_feature(enable). #[cfg_attr( not(portable_atomic_no_cmpxchg16b_target_feature), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn atomic_store_cmpxchg16b(dst: *mut u128, val: u128) { // SAFETY: the caller must uphold the safety contract. unsafe { // cmpxchg16b is always SeqCst. atomic_swap_cmpxchg16b(dst, val, Ordering::SeqCst); } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, _success: Ordering, _failure: Ordering, ) -> Result { #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and cfg guarantees that CMPXCHG16B is available at compile-time. let (prev, ok) = unsafe { cmpxchg16b(dst, old, new) }; #[cfg(not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")))] // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no different kinds of concurrent accesses. let (prev, ok) = unsafe { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_cmpxchg16b() { cmpxchg16b } else { // Use SeqCst because cmpxchg16b is always SeqCst. fallback::atomic_compare_exchange_seqcst } }) }; if ok { Ok(prev) } else { Err(prev) } } // cmpxchg16b is always strong. use self::atomic_compare_exchange as atomic_compare_exchange_weak; // See cmpxchg16b() for target_feature(enable). #[cfg_attr( not(portable_atomic_no_cmpxchg16b_target_feature), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn atomic_swap_cmpxchg16b(dst: *mut u128, val: u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // cfg guarantees that the CPU supports CMPXCHG16B. // // See cmpxchg16b function for more. // // We could use CAS loop by atomic_compare_exchange here, but using an inline assembly allows // omitting the storing/comparing of condition flags and reducing uses of xchg/mov to handle rbx. // // Do not use atomic_rmw_cas_3 because it needs extra MOV to implement swap. unsafe { // cmpxchg16b is always SeqCst. let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( "xchg {rbx_tmp}, rbx", // save rbx which is reserved by LLVM // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // This is based on the code generated for the first load in DW RMWs by LLVM. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement this. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). concat!("mov rax, qword ptr [", $rdi, "]"), concat!("mov rdx, qword ptr [", $rdi, " + 8]"), "2:", concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "jne 2b", "mov rbx, {rbx_tmp}", // restore rbx rbx_tmp = inout(reg) val.pair.lo => _, in("rcx") val.pair.hi, out("rax") prev_lo, out("rdx") prev_hi, in($rdi) dst, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } /// Atomic RMW by CAS loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - rsi/r8 pair: val argument (read-only for `$op`) /// - rax/rdx pair: previous value loaded (read-only for `$op`) /// - rbx/rcx pair: new value that will be stored // We could use CAS loop by atomic_compare_exchange here, but using an inline assembly allows // omitting the storing/comparing of condition flags and reducing uses of xchg/mov to handle rbx. macro_rules! atomic_rmw_cas_3 { ($name:ident, $($op:tt)*) => { // See cmpxchg16b() for target_feature(enable). #[cfg_attr( not(portable_atomic_no_cmpxchg16b_target_feature), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn $name(dst: *mut u128, val: u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // cfg guarantees that the CPU supports CMPXCHG16B. // // See cmpxchg16b function for more. unsafe { // cmpxchg16b is always SeqCst. let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( "mov {rbx_tmp}, rbx", // save rbx which is reserved by LLVM // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // This is based on the code generated for the first load in DW RMWs by LLVM. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement this. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). concat!("mov rax, qword ptr [", $rdi, "]"), concat!("mov rdx, qword ptr [", $rdi, " + 8]"), "2:", $($op)* concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "jne 2b", "mov rbx, {rbx_tmp}", // restore rbx rbx_tmp = out(reg) _, out("rcx") _, out("rax") prev_lo, out("rdx") prev_hi, in($rdi) dst, in("rsi") val.pair.lo, in("r8") val.pair.hi, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } /// Atomic RMW by CAS loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - rax/rdx pair: previous value loaded (read-only for `$op`) /// - rbx/rcx pair: new value that will be stored // We could use CAS loop by atomic_compare_exchange here, but using an inline assembly allows // omitting the storing of condition flags and avoid use of xchg to handle rbx. macro_rules! atomic_rmw_cas_2 { ($name:ident, $($op:tt)*) => { // See cmpxchg16b() for target_feature(enable). #[cfg_attr( not(portable_atomic_no_cmpxchg16b_target_feature), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn $name(dst: *mut u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // cfg guarantees that the CPU supports CMPXCHG16B. // // See cmpxchg16b function for more. unsafe { // cmpxchg16b is always SeqCst. let (mut prev_lo, mut prev_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( "mov {rbx_tmp}, rbx", // save rbx which is reserved by LLVM // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // This is based on the code generated for the first load in DW RMWs by LLVM. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement this. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). concat!("mov rax, qword ptr [", $rdi, "]"), concat!("mov rdx, qword ptr [", $rdi, " + 8]"), "2:", $($op)* concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "jne 2b", "mov rbx, {rbx_tmp}", // restore rbx rbx_tmp = out(reg) _, out("rcx") _, out("rax") prev_lo, out("rdx") prev_hi, in($rdi) dst, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } atomic_rmw_cas_3! { atomic_add_cmpxchg16b, "mov rbx, rax", "add rbx, rsi", "mov rcx, rdx", "adc rcx, r8", } atomic_rmw_cas_3! { atomic_sub_cmpxchg16b, "mov rbx, rax", "sub rbx, rsi", "mov rcx, rdx", "sbb rcx, r8", } atomic_rmw_cas_3! { atomic_and_cmpxchg16b, "mov rbx, rax", "and rbx, rsi", "mov rcx, rdx", "and rcx, r8", } atomic_rmw_cas_3! { atomic_nand_cmpxchg16b, "mov rbx, rax", "and rbx, rsi", "not rbx", "mov rcx, rdx", "and rcx, r8", "not rcx", } atomic_rmw_cas_3! { atomic_or_cmpxchg16b, "mov rbx, rax", "or rbx, rsi", "mov rcx, rdx", "or rcx, r8", } atomic_rmw_cas_3! { atomic_xor_cmpxchg16b, "mov rbx, rax", "xor rbx, rsi", "mov rcx, rdx", "xor rcx, r8", } atomic_rmw_cas_2! { atomic_not_cmpxchg16b, "mov rbx, rax", "not rbx", "mov rcx, rdx", "not rcx", } atomic_rmw_cas_2! { atomic_neg_cmpxchg16b, "mov rbx, rax", "neg rbx", "mov rcx, 0", "sbb rcx, rdx", } atomic_rmw_cas_3! { atomic_max_cmpxchg16b, "cmp rsi, rax", "mov rcx, r8", "sbb rcx, rdx", "mov rcx, r8", "cmovl rcx, rdx", "mov rbx, rsi", "cmovl rbx, rax", } atomic_rmw_cas_3! { atomic_umax_cmpxchg16b, "cmp rsi, rax", "mov rcx, r8", "sbb rcx, rdx", "mov rcx, r8", "cmovb rcx, rdx", "mov rbx, rsi", "cmovb rbx, rax", } atomic_rmw_cas_3! { atomic_min_cmpxchg16b, "cmp rsi, rax", "mov rcx, r8", "sbb rcx, rdx", "mov rcx, r8", "cmovge rcx, rdx", "mov rbx, rsi", "cmovge rbx, rax", } atomic_rmw_cas_3! { atomic_umin_cmpxchg16b, "cmp rsi, rax", "mov rcx, r8", "sbb rcx, rdx", "mov rcx, r8", "cmovae rcx, rdx", "mov rbx, rsi", "cmovae rbx, rax", } macro_rules! select_atomic_rmw { ( unsafe fn $name:ident($($arg:tt)*) $(-> $ret_ty:ty)?; cmpxchg16b = $cmpxchg16b_fn:ident; fallback = $seqcst_fallback_fn:ident; ) => { // If cmpxchg16b is available at compile-time, we can always use cmpxchg16b_fn. #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] use self::$cmpxchg16b_fn as $name; // Otherwise, we need to do run-time detection and can use cmpxchg16b_fn only if cmpxchg16b is available. #[cfg(not(any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", )))] #[inline] unsafe fn $name($($arg)*, _order: Ordering) $(-> $ret_ty)? { fn_alias! { // See cmpxchg16b() for target_feature(enable). #[cfg_attr( not(portable_atomic_no_cmpxchg16b_target_feature), target_feature(enable = "cmpxchg16b") )] unsafe fn($($arg)*) $(-> $ret_ty)?; // cmpxchg16b is always SeqCst. cmpxchg16b_seqcst_fn = $cmpxchg16b_fn(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls cmpxchg16b_fn if cmpxchg16b is available. unsafe { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_cmpxchg16b() { cmpxchg16b_seqcst_fn } else { // Use SeqCst because cmpxchg16b is always SeqCst. fallback::$seqcst_fallback_fn } }) } } }; } select_atomic_rmw! { unsafe fn atomic_swap(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_swap_cmpxchg16b; fallback = atomic_swap_seqcst; } select_atomic_rmw! { unsafe fn atomic_add(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_add_cmpxchg16b; fallback = atomic_add_seqcst; } select_atomic_rmw! { unsafe fn atomic_sub(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_sub_cmpxchg16b; fallback = atomic_sub_seqcst; } select_atomic_rmw! { unsafe fn atomic_and(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_and_cmpxchg16b; fallback = atomic_and_seqcst; } select_atomic_rmw! { unsafe fn atomic_nand(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_nand_cmpxchg16b; fallback = atomic_nand_seqcst; } select_atomic_rmw! { unsafe fn atomic_or(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_or_cmpxchg16b; fallback = atomic_or_seqcst; } select_atomic_rmw! { unsafe fn atomic_xor(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_xor_cmpxchg16b; fallback = atomic_xor_seqcst; } select_atomic_rmw! { unsafe fn atomic_max(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_max_cmpxchg16b; fallback = atomic_max_seqcst; } select_atomic_rmw! { unsafe fn atomic_umax(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_umax_cmpxchg16b; fallback = atomic_umax_seqcst; } select_atomic_rmw! { unsafe fn atomic_min(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_min_cmpxchg16b; fallback = atomic_min_seqcst; } select_atomic_rmw! { unsafe fn atomic_umin(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_umin_cmpxchg16b; fallback = atomic_umin_seqcst; } select_atomic_rmw! { unsafe fn atomic_not(dst: *mut u128) -> u128; cmpxchg16b = atomic_not_cmpxchg16b; fallback = atomic_not_seqcst; } select_atomic_rmw! { unsafe fn atomic_neg(dst: *mut u128) -> u128; cmpxchg16b = atomic_neg_cmpxchg16b; fallback = atomic_neg_seqcst; } #[inline] fn is_lock_free() -> bool { #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] { // CMPXCHG16B is available at compile-time. true } #[cfg(not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")))] { detect::detect().has_cmpxchg16b() } } const IS_ALWAYS_LOCK_FREE: bool = cfg!(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")); atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[allow(clippy::undocumented_unsafe_blocks, clippy::wildcard_imports)] #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/README.md0000644000175000017500000001003015105742312020020 0ustar bdrungbdrung# 128-bit atomic implementations on 64-bit architectures (See the [`atomic64` module](../atomic64) for 64-bit atomic implementations on 32-bit architectures.) ## 128-bit atomic instructions Here is the table of targets that support 128-bit atomics and the instructions used: | target_arch | load | store | CAS | RMW | note | | ----------- | ---- | ----- | --- | --- | ---- | | x86_64 | cmpxchg16b or vmovdqa | cmpxchg16b or vmovdqa | cmpxchg16b | cmpxchg16b | Requires `cmpxchg16b` target feature (enabled by default on Apple and Windows (except Windows 7) targets). vmovdqa requires Intel, AMD, or Zhaoxin CPU with AVX.
Both compile-time and run-time detection are supported for cmpxchg16b. vmovdqa is currently run-time detection only.
Requires rustc 1.59+ | | aarch64/arm64ec | ldxp/stxp or casp or ldp/ldiapp | ldxp/stxp or casp or stp/stilp/swpp | ldxp/stxp or casp | ldxp/stxp or casp/swpp/ldclrp/ldsetp | casp requires `lse` target feature, ldp/stp requires `lse2` target feature, ldiapp/stilp requires `lse2` and `rcpc3` target features, swpp/ldclrp/ldsetp requires `lse128` target feature.
Both compile-time and run-time detection are supported.
Requires rustc 1.59+ (aarch64) / 1.84+ (arm64ec) | | riscv64 | amocas.q | amocas.q | amocas.q | amocas.q | Requires `zacas` target feature. Both compile-time and run-time detection are supported.
Requires rustc 1.59+ | | powerpc64 | lq | stq | lqarx/stqcx. | lqarx/stqcx. | Requires `quadword-atomics` target feature (enabled by default on powerpc64le). Both compile-time and run-time detection are supported.
Requires nightly | | s390x | lpq | stpq | cdsg | cdsg | Requires rustc 1.84+ | | mips64r6 | lldp | lldp/scdp | lldp/scdp | lldp/scdp | Unimplemented (unsupported in LLVM). Requires Release 6 Paired LL/SC family of instructions | | nvptx64 | ld.b128 | st.b128 | atom.cas.b128 | atom.exch.b128/atom.cas.b128 | Unimplemented. Requires `ptx83` and `sm_90`. | On compiler versions or platforms where these are not supported, the fallback implementation is used. See [aarch64.rs](aarch64.rs) module-level comments for more details on the instructions used on AArch64. ## Comparison with core::intrinsics::atomic_\* (core::sync::atomic::Atomic{I,U}128) This directory has target-specific implementations with inline assembly ([x86_64.rs](x86_64.rs), [aarch64.rs](aarch64.rs), [riscv64.rs](riscv64.rs), [powerpc64.rs](powerpc64.rs), [s390x.rs](s390x.rs)) and an implementation without inline assembly ([intrinsics.rs](intrinsics.rs)). The latter currently always needs nightly compilers and is only used for Miri and ThreadSanitizer, which do not support inline assembly. Implementations with inline assembly generate assemblies almost equivalent to the `core::intrinsics::atomic_*` (used in `core::sync::atomic::Atomic{I,U}128`) for many operations, but some operations may or may not generate more efficient code. For example: - On x86_64 and AArch64, implementation with inline assembly contains additional optimizations (e.g., [#16](https://github.com/taiki-e/portable-atomic/pull/16), [#126](https://github.com/taiki-e/portable-atomic/pull/126)) and is much faster for some operations. - On AArch64, implementation with inline assembly supports outline-atomics on more operating systems, and may be faster in environments where outline-atomics can improve performance. - On powerpc64, LLVM does not support generating some 128-bit atomic operations (see [intrinsics.rs](intrinsics.rs) module-level comments), and we use CAS loop to implement them, so implementation with inline assembly may be faster for those operations. - In implementations without inline assembly, the compiler may reuse condition flags that have changed as a result of the operation, or use immediate values instead of registers, depending on the situation. As 128-bit atomics-related APIs stabilize in the standard library, implementations with inline assembly are planned to be updated to get the benefits of both. ## Run-time CPU feature detection See the [`detect` module's readme](../detect/README.md) for run-time CPU feature detection. portable-atomic/src/imp/atomic128/macros.rs0000644000175000017500000004115515105742312020407 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT macro_rules! atomic128 { ($atomic_type:ident, $int_type:ident, $atomic_max:ident, $atomic_min:ident) => { #[repr(C, align(16))] pub(crate) struct $atomic_type { v: core::cell::UnsafeCell<$int_type>, } // Send is implicitly implemented. // SAFETY: any data races are prevented by atomic intrinsics. unsafe impl Sync for $atomic_type {} impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { v: core::cell::UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { is_lock_free() } pub(crate) const IS_ALWAYS_LOCK_FREE: bool = IS_ALWAYS_LOCK_FREE; #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_load(self.v.get().cast::(), order) as $int_type } } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_store(self.v.get().cast::(), val as u128, order) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn swap(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_swap(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { match atomic_compare_exchange( self.v.get().cast::(), current as u128, new as u128, success, failure, ) { Ok(v) => Ok(v as $int_type), Err(v) => Err(v as $int_type), } } } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { match atomic_compare_exchange_weak( self.v.get().cast::(), current as u128, new as u128, success, failure, ) { Ok(v) => Ok(v as $int_type), Err(v) => Err(v as $int_type), } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_add(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_sub(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_and(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_nand(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_or(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_xor(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { $atomic_max(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { $atomic_min(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_not(self.v.get().cast::(), order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_neg(&self, order: Ordering) -> $int_type { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_neg(self.v.get().cast::(), order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } }; } #[cfg(any(target_arch = "powerpc64", target_arch = "s390x", target_arch = "x86_64"))] #[allow(unused_macros)] // also used by intrinsics.rs macro_rules! atomic_rmw_by_atomic_update { () => { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_swap(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |_| val) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_add(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x.wrapping_add(val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_sub(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x.wrapping_sub(val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_and(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x & val) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_nand(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| !(x & val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_or(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x | val) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_xor(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x ^ val) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_not(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| !x) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_neg(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, u128::wrapping_neg) } } atomic_rmw_by_atomic_update!(cmp); }; (cmp) => { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_max(dst: *mut u128, val: u128, order: Ordering) -> u128 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| core::cmp::max(x as i128, val as i128) as u128) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umax(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| core::cmp::max(x, val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_min(dst: *mut u128, val: u128, order: Ordering) -> u128 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| core::cmp::min(x as i128, val as i128) as u128) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umin(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| core::cmp::min(x, val)) } } }; } portable-atomic/src/imp/atomic128/aarch64.rs0000644000175000017500000027175215105742312020363 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* 128-bit atomic implementation on AArch64. This architecture provides the following 128-bit atomic instructions: - LDXP/STXP: LL/SC (Armv8.0 baseline) - CASP: CAS (added as Armv8.1 FEAT_LSE (optional from Armv8.0, mandatory from Armv8.1)) - LDP/STP: load/store (if Armv8.4 FEAT_LSE2 (optional from Armv8.2, mandatory from Armv8.4) is available) - LDIAPP/STILP: acquire-load/release-store (added as Armv8.9 FEAT_LRCPC3 (optional from Armv8.2) (if FEAT_LSE2 is also available)) - LDCLRP/LDSETP/SWPP: fetch-and-{clear,or},swap (added as Armv9.4 FEAT_LSE128 (optional from Armv9.3)) This module supports all of these instructions and attempts to select the best one based on compile-time and run-time information about available CPU features and platforms. For example: - If outline-atomics is not enabled and FEAT_LSE is not available at compile-time, we use LDXP/STXP loop. - If outline-atomics is enabled and FEAT_LSE is not available at compile-time, we use CASP for CAS if FEAT_LSE is available at run-time, otherwise, use LDXP/STXP loop. - If FEAT_LSE is available at compile-time, we use CASP for load/store/CAS/RMW. However, when portable_atomic_ll_sc_rmw cfg is set, use LDXP/STXP loop instead of CASP loop for RMW (by default, it is set on Apple hardware where CASP is slow; see build script for details). - If outline-atomics is enabled and FEAT_LSE2 is not available at compile-time, we use LDP/STP (and also LDIAPP/STILP/SWPP if FEAT_LRCPC3/FEAT_LSE128 is available) for load/store if FEAT_LSE2 is available at run-time, otherwise, use LDXP/STXP or CASP depending on whether FEAT_LSE is available. - If FEAT_LSE2 is available at compile-time, we use LDP/STP for load/store. - If FEAT_LSE128 is available at compile-time, we use LDCLRP/LDSETP/SWPP for fetch_and/fetch_or/swap/{release,seqcst}-store. - If FEAT_LSE2 and FEAT_LRCPC3 are available at compile-time, we use LDIAPP/STILP for acquire-load/release-store. See each "Instruction selection flow for ..." comment in this file for the exact instruction selection per operation. Note: FEAT_LSE2 doesn't imply FEAT_LSE. FEAT_LSE128 implies FEAT_LSE but not FEAT_LSE2. Note that we do not separate LL and SC into separate functions, but handle them within a single asm block. This is because it is theoretically possible for the compiler to insert operations that might clear the reservation between LL and SC. Considering the type of operations we are providing and the fact that [progress64](https://github.com/ARM-software/progress64) uses such code, this is probably not a problem for AArch64, but it seems that AArch64 doesn't guarantee it and hexagon is the only architecture with hardware guarantees that such code works. See also: - https://yarchive.net/comp/linux/cmpxchg_ll_sc_portability.html - https://lists.llvm.org/pipermail/llvm-dev/2016-May/099490.html - https://lists.llvm.org/pipermail/llvm-dev/2018-June/123993.html Also, even when using a CAS loop to implement atomic RMW, include the loop itself in the asm block because it is more efficient for some codegen backends. https://github.com/rust-lang/compiler-builtins/issues/339#issuecomment-1191260474 Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use this module and use intrinsics.rs instead. Refs: - Arm A-profile A64 Instruction Set Architecture https://developer.arm.com/documentation/ddi0602/2024-12 - Arm Compiler armasm User Guide https://developer.arm.com/documentation/dui0801/latest - Arm Architecture Reference Manual for A-profile architecture https://developer.arm.com/documentation/ddi0487/latest (PDF) - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit Generated asm: - aarch64 https://godbolt.org/z/aEWe7zhMh - aarch64 msvc https://godbolt.org/z/Phq7M6MPs - aarch64 (+lse) https://godbolt.org/z/9Go3dT6sW - aarch64 msvc (+lse) https://godbolt.org/z/vGvc6bTMT - aarch64 (+lse,+lse2) https://godbolt.org/z/KddzqsM9o - aarch64 (+lse,+lse2,+rcpc3) https://godbolt.org/z/sePheahxh - aarch64 (+lse2,+lse128) https://godbolt.org/z/WPqM9M1r3 - aarch64 (+lse2,+lse128,+rcpc3) https://godbolt.org/z/5Mf8dc88Y */ include!("macros.rs"); // On musl with static linking, it seems that getauxval is not always available. // See detect/auxv.rs for more. #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), any(target_feature = "lse2", portable_atomic_target_feature = "lse2"), )), ))] #[cfg(any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ))] #[path = "../detect/auxv.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), any(target_feature = "lse2", portable_atomic_target_feature = "lse2"), )), ))] #[cfg(any(target_os = "netbsd", target_os = "openbsd"))] #[path = "../detect/aarch64_aa64reg.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, portable_atomic_outline_atomics))] // TODO(aarch64-illumos): currently disabled by default #[cfg(any( test, not(all( any(target_feature = "lse2", portable_atomic_target_feature = "lse2"), any(target_feature = "lse", portable_atomic_target_feature = "lse"), )), ))] #[cfg(target_os = "illumos")] #[path = "../detect/aarch64_illumos.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse"))))] #[cfg(target_os = "fuchsia")] #[path = "../detect/aarch64_fuchsia.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse"))))] #[cfg(windows)] #[path = "../detect/aarch64_windows.rs"] mod detect; // test only #[cfg(test)] #[cfg(not(qemu))] #[cfg(not(valgrind))] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] #[path = "../detect/aarch64_aa64reg.rs"] mod detect_aa64reg; #[cfg(test)] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(target_vendor = "apple")] #[path = "../detect/aarch64_apple.rs"] mod detect_apple; #[cfg(test)] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(target_os = "openbsd")] #[path = "../detect/auxv.rs"] mod detect_auxv; #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::sync::atomic::Ordering; use crate::utils::{Pair, U128}; #[cfg(any( target_feature = "lse", portable_atomic_target_feature = "lse", not(portable_atomic_no_outline_atomics), ))] macro_rules! debug_assert_lse { () => { #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), target_os = "fuchsia", windows, ), ))] #[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))] { debug_assert!(detect::detect().has_lse()); } }; } #[cfg(any( target_feature = "lse2", portable_atomic_target_feature = "lse2", not(portable_atomic_no_outline_atomics), ))] macro_rules! debug_assert_lse2 { () => { #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // windows, ), ))] #[cfg(not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")))] { debug_assert!(detect::detect().has_lse2()); } }; } #[cfg(any( target_feature = "lse128", portable_atomic_target_feature = "lse128", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] macro_rules! debug_assert_lse128 { () => { #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE128. // target_os = "fuchsia", // windows, ), ))] #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] { debug_assert!(detect::detect().has_lse128()); } }; } #[cfg(any( target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] macro_rules! debug_assert_rcpc3 { () => { #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LRCPC3. // target_os = "fuchsia", // windows, ), ))] #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] { debug_assert!(detect::detect().has_rcpc3()); } }; } // Refs: https://developer.arm.com/documentation/100067/0611/armclang-Integrated-Assembler/AArch32-Target-selection-directives // // This is similar to #[target_feature(enable = "lse")], except that there are // no compiler guarantees regarding (un)inlining, and the scope is within an asm // block rather than a function. We use this directive because #[target_feature(enable = "lse")] // is unstable on pre-1.61 rustc and incompatible with rustc_codegen_cranelift: // https://github.com/rust-lang/rustc_codegen_cranelift/issues/1400#issuecomment-1774599775 // // The .arch_extension directive is effective until the end of the assembly block and // is not propagated to subsequent code, so the end_lse macro is unneeded. // https://godbolt.org/z/o6EPndP94 // https://github.com/torvalds/linux/commit/e0d5896bd356cd577f9710a02d7a474cdf58426b // https://github.com/torvalds/linux/commit/dd1f6308b28edf0452dd5dc7877992903ec61e69 // (It seems GCC effectively ignores this directive and always allow FEAT_LSE instructions: https://godbolt.org/z/W9W6rensG) // // The .arch directive has a similar effect, but we don't use it due to the following issue: // https://github.com/torvalds/linux/commit/dd1f6308b28edf0452dd5dc7877992903ec61e69 // // Note: If FEAT_LSE is not available at compile-time, we must guarantee that // the function that uses it is not inlined into a function where it is not // clear whether FEAT_LSE is available. Otherwise, (even if we checked whether // FEAT_LSE is available at run-time) optimizations that reorder its // instructions across the if condition might introduce undefined behavior. // (see also https://rust-lang.github.io/rfcs/2045-target-feature.html#safely-inlining-target_feature-functions-on-more-contexts) // However, our code uses the ifunc helper macro that works with function pointers, // so we don't have to worry about this unless calling without helper macro. #[cfg(any( target_feature = "lse", portable_atomic_target_feature = "lse", not(portable_atomic_no_outline_atomics), ))] macro_rules! start_lse { () => { ".arch_extension lse" }; } #[cfg(not(portable_atomic_pre_llvm_16))] #[cfg(any( target_feature = "lse128", portable_atomic_target_feature = "lse128", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] macro_rules! start_lse128 { () => { ".arch_extension lse128" }; } #[cfg(not(portable_atomic_pre_llvm_16))] #[cfg(any( target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] macro_rules! start_rcpc3 { () => { ".arch_extension rcpc3" }; } #[cfg(target_endian = "little")] macro_rules! select_le_or_be { ($le:expr, $be:expr) => { $le }; } #[cfg(target_endian = "big")] macro_rules! select_le_or_be { ($le:expr, $be:expr) => { $be }; } macro_rules! atomic_rmw { ($op:ident, $order:ident) => { atomic_rmw!($op, $order, write = $order) }; ($op:ident, $order:ident, write = $write:ident) => { match $order { Ordering::Relaxed => $op!("", "", ""), Ordering::Acquire => $op!("a", "", ""), Ordering::Release => $op!("", "l", ""), Ordering::AcqRel => $op!("a", "l", ""), // In MSVC environments, SeqCst stores/writes needs fences after writes. // https://reviews.llvm.org/D141748 #[cfg(target_env = "msvc")] Ordering::SeqCst if $write == Ordering::SeqCst => $op!("a", "l", "dmb ish"), // AcqRel and SeqCst RMWs are equivalent in non-MSVC environments. Ordering::SeqCst => $op!("a", "l", ""), _ => unreachable!(), } }; } #[cfg(portable_atomic_pre_llvm_16)] #[cfg(any( target_feature = "lse128", portable_atomic_target_feature = "lse128", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] macro_rules! atomic_rmw_inst { ($op:ident, $order:ident) => { atomic_rmw_inst!($op, $order, write = $order) }; ($op:ident, $order:ident, write = $write:ident) => { match $order { Ordering::Relaxed => $op!("2", ""), Ordering::Acquire => $op!("a", ""), Ordering::Release => $op!("6", ""), Ordering::AcqRel => $op!("e", ""), // In MSVC environments, SeqCst stores/writes needs fences after writes. // https://reviews.llvm.org/D141748 #[cfg(target_env = "msvc")] Ordering::SeqCst if $write == Ordering::SeqCst => $op!("e", "dmb ish"), // AcqRel and SeqCst RMWs are equivalent in non-MSVC environments. Ordering::SeqCst => $op!("e", ""), _ => unreachable!(), } }; } // ----------------------------------------------------------------------------- // load /* Instruction selection flow for load: - if compile_time(FEAT_LSE2) => ldp: - if compile_time(FEAT_LRCPC3) && order != relaxed => ldiapp - else => ldp - if platform_supports_detection_of(FEAT_LSE2): - if detect(FEAT_LSE2) && detect(FEAT_LRCPC3) && order != relaxed => lse2_rcpc3 (ldiapp) - if detect(FEAT_LSE2) => lse2 (ldp) - else => no_lse2: - if compile_time(FEAT_LSE) => casp - else => ldxp_stxp Note: - If FEAT_LSE2 is available at compile-time, we don't do run-time detection of FEAT_LRCPC3 at this time, since FEAT_LRCPC3 is not yet available for most CPUs. (macOS that doesn't have any FEAT_LRCPC3-enabled CPUs as of M4 is only a platform that currently enables FEAT_LSE2 at compile-time by default.) - If FEAT_LSE2 is not available at compile-time, we want to do run-time detection of FEAT_LSE2, so we do run-time detection of FEAT_LRCPC3 at the same time. - We don't do run-time detection of FEAT_LSE for load at this time, but since load by CAS is wait-free, it would probably make sense to do run-time detection. (TODO) */ // if compile_time(FEAT_LSE2) => ldp: // cfg guarantee that the CPU supports FEAT_LSE2. #[cfg(any(target_feature = "lse2", portable_atomic_target_feature = "lse2"))] use self::_atomic_load_ldp as atomic_load; #[cfg(not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")))] #[inline] unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { #[inline] unsafe fn atomic_load_no_lse2(src: *mut u128, order: Ordering) -> u128 { // if compile_time(FEAT_LSE) => casp #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { _atomic_load_casp(src, order) } // else => ldxp_stxp #[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))] // SAFETY: the caller must uphold the safety contract. unsafe { _atomic_load_ldxp_stxp(src, order) } } // if platform_supports_detection_of(FEAT_LSE2): #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // windows, ), ))] { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(src: *mut u128) -> u128; atomic_load_lse2_relaxed = _atomic_load_ldp(Ordering::Relaxed); atomic_load_lse2_acquire = _atomic_load_ldp(Ordering::Acquire); atomic_load_lse2_seqcst = _atomic_load_ldp(Ordering::SeqCst); atomic_load_lse2_rcpc3_acquire = _atomic_load_ldiapp(Ordering::Acquire); atomic_load_lse2_rcpc3_seqcst = _atomic_load_ldiapp(Ordering::SeqCst); } fn_alias! { unsafe fn(src: *mut u128) -> u128; atomic_load_no_lse2_relaxed = atomic_load_no_lse2(Ordering::Relaxed); atomic_load_no_lse2_acquire = atomic_load_no_lse2(Ordering::Acquire); atomic_load_no_lse2_seqcst = atomic_load_no_lse2(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // and we've checked if FEAT_LSE2/FEAT_LRCPC3 is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(src: *mut u128) -> u128 { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { // if detect(FEAT_LSE2) => lse2 (ldp) atomic_load_lse2_relaxed } else { // else => no_lse2: atomic_load_no_lse2_relaxed } }) } Ordering::Acquire => { ifunc!(unsafe fn(src: *mut u128) -> u128 { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { if cpuinfo.has_rcpc3() { // if detect(FEAT_LSE2) && detect(FEAT_LRCPC3) && order != relaxed => lse2_rcpc3 (ldiapp) atomic_load_lse2_rcpc3_acquire } else { // if detect(FEAT_LSE2) => lse2 (ldp) atomic_load_lse2_acquire } } else { // else => no_lse2: atomic_load_no_lse2_acquire } }) } Ordering::SeqCst => { ifunc!(unsafe fn(src: *mut u128) -> u128 { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { if cpuinfo.has_rcpc3() { // if detect(FEAT_LSE2) && detect(FEAT_LRCPC3) && order != relaxed => lse2_rcpc3 (ldiapp) atomic_load_lse2_rcpc3_seqcst } else { // if detect(FEAT_LSE2) => lse2 (ldp) atomic_load_lse2_seqcst } } else { // else => no_lse2: atomic_load_no_lse2_seqcst } }) } _ => unreachable!(), } } } // else => no_lse2: #[cfg(not(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // windows, ), )))] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_load_no_lse2(src, order) } } // If CPU supports FEAT_LSE2, LDP/LDIAPP is single-copy atomic reads, // otherwise it is two single-copy atomic reads. // Refs: B2.2.1 of the Arm Architecture Reference Manual Armv8, for Armv8-A architecture profile #[cfg(any( target_feature = "lse2", portable_atomic_target_feature = "lse2", not(portable_atomic_no_outline_atomics), ))] #[inline] unsafe fn _atomic_load_ldp(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_lse2!(); // SAFETY: the caller must guarantee that `dst` is valid for reads, // 16-byte aligned, that there are no concurrent non-atomic operations. // // Refs: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/LDP--Load-pair-of-registers- unsafe { let (out_lo, out_hi); macro_rules! atomic_load_relaxed { ($acquire:tt) => {{ asm!( "ldp {out_lo}, {out_hi}, [{src}]", $acquire, src = in(reg) ptr_reg!(src), out_hi = lateout(reg) out_hi, out_lo = lateout(reg) out_lo, options(nostack, preserves_flags), ); U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole }}; } match order { // if compile_time(FEAT_LRCPC3) && order != relaxed => ldiapp // SAFETY: cfg guarantee that the CPU supports FEAT_LRCPC3. #[cfg(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3"))] Ordering::Acquire | Ordering::SeqCst => _atomic_load_ldiapp(src, order), // else => ldp Ordering::Relaxed => atomic_load_relaxed!(""), #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] Ordering::Acquire => atomic_load_relaxed!("dmb ishld"), #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] Ordering::SeqCst => { asm!( // ldar (or dmb ishld) is required to prevent reordering with preceding stlxp. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108891 for details. "ldar {tmp}, [{src}]", "ldp {out_lo}, {out_hi}, [{src}]", "dmb ishld", src = in(reg) ptr_reg!(src), out_hi = lateout(reg) out_hi, out_lo = lateout(reg) out_lo, tmp = out(reg) _, options(nostack, preserves_flags), ); U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } _ => unreachable!(), } } } #[cfg(any( target_feature = "lse2", portable_atomic_target_feature = "lse2", not(portable_atomic_no_outline_atomics), ))] #[cfg(any( target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] #[inline] unsafe fn _atomic_load_ldiapp(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_lse2!(); debug_assert_rcpc3!(); // SAFETY: the caller must guarantee that `dst` is valid for reads, // 16-byte aligned, that there are no concurrent non-atomic operations. // // Refs: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/LDIAPP--Load-Acquire-RCpc-ordered-pair-of-registers- unsafe { let (out_lo, out_hi); match order { Ordering::Acquire => { #[cfg(not(portable_atomic_pre_llvm_16))] asm!( start_rcpc3!(), "ldiapp {out_lo}, {out_hi}, [{src}]", src = in(reg) ptr_reg!(src), out_hi = lateout(reg) out_hi, out_lo = lateout(reg) out_lo, options(nostack, preserves_flags), ); // LLVM supports FEAT_LRCPC3 instructions on LLVM 16+, so use .inst directive on old LLVM. // https://github.com/llvm/llvm-project/commit/a6aaa969f7caec58a994142f8d855861cf3a1463 #[cfg(portable_atomic_pre_llvm_16)] asm!( // ldiapp x0, x1, [x0] ".inst 0xd9411800", in("x0") ptr_reg!(src), lateout("x1") out_hi, lateout("x0") out_lo, options(nostack, preserves_flags), ); } Ordering::SeqCst => { #[cfg(not(portable_atomic_pre_llvm_16))] asm!( start_rcpc3!(), // ldar (or dmb ishld) is required to prevent reordering with preceding stlxp. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108891 for details. "ldar {tmp}, [{src}]", "ldiapp {out_lo}, {out_hi}, [{src}]", src = in(reg) ptr_reg!(src), out_hi = lateout(reg) out_hi, out_lo = lateout(reg) out_lo, tmp = out(reg) _, options(nostack, preserves_flags), ); // LLVM supports FEAT_LRCPC3 instructions on LLVM 16+, so use .inst directive on old LLVM. // https://github.com/llvm/llvm-project/commit/a6aaa969f7caec58a994142f8d855861cf3a1463 #[cfg(portable_atomic_pre_llvm_16)] asm!( // ldar (or dmb ishld) is required to prevent reordering with preceding stlxp. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108891 for details. "ldar {tmp}, [x0]", // ldiapp x0, x1, [x0] ".inst 0xd9411800", tmp = out(reg) _, in("x0") ptr_reg!(src), lateout("x1") out_hi, lateout("x0") out_lo, options(nostack, preserves_flags), ); } _ => unreachable!(), } U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } // Do not use _atomic_compare_exchange_casp because it needs extra MOV to implement load. #[cfg(any(test, not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2"))))] #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] #[inline] unsafe fn _atomic_load_casp(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_lse!(); // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { let (out_lo, out_hi); macro_rules! atomic_load { ($acquire:tt, $release:tt) => { asm!( start_lse!(), concat!("casp", $acquire, $release, " x2, x3, x2, x3, [{src}]"), src = in(reg) ptr_reg!(src), // must be allocated to even/odd register pair inout("x2") 0_u64 => out_lo, inout("x3") 0_u64 => out_hi, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => atomic_load!("", ""), Ordering::Acquire => atomic_load!("a", ""), Ordering::SeqCst => atomic_load!("a", "l"), _ => unreachable!(), } U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } #[cfg(any( test, all( not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), not(any(target_feature = "lse", portable_atomic_target_feature = "lse")), ), ))] #[inline] unsafe fn _atomic_load_ldxp_stxp(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let (mut out_lo, mut out_hi); macro_rules! atomic_load { ($acquire:tt, $release:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {out_lo}, {out_hi}, [{src}]"), concat!("st", $release, "xp {r:w}, {out_lo}, {out_hi}, [{src}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", src = in(reg) ptr_reg!(src), out_lo = out(reg) out_lo, out_hi = out(reg) out_hi, r = out(reg) _, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => atomic_load!("", ""), Ordering::Acquire => atomic_load!("a", ""), Ordering::SeqCst => atomic_load!("a", "l"), _ => unreachable!(), } U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } // ----------------------------------------------------------------------------- // store /* Instruction selection flow for store: - if compile_time(FEAT_LSE2) => stp: - if compile_time(FEAT_LSE128) && order == seqcst => swpp - if compile_time(FEAT_LRCPC3) && order != relaxed => stilp - if compile_time(FEAT_LSE128) && order != relaxed => swpp - else => stp - if platform_supports_detection_of(FEAT_LSE2): - if detect(FEAT_LSE2) && detect(FEAT_LSE128) && order == seqcst => lse128 (swpp) - if detect(FEAT_LSE2) && detect(FEAT_LRCPC3) && order != relaxed => lse2_rcpc3 (stilp) - if detect(FEAT_LSE2) && detect(FEAT_LSE128) && order != relaxed => lse128 (swpp) - if detect(FEAT_LSE2) => lse2 (stp) - else => no_lse2: - if compile_time(FEAT_LSE) && not(ll_sc_rmw) => casp - else => ldxp_stxp Note: - If FEAT_LSE2 is available at compile-time, we don't do run-time detection of FEAT_LRCPC3/FEAT_LSE128 at this time, since FEAT_LRCPC3/FEAT_LSE128 is not yet available for most CPUs. (macOS that doesn't have any FEAT_LRCPC3/FEAT_LSE128-enabled CPUs as of M4 is only a platform that currently enables FEAT_LSE2 at compile-time by default.) - If FEAT_LSE2 is not available at compile-time, we want to do run-time detection of FEAT_LSE2, so we do run-time detection of FEAT_LRCPC3/FEAT_LSE128 at the same time. - We don't do run-time detection of FEAT_LSE for store at this time. */ // if compile_time(FEAT_LSE2) => stp: // cfg guarantee that the CPU supports FEAT_LSE2. #[cfg(any(target_feature = "lse2", portable_atomic_target_feature = "lse2"))] use self::_atomic_store_stp as atomic_store; #[cfg(not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")))] #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { #[inline] unsafe fn atomic_store_no_lse2(dst: *mut u128, val: u128, order: Ordering) { // if compile_time(FEAT_LSE) && not(ll_sc_rmw) => casp // If FEAT_LSE is available at compile-time and portable_atomic_ll_sc_rmw cfg is not set, // we use CAS-based atomic RMW. #[cfg(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), ))] // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { _atomic_swap_casp(dst, val, order); } // else => ldxp_stxp #[cfg(not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )))] // SAFETY: the caller must uphold the safety contract. unsafe { _atomic_store_ldxp_stxp(dst, val, order); } } #[cfg(any( target_feature = "lse128", portable_atomic_target_feature = "lse128", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] #[inline] unsafe fn _atomic_store_swpp(dst: *mut u128, val: u128, order: Ordering) { // SAFETY: the caller must uphold the safety contract. unsafe { _atomic_swap_swpp(dst, val, order); } } // if platform_supports_detection_of(FEAT_LSE2): #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // windows, ), ))] { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128, val: u128); atomic_store_lse2_relaxed = _atomic_store_stp(Ordering::Relaxed); atomic_store_lse2_release = _atomic_store_stp(Ordering::Release); atomic_store_lse2_seqcst = _atomic_store_stp(Ordering::SeqCst); atomic_store_lse2_rcpc3_release = _atomic_store_stilp(Ordering::Release); atomic_store_lse2_rcpc3_seqcst = _atomic_store_stilp(Ordering::SeqCst); atomic_store_lse128_release = _atomic_store_swpp(Ordering::Release); atomic_store_lse128_seqcst = _atomic_store_swpp(Ordering::SeqCst); } fn_alias! { unsafe fn(dst: *mut u128, val: u128); atomic_store_no_lse2_relaxed = atomic_store_no_lse2(Ordering::Relaxed); atomic_store_no_lse2_release = atomic_store_no_lse2(Ordering::Release); atomic_store_no_lse2_seqcst = atomic_store_no_lse2(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // and we've checked if FEAT_LSE2/FEAT_LRCPC3/FEAT_LSE128 is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { // if detect(FEAT_LSE2) => lse2 (stp) atomic_store_lse2_relaxed } else { // else => no_lse2: atomic_store_no_lse2_relaxed } }); } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { if cpuinfo.has_rcpc3() { // if detect(FEAT_LSE2) && detect(FEAT_LRCPC3) && order != relaxed => lse2_rcpc3 (stilp) atomic_store_lse2_rcpc3_release } else if cpuinfo.has_lse128() { // if detect(FEAT_LSE2) && detect(FEAT_LSE128) && order != relaxed => lse128 (swpp) atomic_store_lse128_release } else { // if detect(FEAT_LSE2) => lse2 (stp) atomic_store_lse2_release } } else { // else => no_lse2: atomic_store_no_lse2_release } }); } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { if cpuinfo.has_lse128() { // if detect(FEAT_LSE2) && detect(FEAT_LSE128) && order == seqcst => lse128 (swpp) atomic_store_lse128_seqcst } else if cpuinfo.has_rcpc3() { // if detect(FEAT_LSE2) && detect(FEAT_LRCPC3) && order != relaxed => lse2_rcpc3 (stilp) atomic_store_lse2_rcpc3_seqcst } else { // if detect(FEAT_LSE2) => lse2 (stp) atomic_store_lse2_seqcst } } else { // else => no_lse2: atomic_store_no_lse2_seqcst } }); } _ => unreachable!(), } } } // else => no_lse2: #[cfg(not(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), // These don't support detection of FEAT_LSE2. // target_os = "fuchsia", // windows, ), )))] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_store_no_lse2(dst, val, order); } } // If CPU supports FEAT_LSE2, STP/STILP is single-copy atomic writes, // otherwise it is two single-copy atomic writes. // Refs: B2.2.1 of the Arm Architecture Reference Manual Armv8, for Armv8-A architecture profile #[cfg(any( target_feature = "lse2", portable_atomic_target_feature = "lse2", not(portable_atomic_no_outline_atomics), ))] #[inline] unsafe fn _atomic_store_stp(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); debug_assert_lse2!(); // SAFETY: the caller must guarantee that `dst` is valid for writes, // 16-byte aligned, that there are no concurrent non-atomic operations. // // Refs: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/STP--Store-pair-of-registers- unsafe { macro_rules! atomic_store { ($acquire:tt, $release:tt) => {{ let val = U128 { whole: val }; asm!( $release, "stp {val_lo}, {val_hi}, [{dst}]", $acquire, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, options(nostack, preserves_flags), ); }}; } match order { // if compile_time(FEAT_LSE128) && order == seqcst => swpp // Prefer swpp if stp requires fences. https://reviews.llvm.org/D143506 // SAFETY: cfg guarantee that the CPU supports FEAT_LSE128. #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] Ordering::SeqCst => { _atomic_swap_swpp(dst, val, order); } // if compile_time(FEAT_LRCPC3) && order != relaxed => stilp // SAFETY: cfg guarantee that the CPU supports FEAT_LRCPC3. #[cfg(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3"))] Ordering::Release => _atomic_store_stilp(dst, val, order), #[cfg(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3"))] #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] Ordering::SeqCst => _atomic_store_stilp(dst, val, order), // if compile_time(FEAT_LSE128) && order != relaxed => swpp // Prefer swpp if stp requires fences. https://reviews.llvm.org/D143506 // SAFETY: cfg guarantee that the CPU supports FEAT_LSE128. #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] Ordering::Release => { _atomic_swap_swpp(dst, val, order); } // else => stp Ordering::Relaxed => atomic_store!("", ""), #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] Ordering::Release => atomic_store!("", "dmb ish"), #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] Ordering::SeqCst => atomic_store!("dmb ish", "dmb ish"), _ => unreachable!(), } } } #[cfg(any( target_feature = "lse2", portable_atomic_target_feature = "lse2", not(portable_atomic_no_outline_atomics), ))] #[cfg(any( target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] #[inline] unsafe fn _atomic_store_stilp(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); debug_assert_lse2!(); debug_assert_rcpc3!(); // SAFETY: the caller must guarantee that `dst` is valid for writes, // 16-byte aligned, that there are no concurrent non-atomic operations. // // Refs: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/STILP--Store-release-ordered-pair-of-registers- unsafe { macro_rules! atomic_store { ($acquire:tt) => {{ let val = U128 { whole: val }; #[cfg(not(portable_atomic_pre_llvm_16))] asm!( start_rcpc3!(), "stilp {val_lo}, {val_hi}, [{dst}]", $acquire, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, options(nostack, preserves_flags), ); // LLVM supports FEAT_LRCPC3 instructions on LLVM 16+, so use .inst directive on old LLVM. // https://github.com/llvm/llvm-project/commit/a6aaa969f7caec58a994142f8d855861cf3a1463 #[cfg(portable_atomic_pre_llvm_16)] asm!( // stilp x2, x3, [x0] ".inst 0xd9031802", $acquire, in("x0") ptr_reg!(dst), in("x2") val.pair.lo, in("x3") val.pair.hi, options(nostack, preserves_flags), ); }}; } match order { Ordering::Release => atomic_store!(""), // LLVM uses store-release (dmb ish; stp); dmb ish, GCC (libatomic) // uses store-release (stilp) without fence for SeqCst store // (https://github.com/gcc-mirror/gcc/commit/7107574958e2bed11d916a1480ef1319f15e5ffe). // Considering https://reviews.llvm.org/D141748, LLVM's lowing seems // to be the safer option here (I'm not convinced that the libatomic's implementation is wrong). Ordering::SeqCst => atomic_store!("dmb ish"), _ => unreachable!(), } } } // Do not use _atomic_swap_ldxp_stxp because it needs extra registers to implement store. #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )) ))] #[inline] unsafe fn _atomic_store_ldxp_stxp(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; macro_rules! store { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp xzr, {tmp}, [{dst}]"), concat!("st", $release, "xp {tmp:w}, {val_lo}, {val_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {tmp:w}, 2b", $fence, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, tmp = out(reg) _, options(nostack, preserves_flags), ) }; } atomic_rmw!(store, order); } } // ----------------------------------------------------------------------------- // compare_exchange /* Instruction selection flow for compare_exchange: - if compile_time(FEAT_LSE) => casp - if platform_supports_detection_of(FEAT_LSE): - if detect(FEAT_LSE) => casp - else => ldxp_stxp */ #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { // if compile_time(FEAT_LSE) => casp #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. let prev = unsafe { _atomic_compare_exchange_casp(dst, old, new, success, failure) }; // if platform_supports_detection_of(FEAT_LSE): #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), target_os = "fuchsia", windows, ), ))] #[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))] let prev = { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128; atomic_compare_exchange_casp_relaxed = _atomic_compare_exchange_casp(Ordering::Relaxed, Ordering::Relaxed); atomic_compare_exchange_casp_acquire = _atomic_compare_exchange_casp(Ordering::Acquire, Ordering::Acquire); atomic_compare_exchange_casp_release = _atomic_compare_exchange_casp(Ordering::Release, Ordering::Relaxed); atomic_compare_exchange_casp_acqrel = _atomic_compare_exchange_casp(Ordering::AcqRel, Ordering::Acquire); // AcqRel and SeqCst RMWs are equivalent in non-MSVC environments. #[cfg(target_env = "msvc")] atomic_compare_exchange_casp_seqcst = _atomic_compare_exchange_casp(Ordering::SeqCst, Ordering::SeqCst); } fn_alias! { unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128; atomic_compare_exchange_ldxp_stxp_relaxed = _atomic_compare_exchange_ldxp_stxp(Ordering::Relaxed, Ordering::Relaxed); atomic_compare_exchange_ldxp_stxp_acquire = _atomic_compare_exchange_ldxp_stxp(Ordering::Acquire, Ordering::Acquire); atomic_compare_exchange_ldxp_stxp_release = _atomic_compare_exchange_ldxp_stxp(Ordering::Release, Ordering::Relaxed); atomic_compare_exchange_ldxp_stxp_acqrel = _atomic_compare_exchange_ldxp_stxp(Ordering::AcqRel, Ordering::Acquire); // AcqRel and SeqCst RMWs are equivalent in non-MSVC environments. #[cfg(target_env = "msvc")] atomic_compare_exchange_ldxp_stxp_seqcst = _atomic_compare_exchange_ldxp_stxp(Ordering::SeqCst, Ordering::SeqCst); } // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and we've checked if FEAT_LSE is available. unsafe { let success = crate::utils::upgrade_success_ordering(success, failure); match success { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { // if detect(FEAT_LSE) => casp atomic_compare_exchange_casp_relaxed } else { // else => ldxp_stxp atomic_compare_exchange_ldxp_stxp_relaxed } }) } Ordering::Acquire => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { // if detect(FEAT_LSE) => casp atomic_compare_exchange_casp_acquire } else { // else => ldxp_stxp atomic_compare_exchange_ldxp_stxp_acquire } }) } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { // if detect(FEAT_LSE) => casp atomic_compare_exchange_casp_release } else { // else => ldxp_stxp atomic_compare_exchange_ldxp_stxp_release } }) } // AcqRel and SeqCst RMWs are equivalent in both implementations in non-MSVC environments. #[cfg(not(target_env = "msvc"))] Ordering::AcqRel | Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { // if detect(FEAT_LSE) => casp atomic_compare_exchange_casp_acqrel } else { // else => ldxp_stxp atomic_compare_exchange_ldxp_stxp_acqrel } }) } #[cfg(target_env = "msvc")] Ordering::AcqRel => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { // if detect(FEAT_LSE) => casp atomic_compare_exchange_casp_acqrel } else { // else => ldxp_stxp atomic_compare_exchange_ldxp_stxp_acqrel } }) } #[cfg(target_env = "msvc")] Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { // if detect(FEAT_LSE) => casp atomic_compare_exchange_casp_seqcst } else { // else => ldxp_stxp atomic_compare_exchange_ldxp_stxp_seqcst } }) } _ => unreachable!(), } } }; // else => ldxp_stxp #[cfg(not(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", all(target_os = "illumos", portable_atomic_outline_atomics), target_os = "fuchsia", windows, ), )))] #[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))] // SAFETY: the caller must uphold the safety contract. let prev = unsafe { _atomic_compare_exchange_ldxp_stxp(dst, old, new, success, failure) }; if prev == old { Ok(prev) } else { Err(prev) } } #[cfg(any( target_feature = "lse", portable_atomic_target_feature = "lse", not(portable_atomic_no_outline_atomics), ))] #[inline] unsafe fn _atomic_compare_exchange_casp( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse!(); let order = crate::utils::upgrade_success_ordering(success, failure); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and the CPU supports FEAT_LSE. // // Refs: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/CASP--CASPA--CASPAL--CASPL--Compare-and-swap-pair-of-words-or-doublewords-in-memory- unsafe { let old = U128 { whole: old }; let new = U128 { whole: new }; let (prev_lo, prev_hi); macro_rules! cmpxchg { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse!(), concat!("casp", $acquire, $release, " x6, x7, x4, x5, [{dst}]"), $fence, dst = in(reg) ptr_reg!(dst), // must be allocated to even/odd register pair inout("x6") old.pair.lo => prev_lo, inout("x7") old.pair.hi => prev_hi, // must be allocated to even/odd register pair in("x4") new.pair.lo, in("x5") new.pair.hi, options(nostack, preserves_flags), ) }; } atomic_rmw!(cmpxchg, order, write = success); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } #[cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse"))))] #[inline] unsafe fn _atomic_compare_exchange_ldxp_stxp( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> u128 { debug_assert!(dst as usize % 16 == 0); let order = crate::utils::upgrade_success_ordering(success, failure); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // // Refs: // - LDXP: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/LDXP--Load-exclusive-pair-of-registers- // - LDAXP: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/LDAXP--Load-acquire-exclusive-pair-of-registers- // - STXP: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/STXP--Store-exclusive-pair-of-registers- // - STLXP: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/STLXP--Store-release-exclusive-pair-of-registers- // // Note: Load-Exclusive pair (by itself) does not guarantee atomicity; to complete an atomic // operation (even load/store), a corresponding Store-Exclusive pair must succeed. // See Arm Architecture Reference Manual for A-profile architecture // Section B2.2.1 "Requirements for single-copy atomicity", and // Section B2.9 "Synchronization and semaphores" for more. unsafe { let old = U128 { whole: old }; let new = U128 { whole: new }; let (mut prev_lo, mut prev_hi); macro_rules! cmpxchg { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {prev_lo}, {prev_hi}, [{dst}]"), "cmp {prev_lo}, {old_lo}", "cset {r:w}, ne", "cmp {prev_hi}, {old_hi}", "cinc {r:w}, {r:w}, ne", "cbz {r:w}, 3f", concat!("st", $release, "xp {r:w}, {prev_lo}, {prev_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", "b 4f", "3:", concat!("st", $release, "xp {r:w}, {new_lo}, {new_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", "4:", $fence, dst = in(reg) ptr_reg!(dst), old_lo = in(reg) old.pair.lo, old_hi = in(reg) old.pair.hi, new_lo = in(reg) new.pair.lo, new_hi = in(reg) new.pair.hi, prev_lo = out(reg) prev_lo, prev_hi = out(reg) prev_hi, r = out(reg) _, // Do not use `preserves_flags` because CMP modifies the condition flags. options(nostack), ) }; } atomic_rmw!(cmpxchg, order, write = success); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } // casp is always strong, and ldxp requires a corresponding (succeed) stxp for // its atomicity (see code comment in _atomic_compare_exchange_ldxp_stxp). // (i.e., AArch64 doesn't have 128-bit weak CAS) use self::atomic_compare_exchange as atomic_compare_exchange_weak; // ----------------------------------------------------------------------------- // RMW /* Instruction selection flow for swap/fetch_and/fetch_or: - if compile_time(FEAT_LSE128) => swpp/ldclrp/ldsetp - if compile_time(FEAT_LSE) && not(ll_sc_rmw) => casp - else => ldxp_stxp Instruction selection flow for other RMWs: - if compile_time(FEAT_LSE) && not(ll_sc_rmw) => casp - else => ldxp_stxp Note: - We don't do run-time detection of FEAT_LSE128 at this time, because FEAT_LSE128 is not yet available for most CPUs, but since swpp/ldclrp/ldsetp is wait-free, it would make sense to do run-time detection in the future. (TODO) - We don't do run-time detection of FEAT_LSE for store at this time. */ // If FEAT_LSE is available at compile-time and portable_atomic_ll_sc_rmw cfg is not set, // we use CAS-based atomic RMW. #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] #[cfg(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), ))] use self::_atomic_swap_casp as atomic_swap; #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] #[cfg(not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )))] use self::_atomic_swap_ldxp_stxp as atomic_swap; #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] use self::_atomic_swap_swpp as atomic_swap; #[cfg(any( target_feature = "lse128", portable_atomic_target_feature = "lse128", all( not(portable_atomic_no_outline_atomics), not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ), ))] #[inline] unsafe fn _atomic_swap_swpp(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse128!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and the CPU supports FEAT_LSE128. // // Refs: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/SWPP--SWPPA--SWPPAL--SWPPL--Swap-quadword-in-memory- unsafe { let val = U128 { whole: val }; let (prev_lo, prev_hi); #[cfg(not(portable_atomic_pre_llvm_16))] macro_rules! swap { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse128!(), concat!("swpp", $acquire, $release, " {val_lo}, {val_hi}, [{dst}]"), $fence, dst = in(reg) ptr_reg!(dst), val_lo = inout(reg) val.pair.lo => prev_lo, val_hi = inout(reg) val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } #[cfg(not(portable_atomic_pre_llvm_16))] atomic_rmw!(swap, order); // LLVM supports FEAT_LSE128 instructions on LLVM 16+, so use .inst directive on old LLVM. // https://github.com/llvm/llvm-project/commit/7fea6f2e0e606e5339c3359568f680eaf64aa306 #[cfg(portable_atomic_pre_llvm_16)] macro_rules! swap { ($order:tt, $fence:tt) => { asm!( // swpp{,a,l,al} x2, x1, [x0] concat!(".inst 0x19", $order, "18002"), $fence, in("x0") ptr_reg!(dst), inout("x2") val.pair.lo => prev_lo, inout("x1") val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } #[cfg(portable_atomic_pre_llvm_16)] atomic_rmw_inst!(swap, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } // Do not use atomic_rmw_cas_3 because it needs extra MOV to implement swap. #[cfg(any(test, not(portable_atomic_ll_sc_rmw)))] #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] #[inline] unsafe fn _atomic_swap_casp(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse!(); // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! swap { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse!(), // If FEAT_LSE2 is not supported, this works like byte-wise atomic. // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. "ldp x4, x5, [{dst}]", "2:", // casp writes the current value to the first register pair, // so copy the `out`'s value for later comparison. "mov {tmp_lo}, x4", "mov {tmp_hi}, x5", concat!("casp", $acquire, $release, " x4, x5, x2, x3, [{dst}]"), "cmp {tmp_hi}, x5", "ccmp {tmp_lo}, x4, #0, eq", "b.ne 2b", $fence, dst = in(reg) ptr_reg!(dst), tmp_lo = out(reg) _, tmp_hi = out(reg) _, // must be allocated to even/odd register pair out("x4") prev_lo, out("x5") prev_hi, // must be allocated to even/odd register pair in("x2") val.pair.lo, in("x3") val.pair.hi, // Do not use `preserves_flags` because CMP and CCMP modify the condition flags. options(nostack), ) }; } atomic_rmw!(swap, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } // Do not use atomic_rmw_ll_sc_3 because it needs extra MOV to implement swap. #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )) ))] #[inline] unsafe fn _atomic_swap_ldxp_stxp(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! swap { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {prev_lo}, {prev_hi}, [{dst}]"), concat!("st", $release, "xp {r:w}, {val_lo}, {val_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", $fence, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, prev_lo = out(reg) prev_lo, prev_hi = out(reg) prev_hi, r = out(reg) _, options(nostack, preserves_flags), ) }; } atomic_rmw!(swap, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } /// Atomic RMW by LL/SC loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - val_lo/val_hi pair: val argument (read-only for `$op`) /// - prev_lo/prev_hi pair: previous value loaded by ll (read-only for `$op`) /// - new_lo/new_hi pair: new value that will be stored by sc macro_rules! atomic_rmw_ll_sc_3 { ($name:ident as $reexport_name:ident $(($preserves_flags:tt))?, $($op:tt)*) => { // If FEAT_LSE is available at compile-time and portable_atomic_ll_sc_rmw cfg is not set, // we use CAS-based atomic RMW generated by atomic_rmw_cas_3! macro instead. #[cfg(not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )))] use self::$name as $reexport_name; #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )) ))] #[inline] unsafe fn $name(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! op { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {prev_lo}, {prev_hi}, [{dst}]"), $($op)* concat!("st", $release, "xp {r:w}, {new_lo}, {new_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", $fence, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, prev_lo = out(reg) prev_lo, prev_hi = out(reg) prev_hi, new_lo = out(reg) _, new_hi = out(reg) _, r = out(reg) _, options(nostack $(, $preserves_flags)?), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } /// Atomic RMW by CAS loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - val_lo/val_hi pair: val argument (read-only for `$op`) /// - x6/x7 pair: previous value loaded (read-only for `$op`) /// - x4/x5 pair: new value that will be stored macro_rules! atomic_rmw_cas_3 { ($name:ident as $reexport_name:ident, $($op:tt)*) => { // If FEAT_LSE is not available at compile-time or portable_atomic_ll_sc_rmw cfg is set, // we use LL/SC-based atomic RMW generated by atomic_rmw_ll_sc_3! macro instead. #[cfg(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), ))] use self::$name as $reexport_name; #[cfg(any(test, not(portable_atomic_ll_sc_rmw)))] #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] #[inline] unsafe fn $name(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse!(); // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! op { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse!(), // If FEAT_LSE2 is not supported, this works like byte-wise atomic. // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. "ldp x6, x7, [{dst}]", "2:", // casp writes the current value to the first register pair, // so copy the `out`'s value for later comparison. "mov {tmp_lo}, x6", "mov {tmp_hi}, x7", $($op)* concat!("casp", $acquire, $release, " x6, x7, x4, x5, [{dst}]"), "cmp {tmp_hi}, x7", "ccmp {tmp_lo}, x6, #0, eq", "b.ne 2b", $fence, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, tmp_lo = out(reg) _, tmp_hi = out(reg) _, // must be allocated to even/odd register pair out("x6") prev_lo, out("x7") prev_hi, // must be allocated to even/odd register pair out("x4") _, out("x5") _, // Do not use `preserves_flags` because CMP and CCMP modify the condition flags. options(nostack), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } /// Atomic RMW by LL/SC loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - prev_lo/prev_hi pair: previous value loaded by ll (read-only for `$op`) /// - new_lo/new_hi pair: new value that will be stored by sc macro_rules! atomic_rmw_ll_sc_2 { ($name:ident as $reexport_name:ident $(($preserves_flags:tt))?, $($op:tt)*) => { // If FEAT_LSE is available at compile-time and portable_atomic_ll_sc_rmw cfg is not set, // we use CAS-based atomic RMW generated by atomic_rmw_cas_2! macro instead. #[cfg(not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )))] use self::$name as $reexport_name; #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )) ))] #[inline] unsafe fn $name(dst: *mut u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let (mut prev_lo, mut prev_hi); macro_rules! op { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {prev_lo}, {prev_hi}, [{dst}]"), $($op)* concat!("st", $release, "xp {r:w}, {new_lo}, {new_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", $fence, dst = in(reg) ptr_reg!(dst), prev_lo = out(reg) prev_lo, prev_hi = out(reg) prev_hi, new_lo = out(reg) _, new_hi = out(reg) _, r = out(reg) _, options(nostack $(, $preserves_flags)?), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } /// Atomic RMW by CAS loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - x6/x7 pair: previous value loaded (read-only for `$op`) /// - x4/x5 pair: new value that will be stored macro_rules! atomic_rmw_cas_2 { ($name:ident as $reexport_name:ident, $($op:tt)*) => { // If FEAT_LSE is not available at compile-time or portable_atomic_ll_sc_rmw cfg is set, // we use LL/SC-based atomic RMW generated by atomic_rmw_ll_sc_3! macro instead. #[cfg(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), ))] use self::$name as $reexport_name; #[cfg(any(test, not(portable_atomic_ll_sc_rmw)))] #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] #[inline] unsafe fn $name(dst: *mut u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse!(); // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { let (mut prev_lo, mut prev_hi); macro_rules! op { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse!(), // If FEAT_LSE2 is not supported, this works like byte-wise atomic. // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. "ldp x6, x7, [{dst}]", "2:", // casp writes the current value to the first register pair, // so copy the `out`'s value for later comparison. "mov {tmp_lo}, x6", "mov {tmp_hi}, x7", $($op)* concat!("casp", $acquire, $release, " x6, x7, x4, x5, [{dst}]"), "cmp {tmp_hi}, x7", "ccmp {tmp_lo}, x6, #0, eq", "b.ne 2b", $fence, dst = in(reg) ptr_reg!(dst), tmp_lo = out(reg) _, tmp_hi = out(reg) _, // must be allocated to even/odd register pair out("x6") prev_lo, out("x7") prev_hi, // must be allocated to even/odd register pair out("x4") _, out("x5") _, // Do not use `preserves_flags` because CMP and CCMP modify the condition flags. options(nostack), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } // Do not use `preserves_flags` because ADDS modifies the condition flags. atomic_rmw_ll_sc_3! { _atomic_add_ldxp_stxp as atomic_add, select_le_or_be!("adds {new_lo}, {prev_lo}, {val_lo}", "adds {new_hi}, {prev_hi}, {val_hi}"), select_le_or_be!("adc {new_hi}, {prev_hi}, {val_hi}", "adc {new_lo}, {prev_lo}, {val_lo}"), } atomic_rmw_cas_3! { _atomic_add_casp as atomic_add, select_le_or_be!("adds x4, x6, {val_lo}", "adds x5, x7, {val_hi}"), select_le_or_be!("adc x5, x7, {val_hi}", "adc x4, x6, {val_lo}"), } // Do not use `preserves_flags` because SUBS modifies the condition flags. atomic_rmw_ll_sc_3! { _atomic_sub_ldxp_stxp as atomic_sub, select_le_or_be!("subs {new_lo}, {prev_lo}, {val_lo}", "subs {new_hi}, {prev_hi}, {val_hi}"), select_le_or_be!("sbc {new_hi}, {prev_hi}, {val_hi}", "sbc {new_lo}, {prev_lo}, {val_lo}"), } atomic_rmw_cas_3! { _atomic_sub_casp as atomic_sub, select_le_or_be!("subs x4, x6, {val_lo}", "subs x5, x7, {val_hi}"), select_le_or_be!("sbc x5, x7, {val_hi}", "sbc x4, x6, {val_lo}"), } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] atomic_rmw_ll_sc_3! { _atomic_and_ldxp_stxp as atomic_and (preserves_flags), "and {new_lo}, {prev_lo}, {val_lo}", "and {new_hi}, {prev_hi}, {val_hi}", } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] atomic_rmw_cas_3! { _atomic_and_casp as atomic_and, "and x4, x6, {val_lo}", "and x5, x7, {val_hi}", } #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] #[inline] unsafe fn atomic_and(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and the CPU supports FEAT_LSE128. // // Refs: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/LDCLRP--LDCLRPA--LDCLRPAL--LDCLRPL--Atomic-bit-clear-on-quadword-in-memory- unsafe { let val = U128 { whole: !val }; let (prev_lo, prev_hi); #[cfg(not(portable_atomic_pre_llvm_16))] macro_rules! clear { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse128!(), concat!("ldclrp", $acquire, $release, " {val_lo}, {val_hi}, [{dst}]"), $fence, dst = in(reg) ptr_reg!(dst), val_lo = inout(reg) val.pair.lo => prev_lo, val_hi = inout(reg) val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } #[cfg(not(portable_atomic_pre_llvm_16))] atomic_rmw!(clear, order); // LLVM supports FEAT_LSE128 instructions on LLVM 16+, so use .inst directive on old LLVM. // https://github.com/llvm/llvm-project/commit/7fea6f2e0e606e5339c3359568f680eaf64aa306 #[cfg(portable_atomic_pre_llvm_16)] macro_rules! clear { ($order:tt, $fence:tt) => { asm!( // ldclrp{,a,l,al} x8, x1, [x0] concat!(".inst 0x19", $order, "11008"), $fence, in("x0") ptr_reg!(dst), inout("x8") val.pair.lo => prev_lo, inout("x1") val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } #[cfg(portable_atomic_pre_llvm_16)] atomic_rmw_inst!(clear, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } atomic_rmw_ll_sc_3! { _atomic_nand_ldxp_stxp as atomic_nand (preserves_flags), "and {new_lo}, {prev_lo}, {val_lo}", "and {new_hi}, {prev_hi}, {val_hi}", "mvn {new_lo}, {new_lo}", "mvn {new_hi}, {new_hi}", } atomic_rmw_cas_3! { _atomic_nand_casp as atomic_nand, "and x4, x6, {val_lo}", "and x5, x7, {val_hi}", "mvn x4, x4", "mvn x5, x5", } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] atomic_rmw_ll_sc_3! { _atomic_or_ldxp_stxp as atomic_or (preserves_flags), "orr {new_lo}, {prev_lo}, {val_lo}", "orr {new_hi}, {prev_hi}, {val_hi}", } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] atomic_rmw_cas_3! { _atomic_or_casp as atomic_or, "orr x4, x6, {val_lo}", "orr x5, x7, {val_hi}", } #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] #[inline] unsafe fn atomic_or(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and the CPU supports FEAT_LSE128. // // Refs: https://developer.arm.com/documentation/ddi0602/2024-12/Base-Instructions/LDSETP--LDSETPA--LDSETPAL--LDSETPL--Atomic-bit-set-on-quadword-in-memory- unsafe { let val = U128 { whole: val }; let (prev_lo, prev_hi); #[cfg(not(portable_atomic_pre_llvm_16))] macro_rules! or { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse128!(), concat!("ldsetp", $acquire, $release, " {val_lo}, {val_hi}, [{dst}]"), $fence, dst = in(reg) ptr_reg!(dst), val_lo = inout(reg) val.pair.lo => prev_lo, val_hi = inout(reg) val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } #[cfg(not(portable_atomic_pre_llvm_16))] atomic_rmw!(or, order); // LLVM supports FEAT_LSE128 instructions on LLVM 16+, so use .inst directive on old LLVM. // https://github.com/llvm/llvm-project/commit/7fea6f2e0e606e5339c3359568f680eaf64aa306 #[cfg(portable_atomic_pre_llvm_16)] macro_rules! or { ($order:tt, $fence:tt) => { asm!( // ldsetp{,a,l,al} x2, x1, [x0] concat!(".inst 0x19", $order, "13002"), $fence, in("x0") ptr_reg!(dst), inout("x2") val.pair.lo => prev_lo, inout("x1") val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } #[cfg(portable_atomic_pre_llvm_16)] atomic_rmw_inst!(or, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } atomic_rmw_ll_sc_3! { _atomic_xor_ldxp_stxp as atomic_xor (preserves_flags), "eor {new_lo}, {prev_lo}, {val_lo}", "eor {new_hi}, {prev_hi}, {val_hi}", } atomic_rmw_cas_3! { _atomic_xor_casp as atomic_xor, "eor x4, x6, {val_lo}", "eor x5, x7, {val_hi}", } atomic_rmw_ll_sc_2! { _atomic_not_ldxp_stxp as atomic_not (preserves_flags), "mvn {new_lo}, {prev_lo}", "mvn {new_hi}, {prev_hi}", } atomic_rmw_cas_2! { _atomic_not_casp as atomic_not, "mvn x4, x6", "mvn x5, x7", } // Do not use `preserves_flags` because NEGS modifies the condition flags. atomic_rmw_ll_sc_2! { _atomic_neg_ldxp_stxp as atomic_neg, select_le_or_be!("negs {new_lo}, {prev_lo}", "negs {new_hi}, {prev_hi}"), select_le_or_be!("ngc {new_hi}, {prev_hi}", "ngc {new_lo}, {prev_lo}"), } atomic_rmw_cas_2! { _atomic_neg_casp as atomic_neg, select_le_or_be!("negs x4, x6", "negs x5, x7"), select_le_or_be!("ngc x5, x7", "ngc x4, x6"), } // Do not use `preserves_flags` because CMP and SBCS modify the condition flags. atomic_rmw_ll_sc_3! { _atomic_max_ldxp_stxp as atomic_max, select_le_or_be!("cmp {val_lo}, {prev_lo}", "cmp {val_hi}, {prev_hi}"), select_le_or_be!("sbcs xzr, {val_hi}, {prev_hi}", "sbcs xzr, {val_lo}, {prev_lo}"), "csel {new_hi}, {prev_hi}, {val_hi}, lt", // select hi 64-bit "csel {new_lo}, {prev_lo}, {val_lo}, lt", // select lo 64-bit } atomic_rmw_cas_3! { _atomic_max_casp as atomic_max, select_le_or_be!("cmp {val_lo}, x6", "cmp {val_hi}, x7"), select_le_or_be!("sbcs xzr, {val_hi}, x7", "sbcs xzr, {val_lo}, x6"), "csel x5, x7, {val_hi}, lt", // select hi 64-bit "csel x4, x6, {val_lo}, lt", // select lo 64-bit } // Do not use `preserves_flags` because CMP and SBCS modify the condition flags. atomic_rmw_ll_sc_3! { _atomic_umax_ldxp_stxp as atomic_umax, select_le_or_be!("cmp {val_lo}, {prev_lo}", "cmp {val_hi}, {prev_hi}"), select_le_or_be!("sbcs xzr, {val_hi}, {prev_hi}", "sbcs xzr, {val_lo}, {prev_lo}"), "csel {new_hi}, {prev_hi}, {val_hi}, lo", // select hi 64-bit "csel {new_lo}, {prev_lo}, {val_lo}, lo", // select lo 64-bit } atomic_rmw_cas_3! { _atomic_umax_casp as atomic_umax, select_le_or_be!("cmp {val_lo}, x6", "cmp {val_hi}, x7"), select_le_or_be!("sbcs xzr, {val_hi}, x7", "sbcs xzr, {val_lo}, x6"), "csel x5, x7, {val_hi}, lo", // select hi 64-bit "csel x4, x6, {val_lo}, lo", // select lo 64-bit } // Do not use `preserves_flags` because CMP and SBCS modify the condition flags. atomic_rmw_ll_sc_3! { _atomic_min_ldxp_stxp as atomic_min, select_le_or_be!("cmp {val_lo}, {prev_lo}", "cmp {val_hi}, {prev_hi}"), select_le_or_be!("sbcs xzr, {val_hi}, {prev_hi}", "sbcs xzr, {val_lo}, {prev_lo}"), "csel {new_hi}, {prev_hi}, {val_hi}, ge", // select hi 64-bit "csel {new_lo}, {prev_lo}, {val_lo}, ge", // select lo 64-bit } atomic_rmw_cas_3! { _atomic_min_casp as atomic_min, select_le_or_be!("cmp {val_lo}, x6", "cmp {val_hi}, x7"), select_le_or_be!("sbcs xzr, {val_hi}, x7", "sbcs xzr, {val_lo}, x6"), "csel x5, x7, {val_hi}, ge", // select hi 64-bit "csel x4, x6, {val_lo}, ge", // select lo 64-bit } // Do not use `preserves_flags` because CMP and SBCS modify the condition flags. atomic_rmw_ll_sc_3! { _atomic_umin_ldxp_stxp as atomic_umin, select_le_or_be!("cmp {val_lo}, {prev_lo}", "cmp {val_hi}, {prev_hi}"), select_le_or_be!("sbcs xzr, {val_hi}, {prev_hi}", "sbcs xzr, {val_lo}, {prev_lo}"), "csel {new_hi}, {prev_hi}, {val_hi}, hs", // select hi 64-bit "csel {new_lo}, {prev_lo}, {val_lo}, hs", // select lo 64-bit } atomic_rmw_cas_3! { _atomic_umin_casp as atomic_umin, select_le_or_be!("cmp {val_lo}, x6", "cmp {val_hi}, x7"), select_le_or_be!("sbcs xzr, {val_hi}, x7", "sbcs xzr, {val_lo}, x6"), "csel x5, x7, {val_hi}, hs", // select hi 64-bit "csel x4, x6, {val_lo}, hs", // select lo 64-bit } #[inline] const fn is_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } const IS_ALWAYS_LOCK_FREE: bool = true; atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/fallback/0000775000175000017500000000000015105742312016601 5ustar bdrungbdrungportable-atomic/src/imp/fallback/mod.rs0000644000175000017500000004320315105742312017726 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Fallback implementation using global locks. This implementation uses seqlock for global locks. This is basically based on global locks in crossbeam-utils's `AtomicCell`, but seqlock is implemented in a way that does not depend on UB (see comments in optimistic_read method in atomic! macro for details). Note that we cannot use a lock per atomic type, since the in-memory representation of the atomic type and the value type must be the same. */ #![cfg_attr( any( all( target_arch = "x86_64", not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), all( target_arch = "powerpc64", feature = "fallback", not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( all( target_env = "gnu", any(target_endian = "little", not(target_feature = "crt-static")), ), all( any(target_env = "musl", target_env = "ohos", target_env = "uclibc"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "openbsd", all( target_os = "aix", not(portable_atomic_pre_llvm_20), portable_atomic_outline_atomics, // TODO(aix): currently disabled by default ), ), not(any(miri, portable_atomic_sanitize_thread)), ), all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "zacas", portable_atomic_target_feature = "zacas", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(target_os = "linux", target_os = "android"), ), ), ), all( target_arch = "riscv64", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "zacas", portable_atomic_target_feature = "zacas", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(target_os = "linux", target_os = "android"), ), ), ), all( target_arch = "arm", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_os = "linux", target_os = "android"), not(portable_atomic_no_outline_atomics), ), ), allow(dead_code) )] #[macro_use] pub(crate) mod utils; // Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap // around. // // In narrow architectures (pointer width <= 16), the counter is still <= 32-bit and may be // vulnerable to wrap around. But it's mostly okay, since in such a primitive hardware, the // counter will not be increased that fast. // // Some 64-bit architectures have ABI with 32-bit pointer width (e.g., x86_64 X32 ABI, // AArch64 ILP32 ABI, mips64 N32 ABI). On those targets, AtomicU64 is available and fast, // so use it to implement normal sequence lock. cfg_has_fast_atomic_64! { mod seq_lock; } cfg_no_fast_atomic_64! { #[path = "seq_lock_wide.rs"] mod seq_lock; } use core::{cell::UnsafeCell, mem, sync::atomic::Ordering}; use self::{ seq_lock::{SeqLock, SeqLockWriteGuard}, utils::CachePadded, }; #[cfg(portable_atomic_no_strict_provenance)] use crate::utils::ptr::PtrExt as _; // Some 64-bit architectures have ABI with 32-bit pointer width (e.g., x86_64 X32 ABI, // AArch64 ILP32 ABI, mips64 N32 ABI). On those targets, AtomicU64 is fast, // so use it to reduce chunks of byte-wise atomic memcpy. use self::seq_lock::{AtomicChunk, Chunk}; // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/atomic/atomic_cell.rs#L969-L1016. #[inline] #[must_use] fn lock(addr: usize) -> &'static SeqLock { // The number of locks is a prime number because we want to make sure `addr % LEN` gets // dispersed across all locks. // // crossbeam-utils 0.8.7 uses 97 here but does not use CachePadded, // so the actual concurrency level will be smaller. const LEN: usize = 67; const L: CachePadded = CachePadded::new(SeqLock::new()); static LOCKS: [CachePadded; LEN] = [ L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, ]; // If the modulus is a constant number, the compiler will use crazy math to transform this into // a sequence of cheap arithmetic operations rather than using the slow modulo instruction. &LOCKS[addr % LEN] } macro_rules! atomic { ($atomic_type:ident, $int_type:ident, $align:literal) => { #[repr(C, align($align))] pub(crate) struct $atomic_type { v: UnsafeCell<$int_type>, } impl $atomic_type { const LEN: usize = mem::size_of::<$int_type>() / mem::size_of::(); #[inline] unsafe fn chunks(&self) -> &[AtomicChunk; Self::LEN] { static_assert!($atomic_type::LEN > 1); static_assert!(mem::size_of::<$int_type>() % mem::size_of::() == 0); // SAFETY: the caller must uphold the safety contract for `chunks`. unsafe { &*(self.v.get() as *const $int_type as *const [AtomicChunk; Self::LEN]) } } #[inline] fn optimistic_read(&self) -> $int_type { // Using `MaybeUninit<[usize; Self::LEN]>` here doesn't change codegen: https://godbolt.org/z/86f8s733M let mut dst: [Chunk; Self::LEN] = [0; Self::LEN]; // SAFETY: // - There are no threads that perform non-atomic concurrent write operations. // - There is no writer that updates the value using atomic operations of different granularity. // // If the atomic operation is not used here, it will cause a data race // when `write` performs concurrent write operation. // Such a data race is sometimes considered virtually unproblematic // in SeqLock implementations: // // - https://github.com/Amanieu/seqlock/issues/2 // - https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/atomic/atomic_cell.rs#L1111-L1116 // - https://rust-lang.zulipchat.com/#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/avoiding.20UB.20due.20to.20races.20by.20discarding.20result.3F // // However, in our use case, the implementation that loads/stores value as // chunks of usize is enough fast and sound, so we use that implementation. // // See also atomic-memcpy crate, a generic implementation of this pattern: // https://github.com/taiki-e/atomic-memcpy let chunks = unsafe { self.chunks() }; for i in 0..Self::LEN { dst[i] = chunks[i].load(Ordering::Relaxed); } // SAFETY: integers are plain old data types so we can always transmute to them. unsafe { mem::transmute::<[Chunk; Self::LEN], $int_type>(dst) } } #[inline] fn read(&self, _guard: &SeqLockWriteGuard<'static>) -> $int_type { // This calls optimistic_read that can return teared value, but the resulting value // is guaranteed not to be teared because we hold the lock to write. self.optimistic_read() } #[inline] fn write(&self, val: $int_type, _guard: &SeqLockWriteGuard<'static>) { // SAFETY: integers are plain old data types so we can always transmute them to arrays of integers. let val = unsafe { mem::transmute::<$int_type, [Chunk; Self::LEN]>(val) }; // SAFETY: // - The guard guarantees that we hold the lock to write. // - There are no threads that perform non-atomic concurrent read or write operations. // // See optimistic_read for the reason that atomic operations are used here. let chunks = unsafe { self.chunks() }; for i in 0..Self::LEN { chunks[i].store(val[i], Ordering::Relaxed); } } } // Send is implicitly implemented. // SAFETY: any data races are prevented by the lock and atomic operation. unsafe impl Sync for $atomic_type {} impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::IS_ALWAYS_LOCK_FREE } pub(crate) const IS_ALWAYS_LOCK_FREE: bool = false; #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); let lock = lock(self.v.get().addr()); // Try doing an optimistic read first. if let Some(stamp) = lock.optimistic_read() { let val = self.optimistic_read(); if lock.validate_read(stamp) { return val; } } // Grab a regular write lock so that writers don't starve this load. let guard = lock.write(); let val = self.read(&guard); // The value hasn't been changed. Drop the guard without incrementing the stamp. guard.abort(); val } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); let guard = lock(self.v.get().addr()).write(); self.write(val, &guard) } #[inline] pub(crate) fn swap(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(val, &guard); prev } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); if prev == current { self.write(new, &guard); Ok(prev) } else { // The value hasn't been changed. Drop the guard without incrementing the stamp. guard.abort(); Err(prev) } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(prev.wrapping_add(val), &guard); prev } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(prev.wrapping_sub(val), &guard); prev } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(prev & val, &guard); prev } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(!(prev & val), &guard); prev } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(prev | val, &guard); prev } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(prev ^ val, &guard); prev } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(core::cmp::max(prev, val), &guard); prev } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(core::cmp::min(prev, val), &guard); prev } #[inline] pub(crate) fn fetch_not(&self, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(!prev, &guard); prev } #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { let guard = lock(self.v.get().addr()).write(); let prev = self.read(&guard); self.write(prev.wrapping_neg(), &guard); prev } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } }; } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( test, not(any( not(portable_atomic_no_atomic_64), all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), )) )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( test, not(any( target_has_atomic = "64", all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), )) )) )] cfg_no_fast_atomic_64! { atomic!(AtomicI64, i64, 8); atomic!(AtomicU64, u64, 8); } atomic!(AtomicI128, i128, 16); atomic!(AtomicU128, u128, 16); #[cfg(test)] mod tests { use super::*; cfg_no_fast_atomic_64! { test_atomic_int!(i64); test_atomic_int!(u64); } test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. cfg_no_fast_atomic_64! { stress_test!(u64); } stress_test!(u128); } portable-atomic/src/imp/fallback/utils.rs0000644000175000017500000001236715105742312020316 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT use core::ops; // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.21/crossbeam-utils/src/cache_padded.rs. /// Pads and aligns a value to the length of a cache line. // Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache // lines at a time, so we have to align to 128 bytes rather than 64. // // Sources: // - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf // - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107 // // aarch64/arm64ec's big.LITTLE architecture has asymmetric cores and "big" cores have 128-byte cache line size. // // Sources: // - https://www.mono-project.com/news/2016/09/12/arm64-icache/ // // powerpc64 has 128-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_ppc64x.go#L9 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/powerpc/include/asm/cache.h#L26 #[cfg_attr( any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "arm64ec", target_arch = "powerpc64", ), repr(align(128)) )] // arm, mips, mips64, sparc, and hexagon have 32-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/sparc/include/asm/cache.h#L17 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/hexagon/include/asm/cache.h#L12 #[cfg_attr( any( target_arch = "arm", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "sparc", target_arch = "hexagon", ), repr(align(32)) )] // m68k has 16-byte cache line size. // // Sources: // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/m68k/include/asm/cache.h#L9 #[cfg_attr(target_arch = "m68k", repr(align(16)))] // s390x has 256-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/s390/include/asm/cache.h#L13 #[cfg_attr(target_arch = "s390x", repr(align(256)))] // x86, wasm, riscv, and sparc64 have 64-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/riscv/include/asm/cache.h#L10 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/sparc/include/asm/cache.h#L19 // // All others are assumed to have 64-byte cache line size. #[cfg_attr( not(any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "arm64ec", target_arch = "powerpc64", target_arch = "arm", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "sparc", target_arch = "hexagon", target_arch = "m68k", target_arch = "s390x", )), repr(align(64)) )] pub(crate) struct CachePadded { value: T, } impl CachePadded { #[inline] pub(crate) const fn new(value: T) -> Self { Self { value } } } impl ops::Deref for CachePadded { type Target = T; #[inline] fn deref(&self) -> &Self::Target { &self.value } } // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/backoff.rs. // Adjusted to reduce spinning. /// Performs exponential backoff in spin loops. pub(crate) struct Backoff { step: u32, } // https://github.com/oneapi-src/oneTBB/blob/v2021.5.0/include/oneapi/tbb/detail/_utils.h#L46-L48 const SPIN_LIMIT: u32 = 4; impl Backoff { #[inline] pub(crate) const fn new() -> Self { Self { step: 0 } } #[inline] pub(crate) fn snooze(&mut self) { if self.step <= SPIN_LIMIT { for _ in 0..1 << self.step { #[allow(deprecated)] core::sync::atomic::spin_loop_hint(); } self.step += 1; } else { #[cfg(not(feature = "std"))] for _ in 0..1 << self.step { #[allow(deprecated)] core::sync::atomic::spin_loop_hint(); } #[cfg(feature = "std")] std::thread::yield_now(); } } } portable-atomic/src/imp/fallback/seq_lock_wide.rs0000644000175000017500000001420715105742312021761 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/atomic/seq_lock_wide.rs. use core::{ mem::ManuallyDrop, sync::atomic::{self, AtomicUsize, Ordering}, }; use super::utils::Backoff; // See mod.rs for details. pub(super) type AtomicChunk = AtomicUsize; pub(super) type Chunk = usize; /// A simple stamped lock. /// /// The state is represented as two `AtomicUsize`: `state_hi` for high bits and `state_lo` for low /// bits. pub(super) struct SeqLock { /// The high bits of the current state of the lock. state_hi: AtomicUsize, /// The low bits of the current state of the lock. /// /// All bits except the least significant one hold the current stamp. When locked, the state_lo /// equals 1 and doesn't contain a valid stamp. state_lo: AtomicUsize, } impl SeqLock { #[inline] pub(super) const fn new() -> Self { Self { state_hi: AtomicUsize::new(0), state_lo: AtomicUsize::new(0) } } /// If not locked, returns the current stamp. /// /// This method should be called before optimistic reads. #[inline] pub(super) fn optimistic_read(&self) -> Option<(usize, usize)> { // The acquire loads from `state_hi` and `state_lo` synchronize with the release stores in // `SeqLockWriteGuard::drop` and `SeqLockWriteGuard::abort`. // // As a consequence, we can make sure that (1) all writes within the era of `state_hi - 1` // happens before now; and therefore, (2) if `state_lo` is even, all writes within the // critical section of (`state_hi`, `state_lo`) happens before now. let state_hi = self.state_hi.load(Ordering::Acquire); let state_lo = self.state_lo.load(Ordering::Acquire); if state_lo == 1 { None } else { Some((state_hi, state_lo)) } } /// Returns `true` if the current stamp is equal to `stamp`. /// /// This method should be called after optimistic reads to check whether they are valid. The /// argument `stamp` should correspond to the one returned by method `optimistic_read`. #[inline] pub(super) fn validate_read(&self, stamp: (usize, usize)) -> bool { // Thanks to the fence, if we're noticing any modification to the data at the critical // section of `(stamp.0, stamp.1)`, then the critical section's write of 1 to state_lo should be // visible. atomic::fence(Ordering::Acquire); // So if `state_lo` coincides with `stamp.1`, then either (1) we're noticing no modification // to the data after the critical section of `(stamp.0, stamp.1)`, or (2) `state_lo` wrapped // around. // // If (2) is the case, the acquire ordering ensures we see the new value of `state_hi`. let state_lo = self.state_lo.load(Ordering::Acquire); // If (2) is the case and `state_hi` coincides with `stamp.0`, then `state_hi` also wrapped // around, which we give up to correctly validate the read. let state_hi = self.state_hi.load(Ordering::Relaxed); // Except for the case that both `state_hi` and `state_lo` wrapped around, the following // condition implies that we're noticing no modification to the data after the critical // section of `(stamp.0, stamp.1)`. (state_hi, state_lo) == stamp } /// Grabs the lock for writing. #[inline] pub(super) fn write(&self) -> SeqLockWriteGuard<'_> { let mut backoff = Backoff::new(); loop { let previous = self.state_lo.swap(1, Ordering::Acquire); if previous != 1 { // To synchronize with the acquire fence in `validate_read` via any modification to // the data at the critical section of `(state_hi, previous)`. atomic::fence(Ordering::Release); return SeqLockWriteGuard { lock: self, state_lo: previous }; } while self.state_lo.load(Ordering::Relaxed) == 1 { backoff.snooze(); } } } } /// An RAII guard that releases the lock and increments the stamp when dropped. #[must_use] pub(super) struct SeqLockWriteGuard<'a> { /// The parent lock. lock: &'a SeqLock, /// The stamp before locking. state_lo: usize, } impl SeqLockWriteGuard<'_> { /// Releases the lock without incrementing the stamp. #[inline] pub(super) fn abort(self) { // We specifically don't want to call drop(), since that's // what increments the stamp. let this = ManuallyDrop::new(self); // Restore the stamp. // // Release ordering for synchronizing with `optimistic_read`. this.lock.state_lo.store(this.state_lo, Ordering::Release); } } impl Drop for SeqLockWriteGuard<'_> { #[inline] fn drop(&mut self) { let state_lo = self.state_lo.wrapping_add(2); // Increase the high bits if the low bits wrap around. // // Release ordering for synchronizing with `optimistic_read`. if state_lo == 0 { let state_hi = self.lock.state_hi.load(Ordering::Relaxed); self.lock.state_hi.store(state_hi.wrapping_add(1), Ordering::Release); } // Release the lock and increment the stamp. // // Release ordering for synchronizing with `optimistic_read`. self.lock.state_lo.store(state_lo, Ordering::Release); } } #[cfg(test)] mod tests { use super::SeqLock; #[test] fn smoke() { let lock = SeqLock::new(); let before = lock.optimistic_read().unwrap(); assert!(lock.validate_read(before)); { let _guard = lock.write(); } assert!(!lock.validate_read(before)); let after = lock.optimistic_read().unwrap(); assert_ne!(before, after); } #[test] fn test_abort() { let lock = SeqLock::new(); let before = lock.optimistic_read().unwrap(); { let guard = lock.write(); guard.abort(); } let after = lock.optimistic_read().unwrap(); assert_eq!(before, after, "aborted write does not update the stamp"); } } portable-atomic/src/imp/fallback/seq_lock.rs0000644000175000017500000001033615105742312020750 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/atomic/seq_lock.rs. use core::{ mem::ManuallyDrop, sync::atomic::{self, Ordering}, }; use super::utils::Backoff; // See mod.rs for details. #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] pub(super) use core::sync::atomic::AtomicU64 as AtomicStamp; #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] pub(super) use core::sync::atomic::AtomicUsize as AtomicStamp; #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] pub(super) type Stamp = usize; #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] pub(super) type Stamp = u64; // See mod.rs for details. pub(super) type AtomicChunk = AtomicStamp; pub(super) type Chunk = Stamp; /// A simple stamped lock. pub(super) struct SeqLock { /// The current state of the lock. /// /// All bits except the least significant one hold the current stamp. When locked, the state /// equals 1 and doesn't contain a valid stamp. state: AtomicStamp, } impl SeqLock { #[inline] pub(super) const fn new() -> Self { Self { state: AtomicStamp::new(0) } } /// If not locked, returns the current stamp. /// /// This method should be called before optimistic reads. #[inline] pub(super) fn optimistic_read(&self) -> Option { let state = self.state.load(Ordering::Acquire); if state == 1 { None } else { Some(state) } } /// Returns `true` if the current stamp is equal to `stamp`. /// /// This method should be called after optimistic reads to check whether they are valid. The /// argument `stamp` should correspond to the one returned by method `optimistic_read`. #[inline] pub(super) fn validate_read(&self, stamp: Stamp) -> bool { atomic::fence(Ordering::Acquire); self.state.load(Ordering::Relaxed) == stamp } /// Grabs the lock for writing. #[inline] pub(super) fn write(&self) -> SeqLockWriteGuard<'_> { let mut backoff = Backoff::new(); loop { let previous = self.state.swap(1, Ordering::Acquire); if previous != 1 { atomic::fence(Ordering::Release); return SeqLockWriteGuard { lock: self, state: previous }; } while self.state.load(Ordering::Relaxed) == 1 { backoff.snooze(); } } } } /// An RAII guard that releases the lock and increments the stamp when dropped. #[must_use] pub(super) struct SeqLockWriteGuard<'a> { /// The parent lock. lock: &'a SeqLock, /// The stamp before locking. state: Stamp, } impl SeqLockWriteGuard<'_> { /// Releases the lock without incrementing the stamp. #[inline] pub(super) fn abort(self) { // We specifically don't want to call drop(), since that's // what increments the stamp. let this = ManuallyDrop::new(self); // Restore the stamp. // // Release ordering for synchronizing with `optimistic_read`. this.lock.state.store(this.state, Ordering::Release); } } impl Drop for SeqLockWriteGuard<'_> { #[inline] fn drop(&mut self) { // Release the lock and increment the stamp. // // Release ordering for synchronizing with `optimistic_read`. self.lock.state.store(self.state.wrapping_add(2), Ordering::Release); } } #[cfg(test)] mod tests { use super::SeqLock; #[test] fn smoke() { let lock = SeqLock::new(); let before = lock.optimistic_read().unwrap(); assert!(lock.validate_read(before)); { let _guard = lock.write(); } assert!(!lock.validate_read(before)); let after = lock.optimistic_read().unwrap(); assert_ne!(before, after); } #[test] fn test_abort() { let lock = SeqLock::new(); let before = lock.optimistic_read().unwrap(); { let guard = lock.write(); guard.abort(); } let after = lock.optimistic_read().unwrap(); assert_eq!(before, after, "aborted write does not update the stamp"); } } portable-atomic/src/imp/fallback/outline_atomics.rs0000644000175000017500000001610615105742312022347 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Helper for outline-atomics. On architectures where DW atomics are not supported on older CPUs, we use fallback implementation when DW atomic instructions are not supported and outline-atomics is enabled. This module provides helpers to implement them. */ use core::sync::atomic::Ordering; #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "riscv64"))] pub(crate) type Udw = u128; #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "riscv64"))] pub(crate) type AtomicUdw = super::super::super::fallback::AtomicU128; #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "riscv64"))] pub(crate) type AtomicIdw = super::super::super::fallback::AtomicI128; #[cfg(any(target_arch = "arm", target_arch = "riscv32"))] pub(crate) type Udw = u64; #[cfg(any(target_arch = "arm", target_arch = "riscv32"))] pub(crate) type AtomicUdw = super::super::super::fallback::AtomicU64; #[cfg(any(target_arch = "arm", target_arch = "riscv32"))] pub(crate) type AtomicIdw = super::super::super::fallback::AtomicI64; // Asserts that the function is called in the correct context. macro_rules! debug_assert_outline_atomics { () => { #[cfg(target_arch = "x86_64")] { debug_assert!(!super::detect::detect().has_cmpxchg16b()); } #[cfg(target_arch = "powerpc64")] { debug_assert!(!super::detect::detect().has_quadword_atomics()); } #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { debug_assert!(!super::detect::detect().has_zacas()); } #[cfg(target_arch = "arm")] { debug_assert!(!super::has_kuser_cmpxchg64()); } }; } #[cold] pub(crate) unsafe fn atomic_load(src: *mut Udw, order: Ordering) -> Udw { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { (*(src as *const AtomicUdw)).load(order) } } fn_alias! { #[cold] pub(crate) unsafe fn(src: *mut Udw) -> Udw; // fallback's atomic load has at least acquire semantics. #[cfg(not(any(target_arch = "arm", target_arch = "x86_64")))] atomic_load_non_seqcst = atomic_load(Ordering::Acquire); atomic_load_seqcst = atomic_load(Ordering::SeqCst); } #[cfg(not(any(target_arch = "arm", target_arch = "riscv32", target_arch = "riscv64")))] #[cold] pub(crate) unsafe fn atomic_store(dst: *mut Udw, val: Udw, order: Ordering) { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { (*(dst as *const AtomicUdw)).store(val, order); } } #[cfg(not(any(target_arch = "arm", target_arch = "riscv32", target_arch = "riscv64")))] fn_alias! { #[cold] pub(crate) unsafe fn(dst: *mut Udw, val: Udw); // fallback's atomic store has at least release semantics. atomic_store_non_seqcst = atomic_store(Ordering::Release); atomic_store_seqcst = atomic_store(Ordering::SeqCst); } #[cold] pub(crate) unsafe fn atomic_compare_exchange( dst: *mut Udw, old: Udw, new: Udw, success: Ordering, failure: Ordering, ) -> (Udw, bool) { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { match (*(dst as *const AtomicUdw)).compare_exchange(old, new, success, failure) { Ok(v) => (v, true), Err(v) => (v, false), } } } fn_alias! { #[cold] pub(crate) unsafe fn(dst: *mut Udw, old: Udw, new: Udw) -> (Udw, bool); // fallback's atomic CAS has at least AcqRel semantics. #[cfg(not(any(target_arch = "arm", target_arch = "x86_64")))] atomic_compare_exchange_non_seqcst = atomic_compare_exchange(Ordering::AcqRel, Ordering::Acquire); atomic_compare_exchange_seqcst = atomic_compare_exchange(Ordering::SeqCst, Ordering::SeqCst); } macro_rules! atomic_rmw_3 { ( $name:ident($atomic_type:ident::$method_name:ident), $non_seqcst_alias:ident, $seqcst_alias:ident ) => { #[cold] pub(crate) unsafe fn $name(dst: *mut Udw, val: Udw, order: Ordering) -> Udw { debug_assert_outline_atomics!(); #[allow( clippy::as_underscore, clippy::cast_possible_wrap, clippy::cast_ptr_alignment, clippy::cast_sign_loss )] // SAFETY: the caller must uphold the safety contract. unsafe { (*(dst as *const $atomic_type)).$method_name(val as _, order) as Udw } } fn_alias! { #[cold] pub(crate) unsafe fn(dst: *mut Udw, val: Udw) -> Udw; // fallback's atomic RMW has at least AcqRel semantics. #[cfg(not(any(target_arch = "arm", target_arch = "x86_64")))] $non_seqcst_alias = $name(Ordering::AcqRel); $seqcst_alias = $name(Ordering::SeqCst); } }; } macro_rules! atomic_rmw_2 { ( $name:ident($atomic_type:ident::$method_name:ident), $non_seqcst_alias:ident, $seqcst_alias:ident ) => { #[cold] pub(crate) unsafe fn $name(dst: *mut Udw, order: Ordering) -> Udw { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { (*(dst as *const $atomic_type)).$method_name(order) as Udw } } fn_alias! { #[cold] pub(crate) unsafe fn(dst: *mut Udw) -> Udw; // fallback's atomic RMW has at least AcqRel semantics. #[cfg(not(any(target_arch = "arm", target_arch = "x86_64")))] $non_seqcst_alias = $name(Ordering::AcqRel); $seqcst_alias = $name(Ordering::SeqCst); } }; } atomic_rmw_3!(atomic_swap(AtomicUdw::swap), atomic_swap_non_seqcst, atomic_swap_seqcst); atomic_rmw_3!(atomic_add(AtomicUdw::fetch_add), atomic_add_non_seqcst, atomic_add_seqcst); atomic_rmw_3!(atomic_sub(AtomicUdw::fetch_sub), atomic_sub_non_seqcst, atomic_sub_seqcst); atomic_rmw_3!(atomic_and(AtomicUdw::fetch_and), atomic_and_non_seqcst, atomic_and_seqcst); atomic_rmw_3!(atomic_nand(AtomicUdw::fetch_nand), atomic_nand_non_seqcst, atomic_nand_seqcst); atomic_rmw_3!(atomic_or(AtomicUdw::fetch_or), atomic_or_non_seqcst, atomic_or_seqcst); atomic_rmw_3!(atomic_xor(AtomicUdw::fetch_xor), atomic_xor_non_seqcst, atomic_xor_seqcst); atomic_rmw_3!(atomic_max(AtomicIdw::fetch_max), atomic_max_non_seqcst, atomic_max_seqcst); atomic_rmw_3!(atomic_umax(AtomicUdw::fetch_max), atomic_umax_non_seqcst, atomic_umax_seqcst); atomic_rmw_3!(atomic_min(AtomicIdw::fetch_min), atomic_min_non_seqcst, atomic_min_seqcst); atomic_rmw_3!(atomic_umin(AtomicUdw::fetch_min), atomic_umin_non_seqcst, atomic_umin_seqcst); atomic_rmw_2!(atomic_not(AtomicUdw::fetch_not), atomic_not_non_seqcst, atomic_not_seqcst); atomic_rmw_2!(atomic_neg(AtomicUdw::fetch_neg), atomic_neg_non_seqcst, atomic_neg_seqcst); portable-atomic/src/imp/float/0000775000175000017500000000000015105742312016147 5ustar bdrungbdrungportable-atomic/src/imp/float/mod.rs0000644000175000017500000000071715105742312017277 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Atomic float implementations */ #![allow(clippy::float_arithmetic)] mod int; #[cfg(portable_atomic_unstable_f16)] cfg_has_atomic_16! { pub(crate) use self::int::AtomicF16; } cfg_has_atomic_32! { pub(crate) use self::int::AtomicF32; } cfg_has_atomic_64! { pub(crate) use self::int::AtomicF64; } #[cfg(portable_atomic_unstable_f128)] cfg_has_atomic_128! { pub(crate) use self::int::AtomicF128; } portable-atomic/src/imp/float/int.rs0000644000175000017500000002031315105742312017304 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Atomic float implementation based on atomic integer. This module provides atomic float implementations using atomic integer. Note that most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. AArch64 with FEAT_LSFE and GPU targets have atomic instructions for float. Both will use architecture-specific implementations instead of this implementation in the future: https://github.com/taiki-e/portable-atomic/issues/34 / https://github.com/taiki-e/portable-atomic/pull/45 */ // TODO: fetch_{minimum,maximum}* https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3008r2.html / https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0493r5.pdf #![cfg_attr( all(target_pointer_width = "16", not(feature = "fallback")), allow(unused_imports, unused_macros) )] use core::{cell::UnsafeCell, sync::atomic::Ordering}; macro_rules! atomic_float { ( $atomic_type:ident, $float_type:ident, $atomic_int_type:ident, $int_type:ident, $align:literal ) => { #[repr(C, align($align))] pub(crate) struct $atomic_type { v: UnsafeCell<$float_type>, } // Send is implicitly implemented. // SAFETY: any data races are prevented by atomic operations. unsafe impl Sync for $atomic_type {} impl $atomic_type { #[inline] pub(crate) const fn new(v: $float_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { crate::$atomic_int_type::is_lock_free() } pub(crate) const IS_ALWAYS_LOCK_FREE: bool = crate::$atomic_int_type::is_always_lock_free(); #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn load(&self, order: Ordering) -> $float_type { $float_type::from_bits(self.as_bits().load(order)) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn store(&self, val: $float_type, order: Ordering) { self.as_bits().store(val.to_bits(), order) } const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; #[inline(always)] pub(crate) const fn as_bits(&self) -> &crate::$atomic_int_type { // SAFETY: $atomic_type and $atomic_int_type have the same layout, // and there is no concurrent access to the value that does not go through this method. unsafe { &*(self as *const Self as *const crate::$atomic_int_type) } } } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $float_type { self.v.get() } } cfg_has_atomic_cas_or_amo32! { impl $atomic_type { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn swap(&self, val: $float_type, order: Ordering) -> $float_type { $float_type::from_bits(self.as_bits().swap(val.to_bits(), order)) } cfg_has_atomic_cas! { #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> { match self.as_bits().compare_exchange( current.to_bits(), new.to_bits(), success, failure, ) { Ok(v) => Ok($float_type::from_bits(v)), Err(v) => Err($float_type::from_bits(v)), } } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange_weak( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> { match self.as_bits().compare_exchange_weak( current.to_bits(), new.to_bits(), success, failure, ) { Ok(v) => Ok($float_type::from_bits(v)), Err(v) => Err($float_type::from_bits(v)), } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_add(&self, val: $float_type, order: Ordering) -> $float_type { self.fetch_update_(order, |x| x + val) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_sub(&self, val: $float_type, order: Ordering) -> $float_type { self.fetch_update_(order, |x| x - val) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn fetch_update_(&self, order: Ordering, mut f: F) -> $float_type where F: FnMut($float_type) -> $float_type, { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = self.load(Ordering::Relaxed); loop { let next = f(prev); match self.compare_exchange_weak(prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(next_prev) => prev = next_prev, } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_max(&self, val: $float_type, order: Ordering) -> $float_type { self.fetch_update_(order, |x| x.max(val)) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_min(&self, val: $float_type, order: Ordering) -> $float_type { self.fetch_update_(order, |x| x.min(val)) } } // cfg_has_atomic_cas! #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_neg(&self, order: Ordering) -> $float_type { const NEG_MASK: $int_type = !0 / 2 + 1; $float_type::from_bits(self.as_bits().fetch_xor(NEG_MASK, order)) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_abs(&self, order: Ordering) -> $float_type { const ABS_MASK: $int_type = !0 / 2; $float_type::from_bits(self.as_bits().fetch_and(ABS_MASK, order)) } } } // cfg_has_atomic_cas_or_amo32! }; } #[cfg(portable_atomic_unstable_f16)] cfg_has_atomic_16! { atomic_float!(AtomicF16, f16, AtomicU16, u16, 2); } cfg_has_atomic_32! { atomic_float!(AtomicF32, f32, AtomicU32, u32, 4); } cfg_has_atomic_64! { atomic_float!(AtomicF64, f64, AtomicU64, u64, 8); } #[cfg(portable_atomic_unstable_f128)] cfg_has_atomic_128! { atomic_float!(AtomicF128, f128, AtomicU128, u128, 16); } portable-atomic/src/imp/avr.rs0000644000175000017500000000575015105742312016205 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT /* Atomic load/store implementation on AVR. Operations not supported here are provided by disabling interrupts. See also src/imp/interrupt/avr.rs. See "Atomic operation overview by architecture" in atomic-maybe-uninit for a more comprehensive and detailed description of the atomic and synchronize instructions in this architecture: https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/src/arch/README.md#avr Note: Ordering is always SeqCst. Refs: - AVR® Instruction Set Manual, Rev. DS40002198B https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-InstructionSet-Manual-DS40002198.pdf - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit Generated asm: - avr https://godbolt.org/z/j49rYbj4d */ use core::{arch::asm, cell::UnsafeCell, sync::atomic::Ordering}; macro_rules! atomic8 { ($atomic_type:ident, $value_type:ty) => { #[repr(transparent)] pub(crate) struct $atomic_type { v: UnsafeCell<$value_type>, } // Send is implicitly implemented for atomic integers, but not for atomic pointers. // SAFETY: any data races are prevented by atomic operations. unsafe impl Send for $atomic_type {} // SAFETY: any data races are prevented by atomic operations. unsafe impl Sync for $atomic_type {} impl $atomic_type { #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $value_type { crate::utils::assert_load_ordering(order); let src = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { let out; asm!( "ld {out}, Z", // atomic { out = *Z } in("Z") src, out = out(reg) out, options(nostack, preserves_flags), ); out } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $value_type, order: Ordering) { crate::utils::assert_store_ordering(order); let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { asm!( "st Z, {val}", // atomic { *Z = val } in("Z") dst, val = in(reg) val, options(nostack, preserves_flags), ); } } } }; } atomic8!(AtomicI8, i8); atomic8!(AtomicU8, u8); portable-atomic/src/tests/0000775000175000017500000000000015105742312015417 5ustar bdrungbdrungportable-atomic/src/tests/mod.rs0000644000175000017500000003657315105742312016560 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT #![allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[macro_use] pub(crate) mod helper; #[allow(dead_code)] #[path = "../../version.rs"] mod version; use test_helper as _; use super::*; test_atomic_bool_pub!(); test_atomic_ptr_pub!(); test_atomic_int_pub!(isize); test_atomic_int_pub!(usize); test_atomic_int_pub!(i8); test_atomic_int_pub!(u8); test_atomic_int_pub!(i16); test_atomic_int_pub!(u16); test_atomic_int_pub!(i32); test_atomic_int_pub!(u32); test_atomic_int_pub!(i64); test_atomic_int_pub!(u64); test_atomic_int_pub!(i128); test_atomic_int_pub!(u128); #[cfg(all(feature = "float", portable_atomic_unstable_f16))] test_atomic_float_pub!(f16); #[cfg(feature = "float")] test_atomic_float_pub!(f32); #[cfg(feature = "float")] test_atomic_float_pub!(f64); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] test_atomic_float_pub!(f128); #[deny(improper_ctypes)] extern "C" { fn _atomic_bool_ffi_safety(_: AtomicBool); fn _atomic_ptr_ffi_safety(_: AtomicPtr); fn _atomic_isize_ffi_safety(_: AtomicIsize); fn _atomic_usize_ffi_safety(_: AtomicUsize); fn _atomic_i8_ffi_safety(_: AtomicI8); fn _atomic_u8_ffi_safety(_: AtomicU8); fn _atomic_i16_ffi_safety(_: AtomicI16); fn _atomic_u16_ffi_safety(_: AtomicU16); fn _atomic_i32_ffi_safety(_: AtomicI32); fn _atomic_u32_ffi_safety(_: AtomicU32); fn _atomic_i64_ffi_safety(_: AtomicI64); fn _atomic_u64_ffi_safety(_: AtomicU64); // TODO: https://github.com/rust-lang/lang-team/issues/255 // fn _atomic_i128_ffi_safety(_: AtomicI128); // fn _atomic_u128_ffi_safety(_: AtomicU128); #[cfg(all(feature = "float", portable_atomic_unstable_f16))] fn _atomic_f16_ffi_safety(_: AtomicF16); #[cfg(feature = "float")] fn _atomic_f32_ffi_safety(_: AtomicF32); #[cfg(feature = "float")] fn _atomic_f64_ffi_safety(_: AtomicF64); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] fn _atomic_f128_ffi_safety(_: AtomicF128); } #[test] fn test_is_lock_free() { assert!(AtomicI8::is_always_lock_free()); assert!(AtomicI8::is_lock_free()); assert!(AtomicU8::is_always_lock_free()); assert!(AtomicU8::is_lock_free()); assert!(AtomicI16::is_always_lock_free()); assert!(AtomicI16::is_lock_free()); assert!(AtomicU16::is_always_lock_free()); assert!(AtomicU16::is_lock_free()); #[cfg(all(feature = "float", portable_atomic_unstable_f16))] assert!(AtomicF16::is_always_lock_free()); #[cfg(all(feature = "float", portable_atomic_unstable_f16))] assert!(AtomicF16::is_lock_free()); assert!(AtomicI32::is_always_lock_free()); assert!(AtomicI32::is_lock_free()); assert!(AtomicU32::is_always_lock_free()); assert!(AtomicU32::is_lock_free()); #[cfg(feature = "float")] assert!(AtomicF32::is_always_lock_free()); #[cfg(feature = "float")] assert!(AtomicF32::is_lock_free()); #[cfg(not(portable_atomic_no_cfg_target_has_atomic))] { if cfg!(any( target_has_atomic = "64", all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), )) { assert!(AtomicI64::is_always_lock_free()); assert!(AtomicI64::is_lock_free()); assert!(AtomicU64::is_always_lock_free()); assert!(AtomicU64::is_lock_free()); #[cfg(feature = "float")] assert!(AtomicF64::is_always_lock_free()); #[cfg(feature = "float")] assert!(AtomicF64::is_lock_free()); } else if cfg!(all( feature = "fallback", target_arch = "arm", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_os = "linux", target_os = "android"), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(portable_atomic_no_outline_atomics), not(target_has_atomic = "64"), not(portable_atomic_test_outline_atomics_detect_false), )) { assert!(!AtomicI64::is_always_lock_free()); assert!(!AtomicU64::is_always_lock_free()); #[cfg(feature = "float")] assert!(!AtomicF64::is_always_lock_free()); assert!(AtomicI64::is_lock_free()); assert!(AtomicU64::is_lock_free()); #[cfg(feature = "float")] assert!(AtomicF64::is_lock_free()); } else { assert!(!AtomicI64::is_always_lock_free()); assert!(!AtomicU64::is_always_lock_free()); #[cfg(feature = "float")] assert!(!AtomicF64::is_always_lock_free()); #[cfg(not(target_arch = "riscv32"))] { assert!(!AtomicI64::is_lock_free()); assert!(!AtomicU64::is_lock_free()); #[cfg(feature = "float")] assert!(!AtomicF64::is_lock_free()); } #[cfg(target_arch = "riscv32")] { // TODO(riscv): check detect.has_zacas } } } if cfg!(portable_atomic_no_asm) && cfg!(not(portable_atomic_unstable_asm)) { assert!(!AtomicI128::is_always_lock_free()); assert!(!AtomicI128::is_lock_free()); assert!(!AtomicU128::is_always_lock_free()); assert!(!AtomicU128::is_lock_free()); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] assert!(!AtomicF128::is_always_lock_free()); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] assert!(!AtomicF128::is_lock_free()); } else if cfg!(any( target_arch = "aarch64", all(target_arch = "arm64ec", not(portable_atomic_no_asm)), all( target_arch = "x86_64", any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), ), all( target_arch = "riscv64", any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ), ), all(target_arch = "s390x", not(portable_atomic_no_asm)), )) { assert!(AtomicI128::is_always_lock_free()); assert!(AtomicI128::is_lock_free()); assert!(AtomicU128::is_always_lock_free()); assert!(AtomicU128::is_lock_free()); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] assert!(AtomicF128::is_always_lock_free()); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] assert!(AtomicF128::is_lock_free()); } else { assert!(!AtomicI128::is_always_lock_free()); assert!(!AtomicU128::is_always_lock_free()); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] assert!(!AtomicF128::is_always_lock_free()); #[cfg(not(any( target_arch = "x86_64", target_arch = "powerpc64", target_arch = "riscv64", )))] { assert!(!AtomicI128::is_lock_free()); assert!(!AtomicU128::is_lock_free()); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] assert!(!AtomicF128::is_lock_free()); } #[cfg(target_arch = "x86_64")] { let has_cmpxchg16b = cfg!(all( feature = "fallback", not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), not(portable_atomic_test_outline_atomics_detect_false), )) && std::is_x86_feature_detected!("cmpxchg16b"); assert_eq!(AtomicI128::is_lock_free(), has_cmpxchg16b); assert_eq!(AtomicU128::is_lock_free(), has_cmpxchg16b); #[cfg(all(feature = "float", portable_atomic_unstable_f128))] assert_eq!(AtomicF128::is_lock_free(), has_cmpxchg16b); } #[cfg(target_arch = "powerpc64")] { // TODO(powerpc64): is_powerpc_feature_detected is unstable } #[cfg(target_arch = "riscv64")] { // TODO(riscv): check detect.has_zacas } } } // test version parsing code used in the build script. #[test] fn test_rustc_version() { use self::version::Version; // rustc 1.34 (rustup) let v = Version::parse( "rustc 1.34.2 (6c2484dc3 2019-05-13) binary: rustc commit-hash: 6c2484dc3c532c052f159264e970278d8b77cdc9 commit-date: 2019-05-13 host: x86_64-apple-darwin release: 1.34.2 LLVM version: 8.0", ) .unwrap(); assert_eq!(v, Version::stable(34, 8)); // rustc 1.50 (rustup) let v = Version::parse( "rustc 1.50.0 (cb75ad5db 2021-02-10) binary: rustc commit-hash: cb75ad5db02783e8b0222fee363c5f63f7e2cf5b commit-date: 2021-02-10 host: aarch64-unknown-linux-gnu release: 1.50.0", ) .unwrap(); assert_eq!(v, Version::stable(50, 0)); // rustc 1.67 (rustup) let v = Version::parse( "rustc 1.67.0 (fc594f156 2023-01-24) binary: rustc commit-hash: fc594f15669680fa70d255faec3ca3fb507c3405 commit-date: 2023-01-24 host: aarch64-apple-darwin release: 1.67.0 LLVM version: 15.0.6", ) .unwrap(); assert_eq!(v, Version::stable(67, 15)); // rustc 1.68-beta (rustup) let v = Version::parse( "rustc 1.68.0-beta.2 (10b73bf73 2023-02-01) binary: rustc commit-hash: 10b73bf73a6b770cd92ad8ff538173bc3298411c commit-date: 2023-02-01 host: aarch64-apple-darwin release: 1.68.0-beta.2 LLVM version: 15.0.6", ) .unwrap(); // We do not distinguish between stable and beta because we are only // interested in whether unstable features are potentially available. assert_eq!(v, Version::stable(68, 15)); // rustc nightly-2019-01-27 (rustup) let v = Version::parse( "rustc 1.33.0-nightly (20c2cba61 2019-01-26) binary: rustc commit-hash: 20c2cba61dc83e612d25ed496025171caa3db30f commit-date: 2019-01-26 host: x86_64-apple-darwin release: 1.33.0-nightly LLVM version: 8.0", ) .unwrap(); assert_eq!(v.minor, 33); assert!(v.nightly); assert_eq!(v.llvm, 8); assert_eq!(v.commit_date().year, 2019); assert_eq!(v.commit_date().month, 1); assert_eq!(v.commit_date().day, 26); // rustc 1.69-nightly (rustup) let v = Version::parse( "rustc 1.69.0-nightly (bd39bbb4b 2023-02-07) binary: rustc commit-hash: bd39bbb4bb92df439bf6d85470e296cc6a47ffbd commit-date: 2023-02-07 host: aarch64-apple-darwin release: 1.69.0-nightly LLVM version: 15.0.7", ) .unwrap(); assert_eq!(v.minor, 69); assert!(v.nightly); assert_eq!(v.llvm, 15); assert_eq!(v.commit_date().year, 2023); assert_eq!(v.commit_date().month, 2); assert_eq!(v.commit_date().day, 7); // clippy-driver 1.69-nightly (rustup) let v = Version::parse( "rustc 1.69.0-nightly (bd39bbb4b 2023-02-07) binary: rustc commit-hash: bd39bbb4bb92df439bf6d85470e296cc6a47ffbd commit-date: 2023-02-07 host: aarch64-apple-darwin release: 1.69.0-nightly LLVM version: 15.0.7", ) .unwrap(); assert_eq!(v.minor, 69); assert!(v.nightly); assert_eq!(v.llvm, 15); assert_eq!(v.commit_date().year, 2023); assert_eq!(v.commit_date().month, 2); assert_eq!(v.commit_date().day, 7); // rustc 1.69-dev (from source: ./x.py build) let v = Version::parse( "rustc 1.69.0-dev binary: rustc commit-hash: unknown commit-date: unknown host: aarch64-unknown-linux-gnu release: 1.69.0-dev LLVM version: 16.0.0", ) .unwrap(); assert_eq!(v.minor, 69); assert!(v.nightly); assert_eq!(v.llvm, 16); assert_eq!(v.commit_date().year, 0); assert_eq!(v.commit_date().month, 0); assert_eq!(v.commit_date().day, 0); // rustc 1.48 (debian 11: apt-get install cargo) let v = Version::parse( "rustc 1.48.0 binary: rustc commit-hash: unknown commit-date: unknown host: aarch64-unknown-linux-gnu release: 1.48.0 LLVM version: 11.0", ) .unwrap(); assert_eq!(v, Version::stable(48, 11)); // rustc 1.67 (fedora: dnf install cargo) let v = Version::parse( "rustc 1.67.0 (fc594f156 2023-01-24) (Fedora 1.67.0-2.fc37) binary: rustc commit-hash: fc594f15669680fa70d255faec3ca3fb507c3405 commit-date: 2023-01-24 host: aarch64-unknown-linux-gnu release: 1.67.0 LLVM version: 15.0.7", ) .unwrap(); assert_eq!(v, Version::stable(67, 15)); // rustc 1.64 (alpine: apk add cargo) let v = Version::parse( "rustc 1.64.0 binary: rustc commit-hash: unknown commit-date: unknown host: aarch64-alpine-linux-musl release: 1.64.0 LLVM version: 15.0.3", ) .unwrap(); assert_eq!(v, Version::stable(64, 15)); } #[cfg(feature = "serde")] #[test] fn test_serde() { use std::fmt; use serde::{ de::{Deserialize, Deserializer}, ser::{Serialize, Serializer}, }; use serde_test::{Token, assert_tokens}; #[derive(Debug)] struct DebugPartialEq(T); impl PartialEq for DebugPartialEq { fn eq(&self, other: &Self) -> bool { std::format!("{:?}", self) == std::format!("{:?}", other) } } impl Serialize for DebugPartialEq { fn serialize(&self, serializer: S) -> Result where S: Serializer, { self.0.serialize(serializer) } } impl<'de, T: Deserialize<'de>> Deserialize<'de> for DebugPartialEq { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { T::deserialize(deserializer).map(Self) } } macro_rules! t { ($atomic_type:ty, $value_type:ident $(as $token_value_type:ident)?, $token_type:ident) => { std::eprint!("test_serde {} ... ", stringify!($value_type)); assert_tokens(&DebugPartialEq(<$atomic_type>::new($value_type::MAX)), &[ Token::$token_type($value_type::MAX $(as $token_value_type)?), ]); assert_tokens(&DebugPartialEq(<$atomic_type>::new($value_type::MIN)), &[ Token::$token_type($value_type::MIN $(as $token_value_type)?), ]); std::eprintln!("ok"); }; } assert_tokens(&DebugPartialEq(AtomicBool::new(true)), &[Token::Bool(true)]); assert_tokens(&DebugPartialEq(AtomicBool::new(false)), &[Token::Bool(false)]); t!(AtomicIsize, isize as i64, I64); t!(AtomicUsize, usize as u64, U64); t!(AtomicI8, i8, I8); t!(AtomicU8, u8, U8); t!(AtomicI16, i16, I16); t!(AtomicU16, u16, U16); t!(AtomicI32, i32, I32); t!(AtomicU32, u32, U32); t!(AtomicI64, i64, I64); t!(AtomicU64, u64, U64); t!(AtomicI128, i128, I128); t!(AtomicU128, u128, U128); // TODO(f16_and_f128): Test f16 & f128 once stabilized. #[cfg(feature = "float")] t!(AtomicF32, f32, F32); #[cfg(feature = "float")] // TODO: fixed in LLVM 18? #[cfg(not(target_arch = "mips"))] // LLVM 17 (nightly-2023-08-09) bug: assertion failed at core/src/num/diy_float.rs:78:9 t!(AtomicF64, f64, F64); } portable-atomic/src/tests/helper.rs0000644000175000017500000033402115105742312017245 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT #![allow(unused_macros, clippy::undocumented_unsafe_blocks)] use core::sync::atomic::Ordering; use crate::tests::helper; macro_rules! __test_atomic_common { ($atomic_type:ty, $value_type:ty) => { #[test] fn assert_auto_traits() { fn _assert() {} _assert::<$atomic_type>(); } #[test] fn alignment() { // https://github.com/rust-lang/rust/blob/1.84.0/library/core/tests/atomic.rs#L252 assert_eq!(core::mem::align_of::<$atomic_type>(), core::mem::size_of::<$atomic_type>()); assert_eq!(core::mem::size_of::<$atomic_type>(), core::mem::size_of::<$value_type>()); } #[test] fn is_lock_free() { const IS_ALWAYS_LOCK_FREE: bool = <$atomic_type>::IS_ALWAYS_LOCK_FREE; assert_eq!(IS_ALWAYS_LOCK_FREE, <$atomic_type>::IS_ALWAYS_LOCK_FREE); let is_lock_free = <$atomic_type>::is_lock_free(); if IS_ALWAYS_LOCK_FREE { // If is_always_lock_free is true, then is_lock_free must always be true. assert!(is_lock_free); } } }; } macro_rules! __test_atomic_pub_common { ($atomic_type:ty, $value_type:ty) => { #[test] fn is_always_lock_free() { assert_eq!(<$atomic_type>::IS_ALWAYS_LOCK_FREE, <$atomic_type>::is_always_lock_free()); } #[test] fn assert_ref_unwind_safe() { #[cfg(not(all(portable_atomic_no_core_unwind_safe, not(feature = "std"))))] static_assertions::assert_impl_all!($atomic_type: std::panic::RefUnwindSafe); #[cfg(all(portable_atomic_no_core_unwind_safe, not(feature = "std")))] static_assertions::assert_not_impl_all!($atomic_type: std::panic::RefUnwindSafe); } }; } macro_rules! __test_atomic_int_load_store { ($atomic_type:ty, $int_type:ident, single_thread) => { __test_atomic_common!($atomic_type, $int_type); use crate::tests::helper::{self, *}; #[test] fn accessor() { let a = <$atomic_type>::new(10); unsafe { assert_eq!(*a.as_ptr(), 10); *a.as_ptr() = 5; assert_eq!(a.as_ptr() as *const (), &a as *const _ as *const ()); assert_eq!(*a.as_ptr(), 5); } } // https://bugs.llvm.org/show_bug.cgi?id=37061 #[test] fn static_load_only() { static VAR: $atomic_type = <$atomic_type>::new(10); for &order in &helper::LOAD_ORDERINGS { assert_eq!(VAR.load(order), 10); } } #[test] fn load_store() { static VAR: $atomic_type = <$atomic_type>::new(10); test_load_ordering(|order| VAR.load(order)); test_store_ordering(|order| VAR.store(10, order)); for (&load_order, &store_order) in helper::LOAD_ORDERINGS.iter().zip(&helper::STORE_ORDERINGS) { assert_eq!(VAR.load(load_order), 10); VAR.store(5, store_order); assert_eq!(VAR.load(load_order), 5); VAR.store(10, store_order); let a = <$atomic_type>::new(1); assert_eq!(a.load(load_order), 1); a.store($int_type::MIN, store_order); assert_eq!(a.load(load_order), $int_type::MIN); a.store($int_type::MAX, store_order); assert_eq!(a.load(load_order), $int_type::MAX); } } }; ($atomic_type:ty, $int_type:ident) => { __test_atomic_int_load_store!($atomic_type, $int_type, single_thread); use crossbeam_utils::thread; use std::{collections::BTreeSet, vec, vec::Vec}; #[test] fn stress_load_store() { let mut rng = fastrand::Rng::new(); let (iterations, threads) = stress_test_config(&mut rng); let data1 = (0..iterations).map(|_| rng.$int_type(..)).collect::>(); let set = data1.iter().copied().collect::>(); let a = <$atomic_type>::new(data1[rng.usize(0..iterations)]); let now = &std::time::Instant::now(); thread::scope(|s| { for _ in 0..threads { s.spawn(|_| { let mut rng = fastrand::Rng::new(); let now = *now; for i in 0..iterations { a.store(data1[i], rand_store_ordering(&mut rng)); } std::eprintln!("store end={:?}", now.elapsed()); }); s.spawn(|_| { let mut rng = fastrand::Rng::new(); let now = *now; let mut v = vec![0; iterations]; for i in 0..iterations { v[i] = a.load(rand_load_ordering(&mut rng)); } std::eprintln!("load end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); } }) .unwrap(); } }; } macro_rules! __test_atomic_float_load_store { ($atomic_type:ty, $float_type:ident, single_thread) => { __test_atomic_common!($atomic_type, $float_type); use crate::tests::helper::{self, *}; #[test] fn accessor() { let a = <$atomic_type>::new(10.); unsafe { assert_eq!(*a.as_ptr(), 10.); *a.as_ptr() = 5.; assert_eq!(a.as_ptr() as *const (), &a as *const _ as *const ()); assert_eq!(*a.as_ptr(), 5.); } } // https://bugs.llvm.org/show_bug.cgi?id=37061 #[test] fn static_load_only() { static VAR: $atomic_type = <$atomic_type>::new(10.); for &order in &helper::LOAD_ORDERINGS { assert_eq!(VAR.load(order), 10.); } } #[test] fn load_store() { static VAR: $atomic_type = <$atomic_type>::new(10.); test_load_ordering(|order| VAR.load(order)); test_store_ordering(|order| VAR.store(10., order)); for (&load_order, &store_order) in helper::LOAD_ORDERINGS.iter().zip(&helper::STORE_ORDERINGS) { assert_eq!(VAR.load(load_order), 10.); VAR.store(5., store_order); assert_eq!(VAR.load(load_order), 5.); VAR.store(10., store_order); let a = <$atomic_type>::new(1.); assert_eq!(a.load(load_order), 1.); a.store(2., store_order); assert_eq!(a.load(load_order), 2.); } } }; ($atomic_type:ty, $float_type:ident) => { __test_atomic_float_load_store!($atomic_type, $float_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_bool_load_store { ($atomic_type:ty, single_thread) => { __test_atomic_common!($atomic_type, bool); use crate::tests::helper::{self, *}; #[test] fn accessor() { let a = <$atomic_type>::new(false); unsafe { assert_eq!(*a.as_ptr(), false); *a.as_ptr() = true; assert_eq!(a.as_ptr() as *const (), &a as *const _ as *const ()); assert_eq!(*a.as_ptr(), true); } } // https://bugs.llvm.org/show_bug.cgi?id=37061 #[test] fn static_load_only() { static VAR: $atomic_type = <$atomic_type>::new(false); for &order in &helper::LOAD_ORDERINGS { assert_eq!(VAR.load(order), false); } } #[test] fn load_store() { static VAR: $atomic_type = <$atomic_type>::new(false); test_load_ordering(|order| VAR.load(order)); test_store_ordering(|order| VAR.store(false, order)); for (&load_order, &store_order) in helper::LOAD_ORDERINGS.iter().zip(&helper::STORE_ORDERINGS) { assert_eq!(VAR.load(load_order), false); VAR.store(true, store_order); assert_eq!(VAR.load(load_order), true); VAR.store(false, store_order); let a = <$atomic_type>::new(true); assert_eq!(a.load(load_order), true); a.store(false, store_order); assert_eq!(a.load(load_order), false); } } }; ($atomic_type:ty) => { __test_atomic_bool_load_store!($atomic_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_ptr_load_store { ($atomic_type:ty, single_thread) => { __test_atomic_common!($atomic_type, *mut u8); use crate::tests::helper::{self, *}; use std::ptr; #[test] fn accessor() { let mut v = 1; let a = <$atomic_type>::new(ptr::null_mut()); unsafe { assert!((*a.as_ptr()).is_null()); *a.as_ptr() = &mut v; assert_eq!(a.as_ptr() as *const (), &a as *const _ as *const ()); assert!(!(*a.as_ptr()).is_null()); } } // https://bugs.llvm.org/show_bug.cgi?id=37061 #[test] fn static_load_only() { static VAR: $atomic_type = <$atomic_type>::new(ptr::null_mut()); for &order in &helper::LOAD_ORDERINGS { assert_eq!(VAR.load(order), ptr::null_mut()); } } #[test] fn load_store() { static VAR: $atomic_type = <$atomic_type>::new(ptr::null_mut()); test_load_ordering(|order| VAR.load(order)); test_store_ordering(|order| VAR.store(ptr::null_mut(), order)); let mut v = 1_u8; let p = &mut v as *mut u8; for (&load_order, &store_order) in helper::LOAD_ORDERINGS.iter().zip(&helper::STORE_ORDERINGS) { assert_eq!(VAR.load(load_order), ptr::null_mut()); VAR.store(p, store_order); assert_eq!(VAR.load(load_order), p); VAR.store(ptr::null_mut(), store_order); let a = <$atomic_type>::new(p); assert_eq!(a.load(load_order), p); a.store(ptr::null_mut(), store_order); assert_eq!(a.load(load_order), ptr::null_mut()); } } }; ($atomic_type:ty) => { __test_atomic_ptr_load_store!($atomic_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_int { ($atomic_type:ty, $int_type:ident, single_thread) => { #[test] fn swap() { let a = <$atomic_type>::new(5); test_swap_ordering(|order| a.swap(5, order)); for &order in &helper::SWAP_ORDERINGS { assert_eq!(a.swap(10, order), 5); assert_eq!(a.swap($int_type::MIN, order), 10); assert_eq!(a.swap($int_type::MAX, order), $int_type::MIN); assert_eq!(a.swap(5, order), $int_type::MAX); } } #[test] fn compare_exchange() { let a = <$atomic_type>::new(5); test_compare_exchange_ordering(|success, failure| { a.compare_exchange(5, 5, success, failure) }); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(5); assert_eq!(a.compare_exchange(5, 10, success, failure), Ok(5)); assert_eq!(a.load(Ordering::Relaxed), 10); assert_eq!(a.compare_exchange(6, 12, success, failure), Err(10)); assert_eq!(a.load(Ordering::Relaxed), 10); } } #[test] fn compare_exchange_weak() { let a = <$atomic_type>::new(4); test_compare_exchange_ordering(|success, failure| { a.compare_exchange_weak(4, 4, success, failure) }); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(4); assert_eq!(a.compare_exchange_weak(6, 8, success, failure), Err(4)); let mut old = a.load(Ordering::Relaxed); loop { let new = old * 2; match a.compare_exchange_weak(old, new, success, failure) { Ok(_) => break, Err(x) => old = x, } } assert_eq!(a.load(Ordering::Relaxed), 8); } } #[test] fn fetch_add() { let a = <$atomic_type>::new(0); test_swap_ordering(|order| a.fetch_add(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0); assert_eq!(a.fetch_add(10, order), 0); assert_eq!(a.load(Ordering::Relaxed), 10); let a = <$atomic_type>::new($int_type::MAX); assert_eq!(a.fetch_add(1, order), $int_type::MAX); assert_eq!(a.load(Ordering::Relaxed), $int_type::MAX.wrapping_add(1)); } } #[test] fn add() { let a = <$atomic_type>::new(0); test_swap_ordering(|order| a.add(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0); a.add(10, order); assert_eq!(a.load(Ordering::Relaxed), 10); let a = <$atomic_type>::new($int_type::MAX); a.add(1, order); assert_eq!(a.load(Ordering::Relaxed), $int_type::MAX.wrapping_add(1)); } } #[test] fn fetch_sub() { let a = <$atomic_type>::new(20); test_swap_ordering(|order| a.fetch_sub(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(20); assert_eq!(a.fetch_sub(10, order), 20); assert_eq!(a.load(Ordering::Relaxed), 10); let a = <$atomic_type>::new($int_type::MIN); assert_eq!(a.fetch_sub(1, order), $int_type::MIN); assert_eq!(a.load(Ordering::Relaxed), $int_type::MIN.wrapping_sub(1)); } } #[test] fn sub() { let a = <$atomic_type>::new(20); test_swap_ordering(|order| a.sub(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(20); a.sub(10, order); assert_eq!(a.load(Ordering::Relaxed), 10); let a = <$atomic_type>::new($int_type::MIN); a.sub(1, order); assert_eq!(a.load(Ordering::Relaxed), $int_type::MIN.wrapping_sub(1)); } } #[test] fn fetch_and() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.fetch_and(0b101101, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); assert_eq!(a.fetch_and(0b110011, order), 0b101101); assert_eq!(a.load(Ordering::Relaxed), 0b100001); } } #[test] fn and() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.and(0b101101, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); a.and(0b110011, order); assert_eq!(a.load(Ordering::Relaxed), 0b100001); } } #[test] fn fetch_nand() { let a = <$atomic_type>::new(0x13); test_swap_ordering(|order| a.fetch_nand(0x31, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0x13); assert_eq!(a.fetch_nand(0x31, order), 0x13); assert_eq!(a.load(Ordering::Relaxed), !(0x13 & 0x31)); } } #[test] fn fetch_or() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.fetch_or(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); assert_eq!(a.fetch_or(0b110011, order), 0b101101); assert_eq!(a.load(Ordering::Relaxed), 0b111111); } } #[test] fn or() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.or(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); a.or(0b110011, order); assert_eq!(a.load(Ordering::Relaxed), 0b111111); } } #[test] fn fetch_xor() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.fetch_xor(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); assert_eq!(a.fetch_xor(0b110011, order), 0b101101); assert_eq!(a.load(Ordering::Relaxed), 0b011110); } } #[test] fn xor() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.xor(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); a.xor(0b110011, order); assert_eq!(a.load(Ordering::Relaxed), 0b011110); } } #[test] fn fetch_max() { let a = <$atomic_type>::new(23); test_swap_ordering(|order| a.fetch_max(23, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(23); assert_eq!(a.fetch_max(22, order), 23); assert_eq!(a.load(Ordering::Relaxed), 23); assert_eq!(a.fetch_max(24, order), 23); assert_eq!(a.load(Ordering::Relaxed), 24); let a = <$atomic_type>::new(0); assert_eq!(a.fetch_max(1, order), 0); assert_eq!(a.load(Ordering::Relaxed), 1); assert_eq!(a.fetch_max(0, order), 1); assert_eq!(a.load(Ordering::Relaxed), 1); let a = <$atomic_type>::new(!0); assert_eq!(a.fetch_max(0, order), !0); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(!0, 0)); } } #[test] fn fetch_min() { let a = <$atomic_type>::new(23); test_swap_ordering(|order| a.fetch_min(23, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(23); assert_eq!(a.fetch_min(24, order), 23); assert_eq!(a.load(Ordering::Relaxed), 23); assert_eq!(a.fetch_min(22, order), 23); assert_eq!(a.load(Ordering::Relaxed), 22); let a = <$atomic_type>::new(1); assert_eq!(a.fetch_min(0, order), 1); assert_eq!(a.load(Ordering::Relaxed), 0); assert_eq!(a.fetch_min(1, order), 0); assert_eq!(a.load(Ordering::Relaxed), 0); let a = <$atomic_type>::new(!0); assert_eq!(a.fetch_min(0, order), !0); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(!0, 0)); } } #[test] fn fetch_not() { let a = <$atomic_type>::new(1); test_swap_ordering(|order| a.fetch_not(order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(1); assert_eq!(a.fetch_not(order), 1); assert_eq!(a.load(Ordering::Relaxed), !1); } } #[test] fn not() { let a = <$atomic_type>::new(1); test_swap_ordering(|order| a.not(order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(1); a.not(order); assert_eq!(a.load(Ordering::Relaxed), !1); } } #[test] fn fetch_neg() { let a = <$atomic_type>::new(5); test_swap_ordering(|order| a.fetch_neg(order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(5); assert_eq!(a.fetch_neg(order), 5); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::wrapping_neg(5)); assert_eq!(a.fetch_neg(order), <$int_type>::wrapping_neg(5)); assert_eq!(a.load(Ordering::Relaxed), 5); let a = <$atomic_type>::new(<$int_type>::MIN); assert_eq!(a.fetch_neg(order), <$int_type>::MIN); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::MIN.wrapping_neg()); assert_eq!(a.fetch_neg(order), <$int_type>::MIN.wrapping_neg()); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::MIN); } } #[test] fn neg() { let a = <$atomic_type>::new(5); test_swap_ordering(|order| a.neg(order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(5); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::wrapping_neg(5)); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), 5); let a = <$atomic_type>::new(<$int_type>::MIN); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::MIN.wrapping_neg()); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::MIN); } } #[test] fn bit_set() { let a = <$atomic_type>::new(0b0001); test_swap_ordering(|order| assert!(a.bit_set(0, order))); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b0000); assert!(!a.bit_set(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0001); assert!(a.bit_set(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0001); } } #[test] fn bit_clear() { let a = <$atomic_type>::new(0b0000); test_swap_ordering(|order| assert!(!a.bit_clear(0, order))); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b0001); assert!(a.bit_clear(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0000); assert!(!a.bit_clear(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0000); } } #[test] fn bit_toggle() { let a = <$atomic_type>::new(0b0000); test_swap_ordering(|order| a.bit_toggle(0, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b0000); assert!(!a.bit_toggle(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0001); assert!(a.bit_toggle(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0000); } } ::quickcheck::quickcheck! { fn quickcheck_swap(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.swap(y, order), x); assert_eq!(a.swap(x, order), y); } true } fn quickcheck_compare_exchange(x: $int_type, y: $int_type) -> bool { #[cfg(all( target_arch = "arm", not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), ))] { // TODO: LLVM bug: // https://github.com/llvm/llvm-project/issues/61880 // https://github.com/taiki-e/portable-atomic/issues/2 if core::mem::size_of::<$int_type>() <= 2 { return true; } } let mut rng = fastrand::Rng::new(); let z = loop { let z = rng.$int_type(..); if z != y { break z; } }; for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.compare_exchange(x, y, success, failure).unwrap(), x); assert_eq!(a.load(Ordering::Relaxed), y); assert_eq!(a.compare_exchange(z, x, success, failure).unwrap_err(), y); assert_eq!(a.load(Ordering::Relaxed), y); } true } fn quickcheck_fetch_add(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_add(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_add(y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_add(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_add(x)); } true } fn quickcheck_add(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.add(y, order); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_add(y)); let a = <$atomic_type>::new(y); a.add(x, order); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_add(x)); } true } fn quickcheck_fetch_sub(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_sub(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_sub(y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_sub(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_sub(x)); } true } fn quickcheck_sub(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.sub(y, order); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_sub(y)); let a = <$atomic_type>::new(y); a.sub(x, order); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_sub(x)); } true } fn quickcheck_fetch_and(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_and(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x & y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_and(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y & x); } true } fn quickcheck_and(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.and(y, order); assert_eq!(a.load(Ordering::Relaxed), x & y); let a = <$atomic_type>::new(y); a.and(x, order); assert_eq!(a.load(Ordering::Relaxed), y & x); } true } fn quickcheck_fetch_nand(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_nand(y, order), x); assert_eq!(a.load(Ordering::Relaxed), !(x & y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_nand(x, order), y); assert_eq!(a.load(Ordering::Relaxed), !(y & x)); } true } fn quickcheck_fetch_or(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_or(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x | y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_or(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y | x); } true } fn quickcheck_or(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.or(y, order); assert_eq!(a.load(Ordering::Relaxed), x | y); let a = <$atomic_type>::new(y); a.or(x, order); assert_eq!(a.load(Ordering::Relaxed), y | x); } true } fn quickcheck_fetch_xor(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_xor(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x ^ y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_xor(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y ^ x); } true } fn quickcheck_xor(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.xor(y, order); assert_eq!(a.load(Ordering::Relaxed), x ^ y); let a = <$atomic_type>::new(y); a.xor(x, order); assert_eq!(a.load(Ordering::Relaxed), y ^ x); } true } fn quickcheck_fetch_max(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_max(y, order), x); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(x, y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_max(x, order), y); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(y, x)); } true } fn quickcheck_fetch_min(x: $int_type, y: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_min(y, order), x); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(x, y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_min(x, order), y); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(y, x)); } true } fn quickcheck_fetch_not(x: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_not(order), x); assert_eq!(a.load(Ordering::Relaxed), !x); assert_eq!(a.fetch_not(order), !x); assert_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_not(x: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.not(order); assert_eq!(a.load(Ordering::Relaxed), !x); a.not(order); assert_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_fetch_neg(x: $int_type) -> bool { #[cfg(all( target_arch = "arm", not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), ))] { // TODO: LLVM bug: // https://github.com/llvm/llvm-project/issues/61880 // https://github.com/taiki-e/portable-atomic/issues/2 if core::mem::size_of::<$int_type>() <= 2 { return true; } } for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_neg(order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_neg()); assert_eq!(a.fetch_neg(order), x.wrapping_neg()); assert_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_neg(x: $int_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_neg()); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_bit_set(x: $int_type, bit: u32) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); let b = a.bit_set(bit, order); let mask = <$int_type>::wrapping_shl(1, bit); assert_eq!(a.load(Ordering::Relaxed), x | mask); assert_eq!(b, x & mask != 0); } true } fn quickcheck_bit_clear(x: $int_type, bit: u32) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); let b = a.bit_clear(bit, order); let mask = <$int_type>::wrapping_shl(1, bit); assert_eq!(a.load(Ordering::Relaxed), x & !mask); assert_eq!(b, x & mask != 0); } true } fn quickcheck_bit_toggle(x: $int_type, bit: u32) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); let b = a.bit_toggle(bit, order); let mask = <$int_type>::wrapping_shl(1, bit); assert_eq!(a.load(Ordering::Relaxed), x ^ mask); assert_eq!(b, x & mask != 0); } true } } }; ($atomic_type:ty, $int_type:ident) => { __test_atomic_int!($atomic_type, $int_type, single_thread); #[test] fn stress_swap() { let mut rng = fastrand::Rng::new(); let (iterations, threads) = stress_test_config(&mut rng); let data1 = &(0..threads) .map(|_| (0..iterations).map(|_| rng.$int_type(..)).collect::>()) .collect::>(); let data2 = &(0..threads) .map(|_| (0..iterations).map(|_| rng.$int_type(..)).collect::>()) .collect::>(); let set = &data1 .iter() .flat_map(|v| v.iter().copied()) .chain(data2.iter().flat_map(|v| v.iter().copied())) .collect::>(); let a = &<$atomic_type>::new(data2[0][rng.usize(0..iterations)]); let now = &std::time::Instant::now(); thread::scope(|s| { for thread in 0..threads { if thread % 2 == 0 { s.spawn(move |_| { let mut rng = fastrand::Rng::new(); let now = *now; for i in 0..iterations { a.store(data1[thread][i], rand_store_ordering(&mut rng)); } std::eprintln!("store end={:?}", now.elapsed()); }); } else { s.spawn(|_| { let mut rng = fastrand::Rng::new(); let now = *now; let mut v = vec![0; iterations]; for i in 0..iterations { v[i] = a.load(rand_load_ordering(&mut rng)); } std::eprintln!("load end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); } s.spawn(move |_| { let mut rng = fastrand::Rng::new(); let now = *now; let mut v = vec![0; iterations]; for i in 0..iterations { v[i] = a.swap(data2[thread][i], rand_swap_ordering(&mut rng)); } std::eprintln!("swap end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); } }) .unwrap(); } #[test] fn stress_compare_exchange() { let mut rng = fastrand::Rng::new(); let (iterations, threads) = stress_test_config(&mut rng); let data1 = &(0..threads) .map(|_| (0..iterations).map(|_| rng.$int_type(..)).collect::>()) .collect::>(); let data2 = &(0..threads) .map(|_| (0..iterations).map(|_| rng.$int_type(..)).collect::>()) .collect::>(); let set = &data1 .iter() .flat_map(|v| v.iter().copied()) .chain(data2.iter().flat_map(|v| v.iter().copied())) .collect::>(); let a = &<$atomic_type>::new(data2[0][rng.usize(0..iterations)]); let now = &std::time::Instant::now(); thread::scope(|s| { for thread in 0..threads { s.spawn(move |_| { let mut rng = fastrand::Rng::new(); let now = *now; for i in 0..iterations { a.store(data1[thread][i], rand_store_ordering(&mut rng)); } std::eprintln!("store end={:?}", now.elapsed()); }); s.spawn(|_| { let mut rng = fastrand::Rng::new(); let now = *now; let mut v = vec![data2[0][0]; iterations]; for i in 0..iterations { v[i] = a.load(rand_load_ordering(&mut rng)); } std::eprintln!("load end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); s.spawn(move |_| { let mut rng = fastrand::Rng::new(); let now = *now; let mut v = vec![data2[0][0]; iterations]; for i in 0..iterations { let old = if i % 2 == 0 { rng.$int_type(..) } else { a.load(Ordering::Relaxed) }; let new = data2[thread][i]; let o = rand_compare_exchange_ordering(&mut rng); match a.compare_exchange(old, new, o.0, o.1) { Ok(r) => assert_eq!(old, r), Err(r) => v[i] = r, } } std::eprintln!("compare_exchange end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); } }) .unwrap(); } }; } macro_rules! __test_atomic_float { ($atomic_type:ty, $float_type:ident, single_thread) => { #[test] fn swap() { let a = <$atomic_type>::new(5.); test_swap_ordering(|order| a.swap(5., order)); for &order in &helper::SWAP_ORDERINGS { assert_eq!(a.swap(10., order), 5.); assert_eq!(a.swap(5., order), 10.); } } #[test] fn compare_exchange() { let a = <$atomic_type>::new(5.); test_compare_exchange_ordering(|success, failure| { a.compare_exchange(5., 5., success, failure) }); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(5.); assert_eq!(a.compare_exchange(5., 10., success, failure), Ok(5.)); assert_eq!(a.load(Ordering::Relaxed), 10.); assert_eq!(a.compare_exchange(6., 12., success, failure), Err(10.)); assert_eq!(a.load(Ordering::Relaxed), 10.); } } #[test] fn compare_exchange_weak() { let a = <$atomic_type>::new(4.); test_compare_exchange_ordering(|success, failure| { a.compare_exchange_weak(4., 4., success, failure) }); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(4.); assert_eq!(a.compare_exchange_weak(6., 8., success, failure), Err(4.)); let mut old = a.load(Ordering::Relaxed); loop { let new = old * 2.; match a.compare_exchange_weak(old, new, success, failure) { Ok(_) => break, Err(x) => old = x, } } assert_eq!(a.load(Ordering::Relaxed), 8.); } } #[test] fn fetch_add() { let a = <$atomic_type>::new(0.); test_swap_ordering(|order| a.fetch_add(0., order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0.); assert_eq!(a.fetch_add(10., order), 0.); assert_eq!(a.load(Ordering::Relaxed), 10.); let a = <$atomic_type>::new($float_type::MAX); assert_eq!(a.fetch_add(1., order), $float_type::MAX); assert_eq!(a.load(Ordering::Relaxed), $float_type::MAX + 1.); } } #[test] fn fetch_sub() { let a = <$atomic_type>::new(20.); test_swap_ordering(|order| a.fetch_sub(0., order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(20.); assert_eq!(a.fetch_sub(10., order), 20.); assert_eq!(a.load(Ordering::Relaxed), 10.); let a = <$atomic_type>::new($float_type::MIN); assert_eq!(a.fetch_sub(1., order), $float_type::MIN); assert_eq!(a.load(Ordering::Relaxed), $float_type::MIN - 1.); } } #[test] fn fetch_max() { if mem::size_of::<$float_type>() == 16 && cfg!(any( target_arch = "arm", target_arch = "mips", target_arch = "mips32r6", target_vendor = "apple", windows, )) { // TODO(f128): return; } let a = <$atomic_type>::new(23.); test_swap_ordering(|order| a.fetch_max(23., order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(23.); assert_eq!(a.fetch_max(22., order), 23.); assert_eq!(a.load(Ordering::Relaxed), 23.); assert_eq!(a.fetch_max(24., order), 23.); assert_eq!(a.load(Ordering::Relaxed), 24.); } } #[test] fn fetch_min() { if mem::size_of::<$float_type>() == 16 && cfg!(any( target_arch = "arm", target_arch = "mips", target_arch = "mips32r6", target_vendor = "apple", windows, )) { // TODO(f128): return; } let a = <$atomic_type>::new(23.); test_swap_ordering(|order| a.fetch_min(23., order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(23.); assert_eq!(a.fetch_min(24., order), 23.); assert_eq!(a.load(Ordering::Relaxed), 23.); assert_eq!(a.fetch_min(22., order), 23.); assert_eq!(a.load(Ordering::Relaxed), 22.); } } #[test] fn fetch_neg() { let a = <$atomic_type>::new(5.); test_swap_ordering(|order| a.fetch_neg(order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(5.); assert_eq!(a.fetch_neg(order), 5.); assert_eq!(a.load(Ordering::Relaxed), -5.); assert_eq!(a.fetch_neg(order), -5.); assert_eq!(a.load(Ordering::Relaxed), 5.); } } #[test] fn fetch_abs() { let a = <$atomic_type>::new(23.); test_swap_ordering(|order| a.fetch_abs(order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(-23.); assert_eq!(a.fetch_abs(order), -23.); assert_eq!(a.load(Ordering::Relaxed), 23.); assert_eq!(a.fetch_abs(order), 23.); assert_eq!(a.load(Ordering::Relaxed), 23.); } } ::quickcheck::quickcheck! { fn quickcheck_swap(x: $float_type, y: $float_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.swap(y, order), x); assert_float_op_eq!(a.swap(x, order), y); } true } fn quickcheck_compare_exchange(x: $float_type, y: $float_type) -> bool { let mut rng = fastrand::Rng::new(); let z = loop { let z = float_rand::$float_type(&mut rng); if z != y { break z; } }; for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.compare_exchange(x, y, success, failure).unwrap(), x); assert_float_op_eq!(a.load(Ordering::Relaxed), y); assert_float_op_eq!( a.compare_exchange(z, x, success, failure).unwrap_err(), y, ); assert_float_op_eq!(a.load(Ordering::Relaxed), y); } true } fn quickcheck_fetch_add(x: $float_type, y: $float_type) -> bool { if cfg!(all(not(debug_assertions), target_arch = "x86", not(target_feature = "sse2"))) { // TODO: rustc bug: https://github.com/rust-lang/rust/issues/114479 return true; } for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_add(y, order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), x + y); let a = <$atomic_type>::new(y); assert_float_op_eq!(a.fetch_add(x, order), y); assert_float_op_eq!(a.load(Ordering::Relaxed), y + x); } true } fn quickcheck_fetch_sub(x: $float_type, y: $float_type) -> bool { if cfg!(all(not(debug_assertions), target_arch = "x86", not(target_feature = "sse2"))) { // TODO: rustc bug: https://github.com/rust-lang/rust/issues/114479 return true; } for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_sub(y, order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), x - y); let a = <$atomic_type>::new(y); assert_float_op_eq!(a.fetch_sub(x, order), y); assert_float_op_eq!(a.load(Ordering::Relaxed), y - x); } true } fn quickcheck_fetch_max(x: $float_type, y: $float_type) -> bool { if mem::size_of::<$float_type>() == 16 && cfg!(any( target_arch = "arm", target_arch = "mips", target_arch = "mips32r6", target_vendor = "apple", windows, )) { // TODO(f128): return true; } for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_max(y, order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), x.max(y)); let a = <$atomic_type>::new(y); assert_float_op_eq!(a.fetch_max(x, order), y); assert_float_op_eq!(a.load(Ordering::Relaxed), y.max(x)); } true } fn quickcheck_fetch_min(x: $float_type, y: $float_type) -> bool { if mem::size_of::<$float_type>() == 16 && cfg!(any( target_arch = "arm", target_arch = "mips", target_arch = "mips32r6", target_vendor = "apple", windows, )) { // TODO(f128): return true; } for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_min(y, order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), x.min(y)); let a = <$atomic_type>::new(y); assert_float_op_eq!(a.fetch_min(x, order), y); assert_float_op_eq!(a.load(Ordering::Relaxed), y.min(x)); } true } fn quickcheck_fetch_neg(x: $float_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_neg(order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), -x); assert_float_op_eq!(a.fetch_neg(order), -x); assert_float_op_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_fetch_abs(x: $float_type) -> bool { for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_abs(order), x); assert_float_op_eq!(a.fetch_abs(order), x.abs()); assert_float_op_eq!(a.load(Ordering::Relaxed), x.abs()); } true } } }; ($atomic_type:ty, $float_type:ident) => { __test_atomic_float!($atomic_type, $float_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_bool { ($atomic_type:ty, single_thread) => { #[test] fn swap() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.swap(true, order)); for &order in &helper::SWAP_ORDERINGS { assert_eq!(a.swap(true, order), true); assert_eq!(a.swap(false, order), true); assert_eq!(a.swap(false, order), false); assert_eq!(a.swap(true, order), false); } } #[test] fn compare_exchange() { let a = <$atomic_type>::new(true); test_compare_exchange_ordering(|success, failure| { a.compare_exchange(true, true, success, failure) }); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.compare_exchange(true, false, success, failure), Ok(true)); assert_eq!(a.load(Ordering::Relaxed), false); assert_eq!(a.compare_exchange(true, true, success, failure), Err(false)); assert_eq!(a.load(Ordering::Relaxed), false); } } #[test] fn compare_exchange_weak() { let a = <$atomic_type>::new(false); test_compare_exchange_ordering(|success, failure| { a.compare_exchange_weak(false, false, success, failure) }); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(false); assert_eq!(a.compare_exchange_weak(true, true, success, failure), Err(false)); let mut old = a.load(Ordering::Relaxed); let new = true; loop { match a.compare_exchange_weak(old, new, success, failure) { Ok(_) => break, Err(x) => old = x, } } assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn fetch_and() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| assert_eq!(a.fetch_and(true, order), true)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_and(false, order), true); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(true); assert_eq!(a.fetch_and(true, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_and(false, order), false); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_and(true, order), false); assert_eq!(a.load(Ordering::Relaxed), false); } } #[test] fn and() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.and(true, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); a.and(false, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(true); a.and(true, order); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); a.and(false, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.and(true, order); assert_eq!(a.load(Ordering::Relaxed), false); } } #[test] fn fetch_or() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| assert_eq!(a.fetch_or(false, order), true)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_or(false, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); assert_eq!(a.fetch_or(true, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_or(false, order), false); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_or(true, order), false); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn or() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.or(false, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); a.or(false, order); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); a.or(true, order); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); a.or(false, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.or(true, order); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn fetch_xor() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| assert_eq!(a.fetch_xor(false, order), true)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_xor(false, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); assert_eq!(a.fetch_xor(true, order), true); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_xor(false, order), false); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_xor(true, order), false); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn xor() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.xor(false, order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); a.xor(false, order); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); a.xor(true, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.xor(false, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.xor(true, order); assert_eq!(a.load(Ordering::Relaxed), true); } } ::quickcheck::quickcheck! { fn quickcheck_compare_exchange(x: bool, y: bool) -> bool { let z = !y; for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.compare_exchange(x, y, success, failure).unwrap(), x); assert_eq!(a.load(Ordering::Relaxed), y); assert_eq!(a.compare_exchange(z, x, success, failure).unwrap_err(), y); assert_eq!(a.load(Ordering::Relaxed), y); } true } } }; ($atomic_type:ty) => { __test_atomic_bool!($atomic_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_ptr { ($atomic_type:ty, single_thread) => { #[test] fn swap() { let a = <$atomic_type>::new(ptr::null_mut()); test_swap_ordering(|order| a.swap(ptr::null_mut(), order)); let x = &mut 1; for &order in &helper::SWAP_ORDERINGS { assert_eq!(a.swap(x, order), ptr::null_mut()); assert_eq!(a.swap(ptr::null_mut(), order), x as *mut _); } } #[test] fn compare_exchange() { let a = <$atomic_type>::new(ptr::null_mut()); test_compare_exchange_ordering(|success, failure| { a.compare_exchange(ptr::null_mut(), ptr::null_mut(), success, failure) }); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(ptr::null_mut()); let x = &mut 1; assert_eq!( a.compare_exchange(ptr::null_mut(), x, success, failure), Ok(ptr::null_mut()), ); assert_eq!(a.load(Ordering::Relaxed), x as *mut _); assert_eq!( a.compare_exchange(ptr::null_mut(), ptr::null_mut(), success, failure), Err(x as *mut _), ); assert_eq!(a.load(Ordering::Relaxed), x as *mut _); } } #[test] fn compare_exchange_weak() { let a = <$atomic_type>::new(ptr::null_mut()); test_compare_exchange_ordering(|success, failure| { a.compare_exchange_weak(ptr::null_mut(), ptr::null_mut(), success, failure) }); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(ptr::null_mut()); let x = &mut 1; assert_eq!(a.compare_exchange_weak(x, x, success, failure), Err(ptr::null_mut())); let mut old = a.load(Ordering::Relaxed); loop { match a.compare_exchange_weak(old, x, success, failure) { Ok(_) => break, Err(x) => old = x, } } assert_eq!(a.load(Ordering::Relaxed), x as *mut _); } } ::quickcheck::quickcheck! { fn quickcheck_swap(x: usize, y: usize) -> bool { let x = sptr::invalid_mut(x); let y = sptr::invalid_mut(y); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.swap(y, order), x); assert_eq!(a.swap(x, order), y); } true } fn quickcheck_compare_exchange(x: usize, y: usize) -> bool { let mut rng = fastrand::Rng::new(); let z = loop { let z = rng.usize(..); if z != y { break z; } }; let x = sptr::invalid_mut(x); let y = sptr::invalid_mut(y); let z = sptr::invalid_mut(z); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.compare_exchange(x, y, success, failure).unwrap(), x); assert_eq!(a.load(Ordering::Relaxed), y); assert_eq!(a.compare_exchange(z, x, success, failure).unwrap_err(), y); assert_eq!(a.load(Ordering::Relaxed), y); } true } } }; ($atomic_type:ty) => { __test_atomic_ptr!($atomic_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_int_pub { ($atomic_type:ty, $int_type:ident) => { __test_atomic_pub_common!($atomic_type, $int_type); use std::{boxed::Box, mem}; #[test] fn fetch_update() { let a = <$atomic_type>::new(7); test_compare_exchange_ordering(|set, fetch| a.fetch_update(set, fetch, |x| Some(x))); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(7); assert_eq!(a.fetch_update(success, failure, |_| None), Err(7)); assert_eq!(a.fetch_update(success, failure, |x| Some(x + 1)), Ok(7)); assert_eq!(a.fetch_update(success, failure, |x| Some(x + 1)), Ok(8)); assert_eq!(a.load(Ordering::SeqCst), 9); } } #[test] fn impls() { #[cfg(not(portable_atomic_no_const_transmute))] const INTO_INNER: $int_type = { let a = <$atomic_type>::new(10); a.into_inner() }; #[cfg(not(portable_atomic_no_const_mut_refs))] const GET_MUT: $atomic_type = { let mut a = <$atomic_type>::new(10); let _ = unsafe { <$atomic_type>::from_ptr(a.as_ptr()) }; *a.get_mut() = 5; a }; #[cfg(not(portable_atomic_no_const_transmute))] { assert_eq!(INTO_INNER, 10); } #[cfg(not(portable_atomic_no_const_mut_refs))] { assert_eq!(GET_MUT.into_inner(), 5); } let a = <$atomic_type>::default(); let b = <$atomic_type>::from(0); assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst)); assert_eq!(std::format!("{:?}", a), std::format!("{:?}", a.load(Ordering::SeqCst))); assert_eq!(a.into_inner(), 0); assert_eq!(b.into_inner(), 0); unsafe { let ptr: *mut Align16<$int_type> = Box::into_raw(Box::new(Align16(0))); assert!(ptr as usize % mem::align_of::<$atomic_type>() == 0); { let a = <$atomic_type>::from_ptr(ptr.cast::<$int_type>()); *a.as_ptr() = 1; } assert_eq!((*ptr).0, 1); drop(Box::from_raw(ptr)); } } ::quickcheck::quickcheck! { fn quickcheck_fetch_update(x: $int_type, y: $int_type) -> bool { let mut rng = fastrand::Rng::new(); let z = loop { let z = rng.$int_type(..); if z != y { break z; } }; for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!( a.fetch_update(success, failure, |_| Some(y)) .unwrap(), x ); assert_eq!( a.fetch_update(success, failure, |_| Some(z)) .unwrap(), y ); assert_eq!(a.load(Ordering::Relaxed), z); assert_eq!( a.fetch_update(success, failure, |z| if z == y { Some(z) } else { None }) .unwrap_err(), z ); assert_eq!(a.load(Ordering::Relaxed), z); } true } } }; } macro_rules! __test_atomic_float_pub { ($atomic_type:ty, $float_type:ident) => { __test_atomic_pub_common!($atomic_type, $float_type); use std::{boxed::Box, mem}; #[test] fn fetch_update() { let a = <$atomic_type>::new(7.); test_compare_exchange_ordering(|set, fetch| a.fetch_update(set, fetch, |x| Some(x))); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(7.); assert_eq!(a.fetch_update(success, failure, |_| None), Err(7.)); assert_eq!(a.fetch_update(success, failure, |x| Some(x + 1.)), Ok(7.)); assert_eq!(a.fetch_update(success, failure, |x| Some(x + 1.)), Ok(8.)); assert_eq!(a.load(Ordering::SeqCst), 9.); } } #[test] fn impls() { #[cfg(not(portable_atomic_no_const_transmute))] const INTO_INNER: $float_type = { let a = <$atomic_type>::new(10.); a.into_inner() }; #[cfg(not(portable_atomic_no_const_mut_refs))] const GET_MUT: $atomic_type = { let mut a = <$atomic_type>::new(10.); let _ = unsafe { <$atomic_type>::from_ptr(a.as_ptr()) }; *a.get_mut() = 5.; a }; #[cfg(not(portable_atomic_no_const_transmute))] { assert_eq!(INTO_INNER, 10.); } #[cfg(not(portable_atomic_no_const_mut_refs))] { assert_eq!(GET_MUT.into_inner(), 5.); } let a = <$atomic_type>::default(); let b = <$atomic_type>::from(0.); assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst)); assert_eq!(std::format!("{:?}", a), std::format!("{:?}", a.load(Ordering::SeqCst))); assert_eq!(a.into_inner(), 0.); assert_eq!(b.into_inner(), 0.); unsafe { let ptr: *mut Align16<$float_type> = Box::into_raw(Box::new(Align16(0.))); assert!(ptr as usize % mem::align_of::<$atomic_type>() == 0); { let a = <$atomic_type>::from_ptr(ptr.cast::<$float_type>()); *a.as_ptr() = 1.; } assert_eq!((*ptr).0, 1.); drop(Box::from_raw(ptr)); } } }; } macro_rules! __test_atomic_bool_pub { ($atomic_type:ty) => { __test_atomic_pub_common!($atomic_type, bool); use std::{boxed::Box, mem}; #[test] fn fetch_nand() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| assert_eq!(a.fetch_nand(false, order), true)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_nand(false, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); assert_eq!(a.fetch_nand(true, order), true); assert_eq!(a.load(Ordering::Relaxed) as usize, 0); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_nand(false, order), false); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_nand(true, order), false); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn fetch_not() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.fetch_not(order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_not(order), true); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_not(order), false); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn not() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.fetch_not(order)); for &order in &helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); a.not(order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.not(order); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn fetch_update() { let a = <$atomic_type>::new(false); test_compare_exchange_ordering(|set, fetch| a.fetch_update(set, fetch, |x| Some(x))); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(false); assert_eq!(a.fetch_update(success, failure, |_| None), Err(false)); assert_eq!(a.fetch_update(success, failure, |x| Some(!x)), Ok(false)); assert_eq!(a.fetch_update(success, failure, |x| Some(!x)), Ok(true)); assert_eq!(a.load(Ordering::SeqCst), false); } } #[test] fn impls() { #[cfg(not(portable_atomic_no_const_transmute))] const INTO_INNER: bool = { let a = <$atomic_type>::new(true); a.into_inner() }; #[cfg(not(portable_atomic_no_const_mut_refs))] const GET_MUT: $atomic_type = { let mut a = <$atomic_type>::new(true); let _ = unsafe { <$atomic_type>::from_ptr(a.as_ptr()) }; *a.get_mut() = false; a }; #[cfg(not(portable_atomic_no_const_transmute))] { assert_eq!(INTO_INNER, true); } #[cfg(not(portable_atomic_no_const_mut_refs))] { assert_eq!(GET_MUT.into_inner(), false); } let a = <$atomic_type>::default(); let b = <$atomic_type>::from(false); assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst)); assert_eq!(std::format!("{:?}", a), std::format!("{:?}", a.load(Ordering::SeqCst))); assert_eq!(a.into_inner(), false); assert_eq!(b.into_inner(), false); unsafe { let ptr: *mut bool = Box::into_raw(Box::new(false)); assert!(ptr as usize % mem::align_of::<$atomic_type>() == 0); { let a = <$atomic_type>::from_ptr(ptr); *a.as_ptr() = true; } assert_eq!((*ptr), true); drop(Box::from_raw(ptr)); } } }; } macro_rules! __test_atomic_ptr_pub { ($atomic_type:ty) => { __test_atomic_pub_common!($atomic_type, *mut u8); #[allow(unused_imports)] use sptr::Strict as _; // for old rustc use std::{boxed::Box, mem}; #[test] fn fetch_update() { let a = <$atomic_type>::new(ptr::null_mut()); test_compare_exchange_ordering(|set, fetch| a.fetch_update(set, fetch, |x| Some(x))); for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(ptr::null_mut()); assert_eq!(a.fetch_update(success, failure, |_| None), Err(ptr::null_mut())); assert_eq!( a.fetch_update(success, failure, |_| Some(&a as *const _ as *mut _)), Ok(ptr::null_mut()) ); assert_eq!(a.load(Ordering::SeqCst), &a as *const _ as *mut _); } } #[test] fn impls() { #[cfg(not(portable_atomic_no_const_transmute))] const INTO_INNER: *mut u8 = { let a = <$atomic_type>::new(ptr::null_mut()); a.into_inner() }; #[cfg(not(portable_atomic_no_const_mut_refs))] const GET_MUT: $atomic_type = { let mut a = <$atomic_type>::new(ptr::null_mut()); let _ = unsafe { <$atomic_type>::from_ptr(a.as_ptr()) }; *a.get_mut() = ptr::null_mut::().wrapping_add(1); a }; #[cfg(not(portable_atomic_no_const_transmute))] { assert!(INTO_INNER.is_null()); } #[cfg(not(portable_atomic_no_const_mut_refs))] { assert_eq!(GET_MUT.into_inner(), ptr::null_mut::().wrapping_add(1)); } let a = <$atomic_type>::default(); let b = <$atomic_type>::from(ptr::null_mut()); assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst)); assert_eq!(std::format!("{:?}", a), std::format!("{:?}", a.load(Ordering::SeqCst))); assert_eq!(std::format!("{:p}", a), std::format!("{:p}", a.load(Ordering::SeqCst))); assert_eq!(a.into_inner(), ptr::null_mut()); assert_eq!(b.into_inner(), ptr::null_mut()); unsafe { let ptr: *mut Align16<*mut u8> = Box::into_raw(Box::new(Align16(ptr::null_mut()))); assert!(ptr as usize % mem::align_of::<$atomic_type>() == 0); { let a = <$atomic_type>::from_ptr(ptr.cast::<*mut u8>()); *a.as_ptr() = ptr::null_mut::().wrapping_add(1); } assert_eq!((*ptr).0, ptr::null_mut::().wrapping_add(1)); drop(Box::from_raw(ptr)); } } // https://github.com/rust-lang/rust/blob/1.84.0/library/core/tests/atomic.rs#L130-L213 #[test] fn ptr_add_null() { let atom = AtomicPtr::::new(core::ptr::null_mut()); assert_eq!(atom.fetch_ptr_add(1, Ordering::SeqCst).addr(), 0); assert_eq!(atom.load(Ordering::SeqCst).addr(), 8); assert_eq!(atom.fetch_byte_add(1, Ordering::SeqCst).addr(), 8); assert_eq!(atom.load(Ordering::SeqCst).addr(), 9); assert_eq!(atom.fetch_ptr_sub(1, Ordering::SeqCst).addr(), 9); assert_eq!(atom.load(Ordering::SeqCst).addr(), 1); assert_eq!(atom.fetch_byte_sub(1, Ordering::SeqCst).addr(), 1); assert_eq!(atom.load(Ordering::SeqCst).addr(), 0); } #[test] fn ptr_add_data() { let num = 0i64; let n = &num as *const i64 as *mut _; let atom = AtomicPtr::::new(n); assert_eq!(atom.fetch_ptr_add(1, Ordering::SeqCst), n); assert_eq!(atom.load(Ordering::SeqCst), n.wrapping_add(1)); assert_eq!(atom.fetch_ptr_sub(1, Ordering::SeqCst), n.wrapping_add(1)); assert_eq!(atom.load(Ordering::SeqCst), n); #[allow(clippy::cast_ptr_alignment)] let bytes_from_n = |b| n.cast::().wrapping_add(b).cast::(); assert_eq!(atom.fetch_byte_add(1, Ordering::SeqCst), n); assert_eq!(atom.load(Ordering::SeqCst), bytes_from_n(1)); assert_eq!(atom.fetch_byte_add(5, Ordering::SeqCst), bytes_from_n(1)); assert_eq!(atom.load(Ordering::SeqCst), bytes_from_n(6)); assert_eq!(atom.fetch_byte_sub(1, Ordering::SeqCst), bytes_from_n(6)); assert_eq!(atom.load(Ordering::SeqCst), bytes_from_n(5)); assert_eq!(atom.fetch_byte_sub(5, Ordering::SeqCst), bytes_from_n(5)); assert_eq!(atom.load(Ordering::SeqCst), n); } #[test] fn ptr_bitops() { let atom = AtomicPtr::::new(core::ptr::null_mut()); assert_eq!(atom.fetch_or(0b0111, Ordering::SeqCst).addr(), 0); assert_eq!(atom.load(Ordering::SeqCst).addr(), 0b0111); assert_eq!(atom.fetch_and(0b1101, Ordering::SeqCst).addr(), 0b0111); assert_eq!(atom.load(Ordering::SeqCst).addr(), 0b0101); assert_eq!(atom.fetch_xor(0b1111, Ordering::SeqCst).addr(), 0b0101); assert_eq!(atom.load(Ordering::SeqCst).addr(), 0b1010); } #[test] fn ptr_bitops_tagging() { const MASK_TAG: usize = 0b1111; const MASK_PTR: usize = !MASK_TAG; #[repr(align(16))] struct Tagme(#[allow(dead_code)] u128); let tagme = Tagme(1000); let ptr = &tagme as *const Tagme as *mut Tagme; let atom: AtomicPtr = AtomicPtr::new(ptr); assert_eq!(ptr.addr() & MASK_TAG, 0); assert_eq!(atom.fetch_or(0b0111, Ordering::SeqCst), ptr); assert_eq!(atom.load(Ordering::SeqCst), ptr.map_addr(|a| a | 0b111)); assert_eq!( atom.fetch_and(MASK_PTR | 0b0010, Ordering::SeqCst), ptr.map_addr(|a| a | 0b111) ); assert_eq!(atom.load(Ordering::SeqCst), ptr.map_addr(|a| a | 0b0010)); assert_eq!(atom.fetch_xor(0b1011, Ordering::SeqCst), ptr.map_addr(|a| a | 0b0010)); assert_eq!(atom.load(Ordering::SeqCst), ptr.map_addr(|a| a | 0b1001)); assert_eq!(atom.fetch_and(MASK_PTR, Ordering::SeqCst), ptr.map_addr(|a| a | 0b1001)); assert_eq!(atom.load(Ordering::SeqCst), ptr); } #[test] fn bit_set() { let a = <$atomic_type>::new(ptr::null_mut::().cast::().map_addr(|a| a | 1)); test_swap_ordering(|order| assert!(a.bit_set(0, order))); for &order in &helper::SWAP_ORDERINGS { let pointer = &mut 1u64 as *mut u64 as *mut u8; let atom = <$atomic_type>::new(pointer); // Tag the bottom bit of the pointer. assert!(!atom.bit_set(0, order)); // Extract and untag. let tagged = atom.load(Ordering::Relaxed); assert_eq!(tagged.addr() & 1, 1); assert_eq!(tagged.map_addr(|p| p & !1), pointer); } } #[test] fn bit_clear() { let a = <$atomic_type>::new(ptr::null_mut::().cast::()); test_swap_ordering(|order| assert!(!a.bit_clear(0, order))); for &order in &helper::SWAP_ORDERINGS { let pointer = &mut 1u64 as *mut u64 as *mut u8; // A tagged pointer let atom = <$atomic_type>::new(pointer.map_addr(|a| a | 1)); assert!(atom.bit_set(0, order)); // Untag assert!(atom.bit_clear(0, order)); } } #[test] fn bit_toggle() { let a = <$atomic_type>::new(ptr::null_mut::().cast::()); test_swap_ordering(|order| a.bit_toggle(0, order)); for &order in &helper::SWAP_ORDERINGS { let pointer = &mut 1u64 as *mut u64 as *mut u8; let atom = <$atomic_type>::new(pointer); // Toggle a tag bit on the pointer. atom.bit_toggle(0, order); assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1); } } }; } macro_rules! test_atomic_int_load_store { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type); } } }; } macro_rules! test_atomic_ptr_load_store { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_ptr { use super::*; __test_atomic_ptr_load_store!(AtomicPtr); } }; } macro_rules! test_atomic_int_single_thread { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type, single_thread); __test_atomic_int!([], $int_type, single_thread); } } }; } macro_rules! test_atomic_ptr_single_thread { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_ptr { use super::*; __test_atomic_ptr_load_store!(AtomicPtr, single_thread); __test_atomic_ptr!(AtomicPtr, single_thread); } }; } macro_rules! test_atomic_int { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type); __test_atomic_int!([], $int_type); } } }; } macro_rules! test_atomic_ptr { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] #[allow(unstable_name_collisions)] // for sptr crate mod test_atomic_ptr { use super::*; __test_atomic_ptr_load_store!(AtomicPtr); __test_atomic_ptr!(AtomicPtr); } }; } macro_rules! test_atomic_int_pub { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type); __test_atomic_int!([], $int_type); __test_atomic_int_pub!([], $int_type); } } }; } #[cfg(feature = "float")] macro_rules! test_atomic_float_pub { ($float_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::float_arithmetic, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_float_load_store!([], $float_type); __test_atomic_float!([], $float_type); __test_atomic_float_pub!([], $float_type); } } }; } macro_rules! test_atomic_bool_pub { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_bool { use super::*; __test_atomic_bool_load_store!(AtomicBool); __test_atomic_bool!(AtomicBool); __test_atomic_bool_pub!(AtomicBool); } }; } macro_rules! test_atomic_ptr_pub { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] #[allow(unstable_name_collisions)] // for sptr crate mod test_atomic_ptr { use super::*; __test_atomic_ptr_load_store!(AtomicPtr); __test_atomic_ptr!(AtomicPtr); __test_atomic_ptr_pub!(AtomicPtr); } }; } // Asserts that `$a` and `$b` have performed equivalent operations. #[cfg(feature = "float")] macro_rules! assert_float_op_eq { ($a:expr, $b:expr $(,)?) => {{ // See also: // - https://github.com/rust-lang/unsafe-code-guidelines/issues/237. // - https://github.com/rust-lang/portable-simd/issues/39. let a = $a; let b = $b; if a.is_nan() && b.is_nan() // don't check sign of NaN: https://github.com/rust-lang/rust/issues/55131 || a.is_infinite() && b.is_infinite() && a.is_sign_positive() == b.is_sign_positive() && a.is_sign_negative() == b.is_sign_negative() { // ok } else { assert_eq!(a, b); } }}; } #[allow(unused_unsafe)] // for old rustc #[cfg_attr(not(portable_atomic_no_track_caller), track_caller)] pub(crate) fn assert_panic(f: impl FnOnce() -> T) -> std::string::String { let backtrace = std::env::var_os("RUST_BACKTRACE"); let hook = std::panic::take_hook(); // set_var/remove_var is fine as we run tests with RUST_TEST_THREADS=1 // std::panic::set_backtrace_style is better way here, but is unstable. unsafe { std::env::set_var("RUST_BACKTRACE", "0") } // Suppress backtrace std::panic::set_hook(std::boxed::Box::new(|_| {})); // Suppress panic msg let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)); std::panic::set_hook(hook); match backtrace { Some(v) => unsafe { std::env::set_var("RUST_BACKTRACE", v) }, None => unsafe { std::env::remove_var("RUST_BACKTRACE") }, } let msg = res.unwrap_err(); msg.downcast_ref::() .cloned() .unwrap_or_else(|| msg.downcast_ref::<&'static str>().copied().unwrap().into()) } pub(crate) fn rand_load_ordering(rng: &mut fastrand::Rng) -> Ordering { helper::LOAD_ORDERINGS[rng.usize(0..helper::LOAD_ORDERINGS.len())] } pub(crate) fn test_load_ordering(f: impl Fn(Ordering) -> T) { for &order in &helper::LOAD_ORDERINGS { f(order); } if !skip_should_panic_test() { assert_eq!( assert_panic(|| f(Ordering::Release)), "there is no such thing as a release load" ); assert_eq!( assert_panic(|| f(Ordering::AcqRel)), "there is no such thing as an acquire-release load" ); } } pub(crate) fn rand_store_ordering(rng: &mut fastrand::Rng) -> Ordering { helper::STORE_ORDERINGS[rng.usize(0..helper::STORE_ORDERINGS.len())] } pub(crate) fn test_store_ordering(f: impl Fn(Ordering) -> T) { for &order in &helper::STORE_ORDERINGS { f(order); } if !skip_should_panic_test() { assert_eq!( assert_panic(|| f(Ordering::Acquire)), "there is no such thing as an acquire store" ); assert_eq!( assert_panic(|| f(Ordering::AcqRel)), "there is no such thing as an acquire-release store" ); } } pub(crate) fn rand_compare_exchange_ordering(rng: &mut fastrand::Rng) -> (Ordering, Ordering) { helper::COMPARE_EXCHANGE_ORDERINGS[rng.usize(0..helper::COMPARE_EXCHANGE_ORDERINGS.len())] } pub(crate) fn test_compare_exchange_ordering( f: impl Fn(Ordering, Ordering) -> T, ) { for &(success, failure) in &helper::COMPARE_EXCHANGE_ORDERINGS { f(success, failure); } if !skip_should_panic_test() { for &order in &helper::SWAP_ORDERINGS { let msg = assert_panic(|| f(order, Ordering::AcqRel)); assert!( msg == "there is no such thing as an acquire-release failure ordering" || msg == "there is no such thing as an acquire-release load", "{}", msg ); let msg = assert_panic(|| f(order, Ordering::Release)); assert!( msg == "there is no such thing as a release failure ordering" || msg == "there is no such thing as a release load", "{}", msg ); } } } pub(crate) fn rand_swap_ordering(rng: &mut fastrand::Rng) -> Ordering { helper::SWAP_ORDERINGS[rng.usize(0..helper::SWAP_ORDERINGS.len())] } pub(crate) fn test_swap_ordering(f: impl Fn(Ordering) -> T) { for &order in &helper::SWAP_ORDERINGS { f(order); } } // for stress test generated by __test_atomic_* macros pub(crate) fn stress_test_config(rng: &mut fastrand::Rng) -> (usize, usize) { let iterations = if cfg!(miri) { 50 } else if cfg!(debug_assertions) { 5_000 } else { 25_000 }; let threads = if cfg!(debug_assertions) { 2 } else { rng.usize(2..=8) }; std::eprintln!("threads={}", threads); (iterations, threads) } fn skip_should_panic_test() -> bool { // Miri's panic handling is slow // MSAN false positive: https://gist.github.com/taiki-e/dd6269a8ffec46284fdc764a4849f884 is_panic_abort() || cfg!(miri) || option_env!("CARGO_PROFILE_RELEASE_LTO").map_or(false, |v| v == "fat") && build_context::SANITIZE.contains("memory") } // For -C panic=abort -Z panic_abort_tests: https://github.com/rust-lang/rust/issues/67650 fn is_panic_abort() -> bool { build_context::PANIC.contains("abort") } pub(crate) const LOAD_ORDERINGS: [Ordering; 3] = [Ordering::Relaxed, Ordering::Acquire, Ordering::SeqCst]; pub(crate) const STORE_ORDERINGS: [Ordering; 3] = [Ordering::Relaxed, Ordering::Release, Ordering::SeqCst]; pub(crate) const SWAP_ORDERINGS: [Ordering; 5] = [Ordering::Relaxed, Ordering::Release, Ordering::Acquire, Ordering::AcqRel, Ordering::SeqCst]; pub(crate) const COMPARE_EXCHANGE_ORDERINGS: [(Ordering, Ordering); 15] = [ (Ordering::Relaxed, Ordering::Relaxed), (Ordering::Relaxed, Ordering::Acquire), (Ordering::Relaxed, Ordering::SeqCst), (Ordering::Acquire, Ordering::Relaxed), (Ordering::Acquire, Ordering::Acquire), (Ordering::Acquire, Ordering::SeqCst), (Ordering::Release, Ordering::Relaxed), (Ordering::Release, Ordering::Acquire), (Ordering::Release, Ordering::SeqCst), (Ordering::AcqRel, Ordering::Relaxed), (Ordering::AcqRel, Ordering::Acquire), (Ordering::AcqRel, Ordering::SeqCst), (Ordering::SeqCst, Ordering::Relaxed), (Ordering::SeqCst, Ordering::Acquire), (Ordering::SeqCst, Ordering::SeqCst), ]; #[repr(C, align(16))] pub(crate) struct Align16(pub(crate) T); // Test the cases that should not fail if the memory ordering is implemented correctly. // This is still not exhaustive and only tests a few cases. // This currently only supports 32-bit or more integers. macro_rules! __stress_test_acquire_release { (should_pass, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => { paste::paste! { #[test] #[cfg_attr(all(debug_assertions, not(miri)), ignore)] // debug mode is slow. #[allow(clippy::cast_possible_truncation)] fn []() { __stress_test_acquire_release!([], $int_type, $write, $load_order, $store_order); } } }; (can_panic, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => { paste::paste! { // Currently, to make this test work well enough outside of Miri, tens of thousands // of iterations are needed, but this test is slow in some environments. // So, ignore on non-Miri environments by default. See also catch_unwind_on_weak_memory_arch. #[test] #[cfg_attr(not(miri), ignore)] #[allow(clippy::cast_possible_truncation)] fn []() { can_panic("a=", || __stress_test_acquire_release!([], $int_type, $write, $load_order, $store_order)); } } }; ($atomic_type:ident, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => {{ use super::*; use crossbeam_utils::thread; use std::{ convert::TryFrom as _, sync::atomic::{AtomicUsize, Ordering}, }; let mut n: usize = if cfg!(miri) { 10 } else { 50_000 }; // This test is relatively fast because it spawns only one thread, but // the iterations are limited to a maximum value of integers. if $int_type::try_from(n).is_err() { n = $int_type::MAX as usize; } let a = &$atomic_type::new(0); let b = &AtomicUsize::new(0); thread::scope(|s| { s.spawn(|_| { for i in 0..n { b.store(i, Ordering::Relaxed); a.$write(i as $int_type, Ordering::$store_order); } }); loop { let a = a.load(Ordering::$load_order); let b = b.load(Ordering::Relaxed); assert!(a as usize <= b, "a={},b={}", a, b); if a as usize == n - 1 { break; } } }) .unwrap(); }}; } macro_rules! __stress_test_seqcst { (should_pass, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => { paste::paste! { // Currently, to make this test work well enough outside of Miri, tens of thousands // of iterations are needed, but this test is very slow in some environments because // it creates two threads for each iteration. // So, ignore on QEMU by default. #[test] #[cfg_attr(any(all(debug_assertions, not(miri)), qemu), ignore)] // debug mode is slow. fn []() { __stress_test_seqcst!([], $write, $load_order, $store_order); } } }; (can_panic, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => { paste::paste! { // Currently, to make this test work well enough outside of Miri, tens of thousands // of iterations are needed, but this test is very slow in some environments because // it creates two threads for each iteration. // So, ignore on non-Miri environments by default. See also catch_unwind_on_non_seqcst_arch. #[test] #[cfg_attr(not(miri), ignore)] fn []() { can_panic("c=2", || __stress_test_seqcst!([], $write, $load_order, $store_order)); } } }; ($atomic_type:ident, $write:ident, $load_order:ident, $store_order:ident) => {{ use super::*; use crossbeam_utils::thread; use std::sync::atomic::{AtomicUsize, Ordering}; let n: usize = if cfg!(miri) { 8 } else if cfg!(valgrind) || build_context::SANITIZE.contains("address") || build_context::SANITIZE.contains("memory") { 50 } else if option_env!("GITHUB_ACTIONS").is_some() && cfg!(not(target_os = "linux")) { // GitHub Actions' macOS and Windows runners are slow. 5_000 } else { 50_000 }; let a = &$atomic_type::new(0); let b = &$atomic_type::new(0); let c = &AtomicUsize::new(0); let ready = &AtomicUsize::new(0); thread::scope(|s| { for n in 0..n { a.store(0, Ordering::Relaxed); b.store(0, Ordering::Relaxed); c.store(0, Ordering::Relaxed); let h_a = s.spawn(|_| { while ready.load(Ordering::Relaxed) == 0 {} a.$write(1, Ordering::$store_order); if b.load(Ordering::$load_order) == 0 { c.fetch_add(1, Ordering::Relaxed); } }); let h_b = s.spawn(|_| { while ready.load(Ordering::Relaxed) == 0 {} b.$write(1, Ordering::$store_order); if a.load(Ordering::$load_order) == 0 { c.fetch_add(1, Ordering::Relaxed); } }); ready.store(1, Ordering::Relaxed); h_a.join().unwrap(); h_b.join().unwrap(); let c = c.load(Ordering::Relaxed); assert!(c == 0 || c == 1, "c={},n={}", c, n); } }) .unwrap(); }}; } // Catches unwinding panic on architectures with weak memory models. #[allow(dead_code)] pub(crate) fn catch_unwind_on_weak_memory_arch(pat: &str, f: impl Fn()) { // With x86 TSO, RISC-V TSO (optional, not default), SPARC TSO (optional, default), // and IBM-370 memory models should never be a panic here. // Miri emulates weak memory models regardless of target architectures. if cfg!(all( any( target_arch = "x86", target_arch = "x86_64", target_arch = "s390x", target_arch = "sparc", target_arch = "sparc64", ), not(any(miri)), )) { f(); } else if !is_panic_abort() { // This could be is_err on architectures with weak memory models. // However, this does not necessarily mean that it will always be panic, // and implementing it with stronger orderings is also okay. match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) { Ok(()) => { // panic!(); } Err(msg) => { let msg = msg .downcast_ref::() .cloned() .unwrap_or_else(|| msg.downcast_ref::<&'static str>().copied().unwrap().into()); assert!(msg.contains(pat), "{}", msg); } } } } // Catches unwinding panic on architectures with non-sequentially consistent memory models. #[allow(dead_code)] pub(crate) fn catch_unwind_on_non_seqcst_arch(pat: &str, f: impl Fn()) { if !is_panic_abort() { // This could be Err on architectures with non-sequentially consistent memory models. // However, this does not necessarily mean that it will always be panic, // and implementing it with stronger orderings is also okay. match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) { Ok(()) => { // panic!(); } Err(msg) => { let msg = msg .downcast_ref::() .cloned() .unwrap_or_else(|| msg.downcast_ref::<&'static str>().copied().unwrap().into()); assert!(msg.contains(pat), "{}", msg); } } } } macro_rules! stress_test_load_store { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use crate::tests::helper::catch_unwind_on_weak_memory_arch as can_panic; __stress_test_acquire_release!(can_panic, $int_type, store, Relaxed, Relaxed); __stress_test_acquire_release!(can_panic, $int_type, store, Relaxed, Release); __stress_test_acquire_release!(can_panic, $int_type, store, Relaxed, SeqCst); __stress_test_acquire_release!(can_panic, $int_type, store, Acquire, Relaxed); __stress_test_acquire_release!(should_pass, $int_type, store, Acquire, Release); __stress_test_acquire_release!(should_pass, $int_type, store, Acquire, SeqCst); __stress_test_acquire_release!(can_panic, $int_type, store, SeqCst, Relaxed); __stress_test_acquire_release!(should_pass, $int_type, store, SeqCst, Release); __stress_test_acquire_release!(should_pass, $int_type, store, SeqCst, SeqCst); } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use crate::tests::helper::catch_unwind_on_non_seqcst_arch as can_panic; __stress_test_seqcst!(can_panic, $int_type, store, Relaxed, Relaxed); __stress_test_seqcst!(can_panic, $int_type, store, Relaxed, Release); __stress_test_seqcst!(can_panic, $int_type, store, Relaxed, SeqCst); __stress_test_seqcst!(can_panic, $int_type, store, Acquire, Relaxed); __stress_test_seqcst!(can_panic, $int_type, store, Acquire, Release); __stress_test_seqcst!(can_panic, $int_type, store, Acquire, SeqCst); __stress_test_seqcst!(can_panic, $int_type, store, SeqCst, Relaxed); __stress_test_seqcst!(can_panic, $int_type, store, SeqCst, Release); __stress_test_seqcst!(should_pass, $int_type, store, SeqCst, SeqCst); } } }; } macro_rules! stress_test { ($int_type:ident) => { stress_test_load_store!($int_type); paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use crate::tests::helper::catch_unwind_on_weak_memory_arch as can_panic; __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, Relaxed); __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, Acquire); __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, Release); __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, AcqRel); __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, SeqCst); __stress_test_acquire_release!(can_panic, $int_type, swap, Acquire, Relaxed); __stress_test_acquire_release!(can_panic, $int_type, swap, Acquire, Acquire); __stress_test_acquire_release!(should_pass, $int_type, swap, Acquire, Release); __stress_test_acquire_release!(should_pass, $int_type, swap, Acquire, AcqRel); __stress_test_acquire_release!(should_pass, $int_type, swap, Acquire, SeqCst); __stress_test_acquire_release!(can_panic, $int_type, swap, SeqCst, Relaxed); __stress_test_acquire_release!(can_panic, $int_type, swap, SeqCst, Acquire); __stress_test_acquire_release!(should_pass, $int_type, swap, SeqCst, Release); __stress_test_acquire_release!(should_pass, $int_type, swap, SeqCst, AcqRel); __stress_test_acquire_release!(should_pass, $int_type, swap, SeqCst, SeqCst); } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use crate::tests::helper::catch_unwind_on_non_seqcst_arch as can_panic; __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, Relaxed); __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, Acquire); __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, Release); __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, AcqRel); __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, SeqCst); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, Relaxed); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, Acquire); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, Release); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, AcqRel); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, SeqCst); __stress_test_seqcst!(can_panic, $int_type, swap, SeqCst, Relaxed); __stress_test_seqcst!(can_panic, $int_type, swap, SeqCst, Acquire); __stress_test_seqcst!(can_panic, $int_type, swap, SeqCst, Release); __stress_test_seqcst!(can_panic, $int_type, swap, SeqCst, AcqRel); __stress_test_seqcst!(should_pass, $int_type, swap, SeqCst, SeqCst); } } }; } #[cfg(feature = "float")] pub(crate) mod float_rand { #[cfg(portable_atomic_unstable_f16)] pub(crate) fn f16(rng: &mut fastrand::Rng) -> f16 { f16::from_bits(rng.u16(..)) } pub(crate) fn f32(rng: &mut fastrand::Rng) -> f32 { f32::from_bits(rng.u32(..)) } pub(crate) fn f64(rng: &mut fastrand::Rng) -> f64 { f64::from_bits(rng.u64(..)) } #[cfg(portable_atomic_unstable_f128)] pub(crate) fn f128(rng: &mut fastrand::Rng) -> f128 { f128::from_bits(rng.u128(..)) } } portable-atomic/src/gen/0000775000175000017500000000000015105742312015026 5ustar bdrungbdrungportable-atomic/src/gen/utils.rs0000644000175000017500000001240215105742312016531 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT // This file is @generated by target_spec.sh. // It is not intended for manual editing. #![allow(unused_macros)] // On AArch64, the base register of memory-related instructions must be 64-bit. // Passing a 32-bit value to `in(reg)` on AArch64 results in the upper bits // having an undefined value, but to work correctly with ILP32 ABI, the upper // bits must be zero, which is handled here by casting to u64. Another way to // handle this is to pass it as a pointer and clear the upper bits inside asm, // but it is easier to overlook than cast, which can catch overlooks by // asm_sub_register lint. // See also https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs64/aapcs64.rst#pointers // // Except for x86_64, which can use 32-bit registers in the destination operand // (on x86_64, we use the ptr_modifier macro to handle this), we need to do the // same for ILP32 ABI on other 64-bit architectures. (At least, as far as I can // see from the assembly generated by LLVM, this is also required for MIPS64 N32 // ABI. I don't know about the RISC-V RV64ILP32* ABI, but in any case, this // should be a safe default for such ABIs). // // Known architectures that have such ABI are x86_64 (X32), AArch64 (ILP32), // mips64 (N32), and riscv64 (RV64ILP32*). (As of 2025-01-23, only the former // two are supported by rustc.) However, we list all known 64-bit architectures // because similar ABIs may exist or future added for other architectures. #[cfg(all( target_pointer_width = "32", any( target_arch = "aarch64", target_arch = "amdgpu", target_arch = "arm64ec", target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "nvptx64", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc64", target_arch = "wasm64", target_arch = "x86_64", ), ))] #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] macro_rules! ptr_reg { ($ptr:ident) => {{ let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _) #[cfg(not(portable_atomic_no_asm_maybe_uninit))] #[allow(clippy::ptr_as_ptr)] { // If we cast to u64 here, the provenance will be lost, // so we convert to MaybeUninit via zero extend helper. crate::utils::zero_extend64_ptr($ptr as *mut ()) } #[cfg(portable_atomic_no_asm_maybe_uninit)] { // Use cast on old rustc because it does not support MaybeUninit // registers. This is still permissive-provenance compatible and // is sound. $ptr as u64 } }}; } #[cfg(not(all( target_pointer_width = "32", any( target_arch = "aarch64", target_arch = "amdgpu", target_arch = "arm64ec", target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "nvptx64", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc64", target_arch = "wasm64", target_arch = "x86_64", ), )))] #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] macro_rules! ptr_reg { ($ptr:ident) => {{ let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _) $ptr // cast is unnecessary here. }}; } // Some 64-bit architectures have ABI with 32-bit pointer width (e.g., x86_64 X32 ABI, // AArch64 ILP32 ABI, MIPS64 N32 ABI). On those targets, AtomicU64 is available // and fast, so use it to implement normal sequence lock. // // See ptr_reg macro for the reason why all known 64-bit architectures are listed. #[cfg(any( not(any(target_pointer_width = "16", target_pointer_width = "32")), // i.e., 64-bit or greater target_arch = "aarch64", target_arch = "amdgpu", target_arch = "arm64ec", target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "nvptx64", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc64", target_arch = "wasm64", target_arch = "x86_64", ))] #[macro_use] mod fast_atomic_64_macros { macro_rules! cfg_has_fast_atomic_64 { ($($tt:tt)*) => { $($tt)* }; } macro_rules! cfg_no_fast_atomic_64 { ($($tt:tt)*) => {}; } } #[cfg(not(any( not(any(target_pointer_width = "16", target_pointer_width = "32")), // i.e., 64-bit or greater target_arch = "aarch64", target_arch = "amdgpu", target_arch = "arm64ec", target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "nvptx64", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc64", target_arch = "wasm64", target_arch = "x86_64", )))] #[macro_use] mod fast_atomic_64_macros { macro_rules! cfg_has_fast_atomic_64 { ($($tt:tt)*) => {}; } macro_rules! cfg_no_fast_atomic_64 { ($($tt:tt)*) => { $($tt)* }; } } portable-atomic/src/gen/build.rs0000644000175000017500000000450415105742312016474 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT // This file is @generated by no_atomic.sh. // It is not intended for manual editing. // Note: This is the list as of nightly-2022-02-10. We don't refer to this in // nightly-2022-02-11+ because feature(cfg_target_has_atomic) stabilized. #[rustfmt::skip] pub(crate) static NO_ATOMIC_CAS: &[&str] = &[ "avr-unknown-gnu-atmega328", "bpfeb-unknown-none", "bpfel-unknown-none", "msp430-none-elf", "riscv32i-unknown-none-elf", "riscv32imc-unknown-none-elf", "thumbv4t-none-eabi", "thumbv6m-none-eabi", ]; // Note: This is the list as of nightly-2022-02-10. We don't refer to this in // nightly-2022-02-11+ because feature(cfg_target_has_atomic) stabilized. #[rustfmt::skip] pub(crate) static NO_ATOMIC_64: &[&str] = &[ "arm-linux-androideabi", "armebv7r-none-eabi", "armebv7r-none-eabihf", "armv4t-unknown-linux-gnueabi", "armv5te-unknown-linux-gnueabi", "armv5te-unknown-linux-musleabi", "armv5te-unknown-linux-uclibceabi", "armv6k-nintendo-3ds", "armv7r-none-eabi", "armv7r-none-eabihf", "avr-unknown-gnu-atmega328", "hexagon-unknown-linux-musl", "m68k-unknown-linux-gnu", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", "mips-unknown-linux-uclibc", "mipsel-sony-psp", "mipsel-unknown-linux-gnu", "mipsel-unknown-linux-musl", "mipsel-unknown-linux-uclibc", "mipsel-unknown-none", "mipsisa32r6-unknown-linux-gnu", "mipsisa32r6el-unknown-linux-gnu", "msp430-none-elf", "powerpc-unknown-freebsd", "powerpc-unknown-linux-gnu", "powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-musl", "powerpc-unknown-netbsd", "powerpc-unknown-openbsd", "powerpc-wrs-vxworks", "powerpc-wrs-vxworks-spe", "riscv32gc-unknown-linux-gnu", "riscv32gc-unknown-linux-musl", "riscv32i-unknown-none-elf", "riscv32imac-unknown-none-elf", "riscv32imc-esp-espidf", "riscv32imc-unknown-none-elf", "thumbv4t-none-eabi", "thumbv6m-none-eabi", "thumbv7em-none-eabi", "thumbv7em-none-eabihf", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", ]; #[rustfmt::skip] pub(crate) static NO_ATOMIC: &[&str] = &[ "bpfeb-unknown-none", "bpfel-unknown-none", "mipsel-sony-psx", ]; portable-atomic/src/cfgs.rs0000644000175000017500000003662615105742312015560 0ustar bdrungbdrung// SPDX-License-Identifier: Apache-2.0 OR MIT #![allow(missing_docs)] #[cfg(not(all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), )))] #[macro_use] mod atomic_8_16_macros { #[macro_export] macro_rules! cfg_has_atomic_8 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_8 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_has_atomic_16 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_16 { ($($tt:tt)*) => {}; } } #[cfg(all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), ))] #[macro_use] mod atomic_8_16_macros { #[macro_export] macro_rules! cfg_has_atomic_8 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_8 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_has_atomic_16 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_16 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg(all( any(not(target_pointer_width = "16"), feature = "fallback"), not(all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), )), ))] #[macro_use] mod atomic_32_macros { #[macro_export] macro_rules! cfg_has_atomic_32 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_32 { ($($tt:tt)*) => {}; } } #[cfg(not(all( any(not(target_pointer_width = "16"), feature = "fallback"), not(all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), )), )))] #[macro_use] mod atomic_32_macros { #[macro_export] macro_rules! cfg_has_atomic_32 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_32 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( all( feature = "fallback", any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ), ), not(portable_atomic_no_atomic_64), not(any(target_pointer_width = "16", target_pointer_width = "32")), all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( all( feature = "fallback", any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ), ), target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), )) )] #[macro_use] mod atomic_64_macros { #[macro_export] macro_rules! cfg_has_atomic_64 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_64 { ($($tt:tt)*) => {}; } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(any( all( feature = "fallback", any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ), ), not(portable_atomic_no_atomic_64), not(any(target_pointer_width = "16", target_pointer_width = "32")), all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(any( all( feature = "fallback", any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ), ), target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), all( target_arch = "riscv32", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), ))) )] #[macro_use] mod atomic_64_macros { #[macro_export] macro_rules! cfg_has_atomic_64 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_64 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg_attr( not(feature = "fallback"), cfg(any( all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ), all(target_arch = "arm64ec", not(portable_atomic_no_asm)), all( target_arch = "x86_64", not(all( any(miri, portable_atomic_sanitize_thread), portable_atomic_no_cmpxchg16b_intrinsic, )), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), ), all( target_arch = "riscv64", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ), ), all(target_arch = "s390x", not(portable_atomic_no_asm)), )) )] #[cfg_attr( all(feature = "fallback", portable_atomic_no_cfg_target_has_atomic), cfg(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", )) )] #[cfg_attr( all(feature = "fallback", not(portable_atomic_no_cfg_target_has_atomic)), cfg(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", )) )] #[macro_use] mod atomic_128_macros { #[macro_export] macro_rules! cfg_has_atomic_128 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_128 { ($($tt:tt)*) => {}; } } #[cfg_attr( not(feature = "fallback"), cfg(not(any( all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ), all(target_arch = "arm64ec", not(portable_atomic_no_asm)), all( target_arch = "x86_64", not(all( any(miri, portable_atomic_sanitize_thread), portable_atomic_no_cmpxchg16b_intrinsic, )), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), ), all( target_arch = "riscv64", not(any(miri, portable_atomic_sanitize_thread)), any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "zacas", portable_atomic_target_feature = "zacas"), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ), ), all(target_arch = "s390x", not(portable_atomic_no_asm)), ))) )] #[cfg_attr( all(feature = "fallback", portable_atomic_no_cfg_target_has_atomic), cfg(not(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[cfg_attr( all(feature = "fallback", not(portable_atomic_no_cfg_target_has_atomic)), cfg(not(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[macro_use] mod atomic_128_macros { #[macro_export] macro_rules! cfg_has_atomic_128 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_128 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", )) )] #[macro_use] mod atomic_cas_macros { #[macro_export] macro_rules! cfg_has_atomic_cas { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_cas { ($($tt:tt)*) => {}; } // private macro_rules! cfg_has_atomic_cas_or_amo32 { ($($tt:tt)*) => { $($tt)* }; } macro_rules! cfg_has_atomic_cas_or_amo8 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[macro_use] mod atomic_cas_macros { #[macro_export] macro_rules! cfg_has_atomic_cas { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_cas { ($($tt:tt)*) => { $($tt)* }; } // private #[cfg_attr( any(target_arch = "riscv32", target_arch = "riscv64"), cfg(not(any(target_feature = "zaamo", portable_atomic_target_feature = "zaamo"))) )] macro_rules! cfg_has_atomic_cas_or_amo32 { ($($tt:tt)*) => {}; } #[cfg_attr( any(target_arch = "riscv32", target_arch = "riscv64"), cfg(not(any(target_feature = "zaamo", portable_atomic_target_feature = "zaamo"))) )] macro_rules! cfg_no_atomic_cas_or_amo32 { ($($tt:tt)*) => { $($tt)* }; } #[cfg(all( any(target_arch = "riscv32", target_arch = "riscv64"), any(target_feature = "zaamo", portable_atomic_target_feature = "zaamo"), ))] macro_rules! cfg_has_atomic_cas_or_amo32 { ($($tt:tt)*) => { $($tt)* }; } #[cfg(all( any(target_arch = "riscv32", target_arch = "riscv64"), any(target_feature = "zaamo", portable_atomic_target_feature = "zaamo"), ))] macro_rules! cfg_no_atomic_cas_or_amo32 { ($($tt:tt)*) => {}; } #[cfg_attr( any(target_arch = "riscv32", target_arch = "riscv64"), cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha"))) )] #[allow(unused_macros)] macro_rules! cfg_has_atomic_cas_or_amo8 { ($($tt:tt)*) => {}; } #[cfg_attr( any(target_arch = "riscv32", target_arch = "riscv64"), cfg(not(any(target_feature = "zabha", portable_atomic_target_feature = "zabha"))) )] #[cfg_attr(target_arch = "bpf", allow(unused_macros))] macro_rules! cfg_no_atomic_cas_or_amo8 { ($($tt:tt)*) => { $($tt)* }; } #[cfg(all( any(target_arch = "riscv32", target_arch = "riscv64"), any(target_feature = "zabha", portable_atomic_target_feature = "zabha"), ))] macro_rules! cfg_has_atomic_cas_or_amo8 { ($($tt:tt)*) => { $($tt)* }; } #[cfg(all( any(target_arch = "riscv32", target_arch = "riscv64"), any(target_feature = "zabha", portable_atomic_target_feature = "zabha"), ))] macro_rules! cfg_no_atomic_cas_or_amo8 { ($($tt:tt)*) => {}; } } // Check that all cfg_ macros work. mod check { crate::cfg_has_atomic_8! { type _Atomic8 = (); } crate::cfg_no_atomic_8! { type _Atomic8 = (); } crate::cfg_has_atomic_16! { type _Atomic16 = (); } crate::cfg_no_atomic_16! { type _Atomic16 = (); } crate::cfg_has_atomic_32! { type _Atomic32 = (); } crate::cfg_no_atomic_32! { type _Atomic32 = (); } crate::cfg_has_atomic_64! { type _Atomic64 = (); } crate::cfg_no_atomic_64! { type _Atomic64 = (); } crate::cfg_has_atomic_128! { type _Atomic128 = (); } crate::cfg_no_atomic_128! { type _Atomic128 = (); } crate::cfg_has_atomic_ptr! { type _AtomicPtr = (); } crate::cfg_no_atomic_ptr! { type _AtomicPtr = (); } crate::cfg_has_atomic_cas! { type __AtomicPtr = (); } crate::cfg_no_atomic_cas! { type __AtomicPtr = (); } #[allow(unused_imports)] use self::{ __AtomicPtr as _, _Atomic8 as _, _Atomic16 as _, _Atomic32 as _, _Atomic64 as _, _Atomic128 as _, _AtomicPtr as _, }; } proc-macro2/0000775000175000017500000000000015105742312012530 5ustar bdrungbdrungproc-macro2/build/0000775000175000017500000000000015105742312013627 5ustar bdrungbdrungproc-macro2/build/probe.rs0000644000175000017500000000156515105742312015311 0ustar bdrungbdrung// This code exercises the surface area that we expect of Span's unstable API. // If the current toolchain is able to compile it, then proc-macro2 is able to // offer these APIs too. #![feature(proc_macro_span)] extern crate proc_macro; use core::ops::{Range, RangeBounds}; use proc_macro::{Literal, Span}; pub fn byte_range(this: &Span) -> Range { this.byte_range() } pub fn start(this: &Span) -> Span { this.start() } pub fn end(this: &Span) -> Span { this.end() } pub fn line(this: &Span) -> usize { this.line() } pub fn column(this: &Span) -> usize { this.column() } pub fn join(this: &Span, other: Span) -> Option { this.join(other) } pub fn subspan>(this: &Literal, range: R) -> Option { this.subspan(range) } // Include in sccache cache key. const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP"); proc-macro2/build.rs0000644000175000017500000002076115105742312014201 0ustar bdrungbdrung#![allow(unknown_lints)] #![allow(unexpected_cfgs)] use std::env; use std::ffi::OsString; use std::fs; use std::io::ErrorKind; use std::iter; use std::path::Path; use std::process::{self, Command, Stdio}; use std::str; fn main() { let rustc = rustc_minor_version().unwrap_or(u32::MAX); if rustc >= 80 { println!("cargo:rustc-check-cfg=cfg(fuzzing)"); println!("cargo:rustc-check-cfg=cfg(no_is_available)"); println!("cargo:rustc-check-cfg=cfg(no_literal_byte_character)"); println!("cargo:rustc-check-cfg=cfg(no_literal_c_string)"); println!("cargo:rustc-check-cfg=cfg(no_source_text)"); println!("cargo:rustc-check-cfg=cfg(proc_macro_span)"); println!("cargo:rustc-check-cfg=cfg(procmacro2_backtrace)"); println!("cargo:rustc-check-cfg=cfg(procmacro2_nightly_testing)"); println!("cargo:rustc-check-cfg=cfg(procmacro2_semver_exempt)"); println!("cargo:rustc-check-cfg=cfg(randomize_layout)"); println!("cargo:rustc-check-cfg=cfg(span_locations)"); println!("cargo:rustc-check-cfg=cfg(super_unstable)"); println!("cargo:rustc-check-cfg=cfg(wrap_proc_macro)"); } let docs_rs = env::var_os("DOCS_RS").is_some(); let semver_exempt = cfg!(procmacro2_semver_exempt) || docs_rs; if semver_exempt { // https://github.com/dtolnay/proc-macro2/issues/147 println!("cargo:rustc-cfg=procmacro2_semver_exempt"); } if semver_exempt || cfg!(feature = "span-locations") { // Provide methods Span::start and Span::end which give the line/column // location of a token. This is behind a cfg because tracking location // inside spans is a performance hit. println!("cargo:rustc-cfg=span_locations"); } if rustc < 57 { // Do not use proc_macro::is_available() to detect whether the proc // macro API is available vs needs to be polyfilled. Instead, use the // proc macro API unconditionally and catch the panic that occurs if it // isn't available. println!("cargo:rustc-cfg=no_is_available"); } if rustc < 66 { // Do not call libproc_macro's Span::source_text. Always return None. println!("cargo:rustc-cfg=no_source_text"); } if rustc < 79 { // Do not call Literal::byte_character nor Literal::c_string. They can // be emulated by way of Literal::from_str. println!("cargo:rustc-cfg=no_literal_byte_character"); println!("cargo:rustc-cfg=no_literal_c_string"); } if !cfg!(feature = "proc-macro") { println!("cargo:rerun-if-changed=build.rs"); return; } println!("cargo:rerun-if-changed=build/probe.rs"); let proc_macro_span; let consider_rustc_bootstrap; if compile_probe(false) { // This is a nightly or dev compiler, so it supports unstable features // regardless of RUSTC_BOOTSTRAP. No need to rerun build script if // RUSTC_BOOTSTRAP is changed. proc_macro_span = true; consider_rustc_bootstrap = false; } else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") { if compile_probe(true) { // This is a stable or beta compiler for which the user has set // RUSTC_BOOTSTRAP to turn on unstable features. Rerun build script // if they change it. proc_macro_span = true; consider_rustc_bootstrap = true; } else if rustc_bootstrap == "1" { // This compiler does not support the proc macro Span API in the // form that proc-macro2 expects. No need to pay attention to // RUSTC_BOOTSTRAP. proc_macro_span = false; consider_rustc_bootstrap = false; } else { // This is a stable or beta compiler for which RUSTC_BOOTSTRAP is // set to restrict the use of unstable features by this crate. proc_macro_span = false; consider_rustc_bootstrap = true; } } else { // Without RUSTC_BOOTSTRAP, this compiler does not support the proc // macro Span API in the form that proc-macro2 expects, but try again if // the user turns on unstable features. proc_macro_span = false; consider_rustc_bootstrap = true; } if proc_macro_span || !semver_exempt { // Wrap types from libproc_macro rather than polyfilling the whole API. // Enabled as long as procmacro2_semver_exempt is not set, because we // can't emulate the unstable API without emulating everything else. // Also enabled unconditionally on nightly, in which case the // procmacro2_semver_exempt surface area is implemented by using the // nightly-only proc_macro API. println!("cargo:rustc-cfg=wrap_proc_macro"); } if proc_macro_span { // Enable non-dummy behavior of Span::start and Span::end methods which // requires an unstable compiler feature. Enabled when building with // nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable // features. println!("cargo:rustc-cfg=proc_macro_span"); } if semver_exempt && proc_macro_span { // Implement the semver exempt API in terms of the nightly-only // proc_macro API. println!("cargo:rustc-cfg=super_unstable"); } if consider_rustc_bootstrap { println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); } } fn compile_probe(rustc_bootstrap: bool) -> bool { if env::var_os("RUSTC_STAGE").is_some() { // We are running inside rustc bootstrap. This is a highly non-standard // environment with issues such as: // // https://github.com/rust-lang/cargo/issues/11138 // https://github.com/rust-lang/rust/issues/114839 // // Let's just not use nightly features here. return false; } let rustc = cargo_env_var("RUSTC"); let out_dir = cargo_env_var("OUT_DIR"); let out_subdir = Path::new(&out_dir).join("probe"); let probefile = Path::new("build").join("probe.rs"); if let Err(err) = fs::create_dir(&out_subdir) { if err.kind() != ErrorKind::AlreadyExists { eprintln!("Failed to create {}: {}", out_subdir.display(), err); process::exit(1); } } let rustc_wrapper = env::var_os("RUSTC_WRAPPER").filter(|wrapper| !wrapper.is_empty()); let rustc_workspace_wrapper = env::var_os("RUSTC_WORKSPACE_WRAPPER").filter(|wrapper| !wrapper.is_empty()); let mut rustc = rustc_wrapper .into_iter() .chain(rustc_workspace_wrapper) .chain(iter::once(rustc)); let mut cmd = Command::new(rustc.next().unwrap()); cmd.args(rustc); if !rustc_bootstrap { cmd.env_remove("RUSTC_BOOTSTRAP"); } cmd.stderr(Stdio::null()) .arg("--edition=2021") .arg("--crate-name=proc_macro2") .arg("--crate-type=lib") .arg("--cap-lints=allow") .arg("--emit=dep-info,metadata") .arg("--out-dir") .arg(&out_subdir) .arg(probefile); if let Some(target) = env::var_os("TARGET") { cmd.arg("--target").arg(target); } // If Cargo wants to set RUSTFLAGS, use that. if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") { if !rustflags.is_empty() { for arg in rustflags.split('\x1f') { cmd.arg(arg); } } } let success = match cmd.status() { Ok(status) => status.success(), Err(_) => false, }; // Clean up to avoid leaving nondeterministic absolute paths in the dep-info // file in OUT_DIR, which causes nonreproducible builds in build systems // that treat the entire OUT_DIR as an artifact. if let Err(err) = fs::remove_dir_all(&out_subdir) { if err.kind() != ErrorKind::NotFound { eprintln!("Failed to clean up {}: {}", out_subdir.display(), err); process::exit(1); } } success } fn rustc_minor_version() -> Option { let rustc = cargo_env_var("RUSTC"); let output = Command::new(rustc).arg("--version").output().ok()?; let version = str::from_utf8(&output.stdout).ok()?; let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } pieces.next()?.parse().ok() } fn cargo_env_var(key: &str) -> OsString { env::var_os(key).unwrap_or_else(|| { eprintln!( "Environment variable ${} is not set during execution of build script", key, ); process::exit(1); }) } proc-macro2/tests/0000775000175000017500000000000015105742312013672 5ustar bdrungbdrungproc-macro2/tests/test_size.rs0000644000175000017500000000754315105742312016260 0ustar bdrungbdrung#![allow(unused_attributes)] extern crate proc_macro; use std::mem; #[rustversion::attr(before(1.64), ignore = "requires Rust 1.64+")] #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[test] fn test_proc_macro_size() { assert_eq!(mem::size_of::(), 4); assert_eq!(mem::size_of::>(), 4); assert_eq!(mem::size_of::(), 20); assert_eq!(mem::size_of::(), 12); assert_eq!(mem::size_of::(), 8); assert_eq!(mem::size_of::(), 16); assert_eq!(mem::size_of::(), 4); } #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[cfg_attr(wrap_proc_macro, ignore = "wrapper mode")] #[cfg_attr(span_locations, ignore = "span locations are on")] #[test] fn test_proc_macro2_fallback_size_without_locations() { assert_eq!(mem::size_of::(), 0); assert_eq!(mem::size_of::>(), 1); assert_eq!(mem::size_of::(), 16); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 8); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 8); } #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[cfg_attr(wrap_proc_macro, ignore = "wrapper mode")] #[cfg_attr(not(span_locations), ignore = "span locations are off")] #[test] fn test_proc_macro2_fallback_size_with_locations() { assert_eq!(mem::size_of::(), 8); assert_eq!(mem::size_of::>(), 12); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 16); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 8); } #[rustversion::attr(before(1.71), ignore = "requires Rust 1.71+")] #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[cfg_attr(not(wrap_proc_macro), ignore = "fallback mode")] #[cfg_attr(span_locations, ignore = "span locations are on")] #[test] fn test_proc_macro2_wrapper_size_without_locations() { assert_eq!(mem::size_of::(), 4); assert_eq!(mem::size_of::>(), 8); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 12); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 32); } #[rustversion::attr(before(1.65), ignore = "requires Rust 1.65+")] #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[cfg_attr(not(wrap_proc_macro), ignore = "fallback mode")] #[cfg_attr(not(span_locations), ignore = "span locations are off")] #[test] fn test_proc_macro2_wrapper_size_with_locations() { assert_eq!(mem::size_of::(), 12); assert_eq!(mem::size_of::>(), 12); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 20); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 32); } proc-macro2/tests/test.rs0000644000175000017500000006403115105742312015221 0ustar bdrungbdrung#![allow( clippy::assertions_on_result_states, clippy::items_after_statements, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::non_ascii_literal, clippy::octal_escapes )] use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use std::ffi::CStr; use std::iter; use std::str::{self, FromStr}; #[test] fn idents() { assert_eq!( Ident::new("String", Span::call_site()).to_string(), "String" ); assert_eq!(Ident::new("fn", Span::call_site()).to_string(), "fn"); assert_eq!(Ident::new("_", Span::call_site()).to_string(), "_"); } #[test] fn raw_idents() { assert_eq!( Ident::new_raw("String", Span::call_site()).to_string(), "r#String" ); assert_eq!(Ident::new_raw("fn", Span::call_site()).to_string(), "r#fn"); } #[test] #[should_panic(expected = "`r#_` cannot be a raw identifier")] fn ident_raw_underscore() { Ident::new_raw("_", Span::call_site()); } #[test] #[should_panic(expected = "`r#super` cannot be a raw identifier")] fn ident_raw_reserved() { Ident::new_raw("super", Span::call_site()); } #[test] #[should_panic(expected = "Ident is not allowed to be empty; use Option")] fn ident_empty() { Ident::new("", Span::call_site()); } #[test] #[should_panic(expected = "Ident cannot be a number; use Literal instead")] fn ident_number() { Ident::new("255", Span::call_site()); } #[test] #[should_panic(expected = "\"a#\" is not a valid Ident")] fn ident_invalid() { Ident::new("a#", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] fn raw_ident_empty() { Ident::new("r#", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] fn raw_ident_number() { Ident::new("r#255", Span::call_site()); } #[test] #[should_panic(expected = "\"r#a#\" is not a valid Ident")] fn raw_ident_invalid() { Ident::new("r#a#", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] fn lifetime_empty() { Ident::new("'", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] fn lifetime_number() { Ident::new("'255", Span::call_site()); } #[test] #[should_panic(expected = r#""'a#" is not a valid Ident"#)] fn lifetime_invalid() { Ident::new("'a#", Span::call_site()); } #[test] fn literal_string() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::string(""), r#" "" "#); assert(Literal::string("aA"), r#" "aA" "#); assert(Literal::string("\t"), r#" "\t" "#); assert(Literal::string("❤"), r#" "❤" "#); assert(Literal::string("'"), r#" "'" "#); assert(Literal::string("\""), r#" "\"" "#); assert(Literal::string("\0"), r#" "\0" "#); assert(Literal::string("\u{1}"), r#" "\u{1}" "#); assert( Literal::string("a\00b\07c\08d\0e\0"), r#" "a\x000b\x007c\08d\0e\0" "#, ); "\"\\\r\n x\"".parse::().unwrap(); "\"\\\r\n \rx\"".parse::().unwrap_err(); } #[test] fn literal_raw_string() { "r\"\r\n\"".parse::().unwrap(); fn raw_string_literal_with_hashes(n: usize) -> String { let mut literal = String::new(); literal.push('r'); literal.extend(iter::repeat('#').take(n)); literal.push('"'); literal.push('"'); literal.extend(iter::repeat('#').take(n)); literal } raw_string_literal_with_hashes(255) .parse::() .unwrap(); // https://github.com/rust-lang/rust/pull/95251 raw_string_literal_with_hashes(256) .parse::() .unwrap_err(); } #[test] fn literal_byte_character() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::byte_character(b'a'), r#" b'a' "#); assert(Literal::byte_character(b'\0'), r#" b'\0' "#); assert(Literal::byte_character(b'\t'), r#" b'\t' "#); assert(Literal::byte_character(b'\n'), r#" b'\n' "#); assert(Literal::byte_character(b'\r'), r#" b'\r' "#); assert(Literal::byte_character(b'\''), r#" b'\'' "#); assert(Literal::byte_character(b'\\'), r#" b'\\' "#); assert(Literal::byte_character(b'\x1f'), r#" b'\x1F' "#); assert(Literal::byte_character(b'"'), r#" b'"' "#); } #[test] fn literal_byte_string() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::byte_string(b""), r#" b"" "#); assert(Literal::byte_string(b"\0"), r#" b"\0" "#); assert(Literal::byte_string(b"\t"), r#" b"\t" "#); assert(Literal::byte_string(b"\n"), r#" b"\n" "#); assert(Literal::byte_string(b"\r"), r#" b"\r" "#); assert(Literal::byte_string(b"\""), r#" b"\"" "#); assert(Literal::byte_string(b"\\"), r#" b"\\" "#); assert(Literal::byte_string(b"\x1f"), r#" b"\x1F" "#); assert(Literal::byte_string(b"'"), r#" b"'" "#); assert( Literal::byte_string(b"a\00b\07c\08d\0e\0"), r#" b"a\x000b\x007c\08d\0e\0" "#, ); "b\"\\\r\n x\"".parse::().unwrap(); "b\"\\\r\n \rx\"".parse::().unwrap_err(); "b\"\\\r\n \u{a0}x\"".parse::().unwrap_err(); "br\"\u{a0}\"".parse::().unwrap_err(); } #[test] fn literal_c_string() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::c_string(<&CStr>::default()), r#" c"" "#); assert( Literal::c_string(CStr::from_bytes_with_nul(b"aA\0").unwrap()), r#" c"aA" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"aA\0").unwrap()), r#" c"aA" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"\t\0").unwrap()), r#" c"\t" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"\xE2\x9D\xA4\0").unwrap()), r#" c"❤" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"'\0").unwrap()), r#" c"'" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"\"\0").unwrap()), r#" c"\"" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"\x7F\xFF\xFE\xCC\xB3\0").unwrap()), r#" c"\u{7f}\xFF\xFE\u{333}" "#, ); let strings = r###" c"hello\x80我叫\u{1F980}" // from the RFC cr"\" cr##"Hello "world"!"## c"\t\n\r\"\\" "###; let mut tokens = strings.parse::().unwrap().into_iter(); for expected in &[ r#"c"hello\x80我叫\u{1F980}""#, r#"cr"\""#, r###"cr##"Hello "world"!"##"###, r#"c"\t\n\r\"\\""#, ] { match tokens.next().unwrap() { TokenTree::Literal(literal) => { assert_eq!(literal.to_string(), *expected); } unexpected => panic!("unexpected token: {:?}", unexpected), } } if let Some(unexpected) = tokens.next() { panic!("unexpected token: {:?}", unexpected); } for invalid in &[r#"c"\0""#, r#"c"\x00""#, r#"c"\u{0}""#, "c\"\0\""] { if let Ok(unexpected) = invalid.parse::() { panic!("unexpected token: {:?}", unexpected); } } } #[test] fn literal_character() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::character('a'), r#" 'a' "#); assert(Literal::character('\t'), r#" '\t' "#); assert(Literal::character('❤'), r#" '❤' "#); assert(Literal::character('\''), r#" '\'' "#); assert(Literal::character('"'), r#" '"' "#); assert(Literal::character('\0'), r#" '\0' "#); assert(Literal::character('\u{1}'), r#" '\u{1}' "#); } #[test] fn literal_integer() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected); } assert(Literal::u8_suffixed(10), "10u8"); assert(Literal::u16_suffixed(10), "10u16"); assert(Literal::u32_suffixed(10), "10u32"); assert(Literal::u64_suffixed(10), "10u64"); assert(Literal::u128_suffixed(10), "10u128"); assert(Literal::usize_suffixed(10), "10usize"); assert(Literal::i8_suffixed(10), "10i8"); assert(Literal::i16_suffixed(10), "10i16"); assert(Literal::i32_suffixed(10), "10i32"); assert(Literal::i64_suffixed(10), "10i64"); assert(Literal::i128_suffixed(10), "10i128"); assert(Literal::isize_suffixed(10), "10isize"); assert(Literal::u8_unsuffixed(10), "10"); assert(Literal::u16_unsuffixed(10), "10"); assert(Literal::u32_unsuffixed(10), "10"); assert(Literal::u64_unsuffixed(10), "10"); assert(Literal::u128_unsuffixed(10), "10"); assert(Literal::usize_unsuffixed(10), "10"); assert(Literal::i8_unsuffixed(10), "10"); assert(Literal::i16_unsuffixed(10), "10"); assert(Literal::i32_unsuffixed(10), "10"); assert(Literal::i64_unsuffixed(10), "10"); assert(Literal::i128_unsuffixed(10), "10"); assert(Literal::isize_unsuffixed(10), "10"); assert(Literal::i32_suffixed(-10), "-10i32"); assert(Literal::i32_unsuffixed(-10), "-10"); } #[test] fn literal_float() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected); } assert(Literal::f32_suffixed(10.0), "10f32"); assert(Literal::f32_suffixed(-10.0), "-10f32"); assert(Literal::f64_suffixed(10.0), "10f64"); assert(Literal::f64_suffixed(-10.0), "-10f64"); assert(Literal::f32_unsuffixed(10.0), "10.0"); assert(Literal::f32_unsuffixed(-10.0), "-10.0"); assert(Literal::f64_unsuffixed(10.0), "10.0"); assert(Literal::f64_unsuffixed(-10.0), "-10.0"); assert( Literal::f64_unsuffixed(1e100), "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", ); } #[test] fn literal_suffix() { fn token_count(p: &str) -> usize { p.parse::().unwrap().into_iter().count() } assert_eq!(token_count("999u256"), 1); assert_eq!(token_count("999r#u256"), 3); assert_eq!(token_count("1."), 1); assert_eq!(token_count("1.f32"), 3); assert_eq!(token_count("1.0_0"), 1); assert_eq!(token_count("1._0"), 3); assert_eq!(token_count("1._m"), 3); assert_eq!(token_count("\"\"s"), 1); assert_eq!(token_count("r\"\"r"), 1); assert_eq!(token_count("r#\"\"#r"), 1); assert_eq!(token_count("b\"\"b"), 1); assert_eq!(token_count("br\"\"br"), 1); assert_eq!(token_count("br#\"\"#br"), 1); assert_eq!(token_count("c\"\"c"), 1); assert_eq!(token_count("cr\"\"cr"), 1); assert_eq!(token_count("cr#\"\"#cr"), 1); assert_eq!(token_count("'c'c"), 1); assert_eq!(token_count("b'b'b"), 1); assert_eq!(token_count("0E"), 1); assert_eq!(token_count("0o0A"), 1); assert_eq!(token_count("0E--0"), 4); assert_eq!(token_count("0.0ECMA"), 1); } #[test] fn literal_iter_negative() { let negative_literal = Literal::i32_suffixed(-3); let tokens = TokenStream::from(TokenTree::Literal(negative_literal)); let mut iter = tokens.into_iter(); match iter.next().unwrap() { TokenTree::Punct(punct) => { assert_eq!(punct.as_char(), '-'); assert_eq!(punct.spacing(), Spacing::Alone); } unexpected => panic!("unexpected token {:?}", unexpected), } match iter.next().unwrap() { TokenTree::Literal(literal) => { assert_eq!(literal.to_string(), "3i32"); } unexpected => panic!("unexpected token {:?}", unexpected), } assert!(iter.next().is_none()); } #[test] fn literal_parse() { assert!("1".parse::().is_ok()); assert!("-1".parse::().is_ok()); assert!("-1u12".parse::().is_ok()); assert!("1.0".parse::().is_ok()); assert!("-1.0".parse::().is_ok()); assert!("-1.0f12".parse::().is_ok()); assert!("'a'".parse::().is_ok()); assert!("\"\n\"".parse::().is_ok()); assert!("0 1".parse::().is_err()); assert!(" 0".parse::().is_err()); assert!("0 ".parse::().is_err()); assert!("/* comment */0".parse::().is_err()); assert!("0/* comment */".parse::().is_err()); assert!("0// comment".parse::().is_err()); assert!("- 1".parse::().is_err()); assert!("- 1.0".parse::().is_err()); assert!("-\"\"".parse::().is_err()); } #[test] fn literal_span() { let positive = "0.1".parse::().unwrap(); let negative = "-0.1".parse::().unwrap(); let subspan = positive.subspan(1..2); #[cfg(not(span_locations))] { let _ = negative; assert!(subspan.is_none()); } #[cfg(span_locations)] { assert_eq!(positive.span().start().column, 0); assert_eq!(positive.span().end().column, 3); assert_eq!(negative.span().start().column, 0); assert_eq!(negative.span().end().column, 4); assert_eq!(subspan.unwrap().source_text().unwrap(), "."); } assert!(positive.subspan(1..4).is_none()); } #[cfg(span_locations)] #[test] fn source_text() { let input = " 𓀕 a z "; let mut tokens = input .parse::() .unwrap() .into_iter(); let first = tokens.next().unwrap(); assert_eq!("𓀕", first.span().source_text().unwrap()); let second = tokens.next().unwrap(); let third = tokens.next().unwrap(); assert_eq!("z", third.span().source_text().unwrap()); assert_eq!("a", second.span().source_text().unwrap()); } #[test] fn roundtrip() { fn roundtrip(p: &str) { println!("parse: {}", p); let s = p.parse::().unwrap().to_string(); println!("first: {}", s); let s2 = s.parse::().unwrap().to_string(); assert_eq!(s, s2); } roundtrip("a"); roundtrip("<<"); roundtrip("<<="); roundtrip( " 1 1.0 1f32 2f64 1usize 4isize 4e10 1_000 1_0i32 8u8 9 0 0xffffffffffffffffffffffffffffffff 1x 1u80 1f320 ", ); roundtrip("'a"); roundtrip("'_"); roundtrip("'static"); roundtrip(r"'\u{10__FFFF}'"); roundtrip("\"\\u{10_F0FF__}foo\\u{1_0_0_0__}\""); } #[test] fn fail() { fn fail(p: &str) { if let Ok(s) = p.parse::() { panic!("should have failed to parse: {}\n{:#?}", p, s); } } fail("' static"); fail("r#1"); fail("r#_"); fail("\"\\u{0000000}\""); // overlong unicode escape (rust allows at most 6 hex digits) fail("\"\\u{999999}\""); // outside of valid range of char fail("\"\\u{_0}\""); // leading underscore fail("\"\\u{}\""); // empty fail("b\"\r\""); // bare carriage return in byte string fail("r\"\r\""); // bare carriage return in raw string fail("\"\\\r \""); // backslash carriage return fail("'aa'aa"); fail("br##\"\"#"); fail("cr##\"\"#"); fail("\"\\\n\u{85}\r\""); } #[cfg(span_locations)] #[test] fn span_test() { check_spans( "\ /// This is a document comment testing 123 { testing 234 }", &[ (1, 0, 1, 30), // # (1, 0, 1, 30), // [ ... ] (1, 0, 1, 30), // doc (1, 0, 1, 30), // = (1, 0, 1, 30), // "This is..." (2, 0, 2, 7), // testing (2, 8, 2, 11), // 123 (3, 0, 5, 1), // { ... } (4, 2, 4, 9), // testing (4, 10, 4, 13), // 234 ], ); } #[cfg(procmacro2_semver_exempt)] #[test] fn default_span() { let start = Span::call_site().start(); assert_eq!(start.line, 1); assert_eq!(start.column, 0); let end = Span::call_site().end(); assert_eq!(end.line, 1); assert_eq!(end.column, 0); assert_eq!(Span::call_site().file(), ""); assert!(Span::call_site().local_file().is_none()); } #[cfg(procmacro2_semver_exempt)] #[test] fn span_join() { let source1 = "aaa\nbbb" .parse::() .unwrap() .into_iter() .collect::>(); let source2 = "ccc\nddd" .parse::() .unwrap() .into_iter() .collect::>(); assert!(source1[0].span().file() != source2[0].span().file()); assert_eq!(source1[0].span().file(), source1[1].span().file()); let joined1 = source1[0].span().join(source1[1].span()); let joined2 = source1[0].span().join(source2[0].span()); assert!(joined1.is_some()); assert!(joined2.is_none()); let start = joined1.unwrap().start(); let end = joined1.unwrap().end(); assert_eq!(start.line, 1); assert_eq!(start.column, 0); assert_eq!(end.line, 2); assert_eq!(end.column, 3); assert_eq!(joined1.unwrap().file(), source1[0].span().file()); } #[test] fn no_panic() { let s = str::from_utf8(b"b\'\xc2\x86 \x00\x00\x00^\"").unwrap(); assert!(s.parse::().is_err()); } #[test] fn punct_before_comment() { let mut tts = TokenStream::from_str("~// comment").unwrap().into_iter(); match tts.next().unwrap() { TokenTree::Punct(tt) => { assert_eq!(tt.as_char(), '~'); assert_eq!(tt.spacing(), Spacing::Alone); } wrong => panic!("wrong token {:?}", wrong), } } #[test] fn joint_last_token() { // This test verifies that we match the behavior of libproc_macro *not* in // the range nightly-2020-09-06 through nightly-2020-09-10, in which this // behavior was temporarily broken. // See https://github.com/rust-lang/rust/issues/76399 let joint_punct = Punct::new(':', Spacing::Joint); let stream = TokenStream::from(TokenTree::Punct(joint_punct)); let punct = match stream.into_iter().next().unwrap() { TokenTree::Punct(punct) => punct, _ => unreachable!(), }; assert_eq!(punct.spacing(), Spacing::Joint); } #[test] fn raw_identifier() { let mut tts = TokenStream::from_str("r#dyn").unwrap().into_iter(); match tts.next().unwrap() { TokenTree::Ident(raw) => assert_eq!("r#dyn", raw.to_string()), wrong => panic!("wrong token {:?}", wrong), } assert!(tts.next().is_none()); } #[test] fn test_debug_ident() { let ident = Ident::new("proc_macro", Span::call_site()); #[cfg(not(span_locations))] let expected = "Ident(proc_macro)"; #[cfg(span_locations)] let expected = "Ident { sym: proc_macro }"; assert_eq!(expected, format!("{:?}", ident)); } #[test] fn test_debug_tokenstream() { let tts = TokenStream::from_str("[a + 1]").unwrap(); #[cfg(not(span_locations))] let expected = "\ TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ Ident { sym: a, }, Punct { char: '+', spacing: Alone, }, Literal { lit: 1, }, ], }, ]\ "; #[cfg(not(span_locations))] let expected_before_trailing_commas = "\ TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ Ident { sym: a }, Punct { char: '+', spacing: Alone }, Literal { lit: 1 } ] } ]\ "; #[cfg(span_locations)] let expected = "\ TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ Ident { sym: a, span: bytes(2..3), }, Punct { char: '+', spacing: Alone, span: bytes(4..5), }, Literal { lit: 1, span: bytes(6..7), }, ], span: bytes(1..8), }, ]\ "; #[cfg(span_locations)] let expected_before_trailing_commas = "\ TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ Ident { sym: a, span: bytes(2..3) }, Punct { char: '+', spacing: Alone, span: bytes(4..5) }, Literal { lit: 1, span: bytes(6..7) } ], span: bytes(1..8) } ]\ "; let actual = format!("{:#?}", tts); if actual.ends_with(",\n]") { assert_eq!(expected, actual); } else { assert_eq!(expected_before_trailing_commas, actual); } } #[test] fn default_tokenstream_is_empty() { let default_token_stream = ::default(); assert!(default_token_stream.is_empty()); } #[test] fn tokenstream_size_hint() { let tokens = "a b (c d) e".parse::().unwrap(); assert_eq!(tokens.into_iter().size_hint(), (4, Some(4))); } #[test] fn tuple_indexing() { // This behavior may change depending on https://github.com/rust-lang/rust/pull/71322 let mut tokens = "tuple.0.0".parse::().unwrap().into_iter(); assert_eq!("tuple", tokens.next().unwrap().to_string()); assert_eq!(".", tokens.next().unwrap().to_string()); assert_eq!("0.0", tokens.next().unwrap().to_string()); assert!(tokens.next().is_none()); } #[cfg(span_locations)] #[test] fn non_ascii_tokens() { check_spans("// abc", &[]); check_spans("// ábc", &[]); check_spans("// abc x", &[]); check_spans("// ábc x", &[]); check_spans("/* abc */ x", &[(1, 10, 1, 11)]); check_spans("/* ábc */ x", &[(1, 10, 1, 11)]); check_spans("/* ab\nc */ x", &[(2, 5, 2, 6)]); check_spans("/* áb\nc */ x", &[(2, 5, 2, 6)]); check_spans("/*** abc */ x", &[(1, 12, 1, 13)]); check_spans("/*** ábc */ x", &[(1, 12, 1, 13)]); check_spans(r#""abc""#, &[(1, 0, 1, 5)]); check_spans(r#""ábc""#, &[(1, 0, 1, 5)]); check_spans(r##"r#"abc"#"##, &[(1, 0, 1, 8)]); check_spans(r##"r#"ábc"#"##, &[(1, 0, 1, 8)]); check_spans("r#\"a\nc\"#", &[(1, 0, 2, 3)]); check_spans("r#\"á\nc\"#", &[(1, 0, 2, 3)]); check_spans("'a'", &[(1, 0, 1, 3)]); check_spans("'á'", &[(1, 0, 1, 3)]); check_spans("//! abc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); check_spans("//! ábc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); check_spans("//! abc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); check_spans("//! ábc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); check_spans("/*! abc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]); check_spans("/*! ábc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]); check_spans("/*! a\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]); check_spans("/*! á\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]); check_spans("abc", &[(1, 0, 1, 3)]); check_spans("ábc", &[(1, 0, 1, 3)]); check_spans("ábć", &[(1, 0, 1, 3)]); check_spans("abc// foo", &[(1, 0, 1, 3)]); check_spans("ábc// foo", &[(1, 0, 1, 3)]); check_spans("ábć// foo", &[(1, 0, 1, 3)]); check_spans("b\"a\\\n c\"", &[(1, 0, 2, 3)]); } #[cfg(span_locations)] fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) { let ts = p.parse::().unwrap(); check_spans_internal(ts, &mut lines); assert!(lines.is_empty(), "leftover ranges: {:?}", lines); } #[cfg(span_locations)] fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) { for i in ts { if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() { *lines = rest; let start = i.span().start(); assert_eq!(start.line, sline, "sline did not match for {}", i); assert_eq!(start.column, scol, "scol did not match for {}", i); let end = i.span().end(); assert_eq!(end.line, eline, "eline did not match for {}", i); assert_eq!(end.column, ecol, "ecol did not match for {}", i); if let TokenTree::Group(g) = i { check_spans_internal(g.stream().clone(), lines); } } } } #[test] fn whitespace() { // space, horizontal tab, vertical tab, form feed, carriage return, line // feed, non-breaking space, left-to-right mark, right-to-left mark let various_spaces = " \t\u{b}\u{c}\r\n\u{a0}\u{200e}\u{200f}"; let tokens = various_spaces.parse::().unwrap(); assert_eq!(tokens.into_iter().count(), 0); let lone_carriage_returns = " \r \r\r\n "; lone_carriage_returns.parse::().unwrap(); } #[test] fn byte_order_mark() { let string = "\u{feff}foo"; let tokens = string.parse::().unwrap(); match tokens.into_iter().next().unwrap() { TokenTree::Ident(ident) => assert_eq!(ident, "foo"), _ => unreachable!(), } let string = "foo\u{feff}"; string.parse::().unwrap_err(); } #[cfg(span_locations)] fn create_span() -> proc_macro2::Span { let tts: TokenStream = "1".parse().unwrap(); match tts.into_iter().next().unwrap() { TokenTree::Literal(literal) => literal.span(), _ => unreachable!(), } } #[cfg(span_locations)] #[test] fn test_invalidate_current_thread_spans() { let actual = format!("{:#?}", create_span()); assert_eq!(actual, "bytes(1..2)"); let actual = format!("{:#?}", create_span()); assert_eq!(actual, "bytes(3..4)"); proc_macro2::extra::invalidate_current_thread_spans(); let actual = format!("{:#?}", create_span()); // Test that span offsets have been reset after the call // to invalidate_current_thread_spans() assert_eq!(actual, "bytes(1..2)"); } #[cfg(span_locations)] #[test] #[should_panic(expected = "Invalid span with no related FileInfo!")] fn test_use_span_after_invalidation() { let span = create_span(); proc_macro2::extra::invalidate_current_thread_spans(); span.source_text(); } proc-macro2/tests/features.rs0000644000175000017500000000023015105742312016047 0ustar bdrungbdrung#[test] #[ignore] fn make_sure_no_proc_macro() { assert!( !cfg!(feature = "proc-macro"), "still compiled with proc_macro?" ); } proc-macro2/tests/marker.rs0000644000175000017500000000512715105742312015524 0ustar bdrungbdrung#![allow(clippy::extra_unused_type_parameters)] use proc_macro2::{ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, }; macro_rules! assert_impl { ($ty:ident is $($marker:ident) and +) => { #[test] #[allow(non_snake_case)] fn $ty() { fn assert_implemented() {} assert_implemented::<$ty>(); } }; ($ty:ident is not $($marker:ident) or +) => { #[test] #[allow(non_snake_case)] fn $ty() { $( { // Implemented for types that implement $marker. #[allow(dead_code)] trait IsNotImplemented { fn assert_not_implemented() {} } impl IsNotImplemented for T {} // Implemented for the type being tested. trait IsImplemented { fn assert_not_implemented() {} } impl IsImplemented for $ty {} // If $ty does not implement $marker, there is no ambiguity // in the following trait method call. <$ty>::assert_not_implemented(); } )+ } }; } assert_impl!(Delimiter is Send and Sync); assert_impl!(Spacing is Send and Sync); assert_impl!(Group is not Send or Sync); assert_impl!(Ident is not Send or Sync); assert_impl!(LexError is not Send or Sync); assert_impl!(Literal is not Send or Sync); assert_impl!(Punct is not Send or Sync); assert_impl!(Span is not Send or Sync); assert_impl!(TokenStream is not Send or Sync); assert_impl!(TokenTree is not Send or Sync); #[cfg(procmacro2_semver_exempt)] mod semver_exempt { use proc_macro2::LineColumn; assert_impl!(LineColumn is Send and Sync); } mod unwind_safe { #[cfg(procmacro2_semver_exempt)] use proc_macro2::LineColumn; use proc_macro2::{ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, }; use std::panic::{RefUnwindSafe, UnwindSafe}; macro_rules! assert_unwind_safe { ($($types:ident)*) => { $( assert_impl!($types is UnwindSafe and RefUnwindSafe); )* }; } assert_unwind_safe! { Delimiter Group Ident LexError Literal Punct Spacing Span TokenStream TokenTree } #[cfg(procmacro2_semver_exempt)] assert_unwind_safe! { LineColumn } } proc-macro2/tests/comments.rs0000644000175000017500000000654115105742312016071 0ustar bdrungbdrung#![allow(clippy::assertions_on_result_states)] use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree}; // #[doc = "..."] -> "..." fn lit_of_outer_doc_comment(tokens: &TokenStream) -> Literal { lit_of_doc_comment(tokens, false) } // #![doc = "..."] -> "..." fn lit_of_inner_doc_comment(tokens: &TokenStream) -> Literal { lit_of_doc_comment(tokens, true) } fn lit_of_doc_comment(tokens: &TokenStream, inner: bool) -> Literal { let mut iter = tokens.clone().into_iter(); match iter.next().unwrap() { TokenTree::Punct(punct) => { assert_eq!(punct.as_char(), '#'); assert_eq!(punct.spacing(), Spacing::Alone); } _ => panic!("wrong token {:?}", tokens), } if inner { match iter.next().unwrap() { TokenTree::Punct(punct) => { assert_eq!(punct.as_char(), '!'); assert_eq!(punct.spacing(), Spacing::Alone); } _ => panic!("wrong token {:?}", tokens), } } iter = match iter.next().unwrap() { TokenTree::Group(group) => { assert_eq!(group.delimiter(), Delimiter::Bracket); assert!(iter.next().is_none(), "unexpected token {:?}", tokens); group.stream().into_iter() } _ => panic!("wrong token {:?}", tokens), }; match iter.next().unwrap() { TokenTree::Ident(ident) => assert_eq!(ident.to_string(), "doc"), _ => panic!("wrong token {:?}", tokens), } match iter.next().unwrap() { TokenTree::Punct(punct) => { assert_eq!(punct.as_char(), '='); assert_eq!(punct.spacing(), Spacing::Alone); } _ => panic!("wrong token {:?}", tokens), } match iter.next().unwrap() { TokenTree::Literal(literal) => { assert!(iter.next().is_none(), "unexpected token {:?}", tokens); literal } _ => panic!("wrong token {:?}", tokens), } } #[test] fn closed_immediately() { let stream = "/**/".parse::().unwrap(); let tokens = stream.into_iter().collect::>(); assert!(tokens.is_empty(), "not empty -- {:?}", tokens); } #[test] fn incomplete() { assert!("/*/".parse::().is_err()); } #[test] fn lit() { let stream = "/// doc".parse::().unwrap(); let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc\""); let stream = "//! doc".parse::().unwrap(); let lit = lit_of_inner_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc\""); let stream = "/** doc */".parse::().unwrap(); let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc \""); let stream = "/*! doc */".parse::().unwrap(); let lit = lit_of_inner_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc \""); } #[test] fn carriage_return() { let stream = "///\r\n".parse::().unwrap(); let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\"\""); let stream = "/**\r\n*/".parse::().unwrap(); let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\"\\r\\n\""); "///\r".parse::().unwrap_err(); "///\r \n".parse::().unwrap_err(); "/**\r \n*/".parse::().unwrap_err(); } proc-macro2/tests/test_fmt.rs0000644000175000017500000000244015105742312016063 0ustar bdrungbdrung#![allow(clippy::from_iter_instead_of_collect)] use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use std::iter; #[test] fn test_fmt_group() { let ident = Ident::new("x", Span::call_site()); let inner = TokenStream::from_iter(iter::once(TokenTree::Ident(ident))); let parens_empty = Group::new(Delimiter::Parenthesis, TokenStream::new()); let parens_nonempty = Group::new(Delimiter::Parenthesis, inner.clone()); let brackets_empty = Group::new(Delimiter::Bracket, TokenStream::new()); let brackets_nonempty = Group::new(Delimiter::Bracket, inner.clone()); let braces_empty = Group::new(Delimiter::Brace, TokenStream::new()); let braces_nonempty = Group::new(Delimiter::Brace, inner.clone()); let none_empty = Group::new(Delimiter::None, TokenStream::new()); let none_nonempty = Group::new(Delimiter::None, inner); // Matches libproc_macro. assert_eq!("()", parens_empty.to_string()); assert_eq!("(x)", parens_nonempty.to_string()); assert_eq!("[]", brackets_empty.to_string()); assert_eq!("[x]", brackets_nonempty.to_string()); assert_eq!("{ }", braces_empty.to_string()); assert_eq!("{ x }", braces_nonempty.to_string()); assert_eq!("", none_empty.to_string()); assert_eq!("x", none_nonempty.to_string()); } proc-macro2/LICENSE-MIT0000644000175000017500000000177715105742312014176 0ustar bdrungbdrungPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. proc-macro2/Cargo.lock0000644000175000017500000001770415105742312014444 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "adler2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "bitflags" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "crc32fast" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-deque" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "errno" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys", ] [[package]] name = "filetime" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", "libredox", "windows-sys", ] [[package]] name = "flate2" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "libc" version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libredox" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags", "libc", "redox_syscall", ] [[package]] name = "linux-raw-sys" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "miniz_oxide" version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", ] [[package]] name = "proc-macro2" version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "proc-macro2" version = "1.0.95" dependencies = [ "flate2", "quote", "rayon", "rustversion", "tar", "unicode-ident", ] [[package]] name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2 1.0.94", ] [[package]] name = "rayon" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "redox_syscall" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags", ] [[package]] name = "rustix" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "rustversion" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" [[package]] name = "tar" version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" dependencies = [ "filetime", "libc", "xattr", ] [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xattr" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" dependencies = [ "libc", "rustix", ] proc-macro2/Cargo.toml0000644000175000017500000000457115105742312014465 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "proc-macro2" version = "1.0.95" authors = [ "David Tolnay ", "Alex Crichton ", ] build = "build.rs" autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case." documentation = "https://docs.rs/proc-macro2" readme = "README.md" keywords = [ "macros", "syn", ] categories = ["development-tools::procedural-macro-helpers"] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/proc-macro2" [package.metadata.docs.rs] rustc-args = ["--cfg=procmacro2_semver_exempt"] rustdoc-args = [ "--cfg=procmacro2_semver_exempt", "--generate-link-to-definition", "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", "--extern-html-root-url=proc_macro=https://doc.rust-lang.org", ] targets = ["x86_64-unknown-linux-gnu"] [package.metadata.playground] features = ["span-locations"] [features] default = ["proc-macro"] nightly = [] proc-macro = [] span-locations = [] [lib] name = "proc_macro2" path = "src/lib.rs" [[test]] name = "comments" path = "tests/comments.rs" [[test]] name = "features" path = "tests/features.rs" [[test]] name = "marker" path = "tests/marker.rs" [[test]] name = "test" path = "tests/test.rs" [[test]] name = "test_fmt" path = "tests/test_fmt.rs" [[test]] name = "test_size" path = "tests/test_size.rs" [dependencies.unicode-ident] version = "1.0" [dev-dependencies.flate2] version = "1.0" [dev-dependencies.quote] version = "1.0" default-features = false [dev-dependencies.rayon] version = "1.0" [dev-dependencies.rustversion] version = "1" [dev-dependencies.tar] version = "0.4" proc-macro2/.cargo-checksum.json0000664000175000017500000000013115105742312016367 0ustar bdrungbdrung{"files":{},"package":"02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"}proc-macro2/LICENSE-APACHE0000644000175000017500000002277315105742312014465 0ustar bdrungbdrung Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS proc-macro2/rust-toolchain.toml0000644000175000017500000000004615105742312016376 0ustar bdrungbdrung[toolchain] components = ["rust-src"] proc-macro2/README.md0000644000175000017500000000743215105742312014013 0ustar bdrungbdrung# proc-macro2 [github](https://github.com/dtolnay/proc-macro2) [crates.io](https://crates.io/crates/proc-macro2) [docs.rs](https://docs.rs/proc-macro2) [build status](https://github.com/dtolnay/proc-macro2/actions?query=branch%3Amaster) A wrapper around the procedural macro API of the compiler's `proc_macro` crate. This library serves two purposes: - **Bring proc-macro-like functionality to other contexts like build.rs and main.rs.** Types from `proc_macro` are entirely specific to procedural macros and cannot ever exist in code outside of a procedural macro. Meanwhile `proc_macro2` types may exist anywhere including non-macro code. By developing foundational libraries like [syn] and [quote] against `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem becomes easily applicable to many other use cases and we avoid reimplementing non-macro equivalents of those libraries. - **Make procedural macros unit testable.** As a consequence of being specific to procedural macros, nothing that uses `proc_macro` can be executed from a unit test. In order for helper libraries or components of a macro to be testable in isolation, they must be implemented using `proc_macro2`. [syn]: https://github.com/dtolnay/syn [quote]: https://github.com/dtolnay/quote ## Usage ```toml [dependencies] proc-macro2 = "1.0" ``` The skeleton of a typical procedural macro typically looks like this: ```rust extern crate proc_macro; #[proc_macro_derive(MyDerive)] pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = proc_macro2::TokenStream::from(input); let output: proc_macro2::TokenStream = { /* transform input */ }; proc_macro::TokenStream::from(output) } ``` If parsing with [Syn], you'll use [`parse_macro_input!`] instead to propagate parse errors correctly back to the compiler when parsing fails. [`parse_macro_input!`]: https://docs.rs/syn/2.0/syn/macro.parse_macro_input.html ## Unstable features The default feature set of proc-macro2 tracks the most recent stable compiler API. Functionality in `proc_macro` that is not yet stable is not exposed by proc-macro2 by default. To opt into the additional APIs available in the most recent nightly compiler, the `procmacro2_semver_exempt` config flag must be passed to rustc. We will polyfill those nightly-only APIs back to Rust 1.56.0. As these are unstable APIs that track the nightly compiler, minor versions of proc-macro2 may make breaking changes to them at any time. ``` RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build ``` Note that this must not only be done for your crate, but for any crate that depends on your crate. This infectious nature is intentional, as it serves as a reminder that you are outside of the normal semver guarantees. Semver exempt methods are marked as such in the proc-macro2 documentation.
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. proc-macro2/src/0000775000175000017500000000000015105742312013317 5ustar bdrungbdrungproc-macro2/src/detection.rs0000644000175000017500000000521715105742312015646 0ustar bdrungbdrunguse core::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Once; static WORKS: AtomicUsize = AtomicUsize::new(0); static INIT: Once = Once::new(); pub(crate) fn inside_proc_macro() -> bool { match WORKS.load(Ordering::Relaxed) { 1 => return false, 2 => return true, _ => {} } INIT.call_once(initialize); inside_proc_macro() } pub(crate) fn force_fallback() { WORKS.store(1, Ordering::Relaxed); } pub(crate) fn unforce_fallback() { initialize(); } #[cfg(not(no_is_available))] fn initialize() { let available = proc_macro::is_available(); WORKS.store(available as usize + 1, Ordering::Relaxed); } // Swap in a null panic hook to avoid printing "thread panicked" to stderr, // then use catch_unwind to determine whether the compiler's proc_macro is // working. When proc-macro2 is used from outside of a procedural macro all // of the proc_macro crate's APIs currently panic. // // The Once is to prevent the possibility of this ordering: // // thread 1 calls take_hook, gets the user's original hook // thread 1 calls set_hook with the null hook // thread 2 calls take_hook, thinks null hook is the original hook // thread 2 calls set_hook with the null hook // thread 1 calls set_hook with the actual original hook // thread 2 calls set_hook with what it thinks is the original hook // // in which the user's hook has been lost. // // There is still a race condition where a panic in a different thread can // happen during the interval that the user's original panic hook is // unregistered such that their hook is incorrectly not called. This is // sufficiently unlikely and less bad than printing panic messages to stderr // on correct use of this crate. Maybe there is a libstd feature request // here. For now, if a user needs to guarantee that this failure mode does // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from // the main thread before launching any other threads. #[cfg(no_is_available)] fn initialize() { use std::panic::{self, PanicInfo}; type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; let null_hook: Box = Box::new(|_panic_info| { /* ignore */ }); let sanity_check = &*null_hook as *const PanicHook; let original_hook = panic::take_hook(); panic::set_hook(null_hook); let works = panic::catch_unwind(proc_macro::Span::call_site).is_ok(); WORKS.store(works as usize + 1, Ordering::Relaxed); let hopefully_null_hook = panic::take_hook(); panic::set_hook(original_hook); if sanity_check != &*hopefully_null_hook { panic!("observed race condition in proc_macro2::inside_proc_macro"); } } proc-macro2/src/lib.rs0000644000175000017500000013044015105742312014433 0ustar bdrungbdrung//! [![github]](https://github.com/dtolnay/proc-macro2) [![crates-io]](https://crates.io/crates/proc-macro2) [![docs-rs]](crate) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //!
//! //! A wrapper around the procedural macro API of the compiler's [`proc_macro`] //! crate. This library serves two purposes: //! //! - **Bring proc-macro-like functionality to other contexts like build.rs and //! main.rs.** Types from `proc_macro` are entirely specific to procedural //! macros and cannot ever exist in code outside of a procedural macro. //! Meanwhile `proc_macro2` types may exist anywhere including non-macro code. //! By developing foundational libraries like [syn] and [quote] against //! `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem //! becomes easily applicable to many other use cases and we avoid //! reimplementing non-macro equivalents of those libraries. //! //! - **Make procedural macros unit testable.** As a consequence of being //! specific to procedural macros, nothing that uses `proc_macro` can be //! executed from a unit test. In order for helper libraries or components of //! a macro to be testable in isolation, they must be implemented using //! `proc_macro2`. //! //! [syn]: https://github.com/dtolnay/syn //! [quote]: https://github.com/dtolnay/quote //! //! # Usage //! //! The skeleton of a typical procedural macro typically looks like this: //! //! ``` //! extern crate proc_macro; //! //! # const IGNORE: &str = stringify! { //! #[proc_macro_derive(MyDerive)] //! # }; //! # #[cfg(wrap_proc_macro)] //! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { //! let input = proc_macro2::TokenStream::from(input); //! //! let output: proc_macro2::TokenStream = { //! /* transform input */ //! # input //! }; //! //! proc_macro::TokenStream::from(output) //! } //! ``` //! //! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to //! propagate parse errors correctly back to the compiler when parsing fails. //! //! [`parse_macro_input!`]: https://docs.rs/syn/2.0/syn/macro.parse_macro_input.html //! //! # Unstable features //! //! The default feature set of proc-macro2 tracks the most recent stable //! compiler API. Functionality in `proc_macro` that is not yet stable is not //! exposed by proc-macro2 by default. //! //! To opt into the additional APIs available in the most recent nightly //! compiler, the `procmacro2_semver_exempt` config flag must be passed to //! rustc. We will polyfill those nightly-only APIs back to Rust 1.56.0. As //! these are unstable APIs that track the nightly compiler, minor versions of //! proc-macro2 may make breaking changes to them at any time. //! //! ```sh //! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build //! ``` //! //! Note that this must not only be done for your crate, but for any crate that //! depends on your crate. This infectious nature is intentional, as it serves //! as a reminder that you are outside of the normal semver guarantees. //! //! Semver exempt methods are marked as such in the proc-macro2 documentation. //! //! # Thread-Safety //! //! Most types in this crate are `!Sync` because the underlying compiler //! types make use of thread-local memory, meaning they cannot be accessed from //! a different thread. // Proc-macro2 types in rustdoc of other crates get linked to here. #![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.95")] #![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))] #![cfg_attr(super_unstable, feature(proc_macro_def_site))] #![cfg_attr(docsrs, feature(doc_cfg))] #![deny(unsafe_op_in_unsafe_fn)] #![allow( clippy::cast_lossless, clippy::cast_possible_truncation, clippy::checked_conversions, clippy::doc_markdown, clippy::elidable_lifetime_names, clippy::incompatible_msrv, clippy::items_after_statements, clippy::iter_without_into_iter, clippy::let_underscore_untyped, clippy::manual_assert, clippy::manual_range_contains, clippy::missing_panics_doc, clippy::missing_safety_doc, clippy::must_use_candidate, clippy::needless_doctest_main, clippy::needless_lifetimes, clippy::new_without_default, clippy::return_self_not_must_use, clippy::shadow_unrelated, clippy::trivially_copy_pass_by_ref, clippy::unnecessary_wraps, clippy::unused_self, clippy::used_underscore_binding, clippy::vec_init_then_push )] #[cfg(all(procmacro2_semver_exempt, wrap_proc_macro, not(super_unstable)))] compile_error! {"\ Something is not right. If you've tried to turn on \ procmacro2_semver_exempt, you need to ensure that it \ is turned on for the compilation of the proc-macro2 \ build script as well. "} #[cfg(all( procmacro2_nightly_testing, feature = "proc-macro", not(proc_macro_span) ))] compile_error! {"\ Build script probe failed to compile. "} extern crate alloc; #[cfg(feature = "proc-macro")] extern crate proc_macro; mod marker; mod parse; mod rcvec; #[cfg(wrap_proc_macro)] mod detection; // Public for proc_macro2::fallback::force() and unforce(), but those are quite // a niche use case so we omit it from rustdoc. #[doc(hidden)] pub mod fallback; pub mod extra; #[cfg(not(wrap_proc_macro))] use crate::fallback as imp; #[path = "wrapper.rs"] #[cfg(wrap_proc_macro)] mod imp; #[cfg(span_locations)] mod location; use crate::extra::DelimSpan; use crate::marker::{ProcMacroAutoTraits, MARKER}; use core::cmp::Ordering; use core::fmt::{self, Debug, Display}; use core::hash::{Hash, Hasher}; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; use core::str::FromStr; use std::error::Error; use std::ffi::CStr; #[cfg(procmacro2_semver_exempt)] use std::path::PathBuf; #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub use crate::location::LineColumn; /// An abstract stream of tokens, or more concretely a sequence of token trees. /// /// This type provides interfaces for iterating over token trees and for /// collecting token trees into one stream. /// /// Token stream is both the input and output of `#[proc_macro]`, /// `#[proc_macro_attribute]` and `#[proc_macro_derive]` definitions. #[derive(Clone)] pub struct TokenStream { inner: imp::TokenStream, _marker: ProcMacroAutoTraits, } /// Error returned from `TokenStream::from_str`. pub struct LexError { inner: imp::LexError, _marker: ProcMacroAutoTraits, } impl TokenStream { fn _new(inner: imp::TokenStream) -> Self { TokenStream { inner, _marker: MARKER, } } fn _new_fallback(inner: fallback::TokenStream) -> Self { TokenStream { inner: imp::TokenStream::from(inner), _marker: MARKER, } } /// Returns an empty `TokenStream` containing no token trees. pub fn new() -> Self { TokenStream::_new(imp::TokenStream::new()) } /// Checks if this `TokenStream` is empty. pub fn is_empty(&self) -> bool { self.inner.is_empty() } } /// `TokenStream::default()` returns an empty stream, /// i.e. this is equivalent with `TokenStream::new()`. impl Default for TokenStream { fn default() -> Self { TokenStream::new() } } /// Attempts to break the string into tokens and parse those tokens into a token /// stream. /// /// May fail for a number of reasons, for example, if the string contains /// unbalanced delimiters or characters not existing in the language. /// /// NOTE: Some errors may cause panics instead of returning `LexError`. We /// reserve the right to change these errors into `LexError`s later. impl FromStr for TokenStream { type Err = LexError; fn from_str(src: &str) -> Result { match imp::TokenStream::from_str_checked(src) { Ok(tokens) => Ok(TokenStream::_new(tokens)), Err(lex) => Err(LexError { inner: lex, _marker: MARKER, }), } } } #[cfg(feature = "proc-macro")] #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { TokenStream::_new(imp::TokenStream::from(inner)) } } #[cfg(feature = "proc-macro")] #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { proc_macro::TokenStream::from(inner.inner) } } impl From for TokenStream { fn from(token: TokenTree) -> Self { TokenStream::_new(imp::TokenStream::from(token)) } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { self.inner.extend(streams); } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { self.inner .extend(streams.into_iter().map(|stream| stream.inner)); } } /// Collects a number of token trees into a single stream. impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { TokenStream::_new(streams.into_iter().collect()) } } impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { TokenStream::_new(streams.into_iter().map(|i| i.inner).collect()) } } /// Prints the token stream as a string that is supposed to be losslessly /// convertible back into the same token stream (modulo spans), except for /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative /// numeric literals. impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } /// Prints token in a form convenient for debugging. impl Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } impl LexError { pub fn span(&self) -> Span { Span::_new(self.inner.span()) } } impl Debug for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } impl Error for LexError {} /// A region of source code, along with macro expansion information. #[derive(Copy, Clone)] pub struct Span { inner: imp::Span, _marker: ProcMacroAutoTraits, } impl Span { fn _new(inner: imp::Span) -> Self { Span { inner, _marker: MARKER, } } fn _new_fallback(inner: fallback::Span) -> Self { Span { inner: imp::Span::from(inner), _marker: MARKER, } } /// The span of the invocation of the current procedural macro. /// /// Identifiers created with this span will be resolved as if they were /// written directly at the macro call location (call-site hygiene) and /// other code at the macro call site will be able to refer to them as well. pub fn call_site() -> Self { Span::_new(imp::Span::call_site()) } /// The span located at the invocation of the procedural macro, but with /// local variables, labels, and `$crate` resolved at the definition site /// of the macro. This is the same hygiene behavior as `macro_rules`. pub fn mixed_site() -> Self { Span::_new(imp::Span::mixed_site()) } /// A span that resolves at the macro definition site. /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn def_site() -> Self { Span::_new(imp::Span::def_site()) } /// Creates a new span with the same line/column information as `self` but /// that resolves symbols as though it were at `other`. pub fn resolved_at(&self, other: Span) -> Span { Span::_new(self.inner.resolved_at(other.inner)) } /// Creates a new span with the same name resolution behavior as `self` but /// with the line/column information of `other`. pub fn located_at(&self, other: Span) -> Span { Span::_new(self.inner.located_at(other.inner)) } /// Convert `proc_macro2::Span` to `proc_macro::Span`. /// /// This method is available when building with a nightly compiler, or when /// building with rustc 1.29+ *without* semver exempt features. /// /// # Panics /// /// Panics if called from outside of a procedural macro. Unlike /// `proc_macro2::Span`, the `proc_macro::Span` type can only exist within /// the context of a procedural macro invocation. #[cfg(wrap_proc_macro)] pub fn unwrap(self) -> proc_macro::Span { self.inner.unwrap() } // Soft deprecated. Please use Span::unwrap. #[cfg(wrap_proc_macro)] #[doc(hidden)] pub fn unstable(self) -> proc_macro::Span { self.unwrap() } /// Returns the span's byte position range in the source file. /// /// This method requires the `"span-locations"` feature to be enabled. /// /// When executing in a procedural macro context, the returned range is only /// accurate if compiled with a nightly toolchain. The stable toolchain does /// not have this information available. When executing outside of a /// procedural macro, such as main.rs or build.rs, the byte range is always /// accurate regardless of toolchain. #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn byte_range(&self) -> Range { self.inner.byte_range() } /// Get the starting line/column in the source file for this span. /// /// This method requires the `"span-locations"` feature to be enabled. /// /// When executing in a procedural macro context, the returned line/column /// are only meaningful if compiled with a nightly toolchain. The stable /// toolchain does not have this information available. When executing /// outside of a procedural macro, such as main.rs or build.rs, the /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn start(&self) -> LineColumn { self.inner.start() } /// Get the ending line/column in the source file for this span. /// /// This method requires the `"span-locations"` feature to be enabled. /// /// When executing in a procedural macro context, the returned line/column /// are only meaningful if compiled with a nightly toolchain. The stable /// toolchain does not have this information available. When executing /// outside of a procedural macro, such as main.rs or build.rs, the /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn end(&self) -> LineColumn { self.inner.end() } /// The path to the source file in which this span occurs, for display /// purposes. /// /// This might not correspond to a valid file system path. It might be /// remapped, or might be an artificial path such as `""`. /// /// This method is semver exempt and not exposed by default. #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn file(&self) -> String { self.inner.file() } /// The path to the source file in which this span occurs on disk. /// /// This is the actual path on disk. It is unaffected by path remapping. /// /// This path should not be embedded in the output of the macro; prefer /// `file()` instead. /// /// This method is semver exempt and not exposed by default. #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn local_file(&self) -> Option { self.inner.local_file() } /// Create a new span encompassing `self` and `other`. /// /// Returns `None` if `self` and `other` are from different files. /// /// Warning: the underlying [`proc_macro::Span::join`] method is /// nightly-only. When called from within a procedural macro not using a /// nightly compiler, this method will always return `None`. pub fn join(&self, other: Span) -> Option { self.inner.join(other.inner).map(Span::_new) } /// Compares two spans to see if they're equal. /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn eq(&self, other: &Span) -> bool { self.inner.eq(&other.inner) } /// Returns the source text behind a span. This preserves the original /// source code, including spaces and comments. It only returns a result if /// the span corresponds to real source code. /// /// Note: The observable result of a macro should only rely on the tokens /// and not on this source text. The result of this function is a best /// effort to be used for diagnostics only. pub fn source_text(&self) -> Option { self.inner.source_text() } } /// Prints a span in a form convenient for debugging. impl Debug for Span { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`). #[derive(Clone)] pub enum TokenTree { /// A token stream surrounded by bracket delimiters. Group(Group), /// An identifier. Ident(Ident), /// A single punctuation character (`+`, `,`, `$`, etc.). Punct(Punct), /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc. Literal(Literal), } impl TokenTree { /// Returns the span of this tree, delegating to the `span` method of /// the contained token or a delimited stream. pub fn span(&self) -> Span { match self { TokenTree::Group(t) => t.span(), TokenTree::Ident(t) => t.span(), TokenTree::Punct(t) => t.span(), TokenTree::Literal(t) => t.span(), } } /// Configures the span for *only this token*. /// /// Note that if this token is a `Group` then this method will not configure /// the span of each of the internal tokens, this will simply delegate to /// the `set_span` method of each variant. pub fn set_span(&mut self, span: Span) { match self { TokenTree::Group(t) => t.set_span(span), TokenTree::Ident(t) => t.set_span(span), TokenTree::Punct(t) => t.set_span(span), TokenTree::Literal(t) => t.set_span(span), } } } impl From for TokenTree { fn from(g: Group) -> Self { TokenTree::Group(g) } } impl From for TokenTree { fn from(g: Ident) -> Self { TokenTree::Ident(g) } } impl From for TokenTree { fn from(g: Punct) -> Self { TokenTree::Punct(g) } } impl From for TokenTree { fn from(g: Literal) -> Self { TokenTree::Literal(g) } } /// Prints the token tree as a string that is supposed to be losslessly /// convertible back into the same token tree (modulo spans), except for /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative /// numeric literals. impl Display for TokenTree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenTree::Group(t) => Display::fmt(t, f), TokenTree::Ident(t) => Display::fmt(t, f), TokenTree::Punct(t) => Display::fmt(t, f), TokenTree::Literal(t) => Display::fmt(t, f), } } } /// Prints token tree in a form convenient for debugging. impl Debug for TokenTree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Each of these has the name in the struct type in the derived debug, // so don't bother with an extra layer of indirection match self { TokenTree::Group(t) => Debug::fmt(t, f), TokenTree::Ident(t) => { let mut debug = f.debug_struct("Ident"); debug.field("sym", &format_args!("{}", t)); imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner); debug.finish() } TokenTree::Punct(t) => Debug::fmt(t, f), TokenTree::Literal(t) => Debug::fmt(t, f), } } } /// A delimited token stream. /// /// A `Group` internally contains a `TokenStream` which is surrounded by /// `Delimiter`s. #[derive(Clone)] pub struct Group { inner: imp::Group, } /// Describes how a sequence of token trees is delimited. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Delimiter { /// `( ... )` Parenthesis, /// `{ ... }` Brace, /// `[ ... ]` Bracket, /// `∅ ... ∅` /// /// An invisible delimiter, that may, for example, appear around tokens /// coming from a "macro variable" `$var`. It is important to preserve /// operator priorities in cases like `$var * 3` where `$var` is `1 + 2`. /// Invisible delimiters may not survive roundtrip of a token stream through /// a string. /// ///
/// /// Note: rustc currently can ignore the grouping of tokens delimited by `None` in the output /// of a proc_macro. Only `None`-delimited groups created by a macro_rules macro in the input /// of a proc_macro macro are preserved, and only in very specific circumstances. /// Any `None`-delimited groups (re)created by a proc_macro will therefore not preserve /// operator priorities as indicated above. The other `Delimiter` variants should be used /// instead in this context. This is a rustc bug. For details, see /// [rust-lang/rust#67062](https://github.com/rust-lang/rust/issues/67062). /// ///
None, } impl Group { fn _new(inner: imp::Group) -> Self { Group { inner } } fn _new_fallback(inner: fallback::Group) -> Self { Group { inner: imp::Group::from(inner), } } /// Creates a new `Group` with the given delimiter and token stream. /// /// This constructor will set the span for this group to /// `Span::call_site()`. To change the span you can use the `set_span` /// method below. pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self { Group { inner: imp::Group::new(delimiter, stream.inner), } } /// Returns the punctuation used as the delimiter for this group: a set of /// parentheses, square brackets, or curly braces. pub fn delimiter(&self) -> Delimiter { self.inner.delimiter() } /// Returns the `TokenStream` of tokens that are delimited in this `Group`. /// /// Note that the returned token stream does not include the delimiter /// returned above. pub fn stream(&self) -> TokenStream { TokenStream::_new(self.inner.stream()) } /// Returns the span for the delimiters of this token stream, spanning the /// entire `Group`. /// /// ```text /// pub fn span(&self) -> Span { /// ^^^^^^^ /// ``` pub fn span(&self) -> Span { Span::_new(self.inner.span()) } /// Returns the span pointing to the opening delimiter of this group. /// /// ```text /// pub fn span_open(&self) -> Span { /// ^ /// ``` pub fn span_open(&self) -> Span { Span::_new(self.inner.span_open()) } /// Returns the span pointing to the closing delimiter of this group. /// /// ```text /// pub fn span_close(&self) -> Span { /// ^ /// ``` pub fn span_close(&self) -> Span { Span::_new(self.inner.span_close()) } /// Returns an object that holds this group's `span_open()` and /// `span_close()` together (in a more compact representation than holding /// those 2 spans individually). pub fn delim_span(&self) -> DelimSpan { DelimSpan::new(&self.inner) } /// Configures the span for this `Group`'s delimiters, but not its internal /// tokens. /// /// This method will **not** set the span of all the internal tokens spanned /// by this group, but rather it will only set the span of the delimiter /// tokens at the level of the `Group`. pub fn set_span(&mut self, span: Span) { self.inner.set_span(span.inner); } } /// Prints the group as a string that should be losslessly convertible back /// into the same group (modulo spans), except for possibly `TokenTree::Group`s /// with `Delimiter::None` delimiters. impl Display for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, formatter) } } impl Debug for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, formatter) } } /// A `Punct` is a single punctuation character like `+`, `-` or `#`. /// /// Multicharacter operators like `+=` are represented as two instances of /// `Punct` with different forms of `Spacing` returned. #[derive(Clone)] pub struct Punct { ch: char, spacing: Spacing, span: Span, } /// Whether a `Punct` is followed immediately by another `Punct` or followed by /// another token or whitespace. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Spacing { /// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`. Alone, /// E.g. `+` is `Joint` in `+=` or `'` is `Joint` in `'#`. /// /// Additionally, single quote `'` can join with identifiers to form /// lifetimes `'ident`. Joint, } impl Punct { /// Creates a new `Punct` from the given character and spacing. /// /// The `ch` argument must be a valid punctuation character permitted by the /// language, otherwise the function will panic. /// /// The returned `Punct` will have the default span of `Span::call_site()` /// which can be further configured with the `set_span` method below. pub fn new(ch: char, spacing: Spacing) -> Self { if let '!' | '#' | '$' | '%' | '&' | '\'' | '*' | '+' | ',' | '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '^' | '|' | '~' = ch { Punct { ch, spacing, span: Span::call_site(), } } else { panic!("unsupported proc macro punctuation character {:?}", ch); } } /// Returns the value of this punctuation character as `char`. pub fn as_char(&self) -> char { self.ch } /// Returns the spacing of this punctuation character, indicating whether /// it's immediately followed by another `Punct` in the token stream, so /// they can potentially be combined into a multicharacter operator /// (`Joint`), or it's followed by some other token or whitespace (`Alone`) /// so the operator has certainly ended. pub fn spacing(&self) -> Spacing { self.spacing } /// Returns the span for this punctuation character. pub fn span(&self) -> Span { self.span } /// Configure the span for this punctuation character. pub fn set_span(&mut self, span: Span) { self.span = span; } } /// Prints the punctuation character as a string that should be losslessly /// convertible back into the same character. impl Display for Punct { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.ch, f) } } impl Debug for Punct { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut debug = fmt.debug_struct("Punct"); debug.field("char", &self.ch); debug.field("spacing", &self.spacing); imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner); debug.finish() } } /// A word of Rust code, which may be a keyword or legal variable name. /// /// An identifier consists of at least one Unicode code point, the first of /// which has the XID_Start property and the rest of which have the XID_Continue /// property. /// /// - The empty string is not an identifier. Use `Option`. /// - A lifetime is not an identifier. Use `syn::Lifetime` instead. /// /// An identifier constructed with `Ident::new` is permitted to be a Rust /// keyword, though parsing one through its [`Parse`] implementation rejects /// Rust keywords. Use `input.call(Ident::parse_any)` when parsing to match the /// behaviour of `Ident::new`. /// /// [`Parse`]: https://docs.rs/syn/2.0/syn/parse/trait.Parse.html /// /// # Examples /// /// A new ident can be created from a string using the `Ident::new` function. /// A span must be provided explicitly which governs the name resolution /// behavior of the resulting identifier. /// /// ``` /// use proc_macro2::{Ident, Span}; /// /// fn main() { /// let call_ident = Ident::new("calligraphy", Span::call_site()); /// /// println!("{}", call_ident); /// } /// ``` /// /// An ident can be interpolated into a token stream using the `quote!` macro. /// /// ``` /// use proc_macro2::{Ident, Span}; /// use quote::quote; /// /// fn main() { /// let ident = Ident::new("demo", Span::call_site()); /// /// // Create a variable binding whose name is this ident. /// let expanded = quote! { let #ident = 10; }; /// /// // Create a variable binding with a slightly different name. /// let temp_ident = Ident::new(&format!("new_{}", ident), Span::call_site()); /// let expanded = quote! { let #temp_ident = 10; }; /// } /// ``` /// /// A string representation of the ident is available through the `to_string()` /// method. /// /// ``` /// # use proc_macro2::{Ident, Span}; /// # /// # let ident = Ident::new("another_identifier", Span::call_site()); /// # /// // Examine the ident as a string. /// let ident_string = ident.to_string(); /// if ident_string.len() > 60 { /// println!("Very long identifier: {}", ident_string) /// } /// ``` #[derive(Clone)] pub struct Ident { inner: imp::Ident, _marker: ProcMacroAutoTraits, } impl Ident { fn _new(inner: imp::Ident) -> Self { Ident { inner, _marker: MARKER, } } fn _new_fallback(inner: fallback::Ident) -> Self { Ident { inner: imp::Ident::from(inner), _marker: MARKER, } } /// Creates a new `Ident` with the given `string` as well as the specified /// `span`. /// /// The `string` argument must be a valid identifier permitted by the /// language, otherwise the function will panic. /// /// Note that `span`, currently in rustc, configures the hygiene information /// for this identifier. /// /// As of this time `Span::call_site()` explicitly opts-in to "call-site" /// hygiene meaning that identifiers created with this span will be resolved /// as if they were written directly at the location of the macro call, and /// other code at the macro call site will be able to refer to them as well. /// /// Later spans like `Span::def_site()` will allow to opt-in to /// "definition-site" hygiene meaning that identifiers created with this /// span will be resolved at the location of the macro definition and other /// code at the macro call site will not be able to refer to them. /// /// Due to the current importance of hygiene this constructor, unlike other /// tokens, requires a `Span` to be specified at construction. /// /// # Panics /// /// Panics if the input string is neither a keyword nor a legal variable /// name. If you are not sure whether the string contains an identifier and /// need to handle an error case, use /// syn::parse_str::<Ident> /// rather than `Ident::new`. #[track_caller] pub fn new(string: &str, span: Span) -> Self { Ident::_new(imp::Ident::new_checked(string, span.inner)) } /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). The /// `string` argument must be a valid identifier permitted by the language /// (including keywords, e.g. `fn`). Keywords which are usable in path /// segments (e.g. `self`, `super`) are not supported, and will cause a /// panic. #[track_caller] pub fn new_raw(string: &str, span: Span) -> Self { Ident::_new(imp::Ident::new_raw_checked(string, span.inner)) } /// Returns the span of this `Ident`. pub fn span(&self) -> Span { Span::_new(self.inner.span()) } /// Configures the span of this `Ident`, possibly changing its hygiene /// context. pub fn set_span(&mut self, span: Span) { self.inner.set_span(span.inner); } } impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { self.inner == other.inner } } impl PartialEq for Ident where T: ?Sized + AsRef, { fn eq(&self, other: &T) -> bool { self.inner == other } } impl Eq for Ident {} impl PartialOrd for Ident { fn partial_cmp(&self, other: &Ident) -> Option { Some(self.cmp(other)) } } impl Ord for Ident { fn cmp(&self, other: &Ident) -> Ordering { self.to_string().cmp(&other.to_string()) } } impl Hash for Ident { fn hash(&self, hasher: &mut H) { self.to_string().hash(hasher); } } /// Prints the identifier as a string that should be losslessly convertible back /// into the same identifier. impl Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } impl Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } /// A literal string (`"hello"`), byte string (`b"hello"`), character (`'a'`), /// byte character (`b'a'`), an integer or floating point number with or without /// a suffix (`1`, `1u8`, `2.3`, `2.3f32`). /// /// Boolean literals like `true` and `false` do not belong here, they are /// `Ident`s. #[derive(Clone)] pub struct Literal { inner: imp::Literal, _marker: ProcMacroAutoTraits, } macro_rules! suffixed_int_literals { ($($name:ident => $kind:ident,)*) => ($( /// Creates a new suffixed integer literal with the specified value. /// /// This function will create an integer like `1u32` where the integer /// value specified is the first part of the token and the integral is /// also suffixed at the end. Literals created from negative numbers may /// not survive roundtrips through `TokenStream` or strings and may be /// broken into two tokens (`-` and positive literal). /// /// Literals created through this method have the `Span::call_site()` /// span by default, which can be configured with the `set_span` method /// below. pub fn $name(n: $kind) -> Literal { Literal::_new(imp::Literal::$name(n)) } )*) } macro_rules! unsuffixed_int_literals { ($($name:ident => $kind:ident,)*) => ($( /// Creates a new unsuffixed integer literal with the specified value. /// /// This function will create an integer like `1` where the integer /// value specified is the first part of the token. No suffix is /// specified on this token, meaning that invocations like /// `Literal::i8_unsuffixed(1)` are equivalent to /// `Literal::u32_unsuffixed(1)`. Literals created from negative numbers /// may not survive roundtrips through `TokenStream` or strings and may /// be broken into two tokens (`-` and positive literal). /// /// Literals created through this method have the `Span::call_site()` /// span by default, which can be configured with the `set_span` method /// below. pub fn $name(n: $kind) -> Literal { Literal::_new(imp::Literal::$name(n)) } )*) } impl Literal { fn _new(inner: imp::Literal) -> Self { Literal { inner, _marker: MARKER, } } fn _new_fallback(inner: fallback::Literal) -> Self { Literal { inner: imp::Literal::from(inner), _marker: MARKER, } } suffixed_int_literals! { u8_suffixed => u8, u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, i128_suffixed => i128, isize_suffixed => isize, } unsuffixed_int_literals! { u8_unsuffixed => u8, u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, i128_unsuffixed => i128, isize_unsuffixed => isize, } /// Creates a new unsuffixed floating-point literal. /// /// This constructor is similar to those like `Literal::i8_unsuffixed` where /// the float's value is emitted directly into the token but no suffix is /// used, so it may be inferred to be a `f64` later in the compiler. /// Literals created from negative numbers may not survive round-trips /// through `TokenStream` or strings and may be broken into two tokens (`-` /// and positive literal). /// /// # Panics /// /// This function requires that the specified float is finite, for example /// if it is infinity or NaN this function will panic. pub fn f64_unsuffixed(f: f64) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f64_unsuffixed(f)) } /// Creates a new suffixed floating-point literal. /// /// This constructor will create a literal like `1.0f64` where the value /// specified is the preceding part of the token and `f64` is the suffix of /// the token. This token will always be inferred to be an `f64` in the /// compiler. Literals created from negative numbers may not survive /// round-trips through `TokenStream` or strings and may be broken into two /// tokens (`-` and positive literal). /// /// # Panics /// /// This function requires that the specified float is finite, for example /// if it is infinity or NaN this function will panic. pub fn f64_suffixed(f: f64) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f64_suffixed(f)) } /// Creates a new unsuffixed floating-point literal. /// /// This constructor is similar to those like `Literal::i8_unsuffixed` where /// the float's value is emitted directly into the token but no suffix is /// used, so it may be inferred to be a `f64` later in the compiler. /// Literals created from negative numbers may not survive round-trips /// through `TokenStream` or strings and may be broken into two tokens (`-` /// and positive literal). /// /// # Panics /// /// This function requires that the specified float is finite, for example /// if it is infinity or NaN this function will panic. pub fn f32_unsuffixed(f: f32) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f32_unsuffixed(f)) } /// Creates a new suffixed floating-point literal. /// /// This constructor will create a literal like `1.0f32` where the value /// specified is the preceding part of the token and `f32` is the suffix of /// the token. This token will always be inferred to be an `f32` in the /// compiler. Literals created from negative numbers may not survive /// round-trips through `TokenStream` or strings and may be broken into two /// tokens (`-` and positive literal). /// /// # Panics /// /// This function requires that the specified float is finite, for example /// if it is infinity or NaN this function will panic. pub fn f32_suffixed(f: f32) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f32_suffixed(f)) } /// String literal. pub fn string(string: &str) -> Literal { Literal::_new(imp::Literal::string(string)) } /// Character literal. pub fn character(ch: char) -> Literal { Literal::_new(imp::Literal::character(ch)) } /// Byte character literal. pub fn byte_character(byte: u8) -> Literal { Literal::_new(imp::Literal::byte_character(byte)) } /// Byte string literal. pub fn byte_string(bytes: &[u8]) -> Literal { Literal::_new(imp::Literal::byte_string(bytes)) } /// C string literal. pub fn c_string(string: &CStr) -> Literal { Literal::_new(imp::Literal::c_string(string)) } /// Returns the span encompassing this literal. pub fn span(&self) -> Span { Span::_new(self.inner.span()) } /// Configures the span associated for this literal. pub fn set_span(&mut self, span: Span) { self.inner.set_span(span.inner); } /// Returns a `Span` that is a subset of `self.span()` containing only /// the source bytes in range `range`. Returns `None` if the would-be /// trimmed span is outside the bounds of `self`. /// /// Warning: the underlying [`proc_macro::Literal::subspan`] method is /// nightly-only. When called from within a procedural macro not using a /// nightly compiler, this method will always return `None`. pub fn subspan>(&self, range: R) -> Option { self.inner.subspan(range).map(Span::_new) } // Intended for the `quote!` macro to use when constructing a proc-macro2 // token out of a macro_rules $:literal token, which is already known to be // a valid literal. This avoids reparsing/validating the literal's string // representation. This is not public API other than for quote. #[doc(hidden)] pub unsafe fn from_str_unchecked(repr: &str) -> Self { Literal::_new(unsafe { imp::Literal::from_str_unchecked(repr) }) } } impl FromStr for Literal { type Err = LexError; fn from_str(repr: &str) -> Result { match imp::Literal::from_str_checked(repr) { Ok(lit) => Ok(Literal::_new(lit)), Err(lex) => Err(LexError { inner: lex, _marker: MARKER, }), } } } impl Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } impl Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } /// Public implementation details for the `TokenStream` type, such as iterators. pub mod token_stream { use crate::marker::{ProcMacroAutoTraits, MARKER}; use crate::{imp, TokenTree}; use core::fmt::{self, Debug}; pub use crate::TokenStream; /// An iterator over `TokenStream`'s `TokenTree`s. /// /// The iteration is "shallow", e.g. the iterator doesn't recurse into /// delimited groups, and returns whole groups as token trees. #[derive(Clone)] pub struct IntoIter { inner: imp::TokenTreeIter, _marker: ProcMacroAutoTraits, } impl Iterator for IntoIter { type Item = TokenTree; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("TokenStream ")?; f.debug_list().entries(self.clone()).finish() } } impl IntoIterator for TokenStream { type Item = TokenTree; type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { IntoIter { inner: self.inner.into_iter(), _marker: MARKER, } } } } proc-macro2/src/extra.rs0000644000175000017500000001205415105742312015010 0ustar bdrungbdrung//! Items which do not have a correspondence to any API in the proc_macro crate, //! but are necessary to include in proc-macro2. use crate::fallback; use crate::imp; use crate::marker::{ProcMacroAutoTraits, MARKER}; use crate::Span; use core::fmt::{self, Debug}; /// Invalidate any `proc_macro2::Span` that exist on the current thread. /// /// The implementation of `Span` uses thread-local data structures and this /// function clears them. Calling any method on a `Span` on the current thread /// created prior to the invalidation will return incorrect values or crash. /// /// This function is useful for programs that process more than 232 /// bytes of Rust source code on the same thread. Just like rustc, proc-macro2 /// uses 32-bit source locations, and these wrap around when the total source /// code processed by the same thread exceeds 232 bytes (4 /// gigabytes). After a wraparound, `Span` methods such as `source_text()` can /// return wrong data. /// /// # Example /// /// As of late 2023, there is 200 GB of Rust code published on crates.io. /// Looking at just the newest version of every crate, it is 16 GB of code. So a /// workload that involves parsing it all would overflow a 32-bit source /// location unless spans are being invalidated. /// /// ``` /// use flate2::read::GzDecoder; /// use std::ffi::OsStr; /// use std::io::{BufReader, Read}; /// use std::str::FromStr; /// use tar::Archive; /// /// rayon::scope(|s| { /// for krate in every_version_of_every_crate() { /// s.spawn(move |_| { /// proc_macro2::extra::invalidate_current_thread_spans(); /// /// let reader = BufReader::new(krate); /// let tar = GzDecoder::new(reader); /// let mut archive = Archive::new(tar); /// for entry in archive.entries().unwrap() { /// let mut entry = entry.unwrap(); /// let path = entry.path().unwrap(); /// if path.extension() != Some(OsStr::new("rs")) { /// continue; /// } /// let mut content = String::new(); /// entry.read_to_string(&mut content).unwrap(); /// match proc_macro2::TokenStream::from_str(&content) { /// Ok(tokens) => {/* ... */}, /// Err(_) => continue, /// } /// } /// }); /// } /// }); /// # /// # fn every_version_of_every_crate() -> Vec { /// # Vec::new() /// # } /// ``` /// /// # Panics /// /// This function is not applicable to and will panic if called from a /// procedural macro. #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn invalidate_current_thread_spans() { crate::imp::invalidate_current_thread_spans(); } /// An object that holds a [`Group`]'s `span_open()` and `span_close()` together /// in a more compact representation than holding those 2 spans individually. /// /// [`Group`]: crate::Group #[derive(Copy, Clone)] pub struct DelimSpan { inner: DelimSpanEnum, _marker: ProcMacroAutoTraits, } #[derive(Copy, Clone)] enum DelimSpanEnum { #[cfg(wrap_proc_macro)] Compiler { join: proc_macro::Span, open: proc_macro::Span, close: proc_macro::Span, }, Fallback(fallback::Span), } impl DelimSpan { pub(crate) fn new(group: &imp::Group) -> Self { #[cfg(wrap_proc_macro)] let inner = match group { imp::Group::Compiler(group) => DelimSpanEnum::Compiler { join: group.span(), open: group.span_open(), close: group.span_close(), }, imp::Group::Fallback(group) => DelimSpanEnum::Fallback(group.span()), }; #[cfg(not(wrap_proc_macro))] let inner = DelimSpanEnum::Fallback(group.span()); DelimSpan { inner, _marker: MARKER, } } /// Returns a span covering the entire delimited group. pub fn join(&self) -> Span { match &self.inner { #[cfg(wrap_proc_macro)] DelimSpanEnum::Compiler { join, .. } => Span::_new(imp::Span::Compiler(*join)), DelimSpanEnum::Fallback(span) => Span::_new_fallback(*span), } } /// Returns a span for the opening punctuation of the group only. pub fn open(&self) -> Span { match &self.inner { #[cfg(wrap_proc_macro)] DelimSpanEnum::Compiler { open, .. } => Span::_new(imp::Span::Compiler(*open)), DelimSpanEnum::Fallback(span) => Span::_new_fallback(span.first_byte()), } } /// Returns a span for the closing punctuation of the group only. pub fn close(&self) -> Span { match &self.inner { #[cfg(wrap_proc_macro)] DelimSpanEnum::Compiler { close, .. } => Span::_new(imp::Span::Compiler(*close)), DelimSpanEnum::Fallback(span) => Span::_new_fallback(span.last_byte()), } } } impl Debug for DelimSpan { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.join(), f) } } proc-macro2/src/fallback.rs0000644000175000017500000010271315105742312015426 0ustar bdrungbdrung#[cfg(wrap_proc_macro)] use crate::imp; #[cfg(span_locations)] use crate::location::LineColumn; use crate::parse::{self, Cursor}; use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut}; use crate::{Delimiter, Spacing, TokenTree}; #[cfg(all(span_locations, not(fuzzing)))] use alloc::collections::BTreeMap; #[cfg(all(span_locations, not(fuzzing)))] use core::cell::RefCell; #[cfg(span_locations)] use core::cmp; use core::fmt::{self, Debug, Display, Write}; use core::mem::ManuallyDrop; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; use core::ptr; use core::str; #[cfg(feature = "proc-macro")] use core::str::FromStr; use std::ffi::CStr; #[cfg(wrap_proc_macro)] use std::panic; #[cfg(procmacro2_semver_exempt)] use std::path::PathBuf; /// Force use of proc-macro2's fallback implementation of the API for now, even /// if the compiler's implementation is available. pub fn force() { #[cfg(wrap_proc_macro)] crate::detection::force_fallback(); } /// Resume using the compiler's implementation of the proc macro API if it is /// available. pub fn unforce() { #[cfg(wrap_proc_macro)] crate::detection::unforce_fallback(); } #[derive(Clone)] pub(crate) struct TokenStream { inner: RcVec, } #[derive(Debug)] pub(crate) struct LexError { pub(crate) span: Span, } impl LexError { pub(crate) fn span(&self) -> Span { self.span } pub(crate) fn call_site() -> Self { LexError { span: Span::call_site(), } } } impl TokenStream { pub(crate) fn new() -> Self { TokenStream { inner: RcVecBuilder::new().build(), } } pub(crate) fn from_str_checked(src: &str) -> Result { // Create a dummy file & add it to the source map let mut cursor = get_cursor(src); // Strip a byte order mark if present const BYTE_ORDER_MARK: &str = "\u{feff}"; if cursor.starts_with(BYTE_ORDER_MARK) { cursor = cursor.advance(BYTE_ORDER_MARK.len()); } parse::token_stream(cursor) } #[cfg(feature = "proc-macro")] pub(crate) fn from_str_unchecked(src: &str) -> Self { Self::from_str_checked(src).unwrap() } pub(crate) fn is_empty(&self) -> bool { self.inner.len() == 0 } fn take_inner(self) -> RcVecBuilder { let nodrop = ManuallyDrop::new(self); unsafe { ptr::read(&nodrop.inner) }.make_owned() } } fn push_token_from_proc_macro(mut vec: RcVecMut, token: TokenTree) { // https://github.com/dtolnay/proc-macro2/issues/235 match token { TokenTree::Literal(crate::Literal { #[cfg(wrap_proc_macro)] inner: crate::imp::Literal::Fallback(literal), #[cfg(not(wrap_proc_macro))] inner: literal, .. }) if literal.repr.starts_with('-') => { push_negative_literal(vec, literal); } _ => vec.push(token), } #[cold] fn push_negative_literal(mut vec: RcVecMut, mut literal: Literal) { literal.repr.remove(0); let mut punct = crate::Punct::new('-', Spacing::Alone); punct.set_span(crate::Span::_new_fallback(literal.span)); vec.push(TokenTree::Punct(punct)); vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal))); } } // Nonrecursive to prevent stack overflow. impl Drop for TokenStream { fn drop(&mut self) { let mut stack = Vec::new(); let mut current = match self.inner.get_mut() { Some(inner) => inner.take().into_iter(), None => return, }; loop { while let Some(token) = current.next() { let group = match token { TokenTree::Group(group) => group.inner, _ => continue, }; #[cfg(wrap_proc_macro)] let group = match group { crate::imp::Group::Fallback(group) => group, crate::imp::Group::Compiler(_) => continue, }; let mut group = group; if let Some(inner) = group.stream.inner.get_mut() { stack.push(current); current = inner.take().into_iter(); } } match stack.pop() { Some(next) => current = next, None => return, } } } } pub(crate) struct TokenStreamBuilder { inner: RcVecBuilder, } impl TokenStreamBuilder { pub(crate) fn new() -> Self { TokenStreamBuilder { inner: RcVecBuilder::new(), } } pub(crate) fn with_capacity(cap: usize) -> Self { TokenStreamBuilder { inner: RcVecBuilder::with_capacity(cap), } } pub(crate) fn push_token_from_parser(&mut self, tt: TokenTree) { self.inner.push(tt); } pub(crate) fn build(self) -> TokenStream { TokenStream { inner: self.inner.build(), } } } #[cfg(span_locations)] fn get_cursor(src: &str) -> Cursor { #[cfg(fuzzing)] return Cursor { rest: src, off: 1 }; // Create a dummy file & add it to the source map #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let mut sm = sm.borrow_mut(); let span = sm.add_file(src); Cursor { rest: src, off: span.lo, } }) } #[cfg(not(span_locations))] fn get_cursor(src: &str) -> Cursor { Cursor { rest: src } } impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("cannot parse string into token stream") } } impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut joint = false; for (i, tt) in self.inner.iter().enumerate() { if i != 0 && !joint { write!(f, " ")?; } joint = false; match tt { TokenTree::Group(tt) => Display::fmt(tt, f), TokenTree::Ident(tt) => Display::fmt(tt, f), TokenTree::Punct(tt) => { joint = tt.spacing() == Spacing::Joint; Display::fmt(tt, f) } TokenTree::Literal(tt) => Display::fmt(tt, f), }?; } Ok(()) } } impl Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("TokenStream ")?; f.debug_list().entries(self.clone()).finish() } } #[cfg(feature = "proc-macro")] impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { TokenStream::from_str_unchecked(&inner.to_string()) } } #[cfg(feature = "proc-macro")] impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { proc_macro::TokenStream::from_str_unchecked(&inner.to_string()) } } impl From for TokenStream { fn from(tree: TokenTree) -> Self { let mut stream = RcVecBuilder::new(); push_token_from_proc_macro(stream.as_mut(), tree); TokenStream { inner: stream.build(), } } } impl FromIterator for TokenStream { fn from_iter>(tokens: I) -> Self { let mut stream = TokenStream::new(); stream.extend(tokens); stream } } impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { let mut v = RcVecBuilder::new(); for stream in streams { v.extend(stream.take_inner()); } TokenStream { inner: v.build() } } } impl Extend for TokenStream { fn extend>(&mut self, tokens: I) { let mut vec = self.inner.make_mut(); tokens .into_iter() .for_each(|token| push_token_from_proc_macro(vec.as_mut(), token)); } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { self.inner.make_mut().extend(streams.into_iter().flatten()); } } pub(crate) type TokenTreeIter = RcVecIntoIter; impl IntoIterator for TokenStream { type Item = TokenTree; type IntoIter = TokenTreeIter; fn into_iter(self) -> TokenTreeIter { self.take_inner().into_iter() } } #[cfg(all(span_locations, not(fuzzing)))] thread_local! { static SOURCE_MAP: RefCell = RefCell::new(SourceMap { // Start with a single dummy file which all call_site() and def_site() // spans reference. files: vec![FileInfo { source_text: String::new(), span: Span { lo: 0, hi: 0 }, lines: vec![0], char_index_to_byte_offset: BTreeMap::new(), }], }); } #[cfg(span_locations)] pub(crate) fn invalidate_current_thread_spans() { #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| sm.borrow_mut().files.truncate(1)); } #[cfg(all(span_locations, not(fuzzing)))] struct FileInfo { source_text: String, span: Span, lines: Vec, char_index_to_byte_offset: BTreeMap, } #[cfg(all(span_locations, not(fuzzing)))] impl FileInfo { fn offset_line_column(&self, offset: usize) -> LineColumn { assert!(self.span_within(Span { lo: offset as u32, hi: offset as u32, })); let offset = offset - self.span.lo as usize; match self.lines.binary_search(&offset) { Ok(found) => LineColumn { line: found + 1, column: 0, }, Err(idx) => LineColumn { line: idx, column: offset - self.lines[idx - 1], }, } } fn span_within(&self, span: Span) -> bool { span.lo >= self.span.lo && span.hi <= self.span.hi } fn byte_range(&mut self, span: Span) -> Range { let lo_char = (span.lo - self.span.lo) as usize; // Look up offset of the largest already-computed char index that is // less than or equal to the current requested one. We resume counting // chars from that point. let (&last_char_index, &last_byte_offset) = self .char_index_to_byte_offset .range(..=lo_char) .next_back() .unwrap_or((&0, &0)); let lo_byte = if last_char_index == lo_char { last_byte_offset } else { let total_byte_offset = match self.source_text[last_byte_offset..] .char_indices() .nth(lo_char - last_char_index) { Some((additional_offset, _ch)) => last_byte_offset + additional_offset, None => self.source_text.len(), }; self.char_index_to_byte_offset .insert(lo_char, total_byte_offset); total_byte_offset }; let trunc_lo = &self.source_text[lo_byte..]; let char_len = (span.hi - span.lo) as usize; lo_byte..match trunc_lo.char_indices().nth(char_len) { Some((offset, _ch)) => lo_byte + offset, None => self.source_text.len(), } } fn source_text(&mut self, span: Span) -> String { let byte_range = self.byte_range(span); self.source_text[byte_range].to_owned() } } /// Computes the offsets of each line in the given source string /// and the total number of characters #[cfg(all(span_locations, not(fuzzing)))] fn lines_offsets(s: &str) -> (usize, Vec) { let mut lines = vec![0]; let mut total = 0; for ch in s.chars() { total += 1; if ch == '\n' { lines.push(total); } } (total, lines) } #[cfg(all(span_locations, not(fuzzing)))] struct SourceMap { files: Vec, } #[cfg(all(span_locations, not(fuzzing)))] impl SourceMap { fn next_start_pos(&self) -> u32 { // Add 1 so there's always space between files. // // We'll always have at least 1 file, as we initialize our files list // with a dummy file. self.files.last().unwrap().span.hi + 1 } fn add_file(&mut self, src: &str) -> Span { let (len, lines) = lines_offsets(src); let lo = self.next_start_pos(); let span = Span { lo, hi: lo + (len as u32), }; self.files.push(FileInfo { source_text: src.to_owned(), span, lines, // Populated lazily by source_text(). char_index_to_byte_offset: BTreeMap::new(), }); span } #[cfg(procmacro2_semver_exempt)] fn filepath(&self, span: Span) -> String { for (i, file) in self.files.iter().enumerate() { if file.span_within(span) { return if i == 0 { "".to_owned() } else { format!("", i) }; } } unreachable!("Invalid span with no related FileInfo!"); } fn fileinfo(&self, span: Span) -> &FileInfo { for file in &self.files { if file.span_within(span) { return file; } } unreachable!("Invalid span with no related FileInfo!"); } fn fileinfo_mut(&mut self, span: Span) -> &mut FileInfo { for file in &mut self.files { if file.span_within(span) { return file; } } unreachable!("Invalid span with no related FileInfo!"); } } #[derive(Clone, Copy, PartialEq, Eq)] pub(crate) struct Span { #[cfg(span_locations)] pub(crate) lo: u32, #[cfg(span_locations)] pub(crate) hi: u32, } impl Span { #[cfg(not(span_locations))] pub(crate) fn call_site() -> Self { Span {} } #[cfg(span_locations)] pub(crate) fn call_site() -> Self { Span { lo: 0, hi: 0 } } pub(crate) fn mixed_site() -> Self { Span::call_site() } #[cfg(procmacro2_semver_exempt)] pub(crate) fn def_site() -> Self { Span::call_site() } pub(crate) fn resolved_at(&self, _other: Span) -> Span { // Stable spans consist only of line/column information, so // `resolved_at` and `located_at` only select which span the // caller wants line/column information from. *self } pub(crate) fn located_at(&self, other: Span) -> Span { other } #[cfg(span_locations)] pub(crate) fn byte_range(&self) -> Range { #[cfg(fuzzing)] return 0..0; #[cfg(not(fuzzing))] { if self.is_call_site() { 0..0 } else { SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).byte_range(*self)) } } } #[cfg(span_locations)] pub(crate) fn start(&self) -> LineColumn { #[cfg(fuzzing)] return LineColumn { line: 0, column: 0 }; #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let sm = sm.borrow(); let fi = sm.fileinfo(*self); fi.offset_line_column(self.lo as usize) }) } #[cfg(span_locations)] pub(crate) fn end(&self) -> LineColumn { #[cfg(fuzzing)] return LineColumn { line: 0, column: 0 }; #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let sm = sm.borrow(); let fi = sm.fileinfo(*self); fi.offset_line_column(self.hi as usize) }) } #[cfg(procmacro2_semver_exempt)] pub(crate) fn file(&self) -> String { #[cfg(fuzzing)] return "".to_owned(); #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let sm = sm.borrow(); sm.filepath(*self) }) } #[cfg(procmacro2_semver_exempt)] pub(crate) fn local_file(&self) -> Option { None } #[cfg(not(span_locations))] pub(crate) fn join(&self, _other: Span) -> Option { Some(Span {}) } #[cfg(span_locations)] pub(crate) fn join(&self, other: Span) -> Option { #[cfg(fuzzing)] return { let _ = other; None }; #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let sm = sm.borrow(); // If `other` is not within the same FileInfo as us, return None. if !sm.fileinfo(*self).span_within(other) { return None; } Some(Span { lo: cmp::min(self.lo, other.lo), hi: cmp::max(self.hi, other.hi), }) }) } #[cfg(not(span_locations))] pub(crate) fn source_text(&self) -> Option { None } #[cfg(span_locations)] pub(crate) fn source_text(&self) -> Option { #[cfg(fuzzing)] return None; #[cfg(not(fuzzing))] { if self.is_call_site() { None } else { Some(SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).source_text(*self))) } } } #[cfg(not(span_locations))] pub(crate) fn first_byte(self) -> Self { self } #[cfg(span_locations)] pub(crate) fn first_byte(self) -> Self { Span { lo: self.lo, hi: cmp::min(self.lo.saturating_add(1), self.hi), } } #[cfg(not(span_locations))] pub(crate) fn last_byte(self) -> Self { self } #[cfg(span_locations)] pub(crate) fn last_byte(self) -> Self { Span { lo: cmp::max(self.hi.saturating_sub(1), self.lo), hi: self.hi, } } #[cfg(span_locations)] fn is_call_site(&self) -> bool { self.lo == 0 && self.hi == 0 } } impl Debug for Span { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[cfg(span_locations)] return write!(f, "bytes({}..{})", self.lo, self.hi); #[cfg(not(span_locations))] write!(f, "Span") } } pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { #[cfg(span_locations)] { if span.is_call_site() { return; } } if cfg!(span_locations) { debug.field("span", &span); } } #[derive(Clone)] pub(crate) struct Group { delimiter: Delimiter, stream: TokenStream, span: Span, } impl Group { pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self { Group { delimiter, stream, span: Span::call_site(), } } pub(crate) fn delimiter(&self) -> Delimiter { self.delimiter } pub(crate) fn stream(&self) -> TokenStream { self.stream.clone() } pub(crate) fn span(&self) -> Span { self.span } pub(crate) fn span_open(&self) -> Span { self.span.first_byte() } pub(crate) fn span_close(&self) -> Span { self.span.last_byte() } pub(crate) fn set_span(&mut self, span: Span) { self.span = span; } } impl Display for Group { // We attempt to match libproc_macro's formatting. // Empty parens: () // Nonempty parens: (...) // Empty brackets: [] // Nonempty brackets: [...] // Empty braces: { } // Nonempty braces: { ... } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (open, close) = match self.delimiter { Delimiter::Parenthesis => ("(", ")"), Delimiter::Brace => ("{ ", "}"), Delimiter::Bracket => ("[", "]"), Delimiter::None => ("", ""), }; f.write_str(open)?; Display::fmt(&self.stream, f)?; if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() { f.write_str(" ")?; } f.write_str(close)?; Ok(()) } } impl Debug for Group { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut debug = fmt.debug_struct("Group"); debug.field("delimiter", &self.delimiter); debug.field("stream", &self.stream); debug_span_field_if_nontrivial(&mut debug, self.span); debug.finish() } } #[derive(Clone)] pub(crate) struct Ident { sym: Box, span: Span, raw: bool, } impl Ident { #[track_caller] pub(crate) fn new_checked(string: &str, span: Span) -> Self { validate_ident(string); Ident::new_unchecked(string, span) } pub(crate) fn new_unchecked(string: &str, span: Span) -> Self { Ident { sym: Box::from(string), span, raw: false, } } #[track_caller] pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self { validate_ident_raw(string); Ident::new_raw_unchecked(string, span) } pub(crate) fn new_raw_unchecked(string: &str, span: Span) -> Self { Ident { sym: Box::from(string), span, raw: true, } } pub(crate) fn span(&self) -> Span { self.span } pub(crate) fn set_span(&mut self, span: Span) { self.span = span; } } pub(crate) fn is_ident_start(c: char) -> bool { c == '_' || unicode_ident::is_xid_start(c) } pub(crate) fn is_ident_continue(c: char) -> bool { unicode_ident::is_xid_continue(c) } #[track_caller] fn validate_ident(string: &str) { if string.is_empty() { panic!("Ident is not allowed to be empty; use Option"); } if string.bytes().all(|digit| b'0' <= digit && digit <= b'9') { panic!("Ident cannot be a number; use Literal instead"); } fn ident_ok(string: &str) -> bool { let mut chars = string.chars(); let first = chars.next().unwrap(); if !is_ident_start(first) { return false; } for ch in chars { if !is_ident_continue(ch) { return false; } } true } if !ident_ok(string) { panic!("{:?} is not a valid Ident", string); } } #[track_caller] fn validate_ident_raw(string: &str) { validate_ident(string); match string { "_" | "super" | "self" | "Self" | "crate" => { panic!("`r#{}` cannot be a raw identifier", string); } _ => {} } } impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { self.sym == other.sym && self.raw == other.raw } } impl PartialEq for Ident where T: ?Sized + AsRef, { fn eq(&self, other: &T) -> bool { let other = other.as_ref(); if self.raw { other.starts_with("r#") && *self.sym == other[2..] } else { *self.sym == *other } } } impl Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.raw { f.write_str("r#")?; } Display::fmt(&self.sym, f) } } #[allow(clippy::missing_fields_in_debug)] impl Debug for Ident { // Ident(proc_macro), Ident(r#union) #[cfg(not(span_locations))] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_tuple("Ident"); debug.field(&format_args!("{}", self)); debug.finish() } // Ident { // sym: proc_macro, // span: bytes(128..138) // } #[cfg(span_locations)] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Ident"); debug.field("sym", &format_args!("{}", self)); debug_span_field_if_nontrivial(&mut debug, self.span); debug.finish() } } #[derive(Clone)] pub(crate) struct Literal { pub(crate) repr: String, span: Span, } macro_rules! suffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( pub(crate) fn $name(n: $kind) -> Literal { Literal::_new(format!(concat!("{}", stringify!($kind)), n)) } )*) } macro_rules! unsuffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( pub(crate) fn $name(n: $kind) -> Literal { Literal::_new(n.to_string()) } )*) } impl Literal { pub(crate) fn _new(repr: String) -> Self { Literal { repr, span: Span::call_site(), } } pub(crate) fn from_str_checked(repr: &str) -> Result { let mut cursor = get_cursor(repr); #[cfg(span_locations)] let lo = cursor.off; let negative = cursor.starts_with_char('-'); if negative { cursor = cursor.advance(1); if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) { return Err(LexError::call_site()); } } if let Ok((rest, mut literal)) = parse::literal(cursor) { if rest.is_empty() { if negative { literal.repr.insert(0, '-'); } literal.span = Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: rest.off, }; return Ok(literal); } } Err(LexError::call_site()) } pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self { Literal::_new(repr.to_owned()) } suffixed_numbers! { u8_suffixed => u8, u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, i128_suffixed => i128, isize_suffixed => isize, f32_suffixed => f32, f64_suffixed => f64, } unsuffixed_numbers! { u8_unsuffixed => u8, u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, i128_unsuffixed => i128, isize_unsuffixed => isize, } pub(crate) fn f32_unsuffixed(f: f32) -> Literal { let mut s = f.to_string(); if !s.contains('.') { s.push_str(".0"); } Literal::_new(s) } pub(crate) fn f64_unsuffixed(f: f64) -> Literal { let mut s = f.to_string(); if !s.contains('.') { s.push_str(".0"); } Literal::_new(s) } pub(crate) fn string(string: &str) -> Literal { let mut repr = String::with_capacity(string.len() + 2); repr.push('"'); escape_utf8(string, &mut repr); repr.push('"'); Literal::_new(repr) } pub(crate) fn character(ch: char) -> Literal { let mut repr = String::new(); repr.push('\''); if ch == '"' { // escape_debug turns this into '\"' which is unnecessary. repr.push(ch); } else { repr.extend(ch.escape_debug()); } repr.push('\''); Literal::_new(repr) } pub(crate) fn byte_character(byte: u8) -> Literal { let mut repr = "b'".to_string(); #[allow(clippy::match_overlapping_arm)] match byte { b'\0' => repr.push_str(r"\0"), b'\t' => repr.push_str(r"\t"), b'\n' => repr.push_str(r"\n"), b'\r' => repr.push_str(r"\r"), b'\'' => repr.push_str(r"\'"), b'\\' => repr.push_str(r"\\"), b'\x20'..=b'\x7E' => repr.push(byte as char), _ => { let _ = write!(repr, r"\x{:02X}", byte); } } repr.push('\''); Literal::_new(repr) } pub(crate) fn byte_string(bytes: &[u8]) -> Literal { let mut repr = "b\"".to_string(); let mut bytes = bytes.iter(); while let Some(&b) = bytes.next() { #[allow(clippy::match_overlapping_arm)] match b { b'\0' => repr.push_str(match bytes.as_slice().first() { // circumvent clippy::octal_escapes lint Some(b'0'..=b'7') => r"\x00", _ => r"\0", }), b'\t' => repr.push_str(r"\t"), b'\n' => repr.push_str(r"\n"), b'\r' => repr.push_str(r"\r"), b'"' => repr.push_str("\\\""), b'\\' => repr.push_str(r"\\"), b'\x20'..=b'\x7E' => repr.push(b as char), _ => { let _ = write!(repr, r"\x{:02X}", b); } } } repr.push('"'); Literal::_new(repr) } pub(crate) fn c_string(string: &CStr) -> Literal { let mut repr = "c\"".to_string(); let mut bytes = string.to_bytes(); while !bytes.is_empty() { let (valid, invalid) = match str::from_utf8(bytes) { Ok(all_valid) => { bytes = b""; (all_valid, bytes) } Err(utf8_error) => { let (valid, rest) = bytes.split_at(utf8_error.valid_up_to()); let valid = str::from_utf8(valid).unwrap(); let invalid = utf8_error .error_len() .map_or(rest, |error_len| &rest[..error_len]); bytes = &bytes[valid.len() + invalid.len()..]; (valid, invalid) } }; escape_utf8(valid, &mut repr); for &byte in invalid { let _ = write!(repr, r"\x{:02X}", byte); } } repr.push('"'); Literal::_new(repr) } pub(crate) fn span(&self) -> Span { self.span } pub(crate) fn set_span(&mut self, span: Span) { self.span = span; } pub(crate) fn subspan>(&self, range: R) -> Option { #[cfg(not(span_locations))] { let _ = range; None } #[cfg(span_locations)] { use core::ops::Bound; let lo = match range.start_bound() { Bound::Included(start) => { let start = u32::try_from(*start).ok()?; self.span.lo.checked_add(start)? } Bound::Excluded(start) => { let start = u32::try_from(*start).ok()?; self.span.lo.checked_add(start)?.checked_add(1)? } Bound::Unbounded => self.span.lo, }; let hi = match range.end_bound() { Bound::Included(end) => { let end = u32::try_from(*end).ok()?; self.span.lo.checked_add(end)?.checked_add(1)? } Bound::Excluded(end) => { let end = u32::try_from(*end).ok()?; self.span.lo.checked_add(end)? } Bound::Unbounded => self.span.hi, }; if lo <= hi && hi <= self.span.hi { Some(Span { lo, hi }) } else { None } } } } impl Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.repr, f) } } impl Debug for Literal { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut debug = fmt.debug_struct("Literal"); debug.field("lit", &format_args!("{}", self.repr)); debug_span_field_if_nontrivial(&mut debug, self.span); debug.finish() } } fn escape_utf8(string: &str, repr: &mut String) { let mut chars = string.chars(); while let Some(ch) = chars.next() { if ch == '\0' { repr.push_str( if chars .as_str() .starts_with(|next| '0' <= next && next <= '7') { // circumvent clippy::octal_escapes lint r"\x00" } else { r"\0" }, ); } else if ch == '\'' { // escape_debug turns this into "\'" which is unnecessary. repr.push(ch); } else { repr.extend(ch.escape_debug()); } } } #[cfg(feature = "proc-macro")] pub(crate) trait FromStr2: FromStr { #[cfg(wrap_proc_macro)] fn valid(src: &str) -> bool; #[cfg(wrap_proc_macro)] fn from_str_checked(src: &str) -> Result { // Validate using fallback parser, because rustc is incapable of // returning a recoverable Err for certain invalid token streams, and // will instead permanently poison the compilation. if !Self::valid(src) { return Err(imp::LexError::CompilerPanic); } // Catch panic to work around https://github.com/rust-lang/rust/issues/58736. match panic::catch_unwind(|| Self::from_str(src)) { Ok(Ok(ok)) => Ok(ok), Ok(Err(lex)) => Err(imp::LexError::Compiler(lex)), Err(_panic) => Err(imp::LexError::CompilerPanic), } } fn from_str_unchecked(src: &str) -> Self { Self::from_str(src).unwrap() } } #[cfg(feature = "proc-macro")] impl FromStr2 for proc_macro::TokenStream { #[cfg(wrap_proc_macro)] fn valid(src: &str) -> bool { TokenStream::from_str_checked(src).is_ok() } } #[cfg(feature = "proc-macro")] impl FromStr2 for proc_macro::Literal { #[cfg(wrap_proc_macro)] fn valid(src: &str) -> bool { Literal::from_str_checked(src).is_ok() } } proc-macro2/src/marker.rs0000644000175000017500000000107515105742312015147 0ustar bdrungbdrunguse alloc::rc::Rc; use core::marker::PhantomData; use core::panic::{RefUnwindSafe, UnwindSafe}; // Zero sized marker with the correct set of autotrait impls we want all proc // macro types to have. #[derive(Copy, Clone)] #[cfg_attr( all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)), derive(PartialEq, Eq) )] pub(crate) struct ProcMacroAutoTraits(PhantomData>); pub(crate) const MARKER: ProcMacroAutoTraits = ProcMacroAutoTraits(PhantomData); impl UnwindSafe for ProcMacroAutoTraits {} impl RefUnwindSafe for ProcMacroAutoTraits {} proc-macro2/src/location.rs0000644000175000017500000000154715105742312015502 0ustar bdrungbdrunguse core::cmp::Ordering; /// A line-column pair representing the start or end of a `Span`. /// /// This type is semver exempt and not exposed by default. #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct LineColumn { /// The 1-indexed line in the source file on which the span starts or ends /// (inclusive). pub line: usize, /// The 0-indexed column (in UTF-8 characters) in the source file on which /// the span starts or ends (inclusive). pub column: usize, } impl Ord for LineColumn { fn cmp(&self, other: &Self) -> Ordering { self.line .cmp(&other.line) .then(self.column.cmp(&other.column)) } } impl PartialOrd for LineColumn { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } proc-macro2/src/wrapper.rs0000644000175000017500000007310715105742312015353 0ustar bdrungbdrunguse crate::detection::inside_proc_macro; use crate::fallback::{self, FromStr2 as _}; #[cfg(span_locations)] use crate::location::LineColumn; use crate::{Delimiter, Punct, Spacing, TokenTree}; use core::fmt::{self, Debug, Display}; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; use std::ffi::CStr; #[cfg(super_unstable)] use std::path::PathBuf; #[derive(Clone)] pub(crate) enum TokenStream { Compiler(DeferredTokenStream), Fallback(fallback::TokenStream), } // Work around https://github.com/rust-lang/rust/issues/65080. // In `impl Extend for TokenStream` which is used heavily by quote, // we hold on to the appended tokens and do proc_macro::TokenStream::extend as // late as possible to batch together consecutive uses of the Extend impl. #[derive(Clone)] pub(crate) struct DeferredTokenStream { stream: proc_macro::TokenStream, extra: Vec, } pub(crate) enum LexError { Compiler(proc_macro::LexError), Fallback(fallback::LexError), // Rustc was supposed to return a LexError, but it panicked instead. // https://github.com/rust-lang/rust/issues/58736 CompilerPanic, } #[cold] fn mismatch(line: u32) -> ! { #[cfg(procmacro2_backtrace)] { let backtrace = std::backtrace::Backtrace::force_capture(); panic!("compiler/fallback mismatch L{}\n\n{}", line, backtrace) } #[cfg(not(procmacro2_backtrace))] { panic!("compiler/fallback mismatch L{}", line) } } impl DeferredTokenStream { fn new(stream: proc_macro::TokenStream) -> Self { DeferredTokenStream { stream, extra: Vec::new(), } } fn is_empty(&self) -> bool { self.stream.is_empty() && self.extra.is_empty() } fn evaluate_now(&mut self) { // If-check provides a fast short circuit for the common case of `extra` // being empty, which saves a round trip over the proc macro bridge. // Improves macro expansion time in winrt by 6% in debug mode. if !self.extra.is_empty() { self.stream.extend(self.extra.drain(..)); } } fn into_token_stream(mut self) -> proc_macro::TokenStream { self.evaluate_now(); self.stream } } impl TokenStream { pub(crate) fn new() -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) } else { TokenStream::Fallback(fallback::TokenStream::new()) } } pub(crate) fn from_str_checked(src: &str) -> Result { if inside_proc_macro() { Ok(TokenStream::Compiler(DeferredTokenStream::new( proc_macro::TokenStream::from_str_checked(src)?, ))) } else { Ok(TokenStream::Fallback( fallback::TokenStream::from_str_checked(src)?, )) } } pub(crate) fn is_empty(&self) -> bool { match self { TokenStream::Compiler(tts) => tts.is_empty(), TokenStream::Fallback(tts) => tts.is_empty(), } } fn unwrap_nightly(self) -> proc_macro::TokenStream { match self { TokenStream::Compiler(s) => s.into_token_stream(), TokenStream::Fallback(_) => mismatch(line!()), } } fn unwrap_stable(self) -> fallback::TokenStream { match self { TokenStream::Compiler(_) => mismatch(line!()), TokenStream::Fallback(s) => s, } } } impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f), TokenStream::Fallback(tts) => Display::fmt(tts, f), } } } impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { TokenStream::Compiler(DeferredTokenStream::new(inner)) } } impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { match inner { TokenStream::Compiler(inner) => inner.into_token_stream(), TokenStream::Fallback(inner) => { proc_macro::TokenStream::from_str_unchecked(&inner.to_string()) } } } } impl From for TokenStream { fn from(inner: fallback::TokenStream) -> Self { TokenStream::Fallback(inner) } } // Assumes inside_proc_macro(). fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { match token { TokenTree::Group(tt) => proc_macro::TokenTree::Group(tt.inner.unwrap_nightly()), TokenTree::Punct(tt) => { let spacing = match tt.spacing() { Spacing::Joint => proc_macro::Spacing::Joint, Spacing::Alone => proc_macro::Spacing::Alone, }; let mut punct = proc_macro::Punct::new(tt.as_char(), spacing); punct.set_span(tt.span().inner.unwrap_nightly()); proc_macro::TokenTree::Punct(punct) } TokenTree::Ident(tt) => proc_macro::TokenTree::Ident(tt.inner.unwrap_nightly()), TokenTree::Literal(tt) => proc_macro::TokenTree::Literal(tt.inner.unwrap_nightly()), } } impl From for TokenStream { fn from(token: TokenTree) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::from( into_compiler_token(token), ))) } else { TokenStream::Fallback(fallback::TokenStream::from(token)) } } } impl FromIterator for TokenStream { fn from_iter>(trees: I) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new( trees.into_iter().map(into_compiler_token).collect(), )) } else { TokenStream::Fallback(trees.into_iter().collect()) } } } impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { let mut streams = streams.into_iter(); match streams.next() { Some(TokenStream::Compiler(mut first)) => { first.evaluate_now(); first.stream.extend(streams.map(|s| match s { TokenStream::Compiler(s) => s.into_token_stream(), TokenStream::Fallback(_) => mismatch(line!()), })); TokenStream::Compiler(first) } Some(TokenStream::Fallback(mut first)) => { first.extend(streams.map(|s| match s { TokenStream::Fallback(s) => s, TokenStream::Compiler(_) => mismatch(line!()), })); TokenStream::Fallback(first) } None => TokenStream::new(), } } } impl Extend for TokenStream { fn extend>(&mut self, stream: I) { match self { TokenStream::Compiler(tts) => { // Here is the reason for DeferredTokenStream. for token in stream { tts.extra.push(into_compiler_token(token)); } } TokenStream::Fallback(tts) => tts.extend(stream), } } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { match self { TokenStream::Compiler(tts) => { tts.evaluate_now(); tts.stream .extend(streams.into_iter().map(TokenStream::unwrap_nightly)); } TokenStream::Fallback(tts) => { tts.extend(streams.into_iter().map(TokenStream::unwrap_stable)); } } } } impl Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f), TokenStream::Fallback(tts) => Debug::fmt(tts, f), } } } impl LexError { pub(crate) fn span(&self) -> Span { match self { LexError::Compiler(_) | LexError::CompilerPanic => Span::call_site(), LexError::Fallback(e) => Span::Fallback(e.span()), } } } impl From for LexError { fn from(e: proc_macro::LexError) -> Self { LexError::Compiler(e) } } impl From for LexError { fn from(e: fallback::LexError) -> Self { LexError::Fallback(e) } } impl Debug for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { LexError::Compiler(e) => Debug::fmt(e, f), LexError::Fallback(e) => Debug::fmt(e, f), LexError::CompilerPanic => { let fallback = fallback::LexError::call_site(); Debug::fmt(&fallback, f) } } } } impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { LexError::Compiler(e) => Display::fmt(e, f), LexError::Fallback(e) => Display::fmt(e, f), LexError::CompilerPanic => { let fallback = fallback::LexError::call_site(); Display::fmt(&fallback, f) } } } } #[derive(Clone)] pub(crate) enum TokenTreeIter { Compiler(proc_macro::token_stream::IntoIter), Fallback(fallback::TokenTreeIter), } impl IntoIterator for TokenStream { type Item = TokenTree; type IntoIter = TokenTreeIter; fn into_iter(self) -> TokenTreeIter { match self { TokenStream::Compiler(tts) => { TokenTreeIter::Compiler(tts.into_token_stream().into_iter()) } TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()), } } } impl Iterator for TokenTreeIter { type Item = TokenTree; fn next(&mut self) -> Option { let token = match self { TokenTreeIter::Compiler(iter) => iter.next()?, TokenTreeIter::Fallback(iter) => return iter.next(), }; Some(match token { proc_macro::TokenTree::Group(tt) => { TokenTree::Group(crate::Group::_new(Group::Compiler(tt))) } proc_macro::TokenTree::Punct(tt) => { let spacing = match tt.spacing() { proc_macro::Spacing::Joint => Spacing::Joint, proc_macro::Spacing::Alone => Spacing::Alone, }; let mut o = Punct::new(tt.as_char(), spacing); o.set_span(crate::Span::_new(Span::Compiler(tt.span()))); TokenTree::Punct(o) } proc_macro::TokenTree::Ident(s) => { TokenTree::Ident(crate::Ident::_new(Ident::Compiler(s))) } proc_macro::TokenTree::Literal(l) => { TokenTree::Literal(crate::Literal::_new(Literal::Compiler(l))) } }) } fn size_hint(&self) -> (usize, Option) { match self { TokenTreeIter::Compiler(tts) => tts.size_hint(), TokenTreeIter::Fallback(tts) => tts.size_hint(), } } } #[derive(Copy, Clone)] pub(crate) enum Span { Compiler(proc_macro::Span), Fallback(fallback::Span), } impl Span { pub(crate) fn call_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::call_site()) } else { Span::Fallback(fallback::Span::call_site()) } } pub(crate) fn mixed_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::mixed_site()) } else { Span::Fallback(fallback::Span::mixed_site()) } } #[cfg(super_unstable)] pub(crate) fn def_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::def_site()) } else { Span::Fallback(fallback::Span::def_site()) } } pub(crate) fn resolved_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub(crate) fn located_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub(crate) fn unwrap(self) -> proc_macro::Span { match self { Span::Compiler(s) => s, Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"), } } #[cfg(span_locations)] pub(crate) fn byte_range(&self) -> Range { match self { #[cfg(proc_macro_span)] Span::Compiler(s) => s.byte_range(), #[cfg(not(proc_macro_span))] Span::Compiler(_) => 0..0, Span::Fallback(s) => s.byte_range(), } } #[cfg(span_locations)] pub(crate) fn start(&self) -> LineColumn { match self { #[cfg(proc_macro_span)] Span::Compiler(s) => LineColumn { line: s.line(), column: s.column().saturating_sub(1), }, #[cfg(not(proc_macro_span))] Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.start(), } } #[cfg(span_locations)] pub(crate) fn end(&self) -> LineColumn { match self { #[cfg(proc_macro_span)] Span::Compiler(s) => { let end = s.end(); LineColumn { line: end.line(), column: end.column().saturating_sub(1), } } #[cfg(not(proc_macro_span))] Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.end(), } } #[cfg(super_unstable)] pub(crate) fn file(&self) -> String { match self { Span::Compiler(s) => s.file(), Span::Fallback(s) => s.file(), } } #[cfg(super_unstable)] pub(crate) fn local_file(&self) -> Option { match self { Span::Compiler(s) => s.local_file(), Span::Fallback(s) => s.local_file(), } } pub(crate) fn join(&self, other: Span) -> Option { let ret = match (self, other) { #[cfg(proc_macro_span)] (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), _ => return None, }; Some(ret) } #[cfg(super_unstable)] pub(crate) fn eq(&self, other: &Span) -> bool { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => a.eq(b), (Span::Fallback(a), Span::Fallback(b)) => a.eq(b), _ => false, } } pub(crate) fn source_text(&self) -> Option { match self { #[cfg(not(no_source_text))] Span::Compiler(s) => s.source_text(), #[cfg(no_source_text)] Span::Compiler(_) => None, Span::Fallback(s) => s.source_text(), } } fn unwrap_nightly(self) -> proc_macro::Span { match self { Span::Compiler(s) => s, Span::Fallback(_) => mismatch(line!()), } } } impl From for crate::Span { fn from(proc_span: proc_macro::Span) -> Self { crate::Span::_new(Span::Compiler(proc_span)) } } impl From for Span { fn from(inner: fallback::Span) -> Self { Span::Fallback(inner) } } impl Debug for Span { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Span::Compiler(s) => Debug::fmt(s, f), Span::Fallback(s) => Debug::fmt(s, f), } } } pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { match span { Span::Compiler(s) => { debug.field("span", &s); } Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s), } } #[derive(Clone)] pub(crate) enum Group { Compiler(proc_macro::Group), Fallback(fallback::Group), } impl Group { pub(crate) fn new(delimiter: Delimiter, stream: TokenStream) -> Self { match stream { TokenStream::Compiler(tts) => { let delimiter = match delimiter { Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis, Delimiter::Bracket => proc_macro::Delimiter::Bracket, Delimiter::Brace => proc_macro::Delimiter::Brace, Delimiter::None => proc_macro::Delimiter::None, }; Group::Compiler(proc_macro::Group::new(delimiter, tts.into_token_stream())) } TokenStream::Fallback(stream) => { Group::Fallback(fallback::Group::new(delimiter, stream)) } } } pub(crate) fn delimiter(&self) -> Delimiter { match self { Group::Compiler(g) => match g.delimiter() { proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis, proc_macro::Delimiter::Bracket => Delimiter::Bracket, proc_macro::Delimiter::Brace => Delimiter::Brace, proc_macro::Delimiter::None => Delimiter::None, }, Group::Fallback(g) => g.delimiter(), } } pub(crate) fn stream(&self) -> TokenStream { match self { Group::Compiler(g) => TokenStream::Compiler(DeferredTokenStream::new(g.stream())), Group::Fallback(g) => TokenStream::Fallback(g.stream()), } } pub(crate) fn span(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span()), Group::Fallback(g) => Span::Fallback(g.span()), } } pub(crate) fn span_open(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span_open()), Group::Fallback(g) => Span::Fallback(g.span_open()), } } pub(crate) fn span_close(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span_close()), Group::Fallback(g) => Span::Fallback(g.span_close()), } } pub(crate) fn set_span(&mut self, span: Span) { match (self, span) { (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s), (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s), (Group::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Group::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } fn unwrap_nightly(self) -> proc_macro::Group { match self { Group::Compiler(g) => g, Group::Fallback(_) => mismatch(line!()), } } } impl From for Group { fn from(g: fallback::Group) -> Self { Group::Fallback(g) } } impl Display for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self { Group::Compiler(group) => Display::fmt(group, formatter), Group::Fallback(group) => Display::fmt(group, formatter), } } } impl Debug for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self { Group::Compiler(group) => Debug::fmt(group, formatter), Group::Fallback(group) => Debug::fmt(group, formatter), } } } #[derive(Clone)] pub(crate) enum Ident { Compiler(proc_macro::Ident), Fallback(fallback::Ident), } impl Ident { #[track_caller] pub(crate) fn new_checked(string: &str, span: Span) -> Self { match span { Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)), Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_checked(string, s)), } } #[track_caller] pub(crate) fn new_raw_checked(string: &str, span: Span) -> Self { match span { Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)), Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw_checked(string, s)), } } pub(crate) fn span(&self) -> Span { match self { Ident::Compiler(t) => Span::Compiler(t.span()), Ident::Fallback(t) => Span::Fallback(t.span()), } } pub(crate) fn set_span(&mut self, span: Span) { match (self, span) { (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s), (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s), (Ident::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Ident::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } fn unwrap_nightly(self) -> proc_macro::Ident { match self { Ident::Compiler(s) => s, Ident::Fallback(_) => mismatch(line!()), } } } impl From for Ident { fn from(inner: fallback::Ident) -> Self { Ident::Fallback(inner) } } impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { match (self, other) { (Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(), (Ident::Fallback(t), Ident::Fallback(o)) => t == o, (Ident::Compiler(_), Ident::Fallback(_)) => mismatch(line!()), (Ident::Fallback(_), Ident::Compiler(_)) => mismatch(line!()), } } } impl PartialEq for Ident where T: ?Sized + AsRef, { fn eq(&self, other: &T) -> bool { let other = other.as_ref(); match self { Ident::Compiler(t) => t.to_string() == other, Ident::Fallback(t) => t == other, } } } impl Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Ident::Compiler(t) => Display::fmt(t, f), Ident::Fallback(t) => Display::fmt(t, f), } } } impl Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Ident::Compiler(t) => Debug::fmt(t, f), Ident::Fallback(t) => Debug::fmt(t, f), } } } #[derive(Clone)] pub(crate) enum Literal { Compiler(proc_macro::Literal), Fallback(fallback::Literal), } macro_rules! suffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( pub(crate) fn $name(n: $kind) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::$name(n)) } else { Literal::Fallback(fallback::Literal::$name(n)) } } )*) } macro_rules! unsuffixed_integers { ($($name:ident => $kind:ident,)*) => ($( pub(crate) fn $name(n: $kind) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::$name(n)) } else { Literal::Fallback(fallback::Literal::$name(n)) } } )*) } impl Literal { pub(crate) fn from_str_checked(repr: &str) -> Result { if inside_proc_macro() { let literal = proc_macro::Literal::from_str_checked(repr)?; Ok(Literal::Compiler(literal)) } else { let literal = fallback::Literal::from_str_checked(repr)?; Ok(Literal::Fallback(literal)) } } pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::from_str_unchecked(repr)) } else { Literal::Fallback(unsafe { fallback::Literal::from_str_unchecked(repr) }) } } suffixed_numbers! { u8_suffixed => u8, u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, i128_suffixed => i128, isize_suffixed => isize, f32_suffixed => f32, f64_suffixed => f64, } unsuffixed_integers! { u8_unsuffixed => u8, u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, i128_unsuffixed => i128, isize_unsuffixed => isize, } pub(crate) fn f32_unsuffixed(f: f32) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f)) } else { Literal::Fallback(fallback::Literal::f32_unsuffixed(f)) } } pub(crate) fn f64_unsuffixed(f: f64) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f)) } else { Literal::Fallback(fallback::Literal::f64_unsuffixed(f)) } } pub(crate) fn string(string: &str) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::string(string)) } else { Literal::Fallback(fallback::Literal::string(string)) } } pub(crate) fn character(ch: char) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::character(ch)) } else { Literal::Fallback(fallback::Literal::character(ch)) } } pub(crate) fn byte_character(byte: u8) -> Literal { if inside_proc_macro() { Literal::Compiler({ #[cfg(not(no_literal_byte_character))] { proc_macro::Literal::byte_character(byte) } #[cfg(no_literal_byte_character)] { let fallback = fallback::Literal::byte_character(byte); proc_macro::Literal::from_str_unchecked(&fallback.repr) } }) } else { Literal::Fallback(fallback::Literal::byte_character(byte)) } } pub(crate) fn byte_string(bytes: &[u8]) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::byte_string(bytes)) } else { Literal::Fallback(fallback::Literal::byte_string(bytes)) } } pub(crate) fn c_string(string: &CStr) -> Literal { if inside_proc_macro() { Literal::Compiler({ #[cfg(not(no_literal_c_string))] { proc_macro::Literal::c_string(string) } #[cfg(no_literal_c_string)] { let fallback = fallback::Literal::c_string(string); proc_macro::Literal::from_str_unchecked(&fallback.repr) } }) } else { Literal::Fallback(fallback::Literal::c_string(string)) } } pub(crate) fn span(&self) -> Span { match self { Literal::Compiler(lit) => Span::Compiler(lit.span()), Literal::Fallback(lit) => Span::Fallback(lit.span()), } } pub(crate) fn set_span(&mut self, span: Span) { match (self, span) { (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s), (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s), (Literal::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Literal::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub(crate) fn subspan>(&self, range: R) -> Option { match self { #[cfg(proc_macro_span)] Literal::Compiler(lit) => lit.subspan(range).map(Span::Compiler), #[cfg(not(proc_macro_span))] Literal::Compiler(_lit) => None, Literal::Fallback(lit) => lit.subspan(range).map(Span::Fallback), } } fn unwrap_nightly(self) -> proc_macro::Literal { match self { Literal::Compiler(s) => s, Literal::Fallback(_) => mismatch(line!()), } } } impl From for Literal { fn from(s: fallback::Literal) -> Self { Literal::Fallback(s) } } impl Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Literal::Compiler(t) => Display::fmt(t, f), Literal::Fallback(t) => Display::fmt(t, f), } } } impl Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Literal::Compiler(t) => Debug::fmt(t, f), Literal::Fallback(t) => Debug::fmt(t, f), } } } #[cfg(span_locations)] pub(crate) fn invalidate_current_thread_spans() { if inside_proc_macro() { panic!( "proc_macro2::extra::invalidate_current_thread_spans is not available in procedural macros" ); } else { crate::fallback::invalidate_current_thread_spans(); } } proc-macro2/src/rcvec.rs0000644000175000017500000000577315105742312015001 0ustar bdrungbdrunguse alloc::rc::Rc; use alloc::vec; use core::mem; use core::panic::RefUnwindSafe; use core::slice; pub(crate) struct RcVec { inner: Rc>, } pub(crate) struct RcVecBuilder { inner: Vec, } pub(crate) struct RcVecMut<'a, T> { inner: &'a mut Vec, } #[derive(Clone)] pub(crate) struct RcVecIntoIter { inner: vec::IntoIter, } impl RcVec { pub(crate) fn is_empty(&self) -> bool { self.inner.is_empty() } pub(crate) fn len(&self) -> usize { self.inner.len() } pub(crate) fn iter(&self) -> slice::Iter { self.inner.iter() } pub(crate) fn make_mut(&mut self) -> RcVecMut where T: Clone, { RcVecMut { inner: Rc::make_mut(&mut self.inner), } } pub(crate) fn get_mut(&mut self) -> Option> { let inner = Rc::get_mut(&mut self.inner)?; Some(RcVecMut { inner }) } pub(crate) fn make_owned(mut self) -> RcVecBuilder where T: Clone, { let vec = if let Some(owned) = Rc::get_mut(&mut self.inner) { mem::take(owned) } else { Vec::clone(&self.inner) }; RcVecBuilder { inner: vec } } } impl RcVecBuilder { pub(crate) fn new() -> Self { RcVecBuilder { inner: Vec::new() } } pub(crate) fn with_capacity(cap: usize) -> Self { RcVecBuilder { inner: Vec::with_capacity(cap), } } pub(crate) fn push(&mut self, element: T) { self.inner.push(element); } pub(crate) fn extend(&mut self, iter: impl IntoIterator) { self.inner.extend(iter); } pub(crate) fn as_mut(&mut self) -> RcVecMut { RcVecMut { inner: &mut self.inner, } } pub(crate) fn build(self) -> RcVec { RcVec { inner: Rc::new(self.inner), } } } impl<'a, T> RcVecMut<'a, T> { pub(crate) fn push(&mut self, element: T) { self.inner.push(element); } pub(crate) fn extend(&mut self, iter: impl IntoIterator) { self.inner.extend(iter); } pub(crate) fn as_mut(&mut self) -> RcVecMut { RcVecMut { inner: self.inner } } pub(crate) fn take(self) -> RcVecBuilder { let vec = mem::take(self.inner); RcVecBuilder { inner: vec } } } impl Clone for RcVec { fn clone(&self) -> Self { RcVec { inner: Rc::clone(&self.inner), } } } impl IntoIterator for RcVecBuilder { type Item = T; type IntoIter = RcVecIntoIter; fn into_iter(self) -> Self::IntoIter { RcVecIntoIter { inner: self.inner.into_iter(), } } } impl Iterator for RcVecIntoIter { type Item = T; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl RefUnwindSafe for RcVec where T: RefUnwindSafe {} proc-macro2/src/parse.rs0000644000175000017500000006772515105742312015016 0ustar bdrungbdrunguse crate::fallback::{ self, is_ident_continue, is_ident_start, Group, Ident, LexError, Literal, Span, TokenStream, TokenStreamBuilder, }; use crate::{Delimiter, Punct, Spacing, TokenTree}; use core::char; use core::str::{Bytes, CharIndices, Chars}; #[derive(Copy, Clone, Eq, PartialEq)] pub(crate) struct Cursor<'a> { pub(crate) rest: &'a str, #[cfg(span_locations)] pub(crate) off: u32, } impl<'a> Cursor<'a> { pub(crate) fn advance(&self, bytes: usize) -> Cursor<'a> { let (_front, rest) = self.rest.split_at(bytes); Cursor { rest, #[cfg(span_locations)] off: self.off + _front.chars().count() as u32, } } pub(crate) fn starts_with(&self, s: &str) -> bool { self.rest.starts_with(s) } pub(crate) fn starts_with_char(&self, ch: char) -> bool { self.rest.starts_with(ch) } pub(crate) fn starts_with_fn(&self, f: Pattern) -> bool where Pattern: FnMut(char) -> bool, { self.rest.starts_with(f) } pub(crate) fn is_empty(&self) -> bool { self.rest.is_empty() } fn len(&self) -> usize { self.rest.len() } fn as_bytes(&self) -> &'a [u8] { self.rest.as_bytes() } fn bytes(&self) -> Bytes<'a> { self.rest.bytes() } fn chars(&self) -> Chars<'a> { self.rest.chars() } fn char_indices(&self) -> CharIndices<'a> { self.rest.char_indices() } fn parse(&self, tag: &str) -> Result, Reject> { if self.starts_with(tag) { Ok(self.advance(tag.len())) } else { Err(Reject) } } } pub(crate) struct Reject; type PResult<'a, O> = Result<(Cursor<'a>, O), Reject>; fn skip_whitespace(input: Cursor) -> Cursor { let mut s = input; while !s.is_empty() { let byte = s.as_bytes()[0]; if byte == b'/' { if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////")) && !s.starts_with("//!") { let (cursor, _) = take_until_newline_or_eof(s); s = cursor; continue; } else if s.starts_with("/**/") { s = s.advance(4); continue; } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***")) && !s.starts_with("/*!") { match block_comment(s) { Ok((rest, _)) => { s = rest; continue; } Err(Reject) => return s, } } } match byte { b' ' | 0x09..=0x0d => { s = s.advance(1); continue; } b if b.is_ascii() => {} _ => { let ch = s.chars().next().unwrap(); if is_whitespace(ch) { s = s.advance(ch.len_utf8()); continue; } } } return s; } s } fn block_comment(input: Cursor) -> PResult<&str> { if !input.starts_with("/*") { return Err(Reject); } let mut depth = 0usize; let bytes = input.as_bytes(); let mut i = 0usize; let upper = bytes.len() - 1; while i < upper { if bytes[i] == b'/' && bytes[i + 1] == b'*' { depth += 1; i += 1; // eat '*' } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { depth -= 1; if depth == 0 { return Ok((input.advance(i + 2), &input.rest[..i + 2])); } i += 1; // eat '/' } i += 1; } Err(Reject) } fn is_whitespace(ch: char) -> bool { // Rust treats left-to-right mark and right-to-left mark as whitespace ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' } fn word_break(input: Cursor) -> Result { match input.chars().next() { Some(ch) if is_ident_continue(ch) => Err(Reject), Some(_) | None => Ok(input), } } // Rustc's representation of a macro expansion error in expression position or // type position. const ERROR: &str = "(/*ERROR*/)"; pub(crate) fn token_stream(mut input: Cursor) -> Result { let mut trees = TokenStreamBuilder::new(); let mut stack = Vec::new(); loop { input = skip_whitespace(input); if let Ok((rest, ())) = doc_comment(input, &mut trees) { input = rest; continue; } #[cfg(span_locations)] let lo = input.off; let first = match input.bytes().next() { Some(first) => first, None => match stack.last() { None => return Ok(trees.build()), #[cfg(span_locations)] Some((lo, _frame)) => { return Err(LexError { span: Span { lo: *lo, hi: *lo }, }) } #[cfg(not(span_locations))] Some(_frame) => return Err(LexError { span: Span {} }), }, }; if let Some(open_delimiter) = match first { b'(' if !input.starts_with(ERROR) => Some(Delimiter::Parenthesis), b'[' => Some(Delimiter::Bracket), b'{' => Some(Delimiter::Brace), _ => None, } { input = input.advance(1); let frame = (open_delimiter, trees); #[cfg(span_locations)] let frame = (lo, frame); stack.push(frame); trees = TokenStreamBuilder::new(); } else if let Some(close_delimiter) = match first { b')' => Some(Delimiter::Parenthesis), b']' => Some(Delimiter::Bracket), b'}' => Some(Delimiter::Brace), _ => None, } { let frame = match stack.pop() { Some(frame) => frame, None => return Err(lex_error(input)), }; #[cfg(span_locations)] let (lo, frame) = frame; let (open_delimiter, outer) = frame; if open_delimiter != close_delimiter { return Err(lex_error(input)); } input = input.advance(1); let mut g = Group::new(open_delimiter, trees.build()); g.set_span(Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: input.off, }); trees = outer; trees.push_token_from_parser(TokenTree::Group(crate::Group::_new_fallback(g))); } else { let (rest, mut tt) = match leaf_token(input) { Ok((rest, tt)) => (rest, tt), Err(Reject) => return Err(lex_error(input)), }; tt.set_span(crate::Span::_new_fallback(Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: rest.off, })); trees.push_token_from_parser(tt); input = rest; } } } fn lex_error(cursor: Cursor) -> LexError { #[cfg(not(span_locations))] let _ = cursor; LexError { span: Span { #[cfg(span_locations)] lo: cursor.off, #[cfg(span_locations)] hi: cursor.off, }, } } fn leaf_token(input: Cursor) -> PResult { if let Ok((input, l)) = literal(input) { // must be parsed before ident Ok((input, TokenTree::Literal(crate::Literal::_new_fallback(l)))) } else if let Ok((input, p)) = punct(input) { Ok((input, TokenTree::Punct(p))) } else if let Ok((input, i)) = ident(input) { Ok((input, TokenTree::Ident(i))) } else if input.starts_with(ERROR) { let rest = input.advance(ERROR.len()); let repr = crate::Literal::_new_fallback(Literal::_new(ERROR.to_owned())); Ok((rest, TokenTree::Literal(repr))) } else { Err(Reject) } } fn ident(input: Cursor) -> PResult { if [ "r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#", "c\"", "cr\"", "cr#", ] .iter() .any(|prefix| input.starts_with(prefix)) { Err(Reject) } else { ident_any(input) } } fn ident_any(input: Cursor) -> PResult { let raw = input.starts_with("r#"); let rest = input.advance((raw as usize) << 1); let (rest, sym) = ident_not_raw(rest)?; if !raw { let ident = crate::Ident::_new_fallback(Ident::new_unchecked(sym, fallback::Span::call_site())); return Ok((rest, ident)); } match sym { "_" | "super" | "self" | "Self" | "crate" => return Err(Reject), _ => {} } let ident = crate::Ident::_new_fallback(Ident::new_raw_unchecked(sym, fallback::Span::call_site())); Ok((rest, ident)) } fn ident_not_raw(input: Cursor) -> PResult<&str> { let mut chars = input.char_indices(); match chars.next() { Some((_, ch)) if is_ident_start(ch) => {} _ => return Err(Reject), } let mut end = input.len(); for (i, ch) in chars { if !is_ident_continue(ch) { end = i; break; } } Ok((input.advance(end), &input.rest[..end])) } pub(crate) fn literal(input: Cursor) -> PResult { let rest = literal_nocapture(input)?; let end = input.len() - rest.len(); Ok((rest, Literal::_new(input.rest[..end].to_string()))) } fn literal_nocapture(input: Cursor) -> Result { if let Ok(ok) = string(input) { Ok(ok) } else if let Ok(ok) = byte_string(input) { Ok(ok) } else if let Ok(ok) = c_string(input) { Ok(ok) } else if let Ok(ok) = byte(input) { Ok(ok) } else if let Ok(ok) = character(input) { Ok(ok) } else if let Ok(ok) = float(input) { Ok(ok) } else if let Ok(ok) = int(input) { Ok(ok) } else { Err(Reject) } } fn literal_suffix(input: Cursor) -> Cursor { match ident_not_raw(input) { Ok((input, _)) => input, Err(Reject) => input, } } fn string(input: Cursor) -> Result { if let Ok(input) = input.parse("\"") { cooked_string(input) } else if let Ok(input) = input.parse("r") { raw_string(input) } else { Err(Reject) } } fn cooked_string(mut input: Cursor) -> Result { let mut chars = input.char_indices(); while let Some((i, ch)) = chars.next() { match ch { '"' => { let input = input.advance(i + 1); return Ok(literal_suffix(input)); } '\r' => match chars.next() { Some((_, '\n')) => {} _ => break, }, '\\' => match chars.next() { Some((_, 'x')) => { backslash_x_char(&mut chars)?; } Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"' | '0')) => {} Some((_, 'u')) => { backslash_u(&mut chars)?; } Some((newline, ch @ ('\n' | '\r'))) => { input = input.advance(newline + 1); trailing_backslash(&mut input, ch as u8)?; chars = input.char_indices(); } _ => break, }, _ch => {} } } Err(Reject) } fn raw_string(input: Cursor) -> Result { let (input, delimiter) = delimiter_of_raw_string(input)?; let mut bytes = input.bytes().enumerate(); while let Some((i, byte)) = bytes.next() { match byte { b'"' if input.rest[i + 1..].starts_with(delimiter) => { let rest = input.advance(i + 1 + delimiter.len()); return Ok(literal_suffix(rest)); } b'\r' => match bytes.next() { Some((_, b'\n')) => {} _ => break, }, _ => {} } } Err(Reject) } fn byte_string(input: Cursor) -> Result { if let Ok(input) = input.parse("b\"") { cooked_byte_string(input) } else if let Ok(input) = input.parse("br") { raw_byte_string(input) } else { Err(Reject) } } fn cooked_byte_string(mut input: Cursor) -> Result { let mut bytes = input.bytes().enumerate(); while let Some((offset, b)) = bytes.next() { match b { b'"' => { let input = input.advance(offset + 1); return Ok(literal_suffix(input)); } b'\r' => match bytes.next() { Some((_, b'\n')) => {} _ => break, }, b'\\' => match bytes.next() { Some((_, b'x')) => { backslash_x_byte(&mut bytes)?; } Some((_, b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"')) => {} Some((newline, b @ (b'\n' | b'\r'))) => { input = input.advance(newline + 1); trailing_backslash(&mut input, b)?; bytes = input.bytes().enumerate(); } _ => break, }, b if b.is_ascii() => {} _ => break, } } Err(Reject) } fn delimiter_of_raw_string(input: Cursor) -> PResult<&str> { for (i, byte) in input.bytes().enumerate() { match byte { b'"' => { if i > 255 { // https://github.com/rust-lang/rust/pull/95251 return Err(Reject); } return Ok((input.advance(i + 1), &input.rest[..i])); } b'#' => {} _ => break, } } Err(Reject) } fn raw_byte_string(input: Cursor) -> Result { let (input, delimiter) = delimiter_of_raw_string(input)?; let mut bytes = input.bytes().enumerate(); while let Some((i, byte)) = bytes.next() { match byte { b'"' if input.rest[i + 1..].starts_with(delimiter) => { let rest = input.advance(i + 1 + delimiter.len()); return Ok(literal_suffix(rest)); } b'\r' => match bytes.next() { Some((_, b'\n')) => {} _ => break, }, other => { if !other.is_ascii() { break; } } } } Err(Reject) } fn c_string(input: Cursor) -> Result { if let Ok(input) = input.parse("c\"") { cooked_c_string(input) } else if let Ok(input) = input.parse("cr") { raw_c_string(input) } else { Err(Reject) } } fn raw_c_string(input: Cursor) -> Result { let (input, delimiter) = delimiter_of_raw_string(input)?; let mut bytes = input.bytes().enumerate(); while let Some((i, byte)) = bytes.next() { match byte { b'"' if input.rest[i + 1..].starts_with(delimiter) => { let rest = input.advance(i + 1 + delimiter.len()); return Ok(literal_suffix(rest)); } b'\r' => match bytes.next() { Some((_, b'\n')) => {} _ => break, }, b'\0' => break, _ => {} } } Err(Reject) } fn cooked_c_string(mut input: Cursor) -> Result { let mut chars = input.char_indices(); while let Some((i, ch)) = chars.next() { match ch { '"' => { let input = input.advance(i + 1); return Ok(literal_suffix(input)); } '\r' => match chars.next() { Some((_, '\n')) => {} _ => break, }, '\\' => match chars.next() { Some((_, 'x')) => { backslash_x_nonzero(&mut chars)?; } Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"')) => {} Some((_, 'u')) => { if backslash_u(&mut chars)? == '\0' { break; } } Some((newline, ch @ ('\n' | '\r'))) => { input = input.advance(newline + 1); trailing_backslash(&mut input, ch as u8)?; chars = input.char_indices(); } _ => break, }, '\0' => break, _ch => {} } } Err(Reject) } fn byte(input: Cursor) -> Result { let input = input.parse("b'")?; let mut bytes = input.bytes().enumerate(); let ok = match bytes.next().map(|(_, b)| b) { Some(b'\\') => match bytes.next().map(|(_, b)| b) { Some(b'x') => backslash_x_byte(&mut bytes).is_ok(), Some(b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"') => true, _ => false, }, b => b.is_some(), }; if !ok { return Err(Reject); } let (offset, _) = bytes.next().ok_or(Reject)?; if !input.chars().as_str().is_char_boundary(offset) { return Err(Reject); } let input = input.advance(offset).parse("'")?; Ok(literal_suffix(input)) } fn character(input: Cursor) -> Result { let input = input.parse("'")?; let mut chars = input.char_indices(); let ok = match chars.next().map(|(_, ch)| ch) { Some('\\') => match chars.next().map(|(_, ch)| ch) { Some('x') => backslash_x_char(&mut chars).is_ok(), Some('u') => backslash_u(&mut chars).is_ok(), Some('n' | 'r' | 't' | '\\' | '0' | '\'' | '"') => true, _ => false, }, ch => ch.is_some(), }; if !ok { return Err(Reject); } let (idx, _) = chars.next().ok_or(Reject)?; let input = input.advance(idx).parse("'")?; Ok(literal_suffix(input)) } macro_rules! next_ch { ($chars:ident @ $pat:pat) => { match $chars.next() { Some((_, ch)) => match ch { $pat => ch, _ => return Err(Reject), }, None => return Err(Reject), } }; } fn backslash_x_char(chars: &mut I) -> Result<(), Reject> where I: Iterator, { next_ch!(chars @ '0'..='7'); next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); Ok(()) } fn backslash_x_byte(chars: &mut I) -> Result<(), Reject> where I: Iterator, { next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); Ok(()) } fn backslash_x_nonzero(chars: &mut I) -> Result<(), Reject> where I: Iterator, { let first = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); let second = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); if first == '0' && second == '0' { Err(Reject) } else { Ok(()) } } fn backslash_u(chars: &mut I) -> Result where I: Iterator, { next_ch!(chars @ '{'); let mut value = 0; let mut len = 0; for (_, ch) in chars { let digit = match ch { '0'..='9' => ch as u8 - b'0', 'a'..='f' => 10 + ch as u8 - b'a', 'A'..='F' => 10 + ch as u8 - b'A', '_' if len > 0 => continue, '}' if len > 0 => return char::from_u32(value).ok_or(Reject), _ => break, }; if len == 6 { break; } value *= 0x10; value += u32::from(digit); len += 1; } Err(Reject) } fn trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject> { let mut whitespace = input.bytes().enumerate(); loop { if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') { return Err(Reject); } match whitespace.next() { Some((_, b @ (b' ' | b'\t' | b'\n' | b'\r'))) => { last = b; } Some((offset, _)) => { *input = input.advance(offset); return Ok(()); } None => return Err(Reject), } } } fn float(input: Cursor) -> Result { let mut rest = float_digits(input)?; if let Some(ch) = rest.chars().next() { if is_ident_start(ch) { rest = ident_not_raw(rest)?.0; } } word_break(rest) } fn float_digits(input: Cursor) -> Result { let mut chars = input.chars().peekable(); match chars.next() { Some(ch) if '0' <= ch && ch <= '9' => {} _ => return Err(Reject), } let mut len = 1; let mut has_dot = false; let mut has_exp = false; while let Some(&ch) = chars.peek() { match ch { '0'..='9' | '_' => { chars.next(); len += 1; } '.' => { if has_dot { break; } chars.next(); if chars .peek() .map_or(false, |&ch| ch == '.' || is_ident_start(ch)) { return Err(Reject); } len += 1; has_dot = true; } 'e' | 'E' => { chars.next(); len += 1; has_exp = true; break; } _ => break, } } if !(has_dot || has_exp) { return Err(Reject); } if has_exp { let token_before_exp = if has_dot { Ok(input.advance(len - 1)) } else { Err(Reject) }; let mut has_sign = false; let mut has_exp_value = false; while let Some(&ch) = chars.peek() { match ch { '+' | '-' => { if has_exp_value { break; } if has_sign { return token_before_exp; } chars.next(); len += 1; has_sign = true; } '0'..='9' => { chars.next(); len += 1; has_exp_value = true; } '_' => { chars.next(); len += 1; } _ => break, } } if !has_exp_value { return token_before_exp; } } Ok(input.advance(len)) } fn int(input: Cursor) -> Result { let mut rest = digits(input)?; if let Some(ch) = rest.chars().next() { if is_ident_start(ch) { rest = ident_not_raw(rest)?.0; } } word_break(rest) } fn digits(mut input: Cursor) -> Result { let base = if input.starts_with("0x") { input = input.advance(2); 16 } else if input.starts_with("0o") { input = input.advance(2); 8 } else if input.starts_with("0b") { input = input.advance(2); 2 } else { 10 }; let mut len = 0; let mut empty = true; for b in input.bytes() { match b { b'0'..=b'9' => { let digit = (b - b'0') as u64; if digit >= base { return Err(Reject); } } b'a'..=b'f' => { let digit = 10 + (b - b'a') as u64; if digit >= base { break; } } b'A'..=b'F' => { let digit = 10 + (b - b'A') as u64; if digit >= base { break; } } b'_' => { if empty && base == 10 { return Err(Reject); } len += 1; continue; } _ => break, } len += 1; empty = false; } if empty { Err(Reject) } else { Ok(input.advance(len)) } } fn punct(input: Cursor) -> PResult { let (rest, ch) = punct_char(input)?; if ch == '\'' { if ident_any(rest)?.0.starts_with_char('\'') { Err(Reject) } else { Ok((rest, Punct::new('\'', Spacing::Joint))) } } else { let kind = match punct_char(rest) { Ok(_) => Spacing::Joint, Err(Reject) => Spacing::Alone, }; Ok((rest, Punct::new(ch, kind))) } } fn punct_char(input: Cursor) -> PResult { if input.starts_with("//") || input.starts_with("/*") { // Do not accept `/` of a comment as a punct. return Err(Reject); } let mut chars = input.chars(); let first = match chars.next() { Some(ch) => ch, None => { return Err(Reject); } }; let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; if recognized.contains(first) { Ok((input.advance(first.len_utf8()), first)) } else { Err(Reject) } } fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult<'a, ()> { #[cfg(span_locations)] let lo = input.off; let (rest, (comment, inner)) = doc_comment_contents(input)?; let fallback_span = Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: rest.off, }; let span = crate::Span::_new_fallback(fallback_span); let mut scan_for_bare_cr = comment; while let Some(cr) = scan_for_bare_cr.find('\r') { let rest = &scan_for_bare_cr[cr + 1..]; if !rest.starts_with('\n') { return Err(Reject); } scan_for_bare_cr = rest; } let mut pound = Punct::new('#', Spacing::Alone); pound.set_span(span); trees.push_token_from_parser(TokenTree::Punct(pound)); if inner { let mut bang = Punct::new('!', Spacing::Alone); bang.set_span(span); trees.push_token_from_parser(TokenTree::Punct(bang)); } let doc_ident = crate::Ident::_new_fallback(Ident::new_unchecked("doc", fallback_span)); let mut equal = Punct::new('=', Spacing::Alone); equal.set_span(span); let mut literal = crate::Literal::_new_fallback(Literal::string(comment)); literal.set_span(span); let mut bracketed = TokenStreamBuilder::with_capacity(3); bracketed.push_token_from_parser(TokenTree::Ident(doc_ident)); bracketed.push_token_from_parser(TokenTree::Punct(equal)); bracketed.push_token_from_parser(TokenTree::Literal(literal)); let group = Group::new(Delimiter::Bracket, bracketed.build()); let mut group = crate::Group::_new_fallback(group); group.set_span(span); trees.push_token_from_parser(TokenTree::Group(group)); Ok((rest, ())) } fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> { if input.starts_with("//!") { let input = input.advance(3); let (input, s) = take_until_newline_or_eof(input); Ok((input, (s, true))) } else if input.starts_with("/*!") { let (input, s) = block_comment(input)?; Ok((input, (&s[3..s.len() - 2], true))) } else if input.starts_with("///") { let input = input.advance(3); if input.starts_with_char('/') { return Err(Reject); } let (input, s) = take_until_newline_or_eof(input); Ok((input, (s, false))) } else if input.starts_with("/**") && !input.rest[3..].starts_with('*') { let (input, s) = block_comment(input)?; Ok((input, (&s[3..s.len() - 2], false))) } else { Err(Reject) } } fn take_until_newline_or_eof(input: Cursor) -> (Cursor, &str) { let chars = input.char_indices(); for (i, ch) in chars { if ch == '\n' { return (input.advance(i), &input.rest[..i]); } else if ch == '\r' && input.rest[i + 1..].starts_with('\n') { return (input.advance(i + 1), &input.rest[..i]); } } (input.advance(input.len()), input.rest) } pyo3/0000775000175000017500000000000015105742312011276 5ustar bdrungbdrungpyo3/assets/0000775000175000017500000000000015105742312012600 5ustar bdrungbdrungpyo3/assets/script.py0000644000175000017500000000006415105742312014454 0ustar bdrungbdrung# Used in PyModule examples. class Blah: pass pyo3/pyo3-runtime/0000775000175000017500000000000015105742312013651 5ustar bdrungbdrungpyo3/pyo3-runtime/tests/0000775000175000017500000000000015105742312015013 5ustar bdrungbdrungpyo3/pyo3-runtime/tests/__init__.py0000644000175000017500000000000015105742312017110 0ustar bdrungbdrungpyo3/pyo3-runtime/LICENSE-MIT0000644000175000017500000000212315105742312015301 0ustar bdrungbdrungCopyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3/pyo3-runtime/LICENSE-APACHE0000644000175000017500000002311715105742312015577 0ustar bdrungbdrungCopyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS pyo3/pyo3-runtime/README.md0000644000175000017500000000001515105742312015122 0ustar bdrungbdrungComing soon! pyo3/pyo3-runtime/pyproject.toml0000644000175000017500000000166615105742312016574 0ustar bdrungbdrung[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "pyo3-runtime" dynamic = ["version"] description = '' readme = "README.md" requires-python = ">=3.7" license = "MIT OR Apache-2.0" keywords = [] authors = [ { name = "David Hewitt", email = "1939362+davidhewitt@users.noreply.github.com" }, ] classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] dependencies = [] [project.urls] Homepage = "https://github.com/PyO3/pyo3" [tool.hatch.version] path = "src/pyo3_runtime/__init__.py" pyo3/pyo3-runtime/src/0000775000175000017500000000000015105742312014440 5ustar bdrungbdrungpyo3/pyo3-runtime/src/pyo3_runtime/0000775000175000017500000000000015105742312017075 5ustar bdrungbdrungpyo3/pyo3-runtime/src/pyo3_runtime/__init__.py0000644000175000017500000000002615105742312021202 0ustar bdrungbdrung__version__ = "0.0.1" pyo3/netlify.toml0000644000175000017500000000015515105742312013644 0ustar bdrungbdrung[build] publish = "netlify_build/" command = ".netlify/build.sh" [build.environment] PYTHON_VERSION = "3.8" pyo3/branding/0000775000175000017500000000000015105742312013062 5ustar bdrungbdrungpyo3/branding/pyotr.svg0000644000175000017500000002406315105742312014763 0ustar bdrungbdrungpyo3/branding/pyo3logo.svg0000644000175000017500000002414515105742312015362 0ustar bdrungbdrungpyo3/branding/pyotr.png0000644000175000017500000124327115105742312014755 0ustar bdrungbdrungPNG  IHDR팥 pHYs.#.#x?v IDATx 02޿Ġ4)<3.OCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC8z1 G"o..] ^Ce R(RdxK%("EJtT@u:9K* E^;% {j~sm$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBPKG IDAT A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$eHBP A$֬Wbf؟onwcm}?e8sZgj87mto{^|õ[#/K'qT=X4+?d/Vnbm}~6 TL$"8w7ڍLx24ժƱ՘=z%fk_/+wv7nXLD{v؆nk;}t?>/ARhύhύ>utbnލ;c3Z]z | SXLıV؏nmcs׳aXLqV8^+={Yz^|_z D H7mtG2-̏hWJOy"[;ݸ潸`Fcd7= ˼祧ؙåg\㕸g3Z3¹͘ @ߝ;݌hEkUR hr+g }լWb31hvHsz% -gN֣=7Q-zOPzh{L8{^zIc {X }3ժƙ"*~HLJπXJXhύ@B2QreՊHg˞-'jܚ+n=uZ-: Cc{s*u#Ơ VKkKYl,g3Dcm=)2rՊȕz[Ȯ^nx?#<|dꄡq?x ͩ3(fE2􌓨UgldBϤ΀ciJqiLꌡV3&@O8@_=\M0tJq[OGR ^{Z)d FA(R:c(/eώޜRꌑVZc|NI4fc:a]٩Ge,j-uȨV  92֚:ܟf:~G-+N=uY_<82rՊNZ)ˍe,ɗz>gR'0Ĝ:/&S'RLI5,RtY(ћ>W_ oqu r`;{G#nJ!ug{`]8Vk3~:n;+OUPFo~~;=o7_E|}cM 2rWv3;=$nݾ:!ҝ3y'{:*dt'2\77ߏa6ANƋb~:_7Ww~o0u Cḱ 7ן+uMgۛSY('{ߺx^KJexdr\~&uon_ۻ:!su38?ݼw=H=zH淽ֵŷv8?VGr5u|w"7Rg0D63c2Cn=uL-+սF\~&7c2J!֌b~<^VRG0|b\1hgrܽ nݾ:k6ˍ8Uz,u Gl7>NYNL̷JS>S-+r5lw: >W!uic:#xts|I|[jf{s*un=^k Dvr\q"ZNB\kD- nkèP6lPeX_R[Rt ל6V|4,fŸHA[%C`:*ō\)uʉ\<umju/uA-+}T4(~&B/u&n=SbLfSȑ'bQL ԲBܽ nݾ:PUyn'?GsW;{-vrtNGbϕkyaĭ7>}Zȗb9??:Go^y7u996ϤΠ{y'u|OdBꔞћ;?wrà cc;+OUb;?z~|wsAOݐ7X_Rgya|u'q)$nΥΠ^i|o΀O5c20*@`5Ÿ6O/g7Ƿx.2rbk{b=GZV/F1u ={ؼqMØ'~Xzǩ3 V{#ڭRŅߋ+;/S{קn%J}wFdt˩38ZVr|wS7+|:u=vXܿN_X?}/R}'/|?u cΠ #(sz:ݿgn*=ŲaFn=jY!u=l]zCrRg'OR;o Y\٩v0?|:1fPVROedqރIH6XΠڭRܽ nݾ:e|(;Uz,ʥB~:17c2Oīo|w=Hzٳ~4C(ƕztʩSon_+~a83C8x/ب׈݉ nމ;,Hdd>qރXcH`t'Ƌj|w"^֌4CUs?Gl;aLfl?3:1eL6@N0j^#vwRZ-u dZ)L `8Y_ʢ(`lՌ 5#$xZKu[33N+<ėNT 3㞏F'R ė?QyoOSq|'ucf~d+c`KYꌞY_Ƌ碖=::Y_bcyt_ZEg:w'=7j{m~s22VJq?V)u ˕lc{s*u O{^X` 047FªQhc9F1uv?GFT+;B9:(c2G7(``(t'}WιpJnl,WS'@RT(#⹋өAdokm2ucj:>OQ'T)ҭdx~:1n{3H>x_o:cjJ3ȉqރu~F@-+ RI2tSǫo|w=H0(@~k&fG_>ėć?J V)u [x罇_)_Qzs=nB[k5P10 8)@.moNNȭ+;8ح`m,WS'SKYlRg[Vdl/Vbku2uC*kךdZ)D2(@tY(ȵ,D-~z*y΢e#c˥3lSgcV)gZ>_oN;[Bg3.S[k|5nLik5Gw }Up&6 p2["sxtꌱlc{s*uCl_?c2Y,N`9 @l,WS' jWv8DRy'+uRfЂ尉1[VR'0œ 7bϕRg Kg`:!l:!tiLt'RgZt prXdR8>r", KYx\2pt z[*޳ө3_clc9+;S2@8I@ntONs9IU΂A]Rݺ!85@omoNN c2T%u#ʉNràEo6q?E| R'ͩ3Fouʱ`䇿/eȅZVF1uȩV qLK>݉ޜJ1:帴y&u#v|ɗF1-CaArESSgC[16Jw"uHe80A61ZVR'0 ݅өFޅZ\kD-Āp[7CۛS1(`moNy0vqiL >SF=ȅb9uX8ߝƉ_B=@gVk3blNΠv뱾d@.J~ s\xUJ06JڵfjF\)5Rg ZV3djF1`\^s 䚍bT+e=HJ!gbcqn2Y(ө3N#Ubku2u=bLfxt+1N\UJ0B\٩Z-u l `0.֌W=DN` mբ( ?zˠ uONk{Nn=uT .3P]6v F2T+~f*u!Sbň=dP e>:[3J!5<ѕzT+Hg})f:ce8ܟB9u &"ɹrYlW3roku{\S IDAT\~f*uɘqj;:bP\ɨ̈XbQL,nb{ӈEgѸ00&3fE2$dT+xsN6sVk_>n=ϘhqGF vT>Õ#*EgEe{A߲9e,c"ɌA꺤k6n=jFdjW[>nSU׮5ɌFz)r 6֗8ܟquղB/e3Wf8ܟI\-+n=u|B9V35V)gZly NLg:#+ōEehXmNN1?W1)jө1ѷҭN`8a@2O'*bJw"u `c9Kj})ۯb9.Rgmq'dC&=ɴ[R'pLJ!^kT>d6mSggSղBSgmoNNkdGRQNI#,(9`°XN/t?l|><ةzb6FeYN3+JF$Q .,5jb5EM j33b;3ضj^lc9d̊Nȉ#hJ݉8ܟq~f*u\)v3F#Z)dꌱŕhQ1(@݅өRx񜑠eXN΀cY_bc9K7WQᵵVZkߌɰp<:HhV q?3#pCN}$_'jY(΀V #͘ 绕 1'HBV qe[k)|dxd3lSgLQͩKH=>Ę ,9qk6Q{v:v]Nm;.3ĪB\Wv^)HVRN,0pV)u}ōύ06:Nl~]NqbۛSY(΀Z_ʼ롃z\X gS'0`ڭSRϸl@Q4^X_bkmxGڭR\<: >n=֗Jw"uCʠ Y4t1.>|J=>S'@tC c2|j1#1(=*N`B\~&6]ZVD 5(8c~km{ӈ٣2&Qt+BevՊoO+;|q:u{z9c$U+zl8;帰ZK}Y(2{d8b9uCh8N[02ڭRZ B oJ SղBSg;ZV/3&Ñϕ(`8 @[R'R3Fe`;.3֗Z\ۛSF16 |ZV3<5:!6n@K\)^c&S'@=;rOҝ ~ޜJkd8 2 Tg! ^ˋ+݉)#(z|1V(U-+n=u$1(֚1OcL:ߝZG Y4voV ^#6)Co 0P/[t`J~z`ж7rc2Jp $dEZ>ݕzSg ZVD Rcc9j[3r(gVN`S0>ڭSȱ,f޽x݇sYT+~|w"u}j|_ۭRx}gp={/R rGoޏ}^ܹ uk͘m9w~v|󅟦HƘ |q c2\)nx.-_/Gҝ0&@\XEsL_O 'b9uCZ)+/,uJ]XLc gL~;G]8:!teۛw!bt\, ֗h63Ƙ 0?WI&*N`H]<ʘ~o,gd΢1AL ANb})/Z棍OԲBt'Rgg,G~bc9+;uc2 J:!D}W 1(`ϕ }uro{s*uB|2&tޠ G1}](N`D6q?E_SV'S',Guۘ ) ڭS!J!??YdV1(#9c2T%u9gP,S'0`w2ݓRFRWQ#f1Cg{s*u‰֍ɐ b 1>H(FDόͨ3!3(r:c}ix=+Jrl`8U+ZLq,dȫR4UUJV qe[k)}qa.oZE- dȻb9u95Zg`:V1(V ZV0&PXVR'Sev:1eqȅ|_y&:e8ܟ1&P8ߝH@N1AR,p&[q9(Fg!Q\~&""~u~q_|w=Hɘ D|Ax:u\)g;?QgR'@_ϕ~5r)DD;=ˡ[?;īc2 i2Ξ=QFӍϹK[WMq,]kFRHIqĭ[><ט 'wRg3eS'ގoGVgSg@.ݽ {Aܺaܺ}?{p_oLQ|qH1uXNj-&B~o0u::rkQF1: ߾#3V)vdzŲA~AɖRV)\lb8jDD֣Z)ʄXƷv r䱳g~:su3sݽ w/nݾ:%ڭR[.vsF8/J`HK2A6q?_x}b[|<Y(`t'{:xٳ`ԲB0u˟՗KV) .Z)`|k{Rgv:N=ϿuOUx82sWw:1(@uNNGERoHX,V)B+7U+XN7O@ڭRxdq?_潸sofr[X9_CgA""ⱳg~:_QRgoEb[Pن~'wRgN=SFј #Z)K{p$b4ŸsAsjJS2Tu*uX:߭N  SrY(G-s`9A@Ou ҝH@b0jY!ڭgW_`55 @uO^y7u ,p:ڭR4(G7^}ヸ{Aܺa|u~Kd ҝH@bejY!^΢p:Ο"WgKYDDxq_7ߏ}x^vTVXW_ u 7t qxj)l7cŸJ)3xc{Ts>况B |Z>N7q`O96c;w8H^s3ƹv8w%ΝoBbwϹvחޏ.ȥ`JQqPksH9YL=l㵗vl,k?]N=+.Ǚo_@=nEc[SO!ʹcİX,@Ƹ@ϛ}O~R.fZ\=5cxF1μ+N:ylΝT˹OzF}q5v)l߽;[箤#ʥ)}wO9-?1Z>6X!L?O GH@7svp'dVQqРh55YL=ulKDD[Bgd}xsSXgc[SO`;՗z APwzBϨr17.eV]R.~pSO=sΏSμ+G1R8ЎĹSx{mw lYr3O 1tbSG^˧ChNSO`.ǩ#CQ-;j 'at8m ed%aƶDV9W{ʩpzhAT 8@OȧTJ8yx(μ+s cH`|g^}!@'e:h!{Hr@â2JP O(s8vh0e2; TJ9Q=Rh[W71H=OL5@LnRL?ޘީsz^szBT]caQrI,2@i61|8Nz-zNOQ)y t9ղbYg^@ET3a@q)[*\̴͹zSN='RO'(dB˻9YL='\ૈ%(dh!dN!WrZTˎ'l6'6Lj6\=tym^=1}9&sZȴ\=f[t=Ah!^=1z@O2RL?ޘީsB㣅8ud( !(Z>~p'9YL=LC?]@=AP9F1ǩ#CQS㣅b3;՗z@ =kt9μ+f[Q-{\eȀSGbbL`#!J)3xsSXO:rqȐ+r2 n_h;yx(μ+s:ȈB|`%(㣅?>'^˧1 rSN= e(s8vh0~Z-bD\uCboA|\=f[$31VH= rq`#(*\̴㍹zK=gM5@F=3b"(pFjZ̟ncȰ@ "(bSG^˧eHF­MP!.Ǚwlk l>n1;UJ= 3y`TJiǛs8zκ;z=`bz@fsrA P)8hNSy$r.oc՟zf@bp[h7./t|>7{R#ߗ IDAT`k1'16@Q?/]+ROd1f[lSOG'16}r|'2r̶\ ɥuR.fZ\=N%R-b5!1:F{Tu&Gkqn/]sۛ|>7˛5A奵3 &k61|8~|f%^W6\sh65!(rj|+sS@<;k8z@ReR.fZ\=)?窖s1kq ]^{<LpTJ8yx(ۗޏsg|>7{R^&(AG 1|8-o{' O&.Q(zp 5x}ӫܕr_,lk b…Fj20:}r|'W҇Oh!,C tJ)33`Ck2\#2BP #eP-;:X!'(2| !e9#5AN4ؖz@A:X!'(tjq&G@F^˧e0"(e2BPղ#M cLROj2!(2@xjz@W:F%&(2@ǨixN_cbz@WAzNQL=6 1+eQ)9(ATˎ5<,'/21VH=k d @F婱B ]KP(Җ @Fd Q @Fd Q(;𰜼:h!%(2!(@O+}'t%AzJ@7!(0ܞA:NO=+ ^{<$(2!(t| ]IP8#5A!(2!(tz-z@W:Έ CA:RxrHc @FS(y$@v=@OۚzlA#M5ue2BP #e2BPHc БeǛ!(TO/}Wv,^JiKPHb}=bKi oJk?_O9Yƶ{K奵xkqyim>}x1 bந%_z & 15Yfc[Lbp- qqvWWnRW|ڎV۷_|YhO߾-4d p_& q`O%N=t@拚b48?;{#N_fcz oD.x|X^齸۷c )>㣅 ZL3S}q2evT~O_oƏglܖ|<~q2V/Z{%<K @s-e"Ab"MJq.:V/DRi@+1/!BPbPnQVnވի qw+RO: ^|L.26o@,_ZXY+bGLS㣅8`}a0޾~#No]XM= nD쎈ŋw3"3[er&&s㣅-L?YZgoď^&.˩'thGCdz c(Fj8Ue~zBf@ow/ueqP]O\47W{Ef/\hL2q' EK=#Se^idS˗e/D ;F1L5\zпw^߉ˬ,^ ^Iz dرC'qXʍOb/"3;q?f%(5|6.s8}F8}wkQ'|leb,_:+ zr2@+FyxXYp'2|q!+ @w :R. B\RnDƝbB3 m }S.|+qn^1z(b1}c˗e/.Z{%@`21bԼ62po_߾P$ֿw^b'@P2{*'e6ީxjztDL;q ^I7;՗zH\f}T˹m }S Կw^,^$2x!:2!bTJ3 w˜=A>{#J=cM╣y<<tDD߉,_\K/ dTc[ leNFވg|lk fZg"_,'bS߹K 3ŅXk 豝;w~z>O GQL=e"|r㣅SXwFgky ŷRȜŋf.ԓ@ݩ'az1.s`O9wh0*\)xgtܖ|v^^˗ԓKSX!:3S}T_e\:<LGk'b-TDD\:'2DP2^6/Lsň`勥݈ݍ; ^I; d"Y̶b՟zþYYx;0IdF`$(5.Sc-9(Ծ`s @F4''˜[h^?ROS}qPTJSn Hi//Ņ; A(FQ/ WG]KsCl*bӱ`}=sΏSh6gRe& qP6k~8zFGyߦQ@FʐfeG_ܰ@gړ2VI= &0!T˹8ux([@wo|+VR`⽷\\JItAA:zeZTJu^@7A""V/ގ22t̶bտWzFGn>ye #gs\vua/~Z+GkH?Бe˗nf.7ٖO=XWWn_i|G_w׮[VcT_:2R.Jl݈ݍ~ޯމˬ,^H;u'(qyqp_5;Kk1R `3lr*?9k||yvVVj䌚u\%N Z.$bK U ݧj =q`v.{u:{ZD[;6,.K Dz{HSTd#l7FGQV#I\rJFvg:6c2iO dN6FfY?q!IW 1/TER݌ Ϡ ~=:M|?H1t7O:69=ӳQ.EDDok-zVJ\1(#d=0(^?Ncpv! g""bEok``&I\@A)xJ ` 15_jDDdLos-Y?q!x2(#d u0bKQ.EDDok``J\0> YoNم(]Aw0.Zn'q2(#d3H9D*(Uj݌ Ǡ kY\\ȧRӳ19=R mFos-"Ip7(S'S'G$jLWcnJdNtmFYOpy:M}3 _(FRDDt7\ƭv ?20b|J/x ujLWcnJdNtmFYO0 N%yOS'K/\]ru)""mEwVdw;AA;An65_j-^׉n6q Fzkߠ 0VbKQ.EDDw~00$xy,ڏwHfjSՈnFok```z:`hLNlK1ez ~<CePFzk?u{:D*(Uj#nDok5y/̠ u +:m֣f=qcPF,..SgB1ե(Wb tdyĠ ־A)jLW#.Gw7Xjw[AQ;Fl-^׉n6dPFԝ~/\]ru)2:se`Dy?:^.?J-JZZtn܊n'u0 ;AnFգO(]م[mFV4`L8Q#l۠ 0"^69=ӳQ.EDYjtis F,..SgS'|RK1dy1(#l uODRRq9Q?vRǜAa۝AbjSՈnFݍ[eŠ ~l-^+݌j+mN 20neqq!:49=ӳQ.EDY7.Ǡ ; ώV41 [7(ҩhߟH0r|5rDwn\ƐAqb3rV:OeqON6(0־h\N49Icj38#w[3c`\&"nDwqe` lwN| 3(|mӳ1x%aPzk?uCθ 20 H} IDAT<ePDss?ϞL1c\20&[ex1٩߈n: 20&ۃ 8wjF=ͺqe`L>F!u#hjSU20 XoNx!?F!u\~"JZ*zqn+u$aPN{:DPru)եnFݍ[NƠ =S'R<ɓS'pLN╘[2z ~48Re` iŅ| 27K1U8 #ڍݸf=u 20 0JZ*d{nDV,84e` NDb$fP8z:8r(Wj$K ; (]مzh7Vbև1ƂAA Ř3ݸJVSg42{GD%p*(Uj݌61Fa Ghrz6]Žh7Vb~#Y#D`^R'[R'גOD^?󿎩I#ǍOXo=Hs8/ ojSzعa+1%$NTP+1rt?n'ubPxzk?u0r(UjQԢJ+s{-K qոpz̼d$K ub\ZKn܌Rg z:K*[;sJ.u0|S'"IAsGqjDgODRRة߈n: 2(|;O.DBdN|mcSg93|۫Y/q[A_+N8RpmGI1LS'مx[;sc  L $Q8._ ׮ʠ L[R'|x0,3r򓩓!dPx&۝Ḁe2ʥ0Lr{m_,Y@bNOw&oNg|s 'TERvasedLavc%z[̠ O_\7,cD`8:P8oxps :>oq2~tE 0 >zףXI']B1]]R9p2 8 c2c2d$R|dN;\_~ v{>;X(0&0~>,NF0Y?u 78VŅ{>70S_8""nf7 ɜ=:r{eƙ3g~:`\}vY(l~^{<,zAfͽ$M|7}ꌡd{eJsZ`]n>bn)qq!g577tpf=erD~|1O̥(Wߋh7V"I;qsae1T.\|| n}ޣa۫YDD>~e1,i}̙3M0 vke>Yo==~?JTN0gONx!?ɯL1T^WgSg|vf+ZMc!:`}O<~Vss?~灙 b=e> *(UjZ~qݰ o9s淩#W'Oc2|a ۃ{9*7?ɯL1T^Wc33a8Z?6&S(6ޣ?Ik_;mL`N~+us+]a8"e^q~d F/V_ŸxXӁO\_;߫ME*?Qdw;`$|̙3Mp]n>Gө3@ss?~;1`$'z3uP9Gٸ+Ũo0,aP]T:ߢ*FM A2_\єI0,eNʕd :aMR@2(pNWVW|6nJeN'*S'GY8Y١k2,@I0(pň3ޣb`a9+ EUNUf9 c Pt eRvtaATU:^ş'*MgX:uWEy y&u@ٸ+Ũo0,@0(PN( U1j @3('aa㦤dPNRevh|ڻ⒯<u61(Go~u|\q7#;1uN]E{,xgo/fP$lyhH}fg0rEsLM[,Xqm4,@1(p~ݠ @y_, IDATFP{|5zi,pQ9xheP$ 1fptGV̮^?ϥucX1vڜ(sP MS'@I3lmdy3e,x%fj 7(eNҚE'=]E{,xgōэI{(LeNҚ<:^Pu3""bLM[۴<{Q\q7rI2'@Xҕ: N(::}.[\4~ozL(N@0(p Zّ: IPtԴN@ӆ(h߿)F]~a>ASGcc3aCNPC1g;^/}kn 7%uyʠ )z Pr˦NU*ko7swdG7N 8EO4wNyؐ1&ncjަދ۾N O8E:-]3!u7(K#W/ߛ=+S'AӰ9:(a353ӆ(h߿)F]~C2(pִtŮRg%_YyPP1(~*?I@n}:0\2=bžVDZÝ8e/]{ň^b@Ox#nÁxb݆ٝ: ljMm]_FfjˢcUq'jb҄A1i ąp˦N);ӆ(&~x#bϚSgp\~#PZvŋģϽںRxixiえx=""&d`yꄼS62u@Q:!/U/X}xtz ZSgp>|RGA╕3Ƒx'oŃ)I\68&}bP\6aP4~,:>_n0~yeĸ:,N;q߉X<7u'Gb#]sA1ScH%Sv(>7쎳cɕs~bҒ: q:X>#xt՛{b#s8 db!qK@Ӗ:#S'e g7=:hLɽƑs83?//aLlj//o֭]s(AlϦN+֤NiLy"b9Q^Y: Š @ZќKɴnYW.ݩaںbu΅;bΟ/ү޳mT+FSg Ő3 RmqG!.{8v`,}=lEsgO7ٯs^6HCb.go֭]S(bGNNlk,W]թJA^T8mzِ ﱩ+_9,ޕ:"=:! :>PP|nK/}kn]ؔ: H=f;,o!-Xz9^{Hh5.VM\q7rI%à @/գ3=bͱ`ٝ:+O,ۓ:<0-zi NթA^9:Nkoɳ_khΡttvǗi!""6%~6nJfP<ܙ:N˂ŻbS(p^|+c%NS'䝲 pZ2e,ǿqVLQ}yA^rx<7Fe([bͱ`ٝ:"y%\#u  yb`8#cjS^6'+S'2hON`֕:"=1nx#S֭'oj߿):hEkZbc3nq7ǂůNlj7ǣL@Ȕ>?7swdG7N(xezي [=lOL%6uNttvƬyc;u~Ǎ{{/ թ A^9:c;_^#:: zb-ѺՠnO*uB?&uKͱ7ňis A^sXp ֭]1~X[S 6u[UoN eR'},Sv(fl<7{IŠ @XќK=1ͱc)=՘5o{u {{/Dyeu$`Ph3(Qs1kS-]/&an}9:p1{3@9ZvN esǿqVLQ9xh$`P=ܙ:"7kxpٞcv>goGW:BLMUUfԶPiLy"ۃ_u}WVNH_a*RPd纣_D)U[?W9xat}U:; NPf )D{d^zsg$$(5k~z0uEf;&|2e{bWb;u }hO*uP@2e▋VM\~]Q9xh$>gPi]{Hc267GVy>ؘX:W]:OH`Esg@֮?}1JΎݿRzt՛SX: F>˾˸#;1u@0(\ \֮<{KttvN$::cWc]SO++O=mZK3:.KQ^Y: WH`c|OX5o{P^=$u%"S}`|5Xbظ)szADִL@2&t<{QgvNdsg#9/u@3(Ȋ<:bL>ئ83?֭>M6fp( #3O.{6⫮I=Ơ @BO4wN@ɳs?y+u ʡk[[KߚэszAV4R'P ,ۓ:CR'% Sv(ָ^=?kN[R Oh;o8}֭]qwOoLfT}}4q٤IfᴎcǎرcGuEFDeF>nuG<ڛ: =>|RGѡ?$?}}RU_&MSƤI =4̋#8,J} >ĤOʠs΍A眛:(-N@{y|o/O2y{M$0nU_SN3gFCCC}f[*{9pZfA]Aٙ3f g73R' mjɳ#lϦN;S'');_VM\~]Q^Y: (Ae̊\\wL=M:5o͋De=!,Y#ua8˨ E>3uEhLM[,t,ǰqSR%Ơ @գ3emDDĨxax>qY鶴mQE=*GR}+uEs#giw}=*M2y衕E,^|+""n;76n'NL\7jkkcƶmbfS'lj7GV'W:1=uEndfW`1JARǍ眗:(beЁtumظaC\s5 bs=ON(ZUe^w*ަW?qUקAuFqN0*Ũ|CP|c#oX\v㗢:uP 䱝{-޸Pv}%>5m6nFKzFeN(=ԴC׽ S]ؔ:(Pe܊\NSWяOMQⅵk㶹sSQ>=:! :( hO);3}6V,ΝթcP ϭi38U٫"sI]QTjkkcѢE#u9iP7 kdfWXQwaS(O4wNTT!(Z\sMvm466NWٙ:Ns#.o+*M28Yeq|G%E!^X6N:gTw{Hꄼ?ߗ!Sv(u] e11iZ (;-M7߀a+JBmmm2(P@hΥN^Q56uQ)e IDAT)Mm]Fe О:N !WVWcqo cc3xasSW.FeFeL瑊 yl@eTWaPS_ώn ,MGe tNΞQJmmQw~ yb`3-uyWVWcAo 5?Jo!,]/f۞:W3;S'i;A膘p4|cP{,o1*~gVDYu >Q΅;RgPN(:CNv*HUq79EࡽX2hEs.uω~&u' e{Uo(/1$uB^?&u@9A7zʏɎn ,Mz7e К<:==u6V>td)_5*ybLM[8m]ʪ8crADsgUV~&u>^X֨ IѺ+u_yyRٙ:H]E{ ~ڏώn ,Mz 'e +;R'UqVYu NCCCCvm JXGgwLŨ n_?&u@Q1(C18qyeU1v}Q9xhU  @ڹXlyh t| xdɒ¼?ם: /u:"Wٕ:ؘ9NvtCLeqh#Aʎ w߀a+8C3f̈?u%lS[WL%u_YySٙ:XO>+o?OWVqt 5-];x3RgЃjkkㅵk#ͦN-Xz<~eAIo>4%_y,.lsǠ @[z8v=:$|"u6V>t Jܝ[Rg= y&u@Q2=u mWVxO|گDyeu YetN(zq$.wE zĉOA ɳ\wviK=>O3lܧc­э}r>(k~ӫzۊ3Eso5N: [ E>3u2OUc,bWV9gP{,o1*[p3,Yl6u%lS[W̚=u@R{r y EcȀȔJ=jL>=߈Ƅ[<9O 2EbEs.u@zplҤXө3(qKWGW: =  3١1?QNA"+v=:u'NL81n;7u%nWukW @ـ EA[S'@&zb-5A"EF=ecOA[hQ466ΠM%SgLꄼS^10u@Rў:z̮>;4-i^e+;R'G&MJA?| <{K >*uEnAӘ/9ι/*MA"sXp 7c#11u 444SgP6uŝ w EeAԅN膘p6nJG}yz@MOA*Pj)5g6u@ٌ\OPZNغ;ߘ:2U[NP|b1a YDWWW MG`4gN*Dkɢ;6F=8cNje`4u@EڻT ^5d͗}2ujHlz(\LpCF.ԧNȔ Utg0N(F4u T2S_?7: F8q?pdxblzL\ Uo3*$?oItl :KgP`k[ȜϦNµgx u\m*ҡS'0Z4rKI}5S@fB T pM3 uM Sƞ?pSNL0WǷY+;S@&BZkS'd1xx,uU`ժUՕ:.{fo_K95 Sʳo~*srlA!GNt"טObP`X8'%u@>?_*&jH;x.u5yL1uBHchlao8}af./ܒ:!F4u d͟?_SGP~cNQgS LYcW;/TC55{!"2e-Ma tOȌ}˚Sފu 8MJW4vqZ|H;ߎ?<:I@mk4&>G \>@s,uG:r:>॑[b럋#Z[: >ų2!~0nķ~o:iX0': S|dD9ڷ<G/p_t<b bb )\]} p>eȜ/碫%u zeAtj|fʖW.nƋdjc֊+~̗ٷRq@٩2N@{"6oN5?M+N ~;4sX6M֦7bvÙUf230T[[>q uL 2U;b/źuXC>}zs=ۛ:.3xx,|d|S>bHC3϶~;.F̮?ĊN$c^%NLQrq;O>|ows~4uA*Ԓ/?d+}l=A2{gGP:2R'dJ]S!u340~`lfvÙU&Vc*lϾ g;#?oi1z9P6e  2ãeZs=7΀9? u WQSk\S3xio;MoĊDˋsmDq{{؁R@Y8,m32녃RL%Tӧ=S|zv,ߐ: "":!S0fdHP`ngs~4uL(gTow= jwϧ?mP},+KSg!R'P>ldfEp6+[^֦c1L:s$NLQf茎/쎟=#FO:&͟?_SG01)cN Lы>gNӧj5<<3gJWowSSgdFC~F̾eM gbEX?h::؂˟?:*Ѿ8}3`BR01Z5凼G1Xn]jfӧOH˻ߌ}۠ 腺 P:)85;#"v,Vñ.N=.uFZt(.n=#9?:nJM& DD7%LsOEs3bt>upc_%gǧ ^hgbhlaꌪV\*>}_NbP ,m32oogP7S'īg|}jS';c럋/f.NKW~|zmL1%}h)püt=@٩ڡ TUVEXR:>ThIo] @85>3Nw;tzDkp8V+ WO=.uƔ莍Q\/?D?V.59kc*V PNe ]]]ા wt1u0AZ_{~/ܒ:brlA33UѱuOZٙ:K.u7N0%ǺuRgP7u\QhILQR'dJCaF0Cc chl(-ĊXQ824rK|ՇbbS)-߿#n9pM TG6Έs|j0^3( iokK˻ߌ}۠ 0qQ$L%//McaW%˖^{^\ cAQ\?{Kq[s\uPsdH@2DD%\<]Lͩ2nZ!uLMql{<(-cVą"~701P(N\w.Ngԥ_%?oItl/?DŁ9pA ZbSRooo}ObbSnB9nG;8ݩs " T|M󕥩3)bVH륑[⥑[""v,V;,JAӱuOũS@ :3_gJgPRg4r1)pr)uP.6ql{Dn`x(VYg&zmϓcυU~ޒغ'^~8s dڶKo_Z-͵ޖEDD,ZȠ axbzD<)pr9uB4fN gbEXY8kf_帧/̌gۣ[Xc=qwv`2(0 łKΩ|M֮ܶj ;zo"Eooo &{{O֩qj3OwFF(EMoDkMnq9 /FnFnS3'J(.nCz49?:)Ơ uzLinm K\3m_TXjU*LXLlx>63RUЉ٩2nZ!uLYCc chleokmz#j͹hmz;MqL1|%gOsB SmK%K룥6""ł9~4=_+_1Z_WSgPaR'uyeZ IDAT&QMS K;0sl{*]9ڷ<G/p_g!Ue\,暸miCDDkⶥY1Iաנ ׭X,N8z|<oHT#}l|߻fmw;GSP w'OwvmK%_&ѡu֥NZ*u\]ϜmoMT u2%W?@E+.^߾/}=Z+.Is=Q| L%Zݻנ Pzt֠ P6'GS'dJMS\cstlG'x.uUY imK~\-msk/ݾ}i}k&ʭwpL>=u +Rg5:1ϟ{)@:aP2u D~0KV39?:*cP4FDmK% 9X0ǧQ*7x)eA,FR'@RVtFvϞ'^K@q%(Tsr`ns=!%_-t?ZuuL1(T/(jSUșbLi(s}8q?H@0(U.^AۗGfR`닡hmmMBX}#>ONT/ԥN56 Fqq[xh$*AȈsrqmiCmksr`uv튯~3N' 3 R7: [?{Kq[s`Nn[Zd<*ޞxcSfX=>7NJ5OD=O_H@ISMK&>_Kv~lŘ TR3ʮ*r RTH@wĢSP $Y8'>;FdtwwN(R'TZ7ݱ1ڷ\c>u Ơ YK&8#} OGpHizvP߿ K3*qt1uB7N WǷS d2ΦƶNh,]ey\,}lJ\O)iȰ\cstlsWߕ: aPʠ%_cN|{ǜ(4{ SA___(8:GNچ TG1:se+LۖΦ)$rww(\LT u2%W?-ub;}h1'u fP&gdz;ł9)@}}}ߟ:KTFWM+p}D=1keg2ʠ Lܕ?:; ͞f@-__rwwY smN)u @h)d+]`vLȾEP500:nZ @;9bPjjs`[vF1: 1(7ɘ ~_N@FJ pӆN+c3 vr)uB5R'PኋWEvG~)dA d3慃R'HsLͥN 4D1w]S2pn[ZoL*PۭsM&8TGS'2;aP2u XXvCSH̠ ܀|MsW> ͞:@5iߐإR)6mޜ1pP(c 56G'bR0A\ ;S'lQASI\}}}l^1*\WS'dJC~F Sg0 Uk:RgXȥNL$CC3lOT RS9)wF=ķN&\՘:([ȖJMbxx8u eֻ(WNT#g2:>T~ޒ}4u 7Ƞ \ڶi*600۶mKAN:xBiN)5 pEغ;殾+u 7 \mKS'enMKꄈ===3( PVG_HTe.S7:> Sgp U]՘:=H Π ߟ:nS'HSLR'5h߲3r)\#2p-O'>VHpIT/S0z{{S'@ ^LT#ͩ2nZvG).^_yKSp =]j6KpCCq3@ñ'uLS'HSLsQ9Ѿeg]}W>+d :WMKQٻy`` 6oޜ: ۛ:&͐A#mN)u cGcS 2LIB.u‡z*u]R'@f9]L) ,ccg;"טO0(WВtYۭMh۶mӓ:0883`<:ȸ u2%W?-uܴY+:}h1'u Y֧ۖNʬu^C+ڴys =䓩 S.NȔ 0!D=Q\ܖ:0(:?2w_oT ޞ)# W~Z0hD]}W~à S'>VHpURɨLzr׮ 0<:ȸCgNȔl?|ã|A\ꄏdT .2LA*JMmh߲3r)SAv!uPf6N&JGxr׮(J3 S:!SR'@Y/S,2pF:([S'\Rk::bpp0u W044vJ3:^:!Sjjss}Θ3u dP)X׬T*ɨ(J3 s)NȔŒ 0)rq;bA}S2p:m6N.Fe?L:9RYϷʭ6:&ղR u`/oJp݌d_lۖ:2AM+NI7wѱuOS2p?B`oHpC~;*ӓ:eWb`` udɑ+\.u$$:;Nze*~OFeڵZ8JشyQ;udɑ R7:i,Ή-;c)U͠ \Ł2hIp6m7oN1 ǟoڔ:2șbLoLwĂRT-2p?U`kHpO~2SL۶miR'dJ~ZȌew?7lOP U<:m6N}}}f͚LRzzzboOO ȼCgNȔBȔ{"טOPU UuĨ T1(qth(X>z`lڼ9uT RSK$:;Ne#oNʬ%u„*Jiؼys Ω*q3bz:!S3R'@&5DQ\ܖ:*?MYۭͩboOOܱ~} N q}ETJHSLR'@f}1w]S*AF@5+ju^CꌲkĮJRцP('GsFM+N[Xa{ fP`$uPf]}qmb'?CQodR@f}co(pc)NȔ P1殾3ڷ\c>u @E2(''SgeԶ9uBŚWRTXf1R'dJ~Z(ū}h1'u @1([ Nʨ֦ T*Ewww9688w_GR@E:t|vLmhL'?oItlyKST2p`,~2x>uP&]-&@ܱ~}l޼9 _OOO^&JRm6N2ht>uBꧥNklcRT 2pl֭Z2{{zbeؼyslڼ9u Tb6uA)NȔ Pіox4ߘ:"~4uP&X!uBR)c͚5ӓ:'XfM¿p\ N4NȔ+f-cc,߰=u@31Sgevksꄤ Ŧ͛cٲeSjXfxx8XfMJVϭޯn/6wѱuOS2ˠ \s;:( a]O=éff͚Nkz6uAGS'dJm}c*yK}[: Oϧ&XPniJGb۶mtٲxGbhh(u҄dܷaC_vks F/ԥNȔ\ Pu\AA_}&uPXK)J]tٲ}߿?u G___ Bm :!S *c)bPn__WJL2Wmfώ͛7`kcHʤ}yS FS'dJMm.uTE7 2pqwRgȠ̵)J'VY˖-Gy$ߟ:2y5{vlڼِ I @z:!S3R'@[tXa{ Lkdk:@?1xx,uFꊮDWW[nҎ;<<}}}}}}qthhҎ SwRgdƜ&Rg0zзwΏNHƠ L1')u0A=oΨ]]]E{[[o1c``  C``Ρ:ȠoiLY`J=OOR$KKDg[ckR%" LڢX,FĻ3W300RٰC:1;uB7N)'?oIoQ`J2(މ;;:Pnnʴh~C FR'p7IH.$ X~&,l;"uT[;`nufe궸{9G{nv,]pGi;:ҽ8U-[Q+ 4 I<z?|1L@_p}^߼RV>!uIeXpU%X|x0YqY]`ne =^:!TW@*e{꘺)ʠ =:&K.N,^ ce~[IiY.-1;Rg20^L ֥uAtN+'R'ѰQɦNqe`ݷ=HM<2u@ |&N+ -73*=20:돧eWN[#r++:-ƙ?l)#Ơ R'% ]:!TdR' S;9ܼΨ P ur(upZTFM4u@^jS:C{զN+%eQE>.O0 9pd xg .KwgWƌ@:U:!̥N>ܫWWVe`ݷ=^~?upZMLw.:u^;^:!`P %^}G acPFؚS'ui]dKSg% pWeꄼRRZ:8M / [elsfPF;{c3sк.u@^|]UJE%ycϠ 6GɡYj]61u@Xqqh:!gR'g!83ܼ.R520 :{RҺɖ K.N]UJY Y2*:20JM֥uR'ypWeꄼ22:8eXphXAH{(֬?:8C7:`TdKu@{̠o++:aFe|fPztKw<7upf4UĥU5]@/OW*uQP7S2_{4upV֧N5Ҹ@qhRꄼRZILU\xhXud, 8=G*S'rHYʨ 0 @zi_|mSG 4Jui] aqÕ1"uP@v:!gR'y,Sj}4,\: @'iXjja 8SR' @{j23(y{(n_w4upf4UĊRgM3ڱ ye2Ǜ{꘺@3(ym=3pu ZM4֬:(@{me @sܫH)2n_w4N>ƒEqEթ3m5Č@1&~'R'aFeaP\gPܷ=upjJ3V-[mL]1l4,<.nmeS"bP _O|%czcE 3ru Q+MkS'䕲L@[ n^gT6e@~ iXjJ6"n1uP3(WR',8Ө 0l @xi_lx3u1V+Rg5Dm4uPںR' &83m:(peܷ=H|5NX+bI3xmꄼRVILXp:291({(x c\1)7VH=3uPv}'R'E,SeT8'e<'~'u1֬:C]zQu,YT:(`R'䕊l]fT~)@2(GɡGXbR\z ?}oN y":(BeڵѰpyt@ܷ=u1jJhc87?;t^ꄼRV>!uP^ڨ pF @3dQu\zQu dKk3#uPMW*u"71uU3aP ؚS'㫫Nxm5Dm4uPN3JiE&u0\[bw @i.[:8; DM4ΫH|Mƛ}sOO`X?;uP^~ԫ3Rg䍒Ҳm8{[ }ڣP #Y55u@@:9s?lY&YQwFeQZQ~~5•k?r3>@^ؙ:ee=1>ۜIPvv<<2n!ZN\iơHt̩LwV6ΊܔQ=Dĩ_uE ﯋/nI"2PĦM.4-u@AzP_ WIdQu3vL5L5LM OtWWFMgD\u`ﰽHŤ8-Fe`l1(E+ŗMP0|=zhlڞ:0"n!V9m5?]{zRgnzcE RgEGtkdgE";uvM@_U׈٪DcLͨ e` MbyC}Гb[_AM4ZŚUScFSE՞K?OmKUUoKG53u9%g';ם#SgG?HpF`Pƀ϶d{SgwCOp,u #ҋ㫫8\ 佻8w=f @zmC|3"7e/R'DY&3vFE(?!chp`[&}Ս+2P q⋗gSg䅇6o|pӓ:Q4"֬+WLJ^s'MotJSE[sEQ9yFNE_W{ 6\%e#:#O+߿7u0B Q-l)Itt C7}8!!2@>jO,8=:( ?0/,N={4ui6Ί Ev'&{}`<LfTWi.[:y}DߩwESFUG`vol>q{06?=y,jKcIiزD@zmC'ƀ=/.Kq8w` uEE.ƕ@9F\T}i6ΊL]C۽-u 0555:=k6gRgw>lD4"֬+WLJn\xf͕Nƀ/M1,2un¨~aL83Ս3q/>|02(çfǖSRgC2-2@>Y32#ȧeNe `F |bfKLGxR֦F-)êk0C7l;}93'c]1cJEhHaLs6|,u 2%t'Rgc##fdtwo~ttx9JKJcByJJchwNuÌ(ߍ@6ΊL]C۽-u 0 5559UcLu$^?%N.Kp:io|pLCxez`3<<2^|ө31zƵGRg$?yqd͋1hSgc+)9(rkSGxfy.u 9yh_[~ m}\d*JR'cВEձ]/u 'jQ3 [OzSg$3{2wo;~'|%zߊ(MԉærҴ8xkOqMMMNY+Sg'm/߳zFMM4֬]ې::c֟,NtNƻfRgchwAmD=%2UYwcN20UgK'E$u ijO=/tNaj]_dQu`yn{gͻSg.v ` wJQ0~_̜ߜ:U֦'N-L://߈m}sÎ?o>]G͹TgFnjɕŖm'RLo^?0 g=:~+%xfStbWvL.suN[y.&ξ8ڵ5Sg`\SS;#[mΤ@k8=:~GM4{V.u=Wݾ'6omO$#9E,ڙQ{~K_ɩ>VwcN&2@|jVylY?%uxn{g=cמ).:{fhH]즗]aYs˔XsMq&v#%S79joyo`,S: bPk'W=o?8:N[M4֬]ې:8]8=:^Tl:nZ{$fndg7.S{~saT A ""%)1urY` {h=`]zQuA={ gUƧNƐo|p\{c)0,߉-N֟vE벉(Isk0;GҺ+}bdtc/H۽-z呩:Csuq^e]mѸ&3mrY/ۣ<712y@*)+ۯm90kjjiRUgK'E!WVLosRE~|\qImg]!dK㙍~|ۣP 菞mqpql9z0sЋţ[Sgdžm_kkǏD}幉QɦDIYy׼4~m{w*MeKbR]i |'}OlyD(x}}쭘T x;0<@_:C}oKw<7uxqpql9z0s/NEلleQdTF׸&N[u$~iZhk0}O)0&4Ϯ3 ;c=즗D`SgW3Gm4u G:xd 3a=%3Sddذ:NfP8c,WOJ$՞=/u )5xfhS:(Fe`t čk`MyDe` 0*#4˭M 1mrY`=h#oJcN_;Sǣ~|,S:( Kj㑧G_OH0\C)e֓1'8۞c"ETN: %eq^xݞ:Ҹ&شe|Ɗ8w=f "653V:(]즗cמ)P~3&22u imN2䇲L6jg6GK~(Yb2{2vlXmR@)rkSGPqٖL`ut __7{$u ϶oE벉S"(/]QOKG9~*uc2@oG_S8{[ǏD}14p*&d,M8yinOEe\SSOg6MRg#k0rӓ:7\Y=+uPDns_@oǑwb;u \.6uP^թ335)<"u 0 ߉G:W\R SEuĘTmOyɘ P,~'nU Cݶ/ڵ5n{"zQ9iZ4]elL}qkk cP6G&[ UNNCG`,ص'u 0#ah]:1~/'D` 5翟K'N[g2suFe,kjjz'uP<\;9tqe c|'@ɖ3GN\gbā#3 oeQ?[:ƴcdž1۝: A`TgKbSgc=즗D``9o|p|3 Wuwmqˣ90&3S֦CeUqG0&cK_;SKj~||9K'ƿ#O΁Q3"y\c2@yxt8am_~qKٖm+s1~3*+>9@i_>z~:ůyvel1"u ޖx~Wo ('82.̨ qMMM癩 ߴe񯛦>CMk^?1c>cF,hiڈX~:::bΝqݯ;::bFWxfs;h w; MyDm:Zwc0eaar iii˖,X`A477kcΝcxbc3j]/>@NauÕݳRgyWP42uc⫢~NNEɨ |42Mb91h]",YQSS3 uksœ7s=g`FCH{}q{0u 5L5LM0?@ (ZYѰpqFe٧fǖSRgtdZ[[c 7Ċ+Fڵ+zx'S@QچSgEk0|N񮙱rŤ#{OwMcB-˔eR@Q8MyǠ pcR|l |Ԙ̌㆕+[oQ.;;e`9$wƍwRiɖ3G˜)b[w΀1~⨟wqFe 'G$u1}zY&nUgOC?: |ay`ut 7w=fXͳ+㙍6W:`,_f?uYee/yS@2*ˠ pNX\NNdeH߿?z7s dKG?3*Rc;_Й:> Wf1`̙weѰpy4,\ƙsɠ pNcR|l >xLf͚5qۭFMMM]woߟ: Nxf|Q{)w͌+&u/nK|Le2˨ Zi.[:(Lْ@Lfɒ%̏~+VD&IX6:ZZZ[o3fΝ;ĉIP0?W+>:#?!n!"g^< jq, )r ksI#GkCe,k7;'\k2qo S55vvztL;U tcH'}N7fcCb j 9BD}$$E\^G:)x?B󏃇9Ͽ S♭%uS=Cg$u.FGDhOz"NFUnLL-;}vdK]S )2e[~kuSg@{L]]]ɟIoQWW~b 9|K&.E5ĉGés(Cn>:7fΘ: -O ˯,u> 7?y_Љ#qag>;uQqu6)U3f?OEaoէбkozT74lLܼ18t!up*2٘6?mQw9ss8'u$aP,Iͩ3u׼CիK_RL:5uV~8#SMNgΏ GitI}a0u %j U_{@D7ĴyKiݑkHŨ jrMM@YĭT9&/})d2 R&+0>`=V<3h)Reh)qkb8sw6u%䳟lǾ0;fΘ: |8>: c#1"`a6u P9,<,>:?^ux8~xqnTT| *kSg@Fe(7W͘1@qw+jc?}>n_bT3O? .LTvY|>u ƪt쵳cON5O}aV,]T: >s!ݛ:H SM1m~.2u s`:22%{Y3bLGqɌXretvvN35;9|#QW39u ȟ>|/u޾s(0dc>u=Ɑ[-uNId2qW]eT~so=CqkR̔ItQmh1%  oܸw52)u@A=Cg$uɗx1|7FeP&UTƇox::U3fx+uP<Zݵ3oǶnիW)i===qwD>OƃkRgcGy"uCS0f'ǃO6N(l}eߔ>;[ۢ-*2թs`܌[Pߑ)0. ;P6޸wغukꜲ000+V)PP2/.2. gOE3ooL8'MQW39u @QhLֶ6/:ș1r?u 92E[02XϨ.ז'󏾑:(Ru׷Dck[LLuFe(EeESCE (y^;7x|XlYꤲqG)P9dc +}x8퓩Sӧc_eH` SgE"isє[R3*@1(\+cϣצ?}>n_bh8/_;oR'oݩS rcU1?}>f_|'b`|~O5ƽˮIP2`իjh d)"[ۢ"S:.P+kkSg0(\}0>}'@x[?]ϝ81uI@~Fe >[:`mz|'GéS-7]KyX:?jի3bڼ\,'<vnJWlrMM@EmvR (iۿ}2""o~3ZZZNL&O|"~DoooHEkI]1uӍ5=bVDa N/9cJ0~Ŀ<'9ƨdSgEN8RW"W͘1@ax[6PҶz=<y1GDđ_U2<}JߋɩS]ض/۸2\..3d 0Q$~x\ Le-["Sא:ױgvıwbP+#גro#|}g#"իc֭XFe b٭ݐ:`Bu<{*:y3:=e\5Oo~1fΘ:>s!ݛ: ""Eck[LKqp @kU▫=WM s,ŮN_E\*27Sg$a\MN-7V([Ov }SgL}C4Eck[dR2*@12(e了h_R^wԶz=.M@DlEck[LK Ơ \U,n:sUP:x퓿|}嗣9aWb=DGGG Hf٭ݐ:`{ltlqw͵uQmhܳ/ux_hlmֶ59#Ss]CE,nD{:r-: -n_R}'߻zulݺ5qWb`` nN 3GϏS'][n[&.jS>m;:Mֶ6/:PT @ xYsA#/͉RFe(wS>u5S}Ltc?9[#3\7ͭƪI\}=#q-Smє[912 2Pj=WIAKws#1{ΜS evC }x8Gs`Oxڈk""bh1%fΘ27K;RgֶhlmNLcWP @X02sѾ*ϪL_ S0nƨ'|2u Lފ'?:޾Zua\ o#'"٩(5Q_zK3f:UmvRf}Iu,^Iqb…SGk֬m۷΀$2/.MemGH0*2hZrw4E!u%āM3W `veZ2qW|Y~"^~;;u LSnJem5: isє[u`T3 IDATrО-WG{*\o[|y&ԩS;E"ϧ΁ w6xpmS([]=#:bW|+2 є[mQN@il3Gā=S ""1c[#\PKb«\U@:bٲe3 v+W΀$^M1sƔPv^|\ܹ'3 JE&b"Sא:shf220FsUhUESCE,Lx #3`rsmu Lq{ɩSl[CRgֶhʭYS(bFeHmrMMPjbŪF)qM9Wdg \}u<䓩S`B=Vw-KeWŖSg#?mD٨II񡅷k0z.ue3f: ɂٕў%U1VeT-${#uL{S̜1%u-O }#u@7DSnE4EE:uEf8e} Nf'E{*r-WG{*j'NJ]G"f~5u 9s"ϧN u͵y3SgL6;VE!uEĨ ),-]L|&ϪL~<+(v+W΀ 7Sg@I7.(Iu׷;VE SP$Nx*ܔ:2bPPh_Rf"uPήOus Dggg Pӧđݔ:J֋;$u@7WǴT`"d-]Lܕ{{D`ZD!7/Z|>u L^mJ%iGHP6*2hZrw4E!u3;;RgP PRsUhUESCEwSP`Ws\ PS>u5S@Y?vw (Kmu/L@:ss8'u%Π Eh_R^wRߙq_ݼhQtww΀ NǾ0;uy+zcpB Vw}eL@2*x3(@iU▫=WM s.MG"f~5uh޽qw΀ wo3+ε?Ie)"[ۢ"S:1:r&nYC}GRP&lL庆h_R?Z|&ZMi5_577GoootwwN upܻP2:;i ~ntL?|' ]l,TQZx[qnTJU3fx+u-hUG%gU;/RWPz{{E"ϧN ytQm ( k6ֶhʭYSHl$.FGRPb&lLIx`U}bGkuޔ~r4UsKDՂ9{6:;;S:sqkRg@Igy@!;FhOT\kK@"l|ߏy..K@ jƌ  +=WKb9c"oJ]Ao9N Yq22p%^|\ܹ'3Dyhl3u -SgPB 0aj=W=W5ՓR'L<2\۷}k֤΀ <}JJlyb0>3Ll4-;r+"S: vSqh2+#גYsқFd椮̙3'΀ YqkRg@ѺgC_Idc\̼cUdR0w=/2-DX0M  ˂O]@ؾ}{ܷfM Pӧđݔ:ֵmGS'0[ۢ-_: rh8q`O A؂ٕk]Gdxes̉c3`B=xpmS (:zF}3'u׷;V(FeRe,Xru窢"u@0(%ؾ}{ܷfM PS>u5S@QҎ||qǩL}C̼}u4ޙ:q4:r&nYC}GRP pQj=W+W:x͙3'΀ kM3ܳ/u`d)"[ۢ"S:q`T+aP%FdƊA.5kRgG:ƵmGS'@E&MK 2%h8e} N]}-)Š aΜ9q7uL^mJEɮoc klmwL]CƐQ.䚚#([2sx[Mf'(=/uE.:vJ"3M|;qॳ3HlHz"FoʚIʚ@|+u E]DDDmvR.gM٘:`veC 1VeRPĦ76ƶSg:3M7VN7c̅ё3q8șN*?P,&UTƇox::5)ukعy1TL]@[bfss p:NNt4^M@9ǞoZǞ#gR'p*21w冨dSP *bQS2{Mn ѹ0u]é(#CePvӛSgP$(IC dݻzuH+8: ξNbXpwڹ9Fxb 3(@kjj6`}Oud+(buuuNX욨H?>F=V JPߑ8D#;cvTd-gGxSP@&`=xa&uN.,_,u$S'@xs18t!u%ā=Uqhhm3( eJL|¹ (˗/OIt<{*ϧé(#e ܕ555SG0>j;̈)WN&g#L&==q)0Ξ{+NlH8GSgPf'b$Wg#Sߐ: w6IqnT:vPPΝH]@XlYHowNGRgPN[6DhO~"SƨxP @sD-]6ug} (˗/OI3 .c2n2&S7}zQ27fcޣCq]CE M-H]Ad2N.?x>>73^::~i$'ў7F!u@YʚɗRȤ-X0:PJҥKS'@;^sxé]v- ?ړ:5s>.u(AO{>|ٲ ]N$ƫ3=( M-u (15T⅙s'RP"%u$dHb_Hheқr}]rcP<>ugǩ (!.]:;ϞJnϤNKfX jcdN2(PbsUx?eCK Pƶu:&\WHleҨTLJ?1*2)L2%=W5.™ (e(g;Sg3CRg3,02u qӧ7(N%թX#?N]@:uj΀dz=uL}#`LXbGץ`(!fR'pH]@ u ̶2]gR'0,0q[wJ83(P"̮\SPBh8qw̅s3`\bX1OPf޾*[Rg0 +S'p)~'^M]AhiiIImzw )P>NoZeX`]>g`( fOI%:S'P"cfss HS`uu4uL82OoL}C ƁA`ve.я_J@ i Lo?: aQdS0 (:NNu:͋ 3 _ ˼ș9%!;}V̽g} ƘAQS<===3(7u<{*uNxUqeyrC ƐS%` \:;S'P"fΜ::oTAyu#CqeHcږ:1bPf] N:y3ug.Kׇe|sW[Rg0<D.HBhiqCS`NE2WʼnO(ZN:+dPH@KI PZ:ȩ8saT+7DE&:+`Pص+u%bҥ m^OcjwDu?ړ:dϊjc AH""":::b`` q @ixT3/r..6w$nYl0,p _sWnHe2(Xˏ;::P*n]4u$w6v6uN%#2#9EhlmKe0(P<uڕ:dt<{*u]gR'@7C;7sW[Rgp 9:+3(r--nށg PVzqx/7nwڕR0u P0Sg3:M3; 'L6u ɠ @pS1@{+_IP2:N+DcO7JPg{֧"(GS'p޽{SgPZZZR'@A0(@0p#Cqhx~aw3m^.|t] .A#gS'pn_ym۶D% P:9:.ۓ]18t!uSqh8eC((M-uà @JRmHPzƱ׌P4uqp8eCS+Gv2%G3T P #JB pYv8uUqhf2?wӧ7GE&:  @ I%Z7>}۶% P|ƫ3wquq1:r&u@Rj2̠ @ f%Rp7oߞ:u?:. {cO7JTvu3xeJO)meXo8pI<@Pڹ)߼*Nԕ: ;)"uƠ @ O(*3ˠLgggݻwkJO pNGRg`T76-"'u@s>6ϥ o9:1N(z݇ P;u@2(Px7Xy'Rp7uP^|\AP6N.=#FGΤ6FE&:,(aG. ]]M3v55lOOUWH` űwJ0.2u OmLP ?z>s!uƪz>q.N}ؓ(\s:uȩ8sSܲ!G{RƜKPv Ǜ^O8 3(`e;xx8u#Rgv-1O0rwGck[ bP -O =rsEGqX Pz_;:վ @9q`O8̎9:`N:l( 7$|>ƹbu;uS'}_5:2Ǟ6Nx*uTMl`Pܷ?^|\ Ms.۶o{c Ūر P; @9}B2~Sqh8eCb`(#Cb>2g<Ͽ%5R#ea0^rwa,8c.&+^ IDATM\c.UO&0wL9Y]$;{B[=xf%iv~d-ȍ?fOOx<4YrUWC73con4A%Tb /G=} @(Ra0uuuKnIP ԙƶhO/i'U___h}?NkT9t n'_ٕ:̺1{Sg42uȱXQ 2ov˘SOPP(΀vR'G﹘:2R1N+^r]}'u5[tu,LP )2e5  xt N7`P 򣞋q}ڔ 红wǖ(>:`2iq]R$2ų @eYȕoMADo]Lg8uP 'g\.Rg$2u2מ\n\CNprR'5TϋuqKSƤ}Xt5Ǡ qH|RgԽ> GAd}? T7;@) p=P=b̺5Š @Ѩ @b73ؾXC5wc\ \H԰cѻcs“Q.Yâ6Fca aP_1*֧^n8PM={R'@8K b9t ^߶.N+u 'dwE&KP FeYduڵ14445T P5 Gr NK8xuQ8џ:ʶK9u@M0(}:目B];5T!2U:Csѻcs~+J9kƭbu3^S>J@I)~g֔7 SԕWB t]g D44Dgg8UQv{MUc\ٖ::~[nFF1qjG\T/ן\s~kDvM3A~+2k-v֣GײسgO ~tn0zwlwE0:#2iqCl.u @U2('2*0y:WYB!GchhhΤ} =qp8ʮ)%ݷ1u@U2(Uƶ#3j޼-z^___sV=:ભ|ڨ ?%n5ݱ~q=;uWi tn0zwlwE0: ""ݷ!r SgT2\Q2`i~vosI穧J>p!uU;FOܾ1N+u @DD|z22\ aP11*0>uBݴiSܹsBfr k2KCG1ե\*ɗwO‰9@dwe32kxtػwسgO PN`﹘: F OF4:c Ţ6 e&狣mŅ)5g =룿7V[N` ؍@;s@m]aYŘq۪Ϡ ȱXQqֹmB/ qFeΝ;@ ҅s1u(qt3qQ<}100k֬Ir}I=:jA&ß:G0u@r8fONG-#ͥNjTQ8`SPt׹KUK%v+WPҎz544裩3Gcp/^߶.N+u Pnː%@`|c{Fe%qC)iC___X"vԣM6E___ 1w]qQ8`eRg$gPIaTtlK'իcΝSS۷aB>pV<},zwlrk'`|/Xۘ: )2L2c饭""P(ģchh(uNM۹sglڴ)uԬKNƝ,3©m=S3gcmRg$cPImGRgTΕm>{;wݫWGꔚ{,u ؔK8\W~+J9@ YvKdߔ: 2LOJ6(w^Omߞ:ݫWGPHu}Bt8}caFd$u@et狣Fe7*S(bӦM{b`` uN3&PN 1\rG=;D0:[b}SgL:2$aT|ꄏ+VoORTjBD_m]|eWYŘq۪ʠ :+R'VB!6m'RT^{͘ @ }Br]qQ<}(KݱpѢ144:ܹӘ @ 95X#njcq qt߳Q. T&;-l.u 0(@rGͧwQ[Ɗ+b޽S*Sg@].jکp?u PrĢ6eFe~>O0&'kc=k:b Ċ+{;wN`xq(u@+g\NTYw|>fqo gPaTulKpMիc=@Ꜥھ=V\}}}S͛ݒ:xg:ny1^߶.ξٓ:B3&A*/GejXhQ_>SLX}=iӦ( s7(}BS.s]q(SU$KnL6:`96|灻Nn۹3X"VsOks&Pl}XhQtww"b^1&_LPξo[gIT\-辍3&LS>Jڑc#qjjZq@Pq100۹3S٘?~dYfΝqǏ~)|ɴxdԘ7߯THj߹52\$ :F0Rqv(7|/u@Ÿke[q_ -Gk644;wEţGPH+g7NToTSUb}#ױ0u3(@E3*-_:ZRgLB۹3X"V\Om@KԞ>kv$ۣ3:;;Xl٤^?^={Dww^?KZSgPC{e@K#^9@9|W}'u0(@U1*Ի…1M840|;ɓBa\)ϩ!GZN/N*dz]Y)@*tn0u u3(@1*Իv}\ꌊ}ttwwGDɓqr``Bۀ4-nCm j^*7:1j_<~isdoJTq 3AQcیW0#Ԑ]b A&ŜU_LTS=?Ip]Sx#3X[R'PC. bR1{&zwlRa0uPab̸mU bPt8k76*ԥ[bUse[jS'0 'q燩S tds3AQwOOPU/: rG=;D0:촸̠ Uͨ P| Uch7F,Ǒcޗ5}qp8)@h_,^:rT`9u Y5u ^Қ:C R1{&zwlri8uP߽.,O0fe 狣h`\M0i==u@UXtZj_L+׷oN*wE&K0&eGͧufN wlK@I),`K8\W~+ʥ9@BXͩ3Ġ 5Ũ PO/iy-3* X5u5b dg׷oNq몘W͠ 5Ǩ PO==u@E\ٖ:b(q8|WKésDݷ!r Sg\2Ԥ#FSgLG:u~Ơ /|ј=@=;FO|zCNNYvKdȠ 5'}P˗Ʋŭ3*]+ 0>x8utn0zwlrkD7[b}Sg|"2ԴFeȚ*ҼX`9\L@9b|zCOOLYw|>fqo ʠ 5Ϩ P|nzԹ2:aLߤtn0>!N+u 0ݷ1oJ Pl언sE[ S'P#v: v]qQ<}|DŶ># 3p#sn89ޚ: S~OQPW񃗊3ݚ7RgTyϋ\.NJK8ݱ%J9$h_7=u@L[jxO)苃77{R"ͥ2%2@-zd G=|q4uU\*]Q. &P&;-~is 0(@2*ԚΕm1%u@rٞ~\H@;FO|zCNN&Ќ[WŜU2Եǟy?8>:`|Y{d Ԁ ãb j@`G=:@W\aP:w8k76*ԌG0sS'P:s8(>:XvK 0(FeҞo~aF d\g>p!u5xXz~:[b}Sg2@myd <ƨ#q R1{&zwlri8u0b/X:serT`9u u\:ZRg$s7NR'P 'm=Sqv]Rgu̠ 狣h`\Mp]xsI/̈|S jR1?G=p`db6AWOښ7*53S'P~R1G:bSdƭbΪSguʠ Fejמo2ԕy-ѹ-u5.NNOOoS=?LEca aTv_hVI=pN[RgP{&zwlri8u p2it@j]#RwrK{SƬ=p)޾:`my(a*]N@+/Z?57ZgM\L?`Opj{NL{6ufĿ!u5_\JCܟˣ1IԱHjKq╩s6(Ra0u P' U8rlĨ PnWB :`͋[RgPJb"""NĊlSt9ky3ξmso95qۿ_-NAJGąѸkek1sK{6usE[|kԀ /Ƈ?:2)?+i`x.54G[Sנ1:MkJ0f+b^GK Ț\=OfOsI*qt3q(S`ƭbAo9u<03u5b3x|FK<;+}tξSk辍~S t Y؜:<̘ђ:`\q IDAT`e~lS<7{jl9 Xtn0zwlJQ&;-ݒ:qe` r^BPKn5#L@ qc~M=sT9ݱ%ʥ)/XWK0w@x䁙1%uÇgNF\klgƊl8V+׷oN`"ױ0uP @y|ͩ C3\=>wY֌76CMTu}ϦN`-Rg5Ƞ ԑG:ZRg\?|xVRgPJr3gj|y\u8(SW!qK_.uP @y|ͩ C3ſ8gkSbϜX5+>o3^J\9 jA3<03-nMpMYўwS.SߑigfecۧёioR.[/<ppWd@ 1(u?Ѽ c6%0'u5W':MgNk|9e\gxxd/mN2P:Wŝ+RgoN@Jz/M5>%=5e&P<},zwl3^J3n]7uP# @ahG:QLu;2 xvV67\*[/l^x2ʥ9XtN)uP|2Tʶf*} Ԑ{@{G)=55% I[/gxx7dҵ[Rg5 Ա7I\+RgP#.a\~rꌈ/=sWڦNO̡RAe1gՃ3*הRG@{S&uik|s믞z]r_inhNmsS#q|%uu`<gRa0oYIpq͞)KT@Z_#uЬ?sc+q:743S4N9t zwlSe-*֔RG@{S&uʶ4F{[SkfTrM/l}|kĥ##3~S+mS"!~>2#WRPFW9c:Ys~zDCDD 6<03\і:#E{)u5WNj_k͞ 0ʥb¶x'\Nw3\20?+N0N;W#L@ q˩3Ƥ#hggecq0:;6G)?ds3*ӔRG@X|j|vy6u5cJ.\bx;F{>:r/wʩ3IG1Oٙ8T+e#snќ1r S@ds89SUW91%uPps̟sq:ݗĞ9SkͩSqR1za[“SѾ`y 1xg =GRgulx|ÜԘZ\cC|}J+MsqgOoRa0u Խ_l.uP%|Wmj邩ڹKc֌)31B\JqolsXm.Gq4ujx.z)Z?57ZgMu+Es8fO 4*wX7|90ps,_Қ:s'lSnl|cCjTTu}ϦN6njVA#FR'L|S|3:lqk7=kz N#VL_K?\cC<>%=5VdRP 'mp?u ԥLvZ,@3(ctaب P?¸!4`by|Ik jN673S4Kݱ9N0u ԥJT020F7O,L԰;W>4+u5h+Q꽔:#֦x~Z{s 0{&?R}9@JKnL6:PM|+uT[5-͝:`,]05Nå{bܐknl{/W߃2 "NDqJ=2: sw~0sn4fSsWSȠ Ѣ37C˩S_ƧF#Xm+qw)w_X:F̹QcPYkhnhC%+wތoħ}.3ͩs5f#ױ(:: : 7̉;W &c2L_RU!_k{FgkSjHx}ۺ(>:Be1gՃ3 bPrd^qCMfy-3aŗ?HPu:2 SxvV678\*7ĩN0N)uP!|c#i7+߹-uPpstlK@ J\1(s6sƷfD!u5gri8u ԴLvZ,]%uP!|W66ggSg$3kƔ!=CS*] u5⃿:-nnL474ġ9Ԁc??7.Ld9Pori8οf 12p-"|o>u@R˲\K)@[5^%miL@{Cq+3jBsCC6)8]{řC/EF̹sfέ߿p !2p N uSg$b 1S uC)^m1kƔ)ԸKo/=oƆ?٦irGSPF#n  Ԙi\Ǣ8s@ !2pV-soʤH*ۿky/.r=.::0b\NQ:2)ol×F?p= 'xXܸ3јiN5';(;oNiL'} ax;*w˗\~rz/Ψ 6%̙_i:*wݱ9N4N)uHS>Jh-u@E5cJ̛{\B|Y?:;uuw1F:n474g6)8]: *5R<3Ҙi\Ǣ8s@ 2p;w9h5N^2-""^H\/̈oԉD/{2.2"?-]h"hy$5!}9PSori8οf`0w֖֔se[K)@"{fi kDw$uF]4WڦD!_+FQSw ̔S'&\7GkRۢwG `DnY5S) ՟| TٹVl-23H}%u0 @X &: O|'@ ෌Pmq4FJ3Hh0߻NJf|cdkΏM RۢwG `*reKs\>u @_՗:=c2T##3{.]84wi3RLa(DTL0eesq\۲)0i [Rgc6ߞ:xJܷO,5Dc&u+ラS`Z!d*W*3G~s/ǞΨfS'ѴtM7\V] -ff6CqRN0eгߏȵuI!S860hoo?:xk٘[4)_WS`ZY!ڪhצN7xd~p T)Ou~ YwCꔳV*Ga(;4؟: `JX~S7Iۓ:8Ke5jY5s&̾Cbӿ;wNiuq =8GNA̵#nWN3o)8pZ+6YS{D]F`󷧎ޱxzg)P,:&DS>׿^ cQW7~`^Q_grⵓ1KvGFGs1Z>j}_vm,bS4.^ܜ8Q)G8:`9| ^UwY~idsseQ) RgaF{{[ _yn)?/nc snZ:ӥLBXغ)1,v*(=;c`O4؟: esq\۲)P*&`3(k-q)_WS`?ؒ:V T'ZvVqW*GaGfp|[&uTޝ[SgRm>=upW⾭xVGc&uZ^b=:&ٹ躧3)F.HW)uXfxt><YqhI*S\[G[>6FȜ`S'T]]3"IUyA QI e`qG`%:; SZ}]M|֮WSzyC< cͅ S^LpNy$.ltYnZ&ěfo>歺"ZEl ^a(iٚdS@UjZ&=0 )rH1Q: `\\9b9:&+5ʊX^:ѱcёL1 qǣFnV 7G㢕1UxѴlM7/Q*H;~Qx 5l4_/|"u p r|2Yo>4ٚX!Q`j73(O~YLU3m{IPC1zd4uSW#"wҨNσ ih]1^)lnND4:`”/G6ߜ:NCˢ(i&'SGcтLrcs|\qdcS7?ؒ:N˱cLlCͭkHU%SxWݩS4d`b\>xX,:`<}4>=XHuqGS6u ##3]߻qh)URwG )uXPu9=3PoOLCquјI0斴g?Ov%4>ָϏ:?0z_1`k.?ØS|9wFHd#qT IDATVyl9*(SboOzbK&gB8qѪ8Sg LCX>3R' 4ƍl/cs`Bƽ}A|So:z82ǣwR2 okkceqdEi?NTʩ޵_u5*7G̈(ݙ:fLӘOhv|zScgդOvO|~a//%uS]*΀b0!_:e)m[wG{{R+\\;#׶,u TJi8)JSwPoOs|2Yo>4 dL=Kk/ım|5hgR2zd41:9呸h\ `~~I#o9/ˮu#v~ČRrh(Zj2ȵ}۶NށA "^yk$b 4_|xA'g,΁6;WُN2kqlݏG/RݬIJ>X-kL6*bTJéѩQȵuDx4Tފ'._SliWקN/~`|)^yy,iKgk'sqbKX\~u 1:e+]?ۓ:+6ߚ:;D䍽SG`%ZwbQX : `L53qsDh%vIn:7 )t&#Qz:X}}?_CsFnVI+okkuƨonYn TboO ѴlMds L691+u  ԰JtvEc&u:5,ƈaXv^[]N1qⵓ1K3,32h\2毾*^)ZG̈( Ɖ):{{_u5*kޝQ*N~ό##sśF~a`jwX|+NwєMcf8p SXغO2 ꊁ^syAt~ k[:);~Om>=u0y4rD٨H09q[pceܤ3;Woo^u:Nv28yo>歺"j2(_J0F4/|",49D>1#wgM gXdnO0{;?)LrsW7/~5u #3 \Kt/:_sR?^芾m[h]ڍqYS`BUJ[R*NiϠ 0n ɾC⻏{,ujn;'s`܍<]߷^~u<=Zd\Sw`9@iϠ 0޿!pX :`Bxi${㻏 8.96\׽9uL#3=eeko\۲)0}[HӚA`|dc.nlXV0;W.i > .u$3t)~4uL*e&q`w$F΀IkOEDO[g4uΔvj\`QOLr\ƼS={RgePH1WF2T>Jw$F]K%=mfѩqm[R*&%Kޒ:&xoOӒA*,Z[nl_KPv4_'~44;wN<sbͅ `Rƨ?Fh9u L.?3vu Dڍb3`BMK"'*9| u0NNY~idss`L:wg X3(Le]O_/:aiX~S;D#ЉJ9^Ql9*8z`WR ֩awbQX : `RG6o?j8?i SGݐ:cJhhYW_6F\ Q) Q+yA8kWơgr2 JܷhX]j/=qYꌈ8^GwӲ8`R'AE5pȵwĉJ9FHrmͭkHg&l~N JSA2,p?SgWg6ď箌uj71h$4 śSgLY -bꫢuȜR?*YYeT)!;TOSAcXlmgSg G-=1{:L8yt/:uƔE5pȵwDyhAČ0UΏC~?uL eކaw'.Y3L옽8Ź<: x˯=흩3EѺvc3b8Q)(cުS]曣RvNIϠ pjX慞r[YImmot_:㴽:!~p<~hDgGa`Z^V:zVk3y dOEśSghژ8Q)G'up0dω]]S`R3(p)w/Б:];^e+n72MI@Dwgb0??uo7ǼUcff6JSgQek&Mg,\LAwɰ 0]G<%kG[:c$S ̓`ImdѴtM,\)[RR?u=ʯc`RjhY}۶Iˠ Y2,L'Xc׳ZG-qni0K90]s38Mh]1Zm|}Xf?NTʩP.`Ҫo^B{{RdP`^)cxM&sAʟ~ `"i(g6*8O6\[>smdsbd@TJécTɬiٚ8C]0(0 SսWijZSguk""bk1h"Y{}wgLr5l4.Z o֨TOɩQ9/L}.uL6jff_uNIgF{{SG6-ͱpA&u ?(gN0-塸iߏbС)0 Z6~.]:qRm[Soş3rmRy-Q4b g6ߞ:`*{w?p4W.s5]O_/<7uƄ]0ZNO:{wk Nae1oXxŦb8QPHD/|",49prm/3dP`>VG]vF$?_zo'筈8;»q -"F̺ILL6(D4: 52LF #NIcF{{Mc&>MU:}bUἑSrPFjk;tj9dcfC>fL9<};Rş3rmRi)onJ:&2 ޖJQuг0ZNUMK㛋8gg33o9" L!B{۶5u L[\t~hZ:u }'uL eaZ}į4ΨJ ?+:@6_]x!]6[9#3h}TJi8vwDVl-Z^:Ji8)JS"ej%/MQV &nh+NFjפN9-uׇhf6.uabUJ1BW{@Fe,vus{ zeaN) Ǝk.iLTt2\574+uʤг3`fں9gan[/SLkOS`Z1*d;? @3,0=<}44/Da;wc\MڸxECl1\8+\t_w_:ci)M~+N +⛋} sۢiQSI2] ]S`0*dPwݔ:AI Q'ƓG㉟=3zyC|ͱ}jgb gGQ,L2i]yŸS0ZNsWw/|qSSb9Sq(cߣD߶S`Z0*dwtށAIİ T>J|z+5ǯ`˄^?qi%3&cqたĕG^Lcf: VŬ3ׇem?} *bҌP*x-0(0 5j-ͱpA&u໏'>GvVue~})>mҪMy)fď筜VC2or7*8uagk7ƊͷuC_IUɠ $92U_=_oRg#\ؐ:* ͇ͽ?Om '箈,X#usDk?Z?m{$=( N)ɨ ;7o6ߞ:wr8_ΎhդN C_{[}/^?r<_ 4& IDATlmot_:cڕ?7Ź<:֮|{|Ůqƈɓ'3 VES6u ^l>lly <7-FwK4%-\'8KB{۶5u LZk7Ɗͷ}QISG0)wbQXdXo_M1׿n&OǽW-ʟMhΡ d+{kK$yqƽ0-jjg,ds1oh]1*a](DVOohhYlD  wm-8C;^}ΥNa g_(SxlG[:#"bk1h"ɮ|{<`Ms/1{qoN5m3{~dI0,gǨ զyAzb)Ԍ#[4STe=:c/g.u X_(u<7Q::D3/vύB9^.og**cߣxk8Ck7Ɗͷx3wlIISGP=W⾭xzg)ΌE 2z0+3ձH|)uv D"'JY~tTNnM&͛& ߻wLvmm6#5uZ:z&G+UJ#i=حGǻ'9QiԒHv3 @X탇>xX+sS*dfM'Pr3*df>xt ;VWvjt `'NWLGjO)5絔k1ۣ#/h4K[Lg%e٥gyt 6`.~ -j7_Qfӥ=y)ԅԁk:P׏) 9) ֥_|:Ovt QLMgTͶ.G߽t6s3I=3~9J܄_lץPV,k+=t T22WFNf:0AMaX4KӫLgTOHt6ȿoBt6H]֟]zJ{M4]?9$lM*?d:0,0*Z)gMgUD"t~deYщZ#^NW錪ڪ3~t6Њ3=Z_R2_y&[_]=ܧˡv-BA"^C0$TQ[4@MLU!)hr]ٰ ܒIrYcKZu+3nvaMGF՛vL6]yܒt 6ŖζT9%%+^ӎw;sX^[=Xw*}C S]P7@aT TfrL̬ܖ7eZJ ,Mgɖ'Lg6|w=ld+^G$hv#UJtRӹlj7MlT(2CcXw jAk@c:*ebխXaаuRAHRm:๙vN-)nӎbܪ__]MSI,XԠ7e`X٩U.4$BfV )@0(P F~U-J3ږvt ܂Gb:t „Gcu|}[s:Ҋ錚PX3M:<7ߎi:5f:S}ڑPFx&G[{Lg`Y^[j7ĕ:pT!g45Fe`J_#rsSMŠ +E=6cXԼguyftFM<g[Mg`ʹ~Akg{$Ii5>]rqx6)hPxR*O)wuBBtF0*SB]ٰ `S1(0a'GVp,"P[<2zӎ tP?tjxdFc}3B%tN:19'j:$է޽>)h~m=1S/\| x2c*dfMA@͘[,ȊN 2,j2o՛vt jv9/%ԁ%_HO֖¢҅霺Lb72 Ǖy)hB=J,_19T20!7+#'MgA@oюthb ʼUg>4wa@YlmۡPU9uAfymnPg,te>]GU,䕛0@U1*ja2@bPPΌ^Sr]i߀a`2oY./(m:7KisMg%(*\tMs%̼"_d:n\bKtnA5Dv)@X탇RaqV̬$&73b!MI4}TS4.e5oխXah22oV$ئSkO?ܒtJ]jݧ-ܢs木ζkWLԅ%_H> ^@}Czey}s ;:pTtS*Ը]S,ۯrUfrt ԍ7elQe@UiE>3QSj {vIΨK֤"^I+Kg+^Ggv(mMԼ㩻Lg`,HWC>zcGͼҴߛe~|QTMk@?A_4eu„LOʧd.9==l:БQ 1}ݦ3V{Q8URQn~`9kX$i07m*%9Q]N%ԶcS[>-*73a:MǨ Ų͏N62vaգYٱS>uwڦ@:鄚'LgW>tztF] w(O@4!'jnQRea MڊV[^C9 ;$yEk: M !TfrL̬`C0(hH|ay<u/:Ҋ錚 y ֫nP{M}ՒHR)/mRYZyۮ뻝CZl)Mڊzն9-smRއ0LmGS]>`PвΌ^Sr]i߀apk<=銚r`TitF:Ru+uXфp\EUJM]Kq锚 bKtFS!@4!eNl}V榸6ᔋ^;è 6?W!3h/2Vtv/cIWf(NΨ)HACO=A%锺uﺭZi yWW6>L~y`ߴvh 7ĕ:pTxJ*0~]9i:m ΅ WNfueO8p,]zmU_jws`Twj1є>}3Qڶo}{2$pWR+39f: è 6KqNuA@Ӻ0,XA);mIy\aݪD,ocY U7fh:/N)I7f1bp\m*ֽKPtP@XGN+;5b!o: V.Ncl˲*\e&LA~en#+:1Skī-1jGY2]Q{vMLgԭhWM=?QSk+9¦Lj)ϚNJIӁ.M-k+֩D"=$!zcGͼu-ˣ`Sg@bPߐ͗uzdEO-u}~evo+'fVLWx&Mg4fe:nY^[mDzp,ZiY^[n~IJyӏiN -XqtJH:۶tFjSwB,tАbۇ1t YM0*b~فGLA[ٱZԚ;7bPUGM-0(S%yק>\.UrZZzLK EǮ5Ŗ>4tJH2n,tJ]%ۺK]Ve hvv +7y k`uÜ;@]bPVtaձY]-5Uw'̆v+'fVLŠLsK[Lg-_0x#[%IE# հ iv4}tJ͘u9n:fESj~Bl'h: hJx2csennQnnQ탇Ltgæ3Ơ 7„džs:;VPwǰ M*X 8GLŠLu\\sOg:%a|‰Z-R*m,[R̽l:&x$ma:X^[NUOVy,tICJuTWT̚f&T2* w*399eWfzl89F7a}[ZʕLàLu|錺lM*5!IZiZ3)#[uda\J~6!]軝CZ&%W[^cIn:pTtS*i`3)]ٰ 0(m:=9e{Lg*swH7a 2k?'zLg-k+?$3&e)/jvAJt҆Z:ŋSjt ˡvF1ֻWxJ@$Jv+uAkNf&T,ն4@SZ22llc?Œ-Y`eKz#\bSΨkT7 (֩JntΆ{}^Btq+^G>U#2-<ʁzd~¨ 6Unft . I.Lz;:;VPwʧNtҝC:锪q_6 k?'zLgԵ֝rZZMgUXRn>0Y.M嫔4Ӓ/d:ex$ҊtwFd&ޣie~J+sSsX7Fe~]9i:XedWfzl89F76XoQfgϙN;Ceyf IDATBL{>u e:x}Bm)Z%sNT-%WY)F-Bl1q[I[٭֮~ -Teձ~tztF]kWF=`C`DU*eI|kf&+N1㑞I1qS|Bm)ֻW->ij@ ީԁe\< 墫0* S*])bP*:;VS˚ZӾ~G0w|ʉY)g6Ѱs9/t;Z i;;p\9U*e9l3r[|$7?tFKlC4ib:!eanEg :v2+E|Jƽ:=x8&IzztpɭaLf]o-qv1 H\N8Ҝ*霛v%kJx;#[4Do=p\~Zi9HC)OW!<ϝ5)73BfQܲpW|sI P'.Lz;:;VPkثn$GF-,NYְW#{sOݧ :k}Цo^Ъ[1 ?ۃSޏ.՟5QZ ȉMgTDzԒHKVs3X%I+^Gk쫦Slێ֝ >Y_m;*7̄:h|1)ML52ԩl#+:~jY+ulEsfMݧ?D~p@?)[TR6.4{MIwtJU\bK]_lMuˎ*YCj<ԸܢT.z}>$&>X@S12SI вΌ^S˚ZӾ~G0PKzӎÔqeӇe?|zΦ ow}zúv=`:zvii5Q  sxd~3b&֞w|J?U w׏.m1Qp\]3j%_R-yW+_~& l5˫g{HWhEP;bۇ>xX٩qE9&Ma2LNI;mŧoM,\?e]Y߿3>@|*^?#O6:+_0b:\|A+ 33^]7V~ϧe .}Q]ޣ3PQ5:R_ A]4lO~Up4\@,ty=--omiGiGCZx\ww}Wʹ>)u/ѣ֝3R~aZ_0񮶭 0?֊y֤C6f^ыE 0Qܬ?φMg1(Gjo:a}3B5htFCR*djvTr]\xtƦ5zձkN4?H72rt2ee+Xҕ٢;-Y5/WN{VHg:ax,KVZ36sNT-%WY)PR[{x$x7W΃ )3y^Bt >vFm;fT%3&Š X XAa|  uˀv )$ N}h_䫔Ll5˫g{82>xR[Tnftɔ<(fD.5sT.SЄ7lQ:׉hGOc: f~Wn w錆D*,͙Ny5t /^42p,ۯC uQ.TU׵GձFe,ۯrUfrt 2de㧖51}atQbS-yM4sLg4<(R2Ӂs).NP-U=mcIM %!OientEe^TQ)qM; .Ap[V݊.L:v2c#O\锆QK"m:iCcI]_UR6VYR2a|9}D 7˲`X٩8 P5̬ Y2f~K2cSdlQ:׉hGOc: *ûtn*e:!x%!eNi*^@kFeV|sӦS6ԍe>Gh@ 4hu ݯܢ@Lc:5,5s@U1(6\6_֙:~jYSk(иNԫ50 hJ8*3٢IŊ+S6hOK[+*c+}CGP5^U Rt jeU.@U1(6ͪ[х WNfuv ǣ~YBL{>%锆lM*5jqTf&^4a~ܶCsN-UJEƔ`Ķ}𰮽 y9&0?>GSP]>wJk:MAPWf:=9e{Lgܖ#OJ<(eNiz6*3Dt Lbe$%6P+uAEf&LcgԶnFepCW*39f:MAPU|Yg 7teO8wK?KR3FgVZy!E*%)eJnAXR^c e>xHt4\tWd~9AM;9 T2 βYQK^ e:Fe,[kF;6hl>WuT[(٭yE̬@ss(2!\r3& 0nn#+:v2+וSat;瞺Onk:!X^[;'3Y> KsSt%IŊ+Snt Ȗ>Wr jIn)l$;VQ#.l*7(7CSP]>wJk: AP3V݊ΎtdV/Lhix߾_׮L4- DMg]CY^[‹3nxd;T*ey}~[Z\!}H탇u埨Xț4̄v4c~K.t tqjM tb8'y<矺O/00p\=3VZ31Dtюn2V+S"h.H\-*73a:РS S wN@m՟3v MŠ i|YgFeMLi_h27ߡ4P93NNMEh -ܿW)U5(S)㲝`X_탇3 ИGR i:5D4?>b: APV݊.L:v2cy<M乙>}3JOxtnDzhMheaFJXǚekͲ5}XxAIG :M,կ[4h@/mGSPC]a y)hP se#+:v2+וSath`!=rK^) ('WaihŖ,P5q+3(v=pG<>`فb: APV݊ΎtdV/Lhi o߯ %}EPDE֮v\ /m$;?B@vToH/\2@rs9~,㙻un*e:DkZHVR*ks>t!cVwPNnB x>ԋ*dfM[T!3CSPC@D#3Ѐ %/u?5|Jƽ@:R:tFC#Jlt6DzĕhpJy 7k2墫PKW*,ۯԁGL4̄`X=SP#]a y)h0 VtaգY֓#+ 8zRtb0p;'1 jnXÊ ic 7=j_k-ON$EmRoH/\tMĵG7a"1à hxs%YS˚_,iۯh2jX|ܒtJCv)Os"q./5\Cs"_dfҜ]kuE:z6NN}H٩U̚4v-?՟XțN@aP4UɬΎxo: Ԡ??[k1P|0MDZYQR6r5VעI#ǿY$v{PR**Ks6 N,ۯԁܮrcg!Y6?D4?>b: AДuzdENfRwV4l5?[R3Nrh`';Т닳.u03XqXz̠$y,&#}H!Ϳ0r5s墫k/c@~]99le@S[u+:;VбY0*43??8kZJ54 $v&=mLN̤i6?2I[Ha6-fIH@%FdUّ$K֫]yѐK<5k3NS&EԻ@Qy.f& 4{AҢbe,T8ѩSzr)!5@}2s2sj۶:UX@`P'N/ѣY(]VOc*D>wduF 4ԺPE sZ.M5i[U{&=%]_.o?*c`7]J>`2Ooac:*=e~N:[98K:Z\tP{#c+SNXC|p,̫f #_=ovJuMe\oڡy *a]vYU,x $Kzx ӖހBAu(gIF딺_  TkB9!{ZqZ~MaiQ2V#T)=~\ԔuƆu E733^ UcP`٢]Խ]Й~tY@j鳋?$c|E;ulѓR EJ^c#XBSf~: Z0 IDATgGX.)opٯ[.i T׮[eԨbӹJ>9n:F7bSjl:5ΗL&#jQOO~Y5Xc-:GӷMCi]\:E7iR)qu D73SP(tCuCtf*_=u&:++gu!S(SKYzuQ&W|N+Sw޿ ps3g\ݧ#m{E iF#mW`cqj۶WDfFs5(56hOpܠOa(eQOdtp #|P(ңONUO,ftyڨ@p^@;Oʡe;Ĭ3Pe|#7ܨsS{quCړopM>QCErvm>YsY@9bH-+KX@{>M@`P٢]Խ]KAG{x(?ZM?=}NoV8tX;I/kΨKn5um@ .jbwE-9X+["@c uMʥ*?]ż<]q90 XN@ bPN/ѣY(]VO(WmT9 I'7ucnl&z:댺ַS>s୅b-Zr!_nH{RcuZ yEZZAuU\V@ յVvogW1_ Hgzz8ziS8hs+/9딟-#Jt۾uy-c[3Vۦ 3P|`CL '*~Hn=HGbI}Uh)Pi-{M!X.5\jJmZ7qe&FSPc0vr|I@Fg嵹'( \ʯI <}:-=` ww[gԭMjlMZgF yyϺ!IUP|Ӫq\W ,D{#25 ^Q]vY¢>O6[g%=txVoRW[:XNuΨ[Z7:5&جI-tM7WUoHlݪ)u`%Kc-ZuF̌ m>c T*Rfb:5A*tf*à :p(%vԞ[g>W3VB}qFe'gcr||9±3VҞX}?'oti,v8 c~'Ɔs5Q%o|7XK># v }i@=ue[ d>/ub:n{*k@B\E=iͳ)x5$gb Fb%9 `+q>?1bsvο20*r)e&FSP#s\н]Й~tڝ:_ZSȢg99@zcTuJjhnW-qXBSp>놴'5V;%i&c]Kvjw<H{ZWz|D^̩m^TP4٧33P#A/zzx SG_MQJ@「s25K7>iԽ;I/kΨ[`Xm[v^(ڬ̫tM7WP!:=R!&W<`,haf\ 9*US5)7U.5Ĩu j25,-E8KAG{Y@I}3z_f3JbjvInN֟^OZgQ6P h:$IޛuCړ :UyOMݛJv:8nPK>)56lr_R|XD>u e%=z4Қ+U{oʩbQR?x!W7j/oΨkMݛؚ@ V1Uӑ6<{\B]5P4!7Pw(C =3/ c~u * K(56\j:UA:-빑E=y\P8䨷U(N.ۇ~X(#K7>ҩpȱN#/l?jQBфZ6\k:6+;jE̺!IU7RtC %?P"=j^_yV\:PyOaulE@]|n:UA:6=Wʫ9WOkȣO(EoY3>.>A_n댺]mN?`:$Iy:Ҧg+R~H,^SsHKWT`,])=~w%/3'/3m{SPDRcĠ ⨧2:8Q:.WMQ: xK[/B`Q6ϟX{!Nj'Ψ{-ߡPcu\(Դ&놴'5V{ӺU#u%?wyXGoT k׭ʥTĨ܆zJ?f Nti T1XcƧsq:E,g|3:=hQvz߫ @M;9ח:E;zoѲa[EoԂ?X{1&#I/Wsi?:PN>~RcvYgc]qf*à zy/9WOk5.5_ЯI-z)ewzbQ7i҆d:9'gc)u-S[ !~N\U%UXжٲݱ/hBnlKOmQu ͼ4冣)(3 ifd:Uʱt2LwKtf*o5iB2댊^Njc2]mԽIXZvP|SΖe=P}ݛw]o*G. T@׮*@b#P=٢U(N/e딊9=4iC2dd*e;jl6+;Sѵ%U23e9_t,gKnTlc-Zux9RSj۶:ec@bPoT^_RsԯN: u#zy댊K <d:E;zT,e/T侗b_rĒZ򆒞|>GɲNTJXLfbTD})(hw&8|.k*à ֢G==_'g)u/S[ @f-Mj/]KTQ{Rc%;s_lyV‰.ލ3#j۶OX:eW#PeeIgzz8zz8'ϧ.W: 5CiW'3̬OQ *1&S9U{n9u (w:Ҧvo^/Δ/oU'Jr֥,jT{-ݧmtny:PEοv& ZL":L?A\3Sy\kt|I>pe>=b:̒~#@aLZ6Cf P셊7ߴQP_ty ErC PZWz|D^f:P%յVU,xJ [0(U[⨧Gfup 3TSԱN@ b`jjvI{1:TVW^ Μr" 7tM;?V`pY%卷i$Luo!ޡ@wS0P[?\j:P%r)sYN@D73SP%@IE=7:2%iKo@: UCi=،uɐ޹=jTd*+S[ MGnQ*PpBl-)\GbI}-yy." P7]*Rfb:P%#&iN@8nP 3,?K&}{y8oiRxi sߟ?Uu`1r:Qn:u´f?OGRl!D;z!otfN>~uJv~E7Y r)};3P%@E5Eݾ7֘޵=l*jQnNL1&Sy[v+KXgoXkGOX[TP4*57teSU ݧGn:epkh T:kK:Sg&;u:3C@kgƷ d*{c2US& jN׮d8 jQ|> Ɇ_:UAsZ71[?Jk>[L{y:0L兢 9Ps EAy9@voҞ߹O>@|n@gYg N7@`PUQOr߬~~)F: 0uPqT?VkLN&{x I:}Lu`/a*bwYGwr|ItPZKɧ=,?>6UaYo|:d*jr`u pE$i13g\R]?8nP]nU.5ĨuWU׮AP8ѩذr)bPUk[֋=Μ˫U{o{9|*gQfǿyuP؈nU:X@$I-)U#b( 2mm+C)C\Vuu JmQ bP5!-깑E=yH>:Zj:i(O]Է3߮x̵ʊ1n5wYgsbZ8?aR5[ .KS5 '432h0KMI>)qu J(ޣ(ZOO';u^ՁCigYXfS~鳋 @Y1&c#Sk3 jhnΨK\]՞߾_n8j0tTjl:%=N!eP^'jOodA;X'Tc//X'e35aLƀw޿:(Ćkb!oQM{NtZ ޥ|.k^Fd0eP7. w֑A7iN*y l\xVd ftujd@͋voҞ߾_>|.c>cj`Aԝt2]SCLuMٸ>~euʚXMuP6ю^T,0HX7ܨG;SF2:(~Hn8jX,vuP.޲^@F2:s.W u~N*S댪?n c2v"j.mVvU S>֤u9nP]nU.5Ĩu@z|Dd"=)( )=>b sJsZW;u:3;7TܒNPOlЯ?^d bjYuPԍ6#GԔuJ}N,:tFuPZG$ueJ<:=hbn}2:X'6 O^o&aulA>sv9u 7ؠ֤u7P8ѥA@RcJ>*Rfb:Ġ ּ鹂]d\ ě\=|d:2kwվ:|#'T´u eS8ѥذy:PA^fN\V-{SPD>u T2~\QOޒ*Y [76хL:2u~z|:c͊nU:0Ĵ8?N8eSK:7|QXc#&iN*c ƆKMYB%\н]`\M~=u'ŭ3˖7ߩNY7)?ֶ`$̫Ǡ 2F?1冣)XpK XgBVqyu>;)f>nl.K wۯc)kVCsXg딊cP PNXBߧ ˬ!XXKyOa%oxu V)eSP eAG{Yueúxl:WbupYNٯS֬@CL};s*9uJ,jdsT[5)˪u V 432h `PXKzhV5:$|dH~B:޿?jرvM:1lf9~W׼SߵNq]N(eڨSfb:P!E}X`}u ʌAe81.PB7nó)XTg?Ϋ39|b>wdߏ IDAT:erw 6XU'iq~N/gR1 *qj۶W2?1冣)X|.ذuʌA(pέ=،uJE9ۺwpX[njl 댊aPPiR{J +yS :*=2@1.:!IҷK*cҦj\R |5{b@UsC {t1cR ,m۫pK3#) 2sjc+A-̌3 P*q+s&;OSK]MG'nұ5/ڭUW[g5!kQv挖)e]ź6Xg֨hw2GM)c+M! 2e.m:fSMO]ecch2hbj|uP3|3s)ellVck:1*kCJ>9n:W Gu ʄA؛g*YTpmG-[&mH37 [|:e 4޿[>DZNjJ(Pv y딲q EԶm U1Yʨ?]Z c-|n:e  PE^9<{F=yKb\@R<}q=txFenݤ?Udc[S j!7`$7ؠsSeà Zc _Ϩ ԔwX N@0(TKNW[.Ge6iC2d>Mzf:1 4ĬS7jq~N/gR 2vƆߴCDu 432h2`Po6.uu*Fe޿??N@1(ԠeJ?2`ͨQ_m :} ~Db6F"B{t1cRr c-:2Pfձ}u @>Ujl:%Ơ P ::tqèWbv^$IY/;I_`׉v:+HL Z^.ZTCCV q0=.!kSpݛuU{)(!e:q9WG: ,:lZSK9cҦ?D:$hק~Yu"jYuPw@E-Vb 26eHm)&5qZWfb:%Ġ P٢Yԃ_L(訧ӵN(xGoo3:=h"#_nQ8Xߦ/'`Pᐣ]^]'s.i{Dm>7O_`h|S@GU´uJ0(T۶ʥ:eT/u .*39q2-QO~8(oIr VidH~6Eo: ~!Nԩ|&8NzkԽ`$Y-)%ԽIn:aT[z|Dd"=) X&@0(a޲N/}^4=WTG_MQ:켺QM.Yw۴u#zN Kݭvyu~wվ:A>NliuFI4&Fe?1冣)XpS3#2s)(e%:2鹢cn;a7]V!f)nAs*x9UuYgpYU{Lvj!͌ Zg zz8>9W(訧ӵNXpmqu|/Eo٤s9&Y/v}񻻕9x mS:X`OXgZH۶JXJ,|R|POgSJ x[lQύ,၌Jkt|Iev }yuc~#:>vQ/Uޛv7_bw?D|zf:XM  `rC {t1c*Mݛb-{NtPRcj۶OX:+T,xJ [g`|dmԅF }oDWu9s<ec}wHuvv^@_V_bXMI `{5Yg\P4sm(pS{~~F@.5}uVPN/E8֑MsԞ[֍ tҽ~M_z}jcw. d{t1crE`Ou!ݧpK3#)2sj۶:+ʥN*d~C~ջvuFݶ7byAGzxVzοWڛv7iֈnӤܒ(c%2Y// .]è @-LM 2*ݾQUu%}{譇enT`eya2t2^:+ PXg\Mjd@I1* GwS8i8vNƞbP@]{um Z5l\_ܩcgۭSBխXkGOX[\-%3(9Fe7O}9@mb#-s==Ӄ_ׁCi/':[ }y@z}黻|uV1GE-fS.KW@:v)Ƞu Dr)2n>Mp@\:WAe8ѣY4izuPuya>wd^:j P;3g\NYD5 2PRcj۶OX:o#*56l+ rr|IG.dt\^N: 0ԩ|h:!S3qsҳ)+Q[A\B{~3pP٢Y8G-IQGMQ:cc[xbj-0@- 66+;{V˅u 6ؚeT/u .qʥNebP@MXur|ItPZG4zfIN:(}zMp@\:+Ġ sƞm[׏SMz:|_OZTnA] o [#]xShBI 0*#56冣)x \Va /LP|*7߽ULN^U'3'6+C49haLo?zJ/gю^ůsmXI>T|.X!,:V*kbIqIόw :|bFg㒤HNAi^s}^~y2^:%˜ P܅i7hl[`$fhw‰.͌ ZV!US5)xT.5Ĩu VL&K&Pvͻձ翪U依i]<_pV[S 6M7Z֎=ܨ@2foҞ߾_Mxa; 2jB[Z.Ls\fY]}NԎ__L Ej FdgjK?]%w0*/ݧ=}u}y"Y%U"E%Ebnv<lcvM e/0i.⃁m@`0Ft6{Z#R^:U"C'IUzB%D瞉|LT::?#ndk㵋~~ ~1[J_ 6#YMƲ9uooF+:508<=R$? Wދk6k-14\MNq|_*cq)ܦVc>bSDyCSl`SZMw8_8LM du.&RB+?[ʥa ֯ܟ:HoI3`Ú9J}X Sǣkf|LT::/z36XK_qb!:LsdXL]J&ukȘ `)׮<73`*Be:X›1ȟD_6:Oh5Ig0(l8#;+T۩SnKk%_X_?G)ߊbrD뿻?~?ν_N:0&lkVc1:%>Qn.j{9x4u 083;|2RZ?ՕJ&ν_.?ɯv6#IVs.V߾S!FyWSg@n Wދk=/Vbhl}L>)|DP:n>A`G'k+STsw.6Gk O:b>:uT(Jlbyi!_${|4}"jJm]x3S}|\~g3?Dvdu.^\Lϥiď;\|` WSgL3o?}RNu1s܆G{<:OxhϦ2Rh򯢯0uƆ1SK_cjz4f"JWSxdW<L$Y_&&h`ZFFyWql;x(hLOԘ>ٙ:¦jz-uЛϟrꔎ2Yc:ssB+^'Sc>:29 Rb=fu(8 c˩3b<vQ w,u)JGSGgpdg|O2&sfC1ui4~wLMlc0bSXj<3[߿?=3|$ 1ac2c>+>=D_& fCѬFc|v+^y7FS/`TVzKekJꔮ4Yc:ss6jwcH6@)F|-2)@X^nW۝}x̜~9u_:;:ĩN'Վ1ud`C!P6b%=dLj*~/Sp 1gQ0B1{Dd ^(N=A`?]3zGfb(: `W x=S؀cWOt3%k#ʚ>"2iC_M 3_/KGŁ'*VSGpKõx:pu 5frw4Z9lP8j3+߭٨L+ch&?0*Щvߡ֯;f#u 7TP=OO11\j1Y/I_B+^'~8~9unZQL68w2'[(cϞla(u q㽓?L e5/ Ǟ'VXi!Z$jvx=hRe1rk(NP_E b~W:r6uγx/ "x`PX[v^=BrLl1YI@~~ ^XJ1R]lywK/3BlC5(>OczQƶ "^x6jL@@ekJdu.bz9P~9uХZ/wǏ;ν_NC2G_&:b\}:ksXe/Ub`h Gֱ2%[(cϞl4@j3_/K@G(4&J pu.&k1yv-r{ x=sP]Qq un`l@Fe:˶ⁿ8:x;|`0(5;ϣdW 6b~9&嘬Z Sgk{ǿܝ:W:tu4w(u@ϻqoNyeb?:6ΠL bZLVbbõI̫F+:חȁEn:PFe:GPǞ=P֬ye;ɿ /4rVcbWb(: XFdX RZeSgTsl;x(3\ IDATz?W~q2u@O)e /US\L]K#7o+-չĶZL%,Sg]boDc|wSW~q29;:=A %_=O<+˭)tPCm:o <<~9&V.^xOL]1"Údcˎ14\Mt'v3_N8w>mBe{4gSMjZ 쌝_d211\s1_Nć#2]ƫIC mC(N;}3&x:u@OqoNYe/2}RTc?\mᚑX'x=_sS#DeїɦNz瞉|ɧGyσ3zV6;:gbÏǵՕ)𥍕\L|043>: Hvxb5fCs18+uCͅzQ P~f ?W~q2u@O2(|!f 7VWکSஙm5#3%xB5޸4V.u=(/Ķ}En:ABzhϦN38͘x=ʙIeϵrXi!00Sõ/55[7G xh4ZI}llQ`T`+G=OOſ9:>Ձ'*VSGёZYpZxHL]W/Vc>: >&7PFn:cjފ3LJSgfm6^?o1fPOUxb~9&>6431\Kjjz$.FcHT]Qq u9J}X >ã~>{Sg4d bPlſvõؿcZ SgЃν_KGd^xO\|!~/UR|N(ν|b)_)\9s2=Š pS4{v:^1jprp-&k2yh4ZIGwїɦNξx;=à #;c1&sc7fb(: ZxH{o\K7|QdSܶvs!^8Sbc3zN6;:gWOfm.ksԘO|qC38~9.į\"/֯J¨ ƶ9S/< o e}0&- }Օv,.Rc>X]i'*nηůoǼqi4])GKk8+6L6u ]՘~'^8f#u -gO{ӯ eG}ژ̭,cbv9VZuC3㥅+-du.Ƌ t5u@ϛsWqr%t@)>R5cT`q1ө3zk G'[Ѭbm.kP01|}hfb[-JWΌϥJ޿>sJ9~~9.Nu՗Qݕ:`]\9s2Sǣ=K{':3qGZ]ibr,5YՕ]Q/ĶZEչ Rt鑘ǣїɦNXW3_/K'*#'Rgfm6^?v8u@3(=nR}>a.X_6Z3Ņ^: `-r7cfC+8~9ulRwR%u @21hXO{&Sgt52#zLڭhnVc3rL Rܱs_Fc>3Y!eeǁNξx39n| X>9~9])t}(ν_N/(L6un. G`)y(&r@3zi7clNZe17Rg|b=X|`E)ߊm(?NcRlHBzhϦN#6{c˩3AbՕv,.Rc>X]iN6f _l}0CqJ9\qi4f1SJ]X(N G`س'"[1z]x+^8:k. c2X\,by:@չxz9""&kQ_õ/L13ƹ+嘮Ź˩ӠJQq K)1Nz|#ǽO:`~p4gSgt%2Ѕ:uLVWڱXKhbu: c+]Rjxq!>K/߸4H /14\MбfNg_<:|x<:'wGqJet˘̭,/c6KXj̧X1|slfp-+]BDDLϥ̃v~ gH:Be{0S|11\brD|8>sۇv,rc03FDFo63d}`H8+29]\Dc|nxQ(oO9oh cP:1[`Xfv9VZ9_GfK 1VZb~9&n khrׯ_z+SFÐ j7sOGs~6u QPL>u,u@Ox;ߌv:fLic>#3+Ikf:wz)'h""&55Kc)/z>k  @:wb# vߡ]K{':eL-/c6X^PJ 1VK 1VZ~tcmn 箔mVן l WΜw4uq}Ǟ=vӬ*e{VWڱTKXi5S'tZ?>6`e|QR>~9 x;8wSg;}3&x:u@;3ј>:kcLfm[Tfm.Nk"/14\M-}x̜~9u跟=9J}X )JGSG_1חE~[Ǣ4;#GDJ\&_u,Sl;x(9|wu{]P.u@0(˜L\*14\{#7PL?j:b%;]E:5kQEq|_՗G6SAd6\a( 8#"[l6VWqm:~/6WF0://ɸ $VVTO/Oн6E\~g+Al\"?XhFwxJ)"Vۭvm5u"=lpx<=őHmʗ*18u[jǶRt1n.Nxe`3&Y2bpXv@y$rش /P VƢ/K]083ͯONiQP*StgRgt<2A|\䇶|l`&돈V3q$7P-LߋR%6N.ۼhf1}>u @OkLi 583;Ϡ l@dS&J Wc/V"?f=[FrDKsXc+gNF1:g(NJBs_ l0dzG _Z_&C#;b8ߐY\ۗbJг~٨F_6:+eʙ3:A@OJǵU  rrD (lL.u e?o[jǶRtBe,?͠ ld\a( 8#"? @Ɩ{&"?XJ/U"_l 5GyCQlOuhf1}>u @2(1>Ϧ lJd""bL\ݔbغb2v>@q|_ wϤNYQ?MН6E\~g+:V6u:c2ܮR%K_/c138<C[1ј> oNI1s{SζEPv:#eJЫp7eTjlJd""bL\ e|ol{1X7|aקel څ}|jo=:#Dɰ>903P\a(6mv+][Mг2غ=;_Жח: ԗ[?v+u@Ymb[<:K[ɠ $`L2mcQ}s`/Օv\[iNzRlg"*XdR'J o,u @Ogb?|:KrdS:AXgd(>(FitW Gn,wI&_jl@lRlK@)v)=ܻ13j{9~S3:AXGd2y8#;8+C["WV3q!@g(lL.u]h̜sN9l*cQߗ:K[㽓?Jq :1&CP*14\{X`)6mv+][M +y|ol} Vnzzo~}*Z)=1s>Stlh<6u1:^ C[bpXvxJїFĦXmR'@)6{4___,zT_6wo\\>{JUVqeSZ:ݽO>c|#uՕv,_Rc>XՕv,./@y4n Fsx{GSgǞ=]\׏v:cdJ͌K6E KFilw G"W\>VWq С2B Wr(lL?uh7Is}}|\n4ϧN͌@DnͯWWڱTU#3b<C:OGc|.:\ɨ]x+{L5<3_N16Uk#/nyXjF,/S'=̈ ݤ\S=)=P9:~_PT*MƘ |9\K1PȎ(D_&V\:b|!Quolg6G&ן: X_6=qj:g (NwϤM&x&vuڭXڈz,c1: p|!ʣ14<RXS3_/KSb<Rt;q깧SgtLT::#?Sg@W"WR%y|o G"?%qmuՙUϕ(QuolÑ5Wl4ϧNVcGSt|3oB Ϡ %c<>y$uL?(lȎ<7/MFf2Qy 6ЖRgvP\9s2Z)=m0J.)~S#6MjZtd`Z]iz,5cj=ZXi5Sgk(/D[Fc<:6fm6NDH3{ɧ l~p Ϡ !c2y@ b< R֬Fs~wnoLJۋ ј>~~]B1} QlR?Ptڅbou4w(u@Wz٨]x3ufPA02/By$(F_&: \Ql4k3~/5×s}dfc>9 c{EP4ׯ>^dgtX_~8v\׾g3642p@o[b=ZXYjRc>utLp}@fh*їɦNё@L6syˌEDDy-8/">w\S= :س'< Ѹ򋓩36,2%neyX^lz,/cu: :J_&J#_D6?: "|0Ӝ>n6n~RmO@hL{:u@q1߻wj+qc36,2%d x/`, iceKXZb=VZYa|0 _/7PJDXLc|Yl<+c3^MŹ:g< ; ^7lؐ -cR}>n5cj=`q kvqs(_;8S(E?􌷿4d PPL>u,u@;9r ɠ |dn-F,/cꍱz,#}lJdXswlD›Q{7Lq|_d (] IDAT}n. GoɧGyσ3:ڕ3'M!/o?oLHb>bQ_&{s8T@)u]䣣1ŅhLfm&Ӡ}0.SX*  GlNzxȉ|X[0('G:Օv,_b=ڭ+iLp}y$u`hZV37[2/V"7XL6uY9c8|;1‘h7SZPGQ(oOбν|w362 d"^j^l-R3 >:(En@,:D;1 ozLLyCFfWRgt=S3wsOP G<OP,Y]iz,/cuK3f4nx wY9S{hf9?: //z~(Mб^?~aPn(ɧ;6-/cݎc3'/D~R+/ kLss<1}>jLp 7e<: # 1‘hLO՜μwGq0 @Xkfb%r (E:b<eׇe̔>I1NLp$F6qY׏Nae x/"D>:6T1:XO\^nh`)"HE1ٲb>xshA{Ι^=;r"u@:3ј>:`C0(@O1(M-cj=ڭXi5_.5ЬS5Je,]/Dn:Ӭ^y-1wR'loh\]'G:#CAzڣ~ޘ @[^j}s`fK3ԗFnBd_ܼ_Vps4v: +*ۯ)NH\S=)]P~yY׏N!g9@L+K뗭fu@Lq|b4߉S=:{aPeLՕv,_>6X|DOd#7Pјn]x+jތ;oEc|I|lƶ0{By{$5w'ߜHеb<RtN(ν=xtvk1VicLe_DDDnԬFc|޹>"lyP=]g`bS/< oZ;}3&x:u@ifcSg$gPbLҎf뱺ҾmЗFn|0 fmxL›ќM``fCQ]\׏v:gc;ϿEzdXSDj((NwݢNl8 v]l l7-[@QoXgB*Vҵp 1T!;5'>RL1YiR_G7nC?H~f  /`G ܂o> `3(QݷRgLvEDd}|Xb) OD[>sڅֹr{2;-jVCsnة8wI`](ľG8a3?dvX~1 #67A30 *ѹkotNZ'+:`7)o|9u@ReX r|扣dX~y&"W;?~?χ(w;~mff@Rꎭ{]{c97lE}f2uԹs(=t sb~: 2iR9=z$ʽR@SOc)_^Տ'e< Ӷqf':mcg3a@ղup8:w(uvP { B=z$:wMRfNŹˠ k`eo;m4:s}W߶N76~]qc`jsQP+1?^pIc~>2z|<rʽqV g7: 2Y>D-Oc)?}bwpc5Pz˟a6}#6nsod9yxo<6JdWR'J (L>w(+3$@x g7k /ehYn+x! RWwlqOTJ|扣QN^~ {֕RG9=r(u33wWΏFVK^5D\:|OTb)Ŏ-Q(S-}[{?S|[SgQc2+P*Gq_Rgw`eOES ;bߣOhz|,33VƎC#*ʱ#Q g\xㅣq[ө5f)_kqr"jSՈށY*(ѶWΏNX\trX_hˠ Mi[vߟ:֥JyXgNVMVJ̾4yֈRWOJY ܿ'곓?,\?:Jq3VԆwSG/{SgRH̏W"s޳up8~(:wMs!(LkN5b~c#Qz%u9w?غg8u />}0:啺3M^DMxO`Mq(uSΡʓ3eOTw#qh,֯Nh oMHOTpG{R'7P 곓qC3[5ɠ I{bWG[:ZJV7~xo,.= oMNhj1?QٗF"QuIh>;mʳFzl|M)o|9uq(uWΝ{Sg@ӫ\ #߉׾L\X_MŸ6=+'"Eo r,~W\N(Nh:mbOT>Xs v3: `]ŰD% wxD[w)--ѳ@ SꎋL5Š +P*}:J?0kFVO~;ƏTIܖ\P*NytnA}f2z>uk[ʯD%um1(-+ޯN$ʉqG#Xg3qr"B1uB1өSZR5bp PD9.VN-e%R9Sr\~qMUZ @rצ'ٓb{1,}[g'c)->3w?#{dg_q0 pK~p{Rg MU#oE}f2uRj\(:\[y;eDm*FΡM>s@K3(M uܐٱSsbDd9DQN-P*Gۦb\9?:g.Do1 )m\=t{~u@˩\V(+ZAnؾG4J]ݩ3WdxcMUc)_LD\:{26cs9]g6=:,Ѿm{{R$Xj [bPré3}jSxㅣqL/ƕ1H{1c=qG#SZJ}v2~(u@c##nA> ԦqxㅣdXwc#QF管(ʩ)QөSZJ5ށ)I%eHށPL1?Q׾Ljss 6+'"yqod,5:g'Rg$5%Ъ rSQN:7;v*^}P\:{Ґ צ'ٓQށ9t6ocb)_L23{qh fPK_-O:!ٱȳFhZKbOT6Ur=QJMP*;QNh)չ u@Rm;Sg42|bǃSgY#.W֐ ܂6>yֈD[: BΡbjsPS$S芋/N)eށ{Ugx̱qG m6=Ξbǖ(оm{̎h9[S'$uD,5:} rSN`̕Ne/D%jS(ŎIT;\g&Sd|@J),c~:}ve3X jsqgؼ}O ]CqIעnB5bp d (ʉ7Š  v3w?qJ`*1HY#u 3(@DD{b+V!Ho)_QF管(ʩ`mjd)-mS1:wH>s!33nAP*}<)Add;K,z(u{O\:| Q}EV5b~: v[Sg涔/Fmh߶8J+צ'R|1ڷmr@$ (ʉ7̠ :up8c3XC @kY_ٱȳFl޾' I*6oΞt g'Rg$Q(c]GheֱRWwx8eaHZ۵鉸Qms`ŵQ)-!Qr@$D bP`F;ukة?xŐ AuP*ǞB1u -6UW;>oH։6cmS16I+b=qXS4d|I`]ZxAR%Xg~poO@MU# GRWΏFm<8 V(Fۦb\9?:El-OYө3>V[VώFν3h!Ym.^~xǣ6J +1S`=(h c#gsPPV^w 6v;~$\,qhԦѹk( r$X6۶H /FcKlߓ:`U1?Q)ɠ :P(cqS?+q%Əde;m"`(uuGVsm ,OXu o]k3>Au`;Y#>ߎw>?^菅w>~#&~;~П?>:CXc rGߊRgwʉxG#SuO~;.V:u@S+?GVS/zl?;+Tg?Z6vttJʓO D/ӱ/T5'*eP*ytla)_RWO{R7.Ŀn-|cOkzw1qM+P +/Em:XCz3H>s!Ə7B5sPSg=οo/ԖǞbGc~RֳVJ;xh dP`}[ xㅣ1DV?:;E+u|r=NyVn vy|>ߎnwN+?͸jSUMɠ ѳ@ VD%d̏Wb)_Lp>Ocs9J] oMGϧDTN2?y߭+:3YO\zV{í\pД r@ 3XE 1~pyXY#umr~4jS:@sCu3܆زܦc2-nwN+?͸$p#Yө3~AV(cq:g?d`jsqؼ}OS*ʑg |﷿h,={|Wu&f΁To9:Wha忉-܉Nʉx6J/HĆΝCsm޾'.=Kb/FQH-ן3޳-nwN+?͸I>mbOTb~5u hQ;b} VXm>w(fF<jԦuh+SѶWΏNhZYm.~닩3Iw?)4Ld=q)IŸ6=:} B{MkXVsǏą)Vٓy(uuܿ'f_Ԧ<>e4v97R'ADD,SgA4';: G;)I-1;6!sPxRW> ܠ*>JWu&f΁(vl7K>eZLw u+6Ux̏Wb)_L4jSըMUcV(hjd)M>3=:R9u JqS6-x'ݔ:uPJ,֯NxARykLVsǏą':)etdl(vt(uH UD9:w#o\?Mmy[Wu&/mR簎-u1MOxAr#OE,7^8ۑLNhzKb\:|>Q{R@#͹!\=P >SgܖMmy _F,Ӟ:uhŸ\=:=eZEo}!uˤ6Ux̏Wb)_LRdlh+SΕbD g(uDw u ?w:cl? "&~sXg[3RgǠ @ (ĽnX\;~$.|;g9-kr~46F+uXTi~U5g)nOk/]x?=uD[/heZޯISgp.VN_d5a~5.WOGcK{R{KgOR:dԁ p4+ͥX1ߎwx+iO:Pihr;<w܆T5^}P̎x`-1?Q3:0?^}<\֑{X4;6yH|mןGƷSg4oǿgCOlΡ{w9Th ;::g:w/܀JQz%u c~5fNŖݟbGWցBYm5(vl{RgA|-}q+/]x?=u]sLm fⴲKg.FҤnP-f:jGmv'h:M1+%鶕 t5E֌:x3q Mmrpl$?)P~$x<ĘG"xj4NL482U"EU\ӏ쏳9\x'ߏlK{:zRrGxܞ:!\t2X:4-9nj}<6_D~հ ep2#3gPJtqO85`?TaV,"՟::yޢR|wd[RԽz 3jښ˟7,%,A*ꏍrq:x'4a:Prq:,2uu,ױ!CWxS'Եi9:nbd[GA2\=R6~t1W8:T<WQͲ8{f>#SJir,:oZ`\r$v^ꌺG[īZ̭MDz} 2uqO[&c/s#yz0@/sc.V6NcgRMPUV6_WMPw\|ƯNJe)u+^[k3W7E $ꏍӏ߽'K3SXdl<7X\FeX4lsFRgTܞ:E/hM_>?,l=^ՊUTwHŠ @"l.dsSxMir+̭5,V6_??@3(ȺG)$RrmoP&ѡUugMCSg4*DOW_|<ژ;Ӕ:eVFat}(@2eu;:(M}_FK@xQ.N; uDqb$)U497neSjڵM'O{Ŋe)Mm+ӯFa~u$؋'ODir,uР $-3ӏ߽ӠxX⪍umiჩ3ʵ3jV:w5ܙ++_Hg0::hPe-;꾏hhcSRsO O~ߨ &ʼn(STܞ:fO4-9o9P\j[cLS,Q\z0uР ,\GOl˩3ӏ߽'K3Srxqͱ%uu"SSgTJy6miKPs-k~:bY%zO=W_|̞iY,Lܠ|XB}{7$Rύ<:2_F6~{,lK[b)Uu`D|O6Z<sgӯW"u S^IX"숫>:!=8{b4:t2ύ<WlK[zЃ3Fyf:bYfepmzXVIiZr\r4>~ȯx1&1w)u `4/ٖue(49:*GӚu.@:EbY%6&mU'_gxV^ჩ3dP` |Mk֦h(F8::R2*]LP5wnKPt'SgN W<ϖ_H\ʶӏO4 2sp{\;htOg+sCѡg㪍קNe(49:*̗fu󍱲%u @ڱ{qS3XbM_{|C[٩x1w)u81H3(-m2+S4cp2u uœQ.NG)԰|wsw:zRgԽJy6:x)M}YYgGqb$u @U;}2|g smˍHAYsqU5GDijxW+WNΞFK42u`eG Woy&RЀJcQ7Ʋ9Ԡ\džx'ȶ{=V,N 5-9?eFa54-XL42 u_qET)/ZT8/u49Ǿ; CS ""K3Fed O2 sOFGE&K_cCn"u5ڦSePir:״ʦM-S&k=`,onnޝ:VOP~t87VS*E=r=SrlsFȶǕk{Sg,d5J]r4 㙹SVqb$NL4ejU&Mٕ:q;GN%s~8uU}`'DĩR', c2T/v׷IQ]aPux{dnTѡ8QKKΨ b-wNH<3 K]6&CUb׷cϧΨK @0(p -m3jS}+ݿ;*RHƨ }`Æ15|0uR׷ZOiŮoΨK @0(p 6qwT.NoSCN`T֝3( c2Ԓ'֡u)՟:he.R6Oѡ8QKUŨ &!*RFhj1jюuߋs3N'u \L6oੇr)u T%2[vNHnj`KfLZմ帾HꌺcPX e.-;"]:fq;S"՟: 񡨔gSg\4c2ԺHꄺK42(ѡ8QK5è d+JpQP55?:dmRguΠ p 5㩇r)u 2|W_:zRg$uj ̘ KPwA 9=rݩ3^<Gf^xv:NH49t dLzS'ԝ|w_xl.oّ:'F_)PV[#Җ: ʘ u'՟:seÆ[wF&*u@U;5`ٷ+*R+'¨[JԩR'sd I92"[SgTJy6}gw<нSnQO@hٖɔg]Ui\.X&k;`Qx>+u@*MǑ}pS`1Uʥ8oCR'$55|0uyɬk::1 @3(oټ35kR@C0*l${F: "O'uP lK[tnOPz[qKSrWd3QJ4kN1A֝ɮJPU*885@hXFex]ȶHpܠ εM'+M_NK u)՗:ce"3Jir5u@rSo~)*R"'Ɖ{SgHds3(8uPo~8%uBCwNAp =зā=3K45|Ш @dWE獷Hp|(*@iZ>kTHPa0uBCuNAl\Gw d*885@}>O=$9=2\ $ LJR'uĘ qթ3A`1Z& LLir<ʼnSrj聘~8uK,]Sg$QqN_ ^_,2b0(4[vD&*u@ѡ8oW&R ā=Fe-;R'$Q8>l _\g1uFutG&K2@uD385`wTʥ)"9q`O'FRghؖ: @ 3&o-N'uPg kí;S'$qx{SgK49:%~ˎ Iz uPZ=c23Wġ`ꌆK2@Cj<.RSSKR.ő}4l-Xrɱ(Sg5m>:NhH @1(4 LJq_X`Uʥ8q`OTʳSX"eFU8>:1k.>NUPa0uBC2(,42@YeGdm3Lat(OdFU#vhwXrSS'5]ߎ/΀ qթ3R6l.uPG %Sg,R.N+Mʼn{RgDoّ:`ɕ&Ǣ\6?O΀-Z'uPG e-wE&*u8q`Cbʼn{Sg]}# p|(uP#c:K㙹3Z/uPG #[Sg,Jy6;Nx3XS',9i\|$4uTCR'4<B2(4[vNXttٷ+n|ӏ쏩SgF-u*ME8:r׷IU0:Sg4<2B2(4mKJq;49:'H [J LJR'UڦS*ܐ:"ͥAeXeG E55pٷ+*Rw&SgZ7:4ჩ*wm P5\?ڒ::zR'u  P:o=Ѓqc2EKΦN`dSg,Xө3*j\?.45 @ȤXLٖܞ:`ќ8d["obn&-\].NEyƁh\ɮJ"O??u*D@Zt*uT~*uoI 2@][]n|R<')А]o[]ȶkl.r݋nYߪ49rM_+LG8qĦR.Eirl"Wć`wA&*(Jae=1N:uo`PX(eqSP*8oC@8a7~=c5o;6.#6tg#c3g\:=(Ʀ;vN`߲à P LJRT"o{oe֝\ir<}o?/+V$I&o{ͰKo)MEY3Fh?@ۢu`NX2Cm5whZr H0:F_ژ:@3(ԥ̓{o!8oWTʥ)\?Ͻ?7lKա\GL<{~ll_)Mp\=G= 0c2zfnm6?::R'r=e͠ P6ܺ3u~8z^hļ>s~@ƀ, ]u;9)MG\:nq|$*!N޸ {4@wy=P LJRLvU^Yќҙ;sE*V @0(ԝDԕā=3`#sŪuD6ٖ׆d`q~ -wtg49vntf|$ũ(L'(*R-gu}`AE@yznm^<: 2B0(ԕL6H`z[qjpɲ-mͷym0׌R]s.nl49T&Ǣ5~FaeucRg@2 x?$0(ԕowC3P7NSSgy}8&|{d[05.h}e^)M%Q76ݱ+u sp{<н3Dq|$uPN:~>NN% qթ3x~82@ȶ[vx*8vn7P2\:z0C#"Ϳs3ũ(Dir,*RJxδl *RF~c,[]΀%-An [<GX8?|W:z"]: ^;r~q˹TʳQ(MN GG6[S2U>-N =:`I~bǺES}ic<36u ѓ:qew3P8vnc2$yӏ|W_$+wjSbw@獷Fqh ͝iTX)d~8%u(Җ:qe~ˎ Kir<r)u x Twy}`8>1׈TJǾ7q|+2UsxhSS,tӑ; ͭCTXtqx\ An Pӌ-mo\&*Z{w0s_+M8ʼnQN @C+LǑ}?7u H#>5uP5C:N":z49:Qe֝.Yat(N^c2,|Wux.ԁ\Gw:xg8qH'&.є&ā]Sx]}h3skgo|?u ,3Wġ 3Heà P9Ԭā=3al.}K,LvUFk`-V87,c`25|0]ԁm^G 8>:b~m~"zHPa04"e[# \:2@ds֝3.1.E-]drݩ*;7*e`%t׮Q Բ=3өSU\UwOES \|WDO(2@dWhO??~7":`w\Vqۼo 4Q2;;ʦESQ8\\GO]v5*udsoP9'썩ჩ3RdR:?.SK@uu_sV)󷷧Xt;uPm:iTw'"F_ژ:K{wDyf:uP2.ņ[w)9dx+2@*;EqhE\J\@)MSؕ:Kɮm^q|$uP[KKԸ\GAjN-(dPe IDATx]#29z=;"JQqEir,u5bj`:zs)\[vx{r)#KTCsFeu 7N}uDP jΆ[wN`lw'N \GO_qH~ut[vD<CQ8CQ)RPŞz׮]Ԣl-]^qkVWsLuNjAׇ[@mgȾ]QKdsǜdWNdh[#(M(Nu :vOl-u u8>qK V`jKARj-;R'\c2%utX4p""\(r*Rw\jPk`d[ڢ<3:`xXFeEsgCRg 7jyss"oP d_&6^nllmgwiK&ŕk{}`[t޸=֬,bi$6_LnL%,^xpEl{fnmW-F 9~Z.u 81OdR\ LԯlK[u`: Fh[R(N񡨔KH`j`}`k.Rx偺V8@9T8K\[R'r=Q0h\2@Mh49'1&PGr=Bq\&(Eqtu1h<SS,H-+ZdTZb~eu P-uP 5aUir<,@uDh<ټޯh4.РɮJEnPkʼnfTjN`:zR'5Ƞ P9T5c2u`>Ae菣p|(uR.űwu_ؓ:|W'F"՗:Q ʦESy/mї6`f.ݩ#I&2+S-c2u`鳱3wGuD&K0r=quǢѴf]TʳQ.N`ESpQ.¨H~e[\/_@Cq*s ""xxfnm F<:!e;^:m=o7"c emmmiI7EԙH鉦54Ԋ\G@,jQIa~uRgH#1wd V&͟+dLvcԀL6WѺ8[ţN`ḺcRp*(NXt߲#uPP-Slw \gE1(Tu7W} @uĺ??ۍԠ-Ѻy0|gd[ڣRrq:u|'F߹-u (LhmiK26wljūZ:ER)s#jA*eٿr:dW-:o>swθrmodY,\GOll(RM%/D<WmPZɞ.MNXٖwQRzu3XDV4 \2@U?+nJ&dO&k~?O|>]FdX&|Wtn5=q2sO"xr4-I\ჩ3e>-uPGʐ784`ex3IVٖhؚ:MTmѺy0Z{SHk15|0Fyf:u詇\GO:S]}mis ԥ @zfnm݉lZ4-9u G+Sg]_ yw7pDJbg>Mk֦N dwGȶG<境le>^<9W~,ˬL{d0::`Q#Җ:3|1 -V,ΡQ7(J@0(TlK[lcW miO~9tg:z6:z}`[d۹a8[O;/|i&Z7N=d[ٟ<KٖwQKg?:%2W8/;|g:zR'ww1Vw翓C]Ub(YTcieF$RL'uaZ"pӫ0ho(y/z%)Te kunԎ¤&5Qs>a{a 1y({^/)Nby>?2h\~`5jh=^'go?ھ3;"kwڝmBv mfkwegkggm j;GTq;~#Q_z@L/ @G(zc`zư @ŨN eX/3.v2ׇ3h1֪~wkv-<82{(;B'3Bed2{X92sm L=GcQ*9r%;雨z tʕh6ngg]nڝm)Vf'bʃc @3YNDzgP4IMu;q̉ eHRĞQh{xxv<8 #Q+Wt3Htֳ Za1(l὇.r;| C2JLٹ(zsG vi!;1T=ajKsno 2Ee ;hqeMQtH4d 䫌=GcQ*9mk͹hV3LD5;`CՖ.f'gl;⃛Shv3ˎ:wuqQ὇7GwƟo?5k//ejމN "QhVr%;`CQG_?dI毿oΠ]Z;@Fv*#Qq=W/~r$zv @K(\L ZP_=GRx p:;:,X%;M~wK|ps*;B὇.l6&𙢷?ݯ0$mxcxDG}jvQ,1jW/f'<ݭ#2]ս~wkv-<802SUtxx|!=Gc`z_vvVckoxF=O33 ٨G@o/gg[f' _Š T9(=9)*15{<{Xrv@˻vv>+W3^Q鏾jv-]NJ_K) Ryp4;haefx-H10=cH@j9:C)-o"o ¥@;xñvg[vҭgXvТ OEed2*#3pژ Е*#15;DQ6A_9|ʕ|v@+Wٸn?>wdAN s8N\>s";`S+bjOR]1_\z} Q_>Y_`n=A1D|2+zc`z_vСjKc MS*ʱcsd>v:D x(vDTF&SZ҇Eq;; Ud'l҅rno շhCe/cPp/UvС+Wß4C| U_NZLQ鏩c(ҸggthOvbvCr\lvi8]QNZA`C10/;@ODQNx*#|j U_?8p*jKdNxb+ ڝmC@sЮ毿n=d۲3hsEe ;hAe 1K@wTcñQqK=;NHU_ޝZ}'R_^p1V~~N @ 2(2`$1OEmBv+xc15{'вJEOkwegtK5SUg IDAT'-Ġ Ȇ6xr ~@[Lƞ1T#1~hv SոggtR} Ӭ|8nN ֞NÕDzbPx$Eo L؍čogg;k Ld'<҅fqֳiTv]<82Cz(=@|L٨gkwegtVݭtR{2C)e7Q_Pݯhv @KSsQglfϜ Q'{O|8nN(֪ tXv" o';hC 3Vyp,vF x(;GckoDed2;`C}k3BA}=毿1[{>~mt ex\u3bk'<86JEOL ủh6nggt<#veP֪䯿@1(|Π &QT|Y?^^vF9oe'JE9;he/U 4j\v =SǣgtR_;aϜfvv@GhGensn=6lsk.9!N   6l܎v,zv }etGbx`@{k6q|v@Gph?enPvF[8g|de2(eZND5vFTFvetOdyTWfgt#ЖjK6.0nhiwoΠ˕d'- @C/— ùqq {JE9v?}6\rv c|Dv@Gs Ў\t[G?his*nΠUF&`Px krՁbjv./e.2@[-]X}GfPVo/}/;eg@D``z&Jv۱xx4\GS=QNx,Ϝfvv@G**^'mǠ έU㽵3Z{ko~-;<3DAg6q J-Tc?x$JEOv_60~z,/XUڍInPvFK9og'=EESȮ 8N8vv@bjv.eJEOLEed2;];;jv@Gꛨf'<TX%;%7~mpOQN/aW3'3b`z&f<8#tTϤ\v@G**Qx$+ n-0;#-qW΀x)zc`z_vOftRQGc(=9>9_PN""T=|K p*;b}QN`<fg<ո|v@)*=mt!;e>OT* @22@D|z(Tdg-Q[73.6P;塬_lgkv6T[oNW'۟*t!;H`PP@vЂ@6 L#t2@+|D~Dv@GLƍogg|2O#"v>bw/b' GU\l|psjC~Lhu$1(]Tc`z&;h1p*;p;Kt}l @k\߹7~뛨ƍeW_Q.z6.zޟ|?şme?/g[x_~wK|=">Y%>ݭ_ZDyp,;HbPLD5JEOvBώegTc;Gog5;4T}rݟ};Q*lԳSRjv@GᔊrvNZRQ9c2s"zvb xl'fTS.wݟf'elԣٸp2} @*z2+;Hvi!>Z:cČqs5n';mMZ[}Jv}@v @~dX|s.; 0رpv宽UNJeVSg'̠ tRQv'GQX(c L὇3.ָ 3ڒg"V׸p2} @ꛨF]Z36V*15;gL6صlh;E?ʃc_r%;>EŠ t2ЁD|Dv>)fSca4F=Negdv2(ר t2aʃc}@vv>7W36eLnS*zWE(g]jlh;}/lԽZNQN6A0C @E77&@W**+Dz3.l}*#-r%;>Eov @)e7p@|DvЦʃc7е*#b@Z~t43ڎg$VfPh5e7QRѓ$R9'zC՗b`z&;BF=Negdvj\NOQN6A rըƵ@2&۱pDz3.h6nggjvrj`QGedWvd͹ /*=1~hrv ez,/h+ в ] @N8NԖ.dgmƘ |hHvЅ? 7QNxfRʃ &2(b`z&;Hl܎gNdgmƘ |Uck6걼p*;|!;KWd'ܧTMbP:􌃠Х.9F=;h#djDz3.h6ngg@2(y@(eOn`z&;HP[7οc2lfCi6}`Tբ?JCWwؠ+iz,/eXh!; 7W.eP\]@gNd'mĘ ~qs \jK6qUF&?FiGUTc;GßNczxԷ2@KzeR6OƠ  w=|<4c2t1">݈O4Fd:z]XrD|lDDQ7Fc\j U©K4X^8/Nh h5^ @3(ݧQ[Oggm˜ @{\f~oqs57Wk~bPXD5Jv.9F=;hdZ_@1+̗TF& (z@zck4)z,/eȤA%Ֆ.FedWve @N6Ymb}c2t Ջc kRQا2[z22ih\Q)@X~t Ux&p*; 7W#F+>UN6AhS};&s` xdr4jѸ Ѹlԣtw>fʃcQXW`S4Xh!e<變VըNdz$= @N6ٵw?+xQ_b8šOLypaHha+zlkԠ CꛨZN}Jv}~o@0(mʠ tFm5?8c2r5+WQr%zvr hRJEO<ɑ 4nƍxI2@qXh5Eeke }z&ϜppJd1t!; 82S{#3~]1P\;;tkԠ CLf'|wK @N6Qm4dL5jQzx mt᾿g?20lCтÁS׸7οcTkGW@ h1ϣ@0(molœdzfL5|>"lԳ`|>p*" f?x4>_wjP!TF&ͷ3H`630=tkλERϽr{ӨFŨ-]7fvV3'S׸Qٕ*#qAԖ.xdDggOAh3}|@h6n3U*15;E?; ]}jԖ.1jTF&olKBԖ.d=* @1(mw0tgNDQZc2; Szk&xDk-G q̉>s|!*|Oh;G⃿;%uŨK2E~5 IDAT?ʃcQ_p_VRN6Ah#};_N6Imb8vvЂȀ <=p*NE(6,BMTTdA[)*1P\>s";p V4&w@ @z`\;;^9fLxjԮ^҅Xh lfk-G '?=7Qjs"ʃc10=c\wwaA੺vv>hY/-]=2ʀA<=~m˴$!E_@h,,p%cqDr{ {:UMBtCw.uR/ޚfuJ#\G- M2sGj~{_|Pre`5{(;NN_bv0}OggtMkf4׮ֵ%cz 6VSeصX??Xcy1.xbGT&(0H*Nz'xxv;T~>;^rl][̓_x(޷.k/}9nx/u)Mo懭o][K/x Quަ61[ח⇭)@\뇭\W61w7\%;xFennƭ_较k nnֵغ͵+9@6VceDBD}z6F,Sť?Xcy1;"h|v[Z 1(@} negdt:|4;ྴ6nFcy1ۛ9@9 U)Q]:;; TvX?3v+n-SRmbovONv[c @W) Cv5ˋMKo I:V4ձw0FJ#; nh,/YzhP=&fv%; "¿G@ w0;o+ޮ:6 dDոqT8{a,J#˧EѾs1T۽׀0P:;FwPNz̠ 82P~sfRIɈ 0ˋX^bH=a(&F}z6-e%~eEmb&"jlE͠ A`ձɨzlQ)1u@1"t[f8{*n=ƮCRzSśsKhތUށAӾ1] Gx;濍_=@_r "~<&9050Z7㵗hmƏ:?JͯEsjD\T&'|K)@Ioo较Xvv@DDTe2j3\fv#էgĭ_sG:;X^b6Vs!\͵+~1`=bGvtծg}=\fS1 ~1(>=O(i30uXrl]_U@hތq>='T|H\>}4;(1uؿ1?61d'9]AP=j77ҙ `=L^~1ˋiw0F,xh1`4Sj,/ƓJ#;`TvG ڕ;@UNzh|v0F'dv0D碱9,Sse|Hl][r[Kgb S۽7-egDDD} sd?ktA @5׮z9ձɘ:|4;f8|(VNڕ|h\>},;U)vc@ozTNxKkc5; ""j3 @UUNzh|v:6@m]_o\͵+Q~;F=mX^tNs~ʏI 0:Vv0~RF}A(h]UjL>bGv PBb\<9pܘ Pjۛp".oO>s$;([KgNmbov[9A0f'=p";H9ձ@ɴp2.gOEfv@߼}Xf!-ިO͵61-00A(Jv @y5y8cdj][KgbxQsQ؛gzvڕ 3?+v8\ %~ @s1 $cqQ~JsJ\>}4.>͵9H=Pcy1Mޮ61ePH}G/{ }c ɹXY8a3Efg%X^N( i!`PȮf'=i߉[/$MƓNN_?LJbeᄑ:X^'F}';~F P$ϪMd'DDDkfv@DD;G1(:6E y([KgeTGdT)6s~~Ct^NkY]i|.;`vNpM@y1`vo!eLxPdznxr./eO귳t&;`&f""v%;(920 ӳ @Z:8 '9ձ6bHڷ7Ǣ΁@׵6Vv5;``T&P^e`T&dg]nn tvM\OōNNvˋ R0* M@okPvd`8;O9 ?C2ҙxb.Sr t]cyp۸G Of']nnz/ d<̑ `0$0x:V,˧E?`[KgFmhmf'DDDulwv#e Y}z6*Ŏ g'}V)w}xҐ k]Qk:Yul2; "":; @d=.k77Ѐ!6 Kq\,xr.kWSBO>s$;(غ0H;6V""F2(ɼegðy#Q؛ ո|XqC2Pf\>}4nWEm$FJ/f' Lv@tڭ(j @D٨;3.j77较k `p2.>͵+9<[Kg≹غ?0LsJ.""c XNJ̠ $ٟtў'^. c3G3i߉ qĜ9[ /NNvC较@zPN_M('2>=t'^4}s|Os>ǏGؑ xb.gC[ז≹غ?0KJQ\kc5; ""*yʨjtAO`īq_=OK.#?Em$;͵q) Np~[?}_w 5lvҋ~~d͸|hs(6v%(j#)A}'*Ŏ aT6&KO'&c2}%VDz3D͵q#q)c2q#nnfPBuU&AH`P R)1uDɸ|xWո{G|.;)j#QJR0*3\  @UjAvC2isا2 ӓ xb΁KI݊p2:;9D:42@:@>OAu?C2oWU 5{(F=YO }k,/ƥ?)Dmbo&f31 tCs$;22ge`<ȐLDwڵ. ձxOfg}~a>.ޑh]N`kތK2S(s @4׮D:6 jv@DD*0L*E5{ X})k5"v/t4 Z7ceᄇ誕\Sf&Fs$ڷ @q C:;;'aR6&ç_x1k]r0h;Em$; qO'ˋq#iNa귳ٺrv@Lv0ĚkW""(2Ge W7dt T梾5< ͸X??@ɵ6V≹hmNaiތKjf'sǠ I: I9$qSq eMSs@_K2Z) NO}i,/f'Mf'Cv5;(Jv 1跏՗֕{~Bdvg]o#?'n|,`;bv@J##s~@T`Xxzc8u}D՟r|ug} ׮CQ؛Hkf,p>4l}?0g[KgbicѾ N#0 %zç_N\ձxOfg=rkŸ|1Rkconf}{0Ԫc 3h bHvee{g'@)kHMXw_W)zӾ|x8{[^hFexfe'%rkLv@Lv0 d0P}yzckW`[qјzhMbÇ@Wl][8]67;bf#;(GӳQ)vdgwT}Lfkc!unl\>}Ԙ N݊W^8s)lfe'%i|C:6 )#(vzA }HЯ|-)@oU&c\vEf\zHZ:eeCܓ}RT3غrv@2@NNv@*Pvؖni#2oKqo6W)1uXT)@4ōne@W,ڕ:|4;V)vD}z6ˋ)@ l][vs3QǠ @O: id?ﷲ?0ձ@twSQPJo~=Z蚭kKk 3( c{2y$;ʬ61ލj|zSqW60c2w~%_eg]Vu0 Jq3.>5X^ n V kmf' %S2Of'{ѻG̈?tYc@4ōne@ϽyծCp";(j6nFulwv @U&:)͠ Hul2Hv Ab|KW3.ǏGؑ<g?dg@_5nci٨:tEcy1|}gPҾ#PVf'X})GI LDv !twG0-GӾ€;>=RT&!eP @xh~KO'&nv{)stQul2egv5.h^kcը h$ڷ7cRv@tڭd @;GdgNC2o?e']6uXTP=DUv{,5[ ç67;Rn3(=P߳?;vyӧW.?0ձɸqTv 2}غ;Jձ~@6n;DDzv%j.;xf\>}4ˋ)07{:*E5;(N[ז3J Kkfv0*Ŏ @;G:;;Rl!7NRTc9ka;jm܌Kw$Z)0Zp2;b薭/g'A KNJeSNX})kzDMW6~)n KEQSc\,mS *kqkLvP[זӾP1(diތȮ]s%gP>=}S!7?tI}z6v>ܧoQTF:6-辧367;Rf#; ڨA(GL*E5{ P~̧_(՘_}"tAc}+_:nLRcy1VNfg0vNJ4`;GJ%;ʤ>mLrīq_=OK;bGvpxXNRh,/Fs$ƟN!Q}z6*giSmv%(jQ `4o^x*(GLj3 {x5?Ҏ]>==ahm܌KwĘ th, Qa蚭kK }UNHQ۽7;2E~J=$?ZvSe%] IDATg|..>v+;JieQ!7`vPB! CNJĠ tImb&*Ŏ #S_p-;肩玺.mҋp˜ ‰hm Imbo;G3hmF7ձ`oǠ tI}z6;{+}bR}z6{\vp2n=CFeX}$-e'MwEm4;2%e(ON|>~[}?|5;xHSegӾ+ 'CnGӾB]NJo9`T&!dVNĠ tAul2ï3fYoWCzhT{G@$FeWQqj}S۽7;Bv+;( 2_ܯQvF_?d'>=={h77XNX$w0;(kK }SF!dP2,>1섾)/3P)1uXvZ71&bR,ΠF8h,/f'Mul2;B0(RT:;;ڞ'^=OW9;xHSJ#;xqQoTX^ fv@_xF0(~5;;]XvAg`8;݇ COFؑA/ƅ?vخj3k {NJbRv@_8D [sJvPe!xpN󿐝/egcbm]Xvs3;HTjv0d:; <#;2#P z }ҷ>o(;xձj.;)+ 'Jb+'q3;ٟ5CdpMf'C 9 5e?N|w]=̑r[p›K>=߃p؎ ޛܧf=b#;xfEm58 c2PNոqTv=T)vDmb&;(ƪ2`(;G!i0(RT<(~ ;opTjƘ [cy13qݱum);c imf'CRT.0({ovtwp ?fv;bGvpXY8A[seawAx=XvBϽ[?Smb&{tAaL‰dgEmā+-JRJQHfvPevNw5;>>UjL=w4;[d`6VSHmb&;(kK =g'2@7T6]ug'Zܧ]u ˜ b4egf'%\seaR) @䍝 =sf'9OegaLqTގ^6ձ]um);犝ρi7 N ܧlvtݵ8;gv~3;OSe'aLNp<;7:Vl]7*[ul2;"F]gPCFmbovt7艗~G}OϺ~aޘ j_Πj3 @I4o^N)2vcPCmC7F|~5;Segk,?i|4 I}ۺrv@OUQ)d'ۜA=gGn܇sQ)vdgPk,ZY8P[TQJ}{3Z73zuO /Nr&fdPCmkwwegte':6f΀fLx?ۛ~~>;.Of'%\SΑ{fPQul2(ol™܇'9Cm1Z:[ח3 @I4zʠ Ov+; =Md'@ϽfzvpӳQ؛Cq3Vr2;FVr2:;tAulwTjvPU @ynjv{Tp+wߖdTf~Uj<̑ ZqQo;K݊tݲum);g# }7lef'@_|}@vCNfvpv6P C}ǘ -ueP߳?;(/g'01(۟Aic2 xWx(";GΑj.;1Vr2:;< @I4o^Ndv0$\Wˠ ܃LvK[ ;e-;GSe'PzsLlsv+ggڈ]i3P^  2 fcx W7Gƫ &f67;ҍ]sk[-e'Lul2;Q 軅r^M=w4;h,/fg%p";dPڕ)j 0 d3 ۟Ax`X]Ѹcn/73{kP :^4&Df_!vNJfv@O;ne'CRTdPއA7?7ΞJlm8 tMMf'2>ӳ qDz3k =?0bGv Mc2@_|dv>-[_NJ#*E5;`3(:6+Cǟlθ'iŸGs$v>C܌˧FN@sJ4eg Ҽy5;gc hmf'ۘAx77x_ =:|,;J}'^y1n=-۔@tڭhʩ9s C2(>=x{; ČM^y7}ib|v:;*E5;(kK =aP {p~qDz39nsG`,ڕ `HZ:&fhތ <70 ;ٟ륭3""n[?Es$F=Ca|l][xGv+n=}Mf'%\3 %`wP۽7;_fvBDD|~?;xSe'Pغ3Scy1 @7ʨf''2S#QF3`5[?@jN&f6azq3Vr2;n>ci޼uNϕgloe&f`[~K(NN,NpOkWfT`[:ҩMf'A O4ܛK?_p6>xoFmbov‰hmfgܗ #nj]NJ#;=RNmc/+sӮſsaPNһbl][o͵+uuv`Pͫ ]z demc"较QF3ԚkWS̵4M͵+ ]W) hAxLvl; [}_ (NN Ҿsd0 vNmov-{kQF3^yxtڭ ~ C@75׮d'tU =UF`Pƃ`YX},Uj=~a;4ڷ7|.;Q4 tO PvfPVul2*Gg|pv4Psj _N}T&1 pZ 6w?ǟC[2IsClPfM>X=E^s޳X`bQ6v  9j'd'5ڠ !k~淞dϏs |ʠ ?ibwߋ΀FW/~7:Ϣ3x2^ X62@ftp e ܎N~7__7 :Gy51O>At/P) yc%:Ro/~ }Mz~Z}/:4=FgܨlQwc+:hrt0+uePnlNQH_|ka'~{a,ƛ|4;'EgxCodP v>wZ?oZ^t4ң>Ljr|s:Ŋz4=`f'Lz H_|گU/gn:yuc8zOG' Ͽ@StWeP v>wP,JOEg@CRJӣaIt)V @Ô^ h2?@ jݍ-O%:7_ݺk`|hyu}at@mZpO_.x|@a 31=yu:oorePV vM_?^Stӭ31yzEgde^ V嘝Nk :h~E<MEPٛW4=Fg^F' 4;qM_:<0:ȐAZ7؉NRJ2_ӑmnP_+ @Ccɠ lG')/J_OOA5 vRwc3:Ru6hT_EnlE' 5;yp-'MȗAZ7؉N._G7Wo U9IO܋h?N` + K) U,@d߇~2(V7؎΀FxE'4atBX2@8d ԉAZp,WVr'҃_tk7 :tT3:0:Š >ۘH IDAT:1(@y'ӽRJX3 {<}Gg4Ƞ @0(@kTsғ//NSwF'@# 2Bo@9r@"ލN=yp/ͫYt@LF'` `PVmnG'/nl{eÏ3Ziz4L<:u:oD' fPYwc+:`2(@+ TTM3n{E'h:>sb g<~|zhbwߋ΀MDgat loV}\AX[Fr ލN}G'hyt 4;E'\Ywc+: dP v(GQnY{TM3H2*f'{%. x4;y5΀VZ߽:Jtdk^?V lUy=248ޏN}Ert=*@]z81z،΀lU$ߏy5Kat R Wyc%: dP vo0S9>΀VZ߽Y{E' Ge:yu524Zwc+:d F3 [0> Yf'StRJeh82PO0:Z֝F'@֞< Tg4;EgBoA WS  tS3ԑCݻ |:D'd͠ )3Te!=|^az4N`A\CuePnlE'ߠF'@+{?:t'd`v8ͫ i WvtPjdƠ tQ9>N)Vnb+WɃ{0:WT]ʠ ؊NAyޏNl=~쩟q932WeP vT!{7:4ӇDgp ӣat b$ UF',@ Hj?u 90:Zg}pEOy5,NF,+qhÙ'24sNN4Pu6N2cPF'h 2pyd͠ @\c0(\AX{̼:w?ܐVnlFg@Vyz u Uit@v ݍ97g}ntd4f,Qu6IU)p3_.ˠ aPF'@k˙WO3 \q0 7a1z9lX:Jtdt~W n y SwF'@v?N8~+a- ދ΀-b j24B[N܌dಞ|nd5NG'dŠ ܎NޏNTM3aSmyttXNZΠ ؊NS~nlFg@V<@2yuȍXheh7@T$ͫYt4JUNR9> !řrr E\P atB\"rQ -OsztjX.2>$:3/2Ǡ nlE' v 10nv2N5 [vtpXN b\`PXftdv2NȂ@@reFwc+:xf^y5΀F v eX$7^OUF' fPlWX{ P{U9=Tg. + 3; P{ӣat ǫNF \Ap-ԋVXݍ- hjP{Uy|x92dXG'Tgh{ P{< h@p3 @ 2P/b}':joz4N澚#XNtb} _eBwc+:x*"E،΀ڛ?N# <,Vos;:jo^0:ZD'dgj@$2d<,w@t Geb\iX*Oju at@mztpD8j?=*1u+ \Aj\0;y0ͫYtx7V | 1mnG'@M Zy pe`':x!"X,uAtkAVM+2(@`qDg@NFnL`atB-NF sˠ W @]̫Yt4h-@ݹ^ beVtpA9nX`':joz4N֪2|beNэN.p7؎NZW@ :* PkMlNIt4Bo7=F'@xVt!2Ԛ@}NF AtVUNҼEgpEe5OWh`':joz4N%yP͠ Vg$ f'4fZ\@S^ 2(@=2P$:7؉Nڛ?NV+G ԀLȗAjX5&ubP7=F'@y,@}>_.Ϡ U֣ $ vչ9*'8 92Vwc+:A"X O+ jgP꼱NF^UUTM3^[ڏNX:1WePZ*z 0j?=\e @K1(ksfPZrԇp}Nt^9:NV`q`^͢k0(@-I[ Pk Qa0(@-=2PN D'@9 y<9>gʠ S:W^wc3:jUeY P;Eo=:!O WsxbȠ SgytdVTM3Ռ<,6M`fP1(fWVtԚ ּ:w `,:h5WeP)z 3nv v\X :+ @ P;j?:x!b&OxWrtv @}̿>Nu7չ2µs #cP)zq!`':je`f'!<1͠ ,n+ jӣat@̫Yto oe\?\OoV\h&2JڏNnlE'@NG'@ra%@uXN2fPZ1(Q ker,:ZdIt7PcF: P+ Oxrd z(z$( T V2 wen>f' k> "ՙAȝAjStg,:lG'@Xӣat/Q֣V 3u7Atؘ ̿>NXG'3(ٻ6<߀AbPH:8JHCuv8.|;<7̳Y951Kt  @p .YϷϓv7J*\ gP7D'@J)r:9N,mr`PlE:N2(sCĺx[t `q\gPT=s IDAT+՗ ZnfUXYuuwzZtBý`it@eȆn w< \E'tZ]E' G G ZfeEzer+:XߌN-8zat7 ,:x 2dÍ8:Zŝp=c Qt@#[Wh?2dIpǼF'@kȚ IQnE',Żߢj@{TA2lG'24NtdArj78}_gPWSQo ĸx7Jz-ʠ Y( `Ntdm:9N/ zoG =ZNAm+|3(W 1(A6;y=N:( A?ȋp?kze tr)WgX 2dh-:y=Nra'\Ϡ 9YQг7VB}yR2(@&zE?:7ýȚ1dM\-:QA)wHIt2da @7 y=Kz+g:9qc39/]lG'+ e~r+:6G'脥8{*:`eYt@Jɠ 9ȇ ]~VFDj|+o +Ã& @ b-:H"\ύ(n:9q,t.[@ `PpyN\ sYgo^E',9+PWg @ ΍YtRYƇ ^яNXwE' @SVaX<2N'^`':`{`Pp^t0:Z( knbx;NX^яNtro Nt漋g8 ՉB TV.8=N?f @C SZtdm:9Nee( W#z@,7@w '@>QtYV.~;=NXyyttABy mNVb}3:Qz.ގ3`@k@3M2(pOp/:6 ݜwvX)XȰ6%@w L./ϣ܊Nhyt8 t F; W?hrY׳JИĈ#R_rU=ZN:Ġ 87rИ(Ur+:Xquu4Ƞ ar;7!. Y:{*:`9tqm)whA2=ZN`T ]zһ1`usYttARJe~twPnE'4t<:`+M' @G AeD' n 7EЈw#Jr~ȕ.ptA~t[9Γaf b}3:N+֢2D'a<hARJ@] 7]T3 @ 4xxtAtIqtF9܏N@N2DnrU_G'Z: n1(@tX.ܘ7g(: Dp:N: [<e:9N/t{y p8:舢܊N:Ơ !\@E'@ @n0(sUt@.|44N:XߌNH0:hAB2D'@xB @ٛ<: \M' @Gx@42y=NVq \I觢lPm96)vt1eڣ?؉Nxj| 0mk:9NhL5>NfP.<(SWFg*4G'|A\ wVQ}|,: \QnE'\i^O09tAB~t.xs, .vt½y:{*: \p(: O`E'@< \{Yt@[r @SYt02whwy=Kgo^Eg+ <yN;tA:2 Yh8}ztc` Ipʱ,\Σr{/:,": ~r5G'+֢ҼF' 3(@' /QtFG'@K2WSQnFg Xo8 4ŀ Ù=e6ޔ7ghg9,:Š ýnn40(j:9N::N KWXEFm#,": zZtf @G9ɠ И:NR~:z4: mVK5>N:1(enmOXUfy^Dgd@<:^яNHqteHuuИ y=ȊA WA9p/:QeXrIpȍ _.iӠ̼^DgdXߌNtrp#2dnf ; v:zW(~ hJPnN0(4Ơ zE?2gi0zh A:M#i^O3SoF'|S]E'QnE'|2(ҵBn#Dzk yzN{%9/ϣ9UeX:'h+Dz+ r:z4: Km,Vtrt=` p/:Fuu>~-7WC<ȁL.2ToF'prp+dWSXtrtH4:X2,p /(:Z(Mat+ދNQ]73D'|A)raPˠ K&\`~t>9: kmVW}ytDQnE' g@a#(]Egd?؉N&7ZMq,A[pQ'@~t>~=NN=ZNH).3(p 5k]j|^OEpy=N: jE' bP49`r˟8ڌM0 3 TNP!8Hyt@<ș9Ivt@J)8:X2PoF' p?:,}|,:r<p%e0(p .WM_?Kz Nt7R[ )` jp?:JuuNGϣ3ZXLb-:JndDȅ1t62,@^t•St@k:RJuutH= e TNM=NR5>J0:5<trt!= @7)ct@y,f~t 8Oʆqa'@r 8Hyt@ dPh Qt@ehb}3,}|,:Ur#c@S`E`r+:>9it@{ Tq:NȠ K +@SrGͫ v:4:~t7չ2,'+?؎H)TQt@k{ KI3(Ry P *7CfPhRZtgyt`eh\?r<2@ gPź$dc :!yYt@rgPhA 'z,AVtFG'qp?ZދNy=Kyt!991 gPhkh t"U V+7SQnFg|+ 1(@kDyYh@kTQ%0(Ҹ xb}3eMx^4 ?r7G'R[ 1(@+l<>/ލQh@W{ 2(4ɱj|,AZac ,姰b}3ftCr+:X1e^rD4G'\E'S1G'K`PhLw/ݶ{F(Ơ ;7WMHf  {Q2zS{tUHmTC/Yte4?Ib-:Zqt!E<:X2,M؍x7JoG! Up?:ZzJQ^tgu 2,MbnW蠍/=,姥/@׹trtLQnE'|f@VAip3p{"l,=cӥ/@m<^g:]Tc à =Hbmy:z.ގ9qt1p/:3y`u [_yR`UlD'͕@/?͢%1(4We4K}OUQUW穾<:(`DVA1vt{z>KpiJMsc%дr{/:XQe^I`ՔV[ _0à Y=XY?m)Qt1Nt rq4M=Hbm)ϩ<_{rpj|tLY56 Ġ KA+ t>go޼Z{r0NN1D2(@v6vuu>yPqt1ftatDeFy&{z%`@Ӝ/"{趍/=>4/}V]r3:F /T'G  + }wt:z1PzfPh\nTcP`; Yt'nW-<姅>_ZH@PeT` Eޠ]BrxB_%BT3nJiheF랸 ~z򧅽n4`6vn:9N:?؉NB5VAQEiPYŻQ:=_52@[Tc E L''/?-rp$:`': 4`1XL׳Ӽ6|Ak7rS%p/: O` n y/NB^o[:@ MvwrX=e ֓E:{f JiΑ9` 4|4EF_/n5rzZt<՗@; _1 Ǡ K@s\@ӊr+:zכ׳kp{ RE'T0g @2@Zy=KӼ6܍A-atAf:9N+ A* ?F?q#д^Ob-: yt <?؎N%6k\v| IDAT^7{=n[32@Yt \P+ dW֓?5Z(}xs#mD'J5>N:ދNJ}y0(,ppFkpN* [NrnȑAXMeHź h/仃zcx'OnF'dPtr0(X_N2{p+zh\觢tnȏAvXMe(ʭ2~a5+2(,A Y_Iz4 [Ƈ @; W:.2¸?*(>:.zAtJ`!rTW @ 2p?E@F<ןٛW zE?m<6(E1(䨾4(̠ X62+iɟߜ^}"]E'|8:dPTeXO {2@T~t4:dPXbp)}{?.*7Spkuu +U'G @ 204Nv{vCɉ1;q#%(΃ A[N\H ֓y54ac :NatQ΃r62R* tTQnE'XLo1OLA* ;x;N:WY A`m=yzcL]6p'ɉcM`!+՗e`ø`u4(3g7߻ZW֓?EgI5>N:ދNtr3(p .1(g'At WF2R*ֿ}s<3io1 .pgoG @G+U'G @02b`뛩]όS ;nXLb-:Juu3(pKuuD'd+d뻃(:(>՗sUgP\h+R]ugL6vF'U4D'0(@J)܊N<`Nۘ @m=yzZtչO`ar5 @ R\ljIȘ @m=ypgQtap/:J0:ȀA[r#O=ʎ6ѹ3-A7XHD6{~gΌm[Uzw6.oStPftgח @E`f(: × OCPK ru|4UV/0(̔P},Ob YO @Eqy5T_w{7:ޮ+ U^_F'aP<+Z@-N-@?E'cP?heytT޸NF0(ձ4x ei? ɠ 33<=Nn!F'@9V @V3mxz(:hbe3:&A o^t\D' WhxrTAat4F{}':ZIE+PoWT]9N*Ơ V#Ŋi 2:?Iet`ԁE2(pGO YIb':RIrq?:hEӣ YэNv 6XNxን/*/ 2(drxD'ieynFgN.zf*oxrTA F'@-C20)l P+Et]|x4_uP/ 2(̔>:p܎[be3:Fw{׻`M/:p +e/hϷ0YK;ϣ :yo5:G @EOVtT^9NF{+xݔ 4\TK1(pc7 xOl\ޤ \ԁK1(dnY1(gP_`PQtPQe2uO 8ft-?ًN (V6^D'eP(:- :˜8P&]Dg -v<;P^_F'eP?{ P hd/:`"@ O 3( O[jeyt¸E'@7 8ݔ 2@ח @O MˊN{(O&b\ޤ `+ _5:TA$D'@-NFjo 1ۻ)+:aLl 2'2`:; O&~t0Vt8|AR[N+ Hyo%enn怜hqy39`Pqy(:02VG'@ח X'{ cL :F矢3(L˛EmOۻ Pkݔqq?:yo5 2(|Afʋk2p;":)[d/:`bM:>@ߊN1(gw/RVjØ 0+ftח @/y n ntN+ :;x 'bxzTA0(ӓVR6u穕-DgLL9LO{Z(+_gPV^߉NheyZ`N[1 ܆Afu5qyލNXy.8G's1N2m`Etpyo5:j! NtT^Iˏ3&^zLߌN0(g<:j! NtT&l]t0'Vt9܆A>+[D'@-ח hK;ϣjn? ho nY%6 YevӕV3={0qI3SnexzԄA> P e`ۻ PIE+ ;;x̉Vp+)ePXD:{ P rMt4Z{c:>NDb2: 2|V+ˣ6ӕ2ۻ)DgLǃ4.GhD'ܚ3Jm|L𿵲<-?ً`+ 6<=Nj  _20}.,DLF9NjĠ _Vk6`-vEtT\D'spk.  35<=NϺ0>Zw@3NHpke0(rxVR؉0E+uFgLE9$0SE+:^  _ 6`6/ >:#E+ [s6 2|Q[Nphf!ۻoFgLA`U@}˛T^_Fg5bP7 d 20l!70S,OO3fxzH`; \pWe9/^  ܖg]ntskF>:#,Oyo%:֜Kʠ _-HnL&:B{}s#[{S3.oAt0G;1(ܕA*+ Potw`&={0UWi\39Rę$ Uyo5:jcxzsà o :`.>NL{P/e2(2:FVtxkD'LU9tZ1:?NjȠ _U6eP&[~0Ug9D'܉H}ZYVL٢hl/3~t0g; w<pe2<=NG^V0UWRy}̑V7P;e0(y -v6:Cqp_e64.o3`dEǭ^[Mˏmt0gjje K9Njʠ 3g%Gp7{az{utL ORy}̙ :Ά'G @M`(:VG'@ O`͔-v3^/Rߌ9^߉N3ZeP[{+ P+s@G'ed/:`&A`ŎyS/] ܛAn-F'@m O`.uVGg joxǠ ebe3:jš4x ;0{E+:Ά'.qϠ : F+[H '{-DgŇ jo ´wet~4A+[D'@ O`uL-?KY(0F's1N! 6(uVv հDJK!M>:Syo5 {1(LAoF'@jn?M٢VWo3œNXw{7: bP{1>My}etRZ~}t M Pu}t0{si0)ee7[Vtv'G @J4 1Hu- IDAT1?Rym`V 5NBwm|ګ7)+:P/ŇkoT4AjtS7_X~@uwS{Ø PeE' ePPO - : E3uw3={P&\+ <=0-e5&:4<=N>c^jeytS*m `ε7gP2N0(4 i1(@( E+:ji\$:-v3Mr\+S{ݠ Po+`j j\ { P[Whe ѳ{~_R{Ø P `l!e  T3Vo)Jx 2@#?E' fPpӣ`jtS7zzˆ6:ZYe8GLA&  AtYIO3 (QFgg5ɠ `Vt+/Rfz{ѳGgTү%: dPhItpeW/ ( P[Ó+ZBzutS?GgTR9L ^7(ԟX`bjtҸWoEg0%|Sje ?NH)0&4Stpee84AQtp kޤVGg0aNE3:e>: dPhatpe7&:uq?:褥LPw{7- _Kt@J)VAe*/33(@q9N&$F'@mחit~="ﭦG^GgTV9LGg @?E's {+ PkW[!@<1:;2@S O9`P*[ P[W -ʹ4xzc$ M>: R4 YY0(@%O )V6FR9ni^jeytd/vv6Qt@J)Nt O9`PJp #F'@]D'ګ7Qw{7-?ދqyEg0ӣ`N @s52P/Ajo.jzut@uJtD O9aPJN&-l5<=L&:?VGg,O|Sje )6.o uw&ƹy`V 0qE+:j :V^+ưm ߵ7 3<9NA*:4K[NZQ{}`P ^ft@˛t.:wyo( ƿD'zx4.=#CݬzZYn Z8;xFR/&%,Et0Ayo%:j :'{^qyEgA{c01``ŠVtnl 8;x(:wAje cP%2LEvu|Mtpk/L,k,Oni\ޤw^߉NrxV` Pӣ`VtAtpl!z0^Iyo%:6ަq9]+SwitČ?E'sƠ SV>G'^ :`.1&qyEgw@ O\ ̖A*:4K+[0*tu|MtpOk/L,+~P+goӸEgAw{7:` 1(@e8S{je ~E+|P+&lftČ3gP(/ +V򃇺<@LKVz[^߉Nat0 PeyVtA7,?Kyo5:ZYSje\ޤw<:`F矢9dPp4O+[Hb':j :xV^H,Os !୳@Uv@ O9dPʰT.>N(ﭤG^Gg4ګ7)DgθIg30q`RMt0aeᆧ^Fg4x"1tv6Qtfxz)2TSt0aft4At0|Sjeyt@uwSwit@-? F'sʠ S-v3.>N&-Wo3j^mp_dnF'L(:Se LE+:jot) `냴4xPKyo5=z::sZY s>bP3(q.:Gjt@?VP[ލNQt0 P)/h }O2&p_2]|x M4:12L]VtR؉΀+/$:G^GgT^+ӷ?;FR[Myo%:`↧ 3(@Xa*[ go n?u*W|>0xhQt0 P)rLA`={jt@%ј _>ˠ DgPeIt0ft4¸FeIZB滟R+ˣS*e叩4:Gixz3&0 A*;4SVtR؉΀F>:褵Wo3*ci˜ Y0(D3(@?E'SRҸ&>HKۻѳGg4Ň8TVIAtT O9gP`J \|xLgOyo5: Lw{7|E'|V{}':`*F' P9njo]&Š 4׷?ZY0syo՘ ߿2:ೖvG'L0: 3&:Vjt4SDgSҷ?0Syoo! 7l]tg 0(TA*gt):q}t0%yo%=z::`&gL-D44.GލNQtAǁ&hbe3:à 4@rxEg|V+S{c0J0(@% O@Shq9JLѣgS[V?_Jko <5<=NH)`ZقQ)je ~J,NVo9录Fxo TEt  E:4[1<=L2:og~^<Ͽ*(r -QP/mKbDvjLet72{he.qAy i AmX[2I=b /;+?y7~^ Ƙ y`3;UzZ{w'; " 6;Cm0jbny-;8=}XN85薝 0(@í6{)*E5;A 5͘ zvNvfF>~bPd_̥嫣8~z`nvTfgs?5&pJQv7Reg2@?1(@_NN`n?Nzdau# 72Ƶ -O Uo,e'Nv1(@' )CI+ʶgaTѿJQNx-dN~^tNv*'6m2('3`n?Nz:u&.~}/megSucPU:NN`Rsk˘ 3& zc);Tww~AV>NNY̥*嫣8~z޸#|/8}C@7RegcP9x:_NzlnvL\7dz壭bv?`Po' @f`G>zlny-Sg3W{ɨ^8U~Ƞ }ˋu  0tXՍ`nylfgSNek$;8e:=K2*d2&;{-;?RTX8UE@_2(@_NNYuL0Te'3թ3q `蝲}/meg ͨcʘ Я WG @f`e'Ijbny-;dz6ݼpڻ; ɠ }lf'=0qCs"{>XQUo\s?1jVvkNԙ S{ :/8oPN tFK2&{Nxm͛ [[ekv2n?}$[mTx~~C/0AZ{qv#Jds˷:u6;dz[G[XJ1p|32nyt}?; FewR)d<ݲڦ?e~fP9x@QtNAW@J1fTxk dvpavkGQ8ue(WGˠ }ϋvJ/>P)Q))ݘLuLv Hz`3;Lx#;'~A^>NzdB3;R({;@(jaTx-drGEvk+'c8;w|QQ;ֽOT~1\$^>x#Rv@we{ݲ7i8~Ҋ} 2)'${`nNl@3(@NzȠ V:X1D8~Fꍥc=qePPg':~ҊnyzZ-eg}:u6V7HfvnNNv2(@(_QQ)bB3;R~^vgd~~t^dg|TdgD< eP;|v g'}Ȩ zc)omH-O壭 7Vo,e'AaPP:NzhB3;VW@2*XDijw[v3H1>Ƶ id'2 20ZdTfgz)20Z7N?iegzc);~Z 0:/!Qn)20O3gwd')G.JABD<z6;Cpavnjp[^zZv[$XJ13ݝfP9xPuL0{#S)aLxh+;L7of'ӯ^AA=?NcݘLmRv ˍRԙ jﺼ eݲXC8:@3*:u6V73_E{qv[\`tv} 2 0zSg΀ߺ 20nylfgb|2k=u7bPQjleg zc)V7Re<f{``M7of'Vv1((_9 hB3;G[ 0*XdP{o'fgJQzc);It^dg2 NvcQ)0F62]4ogg=ݽ%izk IDAT=Nxce(+\`M\hf'{h+; Fe?Uj-tFv /| =kI+;` A8}[dgĨ JQՍ7e=:ƽ6qEm2;{ޘAJ{w';H0qCou/;0ƵXXwUFTd?Nx'͛ =9؍Qv3(@)ۇ @ z_ߏny %2Ș `ow=0ЪSg6{);Auw]euNeg:uƨ $7bfT~@>3tfv@'bPNLo:='2*5su%ogg}ݲ֊ɨ7eg\< bPS:NL\hf'떝oTuL\^ۊZsk1se%;pÇnNH0 0pavĠ [dgRQ8 Qo\N5t˓x`3;TjK)ޚAN{w';H2qC[vbu/;`gШNk[Q:kzvNtNv;FT  o͠ lf'&.4`$}?Iv0~3*s͵K /9~r=0FU`7WGo͠ |u`+02ݲ{[+1|ۘ 'ˍ wVo,EQH{N 0:/$Q)0ox/oZv JQ嵘zvNtNv;Y]OZ Ġ ɠ  ݲ{7TOFײSxCO[C6;Em2; E< wbPT:N~t˓ `HbQ))зSgcQ:'ˍ bJv@c200(@NMo:=-;fv0DSgbau#q7?To,ͨc)gwDdg|f/eg9~NxgeHV legC:u&o}թ)7bnvvoiˁC`hK | 2 ,Z`M7of'Hyh+;2b,V70*E5o}ƵR Qo\N=xvNtNv{Q)1ݼI+;1(D{ ԙXyTf{Uރ47Regj=Nxo 0d&.4`| J1 Qo,e{1su%V8 0$Q<^ CŠ |u$+jQ:#88]b,oǹf[ոz\YN=zFtNv{So,?F^{oo=``u^d'}my{nzey#.~o:u6?یޣh=xf@8~r%``""&.8V:31q QOfknތ[Q< n|^K["CǠ ͋{ "RlF<FDuL,N@#[vbu/;!b,Vtfv XX݈zZv /.NEm2; Vv{gP- "b|3*E5;F[dg#Obny~F Q:)G[K;~8;3(3(ąfvnى63To\Ս(ݞ @JQ嵘[b,;S-O⛿ 6;KI?iegwexݝOL7of'H:~e(;Aթ3xg0Sgcau#k)|'0|fd'SaP9xԙ('3`$=r#;Qb,V8@OM7oͨNN?m~^v{W pp* 0e'Iv'ꍥIF̕zTjv CRTq')nybHZA`X`(t^d'}  yvNv0&7cͨNN`fc͘8Nb=e';ཫGmRv@_ -2 OɨggH*_W+jadjJ,މ6@Z3WWScP9x!-O3W)bnv-Ef0 \q`Ttv壭 SQ qScP`P M!I~^v@DDbau#SgS@xsnF̳w[v3N7F>Qv1(P(_E<D Y/mE SgbauóRTcny-.~b,;zsCޓVv2(QmRvg_nd'J1?Zs?JQUgQo\N{;ߺpjf";AF{qvGj΀{ 3ݼ Q:@6y0jI|zv)'&|K<90 04:/>3ݼ#; :u&V7XNO㓱x󘹲@oXn853W~WNAANV: ?P)bnv-Efhy3o}թ3)$ow+=0Ԋɨ7eg_g':2 Qt˓ I2-@ߪ7gQ:@Uj\x=]$*XvI:fvN8ue* @7`uˎ@_+jxk37S葉 ͸ ny8Udײ3VtNv3(Pi=NfTjvs]$V7<7 JQŏ֣ReMCo/Vv@O` .Rv6~TmR\^ۊ ޳|,~=qUn?8Udײ3A`T`7`u^W?RŏORTsxG wMfl`$\Ev@FdgAJ(Ivgdf3`=yfTfjfL7 bA`f޸wf'ANEvЇꍥyݲ/meg66cJv oRTOcaN i|_g'AN{qvЇkQ)0[Ffϣwfc͘nN?m~^vGmRv@F(;g 0t&|  "?Nxcթ3xnN;Tji,މfWٗ=1su%;/5e:ݝO9s"[3Xs?Ս~6;mtFv }/֣[v3N]mv>j32(閝(G@N "^>ڊnyVjVL\hfJQXXEm2;>9x3WWR>9eJ^gy3; A>{';Uz\x=*E5;`L\h嵭7eǎbu/;'jQЗzΠ Cɠ }&.4>q w2q7k)#RTqc9}Ͼ虙+ }ˠ 0 0ڻ߭REֳwY;qNtf\^ۊ7_GdgDmv>j3R< 3(P!N~|u/^L7ogQN*d,nĹD`<yt^dgܟN[OZ ) 0: @*jzCyh+Qv{Q&caNiTjvooEmRv pozc)dv@:~uv@ 2 -?XNٗ tF,~i-fV\YN`tv t˓8~HaP{zZTjv[DZߺ^XX5Uj-(j9 nyމnNzcs30&22 K |$;ཛnވ66;ꍥƵFՕv4eZ>~7o閝xvNv(jz']4*E5;TF-ߎJ1:*fgՕ(j}Ơ C+j1q|V?meg捸 "*E5fͨ^`@uv U#RTcy3;?mEdg1(Pk=N\lF<85b,.~?^JQH1qm̕Xj3A0(Hhd'޸dv^>ڊnv@͸͛)(jޫp:{;fv@s?NO[-;} #8;Rv=ݽRŹFTf#RTO8` 4RTdg 'aP9x {t^_neg^[qQ)9nތk[1ݼ'nFՕaP`$wwQ)ƢXG[9 qym+&.4S1q׶ORe0?t 0fDQ]bP-;my3;Nb,.~ Q;X|,nŏfg[pav@JQK77$3(pkSg6;|x RooՕ`H1 w6{);ۉ63RMx#*Xv8~uv@_1(h=N7ߺ 3se%?ی `Uj\]˷޸7_gg*'cJvF(;`dfxvNt˓ S&G뱰թ9!-WH-O~ޯj/>`=;z[7'eSv=I?.fb|2~,*ůNX忉MK ͓wHUs?(O(?`KQ)osGL7o嵭7S>4q׶bnvFVv@+ i+e';`w4^_s7_G<kb,oϣ6;|,nŏ poH7qK8)w3(Hi=N7-; P: wbny-q`nHfan<]4;`n?ֳ#W~y3WW3R)Qs";_:zTf ٨74~?n$q3WW 7I薝t3WWb|3;`?m Nv0`ꍥ5<e(;``Tmz!VOZ\K9wIۘ @撋 sз 0r{S GtNRT~6_?nyb|2]1|;Sgs;Vggb|2.0ppav@ߪd@g'h|3(_e?壭8aTd ͘8ߌxh+e'; x d\EײSn/megt~{; 5}$ IDAT;`M7o嵭b|2-c2n<7jQ0 02`עRT3P:r0=c1se%.mE|!M[թ9Z~7&$ߛn[r(Ivdh:ͨ 5=r!6{)Vcթ1ooEq-;ȳwJQ+[Vv@|b‡ƳSoڇ0 ~UtvXN*dYnyC6;sg_t` =yn?+g_EmRv@=}Ϡ #?Oggߺ}G9 U:͛Qף*; dfD1>op}eg٘[0^r+uv@3(, JQ})kjD̼C:u6~?Y]2ꍥ[^~0{;_gg I<0~Yڻ; oXny0*X\Yk[1su%*E5; J׶bnvTd;7_gg ͨ^XOZ |zv}y=F((d YAFlg8YY80;BɅxzYB?;He#p+և5[7Ȣ01=Rs3G_va[?>%?}~^HfFO>={Rmy}=u pn6oGѩSt=(}\zO4+qy#uBVǾbzG|3LhlNh9S~؂߾}A `P#36 \ |QFs.3,᧣oF: ZF7x//OƞBO$|3qsr 7ci\ aP=ө36 D}u!zWۗ:+bOcO5,@+cߋ3Q3$@Y|Q_]Hr?y3oou9u@0(@W/ط^L7񛅟o?bȷ '_ FMGqh,u숥s>//,E73چA|*zNԃ쏵f:|3>}N=:[bs1ƾo>Y@$1k/hIq:X:=xhD QVIܣ> (zHİ *cߋNGd9 Y1u쨵4{6u@:ҏ\vEk㷿:zO<:t b碙oNou9'"7@B7fF,gqS_ ?{ =`5+=|W#|aO b{Q]q WȊq31\~>|d$5J\9?ͼ:%bzQ]Sg2t?TKX㜛p 5A<:t"bO'J Ҳ9t<:tb$U|33Smh;e "|d<"ur>|QFs@ LއHWNĞBO$u|3Fu9u @*_I~_ A=_GNy,~fF>Wtpd}S=xhD OD7e/ Y1֋1GN_qWRgC/(zh{Յ^y3u@[2(q_6o:hs{ =qw7HmX}\)Nsb|"ƿlD^_O@+cߋ0JS'@rK7 ?O҆'b33:o_Fu9u@[*VѨDq@ OKoF3oNC3oĻ?=O|6u _7J$:D!+gc#+ bm~.u@K+d96:c}m޽gRG@+x@S艛Յ)}7ǟLWѩcOfvB[ip^L~OF!+N61{-A<tpd}3P:[^6vy#kԿ=9ܣXsQ:p8y].cߋŃO-Q]+g7Rc?QN1~ߢv:O4z8uznD}u!u 7Qxt)ܧo z:وx >]ѩc8OD!+c'?0&p?y8=6zﭟD^_O '4Rg8t0~X6чDxhDǟ}\م)kQTgb3Q_]XKbȳ?Y4:V3ߌ+gQ]N'?QNQj }>uC/mfsv:y#u EON@y}a|c=uw)bȳQ:::WOK76޽{ϤVS|8~@S艛Յ)lS&zR Y1Jc|"fF|N=OÏ?={Rg@GX=mo*m֨?3:B!u @.ތfHlQZI(GD9z+d,Ú#f\ Qө3:gS{IFc#(d)@S艛Յ)6hTb<"u ;4z8'o,n6oG~: O?N fOŞBO|~V7G}?9x5+OxNGS돣Stsq:/p?cȳ37w# Sm\o0CcSh={ǟǾbŞBOm848xŁoUX}A,{ DS1rl:&_a<:t<ТlԿ?go_ 򟢙o8+ nfqқ^O/B֛:Vzc31xhQ[Dڥ-VR|,GipR34&vP}u!ɠ | @*dqX=:fr,͞C=:6qڵʭŊC@2YFd &@1&5Y@NR'tJ3ιi@._I@3.S_F`GbL}<"sqhowd)m뉗Eit*u@jiC;:Z]}eۡ^y#Cc'ؒrO#"Q]ڵKQ[8 lXO4z!I dֳ$T[Ae+Ԯ]r1G7S;`ilƢ8t u 8t Cbt,|<0p7CccLEipI63&u'Oxks:}he?:`kcil `b<92ڵ3 ; @w1&=t&'ʩ3:Z^_wNhe.<8 +OG}j `≗9 Q[D}jW7R'Ā t/c2ۣ4z8xE;/?:0rl:FZvN}u!IX;2"XO`d_GdwvO^_wNNj.yqYi z>م)k捸r~&xQ^V4刣~7o ̬^|c=^M [T=Y@d}論Y@0&FM{`]f}~:Eqh,k3.7㝳S]YnӨD^_Fu97֣Q]NBVtHƘ <wvQ!uFu9f)@+d1rl:{ˋ X='gR(Ё(J4FWFЌ)š(d(=3vg>Z17~tRV}.3(X#Ϥp^y#).s(Ȩ ݬ8t ""JSy3ߌFuL}ի)2i3÷јo @2fL`3vg[gPQ%29X=:%ksQ=>?.뭁ʧ17e~š9::-VRgt2pF G9a2*w4:OFu9y#7oߵ[՝Q#1荬4Y?s<йS'tc2i{Q_]6rl:w š9::W>`w=o߾ߧv ğ\Ht+tBV4*.zmQ0kqLG'$4{.RgtBhGp;P욬4qF`5FG+sntd}3xgRg 켑cӑ|B 12ի.4r{DWci\ +3A؂b%uЅ<é3DnL`b0:k5MX2R96:HȨ @iTWߜ2&_4:k+3A؂fވFu%uЅJS1x@Bks61uwQ]+ga(jks2eR96:HhiQgL`wb<:^M@-]:RY = IDATi z>uQeL`zL]7S'pAآ|c=z K OD7:H̨ @YhL` ODit*u@[Kme`+.UzcRg-`ilԮy6hkci1] ȱ]om`bPA #Dip ,Q]I;}GQzSgt |Aի7Sg]̭@DD3oĕ3Fe^yӘ .96š3^^_|A&JFbȳ3`T s[1rԥ 7S'e`Ԯ]JtOE!+ZQݵ4{.RgtBVfRgpgbcPIm:r7z>u"c2SRgk7Rge`ծ9:Yg[f_=eL`Oc33s1@k2(ۨhPHo @ 1*\Stowa-$G}j >AFeVPr >1DOB֛:م |2y# 3ScT`3rl:JS3omd96:h1wFefsgL7RtX@+-V<#02j.NRg-ƨ [_}A9 Y1t&uqFAfz4+3Rg-Q]6*p/]S\JՕhTSg% XK(N 2_~bL r y&uqFAի>6LEiTWRs$ ө3fJ Arbt EfWΟ)]w7u6?ͼ:`Pv} OD7:hQͼaT D}j6rl:CRg9WH]0(;mu@+)dq@ 3*tFu%.J4˩SZipN稯.D:`PvHy&@(Gip UW8X!+ơΤ p}T[NfSg-̨ m/ƕ3SޭzSg9A6bPv/MVbSg-Ψ -/Yc2-`|"'ʩ3ދh/e`57Sg|Rg-Ψ fDDqh,%u_  @{1(;XIGON2@'jߟqEbzL 7Sgp ]:F:hFeN7f"+ Keh?e`+7Sg񓧣Sgm7)Q]˯rncȳ1rl:uwݿ?RM6'utڵKpDd}36.7XKgS3 Յ7Sgp .-V,-ө366?gThJsv:)|F!+QzSpWH]T[NBѩ,ڐQԮUh)|OEq@ B^_3@3(vR/uVb WOE3Lt7ݟ1&Т'b33Kks"2j+Vzct M5˷o장s[ WRgp_z3u[dPvYm:K @2*f_=tVȊq33k7RgEe`ծ]J_BVLFu99;JC5+qWQ]Na&@ e`+7Sg|4O=:hcͼW]Z%|c=u _b|"'ʩ3  $P[NJ#G84:hcwFej</Ļ?=ͼ:/Q=:{6?:mbP]:஌<:hsͼL_LfK]HW(d8ҙܣnPj3Rq@ O:ٸ^y3uІz\9?P@8ҙ(d3G:AHXIpWFMG7:Z,͞KFu%.ͩhTSp?ѩ܇\I @"VvQzc@X3*ܕqW7Rp'1\~>uamocPiT#+ѩ.Hth曩S4{.fϦ.\PƮWH63( +ȱRgQ]+g7bm~.u wc(dSՅhTSg @B^I!u$xt4+SШ!6v2L>]:`PjT#kѩ,:H3oĕ3Q_]H$61.J4FpDO]-VRg @bksQȊ3rgTfmb s4{6u4z8%u[pқ!e 12@)d1L -͞߾:%|3.zwm(C/I4M̠ $oG:O:@B,͞KFu%9;rá( Yo XfH1(-?ЎOBVLtrt4)X_}š565~t`R' @ ]:a&uСWSm7ci\,͞M}lv1u pj*GcSp Y1x\ Aի3aeE+K!F fވٳq4h7}!h)l/B֛:mpFvAhͼkFe?Qr ýk4\h|3?Bh(H66?:]`PZ/hv6~tb íWOE3L|Fu%.JWN`<GI62@0(-Xq(h[7_ItFu9Fu%u +oW_|c=u [T|3_z3uk{=:y,Cc3˃f)@؈,<zl"9f,^q0 d}q䕿=)l,=O[K%#Ǧ;7X:ZWDm:mPȊq?B֛:m:]dPZL}jө3.4{6fϥ61Fu9u SQ::mTV|Ġ 74:3.6?WΟf:B3ߌs4{6y#ud|"<:mvқee]:`FMGqh,uEWD::ZW\Qd9%u۬Q]22Ђu Wzc@7]N61Fu9u ۨ84{K{I=x'SglI޾" S.ry#~(|Ho/_o_sF^Qd}Sfy}=fϥ =Ϸ6?:`[X k4{.fhkJ\9?;Lu3Q::Ygc;ϿM1=d:Ѷ$" IP6#-na+.Ш(.j[ܝ]y{hj CY$e DBmCAb cYiy(2&WJ4k0߰cH'O@0 /`2( Ucnt(ux }Rg+Pyd09Ye6u 48{PTgS?v` ԳZLx 1( lA5;OHPՙۃQ(NQj}1v셨g9,={gSgD#V02~Z EqSv UϪqȡr:ՙK1.havŶRg^I@BeHh%\:X.r7 ~ȮϦN`zģ_K*lWLhrbv UGEV|qėSrO//u Khz $fP\eC@KY}olt `ΌD)u $W(k/Ĺ),Gͩ3XBRTgSgAh 'Dk} `g8{PLO\bz8{aOZ/#USLrB~?S Y-#3h eAЪn{ĹxQ:nKuR x0^I2{ɃQٜ:e2=!Y>  4Ĺ*3O>lޒ:#Y5_|6N[2=t<9ՙ),8{>:e4=?Vž[MRg,\{_v_ppTfcіkOT=E..Q_H2޳/y` Qyd\yL L[֔GS',Bf9 kP lTg.N57:p *R@]m,:X,n^=E]Z:`Ix_J Y-D{qMz䩁Q_H@-ϟ\{Qy*XeIݱ7uY _tsCUfs.4H2QמwRH._텮),cP:Ԗ:ugK&/B_ _<2g̥)@Ogl wO2L:3:X,n]Ǻг%uw'4R:5X6ՙKq+څ)$*lT ;Y,-up{^IWϪ1v;:7yz _|6t=M@RT&Υ&U̥K/E._HkGCXՙK1<5:нg1<2:X,nO[=lT %޸R::Z^˯;rbu9qP:нg_l(ud;֟:ז:}nVƽOiO|9|/Y-u M:s)_<R =[' ! eճjGNX"/Ķpp @;?Ye6uwm?:MGG=NMxH._Ggsg;?:&X,LBtnڕ:`YtzVwFSܒ2_?FǺ94̥(}R::_=v _=. I\yd0uzgг%u-gx}qKQjshbg:3:mX}o g4Ub/upgY- XQl},#'F}!u -{wj4]ս;ؕ:3JLO{J@xգqp Ah7 KlrBt< дߎܽXݻ=uh@?|,TNAu.}+Qjshp|!vER@|{nAhAkwM]#ɍͮ~2uWD]sE呓QsQO@ Xכ:R9r%n[[`qGDX @K<5/̥)܄2gc/D= |0&Sٜ:3yR'Vžj/սSg$vq3FPWJgvz l@}?RD_ŚJ@)` X[`M: \xO:`Qճj\<8{pd9D)_<USD?{>:dL;X,W=E]Z: bW仺cnt(u *Q95Qْ:`Ego}obz=uM'Ɔ|2u 2Q3hreEճjmI+Pr_\0:&Խg_l:u jXd492ТNE'E._HL]q°4u*.~":荎usV2o~GRЄmAU&J1yz u- ܴܽ+u@2mX(9F}!D<k>mI-k@}?RФ돬2:Ж:X: ;Ƕ8hmsPS(c@ԳjTgK<4D)*Rg"VžҨg(lzS$ձ7⮟|xЪnJLTfcіkOY-֗/BzXgK~?rRƎGVM@0(-F}!{3ܴ+::`I_˯z ܦݩ)49c2܌D)&O7u*?/rBl},]v4nJLTfcіkO3<27 shr|!>o^2&5v?l ZAXrsӮɵcuR:@"_˯zc]oUjq;1Ǝ`Eb3Z:W(2Tg.Ń'3B{+ڋkbnt(u Q_+3Q-ǚE[=u@C)WĹ)d =SƎGVM@1(+B仺г%u @C(lzVwFS,Sq@otM\uR?|L7 shdRLH@ 2(+D=E}3ƚD OrWJg2Qͻ"/NXvo}Kַƻ!?>VnK@9NGeb~Σ_|ˮ2q.`LOk/`Zжs42sRgТVžgXco іkMJLܨ/XV7 qpT&JѹyWIK2Q7_Ƞ@,mGϦ\ugxգ1~7}p;.x; AXaظ sӮcTdף<2mIlnt(|/ōBZƽOǃ'3h2Ye6Ǝբs.|5[kcz=u @RNƕ7D;:)ՙKqGR십oSgЄ.x)33hqe`gx`h8mXݻ#θXY-D<|!uǪgx[_7UfStJ@*1v?u+AXNE'9 1ڋ]QLNEyd{qǻSSX!p'Ǝթe`[MRg4|[kS4va8Fbuh/vNVѡ(};?7 sX!p'*`0(+TuR<:aYe63SBz\~QjіkO0R돷_=:Ę wjXde`Q_|WwzNhXkw썹ѡX^OPޝ+o|WwtMYe6.x).W,;Ǝ?y.uM2Q3XA Ufco~.u@C{`Ǖ7θԳZ\)D):7\: hAoz4ƾN`*lGh˵N7 2(+BztnSV[=:7+3q:d٘:qWD]sR9>. {/@-K@Lb@ V2@ݱ7u@Ck/vEqt&u @êLQyp)pG*8CQ4$@2dX,c#̦`1(+\uf<6>tS4u. NhXc#/NHecc@ԳZV0c2,D)&O`2(DѹiW w{d٨ΌNhhW*R@D`돬2:ʠ Ye66Rg4\{tnWJgF}!u@S:C#(<mI@呓Qsq°*4 c2,D)&O`3(DDBztnSB{+V?=#SJeW8Xכ:X&呓}Q4$@C1&R;Ye6u+A#؛:iG;FR4zV+3Q(Eh/vNHeo_vԳZc2,ɘz%u+ACՙ SFgKԳZ;5:d~p{S'2Qc1yz S/0&Ry>ú$gPܴܽ+u@SYSQ-թ)MݩѸh=VnO܁2o~1yz lXdX*呓QLq׆ ~:h|!J SjqȡΌNhjmܴ3u p lLp` gLZȮ Ub/u8n"-SJ[=qq:iճZG2Qͻ"/N~2Oc #'0ڰaÏSG%ߵ>>}h u@S\GE=Nh >?q!h0Ye6&O 8$@0&R{@dgSg@DD*}#RjѹyW֧Nh:Ůx7ΤNh NODw{XY-~h}?ޝM7Ř KmzoEh(e]=Rg4uꎹѡ)-F}!]?FC2|\07 `ճZ>Kh(eUf"/NhJ-Uf:3:eԳZG2Qͻ<20$@33&rxգqp 2/UjvMk펽Q-թ)-%*ѹyWS'@1$@3&rg8;ܵaÆS._Oqg8{PTgS\*6}+,zVWb{ǣUSm1&[q_n>׿{[>Wtr$BS<=Rg/0(J?q 3Z=k/p ` gѽ糩S)U:b=߉?U??s{չߎ;WV=] ɠ +ǧ9NUg.#|D =['F禝S)`%Yw;[j?DeXƎGyd0u|,2ma7,D)9:`Eܴ+}P;קNdHVcLV8}xc*:VpYGcnҥ?NeUf_ʠ kǧ h 呓1v+F} Oe( tth4uL[w⡎^|~qGFDWc_A:|Do>i&?D ?΀e5v?#32(ܔG禝3Z遘>ݧ>MY ??;B!1~-~vݗp0?? qC:f.忷Ќ3bgSgdP)vg^H2TrB<āظ)l ʌ4GTXYޞbTwLKҪbؗ:h|Ye6?/rBvިL"̦NX1nڅ(`(lIK:s). ~%ƎGuff8n!߸gxunoX2RLHAճZeڅX^OԳZ̍Pt{0]S'LbX\!Z1񩮳?/{NA睸뮈>:ر~ڰaÏSGӇ"bgxQϪSVM'D禝SU&J1yj *R2&8>v(rRgР/?Mjnt(z_ )b_y-D]3ZF[=l},čB)Fyd0X কGNƛ/qcy`l:uaL_oýxuno XT=:nATg.ņ\SbWX\~۩SVS-lbXUjqx( :mO "ꘊHVOB[w;1'bn)(#'<2:nAܨ/D{qMݞ:"sCSV̸aR=ۯx>qƐ +ƶ{gSgow:&pWD Wv΀;Vjq] MŠ pbާSgB2 :3呓q(<mIPYe6.x)֗څQ_HƘ @c>>y.uM⡎'~|w#oz4bPe(lIr =["FufTltEGN鿋lH1B)Uɮ3hB:1nOVS3ඬ*}#]=Rg;kcz=u ?F}!*Bz\{,P=ۯ7ŸƙgI1?kSgЄn?TvH≗:3:nAeXh/vNhImx`h`e]ՙKqi+qQ(ōB$Hг%4?\*NAX?M:s)ߤfP#7 v--{wĕanP/ť~г%v?S%rWz (>uܒG2:nATgƣ"/NhYŮX12M ''FL._~u4꜋hRLHwĠ pY-^׿:`X2ccnt(Y-u4Mb?oLXV4u\p|/Sgɥ?Y+lmرRpY5&O ǟ{ T&J1=J̝J {ϾضP nCShy'kGNFuf[ߦ:~1w?\5ԳjGcާR>ՙ( N6ԳjLSѽg_<āwO-Ĺ)4?{>:[dLŰ?G4zVOƠ h^1(?aTɕG<2hX ԳZLȮϦbLy5"Xk7yj Y5u,2ɮFyQL]sITe&/ĶN^|+uRYe6^Iʠ &OAeȓ:3ՙ),Ĺ8{\tna+DY-#1=JdgS@S (lN4uWt O|9u,:2ʮFyQe鏳Gh!sQ8gmeRCg9д]?1&VZv24D)EX,ZK=E}3V\{<څX^O"g?F=Eh˵h)WJߍc1yz 3q: VgKyKZ:;w3k:1pc#̦EKܠ^M;S(}~Ȯ dgc@Lxtمt IDAT*e܉̥z%E=P\)@YNɨLKKbUXKltٗ:`i˵GqtM-F}!ޝUf#womJ1v?&ODuf34,=bǿwdZȺ{މϬ~ Z]q΀r_ԳZ X@kLD):7L=1~;VѱPG~{c{#".{+8 =c3q!`GsӮ޳/|6u@êL>'`uJ4;S'&ODv}6u,6l@kܴ+v?B g{Txc*ߺ?{[18֘c*PdT`w{=Ye6+zɃqS3Xۋo_o?RgB/#gxԧDs} γɮѱKʮ;6.M¨ ʔb펽<+PGcPhy=M1(b?/Sg]Tݾ7u \`G 2 s),!2,W..?J Uf%KȠٺ{މS'kXߏY}okmMj kT`eLĹw{="/ugGd3s` (lN4ŷR'}?u,Ub/uY-p :X5r_nju @m>}3m9+WS缣ի.Cxq?LQ""^+_xGOEaxD|(ݩWq\?dxkqȡXxy*uԝ|gw GcH-@0(b[qЅE$5L @0(,rR J Gr|:o>^\3ܞ:x2U0s'cz@ȶv*J0<1h2u2^+_Iuc˶W[dMSXF}RgPcNxԑ::sҏJƠ ,3gc)U#װGV\帯Ї"NRorR2u2u (LQp6Vl;Sgu\?;_c8Wߌy7G@b[E>CGt jLyUt) PW21=?߿+u@UXG{\)7eOEoOWssظ(qȡ)T1wb<ѱe[tlٖY@;y!^@eٹ':<:!FXn\*eܼ7uP3?Gɼa?W1*o0J(ΜM@*.EaxLⅳbecVߙ: 1řsq_ĩ}q!Qd_;c2u?XtM뙏ΠN MΠ l^+_+ks|:+ʩSm+_/_9[z,<?;w1=~ #;#ͧTq\?d߈󇟌x|%ul>wH@beX +W ΐ,NRg3(,̹>+2S*κTf͍ɼarlᘻr{pg-p^+_WN(LE|} qqɯO+S'\: x_#9a霹K0q<_$ X1Z6N(rShk:e }(//u FeJ٘;9/`,ME|d[Sg8?Fd;h8SeX*_Ըo\)Χ$23X3#2٦)!װue]ɼaOƋ󟉅WssJ\@5)qȡpPd[ۣc˶ز--e 1wb<.9dLǖm'XjrSq<)A`ٕKŘߕ:"+2Sm<>3m+1xqw/~}[um}1wr<SPŮcx?d/+#Y")f‘_}3_בPzv5J@t6NA:{iCTHA :OOIx|%VlͩS5,o)I.Gooq!ܞ:x݇7sh^? sS%YdDjK&-}3~箁)T02,_8SgPcJ gXiLĿYؘHQV(}mܕŅ;S"hTEZJgƅ#?EcDcsk4]ڔ{>gܐ: gPԸ1Π{l HΠ k+bectmNzOǮ?HQqZŇW] S0**.+S'=e\*Lq\?d߈ɱQ ;h8SeXJ|%fvkVNF&33"*Μ;"Ә:`Y=/c3*Һtocہ!FeXo).E&l\QaxLq(.Yǖm6z,6'RgP^/:RgP#ni IV+V6FK)˦tݧRgT;?s?}2PʥKQ8~m\4hl2ʥK<? K?zʈ Ը I@:ƅ9,_8SgPώ] e3?Ѐ?{2ΦΨx|%Ň_ms rR2uҸ ,Ra6N<όƩ}řZJ4` e_؞:*t_seXR+~c/Q \t)~0($ZJX-]S,ի.ƿ^Ψ+W㣷ůoLuϨ )S9/'E̝Rg$Gp]SReXj|%`,KB;WߌWNI1X3#2٦)KcNr|;k35uԽL)wGqlTi~6ȶG[Fǖmܐ: *;1cQM$axW3RřsqȡPqx|%VlͩSԿY5\NQ6UB{+2M<~Jq>uu\L~T\4hlhlnM˦T G󇟌O~-~v8s6ʥKD:l\^u1u5Cx翟:*uɯE`T.: 5;hjֺT5:du3>\MWN})^ͥ΁6Ep(ΜMQ1=?2| ^VSjOax̝1߰~X׭tԅ#OGaX H {SGDDV+V6FK)K_|0ඕDmg.m_9PVdÛy'Ǖ| DqlxedVud[;bE1u|`l̝x.&xGO+S'dq׿wfSS!NBs | ҥ8ҥ)P>twS7dȞdR,G{7(^%zKSKwGql.-]o0#Ҟ:(;s'le|)ԘS'P'OΠL>3c3b*bRg,:Ʒ&$ ΀gTjmm?hڔ::W9cQ8s'SU"C.n`I8r9&?i D0cΙ{ɤxgĚ5tꄚĺtLklS gcz|LL6-6]K\s'ƯȔgS'Uc˶ظaa67W]u{NgP8R1Ԏ[_HP>>M 󟉅WssnڕKŘ;1s'#]Ὥo0z0RP# ǯx܌5J@ [J@m~!^` *ɫ͠ P=kwE Y-=rSS_2* 1*u W9ř196l>Z6l? "Ҟ:*Q9s'¹^'"GϧwG[XZ˩3GIU PʥbLJ(zON ks_Rpg[WGeS‘Cs`QKŘ;1s'#""-]_q7gEaGTLԐ|gw Sݽ-"װ"!3QMU P=kwD&۔:বMk.ǣ=Ƿ&S@]ٹ;"¨ 58s63gcz|DDtmh>:c@X.-]:Pn=TgaPXR1wN)rSNr|qH|kO`kFeo DDdhٰL=qɀ šqC33}::4rԠ `Ph5;ܰTө绾}ͧ㉉S@]3*@)1wbZ6lzȌRxsuU\_oMILugȶhHR1N܉kk󵑙|gC0sogΦNx_=;DǖRg@DD45,NN.@x~?u 98bnAjL :}/N|;zON]mSKU0q, " [;f$V.]6ƈMjh;*t@AzW8cP[wE=u usrXx1{3j.uԥ7n5*\qlgƅ#"ꃇhٰL&۔`iKǼ> S9Y7,C^ŽG#&RWps Uerl4zvNp]zON}|XQHĨ ,rcQ8ve[#}m`kSBc<u[ .7::kG)$0̨&ʅ#bwnHn}!uamn:ppgKFe`ig4?s'#b4"̛C3FfQ*\-1@=dqJk:bŠL=*fc3Ι#?ac6Nujk<ߚxA$Hc)Np8ʥbYo 42hd8s`LBYmm{>g.R5eR'@z4b"u"0(Tı(Lw6PR'.7ķ&$ ΁;Cqۻe#3q7f δV0(L;[ԓq9@%5\Ɲ#s'cx e496CxWrSk:D_xb)P@(_x햮We28!H "\tm,ıYe]]3@Q2u\gaPJcQ8-]Rө k{.V]Xx5:Q\Wߓ́lk{d[:eæȶtD{6PJScQ戌߻L6=mz8@Xߨ4?:jAjMFc3Q߭/N&6?y(o\[=;gwnHPZ9|TɱPS>twSճsOtly uo/G[,WooM<NT.]mTj2ȶ_Õ@q\K(LKQ9,-b kPOל_X4uKEIp3&A^uјL 5\/n/}"sdM?4lTj1?mm}\;24EKh*LrřFcǚO ksӱzxWNa \81XeV G6*TR'vTMWssQ[^2WGg^y4P3yp0d?4l|:u]TʥKqH Ie7w e]n:uKޖc=Ƌ w΁6##qjp\8r(u@T:1?#3W:DANStڨ1s-]L)u @͹925hrl4ʥb IeWgFcRDDD_ XBksh9Pwzv0*lg{| IDATupLwDDlat3\*FT|s4Rg|f @չ*O[XrP )L3fjb7bmn:uK,p9q$fvkL;FeQ.0q,"|gwdtm7{PRaLi~6J P[c l>z>;zS5\N≉SgHI5͠ PʥbLw:c2ucB|ԗb\+=;wGK8)@y܉k[6_:[:;7,A)K\řQ.#ׇcԯ|gw󹽑miOj]n*u{[FL`1L*,12@͘~@h [_H2[olr|'6N9PW:<aTH0q~/ohٰ=>"7Oqܵ7Sql/_?~ۯwfpGlP XW]L(p9ksS lLgPR1Sut5\G{/}"so\!{ᙈ-M~_ҵKYg4?{CK&O^1P PZrge`P)[wE=u P Էw<ͧ?y8^ͥ΁ѱwvov oy 7"=;DsCX2rS=r,V/)܀6VXlcpBh=:JsC G&OԠ-ۢhؘ 5/p9u{[ɨFҥ8sp$u 2@͹pP&Po T\ƑصS1*NԈL6=;Dݑ6%w }qXnhgSg@0(Ԥɱ @rxX_u)P7%Cѱ)lr S'jk,F)Μ3jRaX&Lo Txx۱`dM?4-]SUc˶ǫ7NeejaTSKuǠ P| ,ի.wk yg4Z6NԽ-XT3GR'aP#@ 2(b5\/nS؃%6##ѱe[`mp=lSXksөqX^7hgΦ  Pg&FS'5Ƙ Kޖc_S@Mٹۨ Ԩlk{ _+)P:<=;D&O܄L6=;Dݑ6B@ umz@&  PwJ1=~ uP#zON.Ǯ?G{wHǖhب T|gw |a$:<:JSf!uܔƋR$R.]ɱhKRgUnk::|:vWcuI ?4)~xd$-SPZ8Sr:x2@]*1=?uPz_H@qSw [@ȶGpWZM Qxꄺ3wrQkw5v_N6##ѱe[] #ODKצ)PS'M[qeS.]S?N 2@]MTu p͎;?+/a 뷺*I&{L)uTի.NE3z4uBݘr:xevȡ(LOT\Â۹8ksh)Ps߿+zvIDDKHtly u ԄF2ԎөBaxLO2@ݛMT[>2.Ǯ?SR@M@ G&Ouk]?Xd[S@XJי%W.]SK2@+L GNTt?竾WatmȶzXS=y"߿+u ԜJmc3jhgSgà @DL> @mvb22٦xd$:lK5+=?lSYM `QY:=:Ne^7(.1绾;Sg@ٹ;oݕ:jN[`|dhN67:=Kc(ΜM\'2+qH ňj㎧⾶Ps߿+zvI5!=lSyW]L+Μɱ`P-.9řs3 w };Fe` tly y"2|Z-]c #fSSn5ޠ^|=: ͙# .7:nʮ?uPsb #NUg]?Xd[S@]1?ř3Ƞ &@Z[zP_΀mihLU!<ߕ:RSf!u,\ 5Tɱ 0(ITR'Xש3&eMqgƚSߺ+|)PzON*ةGTL24?ϸUmrө`|},r nqCѳsO 8Jug?c3dP]L?{ ʥK3 BX4q_s3uly y"2|kw#ODKצ)@DuJ٘s)T32\*ƙ#3 kXpc;7F"ٝ:ɶGplPdMsXbBpKM0(.9řs3 Θ 5bM΀mL[`Xvkw#ODKצ)[5v]=uB՚?c3dP}98:}:Do P2٦{c),2| E&۔:xP^AQ*h `xcqө3 `tZe, E=3`I GFKצ)h,N%q~aMꄪuQ.Sg u|Q.]J$fPZb;[GL6:U&{>7dR9jՉ_^ꄪ4=~ RgĠ u(@BrS`ɬMN3)(#{Fw0u pR'8< UTɱ"2(p=l r2٦-R dq=lS:|Z4wxqU\*AT.@"}:6EݱqéSk)z $(LK,Lj2wb< ǣkS`s+Kl"?^7PqÆdJ5]=Q*h ` HPmI,ի.:HhCÑNjx c2PR'= U]x5ʠ T9Rg!*j5wnh0%CñqC6nBSf!u,Ψ*0q,uD ܀ɱ(.Io ^\3u6lSٽ~)kw#ODKצ)"pZr~aMLꌪR*h ` R1I,R':˻R'bL6::mmظdRa!u, k+:pK2(p.9řs3e67:;CÑN@YuW jL 196:XenBaX\8t ` BXR^d:eMqgRPoDsC`5z-zK?g'&4&sNp8ʥb `dRT3Go|PR'˿=uW;`QtmOlK{`9 A5r{ [G ܠgF0q,uL ܤrcqCS%|:u,}/}2upzh8N{,3gSP2|ߺ+ ~*u L2 ,zK|٭sZq\LAE0=?:l|)"Z\$xWnBsC Ǚ#qȡ9TظȶNѺTxOP)5ԾR'̠ "9sp$| *j5履L,L)zv|gw98:*ӻP\C%:&`h,KSS&23(H ‘cSE|:u,'&L,5|gw{{\*L)u un|xWΩIřs196:H ":sp$.7:>/.ܙ:X-]#{Fw]ߒ쎍MSĚR'P^%a?`]sjZt)N{,uAET.crl46n(u pr 67:5履L,L)S‘CsJT!H `.-۞Mܠ (-oJ BGq=POm6D#ccS*QZ\:*vb+ 12۝:߰P/KT2KhrPGMSx6uߙx:.&uPAڷ/쉹sEM]٦)@y>>[\Wvlwss:.| ;wd0ٛ:8uܲg\)]sG9܄lsKlٶ3)@rf-_,ĉng(6: eɘ>mS!7:nɛz3 e۳Ѵikϕ:*V"]:RͧNBŇx`Df±@1( .֞~: {ȯ:nZiqU|WRgU"QޯsM]ehX)u Pμ@*HŇ9܄/qD-eBy>ڝ:rS'-Ӯ7$ܑ19|(u!m-vFkSf-M 81#s12۝:[p!Ck2(LGFkO4oM|Ƴঽ<pӶl{66m^P! ;bc@dS5海?mPł5b~|\86:Peѹ#ѻk0u16.Nf-@wq=$԰vslٶӱ `Ɍv-Rg NulwvGi1:d|%MT02h~Pl|l u :ϦNVZ\' -M-ѻk0ÇRԕL!6 D[a{Ɲy(-܊wR,81]:%pؐ#!2(&x8Z{#Ԓ: dVx>uPcl{66mBy>u@k-vF&:u P'Nv:ۤxuM|oψL(vDeBy>'u 6.Nv噾@wq=,c˶Ծ5u Pg_,rūkbd;vN,KRgU @׆xf8)yϏS' )-odg eZw`OwP'bd#2Է/\/2 M֞~Ft48u\5wo~1uPM-ѻk0.:"u6Ǿ=Nb.^)u rN'3*bP sG3mMNm|l ڻ<\#2թS{}D˱ȭx'uJz/\w\zwM*̅Wb~@Yظ'u@=+DfUCܳ#u ԵP|ꮷRg'zy/]z4u@D{2޺8幙9%YO?BܙY:#])uxuM<ߙx:q&e-sb@ʤ ±hw?7:>Q8'Sg|H&:Çܑ9e[S3}a'XŇ9T?7uP T|}iOKgS'uiȀVM]qſLe6ƾh+lOpSO<7SgԜ81ߛ3" ?׷W׆xf8)Pw:qD?(>g~ ujX)zwsGczheV"]:ঽQZ~dXOSޯGdFcd;uUhz(6:be*ȹ#), cW߽%]>;ڻܑX(ϧNX2M]ehX)u mq_Ƴx6uJU:1#q7<7 ֭{?uM[aGll +ȭx'u|>2*f {b~)U%lP=]-ulwss#+p2C!,{V%zw ƅW±9,mGR,b.9ʛf-_,Fd.:dL-Xn#w` c[Fe*-?KIp2ʳ3SnJ[aGlLvuex6JQ1~="sbw|ĩ;;uP#V466I]#+u ԼǖpMߝ~"FfSg+㽅_[ϤnM]'⾭;3+S,5Q&zONIxuM/$qʦ(-RgQWbt⽅SIMpG%u Դ ,~!umɮ-۞M[c}PO-SES)/Dn;sEŇ9ԉ{}?n;֭[~+ٛ:jڋHoęHdW {bn~/Z)m-vFkS*ƆfGeJlw|Xe79|8LԘL>(|G!u ԤƳ~P|5e19|8.rmH.mGG[aGdST7J/9ůGdFcd;uuj~|\86:Aw[|L!>ܐGh9C 磴Kl1?zNƾ6NxC:1lClٶ3Z{OP3r<N7Kmb!Nuǥwפ΁k*쌅|"me۳3&6şnL81WRgTSq=R,mGG[aK޻/-pVl?xuM|oψ Ucs17q2uP TgESPƎu:>S{p +1~po_NT֞زm!eh~8z3MK3Q&Ffxx~I~, ŅcC3:`P4Sg@*:Ϧ΀8'O: Kb<:Blٶ3M-SVnE):9gcCM(^]o⵷>g~ UinT؝:eƾ@ jȭx'uDiqU|QZ̥Nx幙i_M,%K64wƾhjߚ:kؐĆX)}Fi}\Y6ԩz +{M&u7±w< k7NtݗP1 \lSKt?7&DžcC[mnzΐ @{>""μ@X> ,;SpsMU+r5L_ V_)@v*(6:3e19|8uT{~:""b/NZ٦~folH$6Ėm;s9e~|;2:Cܼ dž"YlSKnЙUocx$S mGG[aGdS\BJ~/Sguܼ|/uT+  5a5RK#>Pl|l PL Nhllܓ:W̪g}Gwݹ::vb+;D G⭋gl6j鏇xOܷqgfe5=JySgu,:[wP; mjIU*uun9u@jX)zw ƅW±9-j鏍}Uc~|;2:sw-c}3jQZ::q53jwhX9u pڻwxdPBy>u PV466I+Dyٸ˩3C}+QZ̥ +cg#bnT:4wŃ7+Sܐ_2: 2}|g!2թSvGGԙKIPw6>6Gbޘz=up M]o ڷN)ӣqOnFx1)P~xX HiqU|Di1:.llu}2⎈Ss_iX9:#6 D%uM:)aP.]u#w)PJl{)ԉN?#ݩ3^S{W;.sne[b˶fHj +q=QI25_ώĺ{2̬Lһx4ԁ$~]SͱOFfUCuqܕ@XFyѰvs[vSOFRg|A(/}[?:*Zl{)ԸN?~P ~=;⾮y`j+qաŠ @*] 6GSyh~8s!u 5*?_W!m֞Ȭj.{ WS'@M1$Ԫ?#P ԰=;~ɸ32u Tb.ʭ7:'J'g}G'TKS@3$Բ8(ͤN&25콅Q*^~>u T[OKjw&b.uʸoaxX(_IUǐ PV@2(PJ.Fú͑w}hl2*mqXH ݻ>Z{0[EuL dz1=J\xu(uǺcݺu硫`ie "]:*ޣ")Ԁz>.&u`~|SNmn}9Z{O؁ݱPOV466Izoj㾭O8ߍ||ꮷRP~P|8 3E+cg̪xxp5uTlsKlxѰvs%Pcyw\M ԉҥѰns]:*8v;"6.]w.N Di1:q_<7KS@2dz?o]Op]Xn#XlC|dWN[Q/No+3X"3q`ggR6Ǿ=NXvÇܑmEcc,Fx1)P5~]12/wņŸ΅YTrᏣxuM Hq]+cnTXRز+Sa9n~|~qO rǺuOz\[<3M'SPμ@|s3X&幙i_MjKS{WlSY(_o?ٙ)7Ġ @dmjIU-c: ""zw폆Rg! ˿V:ñTq`ML@6D[aGӣ3n 2DDDѻk0uprt486&?!o#μ@ ĩ?7ʳ3SAؗ)Ua~| )A>o 6>6: gcCbtˡ˩ƙo#uUjz8wdTnh{d{; SBJSNm !GM3[tݗ2?sjw&}/ܼ>? [ ;b˶gSgK6E~IUϞ?B jLyn&.2,5e h7$p &N؁ݩ3A}Ծ5uLrt48:g"I*v(-RPǹ#17q2u  m9Um|%y@,S, 2\S%zw Ԇmަ?7:"px:uu`nT\86dXN5!SԌoSg,2||g!Ҟ@b_4EGȭx'uREһkRgPG&NŹ#ԉ|g! ;}k2~p_LM =(*HoX6gv\Ňcө3SӣąW.ʳ3S2نwbc@dZRԜWbKΠ +mޯz \ӆx4m˩sO=]::gXvd[? ;"]:&Oc<:`5wE3^e~P|8O<:>`Xz5mxP#~75nlٶ3 SgUy,z3c[N맞KIŰ @w#ڷN c3A[ѰvS <LS?yy/b X^|L!Z{mjIP7ÇRg,+2\w` J{LXQȯ:熕WN>\D +19|Ȱ @6ǾBdSԕ8žΠ 7#l{6uP:3c[Nvlw !eijGG:.O}'AnX3}k Vy,˩s>҉O:na6D"Ԓ:n-؁1?z$ pò-ѻkdS5lA~8~?)f-oDi1:nٯeGFyv&u@6D[aG~PN' HƠ 7%Y'uPr+JG"rҖG_ a[,DkO; S ŅcC32(M{碵@ {4?ggYjO`91lCG##Ԓ:xf8N'u@reilC~uci`{xjw3c[Β3o?(-g@0,nŽw"]:0?u>쎅| pKn]3:[QcqnUq_gn ° GkO4oMGX(_c~) lc@l|l uPg6.4En;kW3}(-nS!TSqPML-m n IDATɮN'8(6:b~f˜@2c4v2oB/>lH>a; BӅW±Š E%zwwHnCbt4{r럿QZo۟KIPi~|LѣSnL!Z{mjI (/IPq p; ЗPyn&.2,Th֞Sp؁ݱPOPq p[=s^@(јat6DkO==M-sI +1g<;:"da@X(_C1=zԃ]b5wEkOQ|1v๘8:bkX9zw +qտ3,TL!Z{jȹ#crP fP%o 6>6:H`nT\86*$DS{WGkSͦG_{SgT<2,gES@"ScrPLMԸL!Z{mjI:#~6u@U0(6DɮN$TѣPOԐ|g!DkSXB +{|kNeXRB<=3 PӣGcrPggRU*=٦9,oSgT 2,-vF[a{ LӣGcndJGB}1=z4u@U1(d}ѰvSOC԰vsGkOdS&ǹ#3AE>k*јX(ϧd>1VPg {RgT%2,Žز@}%&Se,DkO; SHl~|M2(zx\S1=z4GNH=ɮN@X(_eXVlC~u0M-S*Qѣ1îP@ d>iX)ufs17q2u@U3(kX9zw +1=z#bBBG: 5~p_LMP ƾ@ JOCQ|m8sаvsvD9TWb5 t?/ڷBJLCQIDD%Z{?M-sScϦeH&m=7")p[Mѣ1=z4u ԝL!h+숆RPEs317;c<:f ~fo ,=ٙ9Ph|G!u Uh|%S2$o 6>6:A31=z4 N,Dw"]:*v=,2TgES@*ј=ٙ9Pun֞w"Ԓ:0~p_LMP P-ѻkK+ѣ]'6DkOක}%MP P1xK{Rgub|%G(Τmn|# k7MSg42T-vF[a{ MѣQ|m8s`Y`O}Xbe8{$P׆crPO:L&/(,؁ݾ,2TlsK)@+QW2 FdHis17q2u@]0(@Ew/I31=z4 NbDJ0~p_LMP7 Plm3>PӣGczhO:Ɉ drp;2: k7-Sczh0ʳ3ssFdD3q=3A*Z%zwLvuT<3׆czh*;;SA*^}iO OP9ԠlsK;֞hX)u\BJc2wmye @$)FR HbtHT3.wҹ nC׫^&]h+;0Ht0I0l`  wNA`o!YlI/)RDe(-) 72Yw' LD"\m@B2ƕ+QO=IJn'zc{P鹘ygDd(.3ƚ Q⏷Fz!u;t|^);|'SO!&P 2F#)vbh#N9#6=s`$eNl6bg2_܌zH{h#[h#sW֎1 Qj}2$iy/ @AP:׾3 a^8ճx' '0ڈz oHPҩ^k_߉JB)ݎGRxkՋ1ɧQ̂k|sSL`e(B\z@ø̣nJj-&./F}f!QOnDz'$(@i}R(a>q\&?K= sj-MϦx]AJYOS(y!0p3 EdS֣\N=$(@Urcŝi0ROJ6=d W+7VRz XȺnGfTmz03;ueNl6bge SW?Kgv?ڈVdݝs" CL<eq3>ZScm2ݭROΑ a>Ն0<@I0VX|{?f:z %|<ƵYMb2#(XTk[w`DeNw#3@qTGmzN@ Kh# N c6=׾zoݭwf`T/NF}f8 SM= 8vs%z38e2ǥ38!HY8>;鹨'SOO?p7 ΀ c[1u3x3p6*q8>ԓSkGzgDPv;QM=SݎsYIPxsMo{Kgpekj-xnTRO dNw#3^I\Zq@>3zpNn'6W%'(ثMŵo9{qqhʮ>p9T듩' Aǥ3Hs\vBMdͦa>|^)A8rY$> f`; ̧a>ՆcDPs; w2Yw\8w1zM11#(ϩTk[wRz #l3vdݝYYx pZ͕R /Ԧ׷S`^dN>lI@I/A SW?KgPp"3EgyzP}fqvůgm(*1^GPG* (VD DdTSQyBԦREmz."cN oBPbgg@)dN ,L|2QY8\H9`<>ܿz (w6=z_Fg""툈R΃¨Tkǁ\T޿bFFr Jz;S#ݣsᙬ J AWSQxx>3loGLSP+7Vܵ f"=~~~SdTSb &">s-@)ϥ33>~Euwbs߻uM_""?`* h1u;ڈa@)|/SF1_i"~|?; ^xzq2'_|>3BLw!([1u31u;/@IyMWMggksQyq{y] )TkqJԦgSO $Ńz0ώ4H=(a>dxg2pDe75ڈz % (g$Dz0d8m2pmēwRF gAPӍZO=1O 9h7#vRFDZ Ն &s2̳h7cRO 9ʺ;R@b2A8gݭh7WRQ.&zx}9֣\N=1!(<;z33$&yܿYzpdHAPYl6"丹"1RĆy-01Ruwὥ3wu;b2$%(#J[ʺ\mkӍSNYLfg0e`<;z37$&(n.G FPFjCTF HPF0Ϣ\a>H=1F stDTF LPF\݉'o OP Zvs% k| &֢ZO=ƒ E!(n.9{ɺ;k @<;n'  b2 0ώYeySd(*A(`/6W2pd(2A(rPb2 h7WR ezwS,e$~nZg@P&2P"r?H= CLi}%n' yb2 0ώˈPV2PBH=N X˺;d gQ(ۉ.)&!(aT\I=N,vbsH=d g*?;:$*0Nb2 p d A\^k=3`l FTd =A\eJ\q.F pmDz\^k- eDz5QRI=_]H\mDI=x{Zvs% N@LF @q=1a,uw"~QYH=Ⱥh?RO^釻koȺ\m0RO^z刈Y%[k8A`.j#[ (=Q`TeN<Ⱥ;!(2csM=`]~+~z0& [V)@URUrD p^<Yw'e^AT8kYY)@  pVzxr pjeހ pڞn|ON=(A7$*vs%z38Q] Al6?{}yhLƣ]%UNv"I嬩?Z0GpCRhd -CR{( Ada K\YRb]euzg8? m~x<y90kx!u Т "2,ٿӨ]YJf\1굕SM<7Ǟk+SIЬǣ^DP]:z&FRgm  tdDQ&F`=CFe^[/ GyLXFe_,Fib$*RmȠ *1*KQURmjCP:{ǞnLK^H XFe&Fҩ3x!Nzm%u 굕8}1aX#FeUgѡ(ϝI>2kף2R`ѡ,^H6 #Z]&=G#߻-u p'bfr,u+u@;*U)(MAubTWotddP`SYPT/NX HlD #\:zLEVIpS2Uib$"¨ 4cx5*@C(Mٗ^NhjeX&ǦONͿ1S3ZB&uk(MDD`k+Q巋SZFGggpZ>Wzm%)lRI@cX(zCShq 139:%m( 7RG8cd7Nk+139NLв [cvNETg41 SZA>P&=G#߻-u Mҩcfr,JgP9:&TX\:u2u @0(<>:&RYHT/Nh+e) \:zLEVIv2h QUp(u ^[ɱtdP(H@n=G#ݘ:RYHT/NhkeekpdzR.z=f&Ǣ^Nh{e-l>|)$RX\:u2u bPۖcǾñiSXg(MDeBLWVHkFg_ܙ)&2ݱkpdSsq*SeX7?x$RoL 3XeXWl>5*j8pT/N` #i3֥SXk)"2$yرP RX\:u2u k Iu?6G"ݘ:UgiԮ,N` |ص8]=SZBDL`!dsp4Rzm%ξ43SXeh(Gb'Rgs(2Z%u Ġ gӱcߡM^[X(O:3(@C~l D&1u @S,Fib$*RAVw{?ٮ)Max"f&RgAZ&=G#߻-u @êVKQ;: ĦOh8Qze4JA恧cǾC3BSP<:bPշ;vLvcd*Q)424|<mS1?5:ePctuQ+/E(ϝI@3(@S۱plx*uZ>W+QUR 6bXuJ&FbbAZBw{98)<7]YJ@1(@dh{N#3/Bx AZNش8,^H@2(@KW+QURЂ VvǮÑnLfvv?ؚ[XJ;-kr>zm%J#v1u -̠ m'{_Oҷ"߻-u ;xgj]ܗu ]yn:J#Q:gPcǾñiSVCqXl-Fek+1?5 Shé#`WQ>:|_~4}gݫ[⧵M~74tLOJ@P(nvǮÑnLp?Q҆{sNuKh$ox ڐA}=Kߊ|)7%QoYl-NڙDz.u $UYHT/NMutvv굕#߻=uGz(w1ۮNy'#xsy u $3xĵʕ)12+կbKb|uu\M[rl\)*1g?LP(H&߻=Lvc >j<]x-u3+{Rgc҆Bp#u4L6 E΁)@ \w1~UQ~o|wz=:nKWF!ow`:O:'~)4s8}H)AH<7~ݩs;Pb|swcƹ)M{.՘K@41S^ZHjCP:Y&]өSdTrꌖ/Ǜ3h 1?5Z%u 42 xRg Q?2;;ϧNi9NuK XWFFB92-<7]YJ- 4|<mS=3SIFe_3cq)R @d恧R@yl߱y>u zڙDz.u ҩcfr,Jh9eEt?6G"ݘ:“=S1૑븚:;nus|Q&QYɱ(ϝI-ˠ }=?x$>:Cq`˱|VQWBxONgPZ_8@ h8O^K0*иsQڕ) @ E'u $Pb;[s SXCFeK3cv1u 22|?3;R@j >Z<3:ubT1,Oxk)v @شcd7Nu|v,ワ:u˟羒:-cfr,*R@2(m"߻=Dw[XSj >Z<3:zm%cxCqXl-NI5J,x&~CWf(]=S7 >j<]x-u- Y>Wɱ]YJ2odPtH|BZQW+/E(ϝI2~l D&1u m(Q_'{RТޭnQӿ|2u @CVbxӅ'bזS L3H Q)~8x<:wgq䱨-R }%=]H:g;1mXLkNjOZDeLx <0:5Ɠw1+x'MzJ\dM׶ĞgkSXel~'5Rd;Nus?wب Dk˩SePXw1x VA|9˽:GNZ\el?y,/:hpe$zƞGLOonُbgv!u $U]5~8Dtw*8XgS&aPH3?r u 7h{.َSapFy$u"+ S&cPHgpoyN:ܟǷC hHFeP,'E:hBeЙ銁9:? |/?:hBqX~JӑM1&Ϩ p#jR?y,3)@ ~!uUJQ,/}yCmCsgCsݯKMBlgkSV]3?9O>J2@eZgoEelܱ7:3]ُoSꚏ-a)@ZwBTϤNZAa*(Nŗ!춡9m)Q_=HMgSQ?=/R-۷*u{}:2=Sʓ/}7Sg@S+_Ͼ|TWS/}O)@~!uUJQ,/}yCmCs=߉?:^jl?[S *8Ř6jR ܲ}_={cϣOG7u @vTo>َSe9w8f/NzJ,'cזSm7V)Bx-`gO-eSg5:X©|~-uf:Sܬ QǞgksZُܛ3Eϙغq1>tK`TbS6Bumy)>F37u@Kwub hI|%_1 f1q:hsVÅ(c3ѵͣ,5=Cs3eݳx4:X%J).LOD0:7 -cֿy2Gxtf6Nh:c;NNf ZCv%pxk˩s~A,'<{:==wh[7.u0=wnRp*Ο9 \>u۳[KwSel\)Š x/DΑ3Ltf6Nh8l~'WSg@èUJq(^AmgxHPy'u4Z'XJpS m^[ͿyNhC6:׮B~2Nzm9uM3(x`v=|(zJP:ʇR'X8^QԖJSVA-_z?` GgfS$uu{v!uO>ݒ:^el?y,/:`g (Ϟ]Hus{ 6+ƇRg@۪̟ Q?:`-R"wHzPdzzS'92~^;uZOL>u 3(GgQl Gȁ9k*q5u\MmV)Ņ(R2^['E0{ƞmwNXu[7.N1{yw|X-uzJ\dugPs,_z?7OF̦I& W~HhyڕXOQ-H  uZOFytzPFRMޘ;u O27TwB]LOo$UWn:ZVp*.-R427<g1xGOcH3(p0=|zP ޕ: h0oWkR*g+mH3/?r0Fǣ3)u׶ċ<:ZFel\) ͠ *YOF0>}.VS'@K?١dS@3$pc zm9ν׿vG$?ŇRg@S3$ps:_HjjR|__%kۮRIfd;΀Zi4N\ڟ:VRsM|_}*9M3u@+0=TzPFRQ|%rSg@K;&.>:RR<2kTwB =>IcKMb?~C3X]eIeL_x̦Ia +ƋODu%:!q:tfbÇo)ƿRg@S;rp^ޝ:!eP m_]Rmؙ]HMߌ7#3X/hWזXZ]ۿI@KM+?:Zv%.8&9-۷*u@̦9@ٺq1KMb?}{3akWb!? G:mh0~0u fkߏم׶ij>Օlh8d~!u_֯Ey6|dI@_}9|&u4ʭQK ^Iǣ񋟽_KЖnپ}RGrwĮEǰ w"q5u43(Q]d,>rB>[b!<█mKR IDAT'-l×)Rg@z4'.O ^Iǣ񋟽_K@Dܲ}_tfb`t+).jR\ba*u _A<}NXv\M5gHhq={c`tu Ƞ @{}:2=S&4=W3`]]?ٷSg̟ Q?:5`P q2 ?o +SgFu%:V!`P uf?r0:3RMd{.َS`M9w8f/NX8”!6aP˰S&r{WEnbXUFcc3` ?R)u Ƞ <}NDKb?pTWS 3$ ͽg+u $v_M_s=VoK7^ X8}<9$dP?37F G1K7eo+?$uC2>2|Cѵ)@?/Gjn{K7V)Ņ( ; xdzzS .QWSuym3ːL0:ePfX^[7.Ο_Iio+?$u\XOFy&:gPҙ{DlJ4x|Obgv!u xU?'2ocPbX1v\M{LJRgg*NŅRA2vTclǫw:u mno+?$uzJ S4$M3(lS nK1=:6T%:s4uzJ,'cזS k{.mXLB9rp^ޝ:""V)Ņ(RB & kt8َShqFcc3 *gX2$0(2,\lG5v{SТ+SgFu%:6VQ?:fPu>)@ۺq15R uϥNpFwR(NŅRڀAUR Η#a1u -`8rp Lv%pxk˩sh#eH° p=vӑ:&GOM*0=噼!0(@Reϓ;_roN M~x珤 TB~23)9242=Q|9R$׶ij>ՕlZXp*̟IaPcXv SHrkFSgЄjR\L>9p e~"˽:uR%:s4uM26.LODeLXeh e2=c;NP\ؑsc4zJgqEm:VAZaܟ؎W#a1u k`8rp \RǣXzm9u 2LW{ GFgfSAd;Ptl9=|%u 26QɧN5gPfXcn\'ܛSX?-=^"u ^|\xGQ[*ucP/2}"ӛ:hCs1D uϥN&UWnJ6u V)Q,LE:֝AN7,|x5rSp&?FGRg*gc!?|Hʠ m˰ ۲xo:NGjCږx磺M@"ڕ(?R)u4210:=wN֍1Dܗ{3u ߌ7#3HV)Q,LE:Ag={Ꞌ'b{.u Dږxl>N)а lS \>v S-G˻Sg+ba*jK9 gl7/:3R e;Ptl9mo8rp Xel SQ,LNbP>Gg+=# @ۺq1ƶroNikG˻Sg+QB~2/:A}b`t<2=SblljKv~Zz8D VYRǣXzm9u452pE+u |x5rS=|%uX8TTϤNaP NvT㡾;َsZkјX ZT SQ[*cPVAfso Ah={c`t:gQ,LEy&:eufox_{ 2=sup{r uϥNIrk:%UF0|k˩s5dPZ@fso +)M^KAh#}ox_ ޕ:XeCs1D uϥN!G˻Sg4l>(S Ƞ m_s$:3R\>v S>߈W~H |(Xzm9u @tEΑ9]HlG5ꛎӑ:z7~ohhJ)3XOFm:he}o)*vT/}7SQ]ɦNhH©(ϞL>u Є 3}M۳Ηc{.uJTWn^|) 26(^[N412g}o)*Ꞌ'x)r_]5;VoKr?@UJpxgOGm:heՙ銾}srd;۝d~^T S|9@ 2(ܐ7/L|َj<7{|Xb?~pɧ[FV,(S-Π pS:3]7/=9Mںq1ƶro?-=~t񱨮d|FV?TgQ-ڄA }"wHtf6n֍b{nU+_^~="3{:jK9@2(LWѵ9MꞋ'nzX|mKQzhTW\ИjRgQ,LSmΠ &}%GFΑlJܠ۳=߉)_;ުo-ݽNikW<\=wNn֍۰^ޝ )ϞL>uePX7ͽ.dfQ- Iн7`?P?”tEΑ9]HKzDftԖJsnAad6FMsع4x?]Q̊)F PH)qp_r%\8Pb$KbP n9px aF 72Q]]RO2֛xxO ;2Qegr0J=8Qmxh֋s^ p2~w=꧞9 'w=Mg)GBD8w2I>.s=, Oel]囷QFHDe,q\yYU?7A {Ynw=NM="2?FP8+o~ROY/^Ed~ p:EY\ypzfwEI=d gG&.߼r0J=Ά Lqя7o(~9wxj." e]e|<ƮmRȚ wk̻6"(s(fz5O=l ,zW72fwm4E9 ez׳(~9g^Em4E9dFP(.ѻ,$&]<+]&$2&(3j49f:E7$kQ懈LI= 3"(*]Ϣwu`zQWwLu2z׳]ϢStSOH7x{&$A~A5F5D&(W֛wj&$*A^D(w=j8,:E7$kẋL^EPWQѻE&(T[N SQ&ѻj4꧞pr (oW\q,L4> m9*Ģ IDATeHN?enR2y@^ŮmROW'(Q!.S&QTԓ! 2pYTitnIऔqTiTIf 7ANǸL5F5zuwԫy9peL&(;m4녀 "A)ʨF}df8#k1zzdAP!0Wh6'@e8[3z]4> ]ۤgAP>egIIpv6|YEgKPE5 rYͣ^ͣ}ڤ| (?Ef:E7$xUv)f]ۤ| r0~)~IKi֋h֋ԓ (/SQ&p`z|Ӯ1."vmz eUiTIqTitnIz4EԫyOԓ&(Y92($2Ԭxǀ ?AHShrtnY| ,Y/b6g *oص}8f5?dceDTiT!4STԓxe_c"ڧMY)C`NStS'/AP2R\q}hfz_!AǸ @m9Dc]x je ff~zyzI= 8#2@Dz4EOWԓeo22S)gVm9c>#AC\NGQSxi֋Wԓ~ :Ě&QT3ԳY/ј]COԳ~ jaq(Գ3֛h6Q>mY/Y/Rx52o)(F(IY2 pnePQ\2(,;A}(.QTԳW֬k$(C\Cl.R~P]D^D^DfH= d Y)CdFhC[oó~iz@veP\.MSL覞٨Ww>mY/b~jzY^53(((Գ(իصM4>c&4BP8:tNSb3dO4t r0NQF5DDpRvS,~boEc2 (Š~>:G74""$2I˻صM4EY2AߨSL9GQ]4(~yf<bΓ هe>EfS覞o$8!_gvY(&"^ퟫyi8At28:t#"N#"nygc,&SY/b~m&<2'(pf~ե OhصMS4fy!Q:E)63DDDQ]Fq߿Nmx m9`| ӊ~eD| |)dkѬ!S?DDD^6vms\[TiDDt3EuEGQNC^Ʈm>Q@j2}\ctM(m~ݮF^<y8w2dNr0݈?+}^&!ڧoDPy&"M~ry&"Y/b6~82 ~w_Fi"(WFzٻ]D^<~wmo<Z|&롚|-im|H )(O},.Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( ALdBP 2Ȅ @&e2!( Aod[+&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!D[sIDATLe&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&'aajgIENDB`pyo3/branding/favicon/0000775000175000017500000000000015105742312014507 5ustar bdrungbdrungpyo3/branding/favicon/pyo3_32x32.png0000644000175000017500000000134115105742312016745 0ustar bdrungbdrungPNG  IHDR szzsRGBDeXIfMM*i  bKIDATX UJA%`g#ZH^@lim|<}PAl-;ffgl\|?{`0-xM,՗h0=4L8|s_[RcrW~ޝ \Aw>Vݯ>ݺ߯_]'$%v'MSf('7,3JyTS oiKJD0(* &4q7?oE3N8c^S<988.7GQ%DT-ŭ8pC5s$ˋ$֋w40f?4л!3i݁Y`*l$4c/뛻*Ey;C |k<:U$/ bd0 x FN$ iKU"\A)H+ Aas|R: ɘ{hced ĤpXPbdaRZnJ OyhGSS$yR/`[IENDB`pyo3/branding/favicon/pyo3_16x16.png0000644000175000017500000000071015105742312016750 0ustar bdrungbdrungPNG  IHDRasRGBDeXIfMM*i4Uq2IDAT8uR1n@\# .M)"< ҤNy@|* .PHYJgf.+K}aku[!*g. E0pqȻoLRܛ $+[F @E|L (qÙ ģ&5b%J –? 3J!ro&@:fЀgE#_UνxHP oA46@/ARhύhύ>utbnލ;c3Z]z | SXLıV؏nmcs׳aXLqV8^+={Yz^|_z D H7mtG2-̏hWJOy"[;ݸ潸`Fcd7= ˼祧ؙåg\㕸g3Z3¹͘ @ߝ;݌hEkUR hr+g }լWb31hvHsz% -gN֣=7Q-zOPzh{L8{^zIc {X }3ժƙ"*~HLJπXJXhύ@B2QreՊHg˞-'jܚ+n=uZ-: Cc{s*u#Ơ VKkKYl,g3Dcm=)2rՊȕz[Ȯ^nx?#<|dꄡq?x ͩ3(fE2􌓨UgldBϤ΀ciJqiLꌡV3&@O8@_=\M0tJq[OGR ^{Z)d FA(R:c(/eώޜRꌑVZc|NI4fc:a]٩Ge,j-uȨV  92֚:ܟf:~G-+N=uY_<82rՊNZ)ˍe,ɗz>gR'0Ĝ:/&S'RLI5,RtY(ћ>W_ oqu r`;{G#nJ!ug{`]8Vk3~:n;+OUPFo~~;=o7_E|}cM 2rWv3;=$nݾ:!ҝ3y'{:*dt'2\77ߏa6ANƋb~:_7Ww~o0u Cḱ 7ן+uMgۛSY('{ߺx^KJexdr\~&uon_ۻ:!su38?ݼw=H=zH淽ֵŷv8?VGr5u|w"7Rg0D63c2Cn=uL-+սF\~&7c2J!֌b~<^VRG0|b\1hgrܽ nݾ:k6ˍ8Uz,u Gl7>NYNL̷JS>S-+r5lw: >W!uic:#xts|I|[jf{s*un=^k Dvr\q"ZNB\kD- nkèP6lPeX_R[Rt ל6V|4,fŸHA[%C`:*ō\)uʉ\<umju/uA-+}T4(~&B/u&n=SbLfSȑ'bQL ԲBܽ nݾ:PUyn'?GsW;{-vrtNGbϕkyaĭ7>}Zȗb9??:Go^y7u996ϤΠ{y'u|OdBꔞћ;?wrà cc;+OUb;?z~|wsAOݐ7X_Rgya|u'q)$nΥΠ^i|o΀O5c20*@`5Ÿ6O/g7Ƿx.2rbk{b=GZV/F1u ={ؼqMØ'~Xzǩ3 V{#ڭRŅߋ+;/S{קn%J}wFdt˩38ZVr|wS7+|:u=vXܿN_X?}/R}'/|?u cΠ #(sz:ݿgn*=ŲaFn=jY!u=l]zCrRg'OR;o Y\٩v0?|:1fPVROedqރIH6XΠڭRܽ nݾ:e|(;Uz,ʥB~:17c2Oīo|w=Hzٳ~4C(ƕztʩSon_+~a83C8x/ب׈݉ nމ;,Hdd>qރXcH`t'Ƌj|w"^֌4CUs?Gl;aLfl?3:1eL6@N0j^#vwRZ-u dZ)L `8Y_ʢ(`lՌ 5#$xZKu[33N+<ėNT 3㞏F'R ė?QyoOSq|'ucf~d+c`KYꌞY_Ƌ碖=::Y_bcyt_ZEg:w'=7j{m~s22VJq?V)u ˕lc{s*u O{^X` 047FªQhc9F1uv?GFT+;B9:(c2G7(``(t'}WιpJnl,WS'@RT(#⹋өAdokm2ucj:>OQ'T)ҭdx~:1n{3H>x_o:cjJ3ȉqރu~F@-+ RI2tSǫo|w=H0(@~k&fG_>ėć?J V)u [x罇_)_Qzs=nB[k5P10 8)@.moNNȭ+;8ح`m,WS'SKYlRg[Vdl/Vbku2uC*kךdZ)D2(@tY(ȵ,D-~z*y΢e#c˥3lSgcV)gZ>_oN;[Bg3.S[k|5nLik5Gw }Up&6 p2["sxtꌱlc{s*uCl_?c2Y,N`9 @l,WS' jWv8DRy'+uRfЂ尉1[VR'0œ 7bϕRg Kg`:!l:!tiLt'RgZt prXdR8>r", KYx\2pt z[*޳ө3_clc9+;S2@8I@ntONs9IU΂A]Rݺ!85@omoNN c2T%u#ʉNràEo6q?E| R'ͩ3Fouʱ`䇿/eȅZVF1uȩV qLK>݉ޜJ1:帴y&u#v|ɗF1-CaArESSgC[16Jw"uHe80A61ZVR'0 ݅өFޅZ\kD-Āp[7CۛS1(`moNy0vqiL >SF=ȅb9uX8ߝƉ_B=@gVk3blNΠv뱾d@.J~ s\xUJ06JڵfjF\)5Rg ZV3djF1`\^s 䚍bT+e=HJ!gbcqn2Y(ө3N#Ubku2u=bLfxt+1N\UJ0B\٩Z-u l `0.֌W=DN` mբ( ?zˠ uONk{Nn=uT .3P]6v F2T+~f*u!Sbň=dP e>:[3J!5<ѕzT+Hg})f:ce8ܟB9u &"ɹrYlW3roku{\S IDAT\~f*uɘqj;:bP\ɨ̈XbQL,nb{ӈEgѸ00&3fE2$dT+xsN6sVk_>n=ϘhqGF vT>Õ#*EgEe{A߲9e,c"ɌA꺤k6n=jFdjW[>nSU׮5ɌFz)r 6֗8ܟquղB/e3Wf8ܟI\-+n=u|B9V35V)gZly NLg:#+ōEehXmNN1?W1)jө1ѷҭN`8a@2O'*bJw"u `c9Kj})ۯb9.Rgmq'dC&=ɴ[R'pLJ!^kT>d6mSggSղBSgmoNNkdGRQNI#,(9`°XN/t?l|><ةzb6FeYN3+JF$Q .,5jb5EM j33b;3ضj^lc9d̊Nȉ#hJ݉8ܟq~f*u\)v3F#Z)dꌱŕhQ1(@݅өRx񜑠eXN΀cY_bc9K7WQᵵVZkߌɰp<:HhV q?3#pCN}$_'jY(΀V #͘ 绕 1'HBV qe[k)|dxd3lSgLQͩKH=>Ę ,9qk6Q{v:v]Nm;.3ĪB\Wv^)HVRN,0pV)u}ōύ06:Nl~]NqbۛSY(΀Z_ʼ롃z\X gS'0`ڭSRϸl@Q4^X_bkmxGڭR\<: >n=֗Jw"uCʠ Y4t1.>|J=>S'@tC c2|j1#1(=*N`B\~&6]ZVD 5(8c~km{ӈ٣2&Qt+BevՊoO+;|q:u{z9c$U+zl8;帰ZK}Y(2{d8b9uCh8N[02ڭRZ B oJ SղBSg;ZV/3&Ñϕ(`8 @[R'R3Fe`;.3֗Z\ۛSF16 |ZV3<5:!6n@K\)^c&S'@=;rOҝ ~ޜJkd8 2 Tg! ^ˋ+݉)#(z|1V(U-+n=u$1(֚1OcL:ߝZG Y4voV ^#6)Co 0P/[t`J~z`ж7rc2Jp $dEZ>ݕzSg ZVD Rcc9j[3r(gVN`S0>ڭSȱ,f޽x݇sYT+~|w"u}j|_ۭRx}gp={/R rGoޏ}^ܹ uk͘m9w~v|󅟦HƘ |q c2\)nx.-_/Gҝ0&@\XEsL_O 'b9uCZ)+/,uJ]XLc gL~;G]8:!teۛw!bt\, ֗h63Ƙ 0?WI&*N`H]<ʘ~o,gd΢1AL ANb})/Z棍OԲBt'Rgg,G~bc9+;uc2 J:!D}W 1(`ϕ }uro{s*uB|2&tޠ G1}](N`D6q?E_SV'S',Guۘ ) ڭS!J!??YdV1(#9c2T%u9gP,S'0`w2ݓRFRWQ#f1Cg{s*u‰֍ɐ b 1>H(FDόͨ3!3(r:c}ix=+Jrl`8U+ZLq,dȫR4UUJV qe[k)}qa.oZE- dȻb9u95Zg`:V1(V ZV0&PXVR'Sev:1eqȅ|_y&:e8ܟ1&P8ߝH@N1AR,p&[q9(Fg!Q\~&""~u~q_|w=Hɘ D|Ax:u\)g;?QgR'@_ϕ~5r)DD;=ˡ[?;īc2 i2Ξ=QFӍϹK[WMq,]kFRHIqĭ[><ט 'wRg3eS'ގoGVgSg@.ݽ {Aܺaܺ}?{p_oLQ|qH1uXNj-&B~o0u::rkQF1: ߾#3V)vdzŲA~AɖRV)\lb8jDD֣Z)ʄXƷv r䱳g~:su3sݽ w/nݾ:%ڭR[.vsF8/J`HK2A6q?_x}b[|<Y(`t'{:xٳ`ԲB0u˟՗KV) .Z)`|k{Rgv:N=ϿuOUx82sWw:1(@uNNGERoHX,V)B+7U+XN7O@ڭRxdq?_潸sofr[X9_CgA""ⱳg~:_QRgoEb[Pن~'wRgN=SFј #Z)K{p$b4ŸsAsjJS2Tu*uX:߭N  SrY(G-s`9A@Ou ҝH@b0jY!ڭgW_`55 @uO^y7u ,p:ڭR4(G7^}ヸ{Aܺa|u~Kd ҝH@bejY!^΢p:Ο"WgKYDDxq_7ߏ}x^vTVXW_ u  7D!&J):xc{wSϡOЛ:;8~pt b2U)8ҶhSϡ4S> Ap<J=#Bc .LOV| LM|02ӓ8ЩZb6׈DQ"_nzrc |]rpùJr8oO'Wcc!vSϡ>3o6 qxr)7ccŸJ):x}~9d!x=sػzkl֭[o5xmzF8}/]gsl7ǛSO` R^0p },8~h4|9$Ԛ)=j5by@ 0|QN=/Q/ݺV-{8'7}:Щ1Xq7 *\⍹F)3h' 'Zb|i[j*ٰu֛G@*r.G)o_|8}z wnO=UㅹKgr@JYN=!s& 1d,揎EO=54=YH=UtScQ-;RϜ`۽9j5\#?"ZFg'Zb|q(@s5=Yz>۷o5b3z lzrc z>^9:CpeXڥFZ>p-Cz쪔rػz h֭[o)|i[LMbpl7^tSO'~xr)ˑwS.RTdi51d,F=z5SL=ugG9jQ#~I 7Q/mΰKi}IA&AgG9^9:;@pnnJ=UJ8Щsػzw{`LMDe Ɩ| |AcGKۢ5SL=1=YH=& qm>0Ax]PWMMbXT-| z>^9:&*УeHOZb6׈DQf/qaJ)'*У` UJ}\#f;évsS Q *\Fj3Z32GP||p=揎$K| @oNY#cqh4sJJɣe>OTw8=ˊ=;qm1N\ ˈ7,8.5eKZ1׈;˩d^kfS 0QeLrqh|i[fd |QeL(?:z>i5zzR.^>\j$If1^kG\^[%~<bW\Μ2mj1׈p)}OP{55QW0Pe̫rqS=zNߚܘz}hj00e1^cXfgܧ=;1N=` ,8~h4|9}cjz}@Cgd 0(ɗlg8eKJkzphLO %7$V)@o5br9= XR.vXCNfĭ mɗEkzNϙܘz15QI= e>cjGbX4szF)ٳ{wS$A;h5\#?`?Js1.*1W50ط ƾxcS,@UJx~H#(5*\FjM'QO5SL= Sex=;\cumzz6N= SeQY#cqh4s֜ k,T` ܧ=;qm1j9[|@4vK'dF6o8J):xc{wSYu{wVRO`LORO A.(*\;8'_b9ZųOWFRA>XoC'aS?2v/o/t|>3CQ)K IDAT~uǘVk,ks_.'}L1f;jSO`@ '1оr|G2drv] ɥuR.tj\#vns1_8vpTL`U8Nz>ۍ.3u{F= Ǟu{O[J}OP`Ř?2?</KkzY5Sp5{w$gG9v?qyƪ};1F=SȀ\RŁN-ޘkޝZr.f;?WSO z@cG٧7_~>ӽQ3ñ=8 2A25Q#cql7ȻʗӓxͱgGyhlq `58ЃZb6׈xaR\^c3f1BX]uGVS=lj|{g9x15QH= Q2=RŁN- XSL!z A'Tˎ3<('00=YH= d %z Ax]PRO{2!(2@O,eP-;A'4 e @F=Zv A8}B }MP #e2BPOLROk2@ϨJ= d 3eG@Ϙ,e2BPjSO5!('& '5AgTJ4</2BP)ղcM LORO[2!(2@Oybz@zJP }KP #e2BP)b }KP #e2BP)ˎ5/'/25QH=o d @F0P' 'p| }IPR-{$Ʒg2BP #eӨSOK2@iN=/ d @F=%z@_zx]P~d @F=QϧЗe3.(p_e2BP #eT-;pzd!#(2 %.g(ӓSO5#(vsS }GP #e2BP #e4=YH==Zv ^9q2O=NhLݱxﭟe4e!rr(ַGv䋥uŸ?ĥ|෿\X+2v٧Q)咼2t텕${4TIP|64S~OD_ذaC\+^+:.]Z]wKP]x~H{'q/^'~vM\X7>YdnS56?ط⡇7ƆX~,n\yWon(@kqhSD!?7"""W,GXb}{鿉|7ίo~+ݥkA!(ޝrq,w#""Vl~[cCD,_y??x7෿L;Ȥ [nzCgG9U%.W?:f1 8ㇿ|,5{(6l+/^xﭟ9APr.^9:SS֔ _$(_o3zƺq󣕸ίo~+ݥԳ>!(hPb2_$.C @Ġ̝<Wޏk ?߸۩g=HP̠dH\fp A/3ѽKsgS֏̧& q8Hu~9NZ8u5/n=AȨp}Oq+WoĉSϮƉS.<6屉ۿ_^nGfϟR…Mn@F=t5>V)bώrQVXfԶ7o]\gc۱@YJ)zw .b[;nxsѽn !AȠp q;XZ~8+"RX}ͨmox{wDDtnf dLku |o>3HXGVGo~m§q{i!B-n@|{g%'& go­#30e cvRO`ˬj9طz zkx/|Y<6VK  iRʥS\ԙĩkqyFy=kz/xݣ0$ͨmo23ѽph CM'N>9?9u-N*.8ЩD&b˓;""b{V\Xp&.KV dHkz<C2k(*xld1~񏣩g1b)y<޾ⅳ@?ڰu֛GwnO=3q;#Q)RO`Nf:{([g,L[xV`Jw)$Z1=YH=T{(jű~\ZT{(X7>ZI=!cQ..#3K h}e9.Ӛ)1XCZ=<#<#"> ,]<s d#Yv@z0> D ̬t3x  ~4xzLMRO|<ގGoGħnGf`mغu#7t,Zbdɩqg텕s>gW{(J)z G??K='?SO-^`S7h5qxr+2r.$(' jۛQތ[` & qqB?4Su{O&0j`u\^z|B~n$""YX^o[]8~h4*\Pc˓;b˓;"V`潷N ̜?+ݥ X 2o/\O=g~B<ۭIN{]!N5Z,$a4S `aa&96e0}9 N 5{X\fm첲 l":EC2JW8A<$.σg6W_W_ fUH\>fK1[Zvtv0NgfL囚Y33F::0"nR'Xn~9r1wr zYF֢wJ2(#ݏs 'RgCn ^9y*u#(RL/bqJ:2x 20Bv2HZq:ul.b9 rDDttvYe`l6nYatv֣R520B6wS'c&RL/bqJ:2ƊA!~`es(Q(#"h׫o$}e`15S3 1wr zYvR20bnnr6ud1TRDDtF 05S3 1[ZV5:ZA+qdPF^^#8݉^RL/bqJ:h׫Yv: 0(#V[zO1[ZjDDވZZA17{xIӝ L/bz+WiE^ziCŠ fnєcՈhoUdFߠ 06J1Tŕ+ߎz쬧Nx,ǻWSgtS3 15˴^8206wS'$NR)J"ZvF<  F?uZ|:S3 15s/GӊF֢^7u0(#h5Hp^:1\> r刈hoUZAQ77zqa9:X^*R)WDw;:;ѬUHT l Ϡ [~3TRDDtz5eiP`NkS3 15s/Gӊvh׫1fPFk b6`Td:l.՘-Ơwȸ̠M'`FI2(Q(#.EވZZD뽸M&OK̦J1Tŕ+ߎf7R#Ƞ |B,\^z5qN1|̖VcahoE^Mce`m6xd(e:;ѮWc20nnr6uO2q)Uvj\x"e`xK^*E\l<ZA+u0 l܍?)O#7+WZŸ 20n5xfbqqZ7R iPѼ3:`(M,B]N+j4k20 ݽ{A=2(|̖Vcj\Ɛd0v %20~$1ps3x#sk3ce:;ѮWSGȠ ֽ geh׫  IDATZ3.# F?uC*Bbٸ 20 $gPD}N0.ǓA 2<ώ:h׫ѬUH20&v l.՘-!dPDuȥ`cPf:3/~ө3x 20 ݽwɉ)[0[k;hNgPȭF?.,gSg0F|,\ŕ+ߎfb\^ $1rs:165+WGᯣP|'2٩Y0R2gu/uDăqF\hoU]gNc͠ F?u|R)JeJYp,1bPa̠wz5[ke)1Sǹ3d'P,GX^z5Jt`10(cuZѬUYD: A3Axf\>.^p\fNՓ'O~?u}%;L]~:~M1t&_?W: 'Oſ?o]Ly#&2'wЊ~4H&:x p䦗J1TahoE^M/A3A9'''R<R'p dQ(P,ǠwZ%Jt0(cV3t'uL&;՘-FӊV4xaf:^l.+W?BdRgˤ^  R';/G\h~h׫H1r`TN|-w:uU(P,ǠwZ%Jt1ts:J&;՘-Fw;J֢wJOe"uF}:B,\W7(IO,:Hc9s 'RgP^*R)W>v{o2(cjяwKc!Bb9zV4kh*;hNG|ɓO$s2ukv'\ꌡSS3J&;b^ފA+ ":Hc9H^n~9r1X9vZ%:;멳ce`Lq~H^&;b9 r:h*ѬUwJqb حF?ul.s/~N`dRl6qa9:FR)JAثވ~#u#̠ 02(Q(Z%J zi20v[ 0vfbqJ,\V5JY20nR'X^*R)zVثވA+uǘAs{A="|̖Vch*ѮWcNqZ foPHn~9r1X9v{opZ f^M~Nx2(Q(Z%J zi 1206wS'<R'@2S3 r%WDh*YO2(cnOuqx _k`_d̖Vcj4kh׫5If^7uPH cqJv=^SIC':> NFXBثވv: `(>gӠ pL#7N+>f^7u@2s{?OIJ|,\׮K"{*: 2Nxjd8z#7V$ʠ nR'^]o_Lv*u0 _j9H;Nx!|]pX&{*: 8 _j5;Sgcn;:d' \g/]3,<2NbLn91bPx"e^BoxH&up$n5q{?6X(0&0^f쥫1OaP`HƉd\x+G9qsw$?̹Sxɲa!_9s̯RGo3{_?.477 |:0ٸ<|0@s{?I/OC?:c2u*NFLӊ~z=j z9SJsZ`]x+xjꔸ}7շ?|:8nk2SyA~t1q^F}hX9sW#ŅO=v8k=k b9ֽm ~=>OǗѵ'O\Sg fⵙ qI0^gb6;Vp`'\Ο_>5I`t5::`,e1wr̖3,WΜ9;L_|zH2nn|?n|5G;L_^=:?7Sg fⵙ 3(65?z:-y[ol܍_5Oǘ p\<2@J4kRfPxk‰)c vm݋ m R 78ĠEg?6,C :`ԼƉɉ)cˆ{Zenwf?[qwZXBlXA#dLf831p nq27{Qw 3g*u(01nn<t`fq7~yx?6ݽ2K65Ù8p"u s<o*,k3 3˰ |軰}7շ?nk{A/3dHP,GX6,/A`1`gZeZm͋_7&0¾z⋟K 2xNdxL~~j>$nzhz~揮~ !skax 8u@DDx PF]3=_95~lXE[jR' }&S5(4S}24*/ Ġ 9쵞axwei浃zQ 3WBtSN?0,oeP Mͦ ^|1kS@2ezc2܋H@cʽO,膩S'p P tG'VNx;<,3ʩs8!葙o00u@Qo/9k UcN^61saJAoPyXj9c ŐA%M)d|{ P2 UcNfzfzOcKP R;zĨk/-1MGjp8g +kS' %+S5(4S}Ұ EǠ @WIP<,3kS@w P @7TՎ|cX92TՎ;-F"_rqk$xA覆-q?FDfOw~*shmO\eH oӯӿR]vO|ٽo;c^?zqR)~װ KP^y2uܠ  eaxK|c2VYņG/i܇ebMe=M@+/{۟8?/_~^,wfP,?:ntM\?ry}C_WqpAxa -q%?Qu8'cG IDATuW@;2ݰm 잸+z6;'+WMУ ofP^iP\|#[qWn{ʥovwx^9fPn8:-*N(I^&ޟ\{y[lxקEê{<ʇAnhruW֦N 0j]d+ꍯ>>?bPֶM@/jBGTGlo<~UI[(^eimK>rGOeSgDDa{{ cSPd tӑӱ%: UdR'C_L6Mc~.>MqQs(e:R'DթJθ g4kҶИ7)2USP vO<:]e3cnӮsOM@3(p PvvM@>e^7P,}_4?ɘ~Us(@eS͝t:68d쪡{ cSP@ #㙖| z7(1go}릸x92aEs.uPgS'P`fM5Ejp2(pֶcS32կ":MbMx1(pֶS'ی:x 1a|AU,eS'@Q?lOxOţGdR=O [G'VN8;7yǞKĘK+xsI~tϾAM36vz"Sgu6gi4$\2 \Z&K*c%}̀(R#*;w\Xoϼ: fP<k['N~xq{>ؼ=mNN5o:oz߼ׇf?4("&I@jxu =u=Ġ ztUAE7s7ISYsMEbX<~w0: dPd*F zWOGgG+uRQҚ-X#35+AWǴCb! 8P:JZX|#;?KaH,Kp#@Ώ;/KEk|ue蕃 Jթ(c퉕_;kqhȠ @ZќKlޞwn|1Z]a[Z1[Emq8 ȤNe+ᑡ1o^SdM =O [>~hrLX@Cc̭~)$Mb q͓S ͹ '^ix~arӶD4rܽ-R\sN(Zcc6Ʀ({ez؊=:zWO -o9b|JXnr'W7>=.V:lk[\@@ꉘ=g| [Z1[cᒽS(Q;֦N((CS'e+>#}ۧ(Kez:R'@9늅KƤ[cٚs(` &5vz"u <o|!u@0(ЇjL@=g<=u}'qζxbkS VN(Y*_;~Ƹh3CG:OjTw8H=+,w/jK@lꄂү":d?7u^_<9:HA>v ùh-zeJCۣqq8ו:>Ԟ:("_7U'H  @[ےOD~1Ĥ[cvyl=קEêS)2 hL@ ؼ=fn5&Ci!'V:\.sg`N3eXќK@ۼ=sEGgWH+, M}_E&u?+|T^gP =O3-^=cL`;pR( (S.uÃżyM:Hdm !c2v9ی.7u}$[q,6'J+ $3rGO3Қ726ojꡩ$nǷ1.V:GH  c2pv]8g[u {;Sg@WIP=u`=+_sΛA]Ց:eL.̲5▯\WVN8_ȎX|B\9Š @bk[\;=1@;sn_:~Ƹx9Ġ @bG:Oڙ:3{XܡPc̭y&bW/N@VK@c#CMS͠ @x9:X@ ()mNDmFe(jUJV]vO X6s<ܮx qńs*:6O'V,j۬ڳ~{\(4]1[c?;n:Yf P?`ovS:ޙ: R@ho?}q7&3.꯾:ӦEmmmL8n-͛ñ~ᅦR0g2lűGOy)uۼK.Dod&~Rg\WխSWӦM3fĴiӢ ?4s+KIꄂ2CG3Jyԏ_ \7dR{{gZqlhc2cbƌqwĉb֬YoӫWO?=pZǾ>6u tKթ^<ْ: ""ֶM@-3~Yubǎx$c2?QU+Wƌ3Rg9Y@̞3utK gtLjC}qQs ͝;z:u}կŲ5ܹsǎXti444$;77|sяҥQ__: eٚq̭q8ו:79zD]voJĔK5NʜATsg`޿`عcG,^8]5kVlڸ1iӦc֬IpV[Z8gQ _&:8lxm|!06uP ͹ ù+oyߌ3b`ITֳ&NK.Ă օ.2S' ijO7>=2USeƠ @yiضd z;m߉SWϮ[+K\;jjjbsǎxbL9)~~D S'P¾~0>u PF GWuN==V?w(""u eΨ  pV_ȎX|B\5yBH(YՑ:G+N]R&NϮ[3fHB3*;^7"uBKސ8:eLu{7Ed A"gضd үFQ+BMMMяbS(sFe *2Jθ pNd詟w=է A"誎 ͰO]Qv̟-]:2gTψڑqbLU@!2(P$ֶ#wt Τ{#FN]Qf͚iS֦Nutv-_iù)E=7(uBAP:$<:#[AƔ{WNMX"2EHX ֥_J)M81]Ψ I;s@lꄂ00u@IWݚ:ٕCzT ?_d=2E\IN]AaT>u elKkި S'9;qScʽO+qP 6O*G71*C!0*pa:O HPP**R' P|{Lՠ}1EjpVƠ @Ώ;R'ff~TRSScT䶴w(JMPP2N(9[S'y}w1'cS(De {#.30*C!X@̞3ueJao IDATN֝QLՠ}1E(:2EfSLQp O/dFe(ȤN(9#*Nv.HM)>ïڋE@1(PV4R'7PZO~-u@x JթJι r@rsLՠ}1EH:2EhmK>rGO(of.Ī+6u el΂]Fe@nM.n1'cS{(4eS͝WRWpuʐ~LRݓ:.cDLՠ}1Ejp  @Ϊ xO''Ƴ֥ΠutvEmFeŎS'2 75d rjĠ @ڳTlu2u@Y:=tf.ĉ㱥KSgP::Où)d pU^md/2UF(bHP~q 4k֬xRgPƶqζ~ %.'u\75&p^Vc ePmGesu!s+5+uelKk>fߙ:N((VN(9[S'qUȸE"2U{gP<k[3JEmCz<^ut9 MPPs czciOA"Ts.u@xvݺMB[7RgPUdR'2޺?WՎ\/"S5WzA"we}8u&V\:2wmy{>u@Ah JPPgS'S'@r^S?z8wl<2%;?HPvz"_s] zICCC<3(c]8g[uNHnAzѸ c{{ڑ1Kǘ{,(k7xj޶?jjjRgЋuW̘1#ueQx~ %.'uƈʃ}r֘c cP*i1*[xSg[4jkkSgPƶc3jeS'S'#[q,uqcL}v&p~ ͹ %ӦΠĪ+SgP断9O~-u@2A(QL=.x{\}EБ}~6=eJږ|*u@9 S# sSgP,SgP**R'+lO=4&/-SoIr> -.2i-WOO3c/9p+u@ڟ˦N(8S'Ndggnb\}Ejp HPrx@L6-u |R'P::qζ}j_ e(M[_{Ęr1ʩI;?0(PB?/l9:du@Ejo::᪖ݹ9yS`V0(P N]z\,%΀؉̀ @hoz5u‡*޲&%=NgPJ&R'T}OK?LXCN#3Љbg.Oelkkl<w5S@2(PO*d oL2lÆ O1rd2O@r P6 +cP V=do1`PS'Tc'b}lÆ jȪG}4uDDDb"nN!u@UR'@Y5V֛OkcG1:A*qRgT:: _x[oQ:`Z:0uURW(nȒOF׶]oHUà @z! N@xGX,΀=9;X ʠnN!u@9=5?^(u>@myto6nNU @3c*sble3•̝;7z&;:MLեNȔ\O},up]vE)P TW_+~8f 7p}n\zK/Gi? Î*3(޲&{R@2(0 S'dZib\ *ܹs㡇J16q1|L¼ U^lL^:\cs靱r#ķcP`W32kO@CEXLs1q,r=Tf?:]5%-Z{Wt?'mSO*{`2u@f=ԩ Tsg?u\K/Gib 2~>uB7NjCgzάOjtriꄲh,F=l)P1 XL:vb*F=CK/`Nz{_Q ]vE)yef|!V x\*\{{{|Sg%?6":0uQŋ㷦N[D`uO4273: s N@:.K/Gib nB]S!u3'0uܔ3SS'̘\cs靱r#ķL2(04צNȔc'bd 5k7u\26q1Op޸P:!sjjsf_x?KR 964uŒ[~pO:R@%sȔ]K P >s2u*OpM~v:!S1:4Og̅sຼ8~k$ѽ}O,۸9u do-^?RGP~5~)u@Կȑɫ>_rj .4DD)~w:C:032!?/޺.up$zuES/RM^Sg$Wze$^zxS Fc2qԇNˌSg|g}^5܏_;KRgp+uB&oYƂ=S Zx|Z5{~;Rd:?6{뗿htX:.37_/Ʋ S:SgdF(.5uWp$ڛ^eMƂp$u׎~>߉c2zs"u $nB*O5&~p7::eZGooo NK&.ƎgnȮ RSY_k/l8 F{ӫќWf(ɋs|%=-ӏɗSs@[ښ324~1^8M5(!s?.)gg}/ TS ͼa-/n d(߶?86l(c fܹq@ȑx[ ^:})N9x}?θL{ӫl,h8 Gf:yq8=5?uFEX'/}{W^NegP k˟w $u WQS{\Sxq>9Mƪ‘D εYv(/=Xy9P<2K[scs1u@f=u=T*j6wܸ{c`` u OO,eRDDġ S'd1\znjT'_S'T-k{xOi*G\xp5r}2e*O!JG >@ݜB̬*Wcuho: &zn2@ZS+us]l*Յ#H,?pvy矊ɥ3V9Vnbo錣ޜH7̝U`ik.vl.ȼo;6!tח:{^|Ӡ 7N+:=5?NOЙ|`fݼCTąάNy-Z{W:⥧/bP |푅ڡ T5kDXR:> c6*9]60JD{ӫp$VU#f?Y{_lY%߶<I͠ @[xRr6(M퍁pE_Zet)N\}}cD=0=P*U#*'D?:cZqQ\&^x͉9p TqaYahh(6lؐ: dPz| <Fe4&.ԥNȔ¼ 0myǪ‘Xr5zq˟}>&/6Nď'_NĠ @{xXK;AnHWggP_Ze"`6yqxqֈh-oˬ.i:.[gSgk޾'>7x&u|(wT}n)éPC/磷ur9uB)N3y)늃"73CH,?0gNa7x&uA yAnHggg&?uʠ @B9 F'#73Ū‘u7nx_(._/}{WDĠ @}-zy} Yi`` zT pM?.eR3 RSr.VYU8[Ǫ‘0&/6N&,X?3&N:""/^#6-'F&u @E6n{^_rjmruu7_H_ơ Sgd. Rg@k-oˬ.i::2tf}<}qzj~gϤ6$'>: é3C 1&/ZZ(._/}{WDf12;:꣥6}%ae!˖-3(CEu2}`I`85ޜ:!S R'@Uz†p8Vĺye9 ๮:>F'dςU=S;c˩s ̀X(wֺh~M~>1|3u3Rg57pƠ PNO͏S=1t'╈WcUH,kz5ڛ^i:~C%1:4~:~k8~[?TbktoG<:YȠ uzLϚ9 Qh6ʯT*HY&u X,Nk6zr*;yS*v R7:fɥ1:7Md7z{㭦8sa>Њ{5ҷw[oN`1(zwGK;:꣥6"".Œַl.틯~30]<)23֥\%9x+a nڶ+^z8rf W!Ueik.,LsM-704&:  p]^8NLŲ S*u?߭]T|ڶ+>'N{s 7Osђ_ȴslt4bÆ S k֬ImN_>Ҟ:RR'dJ~·? kl[:{7'R'Pq ̘,m}BP IDAT~337_'kko>2@92@ٜoN)5. +mӏɗSP\ܐ|M暸ϭl(4xcc1w)TLlT 3N}vO;A -mŒEK}AvK&n憎k?ZvL7(Tϟ(jSUbLi(|2tƏSP% @ƽwg͜Kwf掎(4hv1::Sc0u܀=>󉅩3*ƅ ѽ}oQze8uU d\Qw4Xښ%N v_WSgP!ڗ-K7NS'dJݜB56G׶c2uݩ =McBG}4Ν:lFLƱSlqCTSx۲;7GS;7'RPjRlӒߓK{{~;}Ř TR3ns*r RTH@oY|[G*A!K[sG??4v>0߈ T eotUS\c5EkN@2(e֒7ϋɥw4R<6:Ȓ#qT J=SL)Ȩ+7=|*;Y)ɥc +:ok.>{wY^ K;:S'dJ~N2lڻkۮhך: aPʠ%_55 N`6e5/S'UcVИ:˷-{c)Tw4>qo4NfؗR'Eib L\K)9;cͩS820>uw>KZsSchh(u@Y <:pZYvڶ+r)dA&;_(4;,[徾>@j? @;9ќ:!SR'PD#u NWٷ144TcPS'M<8:p ʼ[Mm.uĢwN c M2&חR'QR)uܴѓS1|x2uPN7NȔB*M_I@`L 144:l?x>uPN7NȔ\wE85u `Pndu6370oٲeFCe=v,uL1(ܸe.S7:*o[F)$fPn@K&Ֆ:Bh~9h 7nb.uT\cstm{,ܗ: F4pu}}}166:`ڍM\Ó3 ul1uB4N X5S;`:}|~OS /ncJ뛱mCCC`Z=|q.u]vE)02pZ53le""߽;FFFfdSTJj7R'gg2!?/uU.߶<{R0 u(4;ϟؑ: 84<: @KN9Xqsf;a-mߕOL=`~=&3zXV'4~1uPa-NȔ¼ "w5k.jѾxfe""blllƏKvNn 31U:fzkۮȷuN 5Xښ?;r7T*Ŗ[SgаA Ґ̼|ڶ+I@kiяw`` ߟؤ544:K 31U:\cs靱l)A|Jlٺ5Rg0 N8vb*uPa-NȔ¼ rw5NQhv դ}qCcJزukC,FLN*R'`ڶ+mS&=ͩi,LD@~≤ ̬ P6Çgg2!?/u\o[]vł=Se*Z5=M3iV,R'D___`ƱP6NLN*T]LMN kl;>3mܜ:dPgMc :oK? [*Ol):GS'dJ]S!u|ewn\c>u 7Ƞ \9*6<<;vHA N:TBoN)5 pE]vE)2pwԧNdú ?SgPF:' \nN!u\Umyto[:Sp U_Ә:vu pwԧNʬ!umٺ5FFFRgp )GS'dJm}cKz>w5S.egwP&"΍Tߟ:2e!wIfڶ+mS52ZH!uUJ%2ݻS';d X:!Sꚲ} +߶<-S2bs ʨLeeJS'T쟇56G׶bI}Sf=2p?yB̺nkJpMM‡x|(J3 S\:!SR'@YXAJYmͩYTu122:+ݻw̙K)5 PvF1:`V2(U,|mkV*΍dT___J9GS'dJCa^ȷuNu E`t֜:ɦߟ:2xeo[Mm.u̘bktm VNU U`tlJp݌dϟؑ:2A)Nkl;>3ܗ:`0(W/Nf@ 7Q)^Wé3 NWހ_9r <+7=:`V0(W3*ծʽT*Ŗ[$422}}}3 N7NȔ9 ̢wEķNje* :( 7m֭uX-3 ӎ-NȔ \myt?'mSA"u0R'ܴ}c)Ǝ;bxx8udą :2]vł=SA#oNf@mM`[.FFFRTߟ:2Љ2:2#w|zg,/u @1(Wq~WC2PVVǠLDıѸs7vR6###eP&S'dJMm.udΊ{IPU oNʬ%u´*JeغukΩ*###qƍ3bl1uB4NLZ޾7r)U |D:okNP΍cdd$uJU/JRƛR'dJM.:2+߶<|[GgP>_G2P͊hokHQñvݺS*XܹqcMxuݨ9 ioLP 5NʬoݱcGlb u{gLfxx8u dG?Rݿ7bLoL!]EkNP 5Ñ7SgeԹ9uB ƺWRTXn1R'dJ~N(+7}1Vnz$u@E2(όNʨ붦 3T*E___9622wnFGS@E:tbaLmhLgڻ?|bPwLGLIowK5<<wn[n1Ck׭R:*Bmͩ O)9"-X]ve:|s2ڰnvDD++_1,cccuزuk(Bm ~v:!SR'@ʷ-{ȷuNe:p_8:(~:!R}}}nݺOH[._QB.uAƛR'dJMp3rѵmW,Z{w3(=gc_ʠ I-[Ɗ+fհX}+vݺ86::*RmF#;5>ϭޫn/klKzKie:U|s32nI 166:l֭)PkS'tl1uB7NbGRgdAț3iV,ƚ[RgdƱرcGtX?pN6CCCc6mcU)t֜:Ƞ u2%W?'uTEkm"טO9e2GZR'dNTw+b/I7!;7n9P @:0uB5R'@U*޲&yS2Š ܠ|!R `voӦXpalݺ5FFFR']~C2P&]+R'41U:!SjjsjۖGoHe&woAkS*b_].VX?p߿?ueFFFb֭`زu!(  bLiKU-]vŢwNȄZxJ1X[ `Կȑ7z{{㣽aÆ;X @ Ʊ;6f*c\?(&.ԥȌUg)Y{gRg$Ko?iJL?sA088FWgg/[]sνcpCᛏ119+y mӏNHƠ L?s6z:\:o#:j30^Q,#љRtlXsm\:!SjS'h]/}{WDgP_}\|`~`=(C _zl$*Ӳ  K)9`VZ'CQ`֩I⯟9? 3iKy]+R'tl1uB4W@*{<)3ʠ L 4HK{%~Gy\rѵmWoL0c wuߖdcpX؍5\&N ݋ucL 4v!Y iM7@8 $vn햀cKm$KV|H’?$}9z[:d>/,궘{צ`e`ܳ+zOSۚ K# Jye6up欹6^u{ bP&@OhܺX <\y 5[:TTNKel.u y1(s@ uP:{R'Lg&WnJpFe OD9Z֐:`­iV8Q:gqtъO«nO @"=}~9n 6Wm ܁eޮrZ`5.,>|QͥNx2b瞁9ӜOCK IDAT\R:`rMcSgw2uBAS'aъXzFecP R'h][C Q+nJHPP3 5͍7SbP;tt8;up֭n]یhoUꄂSQ9-u0rMscyS"  {6wé3smFqwՍ"W:dr*ձ􆻍 [>:8FRwݕ 19:(/1veD*ձO6FSA(;wK9͙%53.J ejU>u«n3*$eP 'h ,rMcqqݕ 19:(e~ie_ֿ)u0I7lJdp(=o(uPD^82#uBAdS'Wݞ: @=s@ ,kkH0!4ު g|4.,^u{TdsSIĠ l<:8K7_cfMNHG_uꄂbLx7.7mT0exp(;upѶ>uʆӜIHPP**kkT0e@}qp , cp:{S'U @ըLi^7},up4gb3.uW6ĜL ȼr.uBA:͠ pfFe`P 3p5[mqIMZ^:(bթ J&W:(1􆻍Š l<FSggn%?kIު uP²u3c wΚA(b7H4+u[n13"wjhj MMQP3 @VΚA(b;w}`ʆҔ7^:(KPP+rZ `ըLŭSgP=h dHM ʼi $Q Ѹ)@H\ѸuñSHz爈Gw9ޜʘ3+4gbNs?pn4gb{_OLR&V-I' ʼ*2[xmѹk[عg >$:1s=;_>ݽ#=yNm#>{Y.uشXlQOߟ:-_fĥkuAU1;~FǀqS+HiΤNJgn"""[u~'/N\7jFMsFe`3(%&Wn)%mS]7bS]QKS&Ǻ3%ecqWSg%[▫Sg%cCG{8fEn5FL)ӧG'n}`nkL::^-R s\ 0֌Ȥqn9͙9l{{Rg%fGRg%h,T9l}Sj8*jcthESSg+20yK30"S`̯[iӣ._:༼vd0~^HH.J{3u\kMDݼ߉ܬk(+ӣ]ek32*A(agVĿl:(vd0<Ngw }\weCkפN8gw{8@XXE3uc='u>8'/i cl dr1c%3ޗQ| @ҵkRg-OuŦ-b)L|Mc[;#sڲ$OLKSg%O>oVF%rG|<Uh-:Š Lyv\4"u@z`tQiΤx__K>@Ū53vMNj(.gmxTpmq0u 0 $l`CS s=i˱xNa}⒚M\ ;=wz H|uc|@uOS'%?{Q[12N$2 _ aT&20I|r3 ¦=S0Z2Yn)i~L RgĬ:a\ƴ:0ZuI$aM\%{C3Id瞁زT 3=**1*eSQ7{AD1gTJǔfwW$l`CS i]qo$u %cE]}غ+u}$Z&=:Rg\Ӽ58}΁A ~{^el8+uyӻc)pF&ܘӜILݽ#aYXE3Iki\9`TKy>#uֱ͕DzEn?ƗY=fx_i˱fcKrs͔'WŦ-bps#`2xݼ$vc'!@xȳw<@z WD1ݑ:8 S]i DM,8+.Y:6m=_=NNƜfczYm<߉|y`صZi^]usDâsIs 3QH78t:K=xOJ:cp6ūc06m9LY|lsk`iDKs&>Օ:G;6PTo6=lמ}c+*2QOL2yo{wN ތo͞:Dθ)0&NǶ'czmfR'%jI_`s{K6k`<͹F?v(x8?D珷E_ǫS"*ӣ2u0 gP5?L)@r<N΁11iisɕu냱{` >g-3blxTu?{8wG uEE6yd1*͠ kzNUSv罇p x3u OkƪF6S: (A>Zs*%o,p;9(&C}]=q;bxTd2uPb@ѿ;x 6WO޿8NxxWMA>o\Xtx[ t<ʦVF~f4@477{,!pFgVΊ|$gi]qo$u %G]}ضd(zC?Ҝ <Fes{KggxO; Π u<w<?]?w̨ aP8k<:( [Oߺ?~1:J֧m)@0*+?oRg}LA8=FmqxcP l}cUT&Qxevpc٢L|qC{|iC{ N%ih[3=9@ X:ZTY{i}|x_['/0fF`߻#~Cy02?=*y1*kJss?V+g7ώ|Z`Oߺ?y'u L KWţߘs ;ccdHT̯'_u)gtpRg0IEˣ5ML]OľG6WH󮑸bEu /]7OoƦ-⊕u05uP+OgOD0&{bS3$W#Ctx[ t<ʦVF~f4`E1ݑ:JAxp(VkC IDATN3+Rhc~ ftNCƆtqGS+'_l([{Rg0 C{s׶8?~(bJDՌ٩1fTߔfWl̊.{ǝ:HޑXsKg(Ii]P:}ع۠ "KahX"*VTtz"=!u|>G)1%>ޚMޑi|{GSxh[3=u P ?wo΁bL(V_|* P;=Pu7#[e k8wG(9S]<;.Y:ݽ#b)ʆxRg% _>Pk΀k.+"[73up:w=ِ:JJy>#uP^|u(>wy>u0v|'񳎡){ؽ?7Ll,uPLM\{CjyM sÝòx1:fTGE6: 8yo{wNaP ǿi=2u 0F<uIxW4Ī5ҜCS@Qι+>:|صw0u?v8*ӣ2_: 8 Fe`lMinnv%(pAjreّv+M[_M%G]s{G=:T~f4,Z.\9D{dC (ze1s, _>yjiģߘ R%w$\Rߟ:1̺`\`T.\y>#uP^<8+ZS`Lɾxqʺhl:(LYggkn2pFdRs@v8tt8ulhX2]s`ѹk[ (*e1S+c/ɾ)8s;0^҆+PzOO9Ù)wJCۥqŊeptEC ƿ 蔾%bw>s3S=3hLĔOl.u42p477N3+_6NM[_ט-s֨Q˟Swww{wDDݱL%G]$0~'>}~u,Q}ع۠ \\Ӽh\vy4,^ٺsd{ܵ-u42ҵkfr immKWXti,YdLcO_kGRg%w$僱u{WS]|u^ q7:Jʯe]9PrĿnͬHkcժUP駟-[O?m`Ɖ婮—ɾ)p8+xQ qupRg@IkX"+߽##u$2ymo81Xwuv :{{M6Ŗ-[9PRn1v{K uz-SXvF q' RgѰxE4.<HEoxTpmq0u 23ⳗRgos19--qݺuq7Gmm20$L/|hLg6WO޿8ZTNw{"hO t*hXfTޝA{%e3_z19--~T[Ɩ-[bӃNCq<0{G[;}=u %G]G8oc2V'韢mf &Fkkk|1gΜؽ{wt<: oƾHL /\/!Ͽ Lq˜ӜI}LcqxcPTLE~f,(8eQ3{q|JLinn??Vק&׎ j=)q-qՍ3[MlhX2.Zٻ;o! ɕ$"t bnzܧB9[<[׏/rb+7y}_pa0u $aP$qwsp(nYR +V׾8qbꬢ300?pIPΜU- Rh rUp^};z&uew5L'N( C3rvD:qIIU5G90 Ͼ4)j:*{dߴ)O$uRIhjj+VԩSk׮( (_},u P 0&f5LxOO9Dhz_׻'Q]ט: 0*@2(\k\Pŭ^3k{O=/NTr _BR5W]: FQ*'OnJ`5T:*ƣ:닕+VĦMRTXlYtuuN%ѹSe_9\ uS;NJ@U&ٖis`ض>{6u 2=:}P16o3V=jŏMSqxtÆP4L}JJԹ|y"x"u#GR^=y d[GkniLLm1Fe(W֦Jh! =ĕ5cGCCCꤊsԩSs)PŁÿ-X 0.^_[]-qhȎ#o3gw3${[*u@I|t3svD;q_G!UWf#ؔ: .ۤY(c)0u @[?vt@)ZsKcҬ\dPl[=:FA̞^>vu ({SU/EObɒ%o&uzӓ:;7͊kRs[G'99ė>+_:lké323iV.;b )pI c51xPe н{phmKhhhC'NLĿ[nը ۇ}RgߌG8?JRn>rձpG:(cƦtÂh]pGdRE1*@9_WW6uPK>;.uŖ[ߊEW&??A΁ϑ?u.n_А:`Dͽ6GMo*ǰ̘[kiJ|֘:yB =Åq'#7"lYpAUU|*8;x"u\+&O@qlG6|U3mfzՈXpa<{">ȪUb-3 7@ʟ:8}GϤ)[c咫w5ekLTL6;uihJjp:~cuNNKfP-qE jcL6UNsp(nYR CSLI\Ň1*SZ&ď{P7>u 98;|sӍrɤXؐ1XCgSgڶhnR_|K]_:b==wO[mhn-u 2*2PAiE jb+;oƪ_}+VĦMqP&fǡ? uS$յdtp"^ӡ9IMiKni%jSkL;Ue LCSxOMŠ Eve,DkSU=C+Ĕ)Sq9ygtvv΀dRg#o'OFSwLQwӍƸy^}]oSHpAmhn-u DDı}ŁmRg3(e暦ߖEȵev\$we˱Go|iӦE\['u $ϯ%jLP;0Pt(uebX8>ué.ZU&Ѻ442YӪS轃2^y%LeTJ71;>=h:Ok83E?2sӍ1wfM]_skR'pv5GSg\kۢu1\*ؑ[[SgJ\XywDv\$2,\ИL8qb|>cF90z(ץN(z ucX898SѵdOygp4t-7~]DD,WS&O'`t)Nl=?Ʀhn44LeyNDZ}ϦNdPJձ(WĬiթsrŊ wFenV2T/NĒO5N(ImDD;q&8SKP7>""_N1q?iV.ZsK9 30*@QbɿJX\ە(WuR'#U/Gqq7S0 oK-KIL̎COݱ ;NUƦh-ԦB@ePՑkg;bִ9(XbElڴ)u d׿w_ HbN:*Bܹh 1QƤYh-l˴9ؿqM =:~AH>;.rs2hAm̟֦IŜ9sR0VZlIIuTO<cڶhnRPƌP =:rm= Pf,9J F@rӓ:ܔ q鹩3Z;Rg$SF;#2 Ms(CÅӱg. Nw1(WۮEhmJW:17Λ|>u W_nM놥}qr| 0iV.ZsK9S(3G_hQpMSU,ZP\jREj/Nپ}{,],u$Rg@yճq꟧(:Ʀzˊ4+U9 220Bjb~ە(WMUsR0R0xtÆ0n>vn!uTO<E*h]pGdRP?~bm 0(ꚦߖEȵev\$OI]Aq& IDAT7Λ===3`mzxZ\|U (ǎ%aҬ\FõsRP{.l[: gP.{dfMNCLRg@___8o^)0&fǡ? uS@Ÿai_<:db-+bҬ\TejSP#XgŒkg_?]7L.ƻ":"s3ϤN1u쯢p|ܾ!u T^=s2u@./w?|*_Ul,JLez1xP*'OU(&WǢ\m,ZPUK]@b3:;;Sg{{sc 3m|d|_( f54:s`8T 2TX\ە(WuR'SbSعPVC3J)޲"&EU6u%Z_N@1(@E=:rmlG]̚V:4lDSWPoK-Kcn۟_K>՘: Ke*wDs{GdRP c51xP*A*B}v\dbтژ?'MUJv?HoMtuu΀15eBzzn ([/z6n[#;9S(bFeke([WG-(SQkHōE>OcWǃ[Sg@YcHPQmqRP {c0: `P(WۮEhmJf]̆=0&fǡ? uS@Y?vtHƦhnҨԦ }5o\cTQgPvMSU,ZP\jR|D\RWPn7/zzzRgZGsҾ89x>u@EdcҬ\LuydRPD{c53(se(9r51X֦9S"k׮[Sg{{sc 3lٸmSgf54:"qlsq`ۺ1o(z4UL,F-uR'\.HtMrŊؼeKSw髱s 3ltR'_lh-R';?`\1y_YӪSqݩ+(R}}}qySz~ p^} ( ǎ|Lcӿ tDU6u ض>{6ueh|]]PKn7Ɵ}iR,t}0!j: `dQ3;uE! gDWWWSG~~6V.*uc/Y(fÅ?|*_Ul,4+| =:2sɓ$fOEX&fMN06~#vn @xq/u MOxճq꟧4wDknid[N ߸ר #ʠ c>;.j"ve,D]IcϠ `˖-qU3`LMi.'OWE .Cõm1p)ؿqQFAFՑkg;bִ9M#23RWPf̘GRgXP|h)`db-+)سny SP 0"7'9hmJP\f]JĖ-[URg2!==7u;N`e#ZsK*S:Q6xؿqQ.A.ՑkGde3f̈#}}3`L=xpuk (9{ q皣3%U2 LCSFQpo߸&u%Π dQ&]r5T:t"lٲ%^*uqOFC)PR5_z"uc#޺ܰ @;8m] JA.H}v\,Ģ\mܞIP pf̘GRgzpPR|h)` 5\So] I(xxRgP e1ш H1(EڲeKܽjU SӟSd\q8u4\~[F؁mؾgSgP >ۑ7FkSUbPK0cƌ8ח:ԃWLPܽ?ueb-+ km;u%f|]]mض%>QqsN]@ jhhSg`(GMgS0Oz[?gONx6QmYMUsXdI444΀150x.:_x+uBHDy~kY<Åө Uژ{46N[:jb5ݝFN]@ d2Q8s&R90_|s (jN~wJTCCCS90_|s (ZrGb.CzQGՕ46N"T5F9ܝ:"gP͞^PS̚V:247-[Rg<S&OצN3(1Gű}Fpod l2oloظӫcc2ޟvM7)SRgy;.09&T_:wF4L&=q)0ΜU4MH9_}D?: s~l?|*Ο;ٖ1:uQs5il/wNKycպ(*g.L,Y8u$ G󱻧: 6\#o=Ǒ[cp:u~[斦8] PfO{Oo磩 (K,II=]{OP$ ^3H̠ @zޏNw)20qD2TG8: k 7-SgA24-dRgL]@XpaHb'gRg@2;?:ޗaPLcS1(P_ޘ:2/uebũ -LI?dX Lm|⮇*M@e5MU1N&u)SD[[[ Hbs B`eʶLO|~m 0(Pf_ј:SY N$N1Pz p휘12efQ&uƠ #hA*7S'-NKfX ۢ#ucȠ @YZx% 2T/s3`-3{3Ir3#NE jS'p ?K]@8qb΀d6o3u= 0 l2edL.} (#7/\:iPʱ!{ʓaQL6u ̠ @=:ZRgp .,4(CPJCgSg2,0T2eb \>^K]AhkkKImfu; )P9 l˴{Sg0 'N"S'P&LSLIt<:F]w/S'{gXf7VDZ}ϥ(+(ceթH?{;uem L3ѵd U;R'@2q`ۺس~aԚ#;Rg0 O(9NN6w:FKSg@reFek"2=u#̠ @uiPjo3(s P:_8:F͎NbX`dͽg}dRg0:(WNՕ:21u 92ݧS'@QzgXf"؀;'z(2)2e>TuvvNL̙3'u$׹ 0N>?9t6uؿqaːm3\:1$p^}tuu@D[[[H`J%2G_MPr&ݐ7u# $ٙ:2А:<=t2uq`(Sޑ:dPܾ=ueb… L#jGDT={-7,pf.[ٖ3 e 쌁5s 0b^zl<:J;2Gvn9%a=#ؔ:KdPiwvv&,\ܼpaH8ƙ0"v|(u#o5,p2L6u @pgJ׹}{‰ 0"vt;#m0̱}ϥ(jٖi153eOMe쌾 P:w?o@0 q`ۺسް tC.f|\$2M7ֿP&N:®s3-NP8߸7{Sޑ:`PLxS1@裩Fޓ PQx3l\ 2e \#}}k׮ P PLām룐OPT޳>2M3eOI%~͛7'*\444NйDdt3lY<l[ÅөsBU6>qCQɦNC(=R P6o3J^3q ݽLwejX "-bƧM0(P&~rl:N R''S'% { [cϺqlsskn-޺ýs{#2=uà @c3e}|AwLyL (n #'o\?(SLm|k*Mo0(PFNgcP+v55k pN>{ 3tسny7c`,{2eϞJyS'W(;8J߉=Ǒ[Sl˴A2{(^NE}+v55ſ?:.Xw/S'i0G{/cK0fo 2e[ON`<éJZOR'EDض.o| {SDez   @Y=NO:w~+v55k v䠿@ď6 9n=#ؔ:(C'WHzC?:mKP /3N>:v}=J]___(Z=ONϞJ$?{:l['>62M3*A2wr||yݛ3GGIA3(C}??9t6uP{6[GvnM0b2L6u @E1(Pvt'Otc=oÆ 10005|>:VgR'[H`y~kY<ܝ:`Dd[;פ(e*W7$|>w(PNPx_;:uP 'Oln[e*kWϦ}̝YsݼeKڵkk(U}GNs!]ϩcGCwXqm-cҬ\ `P<5*P&U]Jّ PEԹk{ ql߳g8sk2sm:0'Ǘ׽NO{̽梞?(PzzzR'@Q9ݮQ 7\#o=GpoKRL6u @Y3(P~rl,[sԨ @2yE 6D__(P"ϧ΀v3J‰ؿqM@s.ZeZ̼sM fPB(.S/aP&ݫVB 'u>2g䠿.'[<.NpQ&ݐ.OP T02g{Ͽ-Ke@X^l.nRڦafNqwlSl'?z)0MvK BfJru rM]%~ :cyqJeKsxd2u>k IDATsrneݸ$PnՓ༽]n&[]{ǑN0.m7l3*AiG2ܘ޽;zzz&rٙ:J^nl8uR'Xǫ_^윅3*A僣{M0mo}k(7eu`$uDD+F́b W~o ^J_&[W#mHPQ >7*E?;vsPNzz|,\ >5:pG^x*߳=)aXqŠ HkKzݻ瞛~ P6}:uLLB>?p<&Jۢkn%nMP1 >Fei_Ugܺm[ M@ 夳3u>2$ʡxs:F GvE!7:h^ڞ:"\ irqmPC2(PF i+]qG0:g"mHP 3ÃwOSgL;oh3:;;c=L@ Oes߉ Ls>5:?p{8v+u Odcܛ:}nQ2SfBٽ{w<rq[xh ( K_; 9ӰxYvw fP˨ jvκ}ǎ陰(=CCC㏧::}rqG0:E9u@2(2*0u6olr\ЄIi1&U7ΣO N?p{8v+u y+n (Ke s4^94:]R;uwwǭ۶M虔::R'@ M4@1^>t⥯@dL!u @1(vWQIR'رcDŽIz}}}ٙ: d l~894m^WvW cP v"?fT` 3%/uSé3ǾcR\uѶu{ bPq1*0֯s蘔ZCCCpQ>:ihxd,^>⥯슗@`ka{[)u@0(\&gP&";'?xrP 0vLpIp`[Y:,࢜ȏᑱ)vRϿ}ǎk0vޝ:q Xg^3S/?6N(yeh/mw`76M\.nغըL}}3@#cd S/=+yjX,Vܲ3u@3(%1*09֭ʔݻwN`+]V7R̢knEܜ:xWMLQrRg0{7:` x/žvFP`YqhX87*s\gO coED8櫉 &V&?uW[)u PB]?:,55T]kդNr>+~e ;./ܱ$ubdtf_Fꌤ~4@3cFUO 7F3Vgߍb! ,[)Vo;2)@}ܑ:lk>bv2u@x5ycS *^*Z:$͚=?.[EL`OJB&WvW4/]:(ou}#xK3.AʚQ`b:lhnN@ͩ3JҜ+Fe-\oODD;S#frAl5ڶnL>u P^zdW{+uE1(@3*LG?8n{1u@YX.^x3uޒ:do̤?B>Xȿ7>/4I.0}d,R #;%2TxKǒ f'G_%~m^=SgP!ZU3JҬIc3Q<.ԒMF֧N}ܑ:`m @E8w ]Us'o=r$u@k_&wN(Y"""bޚM??98Sx?#>exc}04,^m[gN0.3ZZZΥ5Fei'cm/(yUu3>%uFjiUVCf|l5ڶnLx5LW;rݩ3.A*Q`:Y:u@ɚPT?hKQf͞-oO1 ( i*;ga\?R  #Q,S\2T$2tq瞾#3J֯o}qe *-:$͹rm_֒:#=6ssG08: `m[G Sg z{bw eXԞY:`Rudl%O2~3RgPkSg-QUIQ;?S#N\ca){/[]Peh!]SgLk>bv2u@IhK@omZjSgP?u]ꌒ5 Q8'u$|vNdӭ;Rghw{ ()e֌f'G_I[Y/<T?֦Sgl,N:?0cdƧaXhX,u 0 x~(S""qWH7\[TN3"J]x(fdtfѳKQ/kle3b5sarc,hۺ=歽.FM܈&4wz5Ժ&u025Q5y6u @DDhii9:Rjj߻8.Iprgc޿ٗ: 7a}Ԧ}ū3J53g5ΠDz{"0rݑ?IPR՟l}`㭮RgDuccs#qõu1NuK?<ݯLw?(uO!=MQk1RgP²sFSXnK,tk,hbMoQ,Xq4u&$S 2˿JtŚx}1LLs3ZZZΥRP_wq]V:t;[@ $r>?ueͱk7(YKVFÂ+RgP"0# E+nl}`žHLse_ijty,YIpIbN0}wc47VgA[ꌒ"S3+u(s~\&w'|$9 a4,^: ou}#xK3iqW(G)orCHpњ Rkⶏ_: GX5T̜MRgPsFXnK\hj]Y 1zX͈KSuMz{HLS3ZZZΥR5{Gc}U>??b(6u y5ycS ⏾smꌒ5ʵQYK ba$rݑ?C=Nyi{]m^:DH ק(Ys>3 FU&FXtѶu{4/k윅Ã1VM #/<u Zn~kTejnAkl`2( PV-=r$u%RgPϊ%kQYK x윅Ѽ=Wl-歽.F3hlrѼ=25T758)4cP~g_=1u 57fOGk'SLUJ@;_Q|th~Y *_wފ_vM?RU˖~4u[& Ǽbɦ[ PvxߌѼ=up25ԺSĠ \R[Km5$`q͍e~U}<ʟMp-ycS *ߏę7ؙ\olFvNMڢ~v ( UhX<K6^u[jfO`ҝzX ϦNh5w: OOyW:7})fOع̚=?/kI#;ga]1Z>hѰxEČ+z{"^U91w8v10 8*AsSu< ?*USs"NM3ϝcWn^m˯P2نhX<Wl-G&cQ70! xOFk";gahj]o3 cP P ֯8~&u [^ל: pb Ȥ_wv4?j:o4,յvPUmIFv˜rc|WcцaÃ1VM@+ƑѼ=ujDfVC)@1(`PΊ'+c_\: q|y8i)tGDD_ݼ8SU3̚0f5/HR& ǂu[ͷEdb4n 7@DSԺ&r=Q N*A2@hkgi8ON`WU3c#q]sm1ySw4#Q=6u9 cʍdӭh͑(fɣoNrq䅧nAkoM OXq4u P 8*IıŵW,O@8tY;;s65?fMyÅ˯J lC4Ēn+DU& n4CG㝞gX+7~B&5s؁)@0(`P$m-qS>c_\m-3|(Ν:Gc/x8SUZ=^,jg>DU&ƼͷżEU&FF0:vq@W]ymd sa9':(s3ZZZv ݻ8~i]6u9X+Sg\ohoTӯc8duM|c S"S3+up 8JW{+rݩs(QlC]1oͦ)R,{GO]#\|h]XZ p){nӹo8q {/ל .ߏę73ΛylbWn^mJ3kh$ip2نhj]9\wkͿ"bFdkg8<H]1u/25Q5y6u P 8*Q۽c(6u O?>(ne3c_H3՝돿m dumEmQSטD`ݖhۺ=ZGU& 1VM@ 88v+殼62ن9@Doba$Ny u P 8*Q* Nx WE*u bSqOh)tGDD_ݼ8S5uKTUgⲥioyk7oQ07FF0: Fq䅧nAkoMDDk pQ 8*U? G_),_\p8ʼn8w\ 6vlzF_ݼ)欹 cV)Pܕcɦ[c*Sc\`+;=ݬ:w90Ueja8SS2dPơul I~u}_{'u@DD\)_: r31Rwv46zcm7k~ ͬmHTϬkqejD0iLocb_LMֲsF̈NʌAM kѼ>|x/Dsc&udG̛epx?:4^g&YѴxل 9Ѽ=Z>h͑(Fe`'5 $Ӽ= 0.e` 5=CSi w\幩3 gNqɮ]k1 7'e"fh(FR0A}}_+LMV2نYᄒ/u P 8=>'uXtVdp~;P:WǢy3SgPa?CO1ef;s19qCSYKd.:`:dbʍdӭ1ouQ1.P!N}3}}_4FKSuMz{H---RG@9yWFc}U )>??b(_'w_E3@s"NvMߡn^&4~,̚*|x8JW g e ▝蚛RR ľwzm@ՍRG@9rm].̤ڪXtV,S'b3X}h-KvG<: eQ۾-z7E1j 5fJ8ԡ"6ve/SlMC\N,2eפXp-cKnǖڧ`w(NzFfz*NuxS\4l}066LPrmEntOEÖ=Q1b)}1q?u 6:WmL}&Wȿ mSX/N?:cI578)WSDž ?vmŬ~]t"׺)u ,kx/B>u H|k7Xu}$_+;]%(Sg J8s$5 kHVY&qH`0(aoת^: ʲx׾K,17ݔ:ell|q4f\x[?EC\jRy6uEmh{Ѹ}_e1q?fJiLzT-SU}1q?u 밹=wuUH"dP){1uqK^ރSmsZ>7rm1S*:@ƅh(/аeO ;`l0(妈_ ŋL3''R܎-Ooʲ),s?{)f/ϦX2S1x"v<c9u5njFˮQUTO1p@4lٚ9eQzN3(P)>~ܳgM8:XGKcEɓS1msmUq"v|":(TNpM2Um}0R1 C Lȵve=gb| !2pvuIUU;||Le_6J pQ:;:c٪ϟ?X*F<: ekqhnZxFRgXz02Nea˞8v.`e:Rg$WWw)"?W:`tXaqW(er9ץ,\kGܱ?Zv폈b|V Bow4xGe\)d=I$bPLBKcEVxb8u H|}-_~-u+cQ<5:cLO3Oƍ1\Ӝ: erѰewQUxFRg(p ; [D>u,M?S t~x:޻&jseS[WGDw#Dt >}Q\: Z;Ѳkk2C1S*XfJ8XTշD#u, [~+A-qǶ=kW&㙓SDvlo>t[ V^.O>>c8/l$EvQݴ> #CQX.vGad(MBY&qH`?zpM Eȓcd`R=*Rј<:Xd{0Jlܼ5u +d#mo?6uEDD~/q ѼQ1V7=gb|`0:>{VELE?ũ)Y+u5SXA OOw/gdb'`iN0'Eq˾"(Sg,[p ; [D>u,y [1S*NAA'kSg,*Uew5bM<a{lhL 38:78O>F_kg*WNelm[>( Gad(u4S*Ǣ%rs`I+d#[zS Ġ ܠӱ&Wwlspg]˯ dq6u0OtmN 3u_˧רϟ?X*F<: `T7Ge(ƣ0<.BowFq)Z;btq\X! 8rro;\ *]^4*ː1RZ>K3JϝzF)S\4nmwٚx,e%?zy;,^uS ̑qfQ+Kh4Veꛟ-ܑK 4}q:8:kg5v<c9u*d}[ܲȵuDqlP1?~t$6lM}X2U(ƫ/O320NQ,FtnFeIQX~w4`<9:봪8O>F_kg*WNsMrhٵ? IDATJ( 7(\ϑ4D#u,Ibt!\X ,ўB|XkIQX>nJ 5sy6?w)f,ygUxy(7`Tqh(Fad(JYKLz#nؕ:M]q 2fPdq6vOW壽"6WNHΨ ,}dHɸd s'ރQd歩sEY&u▽FU}KFNپhز'2 ZdrQVW_8:'e`׏ўBTDL$eLg/e'Tl=l5ͩM#zmR!S',YGÖ=ʥ%}[P`rfǙRtvTFm,u@2WFe~ГSs`L`h!& 3G1lvFru$ySU.w-G0ᡘ)Sg,9p}]-ץ%%׺9=:e`+ܜMhi1QXј ¥G1}q:u >>c8/l$yEvQV)2hTOȵv%#[SqS)3()ėEqWWU$*ˌ"&W=޹.u ɩ,N]#3=:S̫L66v{U-?Ņ( ES`ɨzN!2dq6+򱦦u xdXl/NRgتD<|6nI.-w쏺M]Q2,p #C ǣ}{dko_'[SqS)1(șRu(u 0 "v%*Rϙ<ßd5V'E1\5ͩDY&u 9EY7fjos?:x%b8'+R+R'̻ʲx྆XSCݗR_?|s?.ON` ϟ'X1 S',4ą~@ad(^}xԶolM}X2٨os=GR7 ,13#q-Ѿ.: `޽mG.]_?<9l|7Gך:^>r.{NT 6nRy6u(d}[ܲo>2s=Gv_:ȟ틉SdP3CxP>~W]۪6W: `^mh?u|4p#ʣ˝}uSMM-Dw!uKXfz*:OξEru ݘ: `AZ; R1>u(["ڑ:-{b؁)S ,q?韊?:gJQiXX֪*4ŚL꾔:[OoթSWK1{y6uDұ|qiN Q*GÖݩS`)d"px,u Z#_ө3X/olrŰ /8pUEeIsݵw7MKs`Aɕß|K|}-SM_/eqhb{02S1ظѰ "hܾ/2@mqGG2=;_:0bDa`٩h{vwKI0ovl_oۑK#/΀ecD^*Wڍ2,7EOL: `AFGÖ=3xVL6[\ϑ)aPVl)ėźLnJ򳡭2>;-s1YM\s#k}zKdRu8_KohUq"nXt >51\Ӝ: ]vQV5,8p}hز'5s ȟ틉S_  있ǚr2tZLG9pO%>)pCƿ}9&ON΀_>>v|".Fru$WVR1njOI5l,be3:>'hO![*}]&u,w)FFKɉIp]vl_oۑK7dl RړahJǢ!.n4,HWeRa<}ĕQȵvd2(ƫ/O 2:3TG V]M& K'u5ާND;]|Ѱ erѸ}ooXXQ.vGad(MԶo=QJ2teXP):;*6W: `N]gwmlaQ2-w7N91sy6?w)fR3,e6uEaxA2`EEad(6uEY&:ȵncހAજ+3C׵**7NS*nђaw[|趸m)0g'p:aur~2W_8;aT)[SqS)/0(\}ҁ(#:7g N]Me^l,V5xoDUeY33gcsbv*u ̭+2mOG>kS',+2U-?x$ySǫ/&׺9dq6 ڕa?uQUySJ1.Sgܽ6WgZ:\DNSgiJ>Dt >k7&.Xx֎eYb~`y*\ϑhزǨ +NY&qCSaPnWe~d<ԔIs,]2FFY,skr?>ӍQUY:ܥJ]>>nX>y8Vc9 Sg,mvQV)24S*ƹ#i\kGXPU"/&N~ʠ pFg`D|Pް ܺ:>@S|M12Z&c8:e]͇nwKɸNVUʼn<ohȟu$X8elm{T`_$97S*ƅo1*ӰeO ;`H 22,s-Ѿ.: `^dn[V#Ҡܘ5]ƨ^g/e\m_OUiBY "S{q8IsBowFq)`2(ƫ/ODMmmm]]U];R̻&O _gpM}o}Y]:`A=D9>sr"u]qx ѵ:u,gbL_NK֩Ć;3nL0o #CŅwN3\Ч"׺)u ̻Ra<QJ+A \YX`a`E?j|xip2uiM<]쩍{w71q=:\Sjgo3NuIsntOCK0'\gSgePHʰ k^?1ӁѸNě{Wm켭:V=kcC[e$XŘ̗3Z; ٧x(J|9q{s3`= ?N+A`Qh_}>~7rSg<9O??=''R'H?;sZ: =SU娞.Nc8:c`k}+RV*NjrZ9aT02?4 2oldl:y~2sX1ut;~r( N!FeX #?ؗ:V2vWWU|e&_>6cKudbmQWSh̕{>Ύ}@z Wf~v`f`(Tt_kg8qɱ2* ɽ6QWS;o[*cC[eDDܳ6Yxbϛ~dǁ']Y*`>\E?;:s 0/ #CŅwNn֎O`z?g::V 2rWWU|u)+ώ\qi4'Ͽ&;V 7^oٱ_։ 3ߋmc PTVlj wơ;܈=ER\\kGtǣn]sx/B>u e%c7,H}__sߋm'86ub|镸q|}Se&SFݦ9L 㩓Lȵv9kK˞A`Yxw2t`,ňY2+ϾuWoy.UTwn󕵱}앨B`ϟUx)2TU.n`MS1S*NjzdkT)l)Hoc-s|/U7Ʒ:#;3LJyeqbÝ1V]:X6vEs׽QsڅȬEm)0gjoc <2(,;e/Vğ}(NNe5xݦyr8csqI^REu|w8_Y^$ T۾-?&.9R1?lTev8#Q*NeŠ b]9Sh_I$}ź /U7Ʒ:#;3LJoUq"Rg+TY&;\[G:,jWFeLU.u\L6[\ϑ)V3CxPް uOykꌈ*3kMqp4R' ZuS{Θ)Mho7U٧-{"[S:[uS{ˆx+e~ʰ 쉗Gj IDATSgKݵ|eml{%*fS'W'v'u@eѰewm`_éLz`ɫgMˆA_`X<=3KՍLqw5-q|}3^WU.zM#{R!2,\ 1ߛ:2o° #ocSgJSexf8^)nX$W88֙:m슖]#?x* #gTcEU}KZ;Ru]-R1u ,ye~+2?+ƮmUQ+KӃM㷧θj*kD22~6*fS'oO2UhcdVb9ۀEBoQL65 q;u ,yeOƙRtvTV?}'[[MQ75^:Zo'v'uU۾-( %FeXr1rgnAeщa`E;xrC|K`TY&mޚ։ QWHD#~$kSg\LU.ZU-1r'fJI?Ǩ KYus {,u,iea`b6u ;_YnꌉLeelTNN+u5˵vD۝ą8ߟ:\P4nߛ:I>JMKAdXXI3OVķ:pFR3vC?Np2hqo:ՓcTL`Qb:#enXO8]:eMeh[>JTO@© E<:U7G۝ą8ߟ:uFeX24ą)$ceoc-3u]򅨘N\w7#de,F#^=y]ԁEè KQ#FNDad(u ,9ea`9O<(NNY57ц-h*΁ee8yt=u nj; 1q?u@D6*? [DYƨKCU}K}P Xr 32r;֦XPݵxPTOS'G1\Ӝ:`ޕeѼȵuī'L{ ǣy;$TկPRbP`\]۪2{S$24V8 TwotlJKRn]|m?ܰ/ʣ2unj;0^1?lT%nSW ;`ATd|XeEO틳cSg$5Ug֬uh*N%a<h#߈Sqyx(/ɉ.T12R'̋L6ZU8 92,%elUdN%㦶+Um,~?6jV%O6GqoEߝ{&3p,7/uKoٚkz\Yy&*Vռ_GDTG** s_T~&u @Z;b>=" O? C3`I0(oO.֥X'ߏ/>: ٚmy{lUd"Gf Ѽ*Xlt??9P 2,#{Q X ,"e 'X~XKIMgܕ:T^\}T B/"?ؗ:XE,rR~<.;u,ze!2\126eTE02?EϠ "fX`exxi`2~n"FJsr{ڨ)U=kkꨫ)bV/㷧XrcRKǒEk[wq?ߚg4H%˒-lX^l'76 4Mn6mslg)wOn${sm q4^HJ!9rڢFdْkF= lYxfy1 z>NPCN (?9f1*J0+ @-ꩁ=50\p֧̕?oN#S]'4r_(S*&?UZ&=yU!}3(?|N}MgNP@+s1 e0,Pfz'ȓzdI1}MR%=.*u`euF uGSS C2)Gd:@чU!NP@;?XgeA@GHhm:L31lѴc]kPk:>>a댪3>wjrgSeXsn\SC2oڸCA'at{5uu Ũ ݡ=wx^q\ywIG];3cm *Xg7|3w2-џL<99J7Puv6bQUczWԓ1.xcͽ[5ذNsޠuyERkU(_(uWՅc9jbչjޥz(CDZg2P(?SE:1딷X7:'Iqg̸hJbQ5wjRu𶆜μGu|PC-x|I斖IfSԠXf5!I5QPE1eGSSd/X1%/ܑ~lQ_Ks)j[wXO~Gqk2q>댚#*\tSIҜ7xkթpuNJmܡ 'R0Rt|׸:PT?{)9;TgSun92j+hkWP: fTҘ$M,q90 puF8IVO*A ;Uߤ\>}sM:ظQuRY+yE 5 E3]Ҁ (łgP"hku:/Ţ)@Yd2K[ mYTJyWO~G0"Pr_(2,da˺ZFyz:YO%7T:l~uчԉ)jЦOޥuޡuP6mX=G];3cm *X'TJywI?vǕnbP}m:4ΨY#jڤbQr;Vǜ7pf7kϐry Œj/U[:qv%7>ԯP"hku P"s3 eV w10*SO3jނǧ r֨gUu/hz&lܨP:yIf3@_߫xg_b2(7TN *?p; 1(5aVi1.Y~[BA7_:;XK$';b\J4 `F=ҫ:>u*ܤ:jݼbPE~Ts5wu¨ MuFuPڰ~W}֨uƊXumINfC3p C ;17xa:engF0*rȳXpSS $1,p>jlb:c<3%wxZ}& \!g6vyY9Uߤ7n?yNnHZuZM$3 (['ujnΟP#@Z,:1hd2KސpGBN(;_|߫;bz򛛭3 fC(Sp~a}rY\Y 9]!gN4 Z' Rw($3]߫fl]J_a @?'Ǭ33 2ovrd^;>E딒ͺqg:+ ,SʝN>ͳ#)X!t*^ѩpuE&y> ,ї/ODd@9׿w[gf\pgBu ŰuFɬk jXAFS7Yg`ȳ ]\7ǜopA,\קLMpE >|_NP#@98.M8l`PpEȼ6|uF}˝RX!Їu|"nrgOhu /\!T],gYgZve 3^qTܢtJ(~uVC/l:3A=ܬ9_Psg_*Z'מNnlHmթpa$'ݡ@رemVSn]8 u*7>ԯP"hku jTI(?5u Pr 7e>uY4.YgĂnSG&hs)X#ilVJ7|UNZz5yx>%7Ne 8 U3*?5f1*k^o J좾Im)uf`l'Gujt:?^ dmnG];3cm *eTf&tR;>\-NiXO5mR` 1뜪|0fUNq (J5ubP:@:7x@ݻp)1DZgJA@ɼqX=W*I,2<( 2A]-j7?ݡ%3P<>nhשpzg^hT5o{uV c2jQKݻts*s9beT&Beki`qIx@=ЗՇ?~Q[['GNe:4c@w_{uJwZ'`x>%0&fE[;OS|}u *Uguhϟ);u j̆c$mMg z/yjkY'\N2*#IF[kܤ@Ztr$';b\SHmթpuVP0Ph<ݢB>C9bչjޥ@@MXpp^g_Ճxj`:ۿوuÙ?n]:.NwNw>MKP:@*:ϔ}:5w:UA@82?s^qa2ƠLy n TS&o=)`4݊vZ@YJ_am %ZST!FePjPDkw:XU 2{h6h78ܬuy=ʺ~ T9oP_[)@y>v+սC@uhkv}NP@u;N@U:su2[ԁ߬\Wں!`: Ԡxt\F3lAu.g'3ޡM iZ9IkYS/˿TΩM:I[g`RJv*kN9͜Pe Pc.uj/h|:X ޼ׇe>Ţ,PCyywIw~,N\>r^딊\M k6H泓5vc:حW/YTiXN \o ^9y~H;J5ubł ǞS[sP墭]:1Ԙu T׆eљv%q9=B:ܸ3M3xf3*R0P,AP}<%77S'Gy:ظQ98nSRMex}rj/ȟap]jޥsj&±5oQP"Yg+A@E:2>,Ӟ+`C)aPPUΌNex+"t!ל_~nuF +?yܢ:"9Ǜ<bI g'T,t8N7LcT ;jS};(vs6+҅XpsT FeP yvgP5T2v:,7Q IDATP2/Yge}o^b0a9<^_:?W$Ң*֕iQwkՂgR<^t_`:jZ8զ]p99UNjnd*Xt5ub:X LnQ.}r]i2`yeƝ1ud5kKz腍+޾iYuBф泓Z*V|M %)eiH:qH&K^H`ݪ f'sT󧕟SS )R :RPԄywIOXA[ErpMF3ʧ?bPH}[ZT$Dz _^dF|N* #$'soZc-5!(_@|T1eGsT02X5_@~1(9G];3cJ%8PУK5Nnk"5O\q댊\|~:Gƴg&uaYJ)e%\t5`:jy!5v*ѱ!M=7WՅc)2XM.>90(YG]}燳:8W[گu(wuuz 늲nhBMlΨXhBL>?Q$V|NrƉ!)eg cՐL|m;(i`H*LmBN jZ`5E[7}UaPPΌ@_V)hKW: Mk:x$ݸ3ƠL\uykR;Wq<BrZZZ\c9oP#7y:=ڪ#+!MqۮQ XBKݻtn2VDvtXDZ.TPES'NA~dQ`_V Wi:,Pnꤾi늲L}mzt:bEN/vTآn~UUFB E6 %t*dR<^[._: BNB~T NZC`Ui}:X6e 3Ef e6ӼdbniNx:fM?aQ<^]xJp,"Ɍ<^ܴWE[;9딲Q'`F댊 کDiy~$*jvOkiUQPE1eGSeaP1.`^m *]M@y =wuu 2%sGW XT5t%=f ҠPCRnnF.O#i}huJXK<>딊N*ۮQ P'_ĉyVP.Sm)"LAż#îљ^p%S ʔmNΨX@HT4V44i(iXszg^N)#N3ʖQ,ݡ*HNhADZC)ؽKzBQPP v@_VjKFO[bP4O'ΨhMcA'`4줖Ӗr7(Έ `x|5oYnvRaN2*k۬ܧB>g\eX%G]}燳:8W[گuXG7u)%uUۿѓ-޾IHue DTOhP, N􁉣)KE ;5[o H2#C[TofDSjCn:Դ?!guUoH)Zx&5v)KXgj@S Gu؀u 6wScj:.ڥ~I]1(@Ne5[ uY`ܺ;&SVUCԫud)U_.3*Zr3Xǣxg&ht7k s)fꤧ5pwnL!A[nL+iNԠXfidGu> ]1(@up0jvr5o5i]NY5?6ۢUg'XgTpUNsuU"ol uU;ICG3̤Y=ҫ:m6 t(ѾYNsBdE3SKL.4P?>X[e >-:1Ԙu ȼ#îљ^ ݅ݶ;Qo~S:jM?aQ<^6\:O8{~ESk%II㚫3Kz#%vGZ4JXg.M(((RS8զ]:7xQv؀B])`DZg2#î`^uuuN˔n+ף?/wKYgT]?z. ] 'ݡP,iNBhBZZZY!gvNP0gbbvc$3jXA͊$3 : d'$ؽK=B>gB3*J({vXsO[oAșTW~uY m&u`Ռ0&6={:mQѼz3V/XHjܴn:gَGҺaKE딒[xtrxb]#]f" j 8 U Vk.7ubPݻp)P:ӿ:x[ Pfr:0pQJmibQ @%~MDSE=B:0&՟ΨxM3VMǣH2#Ia-x|y:RμgE3M((lܮƎ-֪>ެ/X:+PlW0*eO);:l\2ywIڳwFg jOJxeuw\q0&r_rs5Rr%t FOҢu;I'Rne>/^!gcWhB(ZEaǔx;̍9*k2~T_:(ҙ%1(@82;?^mh['pΘez')!Uw>' W)+v/IV[\!gnhRR5`4u[tpW27qEx˶Xpu؀̨ /U!!-œ+9=ؗUU{ڧ`: DwsѶf6Nz?;ѷ~:9Ǜ3JQ$$g+gJA-x|y:.:ظ?/[y^4 es`b5>-\MBNJmibQux&Yι;IJ7SlXwr^딊 ka*$&>Ev5mW 7W sT'MNP䯞K+Xty= à n]љ^%})58>=3ռd$IjzQBAkK}ʔcQ:{ [gUآ٩ꐳV7N ɿTN)pc-ZO DJP@U(Pu V~jQ\h<ޣ@cP*rd}Y̫N[I%uNΛM6k5aӎZ ]!%'aQ6<^*p1ksYA-x|y:dc:7)k*A'Ũ eˎKu.bԉAu PΌNe:ml+ow|SqgLO=7l?wЪPScײq})սSuwS}Y@HnvRKK9x$J)%q*ܤ;~L}CJ k6Ĩ 1ubPDZV`pt*s)$ej3Ejvr # u[a׆dUG&›\n]Nx k6($3V (ԐT~fBKłuλr(PB~ƒX9.5ֹZ,9*P.Sm)_@ø)2ԀywIG];]57o>iݸ3&-I_[nzuIҟ&ÐoLMx`eG_֡=B>kBQm콊vZB}t{3euG}ꖨֶpjjÿ/4=[ǬՑ ⎷ąx;9ׯO}wu)/ܮn댊3Ѻq}e?9o-75(60*`]{ ESP!~~OYg1(^[Ӡ΀u @nҡuFx}Jo-y"/&^>G'G'GXU?Eg[nVݠ bTWcunP gup0:mbXj|=댪oߤ`: 5$fXps.iY'*\,Ͼ0_P-;- 'ޛ4ubPnv:@qrj: ڥOY1(XA`_V3%mP0PgPQO'Ψ hBk3T1Dَʜ 7G3VH(!g[nobP@jv.`TɎ+?5ƨ .K(3Pok&yuf]AŢ,snR XTTy~댪Q(Z{Q 9oq>SjC:J8 o=iP@mXB])(sDN *?Uu1(.ˑaW{`^ Q6qsI댪kT}:*u/ÓE["R:e-xz:-3(@i1*`Ƈe %:|uj2+9=ؗ괱ݯ`: lC=:*x!5uZgT7R~uʛ,x| %)+n<0(@`TrMTc.u X(ѢOY1(e&uY ^֮bQuq})UW`uF  %ԓ}U)w:eEEz4-SE6Fe,bչ]i}:5U.ꁾ{i]z: D+?٥N v9)d"ɌZ6W:M.0/q x/ޫhku Rgu{TSP):58:+9=ؗ괱ݯ`: $;uFUx}JvõJ*Ԑ1---ZHAɎX3ym^PXҠHPu؀u f'u؀,0rB>gà Xq3Ejvr^_зXgT*v3jR9 9ks93Դ?ۊ rۍĨ qrj:e*hQΟN@ aPywIG];yiKWD\_zzEuJUoH)Ψi8*3JG3V7|0ۖC* 1*`y*sji2k߬3{3PC%qfsz/ܒn(*9ׯ/>[g @קdW<^uJ+QR]NYO'7ePF\E"FXC %ҊvY BQƔN@Xrz~gR>qJzyklۿ]'U#)_:w!g"I4 Xg.ZgIPD?{/чԉA aunP gxBAtU CbQ5ф훭3B I]Ңi˂ǧO3vzoiiQKjv.P!_Wc.K ESvt:5A`dQg\WjKz񉸾r^딪!oKONHZ;N( l IDAT^N*#5IUH(RW=ug{߿v?o)lKb+Nc;v(I)73 ft-mig.ӃK(mܒ-=0'?@'DGI,ǶK$kڕV_.-ۻ^|3IFz>X(ޭ>  utUs: d]>t~1dR3m] '3pHL^\z:En=fqUFb׼JQ>@ oQ+!5=Q'U.5Ĩu j2*[c=ޟ<m+XgߺYG5Xg 8-[g`uw1kiոؠ$-粊5wV\ 2.Sc>Th{3PU--j`hQ<=ѱe;xk֩'^٦_Ψ)M~I>:+U1v]_~UiǕԠJ!`4)'`Fe\Ĩ{X8r)e&FSPk’F]K<XguD[7[gԔx["V \׫І-Nhehֱuu+cqAIG '+VQ+=6PUѶnTh{3PkT^t/-ו:Zţ^,Pæ#S-Sj?SÖ3p>rM;Nֵc\ӎ+AŌ͝x'ՆQkfdP] %[SP%PTԔ2)Q 5k]9K訫zG-uAmYgԔ- 3p3g"eiÕX͠$9X:;zunx@Py3GU߳WX:U"ޭ> (e@M893z?#y Ē)0m`uj2`][rWpN::*jk: 9t|8tuF͉u:e).jy1c0Jcfk,c(h[72Vwuz:rBQRSLZF0('ǖ@VgήQ<rdI<:15l:kanR+z3oɝ7-{UB^D|`@)1*`ΟRMNh{3P#xts:ؗQW:ZVpX{#S-SjNӶ_bcx Œμa0ۨf/5OxCj@DۺeNP̜r)5N!'U.5Ĩu j2qrlYgxFxӯ`cJ(gnd:ۺIZg~: 3T;M3&Wok,C (=< `U2rQ;vXP[} B:[ТzƧűpRJFg.IJxG:2lQs\o#XRig"MuvDs&ܨmzenWM^ U{1*`UΟR[qBQ@IxW#֢GsGT:uq쒞|vNAZJBk#uO\B,<4xeuF5?Ns#/Xț/C?0bFb_&6(Y"P)C. EuT:Fr)}{3b(-j`hQ=zASymXgԴ^sZr/ySz;3KW}s?_ߞS]-ae5lB?.댚&a*۠y*~בXPolリĮܜ͝xyZuX|.1xu Dۻ5>g5AJgZC^T^>u8Yp>'BP;f?xAų:ƒqGۃe @MO&N9^m$o*Ш̸VVLQΟPV\4^uՕT g&_yRSʥػ:PTԔ2)X(F]=֟ѶNuP|vNc:~&W;_>Gu:62YׯOޯ c Pz6Xgx^9:-MUeԞԩv5t0~ůx 'KX* EU߳WpQQu[@[}X(tE=u xMRiԭ)\Î>)Xu3*yWSjyN:J(ujXԔu e[֓Y=ޟvi֟T3 d={jT({ڡΨYNE6Zg`pa y<'u5Jt]9^Q8\"P mʥNP̜̜{YBVMo5A*ȒpNGub}FXyK]֣fu޸Z9ur6yuFcje5&PA sZ)+zHn=H?o(E#kb!Xsg @hǨ KLJ)֓PE3#r3s)XCBSy\FǖWSg7_X =4' MO&9j%?h5*K*;F:AI?4_9+" mx@-i.)ujXnE:SPA^'A !^t3z。;{C3l: 0s*պ)=__N֕'Sel\m]cXm] {{:XyZtT:@;ăL:z{JXg` b鹂 .G/h|* Q:Z,"N]~+sWBA>(PY'=S_ޡu%;wo*ybIE;tnx:@[U԰uejɱe=9f jwԔYgW%}NXg d:mNjg_^lQm]kh@ ƒZLMw+vHn=Hrw~FM%=3M ZiP(٪AU,ujXnE:SPѶ::&ej̒FoBA:[4}OĒuF~7[ zS+#ۭ3j?SÖ3P μQ;NP{R*v6g:d#֭\jJQU!Uj Xp:5l*Ǡ @ +zƧűVgZgŒWw: og:y}zv[FAIRfbw4c)#v=װz}"%?T}Ljaz:@*]FԼvyu,ڶUg_|Z| AuQWgxF:Zţ^,m_ׅL:l^>[ĵ=hio_>:o^ qXR| jOTyaFbהܕb͝%?T:bHn-nfN 3cjyu 03Ĩu O 3cSy}Kszc'73_/ĒuFoX'kل>o7XgԼHC‰& {+zPb|S1I*  {PN(jo:=Z'byz^cű:/딲;3[ĵ=h9'gS)Sj?SÖE ?}^GbAec?llI9pT߳WT̻9T԰݊4uXPTԔ2)RXF |>ƧYX)XgT̟?u0&S^ͽEeۺ*v߿҂/P]e;[z>.Ѷ.m}}ܱ'TfG(:UXGzE=?Q0N:/딊93[ĵ=h TNsBF Seg*3uԞKiLYRǯh:/ْ7|P}mrQ?1dJc#jyN4` Eu 2x[Sy\#OktlY>u(G3*..螻x'd:Eڴ:TPƮѯN*JJzy<^5P};KM)31jJ995N@b|:UA\ҒF]=֟+huzPc>'t!SׂO4)cx;Yׯ?x6MX<8-~ mܤV ߵuiOT\W>_dgXsgէwfFfSTĨpT)(PESʥSPeeIgz~8}i=?Qg`c5;CiW&3ljQ *1&S9^]ra@WpL '*rߙHymZ)yC'ZKrŬuPwޮs (ZRO )ѵKdu $lK2 OuhpA<=ѱeyu֨O?9OGeSPX_ҙ7>1Ӂ/j|ֻO}g(maL͝ '3Uy࢜PS IDAT)T>ѫ_u J i_@`PfƦ{t}o`_Z٢u` d*/M*:,NI댪NU$h;~u*ұ>`2ظ@2ógSz$d`?T稡{upE !\JbNm}}AYgĜP{Yg 0(shpAv|i\N*˜ 1ۺ3u2Zo:@;J@m~Ͻ  j3E=֟GL{t :#: eqe~0&c#Wp:*N!댪R@mP^(PQ0(al*ZZ7tc:ؗԊGK @1&c#Цv y}7]gPP䄢)T>ѫ|:%q`A9cSy}Y1q:ؗ|h!X'T3 ʠ1&c)Z d3uRD3Tԩu/Xgm]JleCX,v:Rs -G/+wYlu xpܢyj:j캶N7Q#30&Sa^)@I64*;3Ɔu%3@ %[䄣:b:@J(ޭHSu J$lK0Jiti\N*ݺ'nPU.89G1 ]@y}m]k}PŎ=r) HbNEۺ3`AԜt3ȁ)уz~8gKe72@-;9ǟMo$6(KZgem?0W,0H.maBo+>`ڸ 0b#rYrWڨ3z?sy5;jJ&LA3ʊGswuP2؉4i5۬3 F7(;u)ǫv PN@^P1ZBnfN\V={SPѶnM_\:*el*ZZ7tc:YOۓ eLƀ?S3c6wZg Ѷ.mOXgb_Kߴ@l~`AK?yc7t/͸ Aݲ;n߬|vuƺ9jmTTK^c&4ا>h|ae&~dh''@b\AC:ؗ--K>ţ1TZ"ó6;w7YgWW:cj޾WN lTP´u 'V]CuXC{hfdPnf:@*]FԼvyu Xp:5l 6S73֍oOjS[:U^}q:u+Wp:0QЮ`4ifzo+31O?lظ 0_,;`Tc:4eQ0NiOO=?w'uupٲ_Nu+ܩxf T Sv 댊sa5[g5ܡɗSTĨBVEۺSpN@Ԕ2)eU`\rnN?י%3vm.KMG&S֭&o:0U,f/XT\A/pB#N [RSê٫@,im`u*A2y\&jk: l&G0j\ }ǩuʺнK: ΌkehR1+m]`Jl٥ԩaRS)P1*=6杷spPTԔ2)eprlYOdu/ѱeya\6/W2)ے `ՎL4oŐuʺ9j-?hT +?܅i딊bP\:*]U̩wu j~ T2@ ,+zme\޹3GB`RQvpmu*o'[YkfHLKs*9딊aP\ Psx[Qu[ -JV.5e2cP(1eJ#=ԌuJE㧻 z3Kzh [g{M 3Z8?aQ1 JH)uj:@JV}^bI\!'չ 2@1.pu6%I7.Z:קufu/֥XsuP՜`XywQˋ딊`PBb.>*]F~Sp"Mau ʈAB2ȱ~:gRvM?|DxhNY" mJl:XzegƵRN)+QuuuŧU̻)S>U}\!'ȠuʈA2 fSq}꾍:2Ѥ?u&3u)?SÖzS5je̜uJY6:Ps&_NPc#w+a+J2$ Pո|vEu@UsBi-+9eѥA -=6n[Y{pLM=9)%=B:l@APRdRSTLJԼ69u . Xp1(T\C^QW9kBQ[v6ZgIsݭ/nI^]ra`Mra-MYg 2[v)ujXTpx[ D۶=j2aPb'ǖ9ǿu #3űVDcii~N7gR rItKT1ZBnfNP.5Ĩu ʀA`xq QQu@EڨnKO?ߨ.;ݮE:DrSBF ` DbμaQ rqBQE;tnx:@JVkB\h{3P kOeuxpAKRsqnʨ̆O^Cg[ngHlQiuP|3)%Ǡ (HSc#)A:\'U԰r)27=W"2`ݩQ6pm:$e]z}u ~NMf$ SJ*hV(`jXsΟNPyWcj\PU/[gjϏ<ޟ5%}ie=w5hiM.[\Z#$D{~YDT: x}~TcB ƒy:7ٿ_^l7cj-AP\<^>G )%à xe&G0=fJ?xN:m`y:%  ,+zmՓYK#KrVG:zmj;?Hk]O6D}js{:NgnяS1e͌Ĕ=B:$m]ra NACo)̩wu .C*uj:%  -+:9C z ::jzzQu:ݵ?g45l3;{"?j􆝬羻[NusԳ[N@1-(ve@x":7<`Je&FJ*mUmՏ{:%  99EK)Ƀ`mim랻szᕌun3oWk:ؑ&̻tlu Odu 8Tps)W-)?h֑HSc#)T԰w&'N*xr)e&FSP xKs=?ӗ13?W0UGc*WwOh׵u:o)-+&?EBA@^ة~w2n:o~ ƒZ8?aqՒ;:ܡ'fSTbU԰ozu V)ޭ> 2.)-ꥑ%=֟Fǖ5]Qg`cpQ۷٢c\ew\_=箆 ّ&̻Xu ."WzV`XywQˋ딫oN (ѫ/~:@r3sGJleUpBQN +NUbPeYrWڨC z ::jzzQu[ N/ gt!S(]ڂܟlMjmb_N}q9^5[g?Sܘu F|-fRSTԩa%v)lN*8 Xg*yW#Ԇk_Qoꔚ/o<'K:,_kݤ[Kv&p%L4/ݫ:\Bbc͝~״0;aqEѤzv[gu:u*Jh9!~f|{U`P@Yt8]!ݵNwX__PZ/YW{zկew\7l=q}{d]ٽkS 6o:)|{*)-ܩ RS}2)Tc><`U|:3pPwu!mlqs.;Co?,sxKymuʸ~c2@JOHYg\x[m]ԫ|:@z{3p \V^FC0eTTckѾg!eY'g :r:Ę P݊&_ueiڶ[X:@hu*儢?P:lww)*R+6`dlu_guVI9uHNatê?`#d-.יv4RCZ 1`Cs#؟xHʅ׮ KG:oɠ fFX^ZZ{)?Sk]7N&ǩSθ)ՓOWb':7:hPRg 8qh?:h}}ߍ=gcj˝qR!^=%~6qoT/d}5rݛ;{օ)܄;7F:]1)7o}tGnx4_UA*swDNdsQ>g?L`PXuŇmxe?w O orotgc(y Jq;WWnrgnBWO>;::R7#:tvg#?%ugd6E:)@*M]ߋ|_Fw.Mʠ 󿌞|_[u[wGo_+j+En*@㙘4ĽQu&ucFGg&u p{Kzoݓb /ذ'VK4߿?hTپMqA`6ޞ;dז;w q›;ع҆,Pm94x9>9| dutfߨ}3#J4zu>jص?u _#..}~ :{ ~!o]菗{sg}ᮨtFuKv\Xm?_n8sifu׽>)_k}ptϧR;"JS 2u6r~=S _J:`Pv>Wwj˝҆8vx͝qaiCtgc(y:V׺?OxBn1ha6u׺-:֥JǣVK4߿w2LwrX(@X,~:h;h:溗bOBgBl20@u oNJ+uȘ Z5uWڼO*Sđg^NTa{P B4'&t#br=ugԖ;w q›;ع҆,ǐq7w_>rgn1hMa6uƗZb oԝ'S ZLO.6s_D&ٸ0uМZiL&"R3 -{cbj0f*#n)Z_M@{/;Zwn#c2cx:3,nήu3nX&'S V#uwD&oO X,~:h>7F::eM亗bOBgBl_N@u o_;9c2^/V::3Q3#4y*u=|䆷s8qh?:h.}ߍm3&Q[ߕ6ısw oroԖ;}5;WR' k]'_UӇCQuNb˜ ̺Q|qc /V vJ:hP|𿋎4Lw\aTΦNnJwc`ñ:%J;޺?7;w-`8 IDATD / Ԗ;S'J]߹?H;::Wb2:%""z.ߗ:[dsdA*sR_vKH7p,]xe9uJ9sg."""׽{b8c/%`5͔wGR)7%*~+).gLhn?:SSQ`>%[4|>0u6adn@m3~WP߽3>C>*w"n)u" ͘ pGGG|J,VR]#?_a~XR 4y*tN3oO0(|C66l3&-Ֆ;̥B;wwx8{\I\8vߞߐL0- $ucGK&'S ^Ze.vO䆷zu>u _ ޻$VSZFg.ճ[gƱswLJ Q[00Рk]-?[cܛ:5]ܒ:hwtt|,-T5c]/n Q-ͤNTelc{R)|&O+Q,?N4{/cFMl)^l Ϧhk3›;D֕:+z3S-o17/'[e8쓩3G#5 (8qhu [5?`-|<.u<*SgS [cSj[Sg%(Ƕ3f>^xsgݑԺRXgw66&ܐ~5=ߋLwϚ`T>>:h`l.:p42Yͤs:@c.$5roL1153wD /hX/7s|,Xu?j˝H'u^5;ZE:)@ZcHuw?:ϹX,~:Hob%H*+ƞ+lf/鲻u߾;::3S&S轨\ݪ3CWgtw{k=1pĕc?}4ucPU`|z`fG)zR'cxݩSh@ܟ:hb3oP^clX[c48L e"[ؔ:x1Rg)ex h)gcx!g -c>^xsgݑԺRР6 o RgMnefFe+zo4*#ߤuw=q(ua6fL/3_+ƞ )9u ukN3 shpi5Fe::3qR:'GZI4GM@D8<չ\ePڔ1nP~>gch)u;Wc&J+u 3w~7zST轨\-;]=kd6+΋Rg ,ž<¦)m㿈3/=: @2&íu/@)/Xq6ƆgS'mj>^xsgv94|o02=SP҇be;EoqđQ<:h`c Sիq짏*2fɰƊc 8K5__;|w$\*Ρܹ1FLMk qT,fciٝus0z װUK3qoz:h`<x `\|x   c2|)h)Ʈ>|[xql;uM*7% wB9Vϼֵ>o {h@ds'E)u @[::0(mØ )店bt{b8;K۽: hpعN}gWSgp N>TTΦXa{P wxTfRg=2ЈFKcc/h)uȼ6ywTj]shrظՓO-*M#Ϥ?>Oνz4h gPZ1E{)FJx!FK8K5`DՓ;)&x8_U exd{Sji&NO @ 3&CǞlbtcóĈ i}pSgpիqxԫ)@ص?m?;::eLV5VWf _M˩0_7attf;:U2+΋Rg h[3(-Ș $׽te\x!FK8KdDd1^;wwZ\gw6|VđQ<:h`l.:p42)mOz:mcL"󱣿+ƎX#3ڹęK9;7FљIL}'}2uv~t0u@:h[e6=643<: Z86ywvewem61&7hKL84:maLnh)v M)7d18?ZW$Pgw6|WOFun&u 2\:-cQVRg23X(]Z5uǑbG)6/omosŘ.N]#':R-ĉC3~>2Y?Xkg^z>>:mǠ 4{?C{x㥅r_\,-Au/@3C3Y&681u|(lޙ:uգqGSg nb'SgCi&1ϫZKSeb@)1V^J@:s篌ȼv9:qwu)4zu>Nz:hp~>rRg#4y*u@[1(Md>oe Q-fW (Ş_RRgb>= ԺR' n ۢ3:&0+΋Rg .7==\ `&rc2_f4 20\Me2_|b8ùؔ: &11x̙24L})lL@q{F`6/Nh{SBT>B]#':_ęK4L68lo1+΋Rg2РeLʱX>2+C3_283<: %te0B7N5љ "7%u -ͤh+~Xԫ-Ϡ 4Fz,.be.XYNn\RbG)rj1VZ)u@S^1p(l̤Nŕ&Ođ}mKG:,c2_f< ҅XUSluKxpn>6/NXs1xb!\*΂Փ東.ߗ:6۟oO4lߦNh L84:c2W-D4{}dh/_66^R4[vҕx`Ltمe::3q_L@r"p6,Fy2u@ۘ8r JRg42 v~t0uƪXY_XUS' c(9v"v}|flXƜT3 1U3 )ttf"7%r[3:6vգqGSgM`Gnx[ 0+΋Rg42rcÑNYK +3X̥Xq6ݵ(E{R4Ek}pl)|84j%u rcϥh~s5UdPk1[YBB,VZz$]18ܬƙԺ1]^ Vú\_]=)|ܨGMμ||t3ZAHdB9JPr g#"bOBDD"n)v{)eʮL{c>\,T7\*NՓ東.ߗ:҉QI4L6~\d Rji&NOв @"dr=Jb2l,S'-`(?Cˑ@)">Ǧy7x7Feh $ٝ ۢ:QitLy&uv~t0u@[8r JRg$2@&5&sʱPl,-S-,׽t}lfG)rj1CM-c>1! }Sg_w^<:%5bÑޖ:,c< XUS'mh(?ÇhsŜXJ+˽1UbWTH\|L24ji&NO4lߦn8qhev/%koc_.ty}DDq~kc ̮ DGg&uܒw^<ӯ*uF~0#7Bڜ2Fɬk2 \iP~>""rK1:PyFhX g.Rgk1q~c>`mիqxԫ)@~*SgLr yc3R幨^YYNX5cݵό|~&"blx6h]ST̥˽1Us W՝{h@(lcOJN>TTΦh)e` \X\,fci: c(3 c(?xg^7R͔T XJ k?` 2$@WOFun&u Fy*64u@K~xEC~AXedr=s XZ5u@K/En~W ܌&:RY Ɛ Q<2u6-?7=2M]a냷|lh.VnT&L|84~[~e`SYb<l,Vbe: VEgw66 obh|T~/~—nDD4չ [wwl.rۿy.`8<޶߻7ghqϤhix8_U aPV7r,fc<9p >= SV>3R<,}"[}+)F&On-9ePV1ֵP\,bi:nغ\_DOacV*SDZ䩈/|p -Enx=ןg Cir#M@c8r9 o}O?:88s534y:&pcFy*64u@/KFn2p冷]dԦ굅X,E4XYN "ݓ:6V<WbDunP M)]0:*ypL@ds'E)u @Kfġ- &dr,10DnpKDGg&u-Z>S-MG}apՕad(l}0u_ص?-?;::yd2]=GnpKDakp\/N|~0ρ/6T<_غL0پMWGgL laS }8_U \|x&OX%C{6(pQ,?N,#7-u M ΍}ShR^DiT2u6Q `|،N:'GZI4lߦx虣3Zֱ> [`LڰBi6ʩshPX_=IC(M>Se o24ӷL7u@98kx|~ 0um @Z?wc]/u 4y:s3Q-MGQV2u6u@ =ա7ܫGܯhI'}nAɐڵZGgw6[b}1::3sXc|TFelTf?W+Ӏ&veX2Y ^>չ)@{p>:|tqRg4-2p6,Fy2u|a3kg IDAT}pUu)1@jپMe [wjWDoS<-^c?}4u@2(7ahqϤ΀b`9tvg#?%3:UR<1@m>.sehII8<չ@x|;S:D]dd&7-u~xC3&G#MR|{e䆷rm`vqVMz'z љI-*M'2SD&22(lNX' nއǟIrW+3AdhB,bir: %tvg0{"ݓ:o^>?|"7ʸ̶#7=Mn;/J4'ypLMǠ |L6cO)VׇesXKTGϝSؘ:pm<4ypܼlߦ+3WGf q o}O?:&OđgRg42}~`fe: ]) FGg&ux 104+.7kbGSgc7Ϡ |~|0۟:Zp}\fr%ʩ\WO>z#[9| x)@:ff2q@&OD&L7u @8h*eKtVtC3;= cDAU>xLel$Ƶ]u /R<GI4GL2*Sg}p3 `uR-\)}p]Z@nxqSđ7#7-u@8qx8nDoS ص? [L#7h L84:i o'G&ۛ:z,]\O0#22SQ<չI4L6m^=`5&OđgRgM$۷)zh q٧2u6u@S0(@dsЁ.6W-gFfnP<ɀ^N冷އuw䆷ZđQ<:h"#?h EyM m-]\Mji2K+PN4|G12=sRi}bQ`E&OđgRgM$ž<¦)MZ2'ZbyB =wnlacYc|&OEeds1k?O4#7ehqƨn>3Aֽ?Lz,].be.._YUSg;}s`6i+dx#'2#M48b9nxp{|tqRg4<2SgՓ)l|Ꜷrdhj}ߋ]7lȁ(MJ41ġMZ }8}22ͥ3X닞`ttfR'k#2Jv폡}S 4y:&#ps}@ a w٧䆷ǾK4Ok tK Yжb]/z ':mT>oJ&]1.|#+7%۷)=|dSGg^^PcPcO,-bir,/Vc2: ZRgwʀ̝.ImZo(}p:J$HڸEnx[LJ@x|o@&o5hPl.v폡Ga냩sU_ę~9پM3GSg4zu>wGq&GԈrT:$]9%וh(n8{]*.r6Ţ,؋F ]9B) ^C$,QT#ج8k Ԙ='vlI&>`R}hHeh9RO<w/`m.bscsmINVrTgr6K=mݻKh1l)zVK4cWSg4׿{N>AZJ._Bߎ) w#x̦-IVmȐFu\S /DPlzµLh!_>OK4\_>t$?SǏh8eh)}ptJ>/߈xbOc6JmYV=[̹X8_e'@+mCODN|Nl)^mۆ{*u@S^ e:pCkQ77bz[[L*x̦-Y\ǖY^VC2ƓwIܡ/˧З^M Š -wu` W_dhfz{mזi|16w)& QN46DtIܦZ3GSgM{`(é3d9^p bP??y$uwƵXbWׯXGRM\(E0YꥉXAd9@˗zbWCt E.wM@zÒw쉨g à Mз3~r \(Ŧb:iK16K X8n`D._m>{G'uj%N4!9?ˠ M+/ODoG>DD{'37%.HoӖtcsؒ:PϖA,/ZLm Eî w䡯C3d9^p aP#տ'uk|#{7{هyZWOj>:iK1riK1u ޺caHAUg&у3&/ėKДϞzVK Дv8{;uݼq-Vfn^ =}s>r[bs4ZyD|93RTۿ\/t! ;cOǶSg4#1?>:!8g7,uТ6Jt'1R,V#2QNe";u xé3&ˇ6ySeh*]GRg"7wfn\w-FD|8BsiKc1:cDh&|!=xlzçΌ GXI4cWSg4gP/#yA\l.""bsbDhve1̏n_._GwNh*O>Rg$gP'Gз#u |{yFf>51bӖbDt dؘȐZJ._޽cۣ{gKqpԳZ LTjsb٧Rg$gPG|td|#[""k?k|XL{G>r[-R,/b|9uݻ?6,c3&C pΌ GXIA}ñ+é3`]xcC`&"bSg1s?3kp+aX_l)O4xh*O>Rg$ePֻw:p0u4DD[[ׯ{~ݍkBK{-X X8_) #Iw'GO Qc>: )24BxɑN-kRDD{sikŦΟw#ױ!D̏rԳZ}plzµXXCYg TW`<Mpd!xs2.4xg^yZW׮qƵ5o䓵b3Mm#2?p - :{PTgΥODWMcR d Аۻ>i}ͭZ|:Yܧ~/y1FU+pQNд کL٣SgM*_/<:i.سOH:v8dL6O@1|-}8"toQjqx౧woNտ'+S&-Vb~nQo`^, d9~qod9VJ}9&1Qۙ: ZB._r Ic3]qX$ 0 };c7:h@YOoośt$ -d93/Fԓ: Zov2V˩S&Tϖ"ܿ;u @S(nI!x\GAԳx;ΕɨgK6ZѨLD׎ ):b\L4wL}UW܂\ X-NXweh{mX,ǥza} $Vb|"j%v z@@Z/GۦLV7ꅱΠ :p(>H Z˧_7NNSN{d۔"V67:hRKqo~#-(n5 lHeHwؾo8u@=[&>ĥNse2R,nJ}931ȗzS'@m)h IԗmSqG[ba˵)ʠ vƞo|3uΪ3qco74_Db)u4|'8j\cՙ SJf\0:`] \іHzov2ο͘-tԗSgj%|U+ѵc_ |1&˩3&Vϖ{`(u@(n*:'G";u&1?> =Q|}ñm9а"w:hR㣱}pzR4|WOvFmn:u i/SGSGNN`ԗꅱX,G_|r\[wLNX=[r-XߌRgNѻw:p0u&1?> ˩Sh0{=ݩSdJ92:hr_>t,]F>_F^,`c(팁I:R$Vb|"ěo_I@MǛMqS@ QvM\j%_hhAE._$: )*X,ǥvTg&-NԗꅱX,=DGbhoM:hb߾];#_IV7ca:`]`] |@gKW_#k'Y-ƛ}?RіHIu{p`/dݻ?u@C˗zǯ:`]`m7WSgw:3_>_fTg&<xdW"_{OW/XVD׎ȗzR4\GleXSCO3Tϖ⭉׿{8f'67: ϝDm~:>іHIt/\X޽Sg4X,XseX3ROƟ{HVœvW-N`xѶ#wXwmȪU+ѵc0) +_5 leX|!|ݤMb~T\<|\<\c: fW/Euf"v F._H*㣩3&-Vw -)kʠ kb냏>E=[bLȪIY㧢mSGs9n򥞘hԳ)@˪1 OR kʠ wؾo8u .ťՙ )pVqXTg&@tK`W/\X޽Sg4|7~ꋩ3֔AVUog |O-ב:9w67:>SVě}?⮈9:bX/NXVD׎ȗzR4\GWR2\Ht -ŏ_}1hdJ$mՙLD׎ s`ʹ:c-Vw k~3&˩3֌AVמ{ߝ:Ox87:3l)u|.Y㧢mSk|7|3&U+ѵc0) )_b 5cPUm6x &O>$kZJ}9^Dt\: V]G X-N\u\lz"u@CjuDm~:}%u 0K IDAT(?_{&ulXl)ޚxNFVN5U+1?~*:[з3u͸za,uRK~fV7ca:`Mu}sW._/:ݩS`y!јg9DP:pujZJ=[Sg- _/<:!ybx8uk7ޟ:6ܥ4:>ՙX/Nd}%|dݑ/Uі눬Ztճȗzз3u @iuDuf"j%u 3(۾o8zOFuf"ĥx>bQϖb냏UR@ OǶ'Rg4zW/Xue#]!̏׿{8f'+0Y{b)u|.RO4ϣ-ESNGqk̖OXuemROAmn:&=k4X,ZDX޽Sg4b\0:`Uq=Ñߝ:F=[/3GcQjPgܥ)R'-:s.33]@+i/SGxvܢZ'7za,V˩Pϖ⭉W5 };S'juDm~:}%u "Ŋ{C>"/G-N 1]>:>iC2V˱0YЈ6u[ZDVDQ,Nh[ΕA~F._O;rSa :3?yv(u |Llac`լԗ +-ZB[C_?ݩ3!eJL3Gc~|4uFGc٧-Nݻ?uBG#VRg4^,1lz"Rg@ɪx:>9:X- cqQ,uƛ}?uBRtxpK[Cog9@B+xk(nB9w c#Rϖ{`(u@C(nK[{౧#;Ȫ:>g hAԳZL?R@D`͏F=[J]=/hnbpݻ?NIeJ\<|LtA-L#V<@r|!3U+SҶ#Sg4lxd ;֖:tx౧Sg@2YSG̑M4ј:>:w @gK3B׎=>2Cߝ:]=[/|ڐ pG-Iu NZL=l {\@s3(A=Qۑ:C2g ǢR'Mj|9=hTdr;OuNce66x X7dP6*@RݻMlRg4#@33(xSg-0$FejsR 33[~)u@CLp l0~`w57?~*Ό œ֔QRJtTg&Rg$WRO ;bP`6Dtv3!magFc+s ՌA`-̖_JS'2Dogl7:Luf"=pؐ QR=|!ubΗ#`PhVe6]E.w XuKq8{`TgΥ682=0:hAOK[@2(},Y-u-3*zݻ?uЂJ̏JTW ͠ @ݻ?w;V3#1uHd9wĨ з#@ -: Š @ ʗzǞNw6w)=g4$2ݏNZPmn:33Lp[ ~O#;uܶZ#1SQ9:`U`ݟ:hQR'$ePh6eZ}Qۑ:nK=[/|:GS2BߎȗzRg-h|9j%u@2Rg22-з3e8uܖSqp\>},Y-u3*ZhE]>},u@RCnA⡯N:3gFcC2cTһwE-/G=[JLW`[fPEl7j%=gl: zV׿_< *|Wj1[~)u@2];NeeZ@W`lzg Gu\-VуFeXU]5?>: |WOihr|!f'̑a'|ܴQVUPEe?: @0(vN:3gF碞R4Fe`5t\:hQ_1(4 2M{`(w;YƓU+q8{`d9M67SGRg".Xb%33ڱ'u-1(ФuP l).|,̹9Mg~|Ԩ   .>: |WOK=3>A&N?g s4CRg-:s.j%u@]>A&mߓ:"":3gGR'S3hr];^X;ʠ 4|'NQϖbH=z03RG:3:&ֽ @ z:`A&N7[>g h 6w)uM{`(uf/NXwȗzRg|*2MdwTg&b٧碞RzVGF=[J@6*HDW`OePIv `ʪ:>gt Ũ Tj1?~*u^ hteĮR'A͖O_>㣩S6t4 @MvI 4з#uLuf"ƞ}:.|.Y-uW9SGRgd]=Qۙ:hab%33U'P.uз3e8uH=[')(mCNt Emn:u.>?y$u t_{ވ_oDDįt^q-mZL^{0at{+dP:p(ulD\>},Y-u œEݻR$w?OK̹]Bߎ)Hl}=*u@mRL31?>+9|o=:)4b)8l)u V=`u_{hֱ/_w=7ym)lD OdPAv&u--ťbX-ԗ{M:Rjs67:ha SXooǗŦ9 FG@2(Р|ϝ* Z,٣:s.u w- cqo|5u ஈ&^I]ܖBt`忍?lz.C4 ˿of=`-A}p|aϿJ@ʪx?bԗS9,#V{`(u Rg-6w)ͯF[#u yyͿOgc+q˸ϛ{jgK0YN1eLog gRgТ.|,p%u 67RovNۮ kgŭqS ߺǺ~_x5x3] w"3>-u?kׁChAՙ{|XԳZV#Q:׽ 0[~)u Ř:o=\Ut_O*RO 1(@BߎzO>gt٣-uؓ:J̏Jp6٘G}\|kxt6u |B cPAv ,L̑a'lgL@wxX㣩C}?uƇ:o=\Ut_O0uhJ@ȪxG=`cH P9K3MnNu.5L,h GoG ZlDӱp:DGc~T TP`-:UtH u߈?z_l:>T|!u0(Xoglp \mR=z(.|.Y-u]<\.u#.Η- ;gSgܒ/uo >ΦNuؓ:gHlׁChr_>c>ՙsShxOAG`=ԳZ,/OK@+1uH PGS'l |:}\|kġvNeɗzb3hBl).|>=94-H@ڱ'uA榣6w)u7Rg|.7b-]n9lP]gX,N=?{O@L<W/NI\0];#_I@ 0Yb`X/GP >y9uƪw?ks؀3U+3""-uFm 'p[R\<|=z0E7p{^pԳ4 pgQt3}?5L.: k{^,HڟD[#u M:3L\0:&R_wLEShm:b~|4uԗ/Fog>/ߺt߈ťqIlwy4ͮ";uM-8{`d{#:s.f'Rg N6KFusgq6u Y@#1([0Y3G\x]J@JlȪt^'~u~#g9B ^,rBhnyv uk&;/Y?;pcwO}PvІ \p*jc߉StG/;Utc'cP{(]ݯegn*-ĝ8刈Y?~7$Wq-3Q.dgmf]v@3޽ d䡱Lg@:Pv)vdgm:sҡ5 Xb-.d'L6{v@3:r_Rv nRv NVs@[;# [ qKlw4nWcrgޟUh':;h3ͤczu!^yrNg@=z(r_v k`GvЦ*/ŭ>P8tΠ@vu_ʥhK;ƙ 뻻gG4۾M?hA|^]NP;{`tl36Ԩ/FM;s˶زBϸa]#;\v 䱸q/rװL1#Ѩ/fmĠ U* o3Xa?X̣nRv 4zu/@ (u9vҼ۸й~)%z7<;a]#vuOnoͰLDmtvFe4۾/;T.GS)ДN5#;hSW3 >h9ABw? =[6\={v@ Eﮑ VHez<&c?FnRE|b)K׎ggm7 Π9Ono-.wf'ugϏ36.;J=}u V<ƭҦ SOe@KyGXLz-'HqWxwӏ3hA_}97`|S?Ni[;dP Cѻk$;T7jsSTgN:hQL闲ܮW'3haߎnqg_i;6bP n<씶5#;h#e>X}\F}1Nf̎?-QyhAlG-[=Nwӏ>زBvJ[%2[GUg&'Eudv GE * g'mΠ :/}Qc2s6oǮWSZ^ֆAq{);kpCqhk)vN@v+ɱ#~q!3sRmGShsߎop;vd'm  ( Gﮑ Q_W8{Pv I-<4# c27wf? 23V ۾/;e͝<)?jl? ؑx4+Θ EuqGω쌖 X+egpt,J a~8qp_/.dQOggB; -灡ǍPh=[6\hI @0(RO_l/;e8u@:P4}=bv+#PGVCz_΀+\v?xvF2 2޽QڔUh#{x QSpv3'^]ndh&_zdz3Zg,`-bwHvW:3?yh,jsS+8{_5#; *SځfLf4vsRvF2q{ OljQeWC ǎ@ONfdhVߎ;zNdgXZ0(#E Q_S<,đLfgp;EP;Bv -`Phk Յ8qpN@:{Pvשk`{t325,dh7wƖ 3ZNyh8;hqe68:M|dQ;\ɨLfgpvd'TJvu -}wv mk`Glrvav8qp_4:̣ \'ǎ@NGjlrv͠ жnwovQ_S84R;ggp;EQN"c2]ݯf'Xj3(G 2@/GܗO<y Zv ξWѨ/fgpvd'DDDej<;rLxVAzb}ϩᇲ35POegpwg'DDđ0&\pv me_Ҧ "Q_ff_z: AܟQ.dgms׬k`Gv m<4{@Dĉ:s2;Xcz-fǟ8v25[:ŷn{8:׿k섖Q EXvQEmtv dQ_`g'# @1٥m -p'Z mQڝfǟWz-;HԨbv Ayh8; ""js^]]o}Ԙ moNhYebPhyh{ןy4;(ٗF}1;erIej<;h#΀58쌖eX-e_R/;m5q1?q$;(FOegL߁ X+ =c7 ;R<0CePhi:r_v@۪͝Emtv P@/=bv5#;NG/).oc쌖9 X e6ůGGiSv@[LQS,CyhwvTƳչ~)36&C[{na4;-VAeu =_hKljQe7Ѩ/fg bX On{8nNT*# m  -{f'ןy,N~(;hz0@qIBdg-Ę O/Vlh `PhIDyhwv@[ie828vߓJ1&o*# mo`PhI޻7;4q>?IBO<U2(Me֘~kgvF[42@:r_}m6w&?@NgM U*>~q!jsg3&fL>م섶cPXieQѱ QEBv b~ B_3?q$;hb_d=K7ƱHvF1(42@K/GGiSv@[x>Nz-;hOe'pC `PV/hvB[2(42@(Dz3<?LfgpJ=} Шע2=4-.W> (c섶Tڝ2@׳©|-X5gN*2ePXogg@aX3ο9;mu NZA%ϗ3ZZGSV93|pv1(,ǮWcWP(.f'52J2(ѱV.ĉ6w:;hOe'1J=} QEeڨ puU2xci[vF[3($2@}$C3ZVmLd53?q$Յ T6(Seʠ :/'3PUNh{edPhz޻7;eUg&}ѨײS63?q$;QN5eqGω(ʥq2|`XIeֿn_=X%̾t4\AzxZTWvKlvʱʝ k`Gv" M޻7;%͎??F)EfP(# @y.; cxv~4;VAim);:| ^ 8_e'pUF}1;(M뗲0gcrgv1 2@S(u֑3ZΩ|(ŅLfg:J] 25͝ P{ N`ҭҦ Ѩ/G gv>BT~); oqOEN/|);e4qྨ͝N5W3LGv(mRO_v M{f'c2@;tvԕ*S @A-]ޘ*6[;3;`Ph*5b~Hv}wvGLK۲ nv  Mept,;%rLQe|Fgg!JTF}1;(; qEUNZAiN~(;`js6w&;_5#;*/e'f'@cTRWv MQ*[df7;Tv);*SѨ/fgs Hb8 >NzXv@S;u19(pvUƳzva4;R9NAr_v@:u@Onz10@ulܔpE闲:~tycvvK۲3 ];&gP(RW eg4-c2@*;_(.w^vFJrv _/,WhLhIQ;8tQEez<;(Fͥ&*6*u lNA:J]u Ө/Ɖ-˿{K/;cU ?N5hvTNA~QڔT~9&S;j A>K⩟nvX k`Gv T/eg4c2@hk1?|v) רע:3^L3;VͱH,]`wà PH_zv@S1&K OUN 컯ʥ*[NxApJ=}ѿKM6w&?1Tƣ^]=e˝)^1ԌC&fP(/~=;iĉ~~*S k`GvǪ_\0J\KOO}è -o*# \Z2(J 1Fb~Hvظ);%>KЛ_΀1Θ~kgvסӗ4)2@z`L 6w:jsg3pvUΜNHdgu;V3;5#;hRe( Gyhwv@gG?B;H IDATh"IU.mc NZ cpt,;|Pe"|@h*i21*C3{v~4;PNAC~\1,KdvDЌ.oc;3Xr_t3&dP(ѱB3&*Se<4pU3'&cTfs2K;3X!];&dPHW šxޘ `9jsQ_Qs 20(N(ᇌ\A^ʴQlfR94!24w6ggM+^]}"?c`O1:֐ZWT `{s!j.$i"@],/hP5 ;k(ҽEe_Gօ`%+im#JDpp<~ F^Т-[)3^/pM;@# )1^6RIK>;컏`C31e1(ܳϥNU|#xIc2` !+^[?Otg:dBTgNz ;7;DxϷ Rtnlӿ^WoD!Nf}4z/&{3u Z=u=h??&2=9x\]u3=Nc/H厷jw9i7cKw'V"__>`w<j5V۟8qVcag?9ws>n.z͡xC_:{2|>܍A`?:`׬̿^LbDDƧu0Nc58)4|vsi{s3D;n.cщO j⎇;컏j?NcP zX6{D'vT@-7ZŸz@F*HL!+Fqt"" İ msvsy{x#4Rtnl|0h [CFVU.Na.7S'㲑JD#um ;R9:`W O)nƌTn1K?)o;Vc1"":y{TjD8 Nl}V|g-`Gb7S)5?3qH%uЅ )DuD /og@5S80=c,v)Ootn|k SA'=W~::>pePL};u7WS_P6dO ̧ 5߭BD|06sc#֊tvsH> ޳ys(}|Зoc+?:>.dPTC헟s4Rm: 8:YHieJdJD}xolN5:Z^g>0%2{px?@̾h|)|OVNO| 2;z:ul 4>e4T!9v\Ni7sc#J\ @[+Zqt".ϥ\\ʥ)|`Wkkl&m wUȊ1V?: Y%Ͻ:Z6H%JjQȊnvۃ3s[ 13VcOwދLBD T5(Ơ pW#u7=\N1H%R%u>kpX ͸Y:n.z޳oz(S33h5Rg]Ġ pWKyc7R ys(u}S']Ơ pGՙnzV'߈7^x2:y;u Rm7$+U"+U>؇?fl`p^Z bG{NXzGm5#__R/\ZI@h7e82'=:sY%]M] P6Qh5gWX@>q,u@*NNUƂW[~*_EꔁpΠjӾl3(&Dy@i7헟KhTjQp@(GD|Yp\ @:ob]n.NU7ٷǟa }FꜾS'粑JD#u- 9x۩Y'߈7` e#(զcn R%R @BS^;bG{Nkk?^[s#{+NA`[!+FoV|}5uրTjQȆS'64n.GZvsi/YɁ>]|@ym]߫\Jҷ.R'0.bP6vs3j,=sk<֐8:(O>j,FzL'o'=Av\,@?}xp轘)}gGRg0 Y1uE ۪3'S'ܓWbeb UdJiرRm*qbkyk5h5\ `Z[~*_EꔾcP (G"bkLƭ@/i7ꅧSgVmD NOdJd' o5oi5tNN@0 ͛C[O0|#uNxm:RȊ>"  ;7⍿d#(զ|n@$JO̴[#3h-o x$S {bG{N /O)N"  tGSg/<j ؑBVLVNO(9񱭿h7\22΍ Nގ^V#(4uJϻL1(bPS'/?^qtb{@TJKVDVDynd{RzHdP{7_:g]y/O)Nt 20಑W܋3 Y1JSQ<) [Ff~-E+` _OI }FꔞtgL*զ#b6u I#rs3`Hd`pid\i7XH rGSgZˋ͡x/)=gWǕJ*d @0(:s2ugqn DTgNF6)|VZmC3gOTZIo| ~^ǩSzʅAcV9l8ugzi H|ɣQ>R>Gfth7GfZˋՈZ zA|gxmG{3Qiꔞ㵵z X6R he`=:3]{).ϥ`ֈ̑zj)dQME6ۆfKZI@i7n{O o|'z/:t=uJ{mpYjP0(|Y:Sϥ`|tD<@H%+U:s""NlXi-/F'o  eW='1S3pщh5Rg5V?:Sux'Sgnj@o(զn;VL'ňc+ޏhP?jq|)]¿3uD63 :x۩>/?B ol8ʓ9j,62ƍjt(déSkk8rߛOSt^z΀(d @0(!:nve.Ͻ:>5 s4GSME6ql ;n.NǴK[?ăCWN "".`PLuCt@[qI@+NDum Z2@ߏ)/O۲J뫩3 ;z:u]“۩31H%ʓGcJ9@00M'0N Kڼ9O]~o=:%͛ u&+U 3(|`е~y\c#Μt+ni7`xgQ{NIG͡plH]dPXL;Z2^L@(NXLԣ Gf:m2P{D-}o7?My/돤΀OF\B Π l6E+ոϤbTgNӑ<B6z'qڕF0ZEeDăCWN7n߾h D 120 v;n IDATz'SgЅGQ<ՙS}t`Щ"oFky1ZX<=.vsa`אߏ@l<77Rb 120 Y1G3>헟vs)u]cΜTIR%3'FFj,l(*__M56o ̨̳oxgpW20GQȆSgܦXs/KjQ9uGǣ8:cָQUaTG?+?:>S!+PfPR'ܦo/<: Y1GqJ9{TRm*;|c{\Xp=@h5R't~Q㵵z ؑ*0 @+զ/<ToGH= p}SȆŅ}3.ߌ_b7Rܓ+?Ͼu>6oN{ @ΜLog3'H%g:s2 pSȆ:s"3'"n]y=.E:h-/FK]ݮP (4ugڼy .S疍Acc3]t뫩3cщdNN+(c碓oh5b\tv<VR'͛C|;OkWIwtGyB `3(} @7Y%.ϥ`jq(զRB6ՙ[#~g#Xz]vs)uWox^ `PO?(""bW߉+?:vEV2(̠ V헟KΜy xGs7b\]y=Zˋ۩N7u{Z=^[,W.W'C㵵z_Rqt9 (2Ї O:Ї tB6ՙQ9b]Vc`孕 Ơ wkX+G-|cO͛_w6_ R*d @"e< qYH!+1V?l8u;PMmh[2kAw2|_;D4"&{3~g}_|un3P#sB+ND:H BVz h5ڥC2!+Ub~:ꧣolˬ]NN]!__M@Z`w]yCQ9 |}5u'Ƨ|V Ƞ RmA@ Ltv >E6Rm*u }2|ck\vy.u|BVL@k5}$gP@ud`]{u 6],Oxx$ pTgNDuqzBqt"u=.__P63}fPz\!+FuD `@q풇 Q!+ơSgk||\X<:yk%u{ @ΜL N<~.g N;*dQGyq6bʜqCj}Z^8CT 2ƎN kF:ΜEVN{b\ t2Ji$vi6u(NġS*@_0.NގNl8u Rm:Z>2(=:s2u0^x:uQȊqΜH{¸ Ћ%#@ReG@^vs)uϹqvy.upbd ݦ4>B `U>RO vs9]M0J8t|GS@2e:F]+aWWS'Π z ЩQ9:F!̉Μ0.tvs)umJp 2ЃnݵWg=XL<~. pZY+};C @I vs9]rC ~+NġSTJ= XtOGZse`sd|P<5b]NN]dj@1 à t >vIud:u> -8|+h5Rg1وKv9|\6@tD]K2G>n.ǵK3z^!+ơS:s"u Ū3':s"j_wBVL7JV KΜt=~ =8:?gLرTI t| Rmt`Rwa`]{)Z=m~&z,uʓ(O֣oŸ>b뫩J6RIW'|k{ 2ХJ' {oĵK3zV!+o=k pOXt21V/Y:tnlNenRH2ХʓGS'}ꅧSgD1(]j @k5c\ T9>:l8c~:ZX+Sg2x:@F*ƫ`.Tp=^x:u@)d8t|TgNNT6T:u>V/%щ vs)J>W`PXL]{u(QOl8c~:ZX+SgTM7A|A NAB# @[qRgRm:'y >TjSqac΀('uvmщX<:ce˔R/?aE{p8x\ ϔ*q{+s2ѡ*NNϵ#A2ՙ>ve!"*d8t|TgNNgz'둷V/E#ß"N+B8MJ鈘M12E Y1ʓ@ϥ H%?x/$+UЩЩbe>bKNqt"u}p`.R9:S^|}5u@+N#}& p]U9ՙn.ceb꤮aP`wMvs٘=|KBZkfSgt9c2@_+᳏8x\d#I9@:76R'tNNeKd#7{헟K:>:`8x\|8|(զS'%QȊ즼:+ b`R[gR'}Xs3V!+o=zd3':s">b_LoN:+unlNV0x}K-#/ꅧS'tBVG1GwR<~.J=WJW:i7R'Ġ tRm:R? kκ.'f8::8x\|8|(զS'~[+ZWHDTgNNLZ믿:+j=l8u @׫Μ̉h7܋21uҮ*M:k O_JDS'}ڥYmAud<ݧܣx>x|8x\b/TNwͥ ]\NY:c0G2X컛vXL:X *qع8x\̿^WSg}.щ }sc#u@Ws)-J`Ī3'S'}ڥ ]':s"u@_Μ̉h5ڥh5R'ݓTn.NjBj^b` Y1ʓ@Y5c2{TGtոvi6V/Nߧ}:unlNx`})u o/?:kbeJd.gp:s{ʠ 脇T{!xWaL`p}tXfeb_*Nz݆d""F\xUiR%}|G2H%X0X:76R'vs)ʓ%A'#uOiC2o[X Yј waeXHS qݢ4>=)2O< Nd""^>Utc2ԧ ˌ= ur\J92OG.![֘LqtZ T c7*7Kun_[K?@Ô)@ L` TN7*O=*~a(塜 }9@:Fv4(+e` T既LJ)rtC;@=f|!:؁f#: s\N @e~)@"d}`fN} `Zk>/\Aʾ @"dRJϞ970sA{}-:o_NH AʼW"oB0HR;:f#:s\N Ye~ P2$RJ'Dtb`t>;( l7Z _jV0FZS cU_NH)TʩiGg}dP2|QI)Wߓ?{":` fN3Q{}-:>*W1(}T_Jlwt>:$(W~%:f#:`lR^[ƌA裼\cԇdRJie?RVN3hE'G*2G cHf?⳿yV}%:`lR^[&\:3>2(}RΥ,V!RZYDz3Cy31dPdXE/>Xt0 lD'RVN̠ Ie~):&NQdRJie?lj:=W32(_eQPE'}fP\KY>aGoT~sBlwG$n!2ym1:ޮlߜy.}q#oG+Iǟ=W?TFg֪D'C]((e @8ckd}kiꧢ/"Ǡ P6508$RJ'Dt@ߔrAt0ԪJym!:#e`*F'X!m_F+:>;J ` AءRtqI)Wߓ?{":o,=2`bjW3>1(;P;4 C2۾Vt@ߔs~?:nAv 1(;P_NB{Sߞ!R*?jt0Dd`0(rzSOʯ_N?+O}9+ ch0 9~0F T;1C2)t' kiΞN`JwNȠ 2oLnפl?Dgk cU_NƌAQey>$RJ;yz3C,~6u; (g>2(=/E'2$ }Ӟ3i5 )E`scHz[,}?0:`JY9=_+ ciP2Ѓ`Oګ;Þ ̠ @T既`$p[,ѿ:c\EgAKو{Jk XƋACt eH֞ӛV3vjWCeUN0>v&=o};24:`fS0ZgOE'Lf#:#eU既` ܙcg>^{#@V}%:`"FA:k@;P)-DgP='('?Nر=J Psɍ>1(w2C#[gH˽8՘Ny1:`Gչg XDg.OeO:Q8?\Nرrt0k "/E'P~ c2=*?ؑS^[F@\N&\>9#0. mksWQH~# ;RCEg#U_N(`LT_NG/>dtF!_ؑ=NY>VTt=2()-F'^ɦ},: L,NĠ ܆lj:0P>v&ؙBf鉿Xؑ>ҪD'LnLlj::2p*F'=oG'?xz 4s v.Zt=2(!]NG/};QX_bc iW&R`LPٷ' ugҫg63zV_Jy͈&\NĠ Beޘ MՑG'}9:1JtDv +e>1(Pw0:3~PH'ߜ́)˧3i5R{}-:`" A|v!:nGގN(rt@JY9w `ĴΞN` Ms)˧3`> t1:g{>zV}%:`uZ`•s @k 0p>vtB!ՋYt@JY9Yz$:Aebu6 JY9:2p`Dit@|8i5d0 (e3`P8|&ybt@OJY9Yz$:AJt3A1&_SO~г=Nlwt0&^Lru.:2!*F'l]+:0^9Oz'Ti#jWV 80("]Nֽ oE'lS) :` (WROGgЬ^P;y'^I)+=KDg#uTtɠ ebt /N(z1NٞR;:Q ,N @e~):[{ OzRi#و imD'.N @^[Nں+':c;態=sTvGg#yz9:w Oe~):B<9rYz$:aeƋAx!~0o}2ߜ́éFTs)+\۹LRVN Oe~):B=#ϟ; =c 3&0zk +Wg>0(ȦSOGg@盆ooFgda8M5O/G'geym1:B|0:aNГ=KD'#Π 1(ר/E'@˻w\_ϣzS:VTvOAF^[Np4E'Wߓ^=Г=NF\rt#\NvȠ \Klwtֽi茑oE'$N}KkN`rtCe]y7[F'fϞx9:'}G'#~6u6@{}-:(82𮼶#RjswtFLZ>DK @t˼#Ox7fNlwt06NN`D(:2Rg?m]+:#ĩtzFt@O|8:qV#׍nLru.:!2Rk 0r.Ji_Ut@O*K)˧3<Mvʠ +7]ơu茡fϞx9:'3G'`P``eS)˧3`$m]ޕ81TO =ɦSeL溝KU_` 0btg6wEg ןXNɞGh^N6F'2(3(7uyWNPtPrꙍ 8@sDtiG'\NvȠ /]Nơu茁;?/G'dTvGg#۹302Lru.ett˻w3j1:'3G'`L`2`(g6wEg =ɦS^[ z":ԪD'fPϺn] :c`_G'dKyz9:!0(Dk P(/4R󝻣3'ӏ~20&k^Π \Klwt7~+:zG'2|::(@K @`bU既^h.;wGgГʾ @tZ<hE'fP[ }s{қ.FgܱRVN31bP^h.;wGgyT既8y,:!2(Dk PxG^ ;v'y2:'3G'i5R{}-:; MMG';`P.D'@ὴ?^#NI65֚10 ZD';`P`,}K ;/ =;Ĺ姢22Lca޴zqotFOo}2zf#:'3G'^?: ̠ '-F'X9Ɨz ;:'t*Wg38y,:e8BtՋ{Žw쉿XNɞG0(Pl 0qbto|):|7/\Ie~):(rvT:A&N^[NzqoZ7:=y̓b*WROGg<@A&J^[Nu/E'ܖn 8@s)m<@2L|v!:ŽǭoU既h^N: 0QEvpK/zMM,7ڹ姢Nk#:((2LcNm>wEg`tPV#=``b4E'|85:1P `b 0~uoZ7:ㆾW)NltP ru.:2L_N[LوIe˩وO^4A&F^[NzqoZ7::Z峮g[k^No_N ʠ !-F'9Ɨ_NI)+ʾ `u;c2L|v!:&Ži茔RJ3=q=c2l3(Dk 0脔RJO]лʾ @[~*:aP`"^ܛ^>峮gkOf#:>kE'0(k 0ўi =yoz^s)˧3qXt VF';`PWE'D{vg_|';e nAcP.D';oŝ`*K 3&`x/mO[yOvOzš_L-?1(X+WR)oơ孡_*K kOf#:v.E'dPw=1An쉗zN~r=c X{}-:( 2ru.:x]vڹ p3Và 7dP.D'xqhx[C;@r*Wg3fLA˦AV65/`b޴zqϳғ<9 qLV 0hY>Ƞ c+-F'7B{gVw0:a'f#:ePUE'7Bs)5߹{xo .D'#liG'dPB{'yr`RVNY>NZ AR)+ru6:lرwPlBt0^{Ht#Π c\Nnb93}k nRj^``, -<\q~2 AÜ[~*u; FAƒ0`^ܛc~c S)+ru6:Q'E'PeK\tp8=;}=>㩳وKN IDAT`dS @ 0vչTvGg}=ѧ~ [>Ǣ`L dP۴uyWn+{ӛ}zn۹kV}嶎^_Kݷ/+dSӷۛ=60 U?u<2@/ 0vչߗAg_|5\0gSӾ}㑘Qv0 ͔؍Flutr0 j Ġ c']NKSS/8GYbdSөu0̵0y` uq;չTcRVn810(Và wĠ c.KJzBwHvl6RRzwKmf"u6ٸ~r[wM65+o;sN` 0VمiѠ̷^hkbs VTJAaQ]>28SNA@!t;cAƊ0֞]zo=j c1}R6hW<_wud1+=Prn)12yw}>^= W^[N`Dllm^>Lշ9rdS)gΔ53kPL'E'P@e+n z`O2?:W@m HJl^yUa[Jљm ׿wǯ>`r]; p<L(˻ҏ[s}_ƀ jMFj FrݿS:rb*ݵ;sS:C.^oD'0P0(~%Y^G2;y^`pdSnP(nј+yz2,3selWgr*Wg 8yePPʩ\5(ғ<9"ʦS)Z+1#2FtPp^_K}sL:!D'Ppe \t'/mOW[~>>i5ǜ}oD`X:l|gϕ9C3U?3(Xg>ٺ+>tyHEz`x:Fjrc^:$vWN]k{h&]HY><7疟N` `,s @2Gِj+gƖ`|L65չJvj ƀAB^[Nh߽o}2y>ʦ /dIlo؀a ƺKyz9+yz٫ YNJjWL65չ+C3FfD'0f Pxym!:6/N?wǞ] lj::`dl4WOާHƻ?24wjǢ33e(ru.:Ջ{?0(7Ok`(f#ml^a+#3Br#7sGCe(47_x{isu11Mq10^{Htcʠ fPK|Wk 0 gӹRrv9ZjRJ)rg- ^ոx͠ I0V/ݔRJ;yzL=JY9:` Ki䱴qXjEPN;?6U84q ۍ,`rȂf76,\6져^(Cmz?XݡAb"PpDS]ӎ r$WȐe~m !?d1Vlٲ83<k˱""n ˼cd /J(L'2V>:~9ϹSt4i6@W͕ț+g63Y @y@y\| ?/b KgKF:!noM6>­73@ɼoN`j @N3knIҋEh`;[s&6Ϟ3@yț+3re(j}6u'gf{?u˛yW00ŅNN` @H&P&ۯ,ǥsuJ 0AJXHaTR'|ͳDže;[SP R'0" PJlO|+ڭ]5 0 0~}`Z=5 @]yyܷ| D PJ.ёoNJVM 0ڭhq8ҭ]pG:bPR'S'}n0KpC2p3""1.L8t6>57}ePRr7Pk˩ZMys5.pʈ|僿Qd2sKQ Fw)v铩31e(^h6SSg "ߊOPlΙ<{&[L-=2cӥg P:e`t͕ =u ҅K/>b6vk=ڭ88vi$ P:e`t͕ )v S`[nǥgU63ǎGmf>d<|+6ϞI2(@鸃':gڈWhS^[券5?1ǎG>W 02J>:蓼:.-?OLEz\xTTq5!o:@Re(l|2u' )v铱yLuvl=saj@x 52J>:Nz 5R'CSO K@m-r?}2٨5bjDT3yyHΠ K ys%u@[_F:vk=ڭlTjL-z;: 5b7Ο>: P.l nmO)@uvl=gDD=,s<&斢%.-?9 O:FD\I3d`ѵk?5n -EVȷ Rg@DDT:n[3zƠ Mb7Kc2@͕ț+qɨgcjD QϤNp p QOA\IP?7J vkl|2&eGjl-{UϦN XMP ys5ڭ+vZNNC JWe`4͕ =զR'CJRk,'Zc>u K|`4d:Ů{mtߛ[饧 @uݸ©.e(Zc!uys%u@i;[3x">~OFhw1(@)T볩>7VS'FoN!迼gϤdPRƝ oN(bg+uP%bzdcs`?}2uܕAJZMX؍vk=u@iєO C2Х`j @͕ } p?8ⓩS`uݸ© 0 @NGx8% OFhePզR'}7WR' 1tT3S<{&u| 2 ڌ;nnHUo *dל?}2u#ZMA0,饧cjDT9{SgL%NJƠ /MNz,oNZc!?ǖRȷҋϥ{fPWϤNz,XM7S'bzi@$^SSg=3(@gS'}7WR'T6>y0$SRhe1(2 420jRq!:AS'bj))v;u|hehdT볱:1tT3StS)ک3 N:OehBڭ ]O1x"*Xj\Z~6u$>(/2 l|2ucjRgS'o[1ql)u %[`e520ڭTɪ`UjL-O9CNE:AV:vk=u@iU볩`$ 1x"L@^8:Š +w7Ovys%u@iUd)0*Y5O"9~铩 0 kS'Z>kzX1d.-?u6C XHP5(pHy@UjL-OEV3~ȷ Rg@W``eNafL 04jZ<SONxߎNN]aP実0Jҫ5R'@eoȜp\F^'V~CŠ P0 WƢXp|HS'bbn)&-N{Tⷎ^qM֘OAR6.0ڭ Cabnɠ ܃j}6O≨dcspNZDDL?kW~7^I\gPdP[:`(L-OTɪ#2L`u/wF à XHP:`hT[)00ORL[J 7[wc{{q:.<%0(@'S'=dPO`U1tL-E%K WwsߜGW*2 fPY\ILL `L[JVNN}O≘Z<pO:ŗkjFs5n\ҧ*.2 Zc!uczd=2x".-?:zUFd5֛ػQ׼?zU 0pqwa7WS' O`hUjL-z;:(Wwk:7/|U0<ˠ Ǡ 7z#MFys%u tͭ11l,uPb{x*E_O~؛(p:Oe8l\ ;ǟgDbF񡿯D5$Sɪ2(jSr5@L[l|2)T1x"&"M̵rJ뾾;Og?u à ZIHuq30J3!yHȈ {عcx8ӥ*-2 l 0ڭ C֘^[NbD距 /^CXce(Ym*uCys%uHWd9\%ҭcKs浫fkg~n]Wmn2 w/7WR' "LZc>>ߟa-ccjDT3sj9߹G8o]e }2(5R'=e[h&sv2.T\xT\sK11Yͅk@9~{7=^qOs2(p'neǟZc!^JV!J6: C__^iyFT볎0P 00 .VxN] Zc>>g&.p*.-?:DكZc>u}ܸ;_Noxw611ǎGmf>w`8\XN(b<6Nd Ne:葼:5sv2.T\zItQ>BfcR{;3}6vοG IDAT: 08j @[JH]p?S' b9ܧJV}{1.8u #̠  :``||N2I#Ucj3&S'$kq˩3cso4W+SP|3up 0*G=U:CZ|2ͳ37WR' JVBT3kW#t.uڻy=~kq{L#P^eBGPx7c[@YɛqSeĀ z9^E_O~:dPPɪ1n:Pjh6yL$RyL>|$R/,n3Y֖+S(17AʛS(@VdRħ83yLl=V,[#2&a^yJ+uƇ^:cP*Y5u#Ebb)v #Mǟ?gͳg #-|{8fր @ܼv5v.θ/{{QWN` j}6u#zUlE4RWt1dV\z~[?x|T볆h-~3rܸz%u #  eNaeP|3u@Oex_Ǿ~e9זcYO="ӘO0v.{7^:aP 2(pwV8ǖ/wۯk˩p|T병M_ڿx-q9uFWE_O~:qnR:82$WϦNzĠ FQ%'cjyLl=F``TwFkW#t.uFWU?xhm9n\:jS)کC0(@r:c wW䛩dc1TL/=Ejlbl-NFD6>ᘅg ":qK3h?9u CΠ ɹ+ :`6SO)vc{m9_y1Uwx @\Y_Nꌞt/N`' %|vk#DDljl1{b<Kz{'uFO[7q) )2$Uk,Nz7S' NN0&-ıx_"ߊț+o9  dcrZꌞ܌O:'=ܛNN0R;F,:Lֺp*Y`8&ZcFꌤߋ?/տS0j @I fPQ:4j3FR%Zco}ȷZ+BTME6>lTikWc˩3B+S0$ L6nLU:4F nj&c:2z͕[FcN~a-:So6~?-ǍWR0 LVJA{W䛩l,j5xo tvQ䛷`߷c*Y]@\Y_׮({7'&wR@D8Π d㓩 oF<&#Mj?ۭ[#3͕StI_ ww dc) Kz{'u`<}6vοQϦNFXn ANys5u@fzZxϱNLx/Ga"~5զ"|s3)^yZꌁ6lPƁePdT RlEuB0dcC3ǖkڭ(v7=FgU#C1(׮ŵsO>_)A}10\|3u@[Q?}08w~'Ӿ=qpF^'.{)uFigR'#9,P~e| WlEy `JuRX->o`+ t;<0:qKwH2:wORg0 wB tG:Jܼv5u{+"~G @+:E;uPț+=~IS'#:qV w'oNztpҹV ޡsz<: !2P~eJ6:NN0Tڭ p`ϣRg:'S'%gPrʛ+ "n\\K]|t2(@_e @;[J:浫dؑz4~>Gx&u Ơ }U92:2ݕ7WR'0n^Ͻ:ȑc#""MӉJVM8@ @f7WS'0nuRxV>vg ePC+vR' Nl`,D#w|0h WçȍB\Is/ލ"u w1ɹsKOG%^8,20|2nGM=&s)G#+XLEJ>:an2 }ONZO0JFĕc27O~nzi7PdA*a)کrF_G<.V>T%`@7Pڭ C+oN`Ƚ~V +s{饧#wgS'C }Skݲr\M0( )c2ȑ?T8a)ک.0([rP~17ɹ{l|ECX`9'AZM􀻑V\Iٽh>RG>~8v~r ewNnmNzk˩"W~;Rg>֣O~Џ3dd](l 7:NN0_1*|9p=mGӮ=զR'#sm7uej}6ueVfP1&3xg+]{̩'d kS']`PV䛩FB\I@|mS]LAZMtY:`$;[nmɔ'?9pO{zd՞<6ݗONAN̠ @lbJc2%0ɹ8R{g_bS={|+ @9p ?k˩(׮ƕ|>RG>^z:*Y@[.0(@_ pڭ(kWb:GO~/UbS}y.n1(}Fr1rȑ6}}饧UaP'S']nN9ex?d#GG>o%>'NX`VK e/oDM2&S&sonv 鹝W3:fk?N Qr%;`(/6A(W':90t*`<* |b}-n_1ۼ\ИL1} C4=;  D<4]x{w֍~+;ǴmlЌDD:p4C\ݓ͍ }u.Zvqd̶{쌮sb h72tTuPvfź^:.;qױUc2}1RvJREc5;h#2<2͠ @i~XjvO`d""ՉuhvШԦ cPHeg~h ~=;`(ʕ`*͚a3 CV|/ww)<c2]Fy|";`9c􂢱A:S`fvX@[qEc2}ƘW9zv]P;gƠ Cfܺq1mN ze::u(;@eRQc}u.ZFvPy7>1>32Z2&D:x4;+ײ63(@GUjS @fvU4cu\vl܊[7.ƃ1GuVNAP+sƝ_ǝdc2vd=r%;'`P֬/d'X7;`5VnW3xBd̞ïg' Jm:;  1ti~+>W)&32ZN{?JJvpOzAhf'`PΟVZmƭc7Sx d:g RNA:n*2w:;ۼ\0mN),2S*oN XZvmh=kίcڇ~+;`Lv8 m@'eAh X_)]^N{r%; ""Z^LȠ 7@oZyL >~+,\'N)=_N{թC Ѭ/d'`PԦ+s3z½ͻqͭ tY6   [HgUldgubۼSzng-vNIk }:9Ec5;2w;^aPArgheg݃_DcFv [dLw:Zv@1(f}!;2tD6X>?V6֍;`d;f=_N;fP(mNڬhf'Aheg'>{wS؂R$ƪST'3J\NbYTex, ??e/ƭ_^[)lc2vdvx-;T'e'Ds0 X+OVY/fEv3{1(|alvy7֮}OT'3Bur&; @#<O˱:nvc۸ubNa>-ex< 0(#5 t{b#;=ߊO?E|5oeEāW]f'Jm:; ""ZvAexVNX;P6ƭww)s;k}dgER= /CePDƭubۼB<_2&3@Sz^y|";eh͸yDv4Vnĝ~+;6w0MegFƷXtA:Co:.KW3f]0*;6-Ωؾl =Td'C  Te'dlv06kƽͻ)h)v?c)t@=*  `jvIKcu `H5Vnĝ~+;66#v?vdA{г _0(͠ n=b#;"6cڇW)1QNYe^* @Qh `Hl6n'>{wShvGbdBTjSRNBtAΡ 2w: `hxpB<;g Lv@O*Wd'C  m7`~Xv0Vߍ BTo{%;NITv@D 0(#k f}!VdgUlSc*~bfg#w0*/BLv@)Od'|U43(#sgUldgY_ d%U#ؽHlRv JFeruOv gPxlOܙΛ?gFF\Vlmc;SN)թC _( @sq\vЧZF\:v<{_KUl1Lv@O)+ 1(@ە'谛gODks7t?cdđ^ZLx5FFK)JmxԦXt+AW Oy~D㙑΄eצ^ΠG:x4;gɠ TVNGco֬/ƥobUlh)kS)Lv@O(+Q*oBtA]?u,ZFvУVąw##>R$|);W:*/ioVy9=#LuPv@Lv: [ vtv]V IcJ\x͸}u_/w0{ggЧ(D'Ь/d']`P++ $X;+@yq[QuwZ<&-āWcΗScv/'^jP.2@\?u,ZFvb\:V̝)muɶWc؎@ur&; { k^ 6Z<{";f;oFr~R= YDٱDuPv@Dv0 m:.nA f}1.X>?x&;b=_o{%FFK) Lv@2@ˠ v~۟G?Ik9]u섮-?;צS*pzMtACpWhG?Iv 37չ^ Ɏmc;Ʒvg7*Gy|";㪓?0L iKٟfg@iɷ*9s⹝8jNRN(Y@/j.*emetTjӱS-7g3zFD?gth)^ػ?|);H6Qa6#Of}1;VcJ|p c2_>w*;#/]uPvW4 @z¥oE*6⣿I\:Vk9=Y_g#칝ؽHlۑO:ihlle*Fe ̝e|o6;mo{%FFK)%AVNҕ =Y_gOdg@Okɷ*9}X?%ϖc}K)eAVMe'|`z(Ow)b#씾Oۧ7;ƿJ:0( LvW4 @yQ==&z=yBսveAUNFveetԱԦRN4Ec-x4.g ܩser욞mc;S#:`ЋFɷY_kl|p c2mԬ/3a1q/0.Ƚ EtAgf\?u,ZFv tksq7clv@ϝNxRT312Z΁+Od']uPvW4 @zZNeT׬/ƥoG?Ik9Y_g#ƶ{rv tM6V^ '2@kb#ni\xh,] w~w _Z$NNd',5 @Rv4=;:.""÷K}VߍgODhf OgmoK-Wb;^Ћ Aq:iu\TjӱS`KKWbl4.g ,CTy툝ӇXZd+G\1 LvW A<{"JJ9xbb#n=S+Ou~6צ~]Eڴq-``x!Ћ A\?u,"¨ }eXyLfv ']h)vNķvw <> 0(ɠ З:NNot\<{wz?_;~vw^QGUj mQNZEc5;Hiз>O{?:Tv |E7Ϟȷw#x6_5'ڢ:eMF`8df}!;H2 ʴ7b1wXo؎81h@?++QNdg|EXNV{#PcJ\:v\?u,u?^ FJ۾T^|9&vt Cur&;Tj _Y0J*q[ŸyD4.gZ*ʿ>[o{%c< _y|"b)Ue'|-20F:Qf}1;V4q7 W1q/@'J6jv |GǣRX>?+sSz=FFF12ZS3d 2:9 Hv^2bv =Ul{7%͕/^{.)+ O<> N`|>*:nv Vވ*9_3ŸiS`hT'e'<1/gzYcrv`贊f\?u,""~r ݴ:n,7Qen_tY\12@j @222*0< VR VNZBv̠ 0Ԯ:@4ͳ''XEc-Չ ORNZF2[?aT`4h,]Nn IDATݾ:{ ;F6eg8F4)Ct%.|;.|˘ n_VCRNx$*5d'= TN*q7cueH^u\vQzVNz@);Re'@]?u,K?|+;``4Y#2s031Ptv7j`P2(X?B|GǣTޞз /n_av͠ ˚GxJB|pޏG6WVߍK+ ߨ:9P2<py3÷cgwS'|AZu3,~ߥX߾qbЋ_΀m5#+~MI7 p#y A/uQ^1:`ni\tbrMsY9_Y|gR+%bP`y~_xI0SݸxWlrU1v6L>HI8uD ٴ*?γxeR']Rac>u X[ngb:X"e{Š_QoiuݣxטVeH ղz>蟦NAnڍbK+?u> p#:6J9<їa9 iU΁R wS'|V1NAnāxXiUw/Y7#˛2yݍWuGįSgZw} B>HIU1N,!2Kxx*uĦUN{ե$0o׃2v=HIbP`L2{MLκſYL,r؏QNSF1(-oNbK,!2Xp<$V z?=G_>Gz:Hlt?1:9viVeT+zk7ugU 2(ղz_ELκoN`bVexեA}/Rg.OYe1(̕þl<߿G_>gQNh㘜uS(.ɶFP z%dPDX_V3b}p LUctrco%US'sR'|VUxf|An,5XV8篣׉/~eR'P N{n3=z2(%1(F&g[ya㘜uSwTf X+i)e[M_`2XbЋaYƠ 8~SF8&g) ^VE1NAn,vUXUӪOoeꭝI1bׯ1 ;W5gP5X_YnPV]1w}4~G-{: ҴY7F' Nf$j8WbP`Ncr֍G_>R(ӪL,HUR'Zeu_OnĐ5)ezkכV`ML2{M\t!~$XIU1Y7.G ʿ0֮ VVjY=u0c8#oudy3uuSKISc|X eO1(@DD^Oci7Z u,r؏QLκ19glitXŠ:Xbe|g`͍Ncr֍OgexU1Y7.G |T9<:}:FsJ 0sR'41:9G>u$XiunL^Y7uU:^'u 3(y8 뭖S' T]S\t◿7&C2g]T .oNg1([y_G>G_>7,Z)+V[A 1(|Anxf$##LL2upy uy |AnM,qN Rof͟+ 799eZ uD ތL^Y7up V3by u~``U:ZV5x8&gxxyf&198u Aa?ꭝ6-bϵQS'+ 35zk7A/udU".^հ Iu "IVS:ƪb:Xe)2,R18ɱA+`P[wRgKΰ R#2_Eu9NV1EOܒ*)`PzwXfi<|Udy3u+ƈ 0NVW1 0([4ʸE(ƣ/R'X9gQތL^Y7uܕ -4:nS'+Ġ sQ]#ک+UW]o_ūFc|YL'T8&gVVkX)aPQ`(VeNctrN<<: )G1}:Vnà +er֍Y7f<Fc- L^__V zQ]SJc:Vi`N"uq/zl>O,oX[z(1IK*>e3nNVAVڴ*{ݣhua癋3RQ z1:9vYK20+E4uϐ2|bPp_:g&gݘu#jγ>|A,2yݍׯ}:Vnˠ s1*u0g.fˬw/^~ۇOaY[;RULκs殱Ip+Š:X1ezkכO7:9q[,{x+19F1yllYLp+eP;e 7VS^֣׉çSg,DU(1II4?Ipk8ub 0U1J,@Š:VUGՌg}4jكi3U Ncr֍bZw 3^ 0`3~5ڪq|7h<)1IK3`` 2(탈x:`&&gݘu#jFxf,VWoc&_ƞ1` 2(.q=Q[}4F-{: a?&_E?bK^\4`  s3\5@<y|7h<[`qbn^ӘVe$0k=wS]S'+Ƞ sS]2nԲq>YVW? z. NHՌ,obK 2K>k`L2F'1:9lObi[;4cQ z.MI VeP{Adq\t{V3So>k@` 2pWeiUNڍY7u@r8E|틨vci4:e(Q zQ`jY=;3n͠ pWerx|;u)o⻗ d@`;Ġ pWel˥hOиL>zk'u0#dfoZ]NH w3pWezk7ux3.q=x$2jY=urx:X#~[+ 3(T ԲVRu9Q\tގ;xÌ̛C\f [<2̍Ay۸qZV^'A4:`bv<`5x*FfP{%gYVeNctrx;,x.A18rx~= ?iUN`N:Xaezk7&gk⻗DՌ'DO+gZ]E1]OR'YȶQorx:Xae`sdvP]{ݣewI;ytaA/q$nI`A;M^ poٖ6ʘucr֍zk7A4:Mc^'uˠ VoNxMpg>bPvcrM* wߎdy3Q2euCJ3(̊Aʁt,nVFf \(1(QcÕ`~X ӪL^'ufŠ 3۩Xɶ Բ ҩqT(?ZNq+23̊AfI*m5#˷#ُzk7|ZVWocbx aeU NS'kĠ sW N#ou .Q]zk7f[fUpͣ|;ur:XA=c2js%2Tm*Qcr}w8 IDAT:4Sꆐ*VۑӪXLk py u0KeiUN]Xɶ \)?X^'ufɠ sWϣ`S\E r8AgڍZV|g?jY lbpa0zk7u(ju=Hp/> dPʶ\`}9zk7jxL{љ~LzT7";̆GN7#bPp:X,7(fD>uz`LanՏ0?tI lnڍ,5Xm5y0(moeG{3H[QŃ~Q7 >37>41sM-NEml>Mpoey0(BS`d[M~` Mg#$%(O}h]V3 |עfӴ*$X}(?_nIpoE4u 0֮|h=ŵִ*S'+ڍ,12͋ n`38ǛX$y{?urx:XۇOS'[9N֔Aa<e^'u^`M`. )AX 4u"f {V`^ tfԲz 3=0/eXW 0w~X Š:XN{VWe1(BL2ulZVOڍ,o7c2<`!<ToN<f蟦NV 3Q z5fP 0wV3ul^'uLɠ SvR'eAbK,}.6y``aU:H oNvS'ZVW}4uLþ\`a< =묖S'Z(N y3(x ɠ ,Okiu=H0Š:Xse+Xg:ւx$u ̛A蟦Nzk7ur:XrNVWe3(9L fà )NԲ3fR' cE6W:f]nq'f` 0ӪL$#Ͽav+>cש3f蟦N6A*Ʃ`y Q \>I0SŠ:eXҠ l,oFL37̆$I9N6AjZDu7FUR'Kգؠ >A/u! PgLX/eE1(B 03V3jكq`I=M0S*y ``U:H$˛Q3^ 6 NbKl2,@ p/e`v\~׉,orx:0eXNrUg<f*'f蟦N6At6Y>Hb<fjY={3W z cPs6[VVW-G7SgZp^'jك3U NS'Ƞ W @by uI:F9) o͖R'x Q NS'KᓯR'\9Ǵ*SgȠ IVx++'jF-{:ւ#f + 2(@U1J$fPUR'(%,u\R1(@28t1cPxWc:`.i`C 2@:nX:N1NӨeRg\9Ǵ*Sgʠ IT(uX7#jevRgZ /"~Nrx:`eHt0&WVG:ֆKV3 R'̠ x`PUQoNaPxI1(dPdK2Ua$f蟦N'_N;/$ePdm fd[YyH:̊3#@X[y1 i iUN7<ˆ٩3#@DDl>M07Š:peHۦX~~X΋N 1(fPd?\NC,;0;E4u{eRgEU6ADDdy3f mfNγ scHXeHjZ]N7<Æ" jF:`n|A) a|Wc:F9Nγ sePXeHjZ%0>(:̎ۇOS'MU0(@Z A[3=N XŠ:HliԲ3蟦N2$f}gaJ߅#Ņ#Y#HD)V% a](v};zziwjb R‘N-}ffOۿʝ`|oߜ @t6V<t7 seH( 22(([ P  4\Kez3(ABQc0;*W0(@i1NJ-ʕ H)-REg@m A0(@|9/ RJ{VtԊ+ٺCCm@Ġ $:(Vt\YN; sgP(2soH)f 499v4X ^Sq>2sw% A; sE'A~@?G @ 2@y3e*ܤ@0:jŠ 4WwsN/:`1(@i1I":(Vje *[yfǩ8GgAi12mtP"{VtJ~|ɖ{{}0w0:DTgFt ;̒C0(AJOq>ZY;uַ3VNJ~#:1( NtBy P N~M,s(:-Rg}+:`!|ʠ QDܴ"u7-Eg@ p7:`a|ʠ QO+[2*tߊNZir6:XVNNtB䣣dPҰRgc+:nVVg~AJ8G'%4X0{Qt`u0423(@i~ZY;:3pJh^وXiq&'o3~AJut7 \gc+:jvƈ&Pve(i1I":(jr%e^tJ~|,X+k`;:`a|Π t*j?؉NG ޺Pgo^E'.2AZR߈ 14ISq>]e(i1NJCgF: ɱ+a@G Ƞ :k:7`':j'F' h7AJOjllىvVwscPr%uַ3!@TqtPR뷢0 VBwjrr$:tpcf/ySPgo^E'\AJ8G'%Խ>L@Mt7 P;gZu/:`c`P):[ @ZRtN>:N?؉NXiq{Pe(o^@ t7 P;"MNFg 줬ӋX(c2@t4:()7ZY;u vz?:X`':` TAJ8G'%ʖR{Jt iür|t,H{JoEg,ٛW fPRG_;9Lz<]t` H|ޏNg)DE>vp*P)e(ˢ\E/_VRJ?6*-R{e#:jgrr$:Xl ˏ TAJz;[N/e˽ Ƌ@wNvByA PJ @uߊN޿Ww2P]6$ ||t,q6bPR2(ޱ{iZ\3*Ӌ΀):N(e(-?bPEyR?gTgueP/[`;: =@U&' @uS+kGg)]g@yqrq `0UfPR+<{?l? XwsZRt^t0gVa޼Nhe( ʰ(0壣K|{e#|Ԩ <̏+l@ǗWl Pj.{}hyQ^+PKE>N8:[L3>AJO nh|t&'g@nt`uzaUgPR+iZ\Dg%gPEzQXVv`/:3l@Π 79y\P sz|Ψ ,NwsZRtR5Y+ UgPspNe޽|QΨ ,ڝ P[9 48MIt'1(@.à tz|Q֨ WgF: Ӄ`^oEg:{*:{Phg=*^2" ";jnpg>AJ/F'F' {?~Ш ^KvtV~|̑QŅ!M P  ʰh^>?ʖ ; Pkgo^E'svat@ 3aPJ\F0vt rz|IaTfgu5-.:k?̗*ջK?@;-Eg@E'svAt@iƠ 1-&@Ed^j\Π޽|>/xHYP gocPJq!(|t46*ǃ0g=T ue G IDATԑA*Š ! o_L=* < toVt@i3(@G @Fg@໹~0|Ԩ -<s699N8:lw P) @tߊN}~{eè vat^t0F~ͫ0(@LI*r 7Qws}24QKvtԞ*l)|Ԩ ڮE'svAt@G scPqP핍-3hIbcT&Xu/ e˽Yߊ(7Ơ 39yTP@CMIg y;u:܍N;=.MIt0ckF'ʴ0 ԚA*gZLR31AӃ-k<VwUt0cr/ʠ 49yTL o-P7kwD'@Mtz?:Jw PIea\HgS>:Z{^8]d 줬Ӌ΀;=؋Nf,[`;:t ugPJʏ .Pvje  `ۨ vAt4AJgrr$:` PI @Eu7 4X>:L-}=*cP *vREg@MNݏ5-RP:4&0(@%MIGg:܍N}GOP9kwD'@#xgR:{*:` PYN>F{e#eN%Nq>N 2TJke^^3Jǩ8Gg̝A*ˠ V 4Wߤiq핍{+WB>ڝ goӴDg3vat@)ޏNX2TAc; 4ܴ}Yn>zjTRvREg@#E'3-RPJMaPG @E%2;=KE>{Vn>zð=kwD'@#8ޏfhR*CM0(@壣hP?i_4@;)3@d˽lGgR~s9 Piս>LٲK1x:܍X :`n?N(7Ơ fPNt*:!ջK?줬c!|HgF3JiZ\ cPJG @ qz茔RJQBvz hӃ`P#kw| gPG @,a:=.:gZR0WkF'@HgFoEgA P ²N/u7RJoiq_lTh\Ivt4ƴ0%ڝ 699Nbpe ePbRړa@\Et4}SBM;Pj{ ! P 0:aʖ{RJ?N?I@ toxNfd΃;{*: Aj 0 Nt|tS2|k~Rq^As;)80LN}ˠ PӴ*nuٛ^H7=M+)Tp׃`{ yPzMfPG @ŵDgR'caŅ)&lpUt@2mtPe(|￈]l)|d΃ʖ3Q~VNW~PzT36:[)[vT徹-kR^Zދ΀9=؋Nf`=lB6\fe4:R@ɹwf?/X+knt@%Π 299Nj9Lwl!~Uws:[8_}{-Eg^mt@(2J>:Nj-`':~oiqq)tS2L+kw΀))^Z :^G'3(@ [g${<:+OOʕJbֽuz8U *`/: Ajer6:K3_qtƥtF,[3qE:{|l J({Aj8"Gg5z^t*:ჴ_LNt tz$:D>G.Ϩ&v&ׇ)[EgLNަDg|kYߊ΀Fz":D>G>^t@)vatP#/^>OE>`v_V֎N`AZY;]Et4ٛTWZ2skwD'TFmt@)v#0K JgZLҏ>(tSW z^: hN>Qws:[qz?:4 P;iZ\Dg5ʖRws~:{S͛`+OOʕ樽r%~T㔏3Ot rzPe%7Evӏ>b+[J7=5Pc8^>N>QN/:2|&'o3Jà E'5uzF/(|\ZR/_nt 3:M hiqN3Oچ>R1(@-Yfe~EGg|wd˽vAt4 'Zu/ J1 se|tLg}+e˽ U?|Ut')|w<zd=]|"; P[(:WMNަw?d핍t^GnS0:4-&'X0:{P:e|tLZY;:~Wߤ"Gg|toDZY;]$:N>A{J3*`/:t P[QtPCE'?FgD+[J7}>??Nl):+dW~P9E>NcPG @ w7tz]t\؉at4ڻϣOY:[sz?: Pk(:V M?~,M茙GOS+kGZY00;x*ڟG'T^t@),ڝ $W3YJ7=M+)k~ZRt4 'vREgTNmt@)0Y:737Ogo3fn>z~9L@"Ӄ #vz J:{]cfɠ E'5vAt4M茙jeK鳿|V)= hN>{-EgTqMfPZ499j+W37MIzyt\\7*??< ˖{i,>Fmt@iatPS]_|t1vZY;:Խ>΀{"MIt":^G'AjϠ 0/vʖ{~4-.3梽yj\NhVN?΀ƛo3Ya E'Aj/?>Njlu8w/GgM+[J7=MNt @c|/S+[΀;{$:HW~PYE>NfPڛ499j?I;ʖҵx YߊRJGt^وӃ3(@#ZRZu/:_Et\拏yʕvAtR:=. #|OdP :܍N?Tӻϣ3殳n>z+WSj'-Eg)w#:H<c`PFȏkeK?؉΀?~EGq{e#|4u7)qN$TTKkDgT^t@%$MN3[OᇯJ":cZR/_:/t wUt@%1atPcY C8{<:can?H)鳿~|t&'o3Yׇ699N8: ey[F'QttGOS{Jt @kw):_M wzPeh91+~#:.凯J":ca+棧OZVtёtV)3*Ϡ 1$#2|yRwm+[JK^[tM um`i1 24yo /9vA_V֎N(VN 'ё{" ;{P)ehyA䇯J":cׇ棧r%:tq: '޽||ʕlGgԂAcPFqZ-{؂j(oEghl0:4V{(|t~wN7iZL3*Š X0:.`/i)Nl)}/ Rj\IW-:w/G'?I Z8=؋N24SES܋΀KOӴ:n>zZY;: D+kFgfdZ\<( Sq(kF'MI믢3BuַYj\NXejeK/{<:kw\~|24m@)[EgOEg:ߟ`':`a?NirrQ l)}/ջ_Ft+ёrP 8MNFgTA+?>Ndֽ`?|UvA詁(V?؎~ûϣat@Mt@,p39y_o߳^Qtߢ3pf P1P;go^E'TA X"z^t|/R>:(KYZF|CyZRt@LNSq>424Vq>N{}*$DR~x,$TV`ڱ{@UHV.ćƺI.d. av'P;MBv!D4ej3R-RXh6碙݉lٖY?ya/~OyF F!Sg}TT+3jΞ#/cS_u18>wa0 uo$zlgΦN{ehj&RvD(T+z5c_1FOG=:t2]|NӞ#'R'43AA`F!Sg}[<gMQ=>]cS|=GNDǾb .g/Dee)upzMkWfZ){ehjVvDϥ΀rQ^:&18~2'F5kp& ZYkNC'Rg4A^i~.udzG NPr\=zꌚ5L{ u @=ܞ9J9up'S'4jeՁĠ MM`Oqܛ3jZǧkpT ոứ35v8Sg4$ul24 @=8Y{g x gM!'cp|2 Y:h2,wS{=s6r ` Y{HаnϜM0 ףZYM4ރ?Iꯧ}ހgbtS&#SgP)-NNl"Rhe "/ϤNP3w΀R[S3Bǧkp O:aLK[Ht+hXS'42&{'/lG (dyAgRgP)-yYH!cG'Sg44Hˠ D @{&nw: 7RgԍgbtS5v8zN6ꯧS'Ddml\TVRg42JK@2:ʥjꌺw IDAT;:hC?:ؠ\/6(s3 Ǡ |Z@*]cDDCWee)y=uF])d;bpd OF!Su,}vT>; /ϤNh8eKnD)Ix(˗g̻3N31z|:)@ʻbtS Z3 )?u@C[J9u@1(_*_je5uФƞPnw: 7Rgԝ?t*zGSu18>iLH73 ;D | ɠ |Eiby zW 5>=G^ǦSW=>yw>ܞ9nzR,_IА W!7m}#3ࡔǵsRgԭ}8|wؔ13ju o8u@61(_Q:hr&R'C[=Rgԭ3FZ^p:tܩVʩ3 (dy Oh gΦNhXe+*+KQ^:hbm}7:ڵs|~H'btd흩S18>]cϤSyF,ΞOlP(d;Rg4,hXe//NNNVףZYMRKoFP1u ؞#'@vT`F\ p{lfP @:kp xh^lGT9r" Y:Hk찗ۡN-_q ?lll-2JZYM4C`S,Ξ 3BO=>y@`uq/C2 Ddm3셨Vʩ3ANR:x4ulkNEyFꌆwǁN|&aLOGee)uY{gtvYagP {h" Y:ZRg^je5uJs=>31oj ONhҒgA툞Kp=;: Sc:dCEc2P箝;J9u=ţ7:iekTVp#u@F!SgX=gȻ َs hy@ OByF,ΞOl@!ˣD r{l`PQ: َsD 4Ν2޸zȻR!QvNµsR'4l,h e`N jE3w΀Ms_F:qSNR:eL@*FǾb r{laPQ^%Wf9r"ulR\zk*uF=8ǧ Q@1&ZYkN6lje5/Ϥhe.ܴjEǾb΀MS7?:a ǁތéS{0&٨Vʩ3 =4Yav|y562(wQ:zMNMuӱ|ňV)d;bpd?6,O| c28*my@KtgϧNh*e./{m}1TLꯧRZJ:7: c2Xz:uA㓩NOmfPZ)Gi~.u9r"uljޚje5uJC+d;bȉ(dyhzd,_b$ԉȻSg4:{X<:ϲ)Mp=;:)ӑwNeLKMy@HД|:{p5&3`S-Ξ 3B^:yH 43g:B ,_qARTJnb툞Kףp#uF=8^z3)F@)/܈Nl@ȻSg4A؀37'"kL_je5uFȻctN5v8FnL̵sR'1TR< A72Z{'`U+W'Sg4B#y1FO-5v8fqB/18>:iy 2Qt=m}#3`ӕǵsoh:m}q7x4u 4 c2ИոvT `B#u@Ӻ=s6u@2(d!E&R'=s6g/h:lG9bBfL׵sZ)x4Sg4\TVRg4-2A;:ĵsp#uFSj&OGP1u ԥ=GNU3{ȻbϑSg45Ni Z<:kB΀MWۿje5uJS*d;bb)1p'\ `\;w*up,MZY5(AؠjW'k댞Bc,ǿrwJ*N78>]cϤOGyz zMDݟ:9 =2pJ7R'|;Sg(/\gSg4B#x*BSlʘ 4Ji)nw:upC): 3gS'4=2p|:k{'3`,Ξ 3^Ǿb<5y::SfȮ5ԺBd W^3A(/HƞeyPvOcSQ9Tǧ#Ol Q:?n#u@ӻ=s6uaPZ{h"ulu2DDǾb<5y::@sʻKoWƵsRgS<m}é3^˗gRge-ΞO;:LR6*SC َ/O}SɻbtS-vQSgwwĞ#/ "/ϸe>G:`]& ; ם\c:1TL[kpx1hWfbL 'S'3gS'oܹs*uԛ+ݽ/u*dy_kQK[p=m}#SRK5~DibT+`C `T+q)sAs䄱sQ^7?:/zT:zNDޙ:Nך8қS<:6d9b `|tTVRgw7=Rg3gS'e,_q P'S'(/H_(d;bϑcq+^!c{&u MJs^ j,_v(@-1(Mֵ G[H RJ9.K5o8fNR=>SmR3aG'HtXg9u_aPS'NN-WYYz*d;bϑKoF=:6,&OGݟ:F7;]{1gΦN/T1:=4:\yz\=3:ȻK|&P:1z|: َ)6*y j\@)/܈2r,_IpO=ţw΀-8{>nϼ:{=8OM)zGc@z =FÜ;wJCwRh+> u l>('vN. Y]cWy|~jܩN'| Z{h"~ ZY jPKg&EǾb΀mqQ^: )>OM6 @r,5L ]{p"uaLT+| 2r,_1*ԇ=GNNmQ_je5u PvOcSw qOE[p je5.]<J׸=s6u0(tc.uS<:Qӱ^z۪cǧ#k3r {:=GN[ PJsQ^:u| {h" Y:Eyz\;w*u=G^ӑw?B#u Hi~.nϜMEP1ƞIX=:Ν;RG@=VVchٞ:Z ӹR(/\je5v=:w}6q: R_DO)@Bj/G:XG?h)N/T+qRgp-XIǾb΀ms{l,^H=8,6Mǧk)@b7;] OF!ۑ:igP6S'ܗLף4?:uc;SPFKoFݟ:H4?gΦx4SgT;wJZYug{ )dy7MeL#펮ĝ緮 /GK5u Xo"TRȻbO#ZR@X=:Fޙ:MRKo2):=s6u`P6S'ܗ? 3H۪Q:wǁNŞ#'sQy@})@X2˗gRgw{h"RZr]P' &,EyF ұC^3`&OG)Ԙ1z| UJKqө3*FO l7w9:EK5v=:HۮZY>(h)a<~Di :ȉpZY5wkSutC3؀Og|Rgp X+}6uyQJi)u lJ|~jtN;x4^*#Y{g*Njܿ_,J#^1P'.=:Ԓ:Qy6QDib\=3:-{p"JIH5:?V^I_(dy/?BkƕnĥRgw\?J0([[S<:={_,_1@*/\+)l3wEi~.TR'y@|:SuZYdT+Sut cϑ3ؠJi)~7Rg VVchٞ:={(5u$|eƨLɻ≿y6T#>u%u@S=4CϿ,Oԉߺ:XG?h)N`nϼ< 2Z kug{T+hjWf$)l(/܈Ji)u@S;cWkp,^?]'ԙKowk3x@--_0uC=4_ޥp#u(kiۤc^z3Sup#;:ȻSgpg/DRNCΝ;RG@VVchٞ:Z#S@2wkkw|o2Y{gFUlB /Gh)HޞJi)u {h"uX+!-Rh]{x(Y{gTJKQ^:S]>k^nkBOͳV^YFbwNF|G3u1+~S3oICjInʇ6Ş#'3 R|QN!B#OSo$u@]+dy9r"FlG-^3u<'C7w9:YCOG)<;> u $V^>(;6BGhECo$kNTyF\~絸S]Kc腗o8uRZgSg 6h)Ʈ#⏷R@RkbV<>)$wFOh*o]=<BTޞJi)u )>:p{(ϥ`mV,zGSgl]{o '㭨c:ݽ/g[XG=:xh'7C/:tW= 6VV$);w)\yQ"Om}#QFyz${h"9ZwNw}'u3FOGK5u `qB|RgI 6)((E:+/\je5v=:P*F[HTV|NMo$F>#^yF\z{*uBOaKuX+`mRYY'| M?Nu-u $+wE=:wFȟo]je5u)dyg,O4je5>~c0PJs߾:MdPɝZO #N) Y-j>!² IDAT(u Ԅ+3Fe/ylwFU#\@kZk/g_^:zGPnu@1(ۨC4?R FeXϣl|5 7 CJ5~'ZwN<:Q^R$w&ɁMW)-ܿbjT!cњU+q̴k/dP7"~ M}Q3_S]O>0*]<G[HTV|ux4^xA VVc_^{ ԰߈G۝:OA Af_V<})@i N,/a;+QNXW=C/O|]oވ>(uص@ 6ܣhPe G{i@)dy|CFe<;zG#ku5;S ̻߾:XGOhwRhMCh'hVa 3{5\jo P Yc'7@ڹS3Be +ݽ/u+dy|5>)PS+'ᾴZ<,s+&{h"'vN@srTJKSu 5 ȵsoFyz AHdO|[4? FexP-ص@t}pT+L[H|::]yH9԰=GNO&VV;`D+1tlO%GbqBܩNbTQ*6]?, Y:h"7?gMkpg3D;QK3( ѺsW,_I5Ǩ 2Q)-NT!=㓑woH#^;6@֫he gS<:`Q^_V9Fe ,?%2}*cSѱvq)/1B*dy?jd흩SD}:m`PVV#b ylw-kw휗kad흆e ˻bWɿ}> Y:hBj|'c:X /G[p 6٥ZYM60(Zc:`˴ZwǧsNdTdXBG~'#kL47_V `&>:MV3`*+KOylw{AaTfXK=ţT N3'1T?E 342؝Zd]wNR~'>QNdT`XhџOw $w{oI#^UJKqܩl#2P SWlBk{bq|Yk;:cXO=C/&sbL\=3:XG!cW#kLv(/\O62(5?ފo0/ΨVV[WR@ͪ41TLB2,?/5p#.5wkSu r ` T+qRg @ڻRglG}QWR@*/\7*Ö2,^Gwje5>?ODRND,O𵮞3u٥ZYM@e|[OmGbqBܩNV^>Ȩ ?e:;յ(/\Oğ?j3ug/Ob7v` -^0 @ S]MӹR@3*C ;ۣc]>ʪaH$k=G?iHyWf;bp|2v=:-vܛQ)- 2PcZ 1TLmylw:jQR)daHwTܩNS<O~l\|t 2(5p=z>PwD:jQRL(/lBǓ{>^x%=:`C*}QS*lkÝAA,OFbLWR@]0*Ch)F==ţw 2$4쓏Rgw1cSg ոk3egc|Ͽ'Ή96lsBI'6:#;P4a4" ڽFZj=w{Wºv?WsT{/(U=_3lZN|sJ xHrSQ{ذngbvt*/N`TJLsWd sR'@1$ԊK'FbvT .zv @wT2PJ3V]._ 1?9:Q*Q-vGsWDDf&. |;upMۓ:UR8eb(lƍ[RBGwfͷNTZܹ+ZRhrœ;dZ3;~:.:ů`{'= ; @[k־IlLߌr:F9[&ތ ۟1*C 7~Kц(LjtH .;cKé3Xe p#6mY}G..u@;z0uT\D+u ƟE0:U._}96sfܱ(g)'(ttǮ#3?MMMé#Oд!oMDCSK#)PUn⭉7cgnwFsWd s P-mߋ XkHl@˷oC5l1uĠ TBlܗRg$ #pPM-m>;Z[(\M%7ѳo(o5$c2PrB)D}=uƠ TB=(PZ}d*/NLCӆ(tt΁O}ц(L?]_<=\w5-ƅo  bׁ(ttN K'F\K @Xk ۟N̚\C4>%ޚx3u T[奘|KÍT5h'#Yq.J W]k5-ƹcCQ:hܙ:q3@e |z<뿝: ƍ[-ƏONdTjUMR4wG9+ͷN쎞}>~ؖ:`Eгp<$rPXe */9 ?󓣱TZHUɨ ,O|>?;"o_[Yԁ\>?Ԓ: `U5c2Pv 8⛩3PeJh؝: ۟FOFV־)@rBltl/E'4{5b,jP-6?7~Dk`I҉xc3h=RgЕ*ݬ Խ\Ol&LU4sը UoM! ݱypo4wG9+ͷ:gP4wǚ\C$UuH̎JE;~>eŹtb$u̠ ThO\-;6?7(҉#3Omϡ<Tkokg655 OCӆX7u@hw?K)Pn⭉7cg%u|K[ ƚG"+E9[L2+ttGh\: >;T q*/ *tszlܛ:b5-}ěnL[q9?6¦U^o_OCj/~5 ݱ&א: 7}G3f ABl1#Җ:b44DCӆMUQ|K{:Shܸ%|vw/DVr: {oi/^?'v>g(waLC;v· {fPXk`R莬8S&OFBқ:VM._<7#"|]`}ůZ50&աD..u bvt̎J@ydӦM?K<u7|e>;z ΀db̎E0:[ڢ}`w|s[aLC._]Fѕ: rvdUp_655 LCӆX7u@ٰ?KS&fFVXkHnM!o̓{ﹸU^laU>;?ע?rB$aL1>?:*ȦM~:x0xvx 4?9^N5D..u $Wch̎95+Fn"Ș T/ Gk` *CQ:*i8u`b4wG-u @iܸ%bdKxca3R@Rkr QH,ލr: xbmϡضPkr 1=;O@)NOT!2PZ< lt'"+ΥNTZӱa3Ԓ:*B._ ۟̓{;-mjΕԩ:H@*NOĵ7Pߍw~KofͷNS8}S[nߎ|K{#kP /E;RgԤK'FG=(ttǮ#/]:1Yq.uU̠ 7ngRi!u Ԝ(NODksA=*tt;퍆 TZ5 hbl-RgԴK'FbvT ?&˯K@*NOĵ7=iӦ>Eif*rVJ5;^|s[JYq./ƍ"[Azh̓{ѕ:];v8SgP655 GCӆX7u@Ekhj 1?9:jRi!fOdžDCSK:|!o̓{XkһQS\O|>?z EkߠUfLG._]F"bOɗSgPٴiRG#OP|%n:jV._m{ES&fk1q4Y)uPrB ;:nŸ'CxLѕ: g8bPj̮#ܹ3u@U8w¶9:jh_5.2l1)=0&ʊsq2PcZc l10>ѳo(u$2JzDo0rusc2Pmp?.S3e={xRgTT=:j^sgxi!TXAen Fk`>"+ŅW@w8^L@ȊsqԐMMMé#{͝3BCSK[c~r4u Դ8~,6l&rBIDk`<Mݱ&\*/N*X._'v>[_=o07nIGfbEVK#c2܏+'_1 ל IDATzdӦM?K,|K[<;t:h}C2;S &cL3QexqO xm H:RPoL~7SQJGkߠaFRɗ. U}`wJ@ro +ɠ 8OxpcGEij +aOFqj"'\h}.vFk`V@9[sdž UƘ *+#SgP @˷ųCSgTrgrVJueض` Sf8}>/Fq|9}}onK ʊsqac2Pe0.S3ae:0͝;SgTT5l?v4)=(gwe/cPhsX%8wluTc2<8gO@3(uLgvt\:q$uԝBGw;)}*Lwchf~>\4w|s[$Vh\c2Pe܃útb$fO:nFxWN7F_Ku'/DWw0u b_8$uΈDf1VVG: ~0;3.QFqjUj^ΈLsgR'P<S;×SgP\Z @ :8wl(J3WS@]jrjH9[(NMw#[K%v{@#2ITrNST]F6 CɊsq: @w8^LPJ3SqPRKҰPܝqԄT\];92ܕj^dX.N 2PG;cׁ#3^qz"Ju+/Ďsg`f8}>/Fq|3 ͝QJ@0R ˘ %+#SgPG @y_q;21z\9r k̓_NDGqj € k~r4.1BdXNN2PgvGϾ5>^k`;Pԩ;2sdXNFz`9eŹ8{d ACnzX&cG9:ga}Ε(N70}ɷ}`<,cP.|k8/: tb=\k|!z2S R :4w|s[$jL9[ *eLVsdžRgP @ʷųCSgԌT;6嬔:Mn>80Sk7@h殝wFd `%f҉#Q:xdX 6: @eN;/q@>4a?OU(\R'-mwcnJ@K>b1VBqz"J@2(u?v8:}=|9u?v/Yqĝ*Wsg4w3 /x]1Vʹc8}>uuʠ Ա+٥#1;~*us=G3*VŸLijd sRί~mP1͘ +8= :>;zar),c۞C"+Eij&n5`[>4ܹ3ur Eij`%w @{7)@)ttǎ]+43ug\4s1nzx8wl(Y)u q>As[_[?u@q*O._ Ek`'x `vt\:q$u;3se_KPJ3S1v` #6m{ >#3@=)tt1@tb$fO1Vh\xu8u"zSg$O,T/ G-u P-J?`Y8wl($T9c2##[Ke|K[<;t8/}ԺT;6嬔:xdX :@%1(DDĮ#QK'FbvT cl}al8=-bpơV`%["];#6P`LrvdP1 7;~w8u@M;z(J3WSg?v4P PubfFq|d s-Eq|,JWɗ DC 0&j1J @1(onKPb;6dT*T._/ ;D Ԅx{\4s(gi@ȷE; ݑ| +ŅW5 Rge;vGϾ543 9 l cX1"+~hpn7h<njK>;dXM҉#3C wxq7TT=:ʐ@]ɊsweY)SQJf|p4&h\iPq<9:Xdz.Ǻxf'LLWj$BU)g1v`d sSC  Sgb pH̎J|BGwxi8mS3QJ߾Yq6u| ݑ"vWs{["/D+uƞ쎞}C3`Y?.w3jk[ј{1xec'S@8x#ɠ K y`\p_M|\2 bfF/Fgc)8LDDs3U-ƥG5Ę @zz6]O5^ަ˿yK3w-qGDxoZ?ajr7#l&n8*urgrVJˠ vΝ3B9[sdž*[ضPRԝ(NM3ܫ:#_>_0543?F0:X&d*Oڛk~hJ7y#47x_G`>j]}ttjO?g ڙ3>Vsg:p$u@(g1v,P%-mw!s WlaCw~hX1Uһ1z\9r `<h;!on?6*CˊsqpWeOWT;6嬔:G[_[FAZ?<6-EV&>~9+Eiբ|c~=-x2/vI9[ cLV_if*ƎL܇p>+O +rC/c?nXm鉸g1e,O?h\^*k?R"\=#T>2]}; fOǥGRg!/DWw0u 8O,}}ܯtT?-3`]:1RgZ4:\km' 2 ݑoi)=U^&ތr5IP\\xdLlz|63a ԖD\9r 'kRw_r:Sgk1v`fR@ݙ?9SefL3V..vG._H;u@jhj ۟&ތ[9U^&ތr5IPb\7ڙ^U莧+oiKoKAztM9CqW;Sݾ_-N&uP=#+z@Jp !}-ƎDx;z0/NVH;v\~]>A_ TNrc7 @u2(ܗkgN{͝;gCܱr)P|%rj1ٖsbO5H-ƍ゙:A̎fM^4*5k1vPfR@(LCqc) jmL l|h\^ SS'}1ZR x`e }<7u J3Wc)ܵ7уQ:XAgߐ1*` t9uܗ8-͠ pfOE9[L@Dls0vɵ3c(LNUWڃ: acN{Zi8uP]nbͣ ٟ:h8P#J e# qcX*-NVض=_M}3)?:*7+>:>Uif*.:ښ@uS'=ѝ:XF43:VLVsǕ/NVAϾñy˩3OkK@ [ש>VH9+|#FeƔfуqS`}=PϧNVX._}})<:GTkTjA]{R':2P9cGEif*u <8+'_rVJ\b@XWN:Ae s1;~:uL._H,;z0q¨ ԶkgCQJ43cGŕ/G9+VA;G/;ZcPx(\'Rg.2PJ3Wc)𩮽q<Ǝw#u`$mSxHMS'PCZ Pq< *Q}# }PJ3S1v'BikRo_N_Rw_OΠ Њ^PضP `e sqP\9J9l1|%Ǝ9*j;~wؘ 66:~ɵ3ǣRg3(, O\/FϾé3vc;z0'GSPNJ1v`}-u 6}C3 T !Yq+5+: QBGW>Ѹ[Ѹ_A7͟>+qnnYV`NI\la..:}ѳ'Ajb\9r̎J$гס>ɓ7R'\9rX1eesc5OMsTm|n;-1qOX=Fe~_Sc۞CfOǕ/G9+NVY._p_j!GTD_M+Ơ lfOG-u @y\<|.>r.׾lަt9~LDDb-슱]eJYq69:XaNS!j,8|$S u`$ ]S*w P7@[4:l1ZSgԅ~&rZ_S7537?x{3 ,ȊsQ:XYq.fOǭ.Esgjĵ7DžW#+ΥNȷgdމ_kԐ=&+3sk3`EUijvw)5kc=o:U6]^r)X{'~L:H}`wa=;XDl1.oĭRXqeцhOP?oh\^{t9?3?%>:}Q7 IDAT:XEKěQ 0oďA۶Pt}3Ho_-SgPc&=~ΠMiO>VDif*6< !4S׾W#?9=ذxcTZH87F_x$ >e\:q$\ }c [EoԘ$8j +Vy)<0"zz4Z{7uCm}/®۟=:5xb?0*u8=ϩ(tl|K[?GF}`0=?3mb'5ՒvihdVmm&toMwusY]ŽW=:ArЍA9&pAW*0%kl^xpfo>(~IQ>_ׯ_M-)C+NZ'{eFSPP@aN:r:ߘa+f ?PUٔu ?][0L'tu6^4\'m7Xsu) Y'bQSPp@uOJJUau 䌆^n?URZ,(z1]^n"'PEV>N%0{L}%"]m޳O[n1-Yg g4ᄬ3'\'^2`NF`Hpu i jϣ\ZoBMԕmYQL:>]1 [s /bQ{Mu29Wj@Z]`Q]^Ǭ3'.vԕ=@V(gOWCuBNXu1wשvy~Yu=ޡ_U?by#љ/*zu)wuJhxu5@u(,7?\oKlJ3rFI+tavu;( r6]Լ;g KNF'EoTi h9I%4T:@ll|Y~vTRUٔuXyɌ~>ժ>so̳2peV%#Yg䔒"W-P@6bTrR M>"'^: rdtnXuu6yQER@cPKj ᡤbQ 2d [+f)S2D:>c1'x#6=Pٯ+{ y>}< ²eҩ+۬3μ\'cd"PFO::ߘ*Kyay)c|ų)Ssx)r5zC|e&{Y@֙=_N:@xjj~:4#L'3Sڬ#@arzX_P^249~Oi R$ܗywN&}TFy5I`*Q/i(7^Miju |wÏPJ\*{ x`ѹ7x?"PFO: c2 go\ZNppkNCμμOu,T,3ӹ7۸T6vy+%x:9h\'md@ f d [j*)r[ɹU0˵M ۔Zi.EOr qR M>"'q*y/j]':`ܫM|OER@ų:~ t|D:Z sanm!03RK{)z1Q#x䰴L7Ql{o0$y~mz{Zu@cPKdF?j u rD[qVY d!N:zŁ@:@ғZݺ::ߘRs:`ھ}ŝ&uyJU勺rGsi9u2JGE +9^@ga9n}ZsuTMiG) L{ஜTBlr2 kNFGZ:l Ow]n(`+,"WфNAqνB0(N:>="Ou <)=bQʦT3k:MX,02C2Ƨ^Pݗos{=)  wD=& dXg9Au9bVxh+}eu$hGeDѫr7}2*336 'gX<^|k|:IҎS DUٔ~uJhvͻs)@NaPdt|D{krnmǬ3pSIJέ҅59n**ԼKN*GX2C2?\NWyɌu PIh Y |: 4ΩTZCwrUj ղeRNpVFe,OeL72b ྤbQ |Un`Qwi˷3 :P3`,j73_x[7n]{DUSſ u6yQ4{Ը@>=3s'JŢ=ޡTu : b6u@u̻s**)Uņ)4uao\MԕmQu*[\9bQM9U) FOtI%s)ׯ_M-):ߘvVw[gxm&u P/b,e@VKGT x)!0h?dFz&]^nVNF3c)21ky d1{M*6lU Nj ;_Tu 8n׼;g,e@Vw:U6ZUMYg>iwB\M-CJsq w甎k<)cھ:lJ?::ە[g9Aa>䜽k":=Jέ҅59ndt~%# Xt_> U!0hWRGJŢy 1(rdTjmoL_9aO%xVeSI5YQVJh5ܯT,yw: @7_M-)ܷ +,[&:Ku2%_G~^y+jSRUnS,uYj~R4q B4{TGjޥխY'x@XTCJ1X `iU6j}x[@xg+19$g:a@ fp?TB[`k lJMh(S˭s+ץI0kbQy!yn:uf/Y(0zAzAER؎S*$Iq' k3ȜTBl2 g^SEV>]sXkxH%3ھ}ŝ&uIVnƨ SN*ޣ Yu28ݥ5{Tsi$k˷s0Ӿ -eS:~ ,so,'/`0(r3PyuSUٔv))r}e-?u1* {|2,쏨S&: (hN*oj]\'cUlت^ju eϣQ^2Oj:$@^aP'PEVj-3j k j1TbOFef2\zZ&}Toa`bQ |U͌3@ j|%yJSx( Ac9 W/iu׭SXUeS TMN ,XgyAsTBzXՇT^2cER^2W i YSʨ 3)jtUJh*uBͻ XupW˖IlCaPt|D{dnu 5ոbP=MQuPVi7R?b4)bA9JA,`ɸNFj]4{y: צg;4 iguupWބ~>ժ>|JXTC]3Ǡ iJJUau R$IUeSRuNHN:(hpR(t|X(_5IIŢ=ѡE:$#^eb&upOm2uνզu9/QsWhk%Er5E>f4^+7mӥIFe 'ХIMeUyu28ݥ59t|: )ԼK~_`u K扪==ȤM0zC'3 yӪllNPVj dh(S˭sU2* 'NFWhtfc[g,jDו=ruܓצg;2 (8-Yg+_x#8nw{`0(B:>gwaS-2%3ھ}] yz IDAT/P:(Xj?\z:ȼ;t|XJŢ<◯jupO.ܯaIp_z=͗rSu &~WUeSUZt]=& G쏨S&o0oX4zCJT,*X'vUlbu1[iu:{YƠ +N*kS=L%3!ބTݭtssT*o0d:\zZ&Nwi.=-_y~,t|D~]I^NOmun=6֛ЎS}&nb'|X*;? 2 bguu+޵bTRjG)-\Pz/8zy!bQͻs9 9͌kdV|+{36cj]գ k[e^+7mӥI>wTB#5z Wpߒ}Cr䅊 [« j?f<`Uu`D.EOZgAғ 5YER`Ѕ+T]67G%I@A) r6]9\'c nޝX#E%-9Q:>rkDff/Y'Ys6yߑUUٔu@KfVY6N*9bP%ɨTZ({= UX0|RuNHN:((B_:JG49|k`I%4{L}bA| x5jzWkd:x`m2u͹7_lZҲڏ#ןǻ:@{kw~ڪF-`NF(N%kunU6 P \'d_DGESت{ }*}~ ܔܛm@+maޝӼ{]+7Xc AlKb.=dD4,,dD#G@g9u, ׯM|Ou_<9d)}uW&]^nR\'3Ӽ;g<e@^W賻S䩖m-:yUKW h: (<ו=)d9Ú=_L_d `I%49v]>~N: TeckvGif_KZ*ZV|;kT+xx&Np  9lϣGTU6eܓz_WЅ59@^+ U勺rQxsi]9ߣae@s.E#5ٮޣJLJ5Y@֪ذU/*:;7n҄[ѹ7i*N }))r<*FeEV)U>-'P:>l9qTBt:ە0"֦g<9佯WyɌu`NH~:#oo@`Pt|XuԎSi ղe)` T6JˤT,j9qMDC]i7t|f/Yg@v ߮g`u'[R?:J:>c 5?i Ǭr#oxi Xb! u뤭s :kTywN%Q/T쬜u;j_TMY' ׋u2x:}bPllǻ:@i\[SKBOי_dT3x#TրL/b9=x@e)?^Tr 2NZC\@ƭwOuav.̮N?\?so)rWec50G*5"3,խ3(X|c X㽈E5{:`P_Vy5)r@UW|S୨Qs|H\'ޣ^dxXllǻܸ*'Pj$d/r7X{b rϬu(|׬d4uĠ (xmu u Ƶџ_:(r=7mzMC9}G:%^]ذUpurXTɾRJLJs onݭ;2 @h Z'r;L'3< e$Mq:߸u`Rs\NYcSz,t|XC]$I`*>-lh5.I%n ȤFru5oFwYYY,r4Q 4zCMa/{k :X0kQyJ&vZ%{`9 GiluJEHzUlتVUlb\R*5"3,=ׯ*ZS*NFw0 0en3z'll*;Zǘ Petavu Pp[2JLJ59$I7ebVuuA#Jةll=,UYʠ WrnuBNKŢ~33x^YqoEdP0.ӦxL/rtoָ Cd'P/HTN^TeCu u1`\7e@+ 2gj%oEu ,NEN m|yYʙNhr&{J?\k\b< J(5x@&vVt: pVm޳1NrrϬu(.ήNi':{ =P=7m) 2WUS $?\3(I[!V:>!IRņ`1 k_ʆVpxX't|D;3,e Q*#0Y'fo:MpZν٦t|:p>]m\f:<r2{*>y˭SX^#cR#QN: p<^6ՋlhNGstavuFN= 0(p&{)u ,и .=/C``?EoǤ @ 5Ƨ^ǻ:| UeS קrR:>o@aP hW^x, Oi`mdfq! u23N<$oFWYʠ Orn9i A{pFwhS[0TU6ŋT3 jz]L's ud;+˟nC32t )Rcxus y`o:Xp:!'P:>l`1(GGi.oEu #D|wqvu?S߽so101ָLEF1#QW y5ڼg*6lN dg:XP&vg:##=a`0(pnWsXg0NՅ5 ǻ\MϽ49dXBaM$y?{[}8=.fbatMGXt䏐RnFT-3aUd:j!HwNW5%"!? 2(\N4''80I?><>ȯO#3 )N<t$@G`팆)rZrCg:*; ʠ U(Nhҗ:H`kR'z 5x#k`@gH^˷?.koFPfϝ2j %׶!6?zE)u,3OIQ&_w>P \:TXT3ݩksO6SRM2א]YL&ߒ1P:c` `9 A-xL4MRufϝɃC3EdP*gc!'li<:KVAʵ/?>cOrkQ)Fq2M-We]k +Hx & %Ըn:nK3_w:Ts*u \?=PBzR'~ hȬqssX3Q+#qQ#3x W!h{ u WzWœLwꔪ5yp(3ө3EfPTʳq޸SKd]lX4/oI,|gWI@LSq]eRpj4o틍>u?g!FKkgPa{泩sVqXLO,2רH'Es[` li<:NPk=kcOJy6uUFf23EmCdk[6N͞; ǸQѐ-}S%:Ji~U鎟MǫSTJy%%PG \=]C3E.{6+JboI,\Cӻ8q4u5Rя%ȵm!:Q%@mbܩ(N2u> ogtzuj]lT]1: !PG \tL<}NTԪ3~"iȬbjdj\qhć?֐EmCoL52M-ܖ& ?3{TgRM@ ʵm>5:9)Nj8TlꜚS812iP j`Qx(u6H6{%U)Fq屙4D&jh[cH0:v + Lw<;o&uNͪb|xO `Nl<76?+u HeϦN3%sO6?(LΕg<3mhyN__|K`X::V_gB_)uN]8y`P ܀G֞or]Q/fRg:SjO,\}l_+#s#>il!\ۆȵmU#oҫbܩ=wxcQ)SL.6hܓ:Xf Ů8Tљ)up|$y.uMk׮}/u@5˵mXoXM(ͯ7^:Hh򅡘<8:nXmC4dr_`WFcޚ,G=G!:u 4uuMq=Fg4MSw*gS 4vN3@`˞M ɉѱc0]ӻ͞;76sK7fy IDAT TsR<ScW~(|sacehp%NLw `wn?/?ۛdI66ijLM-uFQͷ+?~@jEC&w=;SP Lw*lWK!"y> 2(*8y`ol~pW`V)ЙL%zO#ϥ%DL|h`fd-K \ı+1NE孹+1P]kf`IWx/nJq@be#Ek@;Nnк J':X6?+]qިgS@rNEDDqfrm"w# ,ywxѼ/u PeJR'PP/FgS At}P4H ɉ⍷פ֞{"׶!^_Eyf:u,k앱+#Ї>љ2>ɷF>YdͰ?as\.޷3:˫Ǐ*9\љ|6ubjOMA4{TL<}Nn[:nسnZm}>/Ƈ|̧Lgrܶȵp+o]1 #}4rmSU$\3xTscg"P ,ɃC36@bS)ЙLCfu15L<7uԼg~~f>8@ijLeA;ONG<? Q<`5drG)@ x ,SKkPa{*B{AV)S[.D 3ຕWN~+uP|gW=aCXF>8q#iX:rm|\'}N}a~{4X^vFG -s ,#Kkbt;ǫSp&_w|XWF8q,>ee]l!ON<0Ǘ}oXxᕑksm!V}̿=NA~쳕Q?i<6;b㽏řR{|1;:DJLwct;u7h<8:Xf ,=]Bx"u\gLCfut?'&_rǍ,ܧ |sW] O$ \lh'u P^ebW*9[PC*x:X ,tL0;S`]l.gJ1}3Աc0]ӻRMԐJyj ,b ޷3:!:u PFg-Sgbt;Fg4M<82dP`MhL%u p4H׬4*M<hˏOᆭ7}pu]G#׶>u P'_U]VR{Xx5sX$#15?uLXDl~xO*Z vZ=uP2=1PLJP2xsO,¥5FdD<?y"uXdʼnQ8>[Ra]lf/ngSguc`;wG<:j팎hȬNԩ }e\ҚC.3{<>A%pwv9 [:Ii~UMԡ|Cӻ8q4u@Uwv{\)@;~qS.Rp JLwX7!gH `[ظ;u@;MSOt8>ws%u\7ܰ2Z{"n(NKeZbocecS+>w UC1Z¥5H`~"ޭ\J,s hp ,Sr!+JWN;#{<3:`iog4dVC?3bWtLw泩sXƇD<:+w7Fk@ c6EopU xϥN˷ka g9F־㛻yK_ܰ2uGbĖS7''CxtDD C@hHPOGcjh{ u [eR'Uw!7NCfu15L<7u@R G#߹-u gjȮx+uJ:Sj }qo&uPqXLJT2KlP DCfu6*u\gM3>Q{=1{T%ՐEG &Rk)upiM*lC>#2|Jy.ƇA%V)STLKkbRg|\~8y`o?\%޷3:],Tg+#O,¥51: s{<3:2e(2ʼncܖ:-'R'Uw(gSg\h?y"*I"+2)7dC54*tϦpy> Њݩ#Qqhaܰ2u Խ6bTexv?u5v{NDqX\I`2M-q7ctFC&:M7g!W/bǓh;~SgQexnR 5W;S@[=:>Ui~USg\L%z/ 97!h{ u ~x¨u:\љ8TKB xQ)ϦA&E"׶>u 5Xx(J7c`;b|xOgS\? թS]ߍ슷RTGdFg=gL0NMk׮}/u@=wvE{Rg@ݺ _}7u|7ƿ:`AUs1>' N*[b㽏F&ߒ:`I˞Fe>R{XCFdXpʼnc1Ԯ@[ظ;u@=+aU.n}KK[o=ۿ0:>Vi~Uv 977ijıxr)uʵm/whR,_89>nEeL=׹7j[YԘJy.F<:r <8=ѐY:Ζ=;o&ui'O9WdZcGk=S9~qS<9oO;gd L,=QN2@<{oNug]lXgJ13]&bP5dr~޷eqliFv[s#2 s#<WFRg5  2Qxe$ GyK_+[ON3*u1[Wnh>jH෌to'r_Li~U }q9ԡrq:N؛:!7]\ij9 KdK:>7P $*幘<8S#Su"+2)m\SS#2NC1{T hllܝ:*xN|aSo McKR_׉3ysSae|aSon<1V.NjTmClѐɥXJ8Wbu[17:.v33x(Fz5uu}Q8>:17]|Xc"׶>uԼ{ܙ?:>dB<{Ó4Dǎ?֞{RT-'+/N*]1:3QϦ΁+b]3dP`ʵm΀_[5KkG:`98y`oTʳS*֐E]Dǎ)5!z0vߩS>֙R{l߈ V<39(( ,S"ʮ(w3C78~qS e\<ʼnS*?};!:u @͹ ڟƿlE8Sj }qo&u|X4e/?>|K IMc6MW.v[3gb[3,n_m9w7Dv[Ku L<'8,2X+ޓ:j҃짱sNW;px1{T`wv{\)um;G/\Z3q=^-ݾ(_1GRg5Π 2GPsr_ǖ3 ""~_ v 3PLJ,#ή|)DDvE)z"4uٳ}VpiMZjW8~qV<?|$3өSא:O7yp(Z{!:u Ԕuٳ ""JgSgTѼN4Dǎ?֞{RltL˞슷b]ln(}?jdR{K 䁽d%qڵkKkw|cw r!˶΀:xvڠ |a(&!Z?|Iԉ|+#Q8>[R@Mh^y!uDDDc2 c`4o+ƇSsE֐E]D{hȬNfϝͩ:?y"*P Cg:Gc{0u H2/?>;^<{RM2URuC @ 9~qStI;}kې:X@=d3yp(fϝJ2U8q,uTJ6ukNiLܠd6?ː PU Gbjd 2{RKUs]quc`>/]Sk!L%u5)c'OԊݩ#z\[y'7u T C3cķ4MP7V66Ek@4śgʥIwvKFC&:ຌ=xө3:Ր:k75?Es[JnO@{=x{M @4o<ʼnsߒ슎Aw=w*uPV466N+N֞?VNq-RgP䷢4MP2hUxx[: ^+6LSKR8>'M92URw+6N]Vt}RgPg^*lCDĭo_ g9P \c.3(P<{<+R@uՖ3#Ul~憕; rk7?uH%4$Ԝrq:uAjK΀S[Om\HBLw >FcVމ7O5+Vl~p! + z#+fϝ:XɵmH G䁽30(PǢy])u T¥5q-RP~zqw*dZblA8/ʥ)Wo=~59~w͕)Ԩo$ysSήhs fϝrq:uTC2@={qeǠ @4;q7W4s)Ԩj3 \ Dnn`H7'aP'EֻbecS*[4]jГEi>:XŻwͳScHG#qˠ @yXRg@99ި 8TKae|aSowSqiv&u$gHWtۿw+R|,25LMή)PuNέ¥5+ss[QϦ`eZbUxԥ\ۆXSG8:AʼncѼXؔ:ΫدELC{=RgHn}KT87Φ%_{<5$ԭEH OePFyx}3*77.{6>ws%uUoN~+J,VlȯѨR'xH02M-s)Lejԥٙ.hܛ.;:*r+3X"hqSnR$Xdӻ=Mk׮}/u}k[:^vE)`|`dW:e{߉7 rq:NWFRuwvEG`;NX*{jW̞;:q PSz摸34u {I@bʼncq^J*=?|Kee|8WmEcc,K37]IX[{t+M7ELbxrk 4/ rxr)u|֞㛻g 29# C3Mk׮}/u}k[:jZoXli<McѼB(\Z>,3\<׍,+ \ D]D&ߒ:`Y=w:ƞlkbPN6DODCfu r!4*6-00S'7qЗ:ej8y`o'N5dr~޷s#OQ)tkfP팍>:RvE)z"4uٳD$Xi~U|4M2w1<`IeZg UzǻH bPt?D;" tdƺbv*u7`kJTs15?~LTʳsasO15L<7uu3(Pg2M->7O2]Qu٩zb]lNE J~kRgPe<8<:֞C2ר8q,ƞڕ:C};c㽏BvE)z"eƖgW:Ra{x(uU8q,&Eqh\+:#߹-u @թ{RMpC ԩpm\-u٩+C3RgP NjѺ IDATG䁽QN@i[RTw P ԩLSK>/2S `KX=<4ӼBꤺqwRgPcFɃCn>S5dr3w=`Hg{L>"ty\i,4슷R'- ~kRg@L<RM 4Dǎ?}ѐY:'SRg,2\ަ͏ŝMcu;.Ra{x(u\Q)3eL+z N \rϠj@M3(tFǎ@X=w7"zƢy9KϏ}?x{M 2գg :#oIPWFh̞;:`Q#z3*S/2/ǾRg䁽qsSLSK D{hȬNPwƇ e\ۆ~ 4i,+J㍷פR.N!b˵msOu1>'u0(j}$uPnަ34u {v?|=u\32i Dk@;NkNSRM$ ~g`v˅3?z0W^HsJGlne_C&w==ɷ{\(LNX2eD \|hȬNԘ-'+#qgXdW:Gct;u,2 /׶!vFk=SKʠ yk_ݩ3]Qަxh^y!u':\Rg3,pZ{og֧NොL=w4Mư 4\iȬN8ޓ: 2|L.zlod-S:]Q?j=w7"W^HR_o&i,2.w=[R)fϝvE<: 2\|gWt?`i<w7"4X}&WK/3qsu!}?h| Ts1G<3: 2\1:Cr!\Ӹi,+Zw?-X*幘S?ư Pwrmog4o틆9\I>/rmSgu*McG-٩KbIk@ Ds[bjd pM2M->7qɭ˞?j9w6Ev[7{WųQ.P!ԦG~) &};g3*u1>'u`Pk3ܕ:ަ͏]̙R{XCd?|LsR\}޷3RpfϝvE<:`Y0(u㛻yK_ X=[Om\uٳWKǫ8~w㍷$(R88q4u U4Dk@ D&ߒ:T)teà ץ!?5o}<:c5o֞5f]~[ p]2R.N(2leZg Z{Ԡ'\x1 pC:c` `bjdL2k}Ѽ/u c|؅hǠ 7}k[:Xy>&_QgS5,};g 2Sfϝ>:`2( 4Dc>UqXL)@ i֞wnK{RMl`A w@8RU*׶!vF>uRvSS52,>=D<S#cϸAL \ Dk@֧ '\Zp `2ɷN#~IѼ/eM<'MP rm1S8: џ?y@xwooǨS.A%z|YT˩0!^7vfew7t= Fi Z8a9̯Ob~u=*ٕs 4vNeJV 3<ڏ~{;S-ćzdsP[cxz@06_Lbx|)NSP%z|YT˩0?y/ZS(%A2>\3)oDdJ`뱸v;毭@I;inPZ2ݭ{4 U1<u Z1*s`U+g1J9H" R`첹u18hŋ{Lbqv,ݎz%T IPKv;i̐׍18hyƤU#2r9ب8ݭC. iooNj(NSҫd՘_]?xR 2\JVw7P $3<ڏ~{;y9P*gOpϟ<ǩgL A.U7nF%z 0Fi Z8a90^EdW`,47R*2\ŵqN# {xzV<HZ_ŵ1Ym!X" #(@W܏ŵOS87*NcpЊ~{;G{AdոCNjᅨ89N="[?ҍjD;L=`* L=L=7 bpЊ~{;xoB_$nGz3bpJ=`j ԇEkTF2(&I)0f2$\,/Rxo8xzq9LdTV#a)3CPzL׍EAJ?3Jixy}'ǩL-݈j D{jL(AJͨ-]O=^7G{ooG;L=RU+͍_L0AJUW pAq 1x} Z\JV}9T+'@錊jL8AJZ_[0Z18hh @i ԖnDz^vAJmqv\H=`n v(0Ѫ-xzL1޹k0Fi Z1<ڋA+FEz0òIԖGmFT+'TwH=7$(@Ujܼr)3'uc"Lln!jK7ήRO'&P>2Lln!n{YFi Z1<ڋA+FEzPr1H ucw?@05W>H=^<.331{1^iDDy,Rln< pLVj}9F. oJP҇E.NϿ9ez-8,o6>w7"(i@(N_H=FnL 1<29{GT%(\Qp.ud JT1HEPp28xy)0seyH=to爛0d`zTR-FDD,}x t{xߢ89N=2׍ݭF<?{}wMlcBrE^,9lJ K``P@c$ !AB,A bmPQ8 ,(ah dv) Y9I\LiM&I&ǟyy >xl2@C0*Ԙ1h2eaT`s,M[ QfvX,Il2@1*pwʓ4}.u ɨ ekqX:b;RܭHT+s3Z-[!c2" mf|Ȩ VojZ`Z-x\̌Ev}9u Ϩ [>~dԲj`QX:ɑ@"eaThuјK$dPh*FeVTñ4}.u AZI-[XRJ2@S2*je.^ɨVNAi)ZȮ/NH[XHOEbi|'GRgu(:`;*2@[xe".LAe]yr4ϥAQ-[VN܎ۭ<9KSgܖlu٘ prR(ODDD%Ze)@0(,2@=[>Scd;bPhiFezX:Sc3dPhyFezRs3eP ղjZ)2@*\'GA ݪZVM4dj)-`-MKZ[:hmbq#u@=8}C3&5;B,ΤL.u@Z>aTTl-f~6`3FeTbf|(kS&ePC6C23CQ˪S&fP6>1;5fLrenQn,X Eō`\~gΕ'G#6 ](C'F節PT+R-fGFT\ekS:Sū>iLH  ]2*rEōг?\~g W&bD vGW}SmVbvj,ϥN0(YrB:1jTZH-[VNE-\`T+sW#ǍuŠ &2*ai|̌E-N9mbq#u@ l8zOl٩bt&u{2(OE&ekQ+)+:'G""@V<9ʵ)Ƞ 3*muR\~i8jY5u jNV""zNbl\nfV,7RG78: X>:R~dfTW-[VNceQ_\̌E-N+mbq#u@+*C'F#ߙ:QIHȨ ԇh,MKHʪk13>l-u Z3㧌MX,nhu|!BϾ)27#:`H@D-PT+sS%,M!c2@i+#'|!BϾ)дf^ҙ[  @<GRg@SekqX:`Rʓ#Fe`T+sqoFv}9u 2(Pʓ#Q˪/N4}>fƢUSlb:=p4Rg@Cz!KgRgl\>2pjZ\~i8V/NVee<9PתZVMڊFnOg:1jT(OHƠ @)cÑڝ:Jyr4ϥHʠ @ qhzNpT+R$#uwUcf|()x6&Smbq#uw'/#O=GR[,٩u%:W˪Q0*@˨ekQ+)us8uRD[DW)p_JPڊF6GJ[bi|NE-N[lsQ˪7x*rs`N33^[XH*C'FjŽEr-u @Cؑ:W\VS][5rܘ h+#|!BϾ)pGKgcvj,u@1(rBSekQ+) ɠ @<GRgVߌrK(OD-C:~ZVMڊFOJQbvj,ϥNh lsQ˪7x*rsha\'GZ:iōlB8tbԨ I\-EhԲjbP_VzNN33AЉQ2llu9.4ʵ)Mˠ ⑧#ShR+WKQ>=:R^-Fyr$jY5:94٩bt&u@Kh+#Gop(uM嗆cubK@}Y>}"ߙ::).4:ōԟB8tbԨ wlᕉX0:%}_VzNԲp_Lв rBSPV/嗆US42ܖS=p$uuhᕉX0:hN@[Zh=::Qҋ1ϥNڊFGJ@b+WKQ>=: wг?\~gz!KgRg pW =oTzN`dqVN}8tbԨ @ XZѨe)|2|d}{H X::`PM/#OL&V<9ʵ)ܦ\bLԲj<ӑLG4}>fƢUSpڊFGg:1jTAղsS etvGW}S\\~]_N]2( upnblN#2(z䩧_L IDATekQ+)l2l78:_:).4:MbPm{0 G.3u D,\H&3()쏾SQٗ:eeqVN` `[?6]Nh9Kcvj,jY5u [Ġ I #3ZB-[٩X>:-fPdFP V嗿)l2${0 G.3u @Yxe".L` B<}SBӣ:1u ̠ u!/D}=SPG PrB}y(v8:n,M٩e)24O}x|7HEyr$VRP 0#O=)nuR'G"::fPRdž#ߵ;u z!KgRg prBSlje.ʓ#Q\K@0(@<GRgl٘K@1(@C8}C36Mӣ:1u Ƞ г?\~gdj)ʧGUSР rB:1}Sƒ}+>sc}O:;%*T֢<9+WJShpeh*}{H fs]3fƇ~ŕw>?Xxc}6@kZɑȮ/N tu}=uxbc׽o9Wy,&߿^?nwrO)2\NFg_Mq]?Lڰ~xl'iԛX0:bP7x*k?S"Fe~~#u $W֢<9+WJShA흝é#`\-E>s8u {ŮN3ţVbfTT+RТ вkrxRܖ'vǣF_}o܍:]-[+}>.LĻshaehi7ci||l?;u#QK)Ǐo쉿ͺSYZSQ\KeX> =R/Ɠ_Iq[~?:Rekq…xv3uDDD[XHbgGwNFގ)weV|z4jY5u P/xG|&| ux3qDO~9u=mmWtTl-bvj,ޭLĠ Kߏ_I}CꔻvΧc毤NM:).}k^M﫭X,nz/#OL'vwz:cSߺ?~~#u ܵZ &bt&u |(2!zFwNZ7v0uƦc\pWV/Eyr$˩Sපwvvz.T|ǽTGz|NtVٵ}Sղ?Z:nA n_DB|lρ9@y??jG_[XHdgGwNo :oNr+7%~cVGxOl-.LbLk흝é#ݛ^L@==;jSEGK÷?:~R\~y8ѫS#1(wfzODg}1ɿHXkR@DDԲcDԲ9ōȺFP At3ŁS$׾oI@[ZѨe)i &(cÑڝ:cw<:}+uJr߽|H@ ekQ+);;;SG@YKWDǃ~YeO*W)ux0?X9:r3㧢Z:A$nO.}?jZ|ϥߋٸgG-uJ]ybgF\_K@ ekq…xv3ulb:MW?6)@Ḅcq)ugWJ@[, Q˪S`-pt>:H@̣7RԽ[sg=Sh2rO)m;;;SG@3zv3EEtLl'w_{vR4{v\?nܓ:&X:WfVmbq#u4ރl8rS-Ѿ':!]}xl \2Sc:{9ɠ l\dž)xxѱu[SZBLߦA-2 &Rg@R흝é#[K""z6ѓ/3EG) |xc}OpS@rmbq#uރl8rS}=yt,t:|CղX03SnDrBSw@̣7R4[sgV/Eyr$˩S><:~/}!uFC)ԑZɑXRJuɠ ԁރl8rSpǛq۱:ex׾::4}>fƢUS@2(u"/D}=3+WK1;5)а @(cÑڝ:VGzb|b>FeH-[H\)NgPD._/ŮS=denő vH3v{DsQ#"Jro)\@4N4lѳge}"qd. GxL&[;",\iw_|@6FRQڑѡ(R@M0(UoOtFcfuzVǣ݇y2u נ*?ťlQO5Š TwDѴ~sZ;Fc`6\Ju8W_L3*PEʥczt(u $2P3M?}S@U=a nz9z'SpS1q(]M5ˠ TEјY:*X n2\Z\yedִE}gHg?ǺŦl>u 7Qʔѡ(R@]0(50L#P bghQʱp8\,/u 2PcZEσ#Җ:m6SXfaنKSFeO0eS@3(5i3D4ߜ:nlC1|(~*ʨ 7PL~Ϡ ԉ-Fgpl G#p)u ʨ Q:҅)1(u{[L4fVNn|<}(z'SP,l$K)UT\K:ӘiGko_f;Fc`6\JB9W_L3*p_#Q.-NAS}{03S=a<}(6eSRFeMaT=~0ο:e5#zS7p4tKA 0*pʥ8{`̌NA z'M/Ŧl>u 5Ĩ 7PK S`PmȴN6c`ñ6:u}/O֦N(SqX8^ИiGko_\od>͓SKf#3nԩ8\.̦Nn"2Ui=LK[m4 Rz-(.eS\Ra6?ssSe`PjypNܞ0>)p;U\Z|n8'D:X&ekݾx"3SP6=Rg5).g'ōSܙ\=~0JfS̠ p]3M3}g*Pod(nLԁri1ȟ<BBnwDѴ~sn۳c݇bS6:*.7.|?u PfN/FlEc)ownwkd.NO⵹@)Lѡ(LNA`YtoG-u \<3"nri1?3c#S*cPXvξݩSJdf#3*6POri!u P ɴtoG-u W \92;Fl5477?:Oľ[o[؛:<?P5ncu8KTԩ88KQ.-A ʗwSѲy[4fR'oܞ0n-Ni*.STǟF0:eP*؉񭍽slC1}`]Jw7 ߏ۩S R.-ƹ^_23ssKGG#XKypdZRԽǺ=΀6wymdmfN/FlƠ Pwʥ8\̌Dσ#Җ: ۳NQ\Z77w&g4$$2@*LeotFg9NV:ӣCQOpZgx"oN R'@gS'@]*fc׿4$2pxoo0uYr>uԍ3ō3 1=:3c#SA?K=ODKsne`nKqAC2@]2(o.[?ڷ-Fcfu$ʽYg.nM5\Z|n8'D: 2_afl$NbˮѾ9@*.s:j!AQ.-bfl$zI@9O֦53v"_}1JfST2W05`tFgߞh̬NT7 P |92Wazt(fFbˮۗ:`s?:jNaTL~ΐ W0(pJfx&ZEσ#Җ: }PL5*ݽQ\ʦNQ:ӣCQOP \xs?}{1:uU3v7йP \2izt(fFbˮۗ:]^+Sg@xe?^dAta6g{[(nLU*z$K)PuJ٘)5ᖎSGԲwĖ]{)_*PNUى}qPU  Ϥe.H qG4fR'O?-۷KJ/L$,|?uTri1νRR2d{13v">[Mĭ+R'|[˱΀HUC2u ~sj-75muѾ)n|w>:ʹbguTkɷR6u T,C2i4477?:^]^3c#0^|kSo4fR'uo֌΀W\Zi?)Pʥ8KqWw/N+ttt|:ٷ'1:u PFR h/L$^K\Z|n8'D:n5477?:/x|t9ZЊ[?P^폣wR.-ƹ^ӿ:{|9u@]̚h~d7۞lå)Pq\NK\Z|n8'D:khnn~&u\Z3(L̚ȬiKԁO?->wR@E).~~[H\Zsu ~Yr$-~/2WElSg@xꝧTpOri!u_ @i߾#թSv{8gSg@E:P2۟:1$P]I[8^|O㳥Ѵ~Kڸ"uPo-D6ON,ls:(k/_߽F|V: +pKGG#6زkoo?u P{M| HbxM˪\Z|n8'D:dPdִŖ]{/u Pc mOERXvOt|Pܘ:M0GbflĐ @3(PCZEW`tߙ:!g?{Qй,J٘)ejPKypdZR5y2ϩ3`YY_ΐ @m2(PڷA2 qok.pSVM7!fPtFgߞh̬NTwkd.Nى}qpS,?aC25Π @h4Eݻ Sze?=:nԩxA:Әi-FSU,P}`6ON\3~1/K)pOeTfM[ta l8{:΀;Oō3;#dA:״زkotߙ:Rg?M/God&8pfN/Fl2(@DDtoA255^lå)p;w~:!ADKypdZRU(PƞcS>͓SCsRgW;#QO@2(5ˬi6,\xlh]1::ľ8sqk 33c'bta6u UΠ --}S*m46lå)ԸWfcC3 b̌D>7lHƠ 7LK;SU&P bghjTqiU<>~ K)ɜ<BjAn82Zr>>͓S1/L$^K@+fczt(fFRP pӴo]iiKTּ^Sg.ng'NE>7ssSe j`6نKSb?=u >dm ؉xAMW`t)@6M/=N 8RgPGʥŘ;W_҅9!2,LSt޽۰ pn~^)TkɷR6u u\Z|n8'D::fP$ 5oগu|*~voq3qlLH2$֘i۝:2ζ6\JB:sqk<;/u50u*G05:A*BfM[tpo?u PE xxqOS0Ot|Pܘ:43v"_}1JfS2(@E1,\p4z'SP^폡sK G(R2(@E2,\{[s1XOB"ťU(.eSPJ٘)p P W+Pζ6\J2:P2۟:*W:ӣCQOW͠ U1w;"Җ:V@Ѹ),k3b3c'bta6u \32T;а pEz'c`mLMľ8sqk L03c#?y$ʥ9p P W\ l8+Sp5ؗ:*pcfl$u Peze+m(ƏGcghd.'kSgPfNHSMaPѾ}Go-wN*ܺ1q4i}=u 7o~O=: V.-F>73c#Q0:n*2Ԝm?hXF͓1h6ONVM@*fczt(fFR1(@2,\{[s1XOUq̝E(LNegPҽ-ڷN*X?jmm:+0wym~ K)S1363c#SkИi;ݑiiKTp4z'SԔ~@ Css R@2(ש}M7N*Ƚp,ZW̧NzsƓo?ťl#ӹ(R@3(7HK{wN*D?jmm:j0xmY ̌|n8ο:A2kڢ뾇}јY:V@Ѹ)U\3|3BlO(R@]2(7Ic):}{ <Fodꔪľ8sqk ؉x{e`o]iiKT{[s1XOR\NKW(f#ȞD:=2ZEݻ/u X?jmm:"ԁ37fNHS_  $Y]=9@BV@Ѹ):P ~T#136Bk3Myh߾#2-msn~^)VMPfNHSWȠ T;}h3u ]kފM/G)ɼ0xm/u@Z8~̌HK sdP*L;oOo?u m4 R,sxo}7w Xݔ`@:HK8p "@{;&է>ќb {q*b#TB*Dm)"\o .W쎤|~NlFlܱoߍ~SO1]r3j*qy|GQMǩw@PalFz p$nYUS2b6c0ݽS['l"f_(| {oV]-"2"` /ۋFzp~?Y^)OopMqy|~)hb(V9-yӭF+$'?Տ?I+GxNL1s%%(,=n/Z9-V?kXUcr֏D5Ԁ ,n/6{"l܂=ooj{a_?ٌ[e1br֏('5#(|GE#[K=ao}<ŭA_/|V~`L mY IDAT^J#ˣۋޣ;[7쭯~iލo_{7nU9Q\Ŭ*SV =n/Z9 y~2߾}_.(|,߉j:N=X12hb(V9 j}n\f7}=~Y|#~9-_fULqy|$` 7"lalF#[K=ao}h}O~'XpLY?nuXK=M19YUAdE\&kS .br88O%(܉n/Z;cSOx)U1㣸<> pYqpyg+T8&g<>rtz&($wqFzfUL~` Bk饞qLA^idyla䝭sV poE\,y9Ǭ*SU2Rhb0Z;S% "*A`4 P;aN/AY^lEJ=Dd8A`%dh<͇߉N="2FPX9yg;6f< s8 +VZ4s`%<SAv{y(.*Q NEdn l~饞K*19QsV ghd<,#./ br8&g}e^ X1eஔA\E1"3*+QM̪2,^Jَlq`f?v4ԳnLUD9XDd eȚڋ=4۩g|bx\4]Ĭ*Sxe2kvqvhvROVT9DU\F9bpUqtzu\d͍;[g5l8]D5G9H= I5#[o?oSG5G1}ůgk6ErtWoe"(ۑ57""Z{|}`U8xl>}oVQ.|ԝ +hFdO3b4r4YU>|s18] "(/h""[{=n&BU O_stt ܱi""v4^_/ <~zQ%"bVQ.^'YV X۟4Y"fUSMQMǟbxegAgp3ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBP&ejBPs2HB P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!MVӬ IDATLe&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P;w 0_P`B(0!Le&2B P`B(0!Le&2B P`B(0!Le&2B P`B(0!h}2Cn ;IENDB`pyo3/CITATION.cff0000644000175000017500000000044315105742312013167 0ustar bdrungbdrungcff-version: 1.2.0 title: PyO3 message: >- If you use this software as part of a publication and wish to cite it, please use the metadata from this file. type: software authors: - name: PyO3 Project and Contributors website: https://github.com/PyO3 license: - Apache-2.0 - MIT pyo3/build.rs0000644000175000017500000000420115105742312012736 0ustar bdrungbdrunguse std::env; use pyo3_build_config::pyo3_build_script_impl::{cargo_env_var, errors::Result}; use pyo3_build_config::{ add_python_framework_link_args, bail, print_feature_cfgs, InterpreterConfig, }; fn ensure_auto_initialize_ok(interpreter_config: &InterpreterConfig) -> Result<()> { if cargo_env_var("CARGO_FEATURE_AUTO_INITIALIZE").is_some() && !interpreter_config.shared { bail!( "The `auto-initialize` feature is enabled, but your python installation only supports \ embedding the Python interpreter statically. If you are attempting to run tests, or a \ binary which is okay to link dynamically, install a Python distribution which ships \ with the Python shared library.\n\ \n\ Embedding the Python interpreter statically does not yet have first-class support in \ PyO3. If you are sure you intend to do this, disable the `auto-initialize` feature.\n\ \n\ For more information, see \ https://pyo3.rs/v{pyo3_version}/\ building-and-distribution.html#embedding-python-in-rust", pyo3_version = env::var("CARGO_PKG_VERSION").unwrap() ); } Ok(()) } /// Prepares the PyO3 crate for compilation. /// /// This loads the config from pyo3-build-config and then makes some additional checks to improve UX /// for users. /// /// Emits the cargo configuration based on this config as well as a few checks of the Rust compiler /// version to enable features which aren't supported on MSRV. fn configure_pyo3() -> Result<()> { let interpreter_config = pyo3_build_config::get(); ensure_auto_initialize_ok(interpreter_config)?; for cfg in interpreter_config.build_script_outputs() { println!("{cfg}") } // Emit cfgs like `invalid_from_utf8_lint` print_feature_cfgs(); // Make `cargo test` etc work on macOS with Xcode bundled Python add_python_framework_link_args(); Ok(()) } fn main() { pyo3_build_config::print_expected_cfgs(); if let Err(e) = configure_pyo3() { eprintln!("error: {}", e.report()); std::process::exit(1) } } pyo3/tests/0000775000175000017500000000000015105742312012440 5ustar bdrungbdrungpyo3/tests/test_bytes.rs0000644000175000017500000000243615105742312015176 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::PyBytes; #[path = "../src/tests/common.rs"] mod common; #[pyfunction] fn bytes_pybytes_conversion(bytes: &[u8]) -> &[u8] { bytes } #[test] fn test_pybytes_bytes_conversion() { Python::with_gil(|py| { let f = wrap_pyfunction!(bytes_pybytes_conversion)(py).unwrap(); py_assert!(py, f, "f(b'Hello World') == b'Hello World'"); }); } #[pyfunction] fn bytes_vec_conversion(py: Python<'_>, bytes: Vec) -> Bound<'_, PyBytes> { PyBytes::new(py, bytes.as_slice()) } #[test] fn test_pybytes_vec_conversion() { Python::with_gil(|py| { let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap(); py_assert!(py, f, "f(b'Hello World') == b'Hello World'"); }); } #[test] fn test_bytearray_vec_conversion() { Python::with_gil(|py| { let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap(); py_assert!(py, f, "f(bytearray(b'Hello World')) == b'Hello World'"); }); } #[test] fn test_py_as_bytes() { let pyobj: pyo3::Py = Python::with_gil(|py| pyo3::types::PyBytes::new(py, b"abc").unbind()); let data = Python::with_gil(|py| pyobj.as_bytes(py)); assert_eq!(data, b"abc"); Python::with_gil(move |_py| drop(pyobj)); } pyo3/tests/test_static_slots.rs0000644000175000017500000000266115105742312016563 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::exceptions::PyIndexError; use pyo3::prelude::*; use pyo3::types::IntoPyDict; use pyo3::py_run; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct Count5(); #[pymethods] impl Count5 { #[new] fn new() -> Self { Self() } #[staticmethod] fn __len__() -> usize { 5 } #[staticmethod] fn __getitem__(idx: isize) -> PyResult { if idx < 0 { Err(PyIndexError::new_err("Count5 cannot count backwards")) } else if idx > 4 { Err(PyIndexError::new_err("Count5 cannot count higher than 5")) } else { Ok(idx as f64 + 1.0) } } } /// Return a dict with `s = Count5()`. fn test_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { let d = [("Count5", py.get_type::())] .into_py_dict(py) .unwrap(); // Though we can construct `s` in Rust, let's test `__new__` works. py_run!(py, *d, "s = Count5()"); d } #[test] fn test_len() { Python::with_gil(|py| { let d = test_dict(py); py_assert!(py, *d, "len(s) == 5"); }); } #[test] fn test_getitem() { Python::with_gil(|py| { let d = test_dict(py); py_assert!(py, *d, "s[4] == 5.0"); }); } #[test] fn test_list() { Python::with_gil(|py| { let d = test_dict(py); py_assert!(py, *d, "list(s) == [1.0, 2.0, 3.0, 4.0, 5.0]"); }); } pyo3/tests/test_buffer.rs0000644000175000017500000001003715105742312015315 0ustar bdrungbdrung#![cfg(feature = "macros")] #![cfg(any(not(Py_LIMITED_API), Py_3_11))] #![cfg_attr(not(cargo_toml_lints), warn(unsafe_op_in_unsafe_fn))] use pyo3::{buffer::PyBuffer, exceptions::PyBufferError, ffi, prelude::*}; use std::{ os::raw::{c_int, c_void}, ptr, }; #[macro_use] #[path = "../src/tests/common.rs"] mod common; enum TestGetBufferError { NullShape, NullStrides, IncorrectItemSize, IncorrectFormat, IncorrectAlignment, } #[pyclass] struct TestBufferErrors { buf: Vec, error: Option, } #[pymethods] impl TestBufferErrors { unsafe fn __getbuffer__( slf: PyRefMut<'_, Self>, view: *mut ffi::Py_buffer, flags: c_int, ) -> PyResult<()> { if view.is_null() { return Err(PyBufferError::new_err("View is null")); } if (flags & ffi::PyBUF_WRITABLE) == ffi::PyBUF_WRITABLE { return Err(PyBufferError::new_err("Object is not writable")); } let bytes = &slf.buf; unsafe { (*view).buf = bytes.as_ptr() as *mut c_void; (*view).len = bytes.len() as isize; (*view).readonly = 1; (*view).itemsize = std::mem::size_of::() as isize; let msg = ffi::c_str!("I"); (*view).format = msg.as_ptr() as *mut _; (*view).ndim = 1; (*view).shape = &mut (*view).len; (*view).strides = &mut (*view).itemsize; (*view).suboffsets = ptr::null_mut(); (*view).internal = ptr::null_mut(); if let Some(err) = &slf.error { use TestGetBufferError::*; match err { NullShape => { (*view).shape = std::ptr::null_mut(); } NullStrides => { (*view).strides = std::ptr::null_mut(); } IncorrectItemSize => { (*view).itemsize += 1; } IncorrectFormat => { (*view).format = ffi::c_str!("B").as_ptr() as _; } IncorrectAlignment => (*view).buf = (*view).buf.add(1), } } (*view).obj = slf.into_ptr(); } Ok(()) } } #[test] fn test_get_buffer_errors() { Python::with_gil(|py| { let instance = Py::new( py, TestBufferErrors { buf: vec![0, 1, 2, 3], error: None, }, ) .unwrap(); assert!(PyBuffer::::get(instance.bind(py)).is_ok()); instance.borrow_mut(py).error = Some(TestGetBufferError::NullShape); assert_eq!( PyBuffer::::get(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: shape is null" ); instance.borrow_mut(py).error = Some(TestGetBufferError::NullStrides); assert_eq!( PyBuffer::::get(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: strides is null" ); instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectItemSize); assert_eq!( PyBuffer::::get(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: buffer contents are not compatible with u32" ); instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectFormat); assert_eq!( PyBuffer::::get(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: buffer contents are not compatible with u32" ); instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectAlignment); assert_eq!( PyBuffer::::get(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: buffer contents are insufficiently aligned for u32" ); }); } pyo3/tests/test_class_attributes.rs0000644000175000017500000001774315105742312017432 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct Foo { #[pyo3(get)] x: i32, } #[pyclass] struct Bar { #[pyo3(get)] x: i32, } #[pymethods] impl Foo { #[classattr] const MY_CONST: &'static str = "foobar"; #[classattr] #[pyo3(name = "RENAMED_CONST")] const MY_CONST_2: &'static str = "foobar_2"; #[classattr] fn a() -> i32 { 5 } #[classattr] #[pyo3(name = "B")] fn b() -> String { "bar".to_string() } #[classattr] fn bar() -> Bar { Bar { x: 2 } } #[classattr] fn a_foo() -> Foo { Foo { x: 1 } } #[classattr] fn a_foo_with_py(py: Python<'_>) -> Py { Py::new(py, Foo { x: 1 }).unwrap() } } #[test] fn class_attributes() { Python::with_gil(|py| { let foo_obj = py.get_type::(); py_assert!(py, foo_obj, "foo_obj.MY_CONST == 'foobar'"); py_assert!(py, foo_obj, "foo_obj.RENAMED_CONST == 'foobar_2'"); py_assert!(py, foo_obj, "foo_obj.a == 5"); py_assert!(py, foo_obj, "foo_obj.B == 'bar'"); py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1"); py_assert!(py, foo_obj, "foo_obj.a_foo_with_py.x == 1"); }); } #[test] fn class_attributes_mutable() { #[pyclass] struct Foo {} #[pymethods] impl Foo { #[classattr] const MY_CONST: &'static str = "foobar"; #[classattr] fn a() -> i32 { 5 } } Python::with_gil(|py| { let obj = py.get_type::(); py_run!(py, obj, "obj.MY_CONST = 'BAZ'"); py_run!(py, obj, "obj.a = 42"); py_assert!(py, obj, "obj.MY_CONST == 'BAZ'"); py_assert!(py, obj, "obj.a == 42"); }); } #[test] #[cfg(any(Py_3_14, all(Py_3_10, not(Py_LIMITED_API))))] fn immutable_type_object() { #[pyclass(immutable_type)] struct ImmutableType {} #[pymethods] impl ImmutableType { #[classattr] const MY_CONST: &'static str = "foobar"; #[classattr] fn a() -> i32 { 5 } } #[pyclass(immutable_type)] enum SimpleImmutable { Variant = 42, } #[pyclass(immutable_type)] enum ComplexImmutable { Variant(u32), } Python::with_gil(|py| { let obj = py.get_type::(); py_expect_exception!(py, obj, "obj.MY_CONST = 'FOOBAR'", PyTypeError); py_expect_exception!(py, obj, "obj.a = 6", PyTypeError); let obj = py.get_type::(); py_expect_exception!(py, obj, "obj.Variant = 0", PyTypeError); let obj = py.get_type::(); py_expect_exception!(py, obj, "obj.Variant = 0", PyTypeError); }); } #[pymethods] impl Bar { #[classattr] fn a_foo() -> Foo { Foo { x: 3 } } } #[test] fn recursive_class_attributes() { Python::with_gil(|py| { let foo_obj = py.get_type::(); let bar_obj = py.get_type::(); py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1"); py_assert!(py, foo_obj, "foo_obj.bar.x == 2"); py_assert!(py, bar_obj, "bar_obj.a_foo.x == 3"); }); } #[test] fn test_fallible_class_attribute() { use pyo3::{exceptions::PyValueError, types::PyString}; struct CaptureStdErr<'py> { oldstderr: Bound<'py, PyAny>, string_io: Bound<'py, PyAny>, } impl<'py> CaptureStdErr<'py> { fn new(py: Python<'py>) -> PyResult { let sys = py.import("sys")?; let oldstderr = sys.getattr("stderr")?; let string_io = py.import("io")?.getattr("StringIO")?.call0()?; sys.setattr("stderr", &string_io)?; Ok(Self { oldstderr, string_io, }) } fn reset(self) -> PyResult { let py = self.string_io.py(); let payload = self .string_io .getattr("getvalue")? .call0()? .downcast::()? .to_cow()? .into_owned(); let sys = py.import("sys")?; sys.setattr("stderr", self.oldstderr)?; Ok(payload) } } #[pyclass] struct BrokenClass; #[pymethods] impl BrokenClass { #[classattr] fn fails_to_init() -> PyResult { Err(PyValueError::new_err("failed to create class attribute")) } } Python::with_gil(|py| { let stderr = CaptureStdErr::new(py).unwrap(); assert!(std::panic::catch_unwind(|| py.get_type::()).is_err()); assert_eq!( stderr.reset().unwrap().trim(), "\ ValueError: failed to create class attribute The above exception was the direct cause of the following exception: RuntimeError: An error occurred while initializing `BrokenClass.fails_to_init` The above exception was the direct cause of the following exception: RuntimeError: An error occurred while initializing class BrokenClass" ) }); } #[pyclass(get_all, set_all, rename_all = "camelCase")] struct StructWithRenamedFields { first_field: bool, second_field: u8, #[pyo3(name = "third_field")] fourth_field: bool, } #[pymethods] impl StructWithRenamedFields { #[new] fn new() -> Self { Self { first_field: true, second_field: 5, fourth_field: false, } } } #[test] fn test_renaming_all_struct_fields() { use pyo3::types::PyBool; Python::with_gil(|py| { let struct_class = py.get_type::(); let struct_obj = struct_class.call0().unwrap(); assert!(struct_obj .setattr("firstField", PyBool::new(py, false)) .is_ok()); py_assert!(py, struct_obj, "struct_obj.firstField == False"); py_assert!(py, struct_obj, "struct_obj.secondField == 5"); assert!(struct_obj .setattr("third_field", PyBool::new(py, true)) .is_ok()); py_assert!(py, struct_obj, "struct_obj.third_field == True"); }); } macro_rules! test_case { ($struct_name: ident, $rule: literal, $field_name: ident, $renamed_field_name: literal, $test_name: ident) => { #[pyclass(get_all, set_all, rename_all = $rule)] #[allow(non_snake_case)] struct $struct_name { $field_name: u8, } #[pymethods] impl $struct_name { #[new] fn new() -> Self { Self { $field_name: 0 } } } #[test] fn $test_name() { //use pyo3::types::PyInt; Python::with_gil(|py| { let struct_class = py.get_type::<$struct_name>(); let struct_obj = struct_class.call0().unwrap(); assert!(struct_obj.setattr($renamed_field_name, 2).is_ok()); let attr = struct_obj.getattr($renamed_field_name).unwrap(); assert_eq!(2, attr.extract::().unwrap()); }); } }; } test_case!( LowercaseTest, "lowercase", fieldOne, "fieldone", test_rename_all_lowercase ); test_case!( CamelCaseTest, "camelCase", field_one, "fieldOne", test_rename_all_camel_case ); test_case!( KebabCaseTest, "kebab-case", field_one, "field-one", test_rename_all_kebab_case ); test_case!( PascalCaseTest, "PascalCase", field_one, "FieldOne", test_rename_all_pascal_case ); test_case!( ScreamingSnakeCaseTest, "SCREAMING_SNAKE_CASE", field_one, "FIELD_ONE", test_rename_all_screaming_snake_case ); test_case!( ScreamingKebabCaseTest, "SCREAMING-KEBAB-CASE", field_one, "FIELD-ONE", test_rename_all_screaming_kebab_case ); test_case!( SnakeCaseTest, "snake_case", fieldOne, "field_one", test_rename_all_snake_case ); test_case!( UppercaseTest, "UPPERCASE", fieldOne, "FIELDONE", test_rename_all_uppercase ); pyo3/tests/test_append_to_inittab.rs0000644000175000017500000000221015105742312017521 0ustar bdrungbdrung#![cfg(all(feature = "macros", not(PyPy)))] use pyo3::prelude::*; #[pyfunction] fn foo() -> usize { 123 } #[pymodule] fn module_fn_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(foo, m)?)?; Ok(()) } #[pymodule] mod module_mod_with_functions { #[pymodule_export] use super::foo; } #[cfg(not(any(PyPy, GraalPy)))] #[test] fn test_module_append_to_inittab() { use pyo3::{append_to_inittab, ffi}; append_to_inittab!(module_fn_with_functions); append_to_inittab!(module_mod_with_functions); Python::with_gil(|py| { py.run( ffi::c_str!( r#" import module_fn_with_functions assert module_fn_with_functions.foo() == 123 "# ), None, None, ) .map_err(|e| e.display(py)) .unwrap(); }); Python::with_gil(|py| { py.run( ffi::c_str!( r#" import module_mod_with_functions assert module_mod_with_functions.foo() == 123 "# ), None, None, ) .map_err(|e| e.display(py)) .unwrap(); }); } pyo3/tests/test_module.rs0000644000175000017500000003077415105742312015343 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::PyString; use pyo3::types::{IntoPyDict, PyDict, PyTuple}; use pyo3::BoundObject; use pyo3_ffi::c_str; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct AnonClass {} #[pyclass] struct ValueClass { value: usize, } #[pymethods] impl ValueClass { #[new] fn new(value: usize) -> ValueClass { ValueClass { value } } } #[pyclass(module = "module")] struct LocatedClass {} #[pyfunction] /// Doubles the given value fn double(x: usize) -> usize { x * 2 } /// This module is implemented in Rust. #[pymodule(gil_used = false)] fn module_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m)] #[pyo3(name = "no_parameters")] fn function_with_name() -> usize { 42 } #[pyfn(m)] #[pyo3(pass_module)] fn with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult> { module.name() } #[pyfn(m)] fn double_value(v: &ValueClass) -> usize { v.value * 2 } m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add("foo", "bar")?; m.add_function(wrap_pyfunction!(double, m)?)?; m.add("also_double", wrap_pyfunction!(double, m)?)?; Ok(()) } #[test] fn test_module_with_functions() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let d = [( "module_with_functions", wrap_pymodule!(module_with_functions)(py), )] .into_py_dict(py) .unwrap(); py_assert!( py, *d, "module_with_functions.__doc__ == 'This module is implemented in Rust.'" ); py_assert!(py, *d, "module_with_functions.no_parameters() == 42"); py_assert!(py, *d, "module_with_functions.foo == 'bar'"); py_assert!(py, *d, "module_with_functions.AnonClass != None"); py_assert!(py, *d, "module_with_functions.LocatedClass != None"); py_assert!( py, *d, "module_with_functions.LocatedClass.__module__ == 'module'" ); py_assert!(py, *d, "module_with_functions.double(3) == 6"); py_assert!( py, *d, "module_with_functions.double.__doc__ == 'Doubles the given value'" ); py_assert!(py, *d, "module_with_functions.also_double(3) == 6"); py_assert!( py, *d, "module_with_functions.also_double.__doc__ == 'Doubles the given value'" ); py_assert!( py, *d, "module_with_functions.double_value(module_with_functions.ValueClass(1)) == 2" ); py_assert!( py, *d, "module_with_functions.with_module() == 'module_with_functions'" ); }); } /// This module uses a legacy two-argument module function. #[pymodule] fn module_with_explicit_py_arg(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(double, m)?)?; Ok(()) } #[test] fn test_module_with_explicit_py_arg() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let d = [( "module_with_explicit_py_arg", wrap_pymodule!(module_with_explicit_py_arg)(py), )] .into_py_dict(py) .unwrap(); py_assert!(py, *d, "module_with_explicit_py_arg.double(3) == 6"); }); } #[pymodule(name = "other_name")] fn some_name(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add("other_name", "other_name")?; Ok(()) } #[test] fn test_module_renaming() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let d = [("different_name", wrap_pymodule!(some_name)(py))] .into_py_dict(py) .unwrap(); py_run!(py, *d, "assert different_name.__name__ == 'other_name'"); }); } #[test] fn test_module_from_code_bound() { Python::with_gil(|py| { let adder_mod = PyModule::from_code( py, c_str!("def add(a,b):\n\treturn a+b"), c_str!("adder_mod.py"), &common::generate_unique_module_name("adder_mod"), ) .expect("Module code should be loaded"); let add_func = adder_mod .getattr("add") .expect("Add function should be in the module"); let ret_value: i32 = add_func .call1((1, 2)) .expect("A value should be returned") .extract() .expect("The value should be able to be converted to an i32"); adder_mod.gil_used(false).expect("Disabling the GIL failed"); assert_eq!(ret_value, 3); }); } #[pyfunction] fn r#move() -> usize { 42 } #[pymodule] fn raw_ident_module(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(r#move, module)?) } #[test] fn test_raw_idents() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let module = wrap_pymodule!(raw_ident_module)(py); py_assert!(py, module, "module.move() == 42"); }); } #[pyfunction] #[pyo3(name = "foobar")] fn custom_named_fn() -> usize { 42 } #[test] fn test_custom_names() { #[pymodule] fn custom_names(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?; Ok(()) } Python::with_gil(|py| { let module = pyo3::wrap_pymodule!(custom_names)(py); py_assert!(py, module, "not hasattr(module, 'custom_named_fn')"); py_assert!(py, module, "module.foobar() == 42"); }); } #[test] fn test_module_dict() { #[pymodule] fn module_dict(m: &Bound<'_, PyModule>) -> PyResult<()> { m.dict().set_item("yay", "me")?; Ok(()) } Python::with_gil(|py| { let module = pyo3::wrap_pymodule!(module_dict)(py); py_assert!(py, module, "module.yay == 'me'"); }); } #[test] fn test_module_dunder_all() { Python::with_gil(|py| { #[pymodule] fn dunder_all(m: &Bound<'_, PyModule>) -> PyResult<()> { m.dict().set_item("yay", "me")?; m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?; Ok(()) } let module = pyo3::wrap_pymodule!(dunder_all)(py); py_assert!(py, module, "module.__all__ == ['foobar']"); }); } #[pyfunction] fn subfunction() -> String { "Subfunction".to_string() } fn submodule(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(subfunction, module)?)?; Ok(()) } #[pymodule] fn submodule_with_init_fn(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(subfunction, module)?)?; Ok(()) } #[pyfunction] fn superfunction() -> String { "Superfunction".to_string() } #[pymodule] fn supermodule(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(superfunction, module)?)?; let module_to_add = PyModule::new(module.py(), "submodule")?; submodule(&module_to_add)?; module.add_submodule(&module_to_add)?; let module_to_add = PyModule::new(module.py(), "submodule_with_init_fn")?; submodule_with_init_fn(&module_to_add)?; module.add_submodule(&module_to_add)?; Ok(()) } #[test] fn test_module_nesting() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let supermodule = wrap_pymodule!(supermodule)(py); py_assert!( py, supermodule, "supermodule.superfunction() == 'Superfunction'" ); py_assert!( py, supermodule, "supermodule.submodule.subfunction() == 'Subfunction'" ); py_assert!( py, supermodule, "supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'" ); }); } // Test that argument parsing specification works for pyfunctions #[pyfunction(signature = (a=5, *args))] fn ext_vararg_fn(py: Python<'_>, a: i32, args: &Bound<'_, PyTuple>) -> PyResult { [ a.into_pyobject(py)?.into_any().into_bound(), args.as_any().clone(), ] .into_pyobject(py) .map(Bound::unbind) } #[pymodule] fn vararg_module(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m, signature = (a=5, *args))] fn int_vararg_fn(py: Python<'_>, a: i32, args: &Bound<'_, PyTuple>) -> PyResult { ext_vararg_fn(py, a, args) } m.add_function(wrap_pyfunction!(ext_vararg_fn, m)?).unwrap(); Ok(()) } #[test] fn test_vararg_module() { Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(vararg_module)(py); py_assert!(py, m, "m.ext_vararg_fn() == [5, ()]"); py_assert!(py, m, "m.ext_vararg_fn(1, 2) == [1, (2,)]"); py_assert!(py, m, "m.int_vararg_fn() == [5, ()]"); py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]"); }); } #[test] fn test_module_with_constant() { // Regression test for #1102 #[pymodule] fn module_with_constant(m: &Bound<'_, PyModule>) -> PyResult<()> { const ANON: AnonClass = AnonClass {}; m.add("ANON", ANON)?; m.add_class::()?; Ok(()) } Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(module_with_constant)(py); py_assert!(py, m, "isinstance(m.ANON, m.AnonClass)"); }); } #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult> { module.name() } #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module_owned( module: Py, py: Python<'_>, ) -> PyResult> { module.bind(py).name() } #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module_and_py<'py>( module: &Bound<'py, PyModule>, _python: Python<'py>, ) -> PyResult> { module.name() } #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module_and_arg<'py>( module: &Bound<'py, PyModule>, string: String, ) -> PyResult<(Bound<'py, PyString>, String)> { module.name().map(|s| (s, string)) } #[pyfunction(signature = (string="foo"))] #[pyo3(pass_module)] fn pyfunction_with_module_and_default_arg<'py>( module: &Bound<'py, PyModule>, string: &str, ) -> PyResult<(Bound<'py, PyString>, String)> { module.name().map(|s| (s, string.into())) } #[pyfunction(signature = (*args, **kwargs))] #[pyo3(pass_module)] fn pyfunction_with_module_and_args_kwargs<'py>( module: &Bound<'py, PyModule>, args: &Bound<'py, PyTuple>, kwargs: Option<&Bound<'py, PyDict>>, ) -> PyResult<(Bound<'py, PyString>, usize, Option)> { module .name() .map(|s| (s, args.len(), kwargs.map(|d| d.len()))) } #[pymodule] fn module_with_functions_with_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_owned, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_and_py, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_and_arg, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_and_default_arg, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_and_args_kwargs, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?; Ok(()) } #[test] fn test_module_functions_with_module() { Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py); py_assert!( py, m, "m.pyfunction_with_module() == 'module_with_functions_with_module'" ); py_assert!( py, m, "m.pyfunction_with_module_owned() == 'module_with_functions_with_module'" ); py_assert!( py, m, "m.pyfunction_with_module_and_py() == 'module_with_functions_with_module'" ); py_assert!( py, m, "m.pyfunction_with_module_and_default_arg() \ == ('module_with_functions_with_module', 'foo')" ); py_assert!( py, m, "m.pyfunction_with_module_and_args_kwargs(1, x=1, y=2) \ == ('module_with_functions_with_module', 1, 2)" ); }); } #[test] fn test_module_doc_hidden() { #[doc(hidden)] #[allow(clippy::unnecessary_wraps)] #[pymodule] fn my_module(_m: &Bound<'_, PyModule>) -> PyResult<()> { Ok(()) } Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(my_module)(py); py_assert!(py, m, "m.__doc__ == ''"); }) } pyo3/tests/test_string.rs0000644000175000017500000000102215105742312015344 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; #[path = "../src/tests/common.rs"] mod common; #[pyfunction] fn take_str(_s: &str) {} #[test] fn test_unicode_encode_error() { Python::with_gil(|py| { let take_str = wrap_pyfunction!(take_str)(py).unwrap(); py_expect_exception!( py, take_str, "take_str('\\ud800')", PyUnicodeEncodeError, "'utf-8' codec can't encode character '\\ud800' in position 0: surrogates not allowed" ); }); } pyo3/tests/test_macro_docs.rs0000644000175000017500000000157115105742312016160 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::IntoPyDict; #[macro_use] #[path = "../src/tests/common.rs"] mod common; #[pyclass] /// The MacroDocs class. #[doc = concat!("Some macro ", "class ", "docs.")] /// A very interesting type! struct MacroDocs {} #[pymethods] impl MacroDocs { #[doc = concat!("A macro ", "example.")] /// With mixed doc types. fn macro_doc(&self) {} } #[test] fn meth_doc() { Python::with_gil(|py| { let d = [("C", py.get_type::())] .into_py_dict(py) .unwrap(); py_assert!( py, *d, "C.__doc__ == 'The MacroDocs class.\\nSome macro class docs.\\nA very interesting type!'" ); py_assert!( py, *d, "C.macro_doc.__doc__ == 'A macro example.\\nWith mixed doc types.'" ); }); } pyo3/tests/test_buffer_protocol.rs0000644000175000017500000001220115105742312017231 0ustar bdrungbdrung#![cfg(feature = "macros")] #![cfg(any(not(Py_LIMITED_API), Py_3_11))] #![cfg_attr(not(cargo_toml_lints), warn(unsafe_op_in_unsafe_fn))] use pyo3::buffer::PyBuffer; use pyo3::exceptions::PyBufferError; use pyo3::ffi; use pyo3::prelude::*; use pyo3::types::IntoPyDict; use std::ffi::CString; use std::os::raw::{c_int, c_void}; use std::ptr; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct TestBufferClass { vec: Vec, drop_called: Arc, } #[pymethods] impl TestBufferClass { unsafe fn __getbuffer__( slf: Bound<'_, Self>, view: *mut ffi::Py_buffer, flags: c_int, ) -> PyResult<()> { unsafe { fill_view_from_readonly_data(view, flags, &slf.borrow().vec, slf.into_any()) } } unsafe fn __releasebuffer__(&self, view: *mut ffi::Py_buffer) { // Release memory held by the format string drop(unsafe { CString::from_raw((*view).format) }); } } impl Drop for TestBufferClass { fn drop(&mut self) { print!("dropped"); self.drop_called.store(true, Ordering::Relaxed); } } #[test] fn test_buffer() { let drop_called = Arc::new(AtomicBool::new(false)); Python::with_gil(|py| { let instance = Py::new( py, TestBufferClass { vec: vec![b' ', b'2', b'3'], drop_called: drop_called.clone(), }, ) .unwrap(); let env = [("ob", instance)].into_py_dict(py).unwrap(); py_assert!(py, *env, "bytes(ob) == b' 23'"); }); assert!(drop_called.load(Ordering::Relaxed)); } #[test] fn test_buffer_referenced() { let drop_called = Arc::new(AtomicBool::new(false)); let buf = { let input = vec![b' ', b'2', b'3']; Python::with_gil(|py| { let instance = TestBufferClass { vec: input.clone(), drop_called: drop_called.clone(), } .into_pyobject(py) .unwrap(); let buf = PyBuffer::::get(&instance).unwrap(); assert_eq!(buf.to_vec(py).unwrap(), input); drop(instance); buf }) }; assert!(!drop_called.load(Ordering::Relaxed)); Python::with_gil(|_| { drop(buf); }); assert!(drop_called.load(Ordering::Relaxed)); } #[test] #[cfg(all(Py_3_8, not(Py_GIL_DISABLED)))] // sys.unraisablehook not available until Python 3.8 fn test_releasebuffer_unraisable_error() { use common::UnraisableCapture; use pyo3::exceptions::PyValueError; #[pyclass] struct ReleaseBufferError {} #[pymethods] impl ReleaseBufferError { unsafe fn __getbuffer__( slf: Bound<'_, Self>, view: *mut ffi::Py_buffer, flags: c_int, ) -> PyResult<()> { static BUF_BYTES: &[u8] = b"hello world"; unsafe { fill_view_from_readonly_data(view, flags, BUF_BYTES, slf.into_any()) } } unsafe fn __releasebuffer__(&self, _view: *mut ffi::Py_buffer) -> PyResult<()> { Err(PyValueError::new_err("oh dear")) } } Python::with_gil(|py| { let capture = UnraisableCapture::install(py); let instance = Py::new(py, ReleaseBufferError {}).unwrap(); let env = [("ob", instance.clone_ref(py))].into_py_dict(py).unwrap(); assert!(capture.borrow(py).capture.is_none()); py_assert!(py, *env, "bytes(ob) == b'hello world'"); let (err, object) = capture.borrow_mut(py).capture.take().unwrap(); assert_eq!(err.to_string(), "ValueError: oh dear"); assert!(object.is(&instance)); capture.borrow_mut(py).uninstall(py); }); } /// # Safety /// /// `view` must be a valid pointer to ffi::Py_buffer, or null /// `data` must outlive the Python lifetime of `owner` (i.e. data must be owned by owner, or data /// must be static data) unsafe fn fill_view_from_readonly_data( view: *mut ffi::Py_buffer, flags: c_int, data: &[u8], owner: Bound<'_, PyAny>, ) -> PyResult<()> { if view.is_null() { return Err(PyBufferError::new_err("View is null")); } if (flags & ffi::PyBUF_WRITABLE) == ffi::PyBUF_WRITABLE { return Err(PyBufferError::new_err("Object is not writable")); } unsafe { (*view).obj = owner.into_ptr(); (*view).buf = data.as_ptr() as *mut c_void; (*view).len = data.len() as isize; (*view).readonly = 1; (*view).itemsize = 1; (*view).format = if (flags & ffi::PyBUF_FORMAT) == ffi::PyBUF_FORMAT { let msg = CString::new("B").unwrap(); msg.into_raw() } else { ptr::null_mut() }; (*view).ndim = 1; (*view).shape = if (flags & ffi::PyBUF_ND) == ffi::PyBUF_ND { &mut (*view).len } else { ptr::null_mut() }; (*view).strides = if (flags & ffi::PyBUF_STRIDES) == ffi::PyBUF_STRIDES { &mut (*view).itemsize } else { ptr::null_mut() }; (*view).suboffsets = ptr::null_mut(); (*view).internal = ptr::null_mut(); } Ok(()) } pyo3/tests/test_variable_arguments.rs0000644000175000017500000000226615105742312017723 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[staticmethod] #[pyo3(signature = (*args))] fn test_args(args: Bound<'_, PyTuple>) -> Bound<'_, PyTuple> { args } #[staticmethod] #[pyo3(signature = (**kwargs))] fn test_kwargs(kwargs: Option>) -> Option> { kwargs } } #[test] fn variable_args() { Python::with_gil(|py| { let my_obj = py.get_type::(); py_assert!(py, my_obj, "my_obj.test_args() == ()"); py_assert!(py, my_obj, "my_obj.test_args(1) == (1,)"); py_assert!(py, my_obj, "my_obj.test_args(1, 2) == (1, 2)"); }); } #[test] fn variable_kwargs() { Python::with_gil(|py| { let my_obj = py.get_type::(); py_assert!(py, my_obj, "my_obj.test_kwargs() == None"); py_assert!(py, my_obj, "my_obj.test_kwargs(test=1) == {'test': 1}"); py_assert!( py, my_obj, "my_obj.test_kwargs(test1=1, test2=2) == {'test1':1, 'test2':2}" ); }); } pyo3/tests/test_class_formatting.rs0000644000175000017500000001013215105742312017377 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use std::fmt::{Display, Formatter}; #[path = "../src/tests/common.rs"] mod common; #[pyclass(eq, str)] #[derive(Debug, PartialEq)] pub enum MyEnum2 { Variant, OtherVariant, } impl Display for MyEnum2 { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{self:?}") } } #[pyclass(eq, str)] #[derive(Debug, PartialEq)] pub enum MyEnum3 { #[pyo3(name = "AwesomeVariant")] Variant, OtherVariant, } impl Display for MyEnum3 { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let variant = match self { MyEnum3::Variant => "AwesomeVariant", MyEnum3::OtherVariant => "OtherVariant", }; write!(f, "MyEnum.{variant}") } } #[test] fn test_enum_class_fmt() { Python::with_gil(|py| { let var2 = Py::new(py, MyEnum2::Variant).unwrap(); let var3 = Py::new(py, MyEnum3::Variant).unwrap(); let var4 = Py::new(py, MyEnum3::OtherVariant).unwrap(); py_assert!(py, var2, "str(var2) == 'Variant'"); py_assert!(py, var3, "str(var3) == 'MyEnum.AwesomeVariant'"); py_assert!(py, var4, "str(var4) == 'MyEnum.OtherVariant'"); }) } #[pyclass(str = "X: {x}, Y: {y}, Z: {z}")] #[derive(PartialEq, Eq, Clone, PartialOrd)] pub struct Point { x: i32, y: i32, z: i32, } #[test] fn test_custom_struct_custom_str() { Python::with_gil(|py| { let var1 = Py::new(py, Point { x: 1, y: 2, z: 3 }).unwrap(); py_assert!(py, var1, "str(var1) == 'X: 1, Y: 2, Z: 3'"); }) } #[pyclass(str)] #[derive(PartialEq, Eq, Clone, PartialOrd)] pub struct Point2 { x: i32, y: i32, z: i32, } impl Display for Point2 { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "({}, {}, {})", self.x, self.y, self.z) } } #[test] fn test_struct_str() { Python::with_gil(|py| { let var1 = Py::new(py, Point2 { x: 1, y: 2, z: 3 }).unwrap(); py_assert!(py, var1, "str(var1) == '(1, 2, 3)'"); }) } #[pyclass(str)] #[derive(PartialEq, Debug)] enum ComplexEnumWithStr { A(u32), B { msg: String }, } impl Display for ComplexEnumWithStr { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{self:?}") } } #[test] fn test_custom_complex_enum_str() { Python::with_gil(|py| { let var1 = Py::new(py, ComplexEnumWithStr::A(45)).unwrap(); let var2 = Py::new( py, ComplexEnumWithStr::B { msg: "Hello".to_string(), }, ) .unwrap(); py_assert!(py, var1, "str(var1) == 'A(45)'"); py_assert!(py, var2, "str(var2) == 'B { msg: \"Hello\" }'"); }) } #[pyclass(str = "{0}, {1}, {2}")] #[derive(PartialEq)] struct Coord(u32, u32, u32); #[pyclass(str = "{{{0}, {1}, {2}}}")] #[derive(PartialEq)] struct Coord2(u32, u32, u32); #[test] fn test_str_representation_by_position() { Python::with_gil(|py| { let var1 = Py::new(py, Coord(1, 2, 3)).unwrap(); let var2 = Py::new(py, Coord2(1, 2, 3)).unwrap(); py_assert!(py, var1, "str(var1) == '1, 2, 3'"); py_assert!(py, var2, "str(var2) == '{1, 2, 3}'"); }) } #[pyclass(str = "name: {name}: {name}, idn: {idn:03} with message: {msg}")] #[derive(PartialEq, Debug)] struct Point4 { name: String, msg: String, idn: u32, } #[test] fn test_mixed_and_repeated_str_formats() { Python::with_gil(|py| { let var1 = Py::new( py, Point4 { name: "aaa".to_string(), msg: "hello".to_string(), idn: 1, }, ) .unwrap(); py_run!( py, var1, r#" assert str(var1) == 'name: aaa: aaa, idn: 001 with message: hello' "# ); }) } #[pyclass(str = "type: {r#type}")] struct Foo { r#type: u32, } #[test] fn test_raw_identifier_struct_custom_str() { Python::with_gil(|py| { let var1 = Py::new(py, Foo { r#type: 3 }).unwrap(); py_assert!(py, var1, "str(var1) == 'type: 3'"); }) } pyo3/tests/test_proto_methods.rs0000644000175000017500000005225315105742312016740 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::exceptions::{PyAttributeError, PyIndexError, PyValueError}; use pyo3::types::{PyDict, PyList, PyMapping, PySequence, PySlice, PyType}; use pyo3::{prelude::*, py_run}; use std::iter; use std::sync::Mutex; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct EmptyClass; #[pyclass] struct ExampleClass { #[pyo3(get, set)] value: i32, custom_attr: Option, } #[pymethods] impl ExampleClass { fn __getattr__(&self, py: Python<'_>, attr: &str) -> PyResult { if attr == "special_custom_attr" { Ok(self.custom_attr.into_pyobject(py)?.into_any().unbind()) } else { Err(PyAttributeError::new_err(attr.to_string())) } } fn __setattr__(&mut self, attr: &str, value: &Bound<'_, PyAny>) -> PyResult<()> { if attr == "special_custom_attr" { self.custom_attr = Some(value.extract()?); Ok(()) } else { Err(PyAttributeError::new_err(attr.to_string())) } } fn __delattr__(&mut self, attr: &str) -> PyResult<()> { if attr == "special_custom_attr" { self.custom_attr = None; Ok(()) } else { Err(PyAttributeError::new_err(attr.to_string())) } } fn __str__(&self) -> String { self.value.to_string() } fn __repr__(&self) -> String { format!("ExampleClass(value={})", self.value) } fn __hash__(&self) -> u64 { let i64_value: i64 = self.value.into(); i64_value as u64 } fn __bool__(&self) -> bool { self.value != 0 } } fn make_example(py: Python<'_>) -> Bound<'_, ExampleClass> { Bound::new( py, ExampleClass { value: 5, custom_attr: Some(20), }, ) .unwrap() } #[test] fn test_getattr() { Python::with_gil(|py| { let example_py = make_example(py); assert_eq!( example_py .getattr("value") .unwrap() .extract::() .unwrap(), 5, ); assert_eq!( example_py .getattr("special_custom_attr") .unwrap() .extract::() .unwrap(), 20, ); assert!(example_py .getattr("other_attr") .unwrap_err() .is_instance_of::(py)); }) } #[test] fn test_setattr() { Python::with_gil(|py| { let example_py = make_example(py); example_py.setattr("special_custom_attr", 15).unwrap(); assert_eq!( example_py .getattr("special_custom_attr") .unwrap() .extract::() .unwrap(), 15, ); }) } #[test] fn test_delattr() { Python::with_gil(|py| { let example_py = make_example(py); example_py.delattr("special_custom_attr").unwrap(); assert!(example_py.getattr("special_custom_attr").unwrap().is_none()); }) } #[test] fn test_str() { Python::with_gil(|py| { let example_py = make_example(py); assert_eq!(example_py.str().unwrap(), "5"); }) } #[test] fn test_repr() { Python::with_gil(|py| { let example_py = make_example(py); assert_eq!(example_py.repr().unwrap(), "ExampleClass(value=5)"); }) } #[test] fn test_hash() { Python::with_gil(|py| { let example_py = make_example(py); assert_eq!(example_py.hash().unwrap(), 5); }) } #[test] fn test_bool() { Python::with_gil(|py| { let example_py = make_example(py); assert!(example_py.is_truthy().unwrap()); example_py.borrow_mut().value = 0; assert!(!example_py.is_truthy().unwrap()); }) } #[pyclass] pub struct LenOverflow; #[pymethods] impl LenOverflow { fn __len__(&self) -> usize { (isize::MAX as usize) + 1 } } #[test] fn len_overflow() { Python::with_gil(|py| { let inst = Py::new(py, LenOverflow).unwrap(); py_expect_exception!(py, inst, "len(inst)", PyOverflowError); }); } #[pyclass] pub struct Mapping { values: Py, } #[pymethods] impl Mapping { fn __len__(&self, py: Python<'_>) -> usize { self.values.bind(py).len() } fn __getitem__<'py>(&self, key: &Bound<'py, PyAny>) -> PyResult> { let any: &Bound<'py, PyAny> = self.values.bind(key.py()); any.get_item(key) } fn __setitem__<'py>(&self, key: &Bound<'py, PyAny>, value: &Bound<'py, PyAny>) -> PyResult<()> { self.values.bind(key.py()).set_item(key, value) } fn __delitem__(&self, key: &Bound<'_, PyAny>) -> PyResult<()> { self.values.bind(key.py()).del_item(key) } } #[test] fn mapping() { Python::with_gil(|py| { PyMapping::register::(py).unwrap(); let inst = Py::new( py, Mapping { values: PyDict::new(py).into(), }, ) .unwrap(); let mapping: &Bound<'_, PyMapping> = inst.bind(py).downcast().unwrap(); py_assert!(py, inst, "len(inst) == 0"); py_run!(py, inst, "inst['foo'] = 'foo'"); py_assert!(py, inst, "inst['foo'] == 'foo'"); py_run!(py, inst, "del inst['foo']"); py_expect_exception!(py, inst, "inst['foo']", PyKeyError); // Default iteration will call __getitem__ with integer indices // which fails with a KeyError py_expect_exception!(py, inst, "[*inst] == []", PyKeyError, "0"); // check mapping protocol assert_eq!(mapping.len().unwrap(), 0); mapping.set_item(0, 5).unwrap(); assert_eq!(mapping.len().unwrap(), 1); assert_eq!(mapping.get_item(0).unwrap().extract::().unwrap(), 5); mapping.del_item(0).unwrap(); assert_eq!(mapping.len().unwrap(), 0); }); } #[derive(FromPyObject)] enum SequenceIndex<'py> { Integer(isize), Slice(Bound<'py, PySlice>), } #[pyclass] pub struct Sequence { values: Vec, } #[pymethods] impl Sequence { fn __len__(&self) -> usize { self.values.len() } fn __getitem__(&self, index: SequenceIndex<'_>, py: Python<'_>) -> PyResult { match index { SequenceIndex::Integer(index) => { let uindex = self.usize_index(index)?; self.values .get(uindex) .map(|o| o.clone_ref(py)) .ok_or_else(|| PyIndexError::new_err(index)) } // Just to prove that slicing can be implemented SequenceIndex::Slice(s) => Ok(s.into()), } } fn __setitem__(&mut self, index: isize, value: PyObject) -> PyResult<()> { let uindex = self.usize_index(index)?; self.values .get_mut(uindex) .map(|place| *place = value) .ok_or_else(|| PyIndexError::new_err(index)) } fn __delitem__(&mut self, index: isize) -> PyResult<()> { let uindex = self.usize_index(index)?; if uindex >= self.values.len() { Err(PyIndexError::new_err(index)) } else { self.values.remove(uindex); Ok(()) } } fn append(&mut self, value: PyObject) { self.values.push(value); } } impl Sequence { fn usize_index(&self, index: isize) -> PyResult { if index < 0 { let corrected_index = index + self.values.len() as isize; if corrected_index < 0 { Err(PyIndexError::new_err(index)) } else { Ok(corrected_index as usize) } } else { Ok(index as usize) } } } #[test] fn sequence() { Python::with_gil(|py| { PySequence::register::(py).unwrap(); let inst = Py::new(py, Sequence { values: vec![] }).unwrap(); let sequence: &Bound<'_, PySequence> = inst.bind(py).downcast().unwrap(); py_assert!(py, inst, "len(inst) == 0"); py_expect_exception!(py, inst, "inst[0]", PyIndexError); py_run!(py, inst, "inst.append('foo')"); py_assert!(py, inst, "inst[0] == 'foo'"); py_assert!(py, inst, "inst[-1] == 'foo'"); py_expect_exception!(py, inst, "inst[1]", PyIndexError); py_expect_exception!(py, inst, "inst[-2]", PyIndexError); py_assert!(py, inst, "[*inst] == ['foo']"); py_run!(py, inst, "del inst[0]"); py_expect_exception!(py, inst, "inst['foo']", PyTypeError); py_assert!(py, inst, "inst[0:2] == slice(0, 2)"); // check sequence protocol // we don't implement sequence length so that CPython doesn't attempt to correct negative // indices. assert!(sequence.len().is_err()); // however regular python len() works thanks to mp_len slot assert_eq!(inst.bind(py).len().unwrap(), 0); py_run!(py, inst, "inst.append(0)"); sequence.set_item(0, 5).unwrap(); assert_eq!(inst.bind(py).len().unwrap(), 1); assert_eq!(sequence.get_item(0).unwrap().extract::().unwrap(), 5); sequence.del_item(0).unwrap(); assert_eq!(inst.bind(py).len().unwrap(), 0); }); } #[pyclass] struct Iterator { iter: Mutex + Send>>, } #[pymethods] impl Iterator { fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(slf: PyRefMut<'_, Self>) -> Option { slf.iter.lock().unwrap().next() } } #[test] fn iterator() { Python::with_gil(|py| { let inst = Py::new( py, Iterator { iter: Mutex::new(Box::new(5..8)), }, ) .unwrap(); py_assert!(py, inst, "iter(inst) is inst"); py_assert!(py, inst, "list(inst) == [5, 6, 7]"); }); } #[pyclass] struct Callable; #[pymethods] impl Callable { fn __call__(&self, arg: i32) -> i32 { arg * 6 } } #[pyclass] struct NotCallable; #[test] fn callable() { Python::with_gil(|py| { let c = Py::new(py, Callable).unwrap(); py_assert!(py, c, "callable(c)"); py_assert!(py, c, "c(7) == 42"); let nc = Py::new(py, NotCallable).unwrap(); py_assert!(py, nc, "not callable(nc)"); }); } #[pyclass] #[derive(Debug)] struct SetItem { key: i32, val: i32, } #[pymethods] impl SetItem { fn __setitem__(&mut self, key: i32, val: i32) { self.key = key; self.val = val; } } #[test] fn setitem() { Python::with_gil(|py| { let c = Bound::new(py, SetItem { key: 0, val: 0 }).unwrap(); py_run!(py, c, "c[1] = 2"); { let c = c.borrow(); assert_eq!(c.key, 1); assert_eq!(c.val, 2); } py_expect_exception!(py, c, "del c[1]", PyNotImplementedError); }); } #[pyclass] struct DelItem { key: i32, } #[pymethods] impl DelItem { fn __delitem__(&mut self, key: i32) { self.key = key; } } #[test] fn delitem() { Python::with_gil(|py| { let c = Bound::new(py, DelItem { key: 0 }).unwrap(); py_run!(py, c, "del c[1]"); { let c = c.borrow(); assert_eq!(c.key, 1); } py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError); }); } #[pyclass] struct SetDelItem { val: Option, } #[pymethods] impl SetDelItem { fn __setitem__(&mut self, _key: i32, val: i32) { self.val = Some(val); } fn __delitem__(&mut self, _key: i32) { self.val = None; } } #[test] fn setdelitem() { Python::with_gil(|py| { let c = Bound::new(py, SetDelItem { val: None }).unwrap(); py_run!(py, c, "c[1] = 2"); { let c = c.borrow(); assert_eq!(c.val, Some(2)); } py_run!(py, c, "del c[1]"); let c = c.borrow(); assert_eq!(c.val, None); }); } #[pyclass] struct Contains {} #[pymethods] impl Contains { fn __contains__(&self, item: i32) -> bool { item >= 0 } } #[test] fn contains() { Python::with_gil(|py| { let c = Py::new(py, Contains {}).unwrap(); py_run!(py, c, "assert 1 in c"); py_run!(py, c, "assert -1 not in c"); py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError); }); } #[pyclass] struct GetItem {} #[pymethods] impl GetItem { fn __getitem__(&self, idx: &Bound<'_, PyAny>) -> PyResult<&'static str> { if let Ok(slice) = idx.downcast::() { let indices = slice.indices(1000)?; if indices.start == 100 && indices.stop == 200 && indices.step == 1 { return Ok("slice"); } } else if let Ok(idx) = idx.extract::() { if idx == 1 { return Ok("int"); } } Err(PyValueError::new_err("error")) } } #[test] fn test_getitem() { Python::with_gil(|py| { let ob = Py::new(py, GetItem {}).unwrap(); py_assert!(py, ob, "ob[1] == 'int'"); py_assert!(py, ob, "ob[100:200:1] == 'slice'"); }); } #[pyclass] struct ClassWithGetAttr { #[pyo3(get, set)] data: u32, } #[pymethods] impl ClassWithGetAttr { fn __getattr__(&self, _name: &str) -> u32 { self.data * 2 } } #[test] fn getattr_doesnt_override_member() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithGetAttr { data: 4 }).unwrap(); py_assert!(py, inst, "inst.data == 4"); py_assert!(py, inst, "inst.a == 8"); }); } #[pyclass] struct ClassWithGetAttribute { #[pyo3(get, set)] data: u32, } #[pymethods] impl ClassWithGetAttribute { fn __getattribute__(&self, _name: &str) -> u32 { self.data * 2 } } #[test] fn getattribute_overrides_member() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithGetAttribute { data: 4 }).unwrap(); py_assert!(py, inst, "inst.data == 8"); py_assert!(py, inst, "inst.y == 8"); }); } #[pyclass] struct ClassWithGetAttrAndGetAttribute; #[pymethods] impl ClassWithGetAttrAndGetAttribute { fn __getattribute__(&self, name: &str) -> PyResult { if name == "exists" { Ok(42) } else if name == "error" { Err(PyValueError::new_err("bad")) } else { Err(PyAttributeError::new_err("fallback")) } } fn __getattr__(&self, name: &str) -> PyResult { if name == "lucky" { Ok(57) } else { Err(PyAttributeError::new_err("no chance")) } } } #[test] fn getattr_and_getattribute() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithGetAttrAndGetAttribute).unwrap(); py_assert!(py, inst, "inst.exists == 42"); py_assert!(py, inst, "inst.lucky == 57"); py_expect_exception!(py, inst, "inst.error", PyValueError); py_expect_exception!(py, inst, "inst.unlucky", PyAttributeError); }); } /// Wraps a Python future and yield it once. #[pyclass] #[derive(Debug)] struct OnceFuture { future: PyObject, polled: bool, } #[pymethods] impl OnceFuture { #[new] fn new(future: PyObject) -> Self { OnceFuture { future, polled: false, } } fn __await__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__<'py>(&mut self, py: Python<'py>) -> Option<&Bound<'py, PyAny>> { if !self.polled { self.polled = true; Some(self.future.bind(py)) } else { None } } } #[test] #[cfg(not(target_arch = "wasm32"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop) fn test_await() { Python::with_gil(|py| { let once = py.get_type::(); let source = pyo3_ffi::c_str!( r#" import asyncio import sys async def main(): res = await Once(await asyncio.sleep(0.1)) assert res is None # For an odd error similar to https://bugs.python.org/issue38563 if sys.platform == "win32" and sys.version_info >= (3, 8, 0): asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.run(main()) "# ); let globals = PyModule::import(py, "__main__").unwrap().dict(); globals.set_item("Once", once).unwrap(); py.run(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); } #[pyclass] struct AsyncIterator { future: Option>, } #[pymethods] impl AsyncIterator { #[new] fn new(future: Py) -> Self { Self { future: Some(future), } } fn __aiter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __anext__(&mut self) -> Option> { self.future.take() } } #[test] #[cfg(not(target_arch = "wasm32"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop) fn test_anext_aiter() { Python::with_gil(|py| { let once = py.get_type::(); let source = pyo3_ffi::c_str!( r#" import asyncio import sys async def main(): count = 0 async for result in AsyncIterator(Once(await asyncio.sleep(0.1))): # The Once is awaited as part of the `async for` and produces None assert result is None count +=1 assert count == 1 # For an odd error similar to https://bugs.python.org/issue38563 if sys.platform == "win32" and sys.version_info >= (3, 8, 0): asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.run(main()) "# ); let globals = PyModule::import(py, "__main__").unwrap().dict(); globals.set_item("Once", once).unwrap(); globals .set_item("AsyncIterator", py.get_type::()) .unwrap(); py.run(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); } /// Increment the count when `__get__` is called. #[pyclass] struct DescrCounter { #[pyo3(get)] count: usize, } #[pymethods] impl DescrCounter { #[new] fn new() -> Self { DescrCounter { count: 0 } } /// Each access will increase the count fn __get__<'a>( mut slf: PyRefMut<'a, Self>, _instance: &Bound<'_, PyAny>, _owner: Option<&Bound<'_, PyType>>, ) -> PyRefMut<'a, Self> { slf.count += 1; slf } /// Allow assigning a new counter to the descriptor, copying the count across fn __set__(&self, _instance: &Bound<'_, PyAny>, new_value: &mut Self) { new_value.count = self.count; } /// Delete to reset the counter fn __delete__(&mut self, _instance: &Bound<'_, PyAny>) { self.count = 0; } } #[test] fn descr_getset() { Python::with_gil(|py| { let counter = py.get_type::(); let source = pyo3_ffi::c_str!(pyo3::indoc::indoc!( r#" class Class: counter = Counter() # access via type counter = Class.counter assert counter.count == 1 # access with instance directly assert Counter.__get__(counter, Class()).count == 2 # access via instance c = Class() assert c.counter.count == 3 # __set__ c.counter = Counter() assert c.counter.count == 4 # __delete__ del c.counter assert c.counter.count == 1 "# )); let globals = PyModule::import(py, "__main__").unwrap().dict(); globals.set_item("Counter", counter).unwrap(); py.run(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); } #[pyclass] struct NotHashable; #[pymethods] impl NotHashable { #[classattr] const __hash__: Option = None; } #[test] fn test_hash_opt_out() { // By default Python provides a hash implementation, which can be disabled by setting __hash__ // to None. Python::with_gil(|py| { let empty = Py::new(py, EmptyClass).unwrap(); py_assert!(py, empty, "hash(empty) is not None"); let not_hashable = Py::new(py, NotHashable).unwrap(); py_expect_exception!(py, not_hashable, "hash(not_hashable)", PyTypeError); }) } /// Class with __iter__ gets default contains from CPython. #[pyclass] struct DefaultedContains; #[pymethods] impl DefaultedContains { fn __iter__(&self, py: Python<'_>) -> PyObject { PyList::new(py, ["a", "b", "c"]) .unwrap() .as_any() .try_iter() .unwrap() .into() } } #[pyclass] struct NoContains; #[pymethods] impl NoContains { fn __iter__(&self, py: Python<'_>) -> PyObject { PyList::new(py, ["a", "b", "c"]) .unwrap() .as_any() .try_iter() .unwrap() .into() } // Equivalent to the opt-out const form in NotHashable above, just more verbose, to confirm this // also works. #[classattr] fn __contains__() -> Option { None } } #[test] fn test_contains_opt_out() { Python::with_gil(|py| { let defaulted_contains = Py::new(py, DefaultedContains).unwrap(); py_assert!(py, defaulted_contains, "'a' in defaulted_contains"); let no_contains = Py::new(py, NoContains).unwrap(); py_expect_exception!(py, no_contains, "'a' in no_contains", PyTypeError); }) } pyo3/tests/test_methods.rs0000644000175000017500000007650115105742312015517 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::PySequence; use pyo3::types::{IntoPyDict, PyDict, PyList, PySet, PyString, PyTuple, PyType}; use pyo3::BoundObject; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct InstanceMethod { member: i32, } #[pymethods] impl InstanceMethod { /// Test method fn method(&self) -> i32 { self.member } // Checks that &Self works fn add_other(&self, other: &Self) -> i32 { self.member + other.member } } #[test] fn instance_method() { Python::with_gil(|py| { let obj = Bound::new(py, InstanceMethod { member: 42 }).unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.method(), 42); py_assert!(py, obj, "obj.method() == 42"); py_assert!(py, obj, "obj.add_other(obj) == 84"); py_assert!(py, obj, "obj.method.__doc__ == 'Test method'"); }); } #[pyclass] struct InstanceMethodWithArgs { member: i32, } #[pymethods] impl InstanceMethodWithArgs { fn method(&self, multiplier: i32) -> i32 { self.member * multiplier } } #[test] fn instance_method_with_args() { Python::with_gil(|py| { let obj = Bound::new(py, InstanceMethodWithArgs { member: 7 }).unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.method(6), 42); py_assert!(py, obj, "obj.method(3) == 21"); py_assert!(py, obj, "obj.method(multiplier=6) == 42"); }); } #[pyclass] struct ClassMethod {} #[pymethods] impl ClassMethod { #[new] fn new() -> Self { ClassMethod {} } #[classmethod] /// Test class method. fn method(cls: &Bound<'_, PyType>) -> PyResult { Ok(format!("{}.method()!", cls.qualname()?)) } #[classmethod] fn method_owned(cls: Py, py: Python<'_>) -> PyResult { Ok(format!("{}.method_owned()!", cls.bind(py).qualname()?)) } } #[test] fn class_method() { Python::with_gil(|py| { let d = [("C", py.get_type::())] .into_py_dict(py) .unwrap(); py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'"); py_assert!(py, *d, "C().method() == 'ClassMethod.method()!'"); py_assert!( py, *d, "C().method_owned() == 'ClassMethod.method_owned()!'" ); py_assert!(py, *d, "C.method.__doc__ == 'Test class method.'"); py_assert!(py, *d, "C().method.__doc__ == 'Test class method.'"); }); } #[pyclass] struct ClassMethodWithArgs {} #[pymethods] impl ClassMethodWithArgs { #[classmethod] fn method(cls: &Bound<'_, PyType>, input: &Bound<'_, PyString>) -> PyResult { Ok(format!("{}.method({})", cls.qualname()?, input)) } } #[test] fn class_method_with_args() { Python::with_gil(|py| { let d = [("C", py.get_type::())] .into_py_dict(py) .unwrap(); py_assert!( py, *d, "C.method('abc') == 'ClassMethodWithArgs.method(abc)'" ); }); } #[pyclass] struct StaticMethod {} #[pymethods] impl StaticMethod { #[new] fn new() -> Self { StaticMethod {} } #[staticmethod] /// Test static method. fn method(_py: Python<'_>) -> &'static str { "StaticMethod.method()!" } } #[test] fn static_method() { Python::with_gil(|py| { assert_eq!(StaticMethod::method(py), "StaticMethod.method()!"); let d = [("C", py.get_type::())] .into_py_dict(py) .unwrap(); py_assert!(py, *d, "C.method() == 'StaticMethod.method()!'"); py_assert!(py, *d, "C().method() == 'StaticMethod.method()!'"); py_assert!(py, *d, "C.method.__doc__ == 'Test static method.'"); py_assert!(py, *d, "C().method.__doc__ == 'Test static method.'"); }); } #[pyclass] struct StaticMethodWithArgs {} #[pymethods] impl StaticMethodWithArgs { #[staticmethod] fn method(_py: Python<'_>, input: i32) -> String { format!("0x{input:x}") } } #[test] fn static_method_with_args() { Python::with_gil(|py| { assert_eq!(StaticMethodWithArgs::method(py, 1234), "0x4d2"); let d = [("C", py.get_type::())] .into_py_dict(py) .unwrap(); py_assert!(py, *d, "C.method(1337) == '0x539'"); }); } #[pyclass] struct MethSignature {} #[pymethods] impl MethSignature { #[pyo3(signature = (test = None))] fn get_optional(&self, test: Option) -> i32 { test.unwrap_or(10) } #[pyo3(signature = (test = None))] fn get_optional2(&self, test: Option) -> Option { test } #[pyo3(signature=(_t1 = None, t2 = None, _t3 = None))] fn get_optional_positional( &self, _t1: Option, t2: Option, _t3: Option, ) -> Option { t2 } #[pyo3(signature = (test = 10))] fn get_default(&self, test: i32) -> i32 { test } #[pyo3(signature = (*, test = 10))] fn get_kwarg(&self, test: i32) -> i32 { test } #[pyo3(signature = (*args, **kwargs))] fn get_kwargs<'py>( &self, py: Python<'py>, args: &Bound<'py, PyTuple>, kwargs: Option<&Bound<'py, PyDict>>, ) -> PyResult> { [ args.as_any().clone(), kwargs.into_pyobject(py)?.into_any().into_bound(), ] .into_pyobject(py) } #[pyo3(signature = (a, *args, **kwargs))] fn get_pos_arg_kw<'py>( &self, py: Python<'py>, a: i32, args: &Bound<'py, PyTuple>, kwargs: Option<&Bound<'py, PyDict>>, ) -> PyResult> { [ a.into_pyobject(py)?.into_any().into_bound(), args.as_any().clone(), kwargs.into_pyobject(py)?.into_any().into_bound(), ] .into_pyobject(py) } #[pyo3(signature = (a, b, /))] fn get_pos_only(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (a, /, b))] fn get_pos_only_and_pos(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (a, /, b, c = 5))] fn get_pos_only_and_pos_and_kw(&self, a: i32, b: i32, c: i32) -> i32 { a + b + c } #[pyo3(signature = (a, /, *, b))] fn get_pos_only_and_kw_only(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (a, /, *, b = 3))] fn get_pos_only_and_kw_only_with_default(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (a, /, b, *, c, d = 5))] fn get_all_arg_types_together(&self, a: i32, b: i32, c: i32, d: i32) -> i32 { a + b + c + d } #[pyo3(signature = (a, /, *args))] fn get_pos_only_with_varargs(&self, a: i32, args: Vec) -> i32 { a + args.iter().sum::() } #[pyo3(signature = (a, /, **kwargs))] fn get_pos_only_with_kwargs( &self, py: Python<'_>, a: i32, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult { [ a.into_pyobject(py)?.into_any().into_bound(), kwargs.into_pyobject(py)?.into_any().into_bound(), ] .into_pyobject(py) .map(Bound::unbind) } #[pyo3(signature = (a=0, /, **kwargs))] fn get_optional_pos_only_with_kwargs( &self, py: Python<'_>, a: i32, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult { [ a.into_pyobject(py)?.into_any().into_bound(), kwargs.into_pyobject(py)?.into_any().into_bound(), ] .into_pyobject(py) .map(Bound::unbind) } #[pyo3(signature = (*, a = 2, b = 3))] fn get_kwargs_only_with_defaults(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (*, a, b))] fn get_kwargs_only(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (*, a = 1, b))] fn get_kwargs_only_with_some_default(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (*args, a))] fn get_args_and_required_keyword( &self, py: Python<'_>, args: &Bound<'_, PyTuple>, a: i32, ) -> PyResult { (args, a) .into_pyobject(py) .map(BoundObject::into_any) .map(Bound::unbind) } #[pyo3(signature = (a, b = 2, *, c = 3))] fn get_pos_arg_kw_sep1(&self, a: i32, b: i32, c: i32) -> i32 { a + b + c } #[pyo3(signature = (a, *, b = 2, c = 3))] fn get_pos_arg_kw_sep2(&self, a: i32, b: i32, c: i32) -> i32 { a + b + c } #[pyo3(signature = (a, **kwargs))] fn get_pos_kw( &self, py: Python<'_>, a: i32, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult { [ a.into_pyobject(py)?.into_any().into_bound(), kwargs.into_pyobject(py)?.into_any().into_bound(), ] .into_pyobject(py) .map(Bound::unbind) } // "args" can be anything that can be extracted from PyTuple #[pyo3(signature = (*args))] fn args_as_vec(&self, args: Vec) -> i32 { args.iter().sum() } } #[test] fn meth_signature() { Python::with_gil(|py| { let inst = Py::new(py, MethSignature {}).unwrap(); py_run!(py, inst, "assert inst.get_optional() == 10"); py_run!(py, inst, "assert inst.get_optional(100) == 100"); py_run!(py, inst, "assert inst.get_optional2() == None"); py_run!(py, inst, "assert inst.get_optional2(100) == 100"); py_run!( py, inst, "assert inst.get_optional_positional(1, 2, 3) == 2" ); py_run!(py, inst, "assert inst.get_optional_positional(1) == None"); py_run!(py, inst, "assert inst.get_default() == 10"); py_run!(py, inst, "assert inst.get_default(100) == 100"); py_run!(py, inst, "assert inst.get_kwarg() == 10"); py_expect_exception!(py, inst, "inst.get_kwarg(100)", PyTypeError); py_run!(py, inst, "assert inst.get_kwarg(test=100) == 100"); py_run!(py, inst, "assert inst.get_kwargs() == [(), None]"); py_run!(py, inst, "assert inst.get_kwargs(1,2,3) == [(1,2,3), None]"); py_run!( py, inst, "assert inst.get_kwargs(t=1,n=2) == [(), {'t': 1, 'n': 2}]" ); py_run!( py, inst, "assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]" ); py_run!(py, inst, "assert inst.get_pos_arg_kw(1) == [1, (), None]"); py_run!( py, inst, "assert inst.get_pos_arg_kw(1, 2, 3) == [1, (2, 3), None]" ); py_run!( py, inst, "assert inst.get_pos_arg_kw(1, b=2) == [1, (), {'b': 2}]" ); py_run!(py, inst, "assert inst.get_pos_arg_kw(a=1) == [1, (), None]"); py_expect_exception!(py, inst, "inst.get_pos_arg_kw()", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(1, a=1)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(b=2)", PyTypeError); py_run!(py, inst, "assert inst.get_pos_only(10, 11) == 21"); py_expect_exception!(py, inst, "inst.get_pos_only(10, b = 11)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_only(a = 10, b = 11)", PyTypeError); py_run!(py, inst, "assert inst.get_pos_only_and_pos(10, 11) == 21"); py_run!( py, inst, "assert inst.get_pos_only_and_pos(10, b = 11) == 21" ); py_expect_exception!( py, inst, "inst.get_pos_only_and_pos(a = 10, b = 11)", PyTypeError ); py_run!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, 11) == 26" ); py_run!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, b = 11) == 26" ); py_run!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, 11, c = 0) == 21" ); py_run!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, b = 11, c = 0) == 21" ); py_expect_exception!( py, inst, "inst.get_pos_only_and_pos_and_kw(a = 10, b = 11)", PyTypeError ); py_run!( py, inst, "assert inst.get_pos_only_and_kw_only(10, b = 11) == 21" ); py_expect_exception!( py, inst, "inst.get_pos_only_and_kw_only(10, 11)", PyTypeError ); py_expect_exception!( py, inst, "inst.get_pos_only_and_kw_only(a = 10, b = 11)", PyTypeError ); py_run!( py, inst, "assert inst.get_pos_only_and_kw_only_with_default(10) == 13" ); py_run!( py, inst, "assert inst.get_pos_only_and_kw_only_with_default(10, b = 11) == 21" ); py_expect_exception!( py, inst, "inst.get_pos_only_and_kw_only_with_default(10, 11)", PyTypeError ); py_expect_exception!( py, inst, "inst.get_pos_only_and_kw_only_with_default(a = 10, b = 11)", PyTypeError ); py_run!( py, inst, "assert inst.get_all_arg_types_together(10, 10, c = 10) == 35" ); py_run!( py, inst, "assert inst.get_all_arg_types_together(10, 10, c = 10, d = 10) == 40" ); py_run!( py, inst, "assert inst.get_all_arg_types_together(10, b = 10, c = 10, d = 10) == 40" ); py_expect_exception!( py, inst, "inst.get_all_arg_types_together(10, 10, 10)", PyTypeError ); py_expect_exception!( py, inst, "inst.get_all_arg_types_together(a = 10, b = 10, c = 10)", PyTypeError ); py_run!(py, inst, "assert inst.get_pos_only_with_varargs(10) == 10"); py_run!( py, inst, "assert inst.get_pos_only_with_varargs(10, 10) == 20" ); py_run!( py, inst, "assert inst.get_pos_only_with_varargs(10, 10, 10, 10, 10) == 50" ); py_expect_exception!( py, inst, "inst.get_pos_only_with_varargs(a = 10)", PyTypeError ); py_run!( py, inst, "assert inst.get_pos_only_with_kwargs(10) == [10, None]" ); py_run!( py, inst, "assert inst.get_pos_only_with_kwargs(10, b = 10) == [10, {'b': 10}]" ); py_run!( py, inst, "assert inst.get_pos_only_with_kwargs(10, b = 10, c = 10, d = 10, e = 10) == [10, {'b': 10, 'c': 10, 'd': 10, 'e': 10}]" ); py_expect_exception!( py, inst, "inst.get_pos_only_with_kwargs(a = 10)", PyTypeError ); py_expect_exception!( py, inst, "inst.get_pos_only_with_kwargs(a = 10, b = 10)", PyTypeError ); py_run!( py, inst, "assert inst.get_optional_pos_only_with_kwargs() == [0, None]" ); py_run!( py, inst, "assert inst.get_optional_pos_only_with_kwargs(10) == [10, None]" ); py_run!( py, inst, "assert inst.get_optional_pos_only_with_kwargs(a=10) == [0, {'a': 10}]" ); py_run!(py, inst, "assert inst.get_kwargs_only_with_defaults() == 5"); py_run!( py, inst, "assert inst.get_kwargs_only_with_defaults(a = 8) == 11" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_defaults(b = 8) == 10" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_defaults(a = 1, b = 1) == 2" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_defaults(b = 1, a = 1) == 2" ); py_run!(py, inst, "assert inst.get_kwargs_only(a = 1, b = 1) == 2"); py_run!(py, inst, "assert inst.get_kwargs_only(b = 1, a = 1) == 2"); py_run!( py, inst, "assert inst.get_kwargs_only_with_some_default(a = 2, b = 1) == 3" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_some_default(b = 1) == 2" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_some_default(b = 1, a = 2) == 3" ); py_expect_exception!( py, inst, "inst.get_kwargs_only_with_some_default()", PyTypeError ); py_run!( py, inst, "assert inst.get_args_and_required_keyword(1, 2, a=3) == ((1, 2), 3)" ); py_run!( py, inst, "assert inst.get_args_and_required_keyword(a=1) == ((), 1)" ); py_expect_exception!( py, inst, "inst.get_args_and_required_keyword()", PyTypeError ); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1) == 6"); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2) == 6"); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2, c=13) == 16" ); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep1(a=1, b=2, c=13) == 16" ); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep1(b=2, c=13, a=1) == 16" ); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep1(c=13, b=2, a=1) == 16" ); py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep1(1, 2, 3)", PyTypeError); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep2(1) == 6"); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep2(1, b=12, c=13) == 26" ); py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep2(1, 2)", PyTypeError); py_run!(py, inst, "assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]"); py_expect_exception!(py, inst, "inst.get_pos_kw(1,2)", PyTypeError); py_run!(py, inst, "assert inst.args_as_vec(1,2,3) == 6"); }); } #[pyclass] /// A class with "documentation". struct MethDocs { x: i32, } #[pymethods] impl MethDocs { /// A method with "documentation" as well. fn method(&self) -> i32 { 0 } #[getter] /// `int`: a very "important" member of 'this' instance. fn get_x(&self) -> i32 { self.x } } #[test] fn meth_doc() { Python::with_gil(|py| { let d = [("C", py.get_type::())].into_py_dict(py).unwrap(); py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'"); py_assert!( py, *d, "C.method.__doc__ == 'A method with \"documentation\" as well.'" ); py_assert!( py, *d, "C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'" ); }); } #[pyclass] struct MethodWithLifeTime {} #[pymethods] impl MethodWithLifeTime { fn set_to_list<'py>(&self, set: &Bound<'py, PySet>) -> PyResult> { let py = set.py(); let mut items = vec![]; for _ in 0..set.len() { items.push(set.pop().unwrap()); } let list = PyList::new(py, items)?; list.sort()?; Ok(list) } } #[test] fn method_with_lifetime() { Python::with_gil(|py| { let obj = Py::new(py, MethodWithLifeTime {}).unwrap(); py_run!( py, obj, "assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]" ); }); } #[pyclass] struct MethodWithPyClassArg { #[pyo3(get)] value: i64, } #[pymethods] impl MethodWithPyClassArg { fn add(&self, other: &MethodWithPyClassArg) -> MethodWithPyClassArg { MethodWithPyClassArg { value: self.value + other.value, } } fn add_pyref(&self, other: PyRef<'_, MethodWithPyClassArg>) -> MethodWithPyClassArg { MethodWithPyClassArg { value: self.value + other.value, } } fn inplace_add(&self, other: &mut MethodWithPyClassArg) { other.value += self.value; } fn inplace_add_pyref(&self, mut other: PyRefMut<'_, MethodWithPyClassArg>) { other.value += self.value; } #[pyo3(signature=(other = None))] fn optional_add(&self, other: Option<&MethodWithPyClassArg>) -> MethodWithPyClassArg { MethodWithPyClassArg { value: self.value + other.map(|o| o.value).unwrap_or(10), } } #[pyo3(signature=(other = None))] fn optional_inplace_add(&self, other: Option<&mut MethodWithPyClassArg>) { if let Some(other) = other { other.value += self.value; } } } #[test] fn method_with_pyclassarg() { Python::with_gil(|py| { let obj1 = Py::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); let obj2 = Py::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py).unwrap(); py_run!(py, *d, "obj = obj1.add(obj2); assert obj.value == 20"); py_run!(py, *d, "obj = obj1.add_pyref(obj2); assert obj.value == 20"); py_run!(py, *d, "obj = obj1.optional_add(); assert obj.value == 20"); py_run!( py, *d, "obj = obj1.optional_add(obj2); assert obj.value == 20" ); py_run!(py, *d, "obj1.inplace_add(obj2); assert obj.value == 20"); py_run!( py, *d, "obj1.inplace_add_pyref(obj2); assert obj2.value == 30" ); py_run!( py, *d, "obj1.optional_inplace_add(); assert obj2.value == 30" ); py_run!( py, *d, "obj1.optional_inplace_add(obj2); assert obj2.value == 40" ); }); } #[pyclass] #[cfg(unix)] struct CfgStruct {} #[pyclass] #[cfg(not(unix))] struct CfgStruct {} #[pymethods] #[cfg(unix)] impl CfgStruct { fn unix_method(&self) -> &str { "unix" } #[cfg(not(unix))] fn never_compiled_method(&self) {} } #[pymethods] #[cfg(not(unix))] impl CfgStruct { fn not_unix_method(&self) -> &str { "not unix" } #[cfg(unix)] fn never_compiled_method(&self) {} } #[test] fn test_cfg_attrs() { Python::with_gil(|py| { let inst = Py::new(py, CfgStruct {}).unwrap(); #[cfg(unix)] { py_assert!(py, inst, "inst.unix_method() == 'unix'"); py_assert!(py, inst, "not hasattr(inst, 'not_unix_method')"); } #[cfg(not(unix))] { py_assert!(py, inst, "not hasattr(inst, 'unix_method')"); py_assert!(py, inst, "inst.not_unix_method() == 'not unix'"); } py_assert!(py, inst, "not hasattr(inst, 'never_compiled_method')"); }); } #[pyclass] #[derive(Default)] struct FromSequence { #[pyo3(get)] numbers: Vec, } #[pymethods] impl FromSequence { #[new] #[pyo3(signature=(seq = None))] fn new(seq: Option<&Bound<'_, PySequence>>) -> PyResult { if let Some(seq) = seq { Ok(FromSequence { numbers: seq.as_any().extract::>()?, }) } else { Ok(FromSequence::default()) } } } #[test] fn test_from_sequence() { Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "typeobj(range(0, 4)).numbers == [0, 1, 2, 3]"); }); } #[pyclass] struct r#RawIdents { #[pyo3(get, set)] r#type: PyObject, r#subtype: PyObject, r#subsubtype: PyObject, } #[pymethods] impl r#RawIdents { #[new] pub fn r#new( r#_py: Python<'_>, r#type: PyObject, r#subtype: PyObject, r#subsubtype: PyObject, ) -> Self { Self { r#type, r#subtype, r#subsubtype, } } #[getter(r#subtype)] pub fn r#get_subtype(&self, py: Python<'_>) -> PyObject { self.r#subtype.clone_ref(py) } #[setter(r#subtype)] pub fn r#set_subtype(&mut self, r#subtype: PyObject) { self.r#subtype = r#subtype; } #[getter] pub fn r#get_subsubtype(&self, py: Python<'_>) -> PyObject { self.r#subsubtype.clone_ref(py) } #[setter] pub fn r#set_subsubtype(&mut self, r#subsubtype: PyObject) { self.r#subsubtype = r#subsubtype; } pub fn r#__call__(&mut self, r#type: PyObject) { self.r#type = r#type; } #[staticmethod] pub fn r#static_method(r#type: PyObject) -> PyObject { r#type } #[classmethod] pub fn r#class_method(_: &Bound<'_, PyType>, r#type: PyObject) -> PyObject { r#type } #[classattr] pub fn r#class_attr_fn() -> i32 { 5 } #[classattr] const r#CLASS_ATTR_CONST: i32 = 6; #[pyo3(signature = (r#struct = "foo"))] fn method_with_keyword<'a>(&self, r#struct: &'a str) -> &'a str { r#struct } } #[test] fn test_raw_idents() { Python::with_gil(|py| { let raw_idents_type = py.get_type::(); assert_eq!(raw_idents_type.qualname().unwrap(), "RawIdents"); py_run!( py, raw_idents_type, r#" instance = raw_idents_type(type=None, subtype=5, subsubtype="foo") assert instance.type is None assert instance.subtype == 5 assert instance.subsubtype == "foo" instance.type = 1 instance.subtype = 2 instance.subsubtype = 3 assert instance.type == 1 assert instance.subtype == 2 assert instance.subsubtype == 3 assert raw_idents_type.static_method(type=30) == 30 assert instance.class_method(type=40) == 40 instance(type=50) assert instance.type == 50 assert raw_idents_type.class_attr_fn == 5 assert raw_idents_type.CLASS_ATTR_CONST == 6 assert instance.method_with_keyword() == "foo" assert instance.method_with_keyword("bar") == "bar" assert instance.method_with_keyword(struct="baz") == "baz" "# ); }) } // Regression test for issue 1505 - Python argument not detected correctly when inside a macro. #[pyclass] struct Issue1505 {} macro_rules! pymethods { ( #[pymethods] impl $ty: ty { fn $fn:ident (&self, $arg:ident : $arg_ty:ty) {} } ) => { #[pymethods] impl $ty { fn $fn(&self, $arg: $arg_ty) {} } }; } pymethods!( #[pymethods] impl Issue1505 { fn issue_1505(&self, _py: Python<'_>) {} } ); // Regression test for issue 1506 - incorrect macro hygiene. // By applying the `#[pymethods]` attribute inside a macro_rules! macro, this separates the macro // call scope from the scope of the impl block. For this to work our macros must be careful to not // cheat hygiene! #[pyclass] struct Issue1506 {} macro_rules! issue_1506 { (#[pymethods] $($body:tt)*) => { #[pymethods] $($body)* }; } issue_1506!( #[pymethods] impl Issue1506 { #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506( &self, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_mut( &mut self, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_custom_receiver( _slf: Py, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_custom_receiver_explicit( _slf: Py, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[new] #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_new( _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) -> Self { Issue1506 {} } #[getter("foo")] fn issue_1506_getter(&self, _py: Python<'_>) -> i32 { 5 } #[setter("foo")] fn issue_1506_setter(&self, _py: Python<'_>, _value: i32) {} #[staticmethod] #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_static( _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[classmethod] #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_class( _cls: &Bound<'_, PyType>, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } } ); #[pyclass] struct Issue1696 {} pymethods!( #[pymethods] impl Issue1696 { fn issue_1696(&self, _x: &InstanceMethod) {} } ); #[test] fn test_option_pyclass_arg() { // Option<&PyClass> argument with a default set in a signature regressed to a compile // error in PyO3 0.17.0 - this test it continues to be accepted. #[pyclass] struct SomePyClass {} #[pyfunction(signature = (arg=None))] fn option_class_arg(arg: Option<&SomePyClass>) -> Option { arg.map(|_| SomePyClass {}) } Python::with_gil(|py| { let f = wrap_pyfunction!(option_class_arg, py).unwrap(); assert!(f.call0().unwrap().is_none()); let obj = Py::new(py, SomePyClass {}).unwrap(); assert!(f .call1((obj,)) .unwrap() .extract::>() .is_ok()); }) } #[test] fn test_issue_2988() { #[pyfunction] #[pyo3(signature = ( _data = vec![], _data2 = vec![], ))] pub fn _foo( _data: Vec, // The from_py_with here looks a little odd, we just need some way // to encourage the macro to expand the from_py_with default path too #[pyo3(from_py_with = as PyAnyMethods>::extract)] _data2: Vec, ) { } } pyo3/tests/test_various.rs0000644000175000017500000001210615105742312015533 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::PyTuple; use std::fmt; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct MutRefArg { n: i32, } #[pymethods] impl MutRefArg { fn get(&self) -> i32 { self.n } fn set_other(&self, mut other: PyRefMut<'_, MutRefArg>) { other.n = 100; } } #[test] fn mut_ref_arg() { Python::with_gil(|py| { let inst1 = Py::new(py, MutRefArg { n: 0 }).unwrap(); let inst2 = Py::new(py, MutRefArg { n: 0 }).unwrap(); py_run!(py, inst1 inst2, "inst1.set_other(inst2)"); let inst2 = inst2.bind(py).borrow(); assert_eq!(inst2.n, 100); }); } #[pyclass] struct PyUsize { #[pyo3(get)] pub value: usize, } #[pyfunction] fn get_zero() -> PyUsize { PyUsize { value: 0 } } #[test] /// Checks that we can use return a custom class in arbitrary function and use those functions /// both in rust and python fn return_custom_class() { Python::with_gil(|py| { // Using from rust assert_eq!(get_zero().value, 0); // Using from python let get_zero = wrap_pyfunction!(get_zero)(py).unwrap(); py_assert!(py, get_zero, "get_zero().value == 0"); }); } #[test] fn intopytuple_primitive() { Python::with_gil(|py| { let tup = (1, 2, "foo"); py_assert!(py, tup, "tup == (1, 2, 'foo')"); py_assert!(py, tup, "tup[0] == 1"); py_assert!(py, tup, "tup[1] == 2"); py_assert!(py, tup, "tup[2] == 'foo'"); }); } #[pyclass] struct SimplePyClass {} #[test] fn intopytuple_pyclass() { Python::with_gil(|py| { let tup = ( Py::new(py, SimplePyClass {}).unwrap(), Py::new(py, SimplePyClass {}).unwrap(), ); py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'"); py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[1]).__name__"); py_assert!(py, tup, "tup[0] != tup[1]"); }); } #[test] fn pytuple_primitive_iter() { Python::with_gil(|py| { let tup = PyTuple::new(py, [1u32, 2, 3].iter()).unwrap(); py_assert!(py, tup, "tup == (1, 2, 3)"); }); } #[test] fn pytuple_pyclass_iter() { Python::with_gil(|py| { let tup = PyTuple::new( py, [ Py::new(py, SimplePyClass {}).unwrap(), Py::new(py, SimplePyClass {}).unwrap(), ] .iter(), ) .unwrap(); py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'"); py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[0]).__name__"); py_assert!(py, tup, "tup[0] != tup[1]"); }); } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn test_pickle() { use pyo3::types::PyDict; #[pyclass(dict, module = "test_module")] struct PickleSupport {} #[pymethods] impl PickleSupport { #[new] fn new() -> PickleSupport { PickleSupport {} } pub fn __reduce__<'py>( slf: &Bound<'py, Self>, py: Python<'py>, ) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyTuple>, Bound<'py, PyAny>)> { let cls = slf.getattr("__class__")?; let dict = slf.getattr("__dict__")?; Ok((cls, PyTuple::empty(py), dict)) } } fn add_module(module: Bound<'_, PyModule>) -> PyResult<()> { PyModule::import(module.py(), "sys")? .dict() .get_item("modules") .unwrap() .unwrap() .downcast::()? .set_item(module.name()?, module) } Python::with_gil(|py| { let module = PyModule::new(py, "test_module").unwrap(); module.add_class::().unwrap(); add_module(module).unwrap(); let inst = Py::new(py, PickleSupport {}).unwrap(); py_run!( py, inst, r#" inst.a = 1 assert inst.__dict__ == {'a': 1} import pickle inst2 = pickle.loads(pickle.dumps(inst)) assert inst2.__dict__ == {'a': 1} "# ); }); } /// Testing https://github.com/PyO3/pyo3/issues/1106. A result type that /// implements `From for PyErr` should be automatically converted /// when using `#[pyfunction]`. /// /// This only makes sure that valid `Result` types do work. For an invalid /// enum type, see `ui/invalid_result_conversion.py`. #[derive(Debug)] struct MyError { pub descr: &'static str, } impl fmt::Display for MyError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "My error message: {}", self.descr) } } /// Important for the automatic conversion to `PyErr`. impl From for PyErr { fn from(err: MyError) -> pyo3::PyErr { pyo3::exceptions::PyOSError::new_err(err.to_string()) } } #[pyfunction] fn result_conversion_function() -> Result<(), MyError> { Err(MyError { descr: "something went wrong", }) } #[test] fn test_result_conversion() { Python::with_gil(|py| { wrap_pyfunction!(result_conversion_function)(py).unwrap(); }); } pyo3/tests/test_field_cfg.rs0000644000175000017500000000213715105742312015750 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; #[pyclass] struct CfgClass { #[pyo3(get, set)] #[cfg(any())] pub a: u32, #[pyo3(get, set)] // This is always true #[cfg(any( target_family = "unix", target_family = "windows", target_family = "wasm" ))] pub b: u32, } #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum CfgSimpleEnum { #[cfg(any())] DisabledVariant, #[cfg(not(any()))] EnabledVariant, } #[test] fn test_cfg() { Python::with_gil(|py| { let cfg = CfgClass { b: 3 }; let py_cfg = Py::new(py, cfg).unwrap(); assert!(py_cfg.bind(py).getattr("a").is_err()); let b: u32 = py_cfg.bind(py).getattr("b").unwrap().extract().unwrap(); assert_eq!(b, 3); }); } #[test] fn test_cfg_simple_enum() { Python::with_gil(|py| { let simple = py.get_type::(); pyo3::py_run!( py, simple, r#" assert hasattr(simple, "EnabledVariant") assert not hasattr(simple, "DisabledVariant") "# ); }) } pyo3/tests/test_exceptions.rs0000644000175000017500000000615715105742312016235 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::{exceptions, py_run}; use std::error::Error; use std::fmt; #[cfg(not(target_os = "windows"))] use std::fs::File; #[path = "../src/tests/common.rs"] mod common; #[pyfunction] #[cfg(not(target_os = "windows"))] fn fail_to_open_file() -> PyResult<()> { File::open("not_there.txt")?; Ok(()) } #[test] #[cfg_attr(target_arch = "wasm32", ignore)] // Not sure why this fails. #[cfg(not(target_os = "windows"))] fn test_filenotfounderror() { Python::with_gil(|py| { let fail_to_open_file = wrap_pyfunction!(fail_to_open_file)(py).unwrap(); py_run!( py, fail_to_open_file, r#" try: fail_to_open_file() except FileNotFoundError as e: assert str(e) == "No such file or directory (os error 2)" "# ); }); } #[derive(Debug)] struct CustomError; impl Error for CustomError {} impl fmt::Display for CustomError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Oh no!") } } impl std::convert::From for PyErr { fn from(err: CustomError) -> PyErr { exceptions::PyOSError::new_err(err.to_string()) } } fn fail_with_custom_error() -> Result<(), CustomError> { Err(CustomError) } #[pyfunction] fn call_fail_with_custom_error() -> PyResult<()> { fail_with_custom_error()?; Ok(()) } #[test] fn test_custom_error() { Python::with_gil(|py| { let call_fail_with_custom_error = wrap_pyfunction!(call_fail_with_custom_error)(py).unwrap(); py_run!( py, call_fail_with_custom_error, r#" try: call_fail_with_custom_error() except OSError as e: assert str(e) == "Oh no!" "# ); }); } #[test] fn test_exception_nosegfault() { use std::net::TcpListener; fn io_err() -> PyResult<()> { TcpListener::bind("no:address")?; Ok(()) } fn parse_int() -> PyResult<()> { "@_@".parse::()?; Ok(()) } assert!(io_err().is_err()); assert!(parse_int().is_err()); } #[test] #[cfg(all(Py_3_8, not(Py_GIL_DISABLED)))] fn test_write_unraisable() { use common::UnraisableCapture; use pyo3::{exceptions::PyRuntimeError, ffi, types::PyNotImplemented}; use std::ptr; Python::with_gil(|py| { let capture = UnraisableCapture::install(py); assert!(capture.borrow(py).capture.is_none()); let err = PyRuntimeError::new_err("foo"); err.write_unraisable(py, None); let (err, object) = capture.borrow_mut(py).capture.take().unwrap(); assert_eq!(err.to_string(), "RuntimeError: foo"); assert!(object.is_none(py)); let err = PyRuntimeError::new_err("bar"); err.write_unraisable(py, Some(&PyNotImplemented::get(py))); let (err, object) = capture.borrow_mut(py).capture.take().unwrap(); assert_eq!(err.to_string(), "RuntimeError: bar"); assert!(unsafe { ptr::eq(object.as_ptr(), ffi::Py_NotImplemented()) }); capture.borrow_mut(py).uninstall(py); }); } pyo3/tests/test_class_conversion.rs0000644000175000017500000000716215105742312017423 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; #[macro_use] #[path = "../src/tests/common.rs"] mod common; #[pyclass] #[derive(Clone, Debug, PartialEq)] struct Cloneable { x: i32, } #[test] fn test_cloneable_pyclass() { let c = Cloneable { x: 10 }; Python::with_gil(|py| { let py_c = Py::new(py, c.clone()).unwrap(); let c2: Cloneable = py_c.extract(py).unwrap(); assert_eq!(c, c2); { let rc: PyRef<'_, Cloneable> = py_c.extract(py).unwrap(); assert_eq!(&c, &*rc); // Drops PyRef before taking PyRefMut } let mrc: PyRefMut<'_, Cloneable> = py_c.extract(py).unwrap(); assert_eq!(&c, &*mrc); }); } #[pyclass(subclass)] #[derive(Default)] struct BaseClass { value: i32, } #[pymethods] impl BaseClass { fn foo(&self) -> &'static str { "BaseClass" } } #[pyclass(extends=BaseClass)] struct SubClass {} #[pymethods] impl SubClass { fn foo(&self) -> &'static str { "SubClass" } } #[pyclass] struct PolymorphicContainer { #[pyo3(get, set)] inner: Py, } #[test] fn test_polymorphic_container_stores_base_class() { Python::with_gil(|py| { let p = Py::new( py, PolymorphicContainer { inner: Py::new(py, BaseClass::default()).unwrap(), }, ) .unwrap(); py_assert!(py, p, "p.inner.foo() == 'BaseClass'"); }); } #[test] fn test_polymorphic_container_stores_sub_class() { Python::with_gil(|py| { let p = Py::new( py, PolymorphicContainer { inner: Py::new(py, BaseClass::default()).unwrap(), }, ) .unwrap(); p.bind(py) .setattr( "inner", Py::new( py, PyClassInitializer::from(BaseClass::default()).add_subclass(SubClass {}), ) .unwrap(), ) .unwrap(); py_assert!(py, p, "p.inner.foo() == 'SubClass'"); }); } #[test] fn test_polymorphic_container_does_not_accept_other_types() { Python::with_gil(|py| { let p = Py::new( py, PolymorphicContainer { inner: Py::new(py, BaseClass::default()).unwrap(), }, ) .unwrap(); let setattr = |value: Bound<'_, PyAny>| p.bind(py).setattr("inner", value); assert!(setattr(1i32.into_pyobject(py).unwrap().into_any()).is_err()); assert!(setattr(py.None().into_bound(py)).is_err()); assert!(setattr((1i32, 2i32).into_pyobject(py).unwrap().into_any()).is_err()); }); } #[test] fn test_pyref_as_base() { Python::with_gil(|py| { let cell = Bound::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap(); // First try PyRefMut let sub: PyRefMut<'_, SubClass> = cell.borrow_mut(); let mut base: PyRefMut<'_, BaseClass> = sub.into_super(); assert_eq!(120, base.value); base.value = 999; assert_eq!(999, base.value); drop(base); // Repeat for PyRef let sub: PyRef<'_, SubClass> = cell.borrow(); let base: PyRef<'_, BaseClass> = sub.into_super(); assert_eq!(999, base.value); }); } #[test] fn test_pycell_deref() { Python::with_gil(|py| { let obj = Bound::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap(); // Should be able to deref as PyAny assert_eq!( obj.call_method0("foo") .and_then(|e| e.extract::()) .unwrap(), "SubClass" ); }); } pyo3/tests/test_class_comparisons.rs0000644000175000017500000002046015105742312017567 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; #[path = "../src/tests/common.rs"] mod common; #[pyclass(eq)] #[derive(Debug, Clone, PartialEq)] pub enum MyEnum { Variant, OtherVariant, } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub enum MyEnumOrd { Variant, OtherVariant, } #[test] fn test_enum_eq_enum() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); let var2 = Py::new(py, MyEnum::Variant).unwrap(); let other_var = Py::new(py, MyEnum::OtherVariant).unwrap(); py_assert!(py, var1 var2, "var1 == var2"); py_assert!(py, var1 other_var, "var1 != other_var"); py_assert!(py, var1 var2, "(var1 != var2) == False"); }) } #[test] fn test_enum_eq_incomparable() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); py_assert!(py, var1, "(var1 == 'foo') == False"); py_assert!(py, var1, "(var1 != 'foo') == True"); }) } #[test] fn test_enum_ord_comparable_opt_in_only() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); let var2 = Py::new(py, MyEnum::OtherVariant).unwrap(); // ordering on simple enums if opt in only, thus raising an error below py_expect_exception!(py, var1 var2, "(var1 > var2) == False", PyTypeError); }) } #[test] fn test_simple_enum_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnumOrd::Variant).unwrap(); let var2 = Py::new(py, MyEnumOrd::OtherVariant).unwrap(); let var3 = Py::new(py, MyEnumOrd::OtherVariant).unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == False"); py_assert!(py, var1 var2, "(var1 < var2) == True"); py_assert!(py, var1 var2, "(var1 >= var2) == False"); py_assert!(py, var2 var3, "(var3 >= var2) == True"); py_assert!(py, var1 var2, "(var1 <= var2) == True"); }) } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub enum MyComplexEnumOrd { Variant(i32), OtherVariant(String), } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub enum MyComplexEnumOrd2 { Variant { msg: String, idx: u32 }, OtherVariant { name: String, idx: u32 }, } #[test] fn test_complex_enum_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new(py, MyComplexEnumOrd::Variant(-2)).unwrap(); let var2 = Py::new(py, MyComplexEnumOrd::Variant(5)).unwrap(); let var3 = Py::new(py, MyComplexEnumOrd::OtherVariant("a".to_string())).unwrap(); let var4 = Py::new(py, MyComplexEnumOrd::OtherVariant("b".to_string())).unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == False"); py_assert!(py, var1 var2, "(var1 < var2) == True"); py_assert!(py, var1 var2, "(var1 >= var2) == False"); py_assert!(py, var1 var2, "(var1 <= var2) == True"); py_assert!(py, var1 var3, "(var1 >= var3) == False"); py_assert!(py, var1 var3, "(var1 <= var3) == True"); py_assert!(py, var3 var4, "(var3 >= var4) == False"); py_assert!(py, var3 var4, "(var3 <= var4) == True"); let var5 = Py::new( py, MyComplexEnumOrd2::Variant { msg: "hello".to_string(), idx: 1, }, ) .unwrap(); let var6 = Py::new( py, MyComplexEnumOrd2::Variant { msg: "hello".to_string(), idx: 1, }, ) .unwrap(); let var7 = Py::new( py, MyComplexEnumOrd2::Variant { msg: "goodbye".to_string(), idx: 7, }, ) .unwrap(); let var8 = Py::new( py, MyComplexEnumOrd2::Variant { msg: "about".to_string(), idx: 0, }, ) .unwrap(); let var9 = Py::new( py, MyComplexEnumOrd2::OtherVariant { name: "albert".to_string(), idx: 1, }, ) .unwrap(); py_assert!(py, var5 var6, "(var5 == var6) == True"); py_assert!(py, var5 var6, "(var5 <= var6) == True"); py_assert!(py, var6 var7, "(var6 <= var7) == False"); py_assert!(py, var6 var7, "(var6 >= var7) == True"); py_assert!(py, var5 var8, "(var5 > var8) == True"); py_assert!(py, var8 var9, "(var9 > var8) == True"); }) } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub struct Point { x: i32, y: i32, z: i32, } #[test] fn test_struct_numeric_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new(py, Point { x: 10, y: 2, z: 3 }).unwrap(); let var2 = Py::new(py, Point { x: 2, y: 2, z: 3 }).unwrap(); let var3 = Py::new(py, Point { x: 1, y: 22, z: 4 }).unwrap(); let var4 = Py::new(py, Point { x: 1, y: 3, z: 4 }).unwrap(); let var5 = Py::new(py, Point { x: 1, y: 3, z: 4 }).unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == True"); py_assert!(py, var1 var2, "(var1 <= var2) == False"); py_assert!(py, var2 var3, "(var3 < var2) == True"); py_assert!(py, var3 var4, "(var3 > var4) == True"); py_assert!(py, var4 var5, "(var4 == var5) == True"); py_assert!(py, var3 var5, "(var3 != var5) == True"); }) } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub struct Person { surname: String, given_name: String, } #[test] fn test_struct_string_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new( py, Person { surname: "zzz".to_string(), given_name: "bob".to_string(), }, ) .unwrap(); let var2 = Py::new( py, Person { surname: "aaa".to_string(), given_name: "sally".to_string(), }, ) .unwrap(); let var3 = Py::new( py, Person { surname: "eee".to_string(), given_name: "qqq".to_string(), }, ) .unwrap(); let var4 = Py::new( py, Person { surname: "ddd".to_string(), given_name: "aaa".to_string(), }, ) .unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == True"); py_assert!(py, var1 var2, "(var1 <= var2) == False"); py_assert!(py, var1 var3, "(var1 >= var3) == True"); py_assert!(py, var2 var3, "(var2 >= var3) == False"); py_assert!(py, var3 var4, "(var3 >= var4) == True"); py_assert!(py, var3 var4, "(var3 != var4) == True"); }) } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone)] pub struct Record { name: String, title: String, idx: u32, } impl PartialOrd for Record { fn partial_cmp(&self, other: &Self) -> Option { Some(self.idx.partial_cmp(&other.idx).unwrap()) } } #[test] fn test_struct_custom_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new( py, Record { name: "zzz".to_string(), title: "bbb".to_string(), idx: 9, }, ) .unwrap(); let var2 = Py::new( py, Record { name: "ddd".to_string(), title: "aaa".to_string(), idx: 1, }, ) .unwrap(); let var3 = Py::new( py, Record { name: "vvv".to_string(), title: "ggg".to_string(), idx: 19, }, ) .unwrap(); let var4 = Py::new( py, Record { name: "vvv".to_string(), title: "ggg".to_string(), idx: 19, }, ) .unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == True"); py_assert!(py, var1 var2, "(var1 <= var2) == False"); py_assert!(py, var1 var3, "(var1 >= var3) == False"); py_assert!(py, var2 var3, "(var2 >= var3) == False"); py_assert!(py, var3 var4, "(var3 == var4) == True"); py_assert!(py, var2 var4, "(var2 != var4) == True"); }) } pyo3/tests/test_declarative_module.rs0000644000175000017500000001410715105742312017676 0ustar bdrungbdrung#![cfg(feature = "macros")] use std::sync::Once; use pyo3::create_exception; use pyo3::exceptions::PyException; use pyo3::prelude::*; use pyo3::sync::{GILOnceCell, OnceExt}; #[path = "../src/tests/common.rs"] mod common; mod some_module { use pyo3::create_exception; use pyo3::exceptions::PyException; use pyo3::prelude::*; #[pyclass] pub struct SomePyClass; create_exception!(some_module, SomeException, PyException); } #[pyclass] struct ValueClass { value: usize, } #[pymethods] impl ValueClass { #[new] fn new(value: usize) -> Self { Self { value } } } #[pyclass(module = "module")] pub struct LocatedClass {} #[pyfunction] fn double(x: usize) -> usize { x * 2 } create_exception!( declarative_module, MyError, PyException, "Some description." ); #[pymodule(submodule)] mod external_submodule {} /// A module written using declarative syntax. #[pymodule] mod declarative_module { #[pymodule_export] use super::declarative_submodule; #[pymodule_export] // This is not a real constraint but to test cfg attribute support #[cfg(not(Py_LIMITED_API))] use super::LocatedClass; use super::*; #[pymodule_export] use super::{declarative_module2, double, MyError, ValueClass as Value}; // test for #4036 #[pymodule_export] use super::some_module::SomePyClass; // test for #4036 #[pymodule_export] use super::some_module::SomeException; #[pymodule_export] use super::external_submodule; #[pymodule_export] const FOO: u32 = 42; #[pymodule_export] #[cfg(Py_LIMITED_API)] const BAR: &str = "BAR"; #[pymodule_export] #[allow(non_upper_case_globals)] const r#type: char = '!'; #[allow(unused)] const NOT_EXPORTED: &str = "not exported"; #[pymodule] mod inner { use super::*; #[pyfunction] fn triple(x: usize) -> usize { x * 3 } #[pyclass(name = "Struct")] struct Struct; #[pymethods] impl Struct { #[new] fn new() -> Self { Self } } #[pyclass(module = "foo")] struct StructInCustomModule; #[pyclass(eq, eq_int, name = "Enum")] #[derive(PartialEq)] enum Enum { A, B, } #[pyclass(eq, eq_int, module = "foo")] #[derive(PartialEq)] enum EnumInCustomModule { A, B, } } #[pymodule] #[pyo3(module = "custom_root")] mod inner_custom_root { use super::*; #[pyclass] struct Struct; } #[pyo3::prelude::pymodule] mod full_path_inner {} #[pymodule_init] fn init(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add("double2", m.getattr("double")?) } } #[pyfunction] fn double_value(v: &ValueClass) -> usize { v.value * 2 } #[pymodule] mod declarative_submodule { #[pymodule_export] use super::{double, double_value}; } #[pymodule(name = "declarative_module_renamed")] mod declarative_module2 { #[pymodule_export] use super::double; } fn declarative_module(py: Python<'_>) -> &Bound<'_, PyModule> { static MODULE: GILOnceCell> = GILOnceCell::new(); static ONCE: Once = Once::new(); // Guarantee that the module is only ever initialized once; GILOnceCell can race. // TODO: use OnceLock when MSRV >= 1.70 ONCE.call_once_py_attached(py, || { MODULE .set(py, pyo3::wrap_pymodule!(declarative_module)(py)) .expect("only ever set once"); }); MODULE.get(py).expect("once is completed").bind(py) } #[test] fn test_declarative_module() { Python::with_gil(|py| { let m = declarative_module(py); py_assert!( py, m, "m.__doc__ == 'A module written using declarative syntax.'" ); py_assert!(py, m, "m.double(2) == 4"); py_assert!(py, m, "m.inner.triple(3) == 9"); py_assert!(py, m, "m.declarative_submodule.double(4) == 8"); py_assert!( py, m, "m.declarative_submodule.double_value(m.ValueClass(1)) == 2" ); py_assert!(py, m, "str(m.MyError('foo')) == 'foo'"); py_assert!(py, m, "m.declarative_module_renamed.double(2) == 4"); #[cfg(Py_LIMITED_API)] py_assert!(py, m, "not hasattr(m, 'LocatedClass')"); #[cfg(not(Py_LIMITED_API))] py_assert!(py, m, "hasattr(m, 'LocatedClass')"); py_assert!(py, m, "isinstance(m.inner.Struct(), m.inner.Struct)"); py_assert!(py, m, "isinstance(m.inner.Enum.A, m.inner.Enum)"); py_assert!(py, m, "hasattr(m, 'external_submodule')"); py_assert!(py, m, "m.FOO == 42"); #[cfg(Py_LIMITED_API)] py_assert!(py, m, "m.BAR == 'BAR'"); #[cfg(not(Py_LIMITED_API))] py_assert!(py, m, "not hasattr(m, 'BAR')"); py_assert!(py, m, "m.type == '!'"); py_assert!(py, m, "not hasattr(m, 'NOT_EXPORTED')"); }) } #[pymodule] mod r#type { #[pymodule_export] use super::double; } #[test] fn test_raw_ident_module() { Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(r#type)(py).into_bound(py); py_assert!(py, m, "m.double(2) == 4"); }) } #[test] fn test_module_names() { Python::with_gil(|py| { let m = declarative_module(py); py_assert!( py, m, "m.inner.Struct.__module__ == 'declarative_module.inner'" ); py_assert!(py, m, "m.inner.StructInCustomModule.__module__ == 'foo'"); py_assert!( py, m, "m.inner.Enum.__module__ == 'declarative_module.inner'" ); py_assert!(py, m, "m.inner.EnumInCustomModule.__module__ == 'foo'"); py_assert!( py, m, "m.inner_custom_root.Struct.__module__ == 'custom_root.inner_custom_root'" ); }) } #[test] fn test_inner_module_full_path() { Python::with_gil(|py| { let m = declarative_module(py); py_assert!(py, m, "m.full_path_inner"); }) } pyo3/tests/test_datetime.rs0000644000175000017500000001511215105742312015637 0ustar bdrungbdrung#![cfg(not(Py_LIMITED_API))] use pyo3::types::{IntoPyDict, PyDate, PyDateTime, PyTime, PyTzInfo}; use pyo3::{ffi, prelude::*}; use pyo3_ffi::PyDateTime_IMPORT; use std::ffi::CString; fn _get_subclasses<'py>( py: Python<'py>, py_type: &str, args: &str, ) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyAny>, Bound<'py, PyAny>)> { // Import the class from Python and create some subclasses let datetime = py.import("datetime")?; let locals = [(py_type, datetime.getattr(py_type)?)] .into_py_dict(py) .unwrap(); let make_subclass_py = CString::new(format!("class Subklass({py_type}):\n pass"))?; let make_sub_subclass_py = ffi::c_str!("class SubSubklass(Subklass):\n pass"); py.run(&make_subclass_py, None, Some(&locals))?; py.run(make_sub_subclass_py, None, Some(&locals))?; // Construct an instance of the base class let obj = py.eval( &CString::new(format!("{py_type}({args})"))?, None, Some(&locals), )?; // Construct an instance of the subclass let sub_obj = py.eval( &CString::new(format!("Subklass({args})"))?, None, Some(&locals), )?; // Construct an instance of the sub-subclass let sub_sub_obj = py.eval( &CString::new(format!("SubSubklass({args})"))?, None, Some(&locals), )?; Ok((obj, sub_obj, sub_sub_obj)) } macro_rules! assert_check_exact { ($check_func:ident, $check_func_exact:ident, $obj: expr) => { unsafe { use pyo3::ffi::*; assert!($check_func(($obj).as_ptr()) != 0); assert!($check_func_exact(($obj).as_ptr()) != 0); } }; } macro_rules! assert_check_only { ($check_func:ident, $check_func_exact:ident, $obj: expr) => { unsafe { use pyo3::ffi::*; assert!($check_func(($obj).as_ptr()) != 0); assert!($check_func_exact(($obj).as_ptr()) == 0); } }; } #[test] fn test_date_check() { Python::with_gil(|py| { let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "date", "2018, 1, 1").unwrap(); unsafe { PyDateTime_IMPORT() } assert_check_exact!(PyDate_Check, PyDate_CheckExact, obj); assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_obj); assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_sub_obj); assert!(obj.is_instance_of::()); assert!(!obj.is_instance_of::()); assert!(!obj.is_instance_of::()); }); } #[test] fn test_time_check() { Python::with_gil(|py| { let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "time", "12, 30, 15").unwrap(); unsafe { PyDateTime_IMPORT() } assert_check_exact!(PyTime_Check, PyTime_CheckExact, obj); assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_obj); assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_sub_obj); assert!(!obj.is_instance_of::()); assert!(obj.is_instance_of::()); assert!(!obj.is_instance_of::()); }); } #[test] fn test_datetime_check() { Python::with_gil(|py| { let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "datetime", "2018, 1, 1, 13, 30, 15") .map_err(|e| e.display(py)) .unwrap(); unsafe { PyDateTime_IMPORT() } assert_check_only!(PyDate_Check, PyDate_CheckExact, obj); assert_check_exact!(PyDateTime_Check, PyDateTime_CheckExact, obj); assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_obj); assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_sub_obj); assert!(obj.is_instance_of::()); assert!(!obj.is_instance_of::()); assert!(obj.is_instance_of::()); }); } #[test] fn test_delta_check() { Python::with_gil(|py| { let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "timedelta", "1, -3").unwrap(); unsafe { PyDateTime_IMPORT() } assert_check_exact!(PyDelta_Check, PyDelta_CheckExact, obj); assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_obj); assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_sub_obj); }); } #[test] fn test_datetime_utc() { use assert_approx_eq::assert_approx_eq; use pyo3::types::PyDateTime; Python::with_gil(|py| { let utc = PyTzInfo::utc(py).unwrap(); let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap(); let locals = [("dt", dt)].into_py_dict(py).unwrap(); let offset: f32 = py .eval( ffi::c_str!("dt.utcoffset().total_seconds()"), None, Some(&locals), ) .unwrap() .extract() .unwrap(); assert_approx_eq!(offset, 0f32); }); } static INVALID_DATES: &[(i32, u8, u8)] = &[ (-1, 1, 1), (0, 1, 1), (10000, 1, 1), (2 << 30, 1, 1), (2018, 0, 1), (2018, 13, 1), (2018, 1, 0), (2017, 2, 29), (2018, 1, 32), ]; static INVALID_TIMES: &[(u8, u8, u8, u32)] = &[(25, 0, 0, 0), (255, 0, 0, 0), (0, 60, 0, 0), (0, 0, 61, 0)]; #[test] fn test_pydate_out_of_bounds() { use pyo3::types::PyDate; Python::with_gil(|py| { for val in INVALID_DATES { let (year, month, day) = val; let dt = PyDate::new(py, *year, *month, *day); dt.unwrap_err(); } }); } #[test] fn test_pytime_out_of_bounds() { use pyo3::types::PyTime; Python::with_gil(|py| { for val in INVALID_TIMES { let (hour, minute, second, microsecond) = val; let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None); dt.unwrap_err(); } }); } #[test] fn test_pydatetime_out_of_bounds() { use pyo3::types::PyDateTime; use std::iter; Python::with_gil(|py| { let valid_time = (0, 0, 0, 0); let valid_date = (2018, 1, 1); let invalid_dates = INVALID_DATES.iter().zip(iter::repeat(&valid_time)); let invalid_times = iter::repeat(&valid_date).zip(INVALID_TIMES.iter()); let vals = invalid_dates.chain(invalid_times); for val in vals { let (date, time) = val; let (year, month, day) = date; let (hour, minute, second, microsecond) = time; let dt = PyDateTime::new( py, *year, *month, *day, *hour, *minute, *second, *microsecond, None, ); dt.unwrap_err(); } }); } pyo3/tests/test_pyfunction.rs0000644000175000017500000004377315105742312016257 0ustar bdrungbdrung#![cfg(feature = "macros")] #![cfg_attr(not(cargo_toml_lints), warn(unsafe_op_in_unsafe_fn))] use std::collections::HashMap; #[cfg(not(Py_LIMITED_API))] use pyo3::buffer::PyBuffer; use pyo3::ffi::c_str; use pyo3::prelude::*; #[cfg(not(Py_LIMITED_API))] use pyo3::types::PyDateTime; #[cfg(not(any(Py_LIMITED_API, PyPy)))] use pyo3::types::PyFunction; use pyo3::types::{self, PyCFunction}; #[path = "../src/tests/common.rs"] mod common; #[pyfunction(name = "struct")] fn struct_function() {} #[test] fn test_rust_keyword_name() { Python::with_gil(|py| { let f = wrap_pyfunction!(struct_function)(py).unwrap(); py_assert!(py, f, "f.__name__ == 'struct'"); }); } #[pyfunction(signature = (arg = true))] fn optional_bool(arg: Option) -> String { format!("{arg:?}") } #[test] fn test_optional_bool() { // Regression test for issue #932 Python::with_gil(|py| { let f = wrap_pyfunction!(optional_bool)(py).unwrap(); py_assert!(py, f, "f() == 'Some(true)'"); py_assert!(py, f, "f(True) == 'Some(true)'"); py_assert!(py, f, "f(False) == 'Some(false)'"); py_assert!(py, f, "f(None) == 'None'"); }); } #[pyfunction] #[pyo3(signature=(arg))] fn required_optional_str(arg: Option<&str>) -> &str { arg.unwrap_or("") } #[test] fn test_optional_str() { // Regression test for issue #4965 Python::with_gil(|py| { let f = wrap_pyfunction!(required_optional_str)(py).unwrap(); py_assert!(py, f, "f('') == ''"); py_assert!(py, f, "f('foo') == 'foo'"); py_assert!(py, f, "f(None) == ''"); }); } #[pyclass] struct MyClass(); #[pyfunction] #[pyo3(signature=(arg))] fn required_optional_class(arg: Option<&MyClass>) { let _ = arg; } #[test] fn test_required_optional_class() { // Regression test for issue #4965 Python::with_gil(|py| { let f = wrap_pyfunction!(required_optional_class)(py).unwrap(); let val = Bound::new(py, MyClass()).unwrap(); py_assert!(py, f val, "f(val) is None"); py_assert!(py, f, "f(None) is None"); }); } #[cfg(not(Py_LIMITED_API))] #[pyfunction] fn buffer_inplace_add(py: Python<'_>, x: PyBuffer, y: PyBuffer) { let x = x.as_mut_slice(py).unwrap(); let y = y.as_slice(py).unwrap(); for (xi, yi) in x.iter().zip(y) { let xi_plus_yi = xi.get() + yi.get(); xi.set(xi_plus_yi); } } #[cfg(not(Py_LIMITED_API))] #[test] fn test_buffer_add() { Python::with_gil(|py| { let f = wrap_pyfunction!(buffer_inplace_add)(py).unwrap(); py_expect_exception!( py, f, r#" import array a = array.array("i", [0, 1, 2, 3]) b = array.array("I", [0, 1, 2, 3]) f(a, b) "#, PyBufferError ); pyo3::py_run!( py, f, r#" import array a = array.array("i", [0, 1, 2, 3]) b = array.array("i", [2, 3, 4, 5]) f(a, b) assert a, array.array("i", [2, 4, 6, 8]) "# ); }); } #[cfg(not(any(Py_LIMITED_API, PyPy)))] #[pyfunction] fn function_with_pyfunction_arg<'py>(fun: &Bound<'py, PyFunction>) -> PyResult> { fun.call((), None) } #[pyfunction] fn function_with_pycfunction_arg<'py>( fun: &Bound<'py, PyCFunction>, ) -> PyResult> { fun.call((), None) } #[test] fn test_functions_with_function_args() { Python::with_gil(|py| { let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(py).unwrap(); let bool_to_string = wrap_pyfunction!(optional_bool)(py).unwrap(); pyo3::py_run!( py, py_cfunc_arg bool_to_string, r#" assert py_cfunc_arg(bool_to_string) == "Some(true)" "# ); #[cfg(not(any(Py_LIMITED_API, PyPy)))] { let py_func_arg = wrap_pyfunction!(function_with_pyfunction_arg)(py).unwrap(); pyo3::py_run!( py, py_func_arg, r#" def foo(): return "bar" assert py_func_arg(foo) == "bar" "# ); } }); } #[cfg(not(Py_LIMITED_API))] fn datetime_to_timestamp(dt: &Bound<'_, PyAny>) -> PyResult { let dt = dt.downcast::()?; let ts: f64 = dt.call_method0("timestamp")?.extract()?; Ok(ts as i64) } #[cfg(not(Py_LIMITED_API))] #[pyfunction] fn function_with_custom_conversion( #[pyo3(from_py_with = datetime_to_timestamp)] timestamp: i64, ) -> i64 { timestamp } #[cfg(not(Py_LIMITED_API))] #[test] fn test_function_with_custom_conversion() { Python::with_gil(|py| { let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap(); pyo3::py_run!( py, custom_conv_func, r#" import datetime dt = datetime.datetime.fromtimestamp(1612040400) assert custom_conv_func(dt) == 1612040400 "# ) }); } #[cfg(not(Py_LIMITED_API))] #[test] fn test_function_with_custom_conversion_error() { Python::with_gil(|py| { let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap(); py_expect_exception!( py, custom_conv_func, "custom_conv_func(['a'])", PyTypeError, "argument 'timestamp': 'list' object cannot be converted to 'PyDateTime'" ); }); } #[test] fn test_from_py_with_defaults() { fn optional_int(x: &Bound<'_, PyAny>) -> PyResult> { if x.is_none() { Ok(None) } else { Some(x.extract()).transpose() } } // issue 2280 combination of from_py_with and Option did not compile #[pyfunction] #[pyo3(signature = (int=None))] fn from_py_with_option(#[pyo3(from_py_with = optional_int)] int: Option) -> i32 { int.unwrap_or(0) } #[pyfunction(signature = (len=0))] fn from_py_with_default( #[pyo3(from_py_with = as PyAnyMethods>::len)] len: usize, ) -> usize { len } Python::with_gil(|py| { let f = wrap_pyfunction!(from_py_with_option)(py).unwrap(); assert_eq!(f.call0().unwrap().extract::().unwrap(), 0); assert_eq!(f.call1((123,)).unwrap().extract::().unwrap(), 123); assert_eq!(f.call1((999,)).unwrap().extract::().unwrap(), 999); let f2 = wrap_pyfunction!(from_py_with_default)(py).unwrap(); assert_eq!(f2.call0().unwrap().extract::().unwrap(), 0); assert_eq!(f2.call1(("123",)).unwrap().extract::().unwrap(), 3); assert_eq!(f2.call1(("1234",)).unwrap().extract::().unwrap(), 4); }); } #[pyclass] #[derive(Debug, FromPyObject)] struct ValueClass { #[pyo3(get)] value: usize, } #[pyfunction] #[pyo3(signature=(str_arg, int_arg, tuple_arg, option_arg = None, struct_arg = None))] fn conversion_error( str_arg: &str, int_arg: i64, tuple_arg: (String, f64), option_arg: Option, struct_arg: Option, ) { println!("{str_arg:?} {int_arg:?} {tuple_arg:?} {option_arg:?} {struct_arg:?}"); } #[test] fn test_conversion_error() { Python::with_gil(|py| { let conversion_error = wrap_pyfunction!(conversion_error)(py).unwrap(); py_expect_exception!( py, conversion_error, "conversion_error(None, None, None, None, None)", PyTypeError, "argument 'str_arg': 'NoneType' object cannot be converted to 'PyString'" ); py_expect_exception!( py, conversion_error, "conversion_error(100, None, None, None, None)", PyTypeError, "argument 'str_arg': 'int' object cannot be converted to 'PyString'" ); py_expect_exception!( py, conversion_error, "conversion_error('string1', 'string2', None, None, None)", PyTypeError, "argument 'int_arg': 'str' object cannot be interpreted as an integer" ); py_expect_exception!( py, conversion_error, "conversion_error('string1', -100, 'string2', None, None)", PyTypeError, "argument 'tuple_arg': 'str' object cannot be converted to 'PyTuple'" ); py_expect_exception!( py, conversion_error, "conversion_error('string1', -100, ('string2', 10.), 'string3', None)", PyTypeError, "argument 'option_arg': 'str' object cannot be interpreted as an integer" ); let exception = py_expect_exception!( py, conversion_error, " class ValueClass: def __init__(self, value): self.value = value conversion_error('string1', -100, ('string2', 10.), None, ValueClass(\"no_expected_type\"))", PyTypeError ); assert_eq!( extract_traceback(py, exception), "TypeError: argument 'struct_arg': failed to \ extract field ValueClass.value: TypeError: 'str' object cannot be interpreted as an integer" ); let exception = py_expect_exception!( py, conversion_error, " class ValueClass: def __init__(self, value): self.value = value conversion_error('string1', -100, ('string2', 10.), None, ValueClass(-5))", PyTypeError ); assert_eq!( extract_traceback(py, exception), "TypeError: argument 'struct_arg': failed to \ extract field ValueClass.value: OverflowError: can't convert negative int to unsigned" ); }); } /// Helper function that concatenates the error message from /// each error in the traceback into a single string that can /// be tested. fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String { let mut error_msg = error.to_string(); while let Some(cause) = error.cause(py) { error_msg.push_str(": "); error_msg.push_str(&cause.to_string()); error = cause } error_msg } #[test] fn test_pycfunction_new() { use pyo3::ffi; Python::with_gil(|py| { unsafe extern "C" fn c_fn( _self: *mut ffi::PyObject, _args: *mut ffi::PyObject, ) -> *mut ffi::PyObject { unsafe { ffi::PyLong_FromLong(4200) } } let py_fn = PyCFunction::new( py, c_fn, c_str!("py_fn"), c_str!("py_fn for test (this is the docstring)"), None, ) .unwrap(); py_assert!(py, py_fn, "py_fn() == 4200"); py_assert!( py, py_fn, "py_fn.__doc__ == 'py_fn for test (this is the docstring)'" ); }); } #[test] fn test_pycfunction_new_with_keywords() { use pyo3::ffi; use std::os::raw::c_long; use std::ptr; Python::with_gil(|py| { unsafe extern "C" fn c_fn( _self: *mut ffi::PyObject, args: *mut ffi::PyObject, kwds: *mut ffi::PyObject, ) -> *mut ffi::PyObject { let mut foo: c_long = 0; let mut bar: c_long = 0; #[cfg(not(Py_3_13))] let foo_name = std::ffi::CString::new("foo").unwrap(); #[cfg(not(Py_3_13))] let kw_bar_name = std::ffi::CString::new("kw_bar").unwrap(); #[cfg(not(Py_3_13))] let mut args_names = [foo_name.into_raw(), kw_bar_name.into_raw(), ptr::null_mut()]; #[cfg(Py_3_13)] let args_names = [ c_str!("foo").as_ptr(), c_str!("kw_bar").as_ptr(), ptr::null_mut(), ]; unsafe { ffi::PyArg_ParseTupleAndKeywords( args, kwds, c_str!("l|l").as_ptr(), #[cfg(Py_3_13)] args_names.as_ptr(), #[cfg(not(Py_3_13))] args_names.as_mut_ptr(), &mut foo, &mut bar, ) }; #[cfg(not(Py_3_13))] drop(unsafe { std::ffi::CString::from_raw(args_names[0]) }); #[cfg(not(Py_3_13))] drop(unsafe { std::ffi::CString::from_raw(args_names[1]) }); unsafe { ffi::PyLong_FromLong(foo * bar) } } let py_fn = PyCFunction::new_with_keywords( py, c_fn, c_str!("py_fn"), c_str!("py_fn for test (this is the docstring)"), None, ) .unwrap(); py_assert!(py, py_fn, "py_fn(42, kw_bar=100) == 4200"); py_assert!(py, py_fn, "py_fn(foo=42, kw_bar=100) == 4200"); py_assert!( py, py_fn, "py_fn.__doc__ == 'py_fn for test (this is the docstring)'" ); }); } #[test] fn test_closure() { Python::with_gil(|py| { let f = |args: &Bound<'_, types::PyTuple>, _kwargs: Option<&Bound<'_, types::PyDict>>| -> PyResult<_> { Python::with_gil(|py| { let res: PyResult> = args .iter() .map(|elem| { if let Ok(i) = elem.extract::() { Ok((i + 1).into_pyobject(py)?.into_any().unbind()) } else if let Ok(f) = elem.extract::() { Ok((2. * f).into_pyobject(py)?.into_any().unbind()) } else if let Ok(mut s) = elem.extract::() { s.push_str("-py"); Ok(s.into_pyobject(py)?.into_any().unbind()) } else { panic!("unexpected argument type for {elem:?}") } }) .collect(); res }) }; let closure_py = PyCFunction::new_closure(py, Some(c_str!("test_fn")), Some(c_str!("test_fn doc")), f) .unwrap(); py_assert!(py, closure_py, "closure_py(42) == [43]"); py_assert!(py, closure_py, "closure_py.__name__ == 'test_fn'"); py_assert!(py, closure_py, "closure_py.__doc__ == 'test_fn doc'"); py_assert!( py, closure_py, "closure_py(42, 3.14, 'foo') == [43, 6.28, 'foo-py']" ); }); } #[test] fn test_closure_counter() { Python::with_gil(|py| { let counter = std::cell::RefCell::new(0); let counter_fn = move |_args: &Bound<'_, types::PyTuple>, _kwargs: Option<&Bound<'_, types::PyDict>>| -> PyResult { let mut counter = counter.borrow_mut(); *counter += 1; Ok(*counter) }; let counter_py = PyCFunction::new_closure(py, None, None, counter_fn).unwrap(); py_assert!(py, counter_py, "counter_py() == 1"); py_assert!(py, counter_py, "counter_py() == 2"); py_assert!(py, counter_py, "counter_py() == 3"); }); } #[test] fn use_pyfunction() { mod function_in_module { use pyo3::prelude::*; #[pyfunction] pub fn foo(x: i32) -> i32 { x } } Python::with_gil(|py| { use function_in_module::foo; // check imported name can be wrapped let f = wrap_pyfunction!(foo, py).unwrap(); assert_eq!(f.call1((5,)).unwrap().extract::().unwrap(), 5); assert_eq!(f.call1((42,)).unwrap().extract::().unwrap(), 42); // check path import can be wrapped let f2 = wrap_pyfunction!(function_in_module::foo, py).unwrap(); assert_eq!(f2.call1((5,)).unwrap().extract::().unwrap(), 5); assert_eq!(f2.call1((42,)).unwrap().extract::().unwrap(), 42); }) } #[pyclass] struct Key(String); #[pyclass] struct Value(i32); #[pyfunction] fn return_value_borrows_from_arguments<'py>( py: Python<'py>, key: &'py Key, value: &'py Value, ) -> HashMap<&'py str, i32> { py.allow_threads(move || { let mut map = HashMap::new(); map.insert(key.0.as_str(), value.0); map }) } #[test] fn test_return_value_borrows_from_arguments() { Python::with_gil(|py| { let function = wrap_pyfunction!(return_value_borrows_from_arguments, py).unwrap(); let key = Py::new(py, Key("key".to_owned())).unwrap(); let value = Py::new(py, Value(42)).unwrap(); py_assert!(py, function key value, "function(key, value) == { \"key\": 42 }"); }); } #[test] fn test_some_wrap_arguments() { // https://github.com/PyO3/pyo3/issues/3460 const NONE: Option = None; #[pyfunction(signature = (a = 1, b = Some(2), c = None, d = NONE))] fn some_wrap_arguments( a: Option, b: Option, c: Option, d: Option, ) -> [Option; 4] { [a, b, c, d] } Python::with_gil(|py| { let function = wrap_pyfunction!(some_wrap_arguments, py).unwrap(); py_assert!(py, function, "function() == [1, 2, None, None]"); }) } #[test] fn test_reference_to_bound_arguments() { #[pyfunction] #[pyo3(signature = (x, y = None))] fn reference_args<'py>( x: &Bound<'py, PyAny>, y: Option<&Bound<'py, PyAny>>, ) -> PyResult> { y.map_or_else(|| Ok(x.clone()), |y| y.add(x)) } Python::with_gil(|py| { let function = wrap_pyfunction!(reference_args, py).unwrap(); py_assert!(py, function, "function(1) == 1"); py_assert!(py, function, "function(1, 2) == 3"); }) } #[test] fn test_pyfunction_raw_ident() { #[pyfunction] fn r#struct() -> bool { true } #[pyfunction] #[pyo3(name = "r#enum")] fn raw_ident() -> bool { true } #[pymodule] fn m(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(r#struct, m)?)?; m.add_function(wrap_pyfunction!(raw_ident, m)?)?; Ok(()) } Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(m)(py); py_assert!(py, m, "m.struct()"); py_assert!(py, m, "m.enum()"); }) } pyo3/tests/test_class_new.rs0000644000175000017500000001661015105742312016025 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::sync::GILOnceCell; use pyo3::types::IntoPyDict; #[pyclass] struct EmptyClassWithNew {} #[pymethods] impl EmptyClassWithNew { #[new] fn new() -> EmptyClassWithNew { EmptyClassWithNew {} } } #[test] fn empty_class_with_new() { Python::with_gil(|py| { let typeobj = py.get_type::(); assert!(typeobj .call((), None) .unwrap() .downcast::() .is_ok()); // Calling with arbitrary args or kwargs is not ok assert!(typeobj.call(("some", "args"), None).is_err()); assert!(typeobj .call((), Some(&[("some", "kwarg")].into_py_dict(py).unwrap())) .is_err()); }); } #[pyclass] struct UnitClassWithNew; #[pymethods] impl UnitClassWithNew { #[new] fn new() -> Self { Self } } #[test] fn unit_class_with_new() { Python::with_gil(|py| { let typeobj = py.get_type::(); assert!(typeobj .call((), None) .unwrap() .downcast::() .is_ok()); }); } #[pyclass] struct TupleClassWithNew(i32); #[pymethods] impl TupleClassWithNew { #[new] fn new(arg: i32) -> Self { Self(arg) } } #[test] fn tuple_class_with_new() { Python::with_gil(|py| { let typeobj = py.get_type::(); let wrp = typeobj.call((42,), None).unwrap(); let obj = wrp.downcast::().unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.0, 42); }); } #[pyclass] #[derive(Debug)] struct NewWithOneArg { data: i32, } #[pymethods] impl NewWithOneArg { #[new] fn new(arg: i32) -> NewWithOneArg { NewWithOneArg { data: arg } } } #[test] fn new_with_one_arg() { Python::with_gil(|py| { let typeobj = py.get_type::(); let wrp = typeobj.call((42,), None).unwrap(); let obj = wrp.downcast::().unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.data, 42); }); } #[pyclass] struct NewWithTwoArgs { data1: i32, data2: i32, } #[pymethods] impl NewWithTwoArgs { #[new] fn new(arg1: i32, arg2: i32) -> Self { NewWithTwoArgs { data1: arg1, data2: arg2, } } } #[test] fn new_with_two_args() { Python::with_gil(|py| { let typeobj = py.get_type::(); let wrp = typeobj .call((10, 20), None) .map_err(|e| e.display(py)) .unwrap(); let obj = wrp.downcast::().unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.data1, 10); assert_eq!(obj_ref.data2, 20); }); } #[pyclass(subclass)] struct SuperClass { #[pyo3(get)] from_rust: bool, } #[pymethods] impl SuperClass { #[new] fn new() -> Self { SuperClass { from_rust: true } } } /// Checks that `subclass.__new__` works correctly. /// See https://github.com/PyO3/pyo3/issues/947 for the corresponding bug. #[test] fn subclass_new() { Python::with_gil(|py| { let super_cls = py.get_type::(); let source = pyo3_ffi::c_str!(pyo3::indoc::indoc!( r#" class Class(SuperClass): def __new__(cls): return super().__new__(cls) # This should return an instance of Class @property def from_rust(self): return False c = Class() assert c.from_rust is False "# )); let globals = PyModule::import(py, "__main__").unwrap().dict(); globals.set_item("SuperClass", super_cls).unwrap(); py.run(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); } #[pyclass] #[derive(Debug)] struct NewWithCustomError {} struct CustomError; impl From for PyErr { fn from(_error: CustomError) -> PyErr { PyValueError::new_err("custom error") } } #[pymethods] impl NewWithCustomError { #[new] fn new() -> Result { Err(CustomError) } } #[test] fn new_with_custom_error() { Python::with_gil(|py| { let typeobj = py.get_type::(); let err = typeobj.call0().unwrap_err(); assert_eq!(err.to_string(), "ValueError: custom error"); }); } #[pyclass] struct NewExisting { #[pyo3(get)] num: usize, } #[pymethods] impl NewExisting { #[new] fn new(py: pyo3::Python<'_>, val: usize) -> pyo3::Py { static PRE_BUILT: GILOnceCell<[pyo3::Py; 2]> = GILOnceCell::new(); let existing = PRE_BUILT.get_or_init(py, || { [ pyo3::Py::new(py, NewExisting { num: 0 }).unwrap(), pyo3::Py::new(py, NewExisting { num: 1 }).unwrap(), ] }); if val < existing.len() { return existing[val].clone_ref(py); } pyo3::Py::new(py, NewExisting { num: val }).unwrap() } } #[test] fn test_new_existing() { Python::with_gil(|py| { let typeobj = py.get_type::(); let obj1 = typeobj.call1((0,)).unwrap(); let obj2 = typeobj.call1((0,)).unwrap(); let obj3 = typeobj.call1((1,)).unwrap(); let obj4 = typeobj.call1((1,)).unwrap(); let obj5 = typeobj.call1((2,)).unwrap(); let obj6 = typeobj.call1((2,)).unwrap(); assert!(obj1.getattr("num").unwrap().extract::().unwrap() == 0); assert!(obj2.getattr("num").unwrap().extract::().unwrap() == 0); assert!(obj3.getattr("num").unwrap().extract::().unwrap() == 1); assert!(obj4.getattr("num").unwrap().extract::().unwrap() == 1); assert!(obj5.getattr("num").unwrap().extract::().unwrap() == 2); assert!(obj6.getattr("num").unwrap().extract::().unwrap() == 2); assert!(obj1.is(&obj2)); assert!(obj3.is(&obj4)); assert!(!obj1.is(&obj3)); assert!(!obj1.is(&obj5)); assert!(!obj5.is(&obj6)); }); } #[pyclass] struct NewReturnsPy; #[pymethods] impl NewReturnsPy { #[new] fn new(py: Python<'_>) -> PyResult> { Py::new(py, NewReturnsPy) } } #[test] fn test_new_returns_py() { Python::with_gil(|py| { let type_ = py.get_type::(); let obj = type_.call0().unwrap(); assert!(obj.is_exact_instance_of::()); }) } #[pyclass] struct NewReturnsBound; #[pymethods] impl NewReturnsBound { #[new] fn new(py: Python<'_>) -> PyResult> { Bound::new(py, NewReturnsBound) } } #[test] fn test_new_returns_bound() { Python::with_gil(|py| { let type_ = py.get_type::(); let obj = type_.call0().unwrap(); assert!(obj.is_exact_instance_of::()); }) } #[pyo3::pyclass] struct NewClassMethod { #[pyo3(get)] cls: pyo3::PyObject, } #[pyo3::pymethods] impl NewClassMethod { #[new] #[classmethod] fn new(cls: &pyo3::Bound<'_, pyo3::types::PyType>) -> Self { Self { cls: cls.clone().into_any().unbind(), } } } #[test] fn test_new_class_method() { pyo3::Python::with_gil(|py| { let cls = py.get_type::(); pyo3::py_run!(py, cls, "assert cls().cls is cls"); }); } pyo3/tests/test_arithmetics.rs0000644000175000017500000006040215105742312016361 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::class::basic::CompareOp; use pyo3::py_run; use pyo3::{prelude::*, BoundObject}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct UnaryArithmetic { inner: f64, } #[pymethods] impl UnaryArithmetic { #[new] fn new(value: f64) -> Self { UnaryArithmetic { inner: value } } fn __repr__(&self) -> String { format!("UA({})", self.inner) } fn __neg__(&self) -> Self { Self::new(-self.inner) } fn __pos__(&self) -> Self { Self::new(self.inner) } fn __abs__(&self) -> Self { Self::new(self.inner.abs()) } fn __invert__(&self) -> Self { Self::new(self.inner.recip()) } #[pyo3(signature=(_ndigits=None))] fn __round__(&self, _ndigits: Option) -> Self { Self::new(self.inner.round()) } } #[test] fn unary_arithmetic() { Python::with_gil(|py| { let c = Py::new(py, UnaryArithmetic::new(2.7)).unwrap(); py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'"); py_run!(py, c, "assert repr(+c) == 'UA(2.7)'"); py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'"); py_run!(py, c, "assert repr(~c) == 'UA(0.37037037037037035)'"); py_run!(py, c, "assert repr(round(c)) == 'UA(3)'"); py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'"); let c: Bound<'_, PyAny> = c.extract(py).unwrap(); assert_py_eq!(c.neg().unwrap().repr().unwrap().as_any(), "UA(-2.7)"); assert_py_eq!(c.pos().unwrap().repr().unwrap().as_any(), "UA(2.7)"); assert_py_eq!(c.abs().unwrap().repr().unwrap().as_any(), "UA(2.7)"); assert_py_eq!( c.bitnot().unwrap().repr().unwrap().as_any(), "UA(0.37037037037037035)" ); }); } #[pyclass] struct Indexable(i32); #[pymethods] impl Indexable { fn __index__(&self) -> i32 { self.0 } fn __int__(&self) -> i32 { self.0 } fn __float__(&self) -> f64 { f64::from(self.0) } fn __invert__(&self) -> Self { Self(!self.0) } } #[test] fn indexable() { Python::with_gil(|py| { let i = Py::new(py, Indexable(5)).unwrap(); py_run!(py, i, "assert int(i) == 5"); py_run!(py, i, "assert [0, 1, 2, 3, 4, 5][i] == 5"); py_run!(py, i, "assert float(i) == 5.0"); py_run!(py, i, "assert int(~i) == -6"); }) } #[pyclass] struct InPlaceOperations { value: u32, } #[pymethods] impl InPlaceOperations { fn __repr__(&self) -> String { format!("IPO({:?})", self.value) } fn __iadd__(&mut self, other: u32) { self.value += other; } fn __isub__(&mut self, other: u32) { self.value -= other; } fn __imul__(&mut self, other: u32) { self.value *= other; } fn __ilshift__(&mut self, other: u32) { self.value <<= other; } fn __irshift__(&mut self, other: u32) { self.value >>= other; } fn __iand__(&mut self, other: u32) { self.value &= other; } fn __ixor__(&mut self, other: u32) { self.value ^= other; } fn __ior__(&mut self, other: u32) { self.value |= other; } fn __ipow__(&mut self, other: u32, _modulo: Option) { self.value = self.value.pow(other); } } #[test] fn inplace_operations() { Python::with_gil(|py| { let init = |value, code| { let c = Py::new(py, InPlaceOperations { value }).unwrap(); py_run!(py, c, code); }; init(0, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'"); init(10, "d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'"); init(3, "d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'"); init(3, "d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'"); init(12, "d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'"); init(12, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'"); init(12, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'"); init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'"); init(3, "d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'"); init( 3, "d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'", ); }); } #[pyclass] struct BinaryArithmetic {} #[pymethods] impl BinaryArithmetic { fn __repr__(&self) -> &'static str { "BA" } fn __add__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA + {rhs:?}") } fn __sub__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA - {rhs:?}") } fn __mul__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA * {rhs:?}") } fn __matmul__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA @ {rhs:?}") } fn __truediv__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA / {rhs:?}") } fn __floordiv__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA // {rhs:?}") } fn __mod__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA % {rhs:?}") } fn __divmod__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("divmod(BA, {rhs:?})") } fn __lshift__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA << {rhs:?}") } fn __rshift__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA >> {rhs:?}") } fn __and__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA & {rhs:?}") } fn __xor__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA ^ {rhs:?}") } fn __or__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA | {rhs:?}") } fn __pow__(&self, rhs: &Bound<'_, PyAny>, mod_: Option) -> String { format!("BA ** {rhs:?} (mod: {mod_:?})") } } #[test] fn binary_arithmetic() { Python::with_gil(|py| { let c = Py::new(py, BinaryArithmetic {}).unwrap(); py_run!(py, c, "assert c + c == 'BA + BA'"); py_run!(py, c, "assert c.__add__(c) == 'BA + BA'"); py_run!(py, c, "assert c + 1 == 'BA + 1'"); py_run!(py, c, "assert c - 1 == 'BA - 1'"); py_run!(py, c, "assert c * 1 == 'BA * 1'"); py_run!(py, c, "assert c @ 1 == 'BA @ 1'"); py_run!(py, c, "assert c / 1 == 'BA / 1'"); py_run!(py, c, "assert c // 1 == 'BA // 1'"); py_run!(py, c, "assert c % 1 == 'BA % 1'"); py_run!(py, c, "assert divmod(c, 1) == 'divmod(BA, 1)'"); py_run!(py, c, "assert c << 1 == 'BA << 1'"); py_run!(py, c, "assert c >> 1 == 'BA >> 1'"); py_run!(py, c, "assert c & 1 == 'BA & 1'"); py_run!(py, c, "assert c ^ 1 == 'BA ^ 1'"); py_run!(py, c, "assert c | 1 == 'BA | 1'"); py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'"); // Class with __add__ only should not allow the reverse op; // this is consistent with Python classes. py_expect_exception!(py, c, "1 + c", PyTypeError); py_expect_exception!(py, c, "1 - c", PyTypeError); py_expect_exception!(py, c, "1 * c", PyTypeError); py_expect_exception!(py, c, "1 @ c", PyTypeError); py_expect_exception!(py, c, "1 / c", PyTypeError); py_expect_exception!(py, c, "1 // c", PyTypeError); py_expect_exception!(py, c, "1 % c", PyTypeError); py_expect_exception!(py, c, "divmod(1, c)", PyTypeError); py_expect_exception!(py, c, "1 << c", PyTypeError); py_expect_exception!(py, c, "1 >> c", PyTypeError); py_expect_exception!(py, c, "1 & c", PyTypeError); py_expect_exception!(py, c, "1 ^ c", PyTypeError); py_expect_exception!(py, c, "1 | c", PyTypeError); py_expect_exception!(py, c, "1 ** c", PyTypeError); py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'"); let c: Bound<'_, PyAny> = c.extract(py).unwrap(); assert_py_eq!(c.add(&c).unwrap(), "BA + BA"); assert_py_eq!(c.sub(&c).unwrap(), "BA - BA"); assert_py_eq!(c.mul(&c).unwrap(), "BA * BA"); assert_py_eq!(c.matmul(&c).unwrap(), "BA @ BA"); assert_py_eq!(c.div(&c).unwrap(), "BA / BA"); assert_py_eq!(c.floor_div(&c).unwrap(), "BA // BA"); assert_py_eq!(c.rem(&c).unwrap(), "BA % BA"); assert_py_eq!(c.divmod(&c).unwrap(), "divmod(BA, BA)"); assert_py_eq!(c.lshift(&c).unwrap(), "BA << BA"); assert_py_eq!(c.rshift(&c).unwrap(), "BA >> BA"); assert_py_eq!(c.bitand(&c).unwrap(), "BA & BA"); assert_py_eq!(c.bitor(&c).unwrap(), "BA | BA"); assert_py_eq!(c.bitxor(&c).unwrap(), "BA ^ BA"); assert_py_eq!(c.pow(&c, py.None()).unwrap(), "BA ** BA (mod: None)"); }); } #[pyclass] struct RhsArithmetic {} #[pymethods] impl RhsArithmetic { fn __radd__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} + RA") } fn __rsub__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} - RA") } fn __rmul__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} * RA") } fn __rlshift__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} << RA") } fn __rrshift__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} >> RA") } fn __rand__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} & RA") } fn __rxor__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} ^ RA") } fn __ror__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} | RA") } fn __rpow__(&self, other: &Bound<'_, PyAny>, _mod: Option<&Bound<'_, PyAny>>) -> String { format!("{other:?} ** RA") } } #[test] fn rhs_arithmetic() { Python::with_gil(|py| { let c = Py::new(py, RhsArithmetic {}).unwrap(); py_run!(py, c, "assert c.__radd__(1) == '1 + RA'"); py_run!(py, c, "assert 1 + c == '1 + RA'"); py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'"); py_run!(py, c, "assert 1 - c == '1 - RA'"); py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'"); py_run!(py, c, "assert 1 * c == '1 * RA'"); py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'"); py_run!(py, c, "assert 1 << c == '1 << RA'"); py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'"); py_run!(py, c, "assert 1 >> c == '1 >> RA'"); py_run!(py, c, "assert c.__rand__(1) == '1 & RA'"); py_run!(py, c, "assert 1 & c == '1 & RA'"); py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'"); py_run!(py, c, "assert 1 ^ c == '1 ^ RA'"); py_run!(py, c, "assert c.__ror__(1) == '1 | RA'"); py_run!(py, c, "assert 1 | c == '1 | RA'"); py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'"); py_run!(py, c, "assert 1 ** c == '1 ** RA'"); }); } #[pyclass] struct LhsAndRhs {} impl std::fmt::Debug for LhsAndRhs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "LR") } } #[pymethods] impl LhsAndRhs { // fn __repr__(&self) -> &'static str { // "BA" // } fn __add__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} + {rhs:?}") } fn __sub__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} - {rhs:?}") } fn __mul__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} * {rhs:?}") } fn __lshift__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} << {rhs:?}") } fn __rshift__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} >> {rhs:?}") } fn __and__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} & {rhs:?}") } fn __xor__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} ^ {rhs:?}") } fn __or__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} | {rhs:?}") } fn __pow__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>, _mod: Option) -> String { format!("{lhs:?} ** {rhs:?}") } fn __matmul__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{lhs:?} @ {rhs:?}") } fn __radd__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} + RA") } fn __rsub__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} - RA") } fn __rmul__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} * RA") } fn __rlshift__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} << RA") } fn __rrshift__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} >> RA") } fn __rand__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} & RA") } fn __rxor__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} ^ RA") } fn __ror__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} | RA") } fn __rpow__(&self, other: &Bound<'_, PyAny>, _mod: Option<&Bound<'_, PyAny>>) -> String { format!("{other:?} ** RA") } fn __rmatmul__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} @ RA") } fn __rtruediv__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} / RA") } fn __rfloordiv__(&self, other: &Bound<'_, PyAny>) -> String { format!("{other:?} // RA") } } #[test] fn lhs_fellback_to_rhs() { Python::with_gil(|py| { let c = Py::new(py, LhsAndRhs {}).unwrap(); // If the light hand value is `LhsAndRhs`, LHS is used. py_run!(py, c, "assert c + 1 == 'LR + 1'"); py_run!(py, c, "assert c - 1 == 'LR - 1'"); py_run!(py, c, "assert c * 1 == 'LR * 1'"); py_run!(py, c, "assert c << 1 == 'LR << 1'"); py_run!(py, c, "assert c >> 1 == 'LR >> 1'"); py_run!(py, c, "assert c & 1 == 'LR & 1'"); py_run!(py, c, "assert c ^ 1 == 'LR ^ 1'"); py_run!(py, c, "assert c | 1 == 'LR | 1'"); py_run!(py, c, "assert c ** 1 == 'LR ** 1'"); py_run!(py, c, "assert c @ 1 == 'LR @ 1'"); // Fellback to RHS because of type mismatching py_run!(py, c, "assert 1 + c == '1 + RA'"); py_run!(py, c, "assert 1 - c == '1 - RA'"); py_run!(py, c, "assert 1 * c == '1 * RA'"); py_run!(py, c, "assert 1 << c == '1 << RA'"); py_run!(py, c, "assert 1 >> c == '1 >> RA'"); py_run!(py, c, "assert 1 & c == '1 & RA'"); py_run!(py, c, "assert 1 ^ c == '1 ^ RA'"); py_run!(py, c, "assert 1 | c == '1 | RA'"); py_run!(py, c, "assert 1 ** c == '1 ** RA'"); py_run!(py, c, "assert 1 @ c == '1 @ RA'"); }); } #[pyclass] struct RichComparisons {} #[pymethods] impl RichComparisons { fn __repr__(&self) -> &'static str { "RC" } fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> String { match op { CompareOp::Lt => format!("{} < {:?}", self.__repr__(), other), CompareOp::Le => format!("{} <= {:?}", self.__repr__(), other), CompareOp::Eq => format!("{} == {:?}", self.__repr__(), other), CompareOp::Ne => format!("{} != {:?}", self.__repr__(), other), CompareOp::Gt => format!("{} > {:?}", self.__repr__(), other), CompareOp::Ge => format!("{} >= {:?}", self.__repr__(), other), } } } #[pyclass] struct RichComparisons2 {} #[pymethods] impl RichComparisons2 { fn __repr__(&self) -> &'static str { "RC2" } fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> PyResult { match op { CompareOp::Eq => true .into_pyobject(other.py()) .map_err(Into::into) .map(BoundObject::into_any) .map(BoundObject::unbind), CompareOp::Ne => false .into_pyobject(other.py()) .map_err(Into::into) .map(BoundObject::into_any) .map(BoundObject::unbind), _ => Ok(other.py().NotImplemented()), } } } #[test] fn rich_comparisons() { Python::with_gil(|py| { let c = Py::new(py, RichComparisons {}).unwrap(); py_run!(py, c, "assert (c < c) == 'RC < RC'"); py_run!(py, c, "assert (c < 1) == 'RC < 1'"); py_run!(py, c, "assert (1 < c) == 'RC > 1'"); py_run!(py, c, "assert (c <= c) == 'RC <= RC'"); py_run!(py, c, "assert (c <= 1) == 'RC <= 1'"); py_run!(py, c, "assert (1 <= c) == 'RC >= 1'"); py_run!(py, c, "assert (c == c) == 'RC == RC'"); py_run!(py, c, "assert (c == 1) == 'RC == 1'"); py_run!(py, c, "assert (1 == c) == 'RC == 1'"); py_run!(py, c, "assert (c != c) == 'RC != RC'"); py_run!(py, c, "assert (c != 1) == 'RC != 1'"); py_run!(py, c, "assert (1 != c) == 'RC != 1'"); py_run!(py, c, "assert (c > c) == 'RC > RC'"); py_run!(py, c, "assert (c > 1) == 'RC > 1'"); py_run!(py, c, "assert (1 > c) == 'RC < 1'"); py_run!(py, c, "assert (c >= c) == 'RC >= RC'"); py_run!(py, c, "assert (c >= 1) == 'RC >= 1'"); py_run!(py, c, "assert (1 >= c) == 'RC <= 1'"); }); } #[test] fn rich_comparisons_python_3_type_error() { Python::with_gil(|py| { let c2 = Py::new(py, RichComparisons2 {}).unwrap(); py_expect_exception!(py, c2, "c2 < c2", PyTypeError); py_expect_exception!(py, c2, "c2 < 1", PyTypeError); py_expect_exception!(py, c2, "1 < c2", PyTypeError); py_expect_exception!(py, c2, "c2 <= c2", PyTypeError); py_expect_exception!(py, c2, "c2 <= 1", PyTypeError); py_expect_exception!(py, c2, "1 <= c2", PyTypeError); py_run!(py, c2, "assert (c2 == c2) == True"); py_run!(py, c2, "assert (c2 == 1) == True"); py_run!(py, c2, "assert (1 == c2) == True"); py_run!(py, c2, "assert (c2 != c2) == False"); py_run!(py, c2, "assert (c2 != 1) == False"); py_run!(py, c2, "assert (1 != c2) == False"); py_expect_exception!(py, c2, "c2 > c2", PyTypeError); py_expect_exception!(py, c2, "c2 > 1", PyTypeError); py_expect_exception!(py, c2, "1 > c2", PyTypeError); py_expect_exception!(py, c2, "c2 >= c2", PyTypeError); py_expect_exception!(py, c2, "c2 >= 1", PyTypeError); py_expect_exception!(py, c2, "1 >= c2", PyTypeError); }); } // Checks that binary operations for which the arguments don't match the // required type, return NotImplemented. mod return_not_implemented { use super::*; #[pyclass] struct RichComparisonToSelf {} #[pymethods] impl RichComparisonToSelf { fn __repr__(&self) -> &'static str { "RC_Self" } fn __richcmp__(&self, other: PyRef<'_, Self>, _op: CompareOp) -> PyObject { other.py().None() } fn __add__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __sub__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __mul__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __matmul__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __truediv__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __floordiv__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __mod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __pow__(slf: PyRef<'_, Self>, _other: u8, _modulo: Option) -> PyRef<'_, Self> { slf } fn __lshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __rshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __divmod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __and__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __or__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __xor__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } // Inplace assignments fn __iadd__(&mut self, _other: PyRef<'_, Self>) {} fn __isub__(&mut self, _other: PyRef<'_, Self>) {} fn __imul__(&mut self, _other: PyRef<'_, Self>) {} fn __imatmul__(&mut self, _other: PyRef<'_, Self>) {} fn __itruediv__(&mut self, _other: PyRef<'_, Self>) {} fn __ifloordiv__(&mut self, _other: PyRef<'_, Self>) {} fn __imod__(&mut self, _other: PyRef<'_, Self>) {} fn __ilshift__(&mut self, _other: PyRef<'_, Self>) {} fn __irshift__(&mut self, _other: PyRef<'_, Self>) {} fn __iand__(&mut self, _other: PyRef<'_, Self>) {} fn __ior__(&mut self, _other: PyRef<'_, Self>) {} fn __ixor__(&mut self, _other: PyRef<'_, Self>) {} fn __ipow__(&mut self, _other: PyRef<'_, Self>, _modulo: Option) {} } fn _test_binary_dunder(dunder: &str) { Python::with_gil(|py| { let c2 = Py::new(py, RichComparisonToSelf {}).unwrap(); py_run!( py, c2, &format!("class Other: pass\nassert c2.__{dunder}__(Other()) is NotImplemented") ); }); } fn _test_binary_operator(operator: &str, dunder: &str) { _test_binary_dunder(dunder); Python::with_gil(|py| { let c2 = Py::new(py, RichComparisonToSelf {}).unwrap(); py_expect_exception!( py, c2, format!("class Other: pass\nc2 {} Other()", operator), PyTypeError ); }); } fn _test_inplace_binary_operator(operator: &str, dunder: &str) { _test_binary_operator(operator, dunder); } #[test] fn equality() { _test_binary_dunder("eq"); _test_binary_dunder("ne"); } #[test] fn ordering() { _test_binary_operator("<", "lt"); _test_binary_operator("<=", "le"); _test_binary_operator(">", "gt"); _test_binary_operator(">=", "ge"); } #[test] fn bitwise() { _test_binary_operator("&", "and"); _test_binary_operator("|", "or"); _test_binary_operator("^", "xor"); _test_binary_operator("<<", "lshift"); _test_binary_operator(">>", "rshift"); } #[test] fn arith() { _test_binary_operator("+", "add"); _test_binary_operator("-", "sub"); _test_binary_operator("*", "mul"); _test_binary_operator("@", "matmul"); _test_binary_operator("/", "truediv"); _test_binary_operator("//", "floordiv"); _test_binary_operator("%", "mod"); _test_binary_operator("**", "pow"); } #[test] fn reverse_arith() { _test_binary_dunder("radd"); _test_binary_dunder("rsub"); _test_binary_dunder("rmul"); _test_binary_dunder("rmatmul"); _test_binary_dunder("rtruediv"); _test_binary_dunder("rfloordiv"); _test_binary_dunder("rmod"); _test_binary_dunder("rdivmod"); _test_binary_dunder("rpow"); } #[test] fn inplace_bitwise() { _test_inplace_binary_operator("&=", "iand"); _test_inplace_binary_operator("|=", "ior"); _test_inplace_binary_operator("^=", "ixor"); _test_inplace_binary_operator("<<=", "ilshift"); _test_inplace_binary_operator(">>=", "irshift"); } #[test] fn inplace_arith() { _test_inplace_binary_operator("+=", "iadd"); _test_inplace_binary_operator("-=", "isub"); _test_inplace_binary_operator("*=", "imul"); _test_inplace_binary_operator("@=", "imatmul"); _test_inplace_binary_operator("/=", "itruediv"); _test_inplace_binary_operator("//=", "ifloordiv"); _test_inplace_binary_operator("%=", "imod"); _test_inplace_binary_operator("**=", "ipow"); } } pyo3/tests/test_inheritance.rs0000644000175000017500000002011415105742312016332 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use pyo3::ffi; use pyo3::types::IntoPyDict; #[path = "../src/tests/common.rs"] mod common; #[pyclass(subclass)] struct BaseClass { #[pyo3(get)] val1: usize, } #[pyclass(subclass)] struct SubclassAble {} #[test] fn subclass() { Python::with_gil(|py| { let d = [("SubclassAble", py.get_type::())] .into_py_dict(py) .unwrap(); py.run( ffi::c_str!("class A(SubclassAble): pass\nassert issubclass(A, SubclassAble)"), None, Some(&d), ) .map_err(|e| e.display(py)) .unwrap(); }); } #[pymethods] impl BaseClass { #[new] fn new() -> Self { BaseClass { val1: 10 } } fn base_method(&self, x: usize) -> usize { x * self.val1 } fn base_set(&mut self, fn_: &Bound<'_, PyAny>) -> PyResult<()> { let value: usize = fn_.call0()?.extract()?; self.val1 = value; Ok(()) } } #[pyclass(extends=BaseClass)] struct SubClass { #[pyo3(get)] val2: usize, } #[pymethods] impl SubClass { #[new] fn new() -> (Self, BaseClass) { (SubClass { val2: 5 }, BaseClass { val1: 10 }) } fn sub_method(&self, x: usize) -> usize { x * self.val2 } fn sub_set_and_ret(&mut self, x: usize) -> usize { self.val2 = x; x } } #[test] fn inheritance_with_new_methods() { Python::with_gil(|py| { let typeobj = py.get_type::(); let inst = typeobj.call((), None).unwrap(); py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5"); }); } #[test] fn call_base_and_sub_methods() { Python::with_gil(|py| { let obj = Py::new(py, SubClass::new()).unwrap(); py_run!( py, obj, r#" assert obj.base_method(10) == 100 assert obj.sub_method(10) == 50 "# ); }); } #[test] fn mutation_fails() { Python::with_gil(|py| { let obj = Py::new(py, SubClass::new()).unwrap(); let global = [("obj", obj)].into_py_dict(py).unwrap(); let e = py .run( ffi::c_str!("obj.base_set(lambda: obj.sub_set_and_ret(1))"), Some(&global), None, ) .unwrap_err(); assert_eq!(&e.to_string(), "RuntimeError: Already borrowed"); }); } #[test] fn is_subclass_and_is_instance() { Python::with_gil(|py| { let sub_ty = py.get_type::(); let base_ty = py.get_type::(); assert!(sub_ty.is_subclass_of::().unwrap()); assert!(sub_ty.is_subclass(&base_ty).unwrap()); let obj = Bound::new(py, SubClass::new()).unwrap().into_any(); assert!(obj.is_instance_of::()); assert!(obj.is_instance_of::()); assert!(obj.is_instance(&sub_ty).unwrap()); assert!(obj.is_instance(&base_ty).unwrap()); }); } #[pyclass(subclass)] struct BaseClassWithResult { _val: usize, } #[pymethods] impl BaseClassWithResult { #[new] fn new(value: isize) -> PyResult { Ok(Self { _val: std::convert::TryFrom::try_from(value)?, }) } } #[pyclass(extends=BaseClassWithResult)] struct SubClass2 {} #[pymethods] impl SubClass2 { #[new] fn new(value: isize) -> PyResult<(Self, BaseClassWithResult)> { let base = BaseClassWithResult::new(value)?; Ok((Self {}, base)) } } #[test] fn handle_result_in_new() { Python::with_gil(|py| { let subclass = py.get_type::(); py_run!( py, subclass, r#" try: subclass(-10) assert Fals except ValueError as e: pass except Exception as e: raise e "# ); }); } // Subclassing builtin types is not allowed in the LIMITED API. #[cfg(not(Py_LIMITED_API))] mod inheriting_native_type { use super::*; use pyo3::exceptions::PyException; use pyo3::types::PyDict; #[cfg(not(any(PyPy, GraalPy)))] #[test] fn inherit_set() { use pyo3::types::PySet; #[pyclass(extends=PySet)] #[derive(Debug)] struct SetWithName { #[pyo3(get, name = "name")] _name: &'static str, } #[pymethods] impl SetWithName { #[new] fn new() -> Self { SetWithName { _name: "Hello :)" } } } Python::with_gil(|py| { let set_sub = pyo3::Py::new(py, SetWithName::new()).unwrap(); py_run!( py, set_sub, r#"set_sub.add(10); assert list(set_sub) == [10]; assert set_sub.name == "Hello :)""# ); }); } #[pyclass(extends=PyDict)] #[derive(Debug)] struct DictWithName { #[pyo3(get, name = "name")] _name: &'static str, } #[pymethods] impl DictWithName { #[new] fn new() -> Self { DictWithName { _name: "Hello :)" } } } #[test] fn inherit_dict() { Python::with_gil(|py| { let dict_sub = pyo3::Py::new(py, DictWithName::new()).unwrap(); py_run!( py, dict_sub, r#"dict_sub[0] = 1; assert dict_sub[0] == 1; assert dict_sub.name == "Hello :)""# ); }); } #[test] fn inherit_dict_drop() { Python::with_gil(|py| { let dict_sub = pyo3::Py::new(py, DictWithName::new()).unwrap(); assert_eq!(dict_sub.get_refcnt(py), 1); let item = &py.eval(ffi::c_str!("object()"), None, None).unwrap(); assert_eq!(item.get_refcnt(), 1); dict_sub.bind(py).set_item("foo", item).unwrap(); assert_eq!(item.get_refcnt(), 2); drop(dict_sub); assert_eq!(item.get_refcnt(), 1); }) } #[pyclass(extends=PyException)] struct CustomException { #[pyo3(get)] context: &'static str, } #[pymethods] impl CustomException { #[new] fn new(_exc_arg: &Bound<'_, PyAny>) -> Self { CustomException { context: "Hello :)", } } } #[test] fn custom_exception() { Python::with_gil(|py| { let cls = py.get_type::(); let dict = [("cls", &cls)].into_py_dict(py).unwrap(); let res = py.run( ffi::c_str!("e = cls('hello'); assert str(e) == 'hello'; assert e.context == 'Hello :)'; raise e"), None, Some(&dict) ); let err = res.unwrap_err(); assert!(err.matches(py, &cls).unwrap(), "{}", err); // catching the exception in Python also works: py_run!( py, cls, r#" try: raise cls("foo") except cls: pass "# ) }) } } #[pyclass(subclass)] struct SimpleClass {} #[pymethods] impl SimpleClass { #[new] fn new() -> Self { Self {} } } #[test] fn test_subclass_ref_counts() { // regression test for issue #1363 Python::with_gil(|py| { #[allow(non_snake_case)] let SimpleClass = py.get_type::(); py_run!( py, SimpleClass, r#" import gc import sys class SubClass(SimpleClass): pass gc.collect() count = sys.getrefcount(SubClass) for i in range(1000): c = SubClass() del c gc.collect() after = sys.getrefcount(SubClass) # depending on Python's GC the count may be either identical or exactly 1000 higher, # both are expected values that are not representative of the issue. # # (With issue #1363 the count will be decreased.) assert after == count or (after == count + 1000), f"{after} vs {count}" "# ); }) } pyo3/tests/test_text_signature.rs0000644000175000017500000002633415105742312017120 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; use pyo3::{types::PyType, wrap_pymodule}; #[path = "../src/tests/common.rs"] mod common; #[test] fn class_without_docs_or_signature() { #[pyclass] struct MyClass {} Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "typeobj.__doc__ is None"); py_assert!(py, typeobj, "typeobj.__text_signature__ is None"); }); } #[test] fn class_with_docs() { /// docs line1 #[pyclass] /// docs line2 struct MyClass {} Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'"); py_assert!(py, typeobj, "typeobj.__text_signature__ is None"); }); } #[test] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)] fn class_with_signature_no_doc() { #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(signature = (a, b=None, *, c=42), text_signature = "(a, b=None, *, c=42)")] fn __new__(a: i32, b: Option, c: i32) -> Self { let _ = (a, b, c); Self {} } } Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "typeobj.__doc__ == ''"); py_assert!( py, typeobj, "typeobj.__text_signature__ == '(a, b=None, *, c=42)'" ); }); } #[test] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)] fn class_with_docs_and_signature() { /// docs line1 #[pyclass] /// docs line2 struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(signature = (a, b=None, *, c=42), text_signature = "(a, b=None, *, c=42)")] fn __new__(a: i32, b: Option, c: i32) -> Self { let _ = (a, b, c); Self {} } } Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'"); py_assert!( py, typeobj, "typeobj.__text_signature__ == '(a, b=None, *, c=42)'" ); }); } #[test] fn test_function() { #[pyfunction(signature = (a, b=None, *, c=42))] #[pyo3(text_signature = "(a, b=None, *, c=42)")] fn my_function(a: i32, b: Option, c: i32) { let _ = (a, b, c); } Python::with_gil(|py| { let f = wrap_pyfunction!(my_function)(py).unwrap(); py_assert!(py, f, "f.__text_signature__ == '(a, b=None, *, c=42)'"); }); } #[test] fn test_auto_test_signature_function() { #[pyfunction] fn my_function(a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[pyfunction(pass_module)] fn my_function_2(module: &Bound<'_, PyModule>, a: i32, b: i32, c: i32) { let _ = (module, a, b, c); } #[pyfunction(signature = (a, /, b = None, *, c = 5))] fn my_function_3(a: i32, b: Option, c: i32) { let _ = (a, b, c); } #[pyfunction(signature = (a, /, b = None, *args, c, d=5, **kwargs))] fn my_function_4( a: i32, b: Option, args: &Bound<'_, PyTuple>, c: i32, d: i32, kwargs: Option<&Bound<'_, PyDict>>, ) { let _ = (a, b, args, c, d, kwargs); } #[pyfunction(signature = (a = 1, /, b = None, c = 1.5, d=5, e = "pyo3", f = 'f', h = true))] fn my_function_5(a: i32, b: Option, c: f32, d: i32, e: &str, f: char, h: bool) { let _ = (a, b, c, d, e, f, h); } #[pyfunction] #[pyo3(signature=(a, b=None, c=None))] fn my_function_6(a: i32, b: Option, c: Option) { let _ = (a, b, c); } Python::with_gil(|py| { let f = wrap_pyfunction!(my_function)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a, b, c)', f.__text_signature__" ); let f = wrap_pyfunction!(my_function_2)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '($module, a, b, c)', f.__text_signature__" ); let f = wrap_pyfunction!(my_function_3)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a, /, b=None, *, c=5)', f.__text_signature__" ); let f = wrap_pyfunction!(my_function_4)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a, /, b=None, *args, c, d=5, **kwargs)', f.__text_signature__" ); let f = wrap_pyfunction!(my_function_5)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a=1, /, b=None, c=1.5, d=5, e=\"pyo3\", f=\\'f\\', h=True)', f.__text_signature__" ); let f = wrap_pyfunction!(my_function_6)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a, b=None, c=None)', f.__text_signature__" ); }); } #[test] fn test_auto_test_signature_method() { #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] fn new(a: i32, b: i32, c: i32) -> Self { let _ = (a, b, c); Self {} } fn method(&self, a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[pyo3(signature = (a, /, b = None, *, c = 5))] fn method_2(&self, a: i32, b: Option, c: i32) { let _ = (a, b, c); } #[pyo3(signature = (a, /, b = None, *args, c, d=5, **kwargs))] fn method_3( &self, a: i32, b: Option, args: &Bound<'_, PyTuple>, c: i32, d: i32, kwargs: Option<&Bound<'_, PyDict>>, ) { let _ = (a, b, args, c, d, kwargs); } #[staticmethod] fn staticmethod(a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[classmethod] fn classmethod(cls: &Bound<'_, PyType>, a: i32, b: i32, c: i32) { let _ = (cls, a, b, c); } } Python::with_gil(|py| { let cls = py.get_type::(); #[cfg(any(not(Py_LIMITED_API), Py_3_10))] py_assert!(py, cls, "cls.__text_signature__ == '(a, b, c)'"); py_assert!( py, cls, "cls.method.__text_signature__ == '($self, a, b, c)'" ); py_assert!( py, cls, "cls.method_2.__text_signature__ == '($self, a, /, b=None, *, c=5)'" ); py_assert!( py, cls, "cls.method_3.__text_signature__ == '($self, a, /, b=None, *args, c, d=5, **kwargs)'" ); py_assert!( py, cls, "cls.staticmethod.__text_signature__ == '(a, b, c)'" ); py_assert!( py, cls, "cls.classmethod.__text_signature__ == '($cls, a, b, c)'" ); }); } #[test] fn test_auto_test_signature_opt_out() { #[pyfunction(text_signature = None)] fn my_function(a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[pyfunction(signature = (a, /, b = None, *, c = 5), text_signature = None)] fn my_function_2(a: i32, b: Option, c: i32) { let _ = (a, b, c); } #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(text_signature = None)] fn new(a: i32, b: i32, c: i32) -> Self { let _ = (a, b, c); Self {} } #[pyo3(text_signature = None)] fn method(&self, a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[pyo3(signature = (a, /, b = None, *, c = 5), text_signature = None)] fn method_2(&self, a: i32, b: Option, c: i32) { let _ = (a, b, c); } #[staticmethod] #[pyo3(text_signature = None)] fn staticmethod(a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[classmethod] #[pyo3(text_signature = None)] fn classmethod(cls: &Bound<'_, PyType>, a: i32, b: i32, c: i32) { let _ = (cls, a, b, c); } } Python::with_gil(|py| { let f = wrap_pyfunction!(my_function)(py).unwrap(); py_assert!(py, f, "f.__text_signature__ == None"); let f = wrap_pyfunction!(my_function_2)(py).unwrap(); py_assert!(py, f, "f.__text_signature__ == None"); let cls = py.get_type::(); py_assert!(py, cls, "cls.__text_signature__ == None"); py_assert!(py, cls, "cls.method.__text_signature__ == None"); py_assert!(py, cls, "cls.method_2.__text_signature__ == None"); py_assert!(py, cls, "cls.staticmethod.__text_signature__ == None"); py_assert!(py, cls, "cls.classmethod.__text_signature__ == None"); }); } #[test] fn test_pyfn() { #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m, signature = (a, b=None, *, c=42))] #[pyo3(text_signature = "(a, b=None, *, c=42)")] fn my_function(a: i32, b: Option, c: i32) { let _ = (a, b, c); } Ok(()) } Python::with_gil(|py| { let m = wrap_pymodule!(my_module)(py); py_assert!( py, m, "m.my_function.__text_signature__ == '(a, b=None, *, c=42)'" ); }); } #[test] fn test_methods() { #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[pyo3(text_signature = "($self, a)")] fn method(&self, a: i32) { let _ = a; } #[pyo3(text_signature = "($self, b)")] fn pyself_method(_this: &Bound<'_, Self>, b: i32) { let _ = b; } #[classmethod] #[pyo3(text_signature = "($cls, c)")] fn class_method(_cls: &Bound<'_, PyType>, c: i32) { let _ = c; } #[staticmethod] #[pyo3(text_signature = "(d)")] fn static_method(d: i32) { let _ = d; } } Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!( py, typeobj, "typeobj.method.__text_signature__ == '($self, a)'" ); py_assert!( py, typeobj, "typeobj.pyself_method.__text_signature__ == '($self, b)'" ); py_assert!( py, typeobj, "typeobj.class_method.__text_signature__ == '($cls, c)'" ); py_assert!( py, typeobj, "typeobj.static_method.__text_signature__ == '(d)'" ); }); } #[test] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)] fn test_raw_identifiers() { #[pyclass] struct r#MyClass {} #[pymethods] impl MyClass { #[new] fn new() -> MyClass { MyClass {} } fn r#method(&self) {} } Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "typeobj.__text_signature__ == '()'"); py_assert!( py, typeobj, "typeobj.method.__text_signature__ == '($self)'" ); }); } pyo3/tests/test_anyhow.rs0000644000175000017500000000223015105742312015345 0ustar bdrungbdrung#![cfg(feature = "anyhow")] use pyo3::{ffi, wrap_pyfunction}; #[test] fn test_anyhow_py_function_ok_result() { use pyo3::{py_run, pyfunction, Python}; #[pyfunction] #[allow(clippy::unnecessary_wraps)] fn produce_ok_result() -> anyhow::Result { Ok(String::from("OK buddy")) } Python::with_gil(|py| { let func = wrap_pyfunction!(produce_ok_result)(py).unwrap(); py_run!( py, func, r#" func() "# ); }); } #[test] fn test_anyhow_py_function_err_result() { use pyo3::prelude::PyDictMethods; use pyo3::{pyfunction, types::PyDict, Python}; #[pyfunction] fn produce_err_result() -> anyhow::Result { anyhow::bail!("error time") } Python::with_gil(|py| { let func = wrap_pyfunction!(produce_err_result)(py).unwrap(); let locals = PyDict::new(py); locals.set_item("func", func).unwrap(); py.run( ffi::c_str!( r#" func() "# ), None, Some(&locals), ) .unwrap_err(); }); } pyo3/tests/test_datetime_import.rs0000644000175000017500000000160015105742312017226 0ustar bdrungbdrung#![cfg(not(Py_LIMITED_API))] use pyo3::{prelude::*, types::PyDate}; use tempfile::Builder; #[test] #[should_panic(expected = "module 'datetime' has no attribute 'datetime_CAPI'")] fn test_bad_datetime_module_panic() { // Create an empty temporary directory // with an empty "datetime" module which we'll put on the sys.path let tmpdir = Builder::new() .prefix("pyo3_test_data_check") .tempdir() .unwrap(); std::fs::File::create(tmpdir.path().join("datetime.py")).unwrap(); Python::with_gil(|py: Python<'_>| { let sys = py.import("sys").unwrap(); sys.getattr("path") .unwrap() .call_method1("insert", (0, tmpdir.path().as_os_str())) .unwrap(); // This should panic because the "datetime" module is empty PyDate::new(py, 2018, 1, 1).unwrap(); }); tmpdir.close().unwrap(); } pyo3/tests/test_frompyobject.rs0000644000175000017500000006033615105742312016556 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::{IntoPyDict, PyDict, PyList, PyString, PyTuple}; #[macro_use] #[path = "../src/tests/common.rs"] mod common; /// Helper function that concatenates the error message from /// each error in the traceback into a single string that can /// be tested. fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String { let mut error_msg = error.to_string(); while let Some(cause) = error.cause(py) { error_msg.push_str(": "); error_msg.push_str(&cause.to_string()); error = cause } error_msg } #[derive(Debug, FromPyObject)] pub struct A<'py> { #[pyo3(attribute)] s: String, #[pyo3(item)] t: Bound<'py, PyString>, #[pyo3(attribute("foo"))] p: Bound<'py, PyAny>, } #[pyclass] pub struct PyA { #[pyo3(get)] s: String, #[pyo3(get)] foo: Option, } #[pymethods] impl PyA { fn __getitem__(&self, key: String) -> pyo3::PyResult { if key == "t" { Ok("bar".into()) } else { Err(PyValueError::new_err("Failed")) } } } #[test] fn test_named_fields_struct() { Python::with_gil(|py| { let pya = PyA { s: "foo".into(), foo: None, }; let py_c = Py::new(py, pya).unwrap(); let a = py_c .extract::>(py) .expect("Failed to extract A from PyA"); assert_eq!(a.s, "foo"); assert_eq!(a.t.to_string_lossy(), "bar"); assert!(a.p.is_none()); }); } #[derive(Debug, FromPyObject)] #[pyo3(transparent)] pub struct B { test: String, } #[test] fn test_transparent_named_field_struct() { Python::with_gil(|py| { let test = "test".into_pyobject(py).unwrap(); let b = test .extract::() .expect("Failed to extract B from String"); assert_eq!(b.test, "test"); let test = 1i32.into_pyobject(py).unwrap(); let b = test.extract::(); assert!(b.is_err()); }); } #[derive(Debug, FromPyObject)] #[pyo3(transparent)] pub struct D { test: T, } #[test] fn test_generic_transparent_named_field_struct() { Python::with_gil(|py| { let test = "test".into_pyobject(py).unwrap(); let d = test .extract::>() .expect("Failed to extract D from String"); assert_eq!(d.test, "test"); let test = 1usize.into_pyobject(py).unwrap(); let d = test .extract::>() .expect("Failed to extract D from String"); assert_eq!(d.test, 1); }); } #[derive(Debug, FromPyObject)] pub struct GenericWithBound(std::collections::HashMap); #[test] fn test_generic_with_bound() { Python::with_gil(|py| { let dict = [("1", 1), ("2", 2)].into_py_dict(py).unwrap(); let map = dict.extract::>().unwrap().0; assert_eq!(map.len(), 2); assert_eq!(map["1"], 1); assert_eq!(map["2"], 2); assert!(!map.contains_key("3")); }); } #[derive(Debug, FromPyObject)] pub struct E { test: T, test2: T2, } #[pyclass] #[derive(Clone)] pub struct PyE { #[pyo3(get)] test: String, #[pyo3(get)] test2: usize, } #[test] fn test_generic_named_fields_struct() { Python::with_gil(|py| { let pye = PyE { test: "test".into(), test2: 2, } .into_pyobject(py) .unwrap(); let e = pye .extract::>() .expect("Failed to extract E from PyE"); assert_eq!(e.test, "test"); assert_eq!(e.test2, 2); let e = pye.extract::>(); assert!(e.is_err()); }); } #[derive(Debug, FromPyObject)] pub struct C { #[pyo3(attribute("test"))] test: String, } #[test] fn test_named_field_with_ext_fn() { Python::with_gil(|py| { let pyc = PyE { test: "foo".into(), test2: 0, } .into_pyobject(py) .unwrap(); let c = pyc.extract::().expect("Failed to extract C from PyE"); assert_eq!(c.test, "foo"); }); } #[derive(Debug, FromPyObject)] pub struct Tuple(String, usize); #[test] fn test_tuple_struct() { Python::with_gil(|py| { let tup = PyTuple::new( py, &[ 1i32.into_pyobject(py).unwrap().into_any(), "test".into_pyobject(py).unwrap().into_any(), ], ) .unwrap(); let tup = tup.extract::(); assert!(tup.is_err()); let tup = PyTuple::new( py, &[ "test".into_pyobject(py).unwrap().into_any(), 1i32.into_pyobject(py).unwrap().into_any(), ], ) .unwrap(); let tup = tup .extract::() .expect("Failed to extract Tuple from PyTuple"); assert_eq!(tup.0, "test"); assert_eq!(tup.1, 1); }); } #[derive(Debug, FromPyObject)] pub struct TransparentTuple(String); #[test] fn test_transparent_tuple_struct() { Python::with_gil(|py| { let tup = 1i32.into_pyobject(py).unwrap(); let tup = tup.extract::(); assert!(tup.is_err()); let test = "test".into_pyobject(py).unwrap(); let tup = test .extract::() .expect("Failed to extract TransparentTuple from PyTuple"); assert_eq!(tup.0, "test"); }); } #[pyclass] struct PyBaz { #[pyo3(get)] tup: (String, String), #[pyo3(get)] e: PyE, } #[derive(Debug, FromPyObject)] #[allow(dead_code)] struct Baz { e: E, tup: Tuple, } #[test] fn test_struct_nested_type_errors() { Python::with_gil(|py| { let pybaz = PyBaz { tup: ("test".into(), "test".into()), e: PyE { test: "foo".into(), test2: 0, }, } .into_pyobject(py) .unwrap(); let test = pybaz.extract::>(); assert!(test.is_err()); assert_eq!( extract_traceback(py,test.unwrap_err()), "TypeError: failed to extract field Baz.tup: TypeError: failed to extract field Tuple.1: \ TypeError: \'str\' object cannot be interpreted as an integer" ); }); } #[test] fn test_struct_nested_type_errors_with_generics() { Python::with_gil(|py| { let pybaz = PyBaz { tup: ("test".into(), "test".into()), e: PyE { test: "foo".into(), test2: 0, }, } .into_pyobject(py) .unwrap(); let test = pybaz.extract::>(); assert!(test.is_err()); assert_eq!( extract_traceback(py, test.unwrap_err()), "TypeError: failed to extract field Baz.e: TypeError: failed to extract field E.test: \ TypeError: \'str\' object cannot be interpreted as an integer", ); }); } #[test] fn test_transparent_struct_error_message() { Python::with_gil(|py| { let tup = 1i32.into_pyobject(py).unwrap(); let tup = tup.extract::(); assert!(tup.is_err()); assert_eq!( extract_traceback(py,tup.unwrap_err()), "TypeError: failed to extract field B.test: TypeError: \'int\' object cannot be converted \ to \'PyString\'" ); }); } #[test] fn test_tuple_struct_error_message() { Python::with_gil(|py| { let tup = (1, "test").into_pyobject(py).unwrap(); let tup = tup.extract::(); assert!(tup.is_err()); assert_eq!( extract_traceback(py, tup.unwrap_err()), "TypeError: failed to extract field Tuple.0: TypeError: \'int\' object cannot be \ converted to \'PyString\'" ); }); } #[test] fn test_transparent_tuple_error_message() { Python::with_gil(|py| { let tup = 1i32.into_pyobject(py).unwrap(); let tup = tup.extract::(); assert!(tup.is_err()); assert_eq!( extract_traceback(py, tup.unwrap_err()), "TypeError: failed to extract field TransparentTuple.0: TypeError: 'int' object \ cannot be converted to 'PyString'", ); }); } #[pyclass] struct RenameAllCls {} #[pymethods] impl RenameAllCls { #[getter] #[pyo3(name = "someField")] fn some_field(&self) -> &'static str { "Foo" } #[getter] #[pyo3(name = "customNumber")] fn custom_number(&self) -> i32 { 42 } fn __getitem__(&self, key: &str) -> PyResult { match key { "otherField" => Ok(42.0), _ => Err(pyo3::exceptions::PyKeyError::new_err("foo")), } } } #[test] fn test_struct_rename_all() { #[derive(FromPyObject)] #[pyo3(rename_all = "camelCase")] struct RenameAll { some_field: String, #[pyo3(item)] other_field: f32, #[pyo3(attribute("customNumber"))] custom_name: i32, } Python::with_gil(|py| { let RenameAll { some_field, other_field, custom_name, } = RenameAllCls {} .into_pyobject(py) .unwrap() .extract() .unwrap(); assert_eq!(some_field, "Foo"); assert_eq!(other_field, 42.0); assert_eq!(custom_name, 42); }); } #[test] fn test_enum_rename_all() { #[derive(FromPyObject)] #[pyo3(rename_all = "camelCase")] enum RenameAll { Foo { some_field: String, #[pyo3(item)] other_field: f32, #[pyo3(attribute("customNumber"))] custom_name: i32, }, } Python::with_gil(|py| { let RenameAll::Foo { some_field, other_field, custom_name, } = RenameAllCls {} .into_pyobject(py) .unwrap() .extract() .unwrap(); assert_eq!(some_field, "Foo"); assert_eq!(other_field, 42.0); assert_eq!(custom_name, 42); }); } #[derive(Debug, FromPyObject)] pub enum Foo<'py> { TupleVar(usize, String), StructVar { test: Bound<'py, PyString>, }, #[pyo3(transparent)] TransparentTuple(usize), #[pyo3(transparent)] TransparentStructVar { a: Option, }, StructVarGetAttrArg { #[pyo3(attribute("bla"))] a: bool, }, StructWithGetItem { #[pyo3(item)] a: String, }, StructWithGetItemArg { #[pyo3(item("foo"))] a: String, }, } #[pyclass] pub struct PyBool { #[pyo3(get)] bla: bool, } #[test] fn test_enum() { Python::with_gil(|py| { let tup = PyTuple::new( py, &[ 1i32.into_pyobject(py).unwrap().into_any(), "test".into_pyobject(py).unwrap().into_any(), ], ) .unwrap(); let f = tup .extract::>() .expect("Failed to extract Foo from tuple"); match f { Foo::TupleVar(test, test2) => { assert_eq!(test, 1); assert_eq!(test2, "test"); } _ => panic!("Expected extracting Foo::TupleVar, got {f:?}"), } let pye = PyE { test: "foo".into(), test2: 0, } .into_pyobject(py) .unwrap(); let f = pye .extract::>() .expect("Failed to extract Foo from PyE"); match f { Foo::StructVar { test } => assert_eq!(test.to_string_lossy(), "foo"), _ => panic!("Expected extracting Foo::StructVar, got {f:?}"), } let int = 1i32.into_pyobject(py).unwrap(); let f = int .extract::>() .expect("Failed to extract Foo from int"); match f { Foo::TransparentTuple(test) => assert_eq!(test, 1), _ => panic!("Expected extracting Foo::TransparentTuple, got {f:?}"), } let none = py.None(); let f = none .extract::>(py) .expect("Failed to extract Foo from int"); match f { Foo::TransparentStructVar { a } => assert!(a.is_none()), _ => panic!("Expected extracting Foo::TransparentStructVar, got {f:?}"), } let pybool = PyBool { bla: true }.into_pyobject(py).unwrap(); let f = pybool .extract::>() .expect("Failed to extract Foo from PyBool"); match f { Foo::StructVarGetAttrArg { a } => assert!(a), _ => panic!("Expected extracting Foo::StructVarGetAttrArg, got {f:?}"), } let dict = PyDict::new(py); dict.set_item("a", "test").expect("Failed to set item"); let f = dict .extract::>() .expect("Failed to extract Foo from dict"); match f { Foo::StructWithGetItem { a } => assert_eq!(a, "test"), _ => panic!("Expected extracting Foo::StructWithGetItem, got {f:?}"), } let dict = PyDict::new(py); dict.set_item("foo", "test").expect("Failed to set item"); let f = dict .extract::>() .expect("Failed to extract Foo from dict"); match f { Foo::StructWithGetItemArg { a } => assert_eq!(a, "test"), _ => panic!("Expected extracting Foo::StructWithGetItemArg, got {f:?}"), } }); } #[test] fn test_enum_error() { Python::with_gil(|py| { let dict = PyDict::new(py); let err = dict.extract::>().unwrap_err(); assert_eq!( err.to_string(), "\ TypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple | TransparentStructVar | StructVarGetAttrArg | StructWithGetItem | StructWithGetItemArg') - variant TupleVar (TupleVar): TypeError: 'dict' object cannot be converted to 'PyTuple' - variant StructVar (StructVar): AttributeError: 'dict' object has no attribute 'test' - variant TransparentTuple (TransparentTuple): TypeError: failed to extract field Foo::TransparentTuple.0, caused by TypeError: 'dict' object cannot be interpreted as an integer - variant TransparentStructVar (TransparentStructVar): TypeError: failed to extract field Foo::TransparentStructVar.a, caused by TypeError: 'dict' object cannot be converted to 'PyString' - variant StructVarGetAttrArg (StructVarGetAttrArg): AttributeError: 'dict' object has no attribute 'bla' - variant StructWithGetItem (StructWithGetItem): KeyError: 'a' - variant StructWithGetItemArg (StructWithGetItemArg): KeyError: 'foo'" ); let tup = PyTuple::empty(py); let err = tup.extract::>().unwrap_err(); assert_eq!( err.to_string(), "\ TypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple | TransparentStructVar | StructVarGetAttrArg | StructWithGetItem | StructWithGetItemArg') - variant TupleVar (TupleVar): ValueError: expected tuple of length 2, but got tuple of length 0 - variant StructVar (StructVar): AttributeError: 'tuple' object has no attribute 'test' - variant TransparentTuple (TransparentTuple): TypeError: failed to extract field Foo::TransparentTuple.0, caused by TypeError: 'tuple' object cannot be interpreted as an integer - variant TransparentStructVar (TransparentStructVar): TypeError: failed to extract field Foo::TransparentStructVar.a, caused by TypeError: 'tuple' object cannot be converted to 'PyString' - variant StructVarGetAttrArg (StructVarGetAttrArg): AttributeError: 'tuple' object has no attribute 'bla' - variant StructWithGetItem (StructWithGetItem): TypeError: tuple indices must be integers or slices, not str - variant StructWithGetItemArg (StructWithGetItemArg): TypeError: tuple indices must be integers or slices, not str" ); }); } #[derive(Debug, FromPyObject)] enum EnumWithCatchAll<'py> { #[allow(dead_code)] #[pyo3(transparent)] Foo(Foo<'py>), #[pyo3(transparent)] CatchAll(Bound<'py, PyAny>), } #[test] fn test_enum_catch_all() { Python::with_gil(|py| { let dict = PyDict::new(py); let f = dict .extract::>() .expect("Failed to extract EnumWithCatchAll from dict"); match f { EnumWithCatchAll::CatchAll(any) => { let d = any.extract::>().expect("Expected pydict"); assert!(d.is_empty()); } _ => panic!("Expected extracting EnumWithCatchAll::CatchAll, got {f:?}"), } }); } #[derive(Debug, FromPyObject)] pub enum Bar { #[pyo3(annotation = "str")] A(String), #[pyo3(annotation = "uint")] B(usize), #[pyo3(annotation = "int", transparent)] C(isize), } #[test] fn test_err_rename() { Python::with_gil(|py| { let dict = PyDict::new(py); let f = dict.extract::(); assert!(f.is_err()); assert_eq!( f.unwrap_err().to_string(), "\ TypeError: failed to extract enum Bar ('str | uint | int') - variant A (str): TypeError: failed to extract field Bar::A.0, caused by TypeError: 'dict' object cannot be converted to 'PyString' - variant B (uint): TypeError: failed to extract field Bar::B.0, caused by TypeError: 'dict' object cannot be interpreted as an integer - variant C (int): TypeError: failed to extract field Bar::C.0, caused by TypeError: 'dict' object cannot be interpreted as an integer" ); }); } #[derive(Debug, FromPyObject)] pub struct Zap { #[pyo3(item)] name: String, #[pyo3(from_py_with = Bound::<'_, PyAny>::len, item("my_object"))] some_object_length: usize, } #[test] fn test_from_py_with() { Python::with_gil(|py| { let py_zap = py .eval( pyo3_ffi::c_str!(r#"{"name": "whatever", "my_object": [1, 2, 3]}"#), None, None, ) .expect("failed to create dict"); let zap = py_zap.extract::().unwrap(); assert_eq!(zap.name, "whatever"); assert_eq!(zap.some_object_length, 3usize); }); } #[derive(Debug, FromPyObject)] pub struct ZapTuple( String, #[pyo3(from_py_with = Bound::<'_, PyAny>::len)] usize, ); #[test] fn test_from_py_with_tuple_struct() { Python::with_gil(|py| { let py_zap = py .eval(pyo3_ffi::c_str!(r#"("whatever", [1, 2, 3])"#), None, None) .expect("failed to create tuple"); let zap = py_zap.extract::().unwrap(); assert_eq!(zap.0, "whatever"); assert_eq!(zap.1, 3usize); }); } #[test] fn test_from_py_with_tuple_struct_error() { Python::with_gil(|py| { let py_zap = py .eval( pyo3_ffi::c_str!(r#"("whatever", [1, 2, 3], "third")"#), None, None, ) .expect("failed to create tuple"); let f = py_zap.extract::(); assert!(f.is_err()); assert_eq!( f.unwrap_err().to_string(), "ValueError: expected tuple of length 2, but got tuple of length 3" ); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] pub enum ZapEnum { Zip(#[pyo3(from_py_with = Bound::<'_, PyAny>::len)] usize), Zap( String, #[pyo3(from_py_with = Bound::<'_, PyAny>::len)] usize, ), } #[test] fn test_from_py_with_enum() { Python::with_gil(|py| { let py_zap = py .eval(pyo3_ffi::c_str!(r#"("whatever", [1, 2, 3])"#), None, None) .expect("failed to create tuple"); let zap = py_zap.extract::().unwrap(); let expected_zap = ZapEnum::Zip(2); assert_eq!(zap, expected_zap); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] #[pyo3(transparent)] pub struct TransparentFromPyWith { #[pyo3(from_py_with = Bound::<'_, PyAny>::len)] len: usize, } #[test] fn test_transparent_from_py_with() { Python::with_gil(|py| { let result = PyList::new(py, [1, 2, 3]) .unwrap() .extract::() .unwrap(); let expected = TransparentFromPyWith { len: 3 }; assert_eq!(result, expected); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] pub struct WithKeywordAttr { r#box: usize, } #[pyclass] pub struct WithKeywordAttrC { #[pyo3(get)] r#box: usize, } #[test] fn test_with_keyword_attr() { Python::with_gil(|py| { let cls = WithKeywordAttrC { r#box: 3 }.into_pyobject(py).unwrap(); let result = cls.extract::().unwrap(); let expected = WithKeywordAttr { r#box: 3 }; assert_eq!(result, expected); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] pub struct WithKeywordItem { #[pyo3(item)] r#box: usize, } #[test] fn test_with_keyword_item() { Python::with_gil(|py| { let dict = PyDict::new(py); dict.set_item("box", 3).unwrap(); let result = dict.extract::().unwrap(); let expected = WithKeywordItem { r#box: 3 }; assert_eq!(result, expected); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] pub struct WithDefaultItem { #[pyo3(item, default)] opt: Option, #[pyo3(item)] value: usize, } #[test] fn test_with_default_item() { Python::with_gil(|py| { let dict = PyDict::new(py); dict.set_item("value", 3).unwrap(); let result = dict.extract::().unwrap(); let expected = WithDefaultItem { value: 3, opt: None, }; assert_eq!(result, expected); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] pub struct WithExplicitDefaultItem { #[pyo3(item, default = 1)] opt: usize, #[pyo3(item)] value: usize, } #[test] fn test_with_explicit_default_item() { Python::with_gil(|py| { let dict = PyDict::new(py); dict.set_item("value", 3).unwrap(); let result = dict.extract::().unwrap(); let expected = WithExplicitDefaultItem { value: 3, opt: 1 }; assert_eq!(result, expected); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] pub struct WithDefaultItemAndConversionFunction { #[pyo3(item, default, from_py_with = Bound::<'_, PyAny>::len)] opt: usize, #[pyo3(item)] value: usize, } #[test] fn test_with_default_item_and_conversion_function() { Python::with_gil(|py| { // Filled case let dict = PyDict::new(py); dict.set_item("opt", (1,)).unwrap(); dict.set_item("value", 3).unwrap(); let result = dict .extract::() .unwrap(); let expected = WithDefaultItemAndConversionFunction { opt: 1, value: 3 }; assert_eq!(result, expected); // Empty case let dict = PyDict::new(py); dict.set_item("value", 3).unwrap(); let result = dict .extract::() .unwrap(); let expected = WithDefaultItemAndConversionFunction { opt: 0, value: 3 }; assert_eq!(result, expected); // Error case let dict = PyDict::new(py); dict.set_item("value", 3).unwrap(); dict.set_item("opt", 1).unwrap(); assert!(dict .extract::() .is_err()); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] pub enum WithDefaultItemEnum { #[pyo3(from_item_all)] Foo { a: usize, #[pyo3(default)] b: usize, }, NeverUsedA { a: usize, }, } #[test] fn test_with_default_item_enum() { Python::with_gil(|py| { // A and B filled let dict = PyDict::new(py); dict.set_item("a", 1).unwrap(); dict.set_item("b", 2).unwrap(); let result = dict.extract::().unwrap(); let expected = WithDefaultItemEnum::Foo { a: 1, b: 2 }; assert_eq!(result, expected); // A filled let dict = PyDict::new(py); dict.set_item("a", 1).unwrap(); let result = dict.extract::().unwrap(); let expected = WithDefaultItemEnum::Foo { a: 1, b: 0 }; assert_eq!(result, expected); }); } pyo3/tests/test_multiple_pymethods.rs0000644000175000017500000000317015105742312017773 0ustar bdrungbdrung#![cfg(feature = "multiple-pymethods")] use pyo3::prelude::*; use pyo3::types::PyType; #[macro_use] #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct PyClassWithMultiplePyMethods {} #[pymethods] impl PyClassWithMultiplePyMethods { #[new] fn new() -> Self { Self {} } } #[pymethods] impl PyClassWithMultiplePyMethods { fn __call__(&self) -> &'static str { "call" } } #[pymethods] impl PyClassWithMultiplePyMethods { fn method(&self) -> &'static str { "method" } } #[pymethods] impl PyClassWithMultiplePyMethods { #[classmethod] fn classmethod(_ty: &Bound<'_, PyType>) -> &'static str { "classmethod" } } #[pymethods] impl PyClassWithMultiplePyMethods { #[staticmethod] fn staticmethod() -> &'static str { "staticmethod" } } #[pymethods] impl PyClassWithMultiplePyMethods { #[classattr] fn class_attribute() -> &'static str { "class_attribute" } } #[pymethods] impl PyClassWithMultiplePyMethods { #[classattr] const CLASS_ATTRIBUTE: &'static str = "CLASS_ATTRIBUTE"; } #[test] fn test_class_with_multiple_pymethods() { Python::with_gil(|py| { let cls = py.get_type::(); py_assert!(py, cls, "cls()() == 'call'"); py_assert!(py, cls, "cls().method() == 'method'"); py_assert!(py, cls, "cls.classmethod() == 'classmethod'"); py_assert!(py, cls, "cls.staticmethod() == 'staticmethod'"); py_assert!(py, cls, "cls.class_attribute == 'class_attribute'"); py_assert!(py, cls, "cls.CLASS_ATTRIBUTE == 'CLASS_ATTRIBUTE'"); }) } pyo3/tests/test_coroutine.rs0000644000175000017500000002260115105742312016053 0ustar bdrungbdrung#![cfg(feature = "experimental-async")] #![cfg(not(target_arch = "wasm32"))] use std::{ffi::CString, task::Poll, thread, time::Duration}; use futures::{channel::oneshot, future::poll_fn, FutureExt}; #[cfg(not(target_has_atomic = "64"))] use portable_atomic::{AtomicBool, Ordering}; use pyo3::{ coroutine::CancelHandle, prelude::*, py_run, types::{IntoPyDict, PyDict, PyType}, }; #[cfg(target_has_atomic = "64")] use std::sync::atomic::{AtomicBool, Ordering}; #[path = "../src/tests/common.rs"] mod common; fn handle_windows(test: &str) -> String { let set_event_loop_policy = r#" import asyncio, sys if sys.platform == "win32": asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) "#; pyo3::unindent::unindent(set_event_loop_policy) + &pyo3::unindent::unindent(test) } #[test] fn noop_coroutine() { #[pyfunction] async fn noop() -> usize { 42 } Python::with_gil(|py| { let noop = wrap_pyfunction!(noop, py).unwrap(); let test = "import asyncio; assert asyncio.run(noop()) == 42"; py_run!(py, noop, &handle_windows(test)); }) } #[test] fn test_coroutine_qualname() { #[pyfunction] async fn my_fn() {} #[pyclass] struct MyClass; #[pymethods] impl MyClass { #[new] fn new() -> Self { Self } // TODO use &self when possible async fn my_method(_self: Py) {} #[classmethod] async fn my_classmethod(_cls: Py) {} #[staticmethod] async fn my_staticmethod() {} } Python::with_gil(|py| { let test = r#" for coro, name, qualname in [ (my_fn(), "my_fn", "my_fn"), (MyClass().my_method(), "my_method", "MyClass.my_method"), #(MyClass().my_classmethod(), "my_classmethod", "MyClass.my_classmethod"), (MyClass.my_staticmethod(), "my_staticmethod", "MyClass.my_staticmethod"), ]: assert coro.__name__ == name and coro.__qualname__ == qualname "#; let locals = [ ("my_fn", wrap_pyfunction!(my_fn, py).unwrap().as_any()), ("MyClass", py.get_type::().as_any()), ] .into_py_dict(py) .unwrap(); py_run!(py, *locals, &handle_windows(test)); }) } #[test] fn sleep_0_like_coroutine() { #[pyfunction] async fn sleep_0() -> usize { let mut waken = false; poll_fn(|cx| { if !waken { cx.waker().wake_by_ref(); waken = true; return Poll::Pending; } Poll::Ready(42) }) .await } Python::with_gil(|py| { let sleep_0 = wrap_pyfunction!(sleep_0, py).unwrap(); let test = "import asyncio; assert asyncio.run(sleep_0()) == 42"; py_run!(py, sleep_0, &handle_windows(test)); }) } #[pyfunction] async fn sleep(seconds: f64) -> usize { let (tx, rx) = oneshot::channel(); thread::spawn(move || { thread::sleep(Duration::from_secs_f64(seconds)); tx.send(42).unwrap(); }); rx.await.unwrap() } #[test] fn sleep_coroutine() { Python::with_gil(|py| { let sleep = wrap_pyfunction!(sleep, py).unwrap(); let test = r#"import asyncio; assert asyncio.run(sleep(0.1)) == 42"#; py_run!(py, sleep, &handle_windows(test)); }) } #[pyfunction] async fn return_tuple() -> (usize, usize) { (42, 43) } #[test] fn tuple_coroutine() { Python::with_gil(|py| { let func = wrap_pyfunction!(return_tuple, py).unwrap(); let test = r#"import asyncio; assert asyncio.run(func()) == (42, 43)"#; py_run!(py, func, &handle_windows(test)); }) } #[test] fn cancelled_coroutine() { Python::with_gil(|py| { let sleep = wrap_pyfunction!(sleep, py).unwrap(); let test = r#" import asyncio async def main(): task = asyncio.create_task(sleep(999)) await asyncio.sleep(0) task.cancel() await task asyncio.run(main()) "#; let globals = PyDict::new(py); globals.set_item("sleep", sleep).unwrap(); let err = py .run( &CString::new(pyo3::unindent::unindent(&handle_windows(test))).unwrap(), Some(&globals), None, ) .unwrap_err(); assert_eq!( err.value(py).get_type().qualname().unwrap(), "CancelledError" ); }) } #[test] fn coroutine_cancel_handle() { #[pyfunction] async fn cancellable_sleep( seconds: f64, #[pyo3(cancel_handle)] mut cancel: CancelHandle, ) -> usize { futures::select! { _ = sleep(seconds).fuse() => 42, _ = cancel.cancelled().fuse() => 0, } } Python::with_gil(|py| { let cancellable_sleep = wrap_pyfunction!(cancellable_sleep, py).unwrap(); let test = r#" import asyncio; async def main(): task = asyncio.create_task(cancellable_sleep(999)) await asyncio.sleep(0) task.cancel() return await task assert asyncio.run(main()) == 0 "#; let globals = PyDict::new(py); globals .set_item("cancellable_sleep", cancellable_sleep) .unwrap(); py.run( &CString::new(pyo3::unindent::unindent(&handle_windows(test))).unwrap(), Some(&globals), None, ) .unwrap(); }) } #[test] fn coroutine_is_cancelled() { #[pyfunction] async fn sleep_loop(#[pyo3(cancel_handle)] cancel: CancelHandle) { while !cancel.is_cancelled() { sleep(0.001).await; } } Python::with_gil(|py| { let sleep_loop = wrap_pyfunction!(sleep_loop, py).unwrap(); let test = r#" import asyncio; async def main(): task = asyncio.create_task(sleep_loop()) await asyncio.sleep(0) task.cancel() await task asyncio.run(main()) "#; let globals = PyDict::new(py); globals.set_item("sleep_loop", sleep_loop).unwrap(); py.run( &CString::new(pyo3::unindent::unindent(&handle_windows(test))).unwrap(), Some(&globals), None, ) .unwrap(); }) } #[test] fn coroutine_panic() { #[pyfunction] async fn panic() { panic!("test panic"); } Python::with_gil(|py| { let panic = wrap_pyfunction!(panic, py).unwrap(); let test = r#" import asyncio coro = panic() try: asyncio.run(coro) except BaseException as err: assert type(err).__name__ == "PanicException" assert str(err) == "test panic" else: assert False try: coro.send(None) except RuntimeError as err: assert str(err) == "cannot reuse already awaited coroutine" else: assert False; "#; py_run!(py, panic, &handle_windows(test)); }) } #[test] fn test_async_method_receiver() { #[pyclass] struct Counter(usize); #[pymethods] impl Counter { #[new] fn new() -> Self { Self(0) } async fn get(&self) -> usize { self.0 } async fn incr(&mut self) -> usize { self.0 += 1; self.0 } } static IS_DROPPED: AtomicBool = AtomicBool::new(false); impl Drop for Counter { fn drop(&mut self) { IS_DROPPED.store(true, Ordering::SeqCst); } } Python::with_gil(|py| { let test = r#" import asyncio obj = Counter() coro1 = obj.get() coro2 = obj.get() try: obj.incr() # borrow checking should fail except RuntimeError as err: pass else: assert False assert asyncio.run(coro1) == 0 coro2.close() coro3 = obj.incr() try: obj.incr() # borrow checking should fail except RuntimeError as err: pass else: assert False try: obj.get() # borrow checking should fail except RuntimeError as err: pass else: assert False assert asyncio.run(coro3) == 1 "#; let locals = [("Counter", py.get_type::())] .into_py_dict(py) .unwrap(); py_run!(py, *locals, test); }); assert!(IS_DROPPED.load(Ordering::SeqCst)); } #[test] fn test_async_method_receiver_with_other_args() { #[pyclass] struct Value(i32); #[pymethods] impl Value { #[new] fn new() -> Self { Self(0) } async fn get_value_plus_with(&self, v1: i32, v2: i32) -> i32 { self.0 + v1 + v2 } async fn set_value(&mut self, new_value: i32) -> i32 { self.0 = new_value; self.0 } } Python::with_gil(|py| { let test = r#" import asyncio v = Value() assert asyncio.run(v.get_value_plus_with(3, 0)) == 3 assert asyncio.run(v.set_value(10)) == 10 assert asyncio.run(v.get_value_plus_with(1, 1)) == 12 "#; let locals = [("Value", py.get_type::())] .into_py_dict(py) .unwrap(); py_run!(py, *locals, test); }); } pyo3/tests/test_pyself.rs0000644000175000017500000000610015105742312015342 0ustar bdrungbdrung#![cfg(feature = "macros")] //! Test slf: PyRef/PyMutRef(especially, slf.into::) works use pyo3::prelude::*; use pyo3::types::{PyBytes, PyString}; use std::collections::HashMap; #[path = "../src/tests/common.rs"] mod common; /// Assumes it's a file reader or so. /// Inspired by https://github.com/jothan/cordoba, thanks. #[pyclass] #[derive(Clone, Debug)] struct Reader { inner: HashMap, } #[pymethods] impl Reader { fn clone_ref<'a, 'py>(slf: &'a Bound<'py, Self>) -> &'a Bound<'py, Self> { slf } fn clone_ref_with_py<'a, 'py>( slf: &'a Bound<'py, Self>, _py: Python<'py>, ) -> &'a Bound<'py, Self> { slf } fn get_iter(slf: &Bound<'_, Self>, keys: Py) -> Iter { Iter { reader: slf.clone().unbind(), keys, idx: 0, } } fn get_iter_and_reset( mut slf: PyRefMut<'_, Self>, keys: Py, py: Python<'_>, ) -> PyResult { let reader = Py::new(py, slf.clone())?; slf.inner.clear(); Ok(Iter { reader, keys, idx: 0, }) } } #[pyclass] #[derive(Debug)] struct Iter { reader: Py, keys: Py, idx: usize, } #[pymethods] impl Iter { #[allow(clippy::self_named_constructors)] fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(mut slf: PyRefMut<'_, Self>) -> PyResult> { let bytes = slf.keys.bind(slf.py()).as_bytes(); match bytes.get(slf.idx) { Some(&b) => { slf.idx += 1; let py = slf.py(); let reader = slf.reader.bind(py); let reader_ref = reader.try_borrow()?; let res = reader_ref .inner .get(&b) .map(|s| PyString::new(py, s).into()); Ok(res) } None => Ok(None), } } } fn reader() -> Reader { let reader = [(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e")]; Reader { inner: reader.iter().map(|(k, v)| (*k, (*v).to_string())).collect(), } } #[test] fn test_nested_iter() { Python::with_gil(|py| { let reader = reader().into_pyobject(py).unwrap(); py_assert!( py, reader, "list(reader.get_iter(bytes([3, 5, 2]))) == ['c', 'e', 'b']" ); }); } #[test] fn test_clone_ref() { Python::with_gil(|py| { let reader = reader().into_pyobject(py).unwrap(); py_assert!(py, reader, "reader == reader.clone_ref()"); py_assert!(py, reader, "reader == reader.clone_ref_with_py()"); }); } #[test] fn test_nested_iter_reset() { Python::with_gil(|py| { let reader = Bound::new(py, reader()).unwrap(); py_assert!( py, reader, "list(reader.get_iter_and_reset(bytes([3, 5, 2]))) == ['c', 'e', 'b']" ); let reader_ref = reader.borrow(); assert!(reader_ref.inner.is_empty()); }); } pyo3/tests/test_mapping.rs0000644000175000017500000000705615105742312015506 0ustar bdrungbdrung#![cfg(feature = "macros")] use std::collections::HashMap; use pyo3::exceptions::PyKeyError; use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::IntoPyDict; use pyo3::types::PyList; use pyo3::types::PyMapping; use pyo3::types::PySequence; #[path = "../src/tests/common.rs"] mod common; #[pyclass(mapping)] struct Mapping { index: HashMap, } #[pymethods] impl Mapping { #[new] #[pyo3(signature=(elements=None))] fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult { if let Some(pylist) = elements { let mut elems = HashMap::with_capacity(pylist.len()); for (i, pyelem) in pylist.into_iter().enumerate() { let elem = pyelem.extract()?; elems.insert(elem, i); } Ok(Self { index: elems }) } else { Ok(Self { index: HashMap::new(), }) } } fn __len__(&self) -> usize { self.index.len() } fn __getitem__(&self, query: String) -> PyResult { self.index .get(&query) .copied() .ok_or_else(|| PyKeyError::new_err("unknown key")) } fn __setitem__(&mut self, key: String, value: usize) { self.index.insert(key, value); } fn __delitem__(&mut self, key: String) -> PyResult<()> { if self.index.remove(&key).is_none() { Err(PyKeyError::new_err("unknown key")) } else { Ok(()) } } #[pyo3(signature=(key, default=None))] fn get( &self, py: Python<'_>, key: &str, default: Option, ) -> PyResult> { match self.index.get(key) { Some(value) => Ok(Some(value.into_pyobject(py)?.into_any().unbind())), None => Ok(default), } } } /// Return a dict with `m = Mapping(['1', '2', '3'])`. fn map_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { let d = [("Mapping", py.get_type::())] .into_py_dict(py) .unwrap(); py_run!(py, *d, "m = Mapping(['1', '2', '3'])"); d } #[test] fn test_getitem() { Python::with_gil(|py| { let d = map_dict(py); py_assert!(py, *d, "m['1'] == 0"); py_assert!(py, *d, "m['2'] == 1"); py_assert!(py, *d, "m['3'] == 2"); py_expect_exception!(py, *d, "print(m['4'])", PyKeyError); }); } #[test] fn test_setitem() { Python::with_gil(|py| { let d = map_dict(py); py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4"); py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0"); py_assert!(py, *d, "len(m) == 4"); py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError); py_expect_exception!(py, *d, "m[0] = -1", PyTypeError); }); } #[test] fn test_delitem() { Python::with_gil(|py| { let d = map_dict(py); py_run!( py, *d, "del m['1']; assert len(m) == 2 and m['2'] == 1 and m['3'] == 2" ); py_expect_exception!(py, *d, "del m[-1]", PyTypeError); py_expect_exception!(py, *d, "del m['4']", PyKeyError); }); } #[test] fn mapping_is_not_sequence() { Python::with_gil(|py| { let mut index = HashMap::new(); index.insert("Foo".into(), 1); index.insert("Bar".into(), 2); let m = Py::new(py, Mapping { index }).unwrap(); PyMapping::register::(py).unwrap(); assert!(m.bind(py).downcast::().is_ok()); assert!(m.bind(py).downcast::().is_err()); }); } pyo3/tests/test_macros.rs0000644000175000017500000000465315105742312015337 0ustar bdrungbdrung#![cfg(feature = "macros")] //! Ensure that pyo3 macros can be used inside macro_rules! use pyo3::prelude::*; #[macro_use] #[path = "../src/tests/common.rs"] mod common; macro_rules! make_struct_using_macro { // Ensure that one doesn't need to fall back on the escape type: tt // in order to macro create pyclass. ($class_name:ident, $py_name:literal) => { #[pyclass(name=$py_name, subclass)] struct $class_name {} }; } make_struct_using_macro!(MyBaseClass, "MyClass"); macro_rules! set_extends_via_macro { ($class_name:ident, $base_class:path) => { // Try and pass a variable into the extends parameter #[allow(dead_code)] #[pyclass(extends=$base_class)] struct $class_name {} }; } set_extends_via_macro!(MyClass2, MyBaseClass); // // Check that pyfunctiona nd text_signature can be called with macro arguments. // macro_rules! fn_macro { ($sig:literal, $a_exp:expr, $b_exp:expr, $c_exp: expr) => { // Try and pass a variable into the signature parameter #[pyfunction(signature = ($a_exp, $b_exp, *, $c_exp))] #[pyo3(text_signature = $sig)] fn my_function_in_macro(a: i32, b: Option, c: i32) { let _ = (a, b, c); } }; } fn_macro!("(a, b=None, *, c=42)", a, b = None, c = 42); macro_rules! property_rename_via_macro { ($prop_name:ident) => { #[pyclass] struct ClassWithProperty { member: u64, } #[pymethods] impl ClassWithProperty { #[getter($prop_name)] fn get_member(&self) -> u64 { self.member } #[setter($prop_name)] fn set_member(&mut self, member: u64) { self.member = member; } } }; } property_rename_via_macro!(my_new_property_name); #[test] fn test_macro_rules_interactions() { Python::with_gil(|py| { let my_base = py.get_type::(); py_assert!(py, my_base, "my_base.__name__ == 'MyClass'"); let my_func = wrap_pyfunction!(my_function_in_macro, py).unwrap(); py_assert!( py, my_func, "my_func.__text_signature__ == '(a, b=None, *, c=42)'" ); let renamed_prop = py.get_type::(); py_assert!( py, renamed_prop, "hasattr(renamed_prop, 'my_new_property_name')" ); }); } pyo3/tests/test_intopyobject.rs0000644000175000017500000001606415105742312016563 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::types::{PyDict, PyList, PyString}; use pyo3::{prelude::*, py_run, IntoPyObject, IntoPyObjectExt}; use std::collections::HashMap; use std::hash::Hash; #[macro_use] #[path = "../src/tests/common.rs"] mod common; #[derive(Debug, IntoPyObject)] pub struct A<'py> { s: String, t: Bound<'py, PyString>, p: Bound<'py, PyAny>, } #[test] fn test_named_fields_struct() { Python::with_gil(|py| { let a = A { s: "Hello".into(), t: PyString::new(py, "World"), p: 42i32.into_pyobject(py).unwrap().into_any(), }; let pya = a.into_pyobject(py).unwrap(); assert_eq!( pya.get_item("s") .unwrap() .unwrap() .downcast::() .unwrap(), "Hello" ); assert_eq!( pya.get_item("t") .unwrap() .unwrap() .downcast::() .unwrap(), "World" ); assert_eq!( pya.get_item("p") .unwrap() .unwrap() .extract::() .unwrap(), 42 ); }); } #[derive(Debug, IntoPyObject)] #[pyo3(transparent)] pub struct B<'a> { test: &'a str, } #[test] fn test_transparent_named_field_struct() { Python::with_gil(|py| { let pyb = B { test: "test" }.into_pyobject(py).unwrap(); let b = pyb.extract::().unwrap(); assert_eq!(b, "test"); }); } #[derive(Debug, IntoPyObject)] #[pyo3(transparent)] pub struct D { test: T, } #[test] fn test_generic_transparent_named_field_struct() { Python::with_gil(|py| { let pyd = D { test: String::from("test"), } .into_pyobject(py) .unwrap(); let d = pyd.extract::().unwrap(); assert_eq!(d, "test"); let pyd = D { test: 1usize }.into_pyobject(py).unwrap(); let d = pyd.extract::().unwrap(); assert_eq!(d, 1); }); } #[derive(Debug, IntoPyObject)] pub struct GenericWithBound(HashMap); #[test] fn test_generic_with_bound() { Python::with_gil(|py| { let mut hash_map = HashMap::::new(); hash_map.insert("1".into(), 1); hash_map.insert("2".into(), 2); let map = GenericWithBound(hash_map).into_pyobject(py).unwrap(); assert_eq!(map.len(), 2); assert_eq!( map.get_item("1") .unwrap() .unwrap() .extract::() .unwrap(), 1 ); assert_eq!( map.get_item("2") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); assert!(map.get_item("3").unwrap().is_none()); }); } #[derive(Debug, IntoPyObject)] pub struct Tuple(String, usize); #[test] fn test_tuple_struct() { Python::with_gil(|py| { let tup = Tuple(String::from("test"), 1).into_pyobject(py).unwrap(); assert!(tup.extract::<(usize, String)>().is_err()); let tup = tup.extract::<(String, usize)>().unwrap(); assert_eq!(tup.0, "test"); assert_eq!(tup.1, 1); }); } #[derive(Debug, IntoPyObject)] pub struct TransparentTuple(String); #[test] fn test_transparent_tuple_struct() { Python::with_gil(|py| { let tup = TransparentTuple(String::from("test")) .into_pyobject(py) .unwrap(); assert!(tup.extract::<(String,)>().is_err()); let tup = tup.extract::().unwrap(); assert_eq!(tup, "test"); }); } fn phantom_into_py<'py, T>( _: std::borrow::Cow<'_, std::marker::PhantomData>, py: Python<'py>, ) -> PyResult> { std::any::type_name::().into_bound_py_any(py) } #[derive(Debug, IntoPyObject, IntoPyObjectRef)] pub enum Foo<'py> { TupleVar( usize, String, #[pyo3(into_py_with = phantom_into_py::<()>)] std::marker::PhantomData<()>, ), StructVar { test: Bound<'py, PyString>, }, #[pyo3(transparent)] TransparentTuple(usize), #[pyo3(transparent)] TransparentStructVar { a: Option, }, } #[test] fn test_enum() { Python::with_gil(|py| { let foo = Foo::TupleVar(1, "test".into(), std::marker::PhantomData) .into_pyobject(py) .unwrap(); assert_eq!( foo.extract::<(usize, String, String)>().unwrap(), (1, String::from("test"), String::from("()")) ); let foo = Foo::StructVar { test: PyString::new(py, "test"), } .into_pyobject(py) .unwrap() .downcast_into::() .unwrap(); assert_eq!( foo.get_item("test") .unwrap() .unwrap() .downcast_into::() .unwrap(), "test" ); let foo = Foo::TransparentTuple(1).into_pyobject(py).unwrap(); assert_eq!(foo.extract::().unwrap(), 1); let foo = Foo::TransparentStructVar { a: None } .into_pyobject(py) .unwrap(); assert!(foo.is_none()); }); } #[derive(Debug, IntoPyObject, IntoPyObjectRef)] pub struct Zap { #[pyo3(item)] name: String, #[pyo3(into_py_with = zap_into_py, item("my_object"))] some_object_length: usize, } fn zap_into_py<'py>( len: std::borrow::Cow<'_, usize>, py: Python<'py>, ) -> PyResult> { Ok(PyList::new(py, 1..*len + 1)?.into_any()) } #[test] fn test_into_py_with() { Python::with_gil(|py| { let zap = Zap { name: "whatever".into(), some_object_length: 3, }; let py_zap_ref = (&zap).into_pyobject(py).unwrap(); let py_zap = zap.into_pyobject(py).unwrap(); py_run!( py, py_zap_ref, "assert py_zap_ref == {'name': 'whatever', 'my_object': [1, 2, 3]},f'{py_zap_ref}'" ); py_run!( py, py_zap, "assert py_zap == {'name': 'whatever', 'my_object': [1, 2, 3]},f'{py_zap}'" ); }); } #[test] fn test_struct_into_py_rename_all() { #[derive(IntoPyObject, IntoPyObjectRef)] #[pyo3(rename_all = "camelCase")] struct Foo { foo_bar: String, #[pyo3(item("BAZ"))] baz: usize, #[pyo3(item)] long_field_name: f32, } let foo = Foo { foo_bar: "foobar".into(), baz: 42, long_field_name: 0.0, }; Python::with_gil(|py| { let py_foo_ref = (&foo).into_pyobject(py).unwrap(); let py_foo = foo.into_pyobject(py).unwrap(); py_run!( py, py_foo_ref, "assert py_foo_ref == {'fooBar': 'foobar', 'BAZ': 42, 'longFieldName': 0},f'{py_foo_ref}'" ); py_run!( py, py_foo, "assert py_foo == {'fooBar': 'foobar', 'BAZ': 42, 'longFieldName': 0},f'{py_foo}'" ); }); } pyo3/tests/test_sequence.rs0000644000175000017500000002531115105742312015655 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::exceptions::{PyIndexError, PyValueError}; use pyo3::types::{IntoPyDict, PyList, PyMapping, PySequence}; use pyo3::{ffi, prelude::*}; use pyo3::py_run; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct ByteSequence { elements: Vec, } #[pymethods] impl ByteSequence { #[new] #[pyo3(signature=(elements = None))] fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult { if let Some(pylist) = elements { let mut elems = Vec::with_capacity(pylist.len()); for pyelem in pylist { let elem = pyelem.extract()?; elems.push(elem); } Ok(Self { elements: elems }) } else { Ok(Self { elements: Vec::new(), }) } } fn __len__(&self) -> usize { self.elements.len() } fn __getitem__(&self, idx: isize) -> PyResult { self.elements .get(idx as usize) .copied() .ok_or_else(|| PyIndexError::new_err("list index out of range")) } fn __setitem__(&mut self, idx: isize, value: u8) { self.elements[idx as usize] = value; } fn __delitem__(&mut self, mut idx: isize) -> PyResult<()> { let self_len = self.elements.len() as isize; if idx < 0 { idx += self_len; } if (idx < self_len) && (idx >= 0) { self.elements.remove(idx as usize); Ok(()) } else { Err(PyIndexError::new_err("list index out of range")) } } fn __contains__(&self, other: &Bound<'_, PyAny>) -> bool { match other.extract::() { Ok(x) => self.elements.contains(&x), Err(_) => false, } } fn __concat__(&self, other: &Self) -> Self { let mut elements = self.elements.clone(); elements.extend_from_slice(&other.elements); Self { elements } } fn __inplace_concat__(mut slf: PyRefMut<'_, Self>, other: &Self) -> Py { slf.elements.extend_from_slice(&other.elements); slf.into() } fn __repeat__(&self, count: isize) -> PyResult { if count >= 0 { let mut elements = Vec::with_capacity(self.elements.len() * count as usize); for _ in 0..count { elements.extend(&self.elements); } Ok(Self { elements }) } else { Err(PyValueError::new_err("invalid repeat count")) } } fn __inplace_repeat__(mut slf: PyRefMut<'_, Self>, count: isize) -> PyResult> { if count >= 0 { let mut elements = Vec::with_capacity(slf.elements.len() * count as usize); for _ in 0..count { elements.extend(&slf.elements); } slf.elements = elements; Ok(slf.into()) } else { Err(PyValueError::new_err("invalid repeat count")) } } } /// Return a dict with `s = ByteSequence([1, 2, 3])`. fn seq_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { let d = [("ByteSequence", py.get_type::())] .into_py_dict(py) .unwrap(); // Though we can construct `s` in Rust, let's test `__new__` works. py_run!(py, *d, "s = ByteSequence([1, 2, 3])"); d } #[test] fn test_getitem() { Python::with_gil(|py| { let d = seq_dict(py); py_assert!(py, *d, "s[0] == 1"); py_assert!(py, *d, "s[1] == 2"); py_assert!(py, *d, "s[2] == 3"); py_expect_exception!(py, *d, "print(s[-4])", PyIndexError); py_expect_exception!(py, *d, "print(s[4])", PyIndexError); }); } #[test] fn test_setitem() { Python::with_gil(|py| { let d = seq_dict(py); py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]"); py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError); }); } #[test] fn test_delitem() { Python::with_gil(|py| { let d = [("ByteSequence", py.get_type::())] .into_py_dict(py) .unwrap(); py_run!( py, *d, "s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]" ); py_run!( py, *d, "s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]" ); py_run!( py, *d, "s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]" ); py_run!( py, *d, "s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]" ); py_expect_exception!( py, *d, "s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))", PyIndexError ); py_expect_exception!( py, *d, "s = ByteSequence([1, 2, 3]); del s[4]", PyIndexError ); }); } #[test] fn test_contains() { Python::with_gil(|py| { let d = seq_dict(py); py_assert!(py, *d, "1 in s"); py_assert!(py, *d, "2 in s"); py_assert!(py, *d, "3 in s"); py_assert!(py, *d, "4 not in s"); py_assert!(py, *d, "'hello' not in s"); }); } #[test] fn test_concat() { Python::with_gil(|py| { let d = seq_dict(py); py_run!( py, *d, "s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]" ); py_expect_exception!( py, *d, "s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2", PyTypeError ); }); } #[test] fn test_inplace_concat() { Python::with_gil(|py| { let d = seq_dict(py); py_run!( py, *d, "s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]" ); py_expect_exception!(py, *d, "s += 'hello'", PyTypeError); }); } #[test] fn test_repeat() { Python::with_gil(|py| { let d = seq_dict(py); py_run!(py, *d, "s2 = s * 2; assert list(s2) == [1, 2, 3, 1, 2, 3]"); py_expect_exception!(py, *d, "s2 = s * -1", PyValueError); }); } #[test] fn test_inplace_repeat() { Python::with_gil(|py| { let d = [("ByteSequence", py.get_type::())] .into_py_dict(py) .unwrap(); py_run!( py, *d, "s = ByteSequence([1, 2]); s *= 3; assert list(s) == [1, 2, 1, 2, 1, 2]" ); py_expect_exception!(py, *d, "s = ByteSequence([1, 2]); s *= -1", PyValueError); }); } // Check that #[pyo3(get, set)] works correctly for Vec #[pyclass] struct AnyObjectList { #[pyo3(get, set)] items: Vec, } #[test] fn test_any_object_list_get() { Python::with_gil(|py| { let list = AnyObjectList { items: [1i32, 2, 3] .iter() .map(|i| i.into_pyobject(py).unwrap().into_any().unbind()) .collect(), } .into_pyobject(py) .unwrap(); py_assert!(py, list, "list.items == [1, 2, 3]"); }); } #[test] fn test_any_object_list_set() { Python::with_gil(|py| { let list = Bound::new(py, AnyObjectList { items: vec![] }).unwrap(); py_run!(py, list, "list.items = [1, 2, 3]"); assert!(list .borrow() .items .iter() .zip(&[1u32, 2, 3]) .all(|(a, b)| a.bind(py).eq(b.into_pyobject(py).unwrap()).unwrap())); }); } #[pyclass(sequence)] struct OptionList { #[pyo3(get, set)] items: Vec>, } #[pymethods] impl OptionList { fn __len__(&self) -> usize { self.items.len() } fn __getitem__(&self, idx: isize) -> PyResult> { match self.items.get(idx as usize) { Some(x) => Ok(*x), None => Err(PyIndexError::new_err("Index out of bounds")), } } } #[test] fn test_option_list_get() { // Regression test for #798 Python::with_gil(|py| { let list = Py::new( py, OptionList { items: vec![Some(1), None], }, ) .unwrap(); py_assert!(py, list, "list[0] == 1"); py_assert!(py, list, "list[1] == None"); py_expect_exception!(py, list, "list[2]", PyIndexError); }); } #[test] fn sequence_is_not_mapping() { Python::with_gil(|py| { let list = Bound::new( py, OptionList { items: vec![Some(1), None], }, ) .unwrap() .into_any(); PySequence::register::(py).unwrap(); assert!(list.downcast::().is_err()); assert!(list.downcast::().is_ok()); }) } #[test] fn sequence_length() { Python::with_gil(|py| { let list = Bound::new( py, OptionList { items: vec![Some(1), None], }, ) .unwrap() .into_any(); assert_eq!(list.len().unwrap(), 2); assert_eq!(unsafe { ffi::PySequence_Length(list.as_ptr()) }, 2); assert_eq!(unsafe { ffi::PyMapping_Length(list.as_ptr()) }, -1); unsafe { ffi::PyErr_Clear() }; }) } #[cfg(Py_3_10)] #[pyclass(generic, sequence)] struct GenericList { #[pyo3(get, set)] items: Vec, } #[cfg(Py_3_10)] #[pymethods] impl GenericList { fn __len__(&self) -> usize { self.items.len() } fn __getitem__(&self, idx: isize) -> PyResult { match self.items.get(idx as usize) { Some(x) => pyo3::Python::with_gil(|py| Ok(x.clone_ref(py))), None => Err(PyIndexError::new_err("Index out of bounds")), } } } #[cfg(Py_3_10)] #[test] fn test_generic_both_subscriptions_types() { use pyo3::types::PyInt; use std::convert::Infallible; Python::with_gil(|py| { let l = Bound::new( py, GenericList { items: [1, 2, 3] .iter() .map(|x| -> PyObject { let x: Result, Infallible> = x.into_pyobject(py); x.unwrap().into_any().unbind() }) .chain([py.None()]) .collect(), }, ) .unwrap(); let ty = py.get_type::(); py_assert!(py, l, "l[0] == 1"); py_run!( py, ty, "import types; import typing; IntOrNone: typing.TypeAlias = typing.Union[int, None]; assert ty[IntOrNone] == types.GenericAlias(ty, (IntOrNone,))" ); py_assert!(py, l, "list(reversed(l)) == [None, 3, 2, 1]"); }); } pyo3/tests/test_serde.rs0000644000175000017500000000450315105742312015147 0ustar bdrungbdrung#[cfg(feature = "serde")] mod test_serde { use pyo3::prelude::*; use serde::{Deserialize, Serialize}; #[pyclass] #[derive(Debug, Serialize, Deserialize)] struct Group { name: String, } #[pyclass] #[derive(Debug, Serialize, Deserialize)] struct User { username: String, group: Option>, friends: Vec>, } #[test] fn test_serialize() { let friend1 = User { username: "friend 1".into(), group: None, friends: vec![], }; let friend2 = User { username: "friend 2".into(), group: None, friends: vec![], }; let user = Python::with_gil(|py| { let py_friend1 = Py::new(py, friend1).expect("failed to create friend 1"); let py_friend2 = Py::new(py, friend2).expect("failed to create friend 2"); let friends = vec![py_friend1, py_friend2]; let py_group = Py::new( py, Group { name: "group name".into(), }, ) .unwrap(); User { username: "danya".into(), group: Some(py_group), friends, } }); let serialized = serde_json::to_string(&user).expect("failed to serialize"); assert_eq!( serialized, r#"{"username":"danya","group":{"name":"group name"},"friends":[{"username":"friend 1","group":null,"friends":[]},{"username":"friend 2","group":null,"friends":[]}]}"# ); } #[test] fn test_deserialize() { let serialized = r#"{"username": "danya", "friends": [{"username": "friend", "group": {"name": "danya's friends"}, "friends": []}]}"#; let user: User = serde_json::from_str(serialized).expect("failed to deserialize"); assert_eq!(user.username, "danya"); assert!(user.group.is_none()); assert_eq!(user.friends.len(), 1usize); let friend = user.friends.first().unwrap(); Python::with_gil(|py| { assert_eq!(friend.borrow(py).username, "friend"); assert_eq!( friend.borrow(py).group.as_ref().unwrap().borrow(py).name, "danya's friends" ) }); } } pyo3/tests/test_class_basics.rs0000644000175000017500000004340515105742312016502 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::PyType; use pyo3::{py_run, PyClass}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct EmptyClass {} #[test] fn empty_class() { Python::with_gil(|py| { let typeobj = py.get_type::(); // By default, don't allow creating instances from python. assert!(typeobj.call((), None).is_err()); py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'"); }); } #[pyclass] struct UnitClass; #[test] fn unit_class() { Python::with_gil(|py| { let typeobj = py.get_type::(); // By default, don't allow creating instances from python. assert!(typeobj.call((), None).is_err()); py_assert!(py, typeobj, "typeobj.__name__ == 'UnitClass'"); }); } /// Line1 ///Line2 /// Line3 // this is not doc string #[pyclass] struct ClassWithDocs { /// Property field #[pyo3(get, set)] value: i32, /// Read-only property field #[pyo3(get)] readonly: i32, /// Write-only property field #[pyo3(set)] #[allow(dead_code)] // Rust detects field is never read writeonly: i32, } #[test] fn class_with_docstr() { Python::with_gil(|py| { let typeobj = py.get_type::(); py_run!( py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'" ); py_run!( py, typeobj, "assert typeobj.value.__doc__ == 'Property field'" ); py_run!( py, typeobj, "assert typeobj.readonly.__doc__ == 'Read-only property field'" ); py_run!( py, typeobj, "assert typeobj.writeonly.__doc__ == 'Write-only property field'" ); }); } #[pyclass(name = "CustomName")] struct EmptyClass2 {} #[pymethods] impl EmptyClass2 { #[pyo3(name = "custom_fn")] fn bar(&self) {} #[staticmethod] #[pyo3(name = "custom_static")] fn bar_static() {} #[getter] #[pyo3(name = "custom_getter")] fn foo(&self) -> i32 { 5 } } #[test] fn custom_names() { Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'"); py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'"); py_assert!( py, typeobj, "typeobj.custom_static.__name__ == 'custom_static'" ); py_assert!( py, typeobj, "typeobj.custom_getter.__name__ == 'custom_getter'" ); py_assert!(py, typeobj, "not hasattr(typeobj, 'bar')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'bar_static')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'foo')"); }); } #[pyclass(name = "loop")] struct ClassRustKeywords { #[pyo3(name = "unsafe", get, set)] unsafe_variable: usize, } #[pymethods] impl ClassRustKeywords { #[pyo3(name = "struct")] fn struct_method(&self) {} #[staticmethod] #[pyo3(name = "type")] fn type_method() {} } #[test] fn keyword_names() { Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "typeobj.__name__ == 'loop'"); py_assert!(py, typeobj, "typeobj.struct.__name__ == 'struct'"); py_assert!(py, typeobj, "typeobj.type.__name__ == 'type'"); py_assert!(py, typeobj, "typeobj.unsafe.__name__ == 'unsafe'"); py_assert!(py, typeobj, "not hasattr(typeobj, 'unsafe_variable')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'struct_method')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'type_method')"); }); } #[pyclass] struct RawIdents { #[pyo3(get, set)] r#type: i64, } #[pymethods] impl RawIdents { fn r#fn(&self) {} } #[test] fn test_raw_idents() { Python::with_gil(|py| { let typeobj = py.get_type::(); py_assert!(py, typeobj, "not hasattr(typeobj, 'r#fn')"); py_assert!(py, typeobj, "hasattr(typeobj, 'fn')"); py_assert!(py, typeobj, "hasattr(typeobj, 'type')"); }); } #[pyclass] struct EmptyClassInModule {} // Ignored because heap types do not show up as being in builtins, instead they // raise AttributeError: // https://github.com/python/cpython/blob/v3.11.1/Objects/typeobject.c#L541-L570 #[test] #[ignore] fn empty_class_in_module() { Python::with_gil(|py| { let module = PyModule::new(py, "test_module.nested").unwrap(); module.add_class::().unwrap(); let ty = module.getattr("EmptyClassInModule").unwrap(); assert_eq!( ty.getattr("__name__").unwrap().extract::().unwrap(), "EmptyClassInModule" ); let module: String = ty.getattr("__module__").unwrap().extract().unwrap(); // Rationale: The class can be added to many modules, but will only be initialized once. // We currently have no way of determining a canonical module, so builtins is better // than using whatever calls init first. assert_eq!(module, "builtins"); }); } #[pyclass] struct ClassWithObjectField { // It used to be that PyObject was not supported with (get, set) // - this test is just ensuring it compiles. #[pyo3(get, set)] value: PyObject, } #[pymethods] impl ClassWithObjectField { #[new] fn new(value: PyObject) -> ClassWithObjectField { Self { value } } } #[test] fn class_with_object_field() { Python::with_gil(|py| { let ty = py.get_type::(); py_assert!(py, ty, "ty(5).value == 5"); py_assert!(py, ty, "ty(None).value == None"); }); } #[pyclass(frozen, eq, hash)] #[derive(PartialEq, Hash)] struct ClassWithHash { value: usize, } #[test] fn class_with_hash() { Python::with_gil(|py| { use pyo3::types::IntoPyDict; let class = ClassWithHash { value: 42 }; let hash = { use std::hash::{Hash, Hasher}; let mut hasher = std::collections::hash_map::DefaultHasher::new(); class.hash(&mut hasher); hasher.finish() as isize }; let env = [ ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_pyobject(py).unwrap().into_any().unbind()), ] .into_py_dict(py) .unwrap(); py_assert!(py, *env, "hash(obj) == hsh"); }); } #[pyclass(unsendable, subclass)] struct UnsendableBase { value: std::rc::Rc, } #[pymethods] impl UnsendableBase { #[new] fn new(value: usize) -> UnsendableBase { Self { value: std::rc::Rc::new(value), } } #[getter] fn value(&self) -> usize { *self.value } } #[pyclass(extends=UnsendableBase)] struct UnsendableChild {} #[pymethods] impl UnsendableChild { #[new] fn new(value: usize) -> (UnsendableChild, UnsendableBase) { (UnsendableChild {}, UnsendableBase::new(value)) } } fn test_unsendable() -> PyResult<()> { let (keep_obj_here, obj) = Python::with_gil(|py| -> PyResult<_> { let obj: Py = PyType::new::(py).call1((5,))?.extract()?; // Accessing the value inside this thread should not panic let caught_panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| -> PyResult<_> { assert_eq!(obj.getattr(py, "value")?.extract::(py)?, 5); Ok(()) })) .is_err(); assert!(!caught_panic); Ok((obj.clone_ref(py), obj)) })?; let caught_panic = std::thread::spawn(move || { // This access must panic Python::with_gil(move |py| { obj.borrow(py); }); }) .join(); Python::with_gil(|_py| drop(keep_obj_here)); if let Err(err) = caught_panic { if let Some(msg) = err.downcast_ref::() { panic!("{}", msg); } } Ok(()) } /// If a class is marked as `unsendable`, it panics when accessed by another thread. #[test] #[cfg_attr(target_arch = "wasm32", ignore)] #[should_panic( expected = "test_class_basics::UnsendableBase is unsendable, but sent to another thread" )] fn panic_unsendable_base() { test_unsendable::().unwrap(); } #[test] #[cfg_attr(target_arch = "wasm32", ignore)] #[should_panic( expected = "test_class_basics::UnsendableBase is unsendable, but sent to another thread" )] fn panic_unsendable_child() { test_unsendable::().unwrap(); } fn get_length(obj: &Bound<'_, PyAny>) -> PyResult { let length = obj.len()?; Ok(length) } fn is_even(obj: &Bound<'_, PyAny>) -> PyResult { obj.extract::().map(|i| i % 2 == 0) } #[pyclass] struct ClassWithFromPyWithMethods {} #[pymethods] impl ClassWithFromPyWithMethods { fn instance_method(&self, #[pyo3(from_py_with = get_length)] argument: usize) -> usize { argument } #[classmethod] fn classmethod( _cls: &Bound<'_, PyType>, #[pyo3(from_py_with = Bound::<'_, PyAny>::len)] argument: usize, ) -> usize { argument } #[staticmethod] fn staticmethod(#[pyo3(from_py_with = get_length)] argument: usize) -> usize { argument } fn __contains__(&self, #[pyo3(from_py_with = is_even)] obj: bool) -> bool { obj } } #[test] fn test_pymethods_from_py_with() { Python::with_gil(|py| { let instance = Py::new(py, ClassWithFromPyWithMethods {}).unwrap(); py_run!( py, instance, r#" arg = {1: 1, 2: 3} assert instance.instance_method(arg) == 2 assert instance.classmethod(arg) == 2 assert instance.staticmethod(arg) == 2 assert 42 in instance assert 73 not in instance "# ); }) } #[pyclass] struct TupleClass(#[pyo3(get, set, name = "value")] i32); #[test] fn test_tuple_struct_class() { Python::with_gil(|py| { let typeobj = py.get_type::(); assert!(typeobj.call((), None).is_err()); py_assert!(py, typeobj, "typeobj.__name__ == 'TupleClass'"); let instance = Py::new(py, TupleClass(5)).unwrap(); py_run!( py, instance, r#" assert instance.value == 5; instance.value = 1234; assert instance.value == 1234; "# ); assert_eq!(instance.borrow(py).0, 1234); }); } #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(dict, subclass)] struct DunderDictSupport { // Make sure that dict_offset runs with non-zero sized Self _pad: [u8; 32], } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn dunder_dict_support() { Python::with_gil(|py| { let inst = Py::new( py, DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ) .unwrap(); py_run!( py, inst, r#" inst.a = 1 assert inst.a == 1 "# ); }); } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn access_dunder_dict() { Python::with_gil(|py| { let inst = Py::new( py, DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ) .unwrap(); py_run!( py, inst, r#" inst.a = 1 assert inst.__dict__ == {'a': 1} "# ); }); } // If the base class has dict support, child class also has dict #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(extends=DunderDictSupport)] struct InheritDict { _value: usize, } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn inherited_dict() { Python::with_gil(|py| { let inst = Py::new( py, ( InheritDict { _value: 0 }, DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ), ) .unwrap(); py_run!( py, inst, r#" inst.a = 1 assert inst.a == 1 "# ); }); } #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(weakref, dict)] struct WeakRefDunderDictSupport { // Make sure that weaklist_offset runs with non-zero sized Self _pad: [u8; 32], } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn weakref_dunder_dict_support() { Python::with_gil(|py| { let inst = Py::new( py, WeakRefDunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ) .unwrap(); py_run!( py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1" ); }); } #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(weakref, subclass)] struct WeakRefSupport { _pad: [u8; 32], } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn weakref_support() { Python::with_gil(|py| { let inst = Py::new( py, WeakRefSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ) .unwrap(); py_run!( py, inst, "import weakref; assert weakref.ref(inst)() is inst" ); }); } // If the base class has weakref support, child class also has weakref. #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(extends=WeakRefSupport)] struct InheritWeakRef { _value: usize, } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn inherited_weakref() { Python::with_gil(|py| { let inst = Py::new( py, ( InheritWeakRef { _value: 0 }, WeakRefSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ), ) .unwrap(); py_run!( py, inst, "import weakref; assert weakref.ref(inst)() is inst" ); }); } #[test] fn access_frozen_class_without_gil() { use std::sync::atomic::{AtomicUsize, Ordering}; #[pyclass(frozen)] struct FrozenCounter { value: AtomicUsize, } let py_counter: Py = Python::with_gil(|py| { let counter = FrozenCounter { value: AtomicUsize::new(0), }; let cell = Bound::new(py, counter).unwrap(); cell.get().value.fetch_add(1, Ordering::Relaxed); cell.into() }); assert_eq!(py_counter.get().value.load(Ordering::Relaxed), 1); Python::with_gil(move |_py| drop(py_counter)); } #[test] #[cfg(all(Py_3_8, not(Py_GIL_DISABLED)))] // sys.unraisablehook not available until Python 3.8 #[cfg_attr(target_arch = "wasm32", ignore)] fn drop_unsendable_elsewhere() { use common::UnraisableCapture; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, }; use std::thread::spawn; #[pyclass(unsendable)] struct Unsendable { dropped: Arc, } impl Drop for Unsendable { fn drop(&mut self) { self.dropped.store(true, Ordering::SeqCst); } } Python::with_gil(|py| { let capture = UnraisableCapture::install(py); let dropped = Arc::new(AtomicBool::new(false)); let unsendable = Py::new( py, Unsendable { dropped: dropped.clone(), }, ) .unwrap(); py.allow_threads(|| { spawn(move || { Python::with_gil(move |_py| { drop(unsendable); }); }) .join() .unwrap(); }); assert!(!dropped.load(Ordering::SeqCst)); let (err, object) = capture.borrow_mut(py).capture.take().unwrap(); assert_eq!(err.to_string(), "RuntimeError: test_class_basics::drop_unsendable_elsewhere::Unsendable is unsendable, but is being dropped on another thread"); assert!(object.is_none(py)); capture.borrow_mut(py).uninstall(py); }); } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn test_unsendable_dict() { #[pyclass(dict, unsendable)] struct UnsendableDictClass {} #[pymethods] impl UnsendableDictClass { #[new] fn new() -> Self { UnsendableDictClass {} } } Python::with_gil(|py| { let inst = Py::new(py, UnsendableDictClass {}).unwrap(); py_run!(py, inst, "assert inst.__dict__ == {}"); }); } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn test_unsendable_dict_with_weakref() { #[pyclass(dict, unsendable, weakref)] struct UnsendableDictClassWithWeakRef {} #[pymethods] impl UnsendableDictClassWithWeakRef { #[new] fn new() -> Self { Self {} } } Python::with_gil(|py| { let inst = Py::new(py, UnsendableDictClassWithWeakRef {}).unwrap(); py_run!(py, inst, "assert inst.__dict__ == {}"); py_run!( py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1" ); }); } #[cfg(Py_3_9)] #[pyclass(generic)] struct ClassWithRuntimeParametrization { #[pyo3(get, set)] value: PyObject, } #[cfg(Py_3_9)] #[pymethods] impl ClassWithRuntimeParametrization { #[new] fn new(value: PyObject) -> ClassWithRuntimeParametrization { Self { value } } } #[test] #[cfg(Py_3_9)] fn test_runtime_parametrization() { Python::with_gil(|py| { let ty = py.get_type::(); py_assert!(py, ty, "ty[int] == ty.__class_getitem__((int,))"); py_run!( py, ty, "import types; assert ty.__class_getitem__((int,)) == types.GenericAlias(ty, (int,))" ); }); } pyo3/tests/test_gc.rs0000644000175000017500000004733215105742312014445 0ustar bdrungbdrung#![cfg(feature = "macros")] #![cfg_attr(not(cargo_toml_lints), warn(unsafe_op_in_unsafe_fn))] use pyo3::class::PyTraverseError; use pyo3::class::PyVisit; use pyo3::ffi; use pyo3::prelude::*; #[cfg(not(Py_GIL_DISABLED))] use pyo3::py_run; #[cfg(not(target_arch = "wasm32"))] use std::cell::Cell; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; use std::sync::{Arc, Mutex}; #[path = "../src/tests/common.rs"] mod common; #[pyclass(freelist = 2)] struct ClassWithFreelist {} #[test] fn class_with_freelist() { let ptr = Python::with_gil(|py| { let inst = Py::new(py, ClassWithFreelist {}).unwrap(); let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap(); let ptr = inst.as_ptr(); drop(inst); ptr }); Python::with_gil(|py| { let inst3 = Py::new(py, ClassWithFreelist {}).unwrap(); assert_eq!(ptr, inst3.as_ptr()); let inst4 = Py::new(py, ClassWithFreelist {}).unwrap(); assert_ne!(ptr, inst4.as_ptr()) }); } #[pyclass(freelist = 2)] #[cfg(not(target_arch = "wasm32"))] struct ClassWithFreelistAndData { data: Option, } #[cfg(not(target_arch = "wasm32"))] fn spin_freelist(py: Python<'_>, data: usize) { for _ in 0..500 { let inst1 = Py::new(py, ClassWithFreelistAndData { data: Some(data) }).unwrap(); let inst2 = Py::new(py, ClassWithFreelistAndData { data: Some(data) }).unwrap(); assert_eq!(inst1.borrow(py).data, Some(data)); assert_eq!(inst2.borrow(py).data, Some(data)); } } #[test] #[cfg(not(target_arch = "wasm32"))] fn multithreaded_class_with_freelist() { std::thread::scope(|s| { s.spawn(|| { Python::with_gil(|py| spin_freelist(py, 12)); }); s.spawn(|| { Python::with_gil(|py| spin_freelist(py, 0x4d3d3d3)); }); }); } /// Helper function to create a pair of objects that can be used to test drops; /// the first object is a guard that records when it has been dropped, the second /// object is a check that can be used to assert that the guard has been dropped. fn drop_check() -> (DropGuard, DropCheck) { let flag = Arc::new(Once::new()); (DropGuard(flag.clone()), DropCheck(flag)) } /// Helper structure that records when it has been dropped in the cor struct DropGuard(Arc); impl Drop for DropGuard { fn drop(&mut self) { self.0.call_once(|| ()); } } struct DropCheck(Arc); impl DropCheck { #[track_caller] fn assert_not_dropped(&self) { assert!(!self.0.is_completed()); } #[track_caller] fn assert_dropped(&self) { assert!(self.0.is_completed()); } #[track_caller] fn assert_drops_with_gc(&self, object: *mut pyo3::ffi::PyObject) { // running the GC might take a few cycles to collect an object for _ in 0..100 { if self.0.is_completed() { return; } Python::with_gil(|py| { py.run(ffi::c_str!("import gc; gc.collect()"), None, None) .unwrap(); }); #[cfg(Py_GIL_DISABLED)] { // on the free-threaded build, the GC might be running in a separate thread, allow // some time for this std::thread::sleep(std::time::Duration::from_millis(5)); } } panic!( "Object was not dropped after 100 GC cycles, refcount is {}", // this could be garbage, but it's in a test and we're just printing the value unsafe { ffi::Py_REFCNT(object) } ); } } #[test] fn data_is_dropped() { #[pyclass] struct DataIsDropped { _guard1: DropGuard, _guard2: DropGuard, } let (guard1, check1) = drop_check(); let (guard2, check2) = drop_check(); Python::with_gil(|py| { let data_is_dropped = DataIsDropped { _guard1: guard1, _guard2: guard2, }; let inst = Py::new(py, data_is_dropped).unwrap(); check1.assert_not_dropped(); check2.assert_not_dropped(); drop(inst); }); check1.assert_dropped(); check2.assert_dropped(); } #[pyclass(subclass)] struct CycleWithClear { cycle: Option, _guard: DropGuard, } #[pymethods] impl CycleWithClear { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.cycle) } fn __clear__(slf: &Bound<'_, Self>) { println!("clear run, refcount before {}", slf.get_refcnt()); slf.borrow_mut().cycle = None; println!("clear run, refcount after {}", slf.get_refcnt()); } } #[test] fn test_cycle_clear() { let (guard, check) = drop_check(); let ptr = Python::with_gil(|py| { let inst = Bound::new( py, CycleWithClear { cycle: None, _guard: guard, }, ) .unwrap(); inst.borrow_mut().cycle = Some(inst.clone().into_any().unbind()); // gc.get_objects can create references to partially initialized objects, // leading to races on the free-threaded build. // see https://github.com/python/cpython/issues/130421#issuecomment-2682924142 #[cfg(not(Py_GIL_DISABLED))] py_run!(py, inst, "import gc; assert inst in gc.get_objects()"); check.assert_not_dropped(); inst.as_ptr() }); check.assert_drops_with_gc(ptr); } /// Test that traversing `None` of `Option>` does not cause a segfault #[test] fn gc_null_traversal() { #[pyclass] struct GcNullTraversal { cycle: Option>, null: Option>, } #[pymethods] impl GcNullTraversal { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.cycle)?; visit.call(&self.null)?; // Should not segfault Ok(()) } fn __clear__(&mut self) { self.cycle = None; self.null = None; } } Python::with_gil(|py| { let obj = Py::new( py, GcNullTraversal { cycle: None, null: None, }, ) .unwrap(); obj.borrow_mut(py).cycle = Some(obj.clone_ref(py)); // the object doesn't have to be cleaned up, it just needs to be traversed. py.run(ffi::c_str!("import gc; gc.collect()"), None, None) .unwrap(); }); } #[test] fn inheritance_with_new_methods_with_drop() { #[pyclass(subclass)] struct BaseClassWithDrop { guard: Option, } #[pymethods] impl BaseClassWithDrop { #[new] fn new() -> BaseClassWithDrop { BaseClassWithDrop { guard: None } } } #[pyclass(extends = BaseClassWithDrop)] struct SubClassWithDrop { guard: Option, } #[pymethods] impl SubClassWithDrop { #[new] fn new() -> (Self, BaseClassWithDrop) { ( SubClassWithDrop { guard: None }, BaseClassWithDrop { guard: None }, ) } } let (guard_base, check_base) = drop_check(); let (guard_sub, check_sub) = drop_check(); Python::with_gil(|py| { let typeobj = py.get_type::(); let inst = typeobj .call((), None) .unwrap() .downcast_into::() .unwrap(); inst.as_super().borrow_mut().guard = Some(guard_base); inst.borrow_mut().guard = Some(guard_sub); check_base.assert_not_dropped(); check_sub.assert_not_dropped(); }); check_base.assert_dropped(); check_sub.assert_dropped(); } #[test] fn gc_during_borrow() { #[pyclass] struct TraversableClass { traversed: AtomicBool, } impl TraversableClass { fn new() -> Self { Self { traversed: AtomicBool::new(false), } } } #[pymethods] impl TraversableClass { fn __clear__(&mut self) {} #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.traversed.store(true, Ordering::Relaxed); Ok(()) } } Python::with_gil(|py| { // get the traverse function let ty = py.get_type::(); let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() }; // create an object and check that traversing it works normally // when it's not borrowed let cell = Bound::new(py, TraversableClass::new()).unwrap(); assert!(!cell.borrow().traversed.load(Ordering::Relaxed)); unsafe { traverse(cell.as_ptr(), novisit, std::ptr::null_mut()) }; assert!(cell.borrow().traversed.load(Ordering::Relaxed)); // create an object and check that it is not traversed if the GC // is invoked while it is already borrowed mutably let cell2 = Bound::new(py, TraversableClass::new()).unwrap(); let guard = cell2.borrow_mut(); assert!(!guard.traversed.load(Ordering::Relaxed)); unsafe { traverse(cell2.as_ptr(), novisit, std::ptr::null_mut()) }; assert!(!guard.traversed.load(Ordering::Relaxed)); drop(guard); }); } #[test] fn traverse_partial() { #[pyclass] struct PartialTraverse { member: PyObject, } impl PartialTraverse { fn new(py: Python<'_>) -> Self { Self { member: py.None() } } } #[pymethods] impl PartialTraverse { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.member)?; // In the test, we expect this to never be hit unreachable!() } } Python::with_gil(|py| { // get the traverse function let ty = py.get_type::(); let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() }; // confirm that traversing errors let obj = Py::new(py, PartialTraverse::new(py)).unwrap(); assert_eq!( unsafe { traverse(obj.as_ptr(), visit_error, std::ptr::null_mut()) }, -1 ); }) } #[test] fn traverse_panic() { #[pyclass] struct PanickyTraverse { member: PyObject, } impl PanickyTraverse { fn new(py: Python<'_>) -> Self { Self { member: py.None() } } } #[pymethods] impl PanickyTraverse { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.member)?; panic!("at the disco"); } } Python::with_gil(|py| { // get the traverse function let ty = py.get_type::(); let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() }; // confirm that traversing errors let obj = Py::new(py, PanickyTraverse::new(py)).unwrap(); assert_eq!( unsafe { traverse(obj.as_ptr(), novisit, std::ptr::null_mut()) }, -1 ); }) } #[test] fn tries_gil_in_traverse() { #[pyclass] struct TriesGILInTraverse {} #[pymethods] impl TriesGILInTraverse { fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { Python::with_gil(|_py| Ok(())) } } Python::with_gil(|py| { // get the traverse function let ty = py.get_type::(); let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() }; // confirm that traversing panicks let obj = Py::new(py, TriesGILInTraverse {}).unwrap(); assert_eq!( unsafe { traverse(obj.as_ptr(), novisit, std::ptr::null_mut()) }, -1 ); }) } #[test] fn traverse_cannot_be_hijacked() { #[pyclass] struct HijackedTraverse { traversed: AtomicBool, hijacked: AtomicBool, } impl HijackedTraverse { fn new() -> Self { Self { traversed: AtomicBool::new(false), hijacked: AtomicBool::new(false), } } fn traversed_and_hijacked(&self) -> (bool, bool) { ( self.traversed.load(Ordering::Acquire), self.hijacked.load(Ordering::Acquire), ) } } #[pymethods] impl HijackedTraverse { #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.traversed.store(true, Ordering::Release); Ok(()) } } #[allow(dead_code)] trait Traversable { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>; } impl Traversable for PyRef<'_, HijackedTraverse> { fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.hijacked.store(true, Ordering::Release); Ok(()) } } Python::with_gil(|py| { // get the traverse function let ty = py.get_type::(); let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() }; let cell = Bound::new(py, HijackedTraverse::new()).unwrap(); assert_eq!(cell.borrow().traversed_and_hijacked(), (false, false)); unsafe { traverse(cell.as_ptr(), novisit, std::ptr::null_mut()) }; assert_eq!(cell.borrow().traversed_and_hijacked(), (true, false)); }) } #[pyclass] struct DropDuringTraversal { cycle: Mutex>>, _guard: DropGuard, } #[pymethods] impl DropDuringTraversal { #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { let mut cycle_ref = self.cycle.lock().unwrap(); *cycle_ref = None; Ok(()) } } #[cfg(not(pyo3_disable_reference_pool))] #[test] fn drop_during_traversal_with_gil() { let (guard, check) = drop_check(); let ptr = Python::with_gil(|py| { let cycle = Mutex::new(None); let inst = Py::new( py, DropDuringTraversal { cycle, _guard: guard, }, ) .unwrap(); *inst.borrow_mut(py).cycle.lock().unwrap() = Some(inst.clone_ref(py)); check.assert_not_dropped(); let ptr = inst.as_ptr(); drop(inst); // drop the object while holding the GIL #[cfg(not(Py_GIL_DISABLED))] { // other thread might have caused GC on free-threaded build check.assert_not_dropped(); } ptr }); check.assert_drops_with_gc(ptr); } #[cfg(not(pyo3_disable_reference_pool))] #[test] fn drop_during_traversal_without_gil() { let (guard, check) = drop_check(); let inst = Python::with_gil(|py| { let cycle = Mutex::new(None); let inst = Py::new( py, DropDuringTraversal { cycle, _guard: guard, }, ) .unwrap(); *inst.borrow_mut(py).cycle.lock().unwrap() = Some(inst.clone_ref(py)); check.assert_not_dropped(); inst }); let ptr = inst.as_ptr(); drop(inst); // drop the object without holding the GIL check.assert_drops_with_gc(ptr); } #[test] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled fn unsendable_are_not_traversed_on_foreign_thread() { #[pyclass(unsendable)] struct UnsendableTraversal { traversed: Cell, } #[pymethods] impl UnsendableTraversal { fn __clear__(&mut self) {} #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.traversed.set(true); Ok(()) } } #[derive(Clone, Copy)] struct SendablePtr(*mut pyo3::ffi::PyObject); unsafe impl Send for SendablePtr {} Python::with_gil(|py| { let ty = py.get_type::(); let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() }; let obj = Bound::new( py, UnsendableTraversal { traversed: Cell::new(false), }, ) .unwrap(); let ptr = SendablePtr(obj.as_ptr()); std::thread::spawn(move || { // traversal on foreign thread is a no-op assert_eq!( unsafe { traverse({ ptr }.0, novisit, std::ptr::null_mut()) }, 0 ); }) .join() .unwrap(); assert!(!obj.borrow().traversed.get()); // traversal on home thread still works assert_eq!( unsafe { traverse({ ptr }.0, novisit, std::ptr::null_mut()) }, 0 ); assert!(obj.borrow().traversed.get()); }); } #[test] fn test_traverse_subclass() { #[pyclass(extends = CycleWithClear)] struct SubOverrideTraverse {} #[pymethods] impl SubOverrideTraverse { #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { // subclass traverse overrides the base class traverse Ok(()) } } let (guard, check) = drop_check(); Python::with_gil(|py| { let base = CycleWithClear { cycle: None, _guard: guard, }; let obj = Bound::new( py, PyClassInitializer::from(base).add_subclass(SubOverrideTraverse {}), ) .unwrap(); obj.borrow_mut().as_super().cycle = Some(obj.clone().into_any().unbind()); check.assert_not_dropped(); let ptr = obj.as_ptr(); drop(obj); #[cfg(not(Py_GIL_DISABLED))] { // other thread might have caused GC on free-threaded build check.assert_not_dropped(); } check.assert_drops_with_gc(ptr); }); } #[test] fn test_traverse_subclass_override_clear() { #[pyclass(extends = CycleWithClear)] struct SubOverrideClear {} #[pymethods] impl SubOverrideClear { #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { // subclass traverse overrides the base class traverse, necessary for // the sub clear to be called // FIXME: should this really need to be the case? Ok(()) } fn __clear__(&self) { // subclass clear overrides the base class clear } } let (guard, check) = drop_check(); Python::with_gil(|py| { let base = CycleWithClear { cycle: None, _guard: guard, }; let obj = Bound::new( py, PyClassInitializer::from(base).add_subclass(SubOverrideClear {}), ) .unwrap(); obj.borrow_mut().as_super().cycle = Some(obj.clone().into_any().unbind()); check.assert_not_dropped(); let ptr = obj.as_ptr(); drop(obj); #[cfg(not(Py_GIL_DISABLED))] { // other thread might have caused GC on free-threaded build check.assert_not_dropped(); } check.assert_drops_with_gc(ptr); }); } // Manual traversal utilities unsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option { unsafe { std::mem::transmute(pyo3::ffi::PyType_GetSlot(tp, pyo3::ffi::Py_tp_traverse)) } } // a dummy visitor function extern "C" fn novisit( _object: *mut pyo3::ffi::PyObject, _arg: *mut core::ffi::c_void, ) -> std::os::raw::c_int { 0 } // a visitor function which errors (returns nonzero code) extern "C" fn visit_error( _object: *mut pyo3::ffi::PyObject, _arg: *mut core::ffi::c_void, ) -> std::os::raw::c_int { -1 } pyo3/tests/test_super.rs0000644000175000017500000000224015105742312015177 0ustar bdrungbdrung#![cfg(all(feature = "macros", not(any(PyPy, GraalPy))))] use pyo3::{prelude::*, types::PySuper}; #[pyclass(subclass)] struct BaseClass { val1: usize, } #[pymethods] impl BaseClass { #[new] fn new() -> Self { BaseClass { val1: 10 } } pub fn method(&self) -> usize { self.val1 } } #[pyclass(extends=BaseClass)] struct SubClass {} #[pymethods] impl SubClass { #[new] fn new() -> (Self, BaseClass) { (SubClass {}, BaseClass::new()) } fn method<'py>(self_: &Bound<'py, Self>) -> PyResult> { let super_ = self_.py_super()?; super_.call_method("method", (), None) } fn method_super_new<'py>(self_: &Bound<'py, Self>) -> PyResult> { let super_ = PySuper::new(&self_.get_type(), self_)?; super_.call_method("method", (), None) } } #[test] fn test_call_super_method() { Python::with_gil(|py| { let cls = py.get_type::(); pyo3::py_run!( py, cls, r#" obj = cls() assert obj.method() == 10 assert obj.method_super_new() == 10 "# ) }); } pyo3/tests/test_default_impls.rs0000644000175000017500000000155415105742312016700 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::prelude::*; #[path = "../src/tests/common.rs"] mod common; // Test default generated __repr__. #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum TestDefaultRepr { Var, } #[test] fn test_default_slot_exists() { Python::with_gil(|py| { let test_object = Py::new(py, TestDefaultRepr::Var).unwrap(); py_assert!( py, test_object, "repr(test_object) == 'TestDefaultRepr.Var'" ); }) } #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum OverrideSlot { Var, } #[pymethods] impl OverrideSlot { fn __repr__(&self) -> &str { "overridden" } } #[test] fn test_override_slot() { Python::with_gil(|py| { let test_object = Py::new(py, OverrideSlot::Var).unwrap(); py_assert!(py, test_object, "repr(test_object) == 'overridden'"); }) } pyo3/tests/test_getter_setter.rs0000644000175000017500000001570115105742312016727 0ustar bdrungbdrung#![cfg(feature = "macros")] use std::cell::Cell; use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::PyString; use pyo3::types::{IntoPyDict, PyList}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct ClassWithProperties { num: i32, } #[pymethods] impl ClassWithProperties { fn get_num(&self) -> i32 { self.num } #[getter(DATA)] /// a getter for data fn get_data(&self) -> i32 { self.num } #[setter(DATA)] fn set_data(&mut self, value: i32) { self.num = value; } #[getter] /// a getter with a type un-wrapped by PyResult fn get_unwrapped(&self) -> i32 { self.num } #[setter] fn set_unwrapped(&mut self, value: i32) { self.num = value; } #[setter] fn set_from_len(&mut self, #[pyo3(from_py_with = extract_len)] value: i32) { self.num = value; } #[setter] fn set_from_any(&mut self, value: &Bound<'_, PyAny>) -> PyResult<()> { self.num = value.extract()?; Ok(()) } #[getter] fn get_data_list<'py>(&self, py: Python<'py>) -> PyResult> { PyList::new(py, [self.num]) } } fn extract_len(any: &Bound<'_, PyAny>) -> PyResult { any.len().map(|len| len as i32) } #[test] fn class_with_properties() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithProperties { num: 10 }).unwrap(); py_run!(py, inst, "assert inst.get_num() == 10"); py_run!(py, inst, "assert inst.get_num() == inst.DATA"); py_run!(py, inst, "inst.DATA = 20"); py_run!(py, inst, "assert inst.get_num() == 20 == inst.DATA"); py_expect_exception!(py, inst, "del inst.DATA", PyAttributeError); py_run!(py, inst, "assert inst.get_num() == inst.unwrapped == 20"); py_run!(py, inst, "inst.unwrapped = 42"); py_run!(py, inst, "assert inst.get_num() == inst.unwrapped == 42"); py_run!(py, inst, "assert inst.data_list == [42]"); py_run!(py, inst, "inst.from_len = [0, 0, 0]"); py_run!(py, inst, "assert inst.get_num() == 3"); py_run!(py, inst, "inst.from_any = 15"); py_run!(py, inst, "assert inst.get_num() == 15"); let d = [("C", py.get_type::())] .into_py_dict(py) .unwrap(); py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'"); }); } #[pyclass] struct GetterSetter { #[pyo3(get, set)] num: i32, #[pyo3(get, set)] text: String, } #[pymethods] impl GetterSetter { fn get_num2(&self) -> i32 { self.num } } #[test] fn getter_setter_autogen() { Python::with_gil(|py| { let inst = Py::new( py, GetterSetter { num: 10, text: "Hello".to_string(), }, ) .unwrap(); py_run!(py, inst, "assert inst.num == 10"); py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); py_run!( py, inst, "assert inst.text == 'Hello'; inst.text = 'There'; assert inst.text == 'There'" ); }); } #[pyclass] struct RefGetterSetter { num: i32, } #[pymethods] impl RefGetterSetter { #[getter] fn get_num(slf: PyRef<'_, Self>) -> i32 { slf.num } #[setter] fn set_num(mut slf: PyRefMut<'_, Self>, value: i32) { slf.num = value; } } #[test] fn ref_getter_setter() { // Regression test for #837 Python::with_gil(|py| { let inst = Py::new(py, RefGetterSetter { num: 10 }).unwrap(); py_run!(py, inst, "assert inst.num == 10"); py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } #[pyclass] struct TupleClassGetterSetter(i32); #[pymethods] impl TupleClassGetterSetter { #[getter(num)] fn get_num(&self) -> i32 { self.0 } #[setter(num)] fn set_num(&mut self, value: i32) { self.0 = value; } } #[test] fn tuple_struct_getter_setter() { Python::with_gil(|py| { let inst = Py::new(py, TupleClassGetterSetter(10)).unwrap(); py_assert!(py, inst, "inst.num == 10"); py_run!(py, inst, "inst.num = 20"); py_assert!(py, inst, "inst.num == 20"); }); } #[pyclass(get_all, set_all)] struct All { num: i32, } #[test] fn get_set_all() { Python::with_gil(|py| { let inst = Py::new(py, All { num: 10 }).unwrap(); py_run!(py, inst, "assert inst.num == 10"); py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } #[pyclass(get_all)] struct All2 { #[pyo3(set)] num: i32, } #[test] fn get_all_and_set() { Python::with_gil(|py| { let inst = Py::new(py, All2 { num: 10 }).unwrap(); py_run!(py, inst, "assert inst.num == 10"); py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } #[pyclass(unsendable)] struct CellGetterSetter { #[pyo3(get, set)] cell_inner: Cell, } #[test] fn cell_getter_setter() { let c = CellGetterSetter { cell_inner: Cell::new(10), }; Python::with_gil(|py| { let inst = Py::new(py, c).unwrap(); let cell = Cell::new(20i32).into_pyobject(py).unwrap(); py_run!(py, cell, "assert cell == 20"); py_run!(py, inst, "assert inst.cell_inner == 10"); py_run!( py, inst, "inst.cell_inner = 20; assert inst.cell_inner == 20" ); }); } #[test] fn borrowed_value_with_lifetime_of_self() { #[pyclass] struct BorrowedValue {} #[pymethods] impl BorrowedValue { #[getter] fn value(&self) -> &str { "value" } } Python::with_gil(|py| { let inst = Py::new(py, BorrowedValue {}).unwrap(); py_run!(py, inst, "assert inst.value == 'value'"); }); } #[test] fn frozen_py_field_get() { #[pyclass(frozen)] struct FrozenPyField { #[pyo3(get)] value: Py, } Python::with_gil(|py| { let inst = Py::new( py, FrozenPyField { value: "value".into_pyobject(py).unwrap().unbind(), }, ) .unwrap(); py_run!(py, inst, "assert inst.value == 'value'"); }); } #[test] fn test_optional_setter() { #[pyclass] struct SimpleClass { field: Option, } #[pymethods] impl SimpleClass { #[getter] fn get_field(&self) -> Option { self.field } #[setter] fn set_field(&mut self, field: Option) { self.field = field; } } Python::with_gil(|py| { let instance = Py::new(py, SimpleClass { field: None }).unwrap(); py_run!(py, instance, "assert instance.field is None"); py_run!( py, instance, "instance.field = 42; assert instance.field == 42" ); py_run!( py, instance, "instance.field = None; assert instance.field is None" ); }) } pyo3/tests/test_frompy_intopy_roundtrip.rs0000644000175000017500000002062415105742312021073 0ustar bdrungbdrung#![cfg(feature = "macros")] use pyo3::types::{PyDict, PyString}; use pyo3::{prelude::*, IntoPyObject, IntoPyObjectExt, IntoPyObjectRef}; use std::collections::HashMap; use std::hash::Hash; #[macro_use] #[path = "../src/tests/common.rs"] mod common; #[derive(Debug, Clone, IntoPyObject, IntoPyObjectRef, FromPyObject)] pub struct A<'py> { #[pyo3(item)] s: String, #[pyo3(item)] t: Bound<'py, PyString>, #[pyo3(item("foo"))] p: Bound<'py, PyAny>, } #[test] fn test_named_fields_struct() { Python::with_gil(|py| { let a = A { s: "Hello".into(), t: PyString::new(py, "World"), p: 42i32.into_pyobject(py).unwrap().into_any(), }; let pya = (&a).into_pyobject(py).unwrap(); let new_a = pya.extract::>().unwrap(); assert_eq!(a.s, new_a.s); assert_eq!(a.t.to_cow().unwrap(), new_a.t.to_cow().unwrap()); assert_eq!( a.p.extract::().unwrap(), new_a.p.extract::().unwrap() ); let pya = a.clone().into_pyobject(py).unwrap(); let new_a = pya.extract::>().unwrap(); assert_eq!(a.s, new_a.s); assert_eq!(a.t.to_cow().unwrap(), new_a.t.to_cow().unwrap()); assert_eq!( a.p.extract::().unwrap(), new_a.p.extract::().unwrap() ); }); } #[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)] #[pyo3(transparent)] pub struct B { test: String, } #[test] fn test_transparent_named_field_struct() { Python::with_gil(|py| { let b = B { test: "test".into(), }; let pyb = (&b).into_pyobject(py).unwrap(); let new_b = pyb.extract::().unwrap(); assert_eq!(b, new_b); let pyb = b.clone().into_pyobject(py).unwrap(); let new_b = pyb.extract::().unwrap(); assert_eq!(b, new_b); }); } #[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)] #[pyo3(transparent)] pub struct D { test: T, } #[test] fn test_generic_transparent_named_field_struct() { Python::with_gil(|py| { let d = D { test: String::from("test"), }; let pyd = (&d).into_pyobject(py).unwrap(); let new_d = pyd.extract::>().unwrap(); assert_eq!(d, new_d); let d = D { test: 1usize }; let pyd = (&d).into_pyobject(py).unwrap(); let new_d = pyd.extract::>().unwrap(); assert_eq!(d, new_d); let d = D { test: String::from("test"), }; let pyd = d.clone().into_pyobject(py).unwrap(); let new_d = pyd.extract::>().unwrap(); assert_eq!(d, new_d); let d = D { test: 1usize }; let pyd = d.clone().into_pyobject(py).unwrap(); let new_d = pyd.extract::>().unwrap(); assert_eq!(d, new_d); }); } #[derive(Debug, IntoPyObject, IntoPyObjectRef, FromPyObject)] pub struct GenericWithBound(HashMap); #[test] fn test_generic_with_bound() { Python::with_gil(|py| { let mut hash_map = HashMap::::new(); hash_map.insert("1".into(), 1); hash_map.insert("2".into(), 2); let map = GenericWithBound(hash_map); let py_map = (&map).into_pyobject(py).unwrap(); assert_eq!(py_map.len(), 2); assert_eq!( py_map .get_item("1") .unwrap() .unwrap() .extract::() .unwrap(), 1 ); assert_eq!( py_map .get_item("2") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); assert!(py_map.get_item("3").unwrap().is_none()); let py_map = map.into_pyobject(py).unwrap(); assert_eq!(py_map.len(), 2); assert_eq!( py_map .get_item("1") .unwrap() .unwrap() .extract::() .unwrap(), 1 ); assert_eq!( py_map .get_item("2") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); assert!(py_map.get_item("3").unwrap().is_none()); }); } #[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)] pub struct Tuple(String, usize); #[test] fn test_tuple_struct() { Python::with_gil(|py| { let tup = Tuple(String::from("test"), 1); let tuple = (&tup).into_pyobject(py).unwrap(); let new_tup = tuple.extract::().unwrap(); assert_eq!(tup, new_tup); let tuple = tup.clone().into_pyobject(py).unwrap(); let new_tup = tuple.extract::().unwrap(); assert_eq!(tup, new_tup); }); } #[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)] pub struct TransparentTuple(String); #[test] fn test_transparent_tuple_struct() { Python::with_gil(|py| { let tup = TransparentTuple(String::from("test")); let tuple = (&tup).into_pyobject(py).unwrap(); let new_tup = tuple.extract::().unwrap(); assert_eq!(tup, new_tup); let tuple = tup.clone().into_pyobject(py).unwrap(); let new_tup = tuple.extract::().unwrap(); assert_eq!(tup, new_tup); }); } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct IntWrapper(u32); fn int_wrapper_into_py<'py>( v: std::borrow::Cow<'_, IntWrapper>, py: Python<'py>, ) -> PyResult> { v.0.into_bound_py_any(py) } fn int_wrapper_from_py(v: &Bound<'_, PyAny>) -> PyResult { v.extract().map(IntWrapper) } #[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)] pub enum Foo { TupleVar(usize, String), StructVar { #[pyo3(item)] test: char, #[pyo3(item, into_py_with=int_wrapper_into_py, from_py_with=int_wrapper_from_py)] int: IntWrapper, }, #[pyo3(transparent)] TransparentTuple(usize), #[pyo3(transparent)] TransparentStructVar { a: Option, }, #[pyo3(rename_all = "camelCase", from_item_all)] RenameAll { long_field_name: [u16; 2], other_field: Option, }, } #[test] fn test_enum() { Python::with_gil(|py| { let tuple_var = Foo::TupleVar(1, "test".into()); let foo = (&tuple_var).into_pyobject(py).unwrap(); assert_eq!(tuple_var, foo.extract::().unwrap()); let foo = tuple_var.clone().into_pyobject(py).unwrap(); assert_eq!(tuple_var, foo.extract::().unwrap()); let struct_var = Foo::StructVar { test: 'b', int: IntWrapper(42), }; let foo = (&struct_var) .into_pyobject(py) .unwrap() .downcast_into::() .unwrap(); assert_eq!(struct_var, foo.extract::().unwrap()); let foo = struct_var .clone() .into_pyobject(py) .unwrap() .downcast_into::() .unwrap(); assert_eq!(struct_var, foo.extract::().unwrap()); let transparent_tuple = Foo::TransparentTuple(1); let foo = (&transparent_tuple).into_pyobject(py).unwrap(); assert_eq!(transparent_tuple, foo.extract::().unwrap()); let foo = transparent_tuple.clone().into_pyobject(py).unwrap(); assert_eq!(transparent_tuple, foo.extract::().unwrap()); let transparent_struct_var = Foo::TransparentStructVar { a: None }; let foo = (&transparent_struct_var).into_pyobject(py).unwrap(); assert_eq!(transparent_struct_var, foo.extract::().unwrap()); let foo = transparent_struct_var.clone().into_pyobject(py).unwrap(); assert_eq!(transparent_struct_var, foo.extract::().unwrap()); let rename_all_struct_var = Foo::RenameAll { long_field_name: [1, 2], other_field: None, }; let foo = (&rename_all_struct_var).into_pyobject(py).unwrap(); assert_eq!(rename_all_struct_var, foo.extract::().unwrap()); let foo = rename_all_struct_var.clone().into_pyobject(py).unwrap(); assert_eq!(rename_all_struct_var, foo.extract::().unwrap()); }); } pyo3/tests/test_pyerr_debug_unformattable.rs0000644000175000017500000000417515105742312021304 0ustar bdrungbdrunguse pyo3::ffi; use pyo3::prelude::*; // This test mucks around with sys.modules, so run it separately to prevent it // from potentially corrupting the state of the python interpreter used in other // tests. #[test] fn err_debug_unformattable() { // Debug representation should be like the following (without the newlines): // PyErr { // type: , // value: Exception('banana'), // traceback: Some(\">\") // } Python::with_gil(|py| { // PyTracebackMethods::format uses io.StringIO. Mock it out to trigger a // formatting failure: // TypeError: 'Mock' object cannot be converted to 'PyString' let err = py .run( ffi::c_str!( r#" import io, sys, unittest.mock sys.modules['orig_io'] = sys.modules['io'] sys.modules['io'] = unittest.mock.Mock() raise Exception('banana')"# ), None, None, ) .expect_err("raising should have given us an error"); let debug_str = format!("{err:?}"); assert!(debug_str.starts_with("PyErr { ")); assert!(debug_str.ends_with(" }")); // Strip "PyErr { " and " }". Split into 3 substrings to separate type, // value, and traceback while not splitting the string within traceback. let mut fields = debug_str["PyErr { ".len()..debug_str.len() - 2].splitn(3, ", "); assert_eq!(fields.next().unwrap(), "type: "); assert_eq!(fields.next().unwrap(), "value: Exception('banana')"); let traceback = fields.next().unwrap(); assert!( traceback.starts_with("traceback: Some(\"(); let var = Py::new(py, MyEnum::Variant).unwrap(); py_assert!(py, my_enum var, "my_enum.Variant == var"); }) } #[test] fn test_enum_eq_enum() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); let var2 = Py::new(py, MyEnum::Variant).unwrap(); let other_var = Py::new(py, MyEnum::OtherVariant).unwrap(); py_assert!(py, var1 var2, "var1 == var2"); py_assert!(py, var1 other_var, "var1 != other_var"); py_assert!(py, var1 var2, "(var1 != var2) == False"); }) } #[test] fn test_enum_eq_incomparable() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); py_assert!(py, var1, "(var1 == 'foo') == False"); py_assert!(py, var1, "(var1 != 'foo') == True"); }) } #[pyfunction] fn return_enum() -> MyEnum { MyEnum::Variant } #[test] fn test_return_enum() { Python::with_gil(|py| { let f = wrap_pyfunction!(return_enum)(py).unwrap(); let mynum = py.get_type::(); py_run!(py, f mynum, "assert f() == mynum.Variant") }); } #[pyfunction] fn enum_arg(e: MyEnum) { assert_eq!(MyEnum::OtherVariant, e) } #[test] fn test_enum_arg() { Python::with_gil(|py| { let f = wrap_pyfunction!(enum_arg)(py).unwrap(); let mynum = py.get_type::(); py_run!(py, f mynum, "f(mynum.OtherVariant)") }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] enum CustomDiscriminant { One = 1, Two = 2, } #[test] fn test_custom_discriminant() { Python::with_gil(|py| { #[allow(non_snake_case)] let CustomDiscriminant = py.get_type::(); let one = Py::new(py, CustomDiscriminant::One).unwrap(); let two = Py::new(py, CustomDiscriminant::Two).unwrap(); py_run!(py, CustomDiscriminant one two, r#" assert CustomDiscriminant.One == one assert CustomDiscriminant.Two == two assert CustomDiscriminant.One == 1 assert CustomDiscriminant.Two == 2 assert one != two assert CustomDiscriminant.One != 2 assert CustomDiscriminant.Two != 1 "#); }) } #[test] fn test_enum_to_int() { Python::with_gil(|py| { let one = Py::new(py, CustomDiscriminant::One).unwrap(); py_assert!(py, one, "int(one) == 1"); let v = Py::new(py, MyEnum::Variant).unwrap(); let v_value = MyEnum::Variant as isize; py_run!(py, v v_value, "int(v) == v_value"); }) } #[test] fn test_enum_compare_int() { Python::with_gil(|py| { let one = Py::new(py, CustomDiscriminant::One).unwrap(); py_run!( py, one, r#" assert one == 1 assert 1 == one assert one != 2 "# ) }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] #[repr(u8)] enum SmallEnum { V = 1, } #[test] fn test_enum_compare_int_no_throw_when_overflow() { Python::with_gil(|py| { let v = Py::new(py, SmallEnum::V).unwrap(); py_assert!(py, v, "v != 1<<30") }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] #[repr(usize)] #[allow(clippy::enum_clike_unportable_variant)] enum BigEnum { V = usize::MAX, } #[test] fn test_big_enum_no_overflow() { Python::with_gil(|py| { let usize_max = usize::MAX; let v = Py::new(py, BigEnum::V).unwrap(); py_assert!(py, usize_max v, "v == usize_max"); py_assert!(py, usize_max v, "int(v) == usize_max"); }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] #[repr(u16, align(8))] enum TestReprParse { V, } #[test] fn test_repr_parse() { assert_eq!(std::mem::align_of::(), 8); } #[pyclass(eq, eq_int, name = "MyEnum")] #[derive(Debug, PartialEq, Eq, Clone)] pub enum RenameEnum { Variant, } #[test] fn test_rename_enum_repr_correct() { Python::with_gil(|py| { let var1 = Py::new(py, RenameEnum::Variant).unwrap(); py_assert!(py, var1, "repr(var1) == 'MyEnum.Variant'"); }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] pub enum RenameVariantEnum { #[pyo3(name = "VARIANT")] Variant, } #[test] fn test_rename_variant_repr_correct() { Python::with_gil(|py| { let var1 = Py::new(py, RenameVariantEnum::Variant).unwrap(); py_assert!(py, var1, "repr(var1) == 'RenameVariantEnum.VARIANT'"); }) } #[pyclass(eq, eq_int, rename_all = "SCREAMING_SNAKE_CASE")] #[derive(Debug, PartialEq, Eq, Clone)] #[allow(clippy::enum_variant_names)] enum RenameAllVariantsEnum { VariantOne, VariantTwo, #[pyo3(name = "VariantThree")] VariantFour, } #[test] fn test_renaming_all_enum_variants() { Python::with_gil(|py| { let enum_obj = py.get_type::(); py_assert!(py, enum_obj, "enum_obj.VARIANT_ONE == enum_obj.VARIANT_ONE"); py_assert!(py, enum_obj, "enum_obj.VARIANT_TWO == enum_obj.VARIANT_TWO"); py_assert!( py, enum_obj, "enum_obj.VariantThree == enum_obj.VariantThree" ); }); } #[pyclass(module = "custom_module")] #[derive(Debug)] enum CustomModuleComplexEnum { Variant(), Py(Py), } #[test] fn test_custom_module() { Python::with_gil(|py| { let enum_obj = py.get_type::(); py_assert!( py, enum_obj, "enum_obj.Variant.__module__ == 'custom_module'" ); }); } #[pyclass(eq)] #[derive(Debug, Clone, PartialEq)] pub enum EqOnly { VariantA, VariantB, } #[test] fn test_simple_enum_eq_only() { Python::with_gil(|py| { let var1 = Py::new(py, EqOnly::VariantA).unwrap(); let var2 = Py::new(py, EqOnly::VariantA).unwrap(); let var3 = Py::new(py, EqOnly::VariantB).unwrap(); py_assert!(py, var1 var2, "var1 == var2"); py_assert!(py, var1 var3, "var1 != var3"); }) } #[pyclass(frozen, eq, eq_int, hash)] #[derive(PartialEq, Hash)] enum SimpleEnumWithHash { A, B, } #[test] fn test_simple_enum_with_hash() { Python::with_gil(|py| { use pyo3::types::IntoPyDict; let class = SimpleEnumWithHash::A; let hash = { use std::hash::{Hash, Hasher}; let mut hasher = std::collections::hash_map::DefaultHasher::new(); class.hash(&mut hasher); hasher.finish() as isize }; let env = [ ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_pyobject(py).unwrap().into_any().unbind()), ] .into_py_dict(py) .unwrap(); py_assert!(py, *env, "hash(obj) == hsh"); }); } #[pyclass(eq, hash)] #[derive(PartialEq, Hash)] enum ComplexEnumWithHash { A(u32), B { msg: String }, } #[test] fn test_complex_enum_with_hash() { Python::with_gil(|py| { use pyo3::types::IntoPyDict; let class = ComplexEnumWithHash::B { msg: String::from("Hello"), }; let hash = { use std::hash::{Hash, Hasher}; let mut hasher = std::collections::hash_map::DefaultHasher::new(); class.hash(&mut hasher); hasher.finish() as isize }; let env = [ ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_pyobject(py).unwrap().into_any().unbind()), ] .into_py_dict(py) .unwrap(); py_assert!(py, *env, "hash(obj) == hsh"); }); } #[test] fn custom_eq() { #[pyclass(frozen)] #[derive(PartialEq)] pub enum CustomPyEq { A, B, } #[pymethods] impl CustomPyEq { fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool { if let Ok(rhs) = other.downcast::() { rhs.to_cow().map_or(false, |rhs| self.__str__() == rhs) } else if let Ok(rhs) = other.downcast::() { self == rhs.get() } else { false } } fn __str__(&self) -> String { match self { CustomPyEq::A => "A".to_string(), CustomPyEq::B => "B".to_string(), } } } Python::with_gil(|py| { let a = Bound::new(py, CustomPyEq::A).unwrap(); let b = Bound::new(py, CustomPyEq::B).unwrap(); assert!(a.as_any().eq(&a).unwrap()); assert!(a.as_any().eq("A").unwrap()); assert!(a.as_any().ne(&b).unwrap()); assert!(a.as_any().ne("B").unwrap()); assert!(b.as_any().eq(&b).unwrap()); assert!(b.as_any().eq("B").unwrap()); assert!(b.as_any().ne(&a).unwrap()); assert!(b.as_any().ne("A").unwrap()); }) } #[pyclass] #[derive(Clone, Copy)] pub enum ComplexEnumWithRaw { Raw { r#type: i32 }, } // Cover simple field lookups with raw identifiers #[test] fn complex_enum_with_raw() { Python::with_gil(|py| { let complex = ComplexEnumWithRaw::Raw { r#type: 314159 }; py_assert!(py, complex, "complex.type == 314159"); }); } // Cover pattern matching with raw identifiers #[test] #[cfg(Py_3_10)] fn complex_enum_with_raw_pattern_match() { Python::with_gil(|py| { let complex = ComplexEnumWithRaw::Raw { r#type: 314159 }; let cls = py.get_type::(); // Cover destructuring by pattern matching py_run!(py, cls complex, r#" match complex: case cls.Raw(type=ty): assert ty == 314159 case _: assert False, "no matching variant found" "#); }); } pyo3/Releasing.md0000644000175000017500000000661215105742312013534 0ustar bdrungbdrung# Releasing This is notes for the current process of releasing a new PyO3 version. Replace `` in all instructions below with the new version. ## 1. Prepare the release commit Follow the process below to update all required pieces to bump the version. All these changes are done in a single commit because it makes it clear to git readers what happened to bump the version. It also makes it easy to cherry-pick the version bump onto the `main` branch when tidying up branch history at the end of the release process. 1. Replace all instances of the PyO3 current version and the with the new version to be released. Places to check: - `Cargo.toml` for all PyO3 crates in the repository. - Examples in `README.md` - PyO3 version embedded into documentation like the README. - `pre-script.rhai` templates for the examples. - `[towncrier]` section in `pyproject.toml`. Some of the above locations may already have the new version with a `-dev` suffix, which needs to be removed. **Make sure not to modify the CHANGELOG during this step!** 2. Run `towncrier build` to generate the CHANGELOG. The version used by `towncrier` should automatically be correct because of the update to `pyproject.toml` in step 1. 3. Manually edit the CHANGELOG for final notes. Steps to do: - Adjust wording of any release lines to make them clearer for users / fix typos. - Add a new link at the bottom for the new version, and update the `Unreleased` link. 4. Create the commit containing all the above changes, with a message of `release: `. Push to `release-` branch on the main PyO3 repository, where `` depends on whether this is a major or minor release: - for O.X.0 minor releases, just use `0.X`, e.g. `release-0.17`. This will become the maintenance branch after release. - for 0.X.Y patch releases, use the full `0.X.Y`, e.g. `release-0.17.1`. This will be deleted after merge. ## 2. Create the release PR and draft release notes Open a PR for the branch, and confirm that it passes CI. For `0.X.0` minor releases, the PR should be merging into `main`, for `0.X.Y` patch releases, the PR should be merging the `release-0.X` maintenance branch. On https://github.com/PyO3/pyo3/releases, click "Draft a new release". The tag will be a new tag of `v` (note preceding `v`) and target should be the `release-` branch you just pushed. Write release notes which match the style of previous releases. You can get the list of contributors by running `nox -s contributors -- v release-` to get contributors from the previous version tag through to the branch tip you just pushed. (This uses the GitHub API, so you'll need to push the branch first.) Save as a draft and wait for now. ## 3. Leave for a cooling off period Wait a couple of days in case anyone wants to hold up the release to add bugfixes etc. ## 4. Put live To put live: - 1. merge the release PR - 2. publish a release on GitHub targeting the release branch CI will automatically push to `crates.io`. ## 5. Tidy the main branch If the release PR targeted a branch other than main, you will need to cherry-pick the version bumps, CHANGELOG modifications and removal of towncrier `newsfragments` and open another PR to land these on main. ## 6. Delete the release branch (patch releases only) For 0.X.Y patch releases, the release branch is no longer needed, so it should be deleted. pyo3/Contributing.md0000644000175000017500000003173315105742312014274 0ustar bdrungbdrung# Contributing Thank you for your interest in contributing to PyO3! All are welcome - please consider reading our [Code of Conduct](https://github.com/PyO3/pyo3/blob/main/Code-of-Conduct.md) to keep our community positive and inclusive. If you are searching for ideas how to contribute, proceed to the ["Getting started contributing"](#getting-started-contributing) section. If you have found a specific issue to contribute to and need information about the development process, you may find the section ["Writing pull requests"](#writing-pull-requests) helpful. If you want to become familiar with the codebase, see [Architecture.md](https://github.com/PyO3/pyo3/blob/main/Architecture.md). ## Getting started contributing Please join in with any part of PyO3 which interests you. We use GitHub issues to record all bugs and ideas. Feel free to request an issue to be assigned to you if you want to work on it. You can browse the API of the non-public parts of PyO3 [here](https://pyo3.netlify.app/internal/doc/pyo3/index.html). The following sections also contain specific ideas on where to start contributing to PyO3. ## Setting up a development environment To work and develop PyO3, you need Python & Rust installed on your system. * We encourage the use of [rustup](https://rustup.rs/) to be able to select and choose specific toolchains based on the project. * [Pyenv](https://github.com/pyenv/pyenv) is also highly recommended for being able to choose a specific Python version. * [virtualenv](https://virtualenv.pypa.io/en/latest/) can also be used with or without Pyenv to use specific installed Python versions. * [`nox`][nox] is used to automate many of our CI tasks. ### Help users identify bugs The [PyO3 Discord server](https://discord.gg/33kcChzH7f) is very active with users who are new to PyO3, and often completely new to Rust. Helping them debug is a great way to get experience with the PyO3 codebase. Helping others often reveals bugs, documentation weaknesses, and missing APIs. It's a good idea to open GitHub issues for these immediately so the resolution can be designed and implemented! ### Implement issues ready for development Issues where the solution is clear and work is not in progress use the [needs-implementer](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-implementer) label. Don't be afraid if the solution is not clear to you! The core PyO3 contributors will be happy to mentor you through any questions you have to help you write the solution. ### Help write great docs PyO3 has a user guide (using mdbook) as well as the usual Rust API docs. The aim is for both of these to be detailed, easy to understand, and up-to-date. Pull requests are always welcome to fix typos, change wording, add examples, etc. There are some specific areas of focus where help is currently needed for the documentation: - Issues requesting documentation improvements are tracked with the [documentation](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Adocumentation) label. - Not all APIs had docs or examples when they were made. The goal is to have documentation on all PyO3 APIs ([#306](https://github.com/PyO3/pyo3/issues/306)). If you see an API lacking a doc, please write one and open a PR! To build the docs (including all features), install [`nox`][nox] and then run ```shell nox -s docs -- open ``` #### Doctests We use lots of code blocks in our docs. Run `cargo test --doc` when making changes to check that the doctests still work, or `cargo test` to run all the Rust tests including doctests. See https://doc.rust-lang.org/rustdoc/documentation-tests.html for a guide on doctests. #### Building the guide You can preview the user guide by building it locally with `mdbook`. First, install [`mdbook`][mdbook], the [`mdbook-tabs`][mdbook-tabs] plugin and [`nox`][nox]. Then, run ```shell nox -s build-guide -- --open ``` To check all links in the guide are valid, also install [`lychee`][lychee] and use the `check-guide` session instead: ```shell nox -s check-guide ``` ### Help design the next PyO3 Issues which don't yet have a clear solution use the [needs-design](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-design) label. If any of these issues interest you, please join in with the conversation on the issue! All opinions are valued, and if you're interested in going further with e.g. draft PRs to experiment with API designs, even better! ### Review pull requests Everybody is welcome to submit comments on open PRs. Please help ensure new PyO3 APIs are safe, performant, tidy, and easy to use! ## Writing pull requests Here are a few things to note when you are writing PRs. ### Testing and Continuous Integration The PyO3 repo uses GitHub Actions. PRs are blocked from merging if CI is not successful. Formatting, linting and tests are checked for all Rust and Python code. In addition, all warnings in Rust code are disallowed (using `RUSTFLAGS="-D warnings"`). Tests run with all supported Python versions with the latest stable Rust compiler, as well as for Python 3.9 with the minimum supported Rust version. If you are adding a new feature, you should add it to the `full` feature in our *Cargo.toml** so that it is tested in CI. You can run these checks yourself with `nox`. Use `nox -l` to list the full set of subcommands you can run. #### Linting Python code `nox -s ruff` #### Linting Rust code `nox -s rustfmt` #### Semver checks `cargo semver-checks check-release` #### Clippy `nox -s clippy-all` #### Tests `nox -s test` or `cargo test` for Rust tests only, `nox -f pytests/noxfile.py -s test` for Python tests only #### Check all conditional compilation `nox -s check-feature-powerset` #### UI Tests PyO3 uses [`trybuild`](https://github.com/dtolnay/trybuild) to develop UI tests to capture error messages from the Rust compiler for some of the macro functionality. Because there are several feature combinations for these UI tests, when updating them all (e.g. for a new Rust compiler version) it may be helpful to use the `update-ui-tests` nox session: ```bash nox -s update-ui-tests ``` ### Documenting changes We use [towncrier](https://towncrier.readthedocs.io/en/stable/index.html) to generate a CHANGELOG for each release. To include your changes in the release notes, you should create one (or more) news items in the `newsfragments` directory. Valid news items should be saved as `..md` where `` is the pull request number and `` is one of the following: - `packaging` - for dependency changes and Python / Rust version compatibility changes - `added` - for new features - `changed` - for features which already existed but have been altered or deprecated - `removed` - for features which have been removed - `fixed` - for "changed" features which were classed as a bugfix Docs-only PRs do not need news items; start your PR title with `docs:` to skip the check. ### Style guide #### Generic code PyO3 has a lot of generic APIs to increase usability. These can come at the cost of generic code bloat. Where reasonable, try to implement a concrete sub-portion of generic functions. There are two forms of this: - If the concrete sub-portion doesn't benefit from re-use by other functions, name it `inner` and keep it as a local to the function. - If the concrete sub-portion is re-used by other functions, preferably name it `_foo` and place it directly below `foo` in the source code (where `foo` is the original generic function). #### FFI calls PyO3 makes a lot of FFI calls to Python's C API using raw pointers. Where possible try to avoid using pointers-to-temporaries in expressions: ```rust // dangerous pyo3::ffi::Something(name.to_object(py).as_ptr()); // because the following refactoring is a use-after-free error: let name = name.to_object(py).as_ptr(); pyo3::ffi::Something(name) ``` Instead, prefer to bind the safe owned `PyObject` wrapper before passing to ffi functions: ```rust let name: PyObject = name.to_object(py); pyo3::ffi::Something(name.as_ptr()) // name will automatically be freed when it falls out of scope ``` ## Python and Rust version support policy PyO3 aims to keep sufficient compatibility to make packaging Python extensions built with PyO3 feasible on most common package managers. To keep package maintainers' lives simpler, PyO3 will commit, wherever possible, to only adjust minimum supported Rust and Python versions at the same time. This bump will only come in an `0.x` release, roughly once per year, after the oldest supported Python version reaches its end-of-life. (Check https://endoflife.date/python for a clear timetable on these.) Below are guidelines on what compatibility all PRs are expected to deliver for each language. ### Python PyO3 supports all officially supported Python versions, as well as the latest PyPy3 release. All of these versions are tested in CI. #### Adding support for new CPython versions If you plan to add support for a pre-release version of CPython, here's a (non-exhaustive) checklist: - [ ] Wait until the last alpha release (usually alpha7), since ABI is not guranteed until the first beta release - [ ] Add prelease_ver-dev (e.g. `3.14-dev`) to `‎.github/workflows/ci.yml`, and bump version in `noxfile.py`, `pyo3-ffi/Cargo.toml` under `max-version` within `[package.metadata.cpython]`, and `max` within `pyo3-ffi/build.rs` - [ ] Add a new abi3-prerelease feature for the version (e.g. `abi3-py314`) - In `pyo3-build-config/Cargo.toml`, set abi3-most_current_stable to ["abi3-prerelease"] and abi3-prerelease to ["abi3"] - In `pyo3-ffi/Cargo.toml`, set abi3-most_current_stable to ["abi3-prerelease", "pyo3-build-config/abi3-most_current_stable"] and abi3-prerelease to ["abi3", "pyo3-build-config/abi3-prerelease"] - In `Cargo.toml`, set abi3-most_current_stable to ["abi3-prerelease", "pyo3-ffi/abi3-most_current_stable"] and abi3-prerelease to ["abi3", "pyo3-ffi/abi3-prerelease"] - [ ] Use `#[cfg(Py_prerelease])` (e.g. `#[cfg(Py_3_14)]`) and `#[cfg(not(Py_prerelease]))` to indicate changes between the stable branches of CPython and the pre-release - [ ] Do not add a Rust binding to any function, struct, or global variable prefixed with `_` in CPython's headers - [ ] Ping @ngoldbaum and @davidhewitt for assistance ### Rust PyO3 aims to make use of up-to-date Rust language features to keep the implementation as efficient as possible. The minimum Rust version supported will be decided when the release which bumps Python and Rust versions is made. At the time, the minimum Rust version will be set no higher than the lowest Rust version shipped in the current Debian, RHEL and Alpine Linux distributions. CI tests both the most recent stable Rust version and the minimum supported Rust version. Because of Rust's stability guarantees this is sufficient to confirm support for all Rust versions in between. ## Benchmarking PyO3 has two sets of benchmarks for evaluating some aspects of its performance. The benchmark suite is currently very small - please open PRs with new benchmarks if you're interested in helping to expand it! First, there are Rust-based benchmarks located in the `pyo3-benches` subdirectory. You can run these benchmarks with: nox -s bench Second, there is a Python-based benchmark contained in the `pytests` subdirectory. You can read more about it [here](https://github.com/PyO3/pyo3/tree/main/pytests). ## Code coverage You can view what code is and isn't covered by PyO3's tests. We aim to have 100% coverage - please check coverage and add tests if you notice a lack of coverage! - First, ensure the llvm-cov cargo plugin is installed. You may need to run the plugin through cargo once before using it with `nox`. ```shell cargo install cargo-llvm-cov cargo llvm-cov ``` - Then, generate an `lcov.info` file with ```shell nox -s coverage -- lcov ``` You can install an IDE plugin to view the coverage. For example, if you use VSCode: - Add the [coverage-gutters](https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters) plugin. - Add these settings to VSCode's `settings.json`: ```json { "coverage-gutters.coverageFileNames": [ "lcov.info", "cov.xml", "coverage.xml", ], "coverage-gutters.showLineCoverage": true } ``` - You should now be able to see green highlights for code that is tested, and red highlights for code that is not tested. ## Sponsor this project At the moment there is no official organisation that accepts sponsorship on PyO3's behalf. If you're seeking to provide significant funding to the PyO3 ecosystem, please reach out to us on [GitHub](https://github.com/PyO3/pyo3/issues/new) or [Discord](https://discord.gg/33kcChzH7f) and we can discuss. In the meanwhile, some of our maintainers have personal GitHub sponsorship pages and would be grateful for your support: - [davidhewitt](https://github.com/sponsors/davidhewitt) - [messense](https://github.com/sponsors/messense) [mdbook]: https://rust-lang.github.io/mdBook/cli/index.html [mdbook-tabs]: https://mdbook-plugins.rustforweb.org/tabs.html [lychee]: https://github.com/lycheeverse/lychee [nox]: https://github.com/theacodes/nox pyo3/LICENSE-MIT0000644000175000017500000000212315105742312012726 0ustar bdrungbdrungCopyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3/Cargo.lock0000644000175000017500000011146215105742312013206 0ustar bdrungbdrung# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android-tzdata" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] [[package]] name = "anyhow" version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "assert_approx_eq" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c07dab4369547dbe5114677b33fbbf724971019f3818172d59a97a61c774ffd" [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bigdecimal" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a22f228ab7a1b23027ccc6c350b72868017af7ea8356fbdf19f8d991c690013" dependencies = [ "autocfg", "libm", "num-bigint", "num-integer", "num-traits", ] [[package]] name = "bitflags" version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bumpalo" version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "cc" version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "shlex", ] [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "chrono" version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", "windows-link", ] [[package]] name = "chrono-tz" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3" dependencies = [ "chrono", "chrono-tz-build", "phf", ] [[package]] name = "chrono-tz-build" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402" dependencies = [ "parse-zoneinfo", "phf_codegen", ] [[package]] name = "core-foundation-sys" version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "crossbeam-deque" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "deranged" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", ] [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", "windows-sys", ] [[package]] name = "eyre" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", ] [[package]] name = "fastrand" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "futures" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", "futures-executor", "futures-io", "futures-sink", "futures-task", "futures-util", ] [[package]] name = "futures-channel" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", ] [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", "futures-util", ] [[package]] name = "futures-io" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "futures-sink" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", "futures-io", "futures-macro", "futures-sink", "futures-task", "memchr", "pin-project-lite", "pin-utils", "slab", ] [[package]] name = "getrandom" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", "r-efi", "wasi", ] [[package]] name = "glob" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", "equivalent", "foldhash", ] [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "iana-time-zone" version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "log", "wasm-bindgen", "windows-core", ] [[package]] name = "iana-time-zone-haiku" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ "cc", ] [[package]] name = "indenter" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown", ] [[package]] name = "indoc" version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" [[package]] name = "inventory" version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83" dependencies = [ "rustversion", ] [[package]] name = "itoa" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" dependencies = [ "jiff-static", "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", "serde", "windows-sys", ] [[package]] name = "jiff-static" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "jiff-tzdb" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524" [[package]] name = "jiff-tzdb-platform" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" dependencies = [ "jiff-tzdb", ] [[package]] name = "js-sys" version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libm" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "linux-raw-sys" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "lock_api" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", ] [[package]] name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memoffset" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] [[package]] name = "num-bigint" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", ] [[package]] name = "num-complex" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ "num-traits", ] [[package]] name = "num-rational" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ "num-bigint", "num-integer", "num-traits", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "ordered-float" version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" dependencies = [ "num-traits", ] [[package]] name = "parking_lot" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-targets", ] [[package]] name = "parse-zoneinfo" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" dependencies = [ "regex", ] [[package]] name = "phf" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_codegen" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", "phf_shared", ] [[package]] name = "phf_generator" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand 0.8.5", ] [[package]] name = "phf_shared" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "portable-atomic" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" dependencies = [ "portable-atomic", ] [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] [[package]] name = "proc-macro2" version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" dependencies = [ "bitflags", "lazy_static", "num-traits", "rand 0.9.1", "rand_chacha", "rand_xorshift", "regex-syntax", "unarray", ] [[package]] name = "pyo3" version = "0.25.1" dependencies = [ "anyhow", "assert_approx_eq", "bigdecimal", "chrono", "chrono-tz", "either", "eyre", "futures", "hashbrown", "iana-time-zone", "indexmap", "indoc", "inventory", "jiff", "libc", "lock_api", "memoffset", "num-bigint", "num-complex", "num-rational", "once_cell", "ordered-float", "parking_lot", "portable-atomic", "proptest", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", "rayon", "rust_decimal", "send_wrapper", "serde", "serde_json", "smallvec", "static_assertions", "tempfile", "time", "trybuild", "unindent", "uuid", ] [[package]] name = "pyo3-build-config" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598" dependencies = [ "once_cell", "python3-dll-a", "target-lexicon", ] [[package]] name = "pyo3-ffi" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c" dependencies = [ "libc", "pyo3-build-config", ] [[package]] name = "pyo3-macros" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", "syn", ] [[package]] name = "pyo3-macros-backend" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc" dependencies = [ "heck", "proc-macro2", "pyo3-build-config", "quote", "syn", ] [[package]] name = "python3-dll-a" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d381ef313ae70b4da5f95f8a4de773c6aa5cd28f73adec4b4a31df70b66780d8" dependencies = [ "cc", ] [[package]] name = "quote" version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "rand_core 0.6.4", ] [[package]] name = "rand" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha", "rand_core 0.9.3", ] [[package]] name = "rand_chacha" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core 0.9.3", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" [[package]] name = "rand_core" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom", ] [[package]] name = "rand_xorshift" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ "rand_core 0.9.3", ] [[package]] name = "rayon" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "redox_syscall" version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" dependencies = [ "bitflags", ] [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rust_decimal" version = "1.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50" dependencies = [ "arrayvec", "num-traits", ] [[package]] name = "rustix" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "rustversion" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "send_wrapper" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "siphasher" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "syn" version = "2.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-lexicon" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" [[package]] name = "target-triple" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" [[package]] name = "tempfile" version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", "getrandom", "once_cell", "rustix", "windows-sys", ] [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "time" version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "num-conv", "powerfmt", "time-core", ] [[package]] name = "time-core" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", "toml_datetime", "toml_edit", ] [[package]] name = "toml_datetime" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "toml_write", "winnow", ] [[package]] name = "toml_write" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "trybuild" version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c9bf9513a2f4aeef5fdac8677d7d349c79fdbcc03b9c86da6e9d254f1e43be2" dependencies = [ "glob", "serde", "serde_derive", "serde_json", "target-triple", "termcolor", "toml", ] [[package]] name = "unarray" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unindent" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" [[package]] name = "uuid" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ "getrandom", "js-sys", "wasm-bindgen", ] [[package]] name = "wasi" version = "0.14.2+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" dependencies = [ "wit-bindgen-rt", ] [[package]] name = "wasm-bindgen" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] [[package]] name = "windows-core" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-interface" version = "0.59.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "windows-link" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-result" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen-rt" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ "bitflags", ] [[package]] name = "zerocopy" version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", "syn", ] pyo3/Cargo.toml0000644000175000017500000002342115105742312013226 0ustar bdrungbdrung# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.63" name = "pyo3" version = "0.25.1" authors = ["PyO3 Project and Contributors "] build = "build.rs" exclude = [ "/.gitignore", ".cargo/config", "/codecov.yml", "/Makefile", "/pyproject.toml", "/noxfile.py", "/.github", "/tests/test_compile_error.rs", "/tests/ui", ] autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Bindings to Python interpreter" homepage = "https://github.com/pyo3/pyo3" documentation = "https://docs.rs/crate/pyo3/" readme = "README.md" keywords = [ "pyo3", "python", "cpython", "ffi", ] categories = [ "api-bindings", "development-tools::ffi", ] license = "MIT OR Apache-2.0" repository = "https://github.com/pyo3/pyo3" [package.metadata.docs.rs] features = ["full"] no-default-features = true rustdoc-args = [ "--cfg", "docsrs", ] [features] abi3 = [ "pyo3-build-config/abi3", "pyo3-ffi/abi3", ] abi3-py310 = [ "abi3-py311", "pyo3-build-config/abi3-py310", "pyo3-ffi/abi3-py310", ] abi3-py311 = [ "abi3-py312", "pyo3-build-config/abi3-py311", "pyo3-ffi/abi3-py311", ] abi3-py312 = [ "abi3-py313", "pyo3-build-config/abi3-py312", "pyo3-ffi/abi3-py312", ] abi3-py313 = [ "abi3-py314", "pyo3-build-config/abi3-py313", "pyo3-ffi/abi3-py313", ] abi3-py314 = [ "abi3", "pyo3-build-config/abi3-py314", "pyo3-ffi/abi3-py314", ] abi3-py37 = [ "abi3-py38", "pyo3-build-config/abi3-py37", "pyo3-ffi/abi3-py37", ] abi3-py38 = [ "abi3-py39", "pyo3-build-config/abi3-py38", "pyo3-ffi/abi3-py38", ] abi3-py39 = [ "abi3-py310", "pyo3-build-config/abi3-py39", "pyo3-ffi/abi3-py39", ] arc_lock = [ "lock_api", "lock_api/arc_lock", "parking_lot?/arc_lock", ] auto-initialize = [] chrono-local = [ "chrono/clock", "dep:iana-time-zone", ] default = ["macros"] experimental-async = [ "macros", "pyo3-macros/experimental-async", ] experimental-inspect = ["pyo3-macros/experimental-inspect"] extension-module = ["pyo3-ffi/extension-module"] full = [ "macros", "anyhow", "arc_lock", "bigdecimal", "chrono", "chrono-local", "chrono-tz", "either", "experimental-async", "experimental-inspect", "eyre", "hashbrown", "indexmap", "lock_api", "num-bigint", "num-complex", "num-rational", "ordered-float", "parking_lot", "py-clone", "rust_decimal", "serde", "smallvec", "uuid", ] generate-import-lib = ["pyo3-ffi/generate-import-lib"] macros = [ "pyo3-macros", "indoc", "unindent", ] multiple-pymethods = [ "inventory", "pyo3-macros/multiple-pymethods", ] nightly = [] parking_lot = [ "dep:parking_lot", "lock_api", ] py-clone = [] [lib] name = "pyo3" path = "src/lib.rs" [[test]] name = "test_anyhow" path = "tests/test_anyhow.rs" [[test]] name = "test_append_to_inittab" path = "tests/test_append_to_inittab.rs" [[test]] name = "test_arithmetics" path = "tests/test_arithmetics.rs" [[test]] name = "test_buffer" path = "tests/test_buffer.rs" [[test]] name = "test_buffer_protocol" path = "tests/test_buffer_protocol.rs" [[test]] name = "test_bytes" path = "tests/test_bytes.rs" [[test]] name = "test_class_attributes" path = "tests/test_class_attributes.rs" [[test]] name = "test_class_basics" path = "tests/test_class_basics.rs" [[test]] name = "test_class_comparisons" path = "tests/test_class_comparisons.rs" [[test]] name = "test_class_conversion" path = "tests/test_class_conversion.rs" [[test]] name = "test_class_formatting" path = "tests/test_class_formatting.rs" [[test]] name = "test_class_new" path = "tests/test_class_new.rs" [[test]] name = "test_coroutine" path = "tests/test_coroutine.rs" [[test]] name = "test_datetime" path = "tests/test_datetime.rs" [[test]] name = "test_datetime_import" path = "tests/test_datetime_import.rs" [[test]] name = "test_declarative_module" path = "tests/test_declarative_module.rs" [[test]] name = "test_default_impls" path = "tests/test_default_impls.rs" [[test]] name = "test_enum" path = "tests/test_enum.rs" [[test]] name = "test_exceptions" path = "tests/test_exceptions.rs" [[test]] name = "test_field_cfg" path = "tests/test_field_cfg.rs" [[test]] name = "test_frompy_intopy_roundtrip" path = "tests/test_frompy_intopy_roundtrip.rs" [[test]] name = "test_frompyobject" path = "tests/test_frompyobject.rs" [[test]] name = "test_gc" path = "tests/test_gc.rs" [[test]] name = "test_getter_setter" path = "tests/test_getter_setter.rs" [[test]] name = "test_inheritance" path = "tests/test_inheritance.rs" [[test]] name = "test_intopyobject" path = "tests/test_intopyobject.rs" [[test]] name = "test_macro_docs" path = "tests/test_macro_docs.rs" [[test]] name = "test_macros" path = "tests/test_macros.rs" [[test]] name = "test_mapping" path = "tests/test_mapping.rs" [[test]] name = "test_methods" path = "tests/test_methods.rs" [[test]] name = "test_module" path = "tests/test_module.rs" [[test]] name = "test_multiple_pymethods" path = "tests/test_multiple_pymethods.rs" [[test]] name = "test_proto_methods" path = "tests/test_proto_methods.rs" [[test]] name = "test_pyerr_debug_unformattable" path = "tests/test_pyerr_debug_unformattable.rs" [[test]] name = "test_pyfunction" path = "tests/test_pyfunction.rs" [[test]] name = "test_pyself" path = "tests/test_pyself.rs" [[test]] name = "test_sequence" path = "tests/test_sequence.rs" [[test]] name = "test_serde" path = "tests/test_serde.rs" [[test]] name = "test_static_slots" path = "tests/test_static_slots.rs" [[test]] name = "test_string" path = "tests/test_string.rs" [[test]] name = "test_super" path = "tests/test_super.rs" [[test]] name = "test_text_signature" path = "tests/test_text_signature.rs" [[test]] name = "test_variable_arguments" path = "tests/test_variable_arguments.rs" [[test]] name = "test_various" path = "tests/test_various.rs" [dependencies.anyhow] version = "1.0.1" optional = true [dependencies.bigdecimal] version = "0.4" optional = true [dependencies.chrono] version = "0.4.25" optional = true default-features = false [dependencies.chrono-tz] version = ">= 0.10, < 0.11" optional = true default-features = false [dependencies.either] version = "1.9" optional = true [dependencies.eyre] version = ">= 0.6.8, < 0.7" optional = true [dependencies.hashbrown] version = ">= 0.14.5, < 0.16" optional = true [dependencies.iana-time-zone] version = "0.1" features = ["fallback"] optional = true [dependencies.indexmap] version = ">= 2.5.0, < 3" optional = true [dependencies.indoc] version = "2.0.1" optional = true [dependencies.inventory] version = "0.3.5" optional = true [dependencies.jiff-02] version = "0.2" optional = true package = "jiff" [dependencies.libc] version = "0.2.62" [dependencies.lock_api] version = "0.4" optional = true [dependencies.memoffset] version = "0.9" [dependencies.num-bigint] version = "0.4.2" optional = true [dependencies.num-complex] version = ">= 0.4.6, < 0.5" optional = true [dependencies.num-rational] version = "0.4.1" optional = true [dependencies.once_cell] version = "1.13" [dependencies.ordered-float] version = "5.0.0" optional = true default-features = false [dependencies.parking_lot] version = "0.12" optional = true [dependencies.pyo3-ffi] version = "=0.25.1" [dependencies.pyo3-macros] version = "=0.25.1" optional = true [dependencies.rust_decimal] version = "1.15" optional = true default-features = false [dependencies.serde] version = "1.0" optional = true [dependencies.smallvec] version = "1.0" optional = true [dependencies.time] version = "0.3.38" optional = true default-features = false [dependencies.unindent] version = "0.2.1" optional = true [dependencies.uuid] version = "1.11.0" optional = true [dev-dependencies.assert_approx_eq] version = "1.1.0" [dev-dependencies.chrono] version = "0.4.25" [dev-dependencies.chrono-tz] version = ">= 0.10, < 0.11" [dev-dependencies.futures] version = "0.3.28" [dev-dependencies.parking_lot] version = "0.12.3" features = ["arc_lock"] [dev-dependencies.proptest] version = "1.0" features = ["std"] default-features = false [dev-dependencies.rayon] version = "1.6.1" [dev-dependencies.send_wrapper] version = "0.6" [dev-dependencies.serde] version = "1.0" features = ["derive"] [dev-dependencies.serde_json] version = "1.0.61" [dev-dependencies.static_assertions] version = "1.1.0" [dev-dependencies.tempfile] version = "3.12.0" [dev-dependencies.trybuild] version = ">=1.0.70" [dev-dependencies.uuid] version = "1.10.0" features = ["v4"] [build-dependencies.pyo3-build-config] version = "=0.25.1" features = ["resolve-config"] [target.'cfg(not(target_has_atomic = "64"))'.dependencies.portable-atomic] version = "1.0" [lints.clippy] checked_conversions = "warn" dbg_macro = "warn" explicit_into_iter_loop = "warn" explicit_iter_loop = "warn" filter_map_next = "warn" flat_map_option = "warn" let_unit_value = "warn" manual_assert = "warn" manual_ok_or = "warn" todo = "warn" unnecessary_wraps = "warn" used_underscore_binding = "warn" useless_transmute = "warn" [lints.rust] elided_lifetimes_in_paths = "warn" invalid_doc_attributes = "warn" rust_2021_prelude_collisions = "warn" unsafe_op_in_unsafe_fn = "warn" unused_lifetimes = "warn" [lints.rust.rust_2018_idioms] level = "warn" priority = -1 [lints.rustdoc] bare_urls = "warn" broken_intra_doc_links = "warn" pyo3/.cargo-checksum.json0000664000175000017500000000013115105742312015135 0ustar bdrungbdrung{"files":{},"package":"8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a"}pyo3/LICENSE-APACHE0000644000175000017500000002311715105742312013224 0ustar bdrungbdrungCopyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS pyo3/guide/0000775000175000017500000000000015105742312012373 5ustar bdrungbdrungpyo3/guide/pyo3_version.py0000644000175000017500000000326515105742312015410 0ustar bdrungbdrung"""Simple mdbook preprocessor to inject pyo3 version into the guide. It will replace: - {{#PYO3_VERSION_TAG}} with the contents of the PYO3_VERSION_TAG environment var - {{#PYO3_DOCS_URL}} with the location of docs (e.g. 'https://docs.rs/pyo3/0.13.2') - {{#PYO3_CRATE_VERSION}} with a relevant toml snippet (e.g. 'version = "0.13.2"') Tested against mdbook 0.4.10. """ import json import os import sys # Set PYO3_VERSION in CI to build the correct version into links PYO3_VERSION_TAG = os.environ.get("PYO3_VERSION_TAG", "main") if PYO3_VERSION_TAG == "main": PYO3_DOCS_URL = "https://pyo3.rs/main/doc" PYO3_DOCS_VERSION = "latest" PYO3_CRATE_VERSION = 'git = "https://github.com/pyo3/pyo3"' else: # v0.13.2 -> 0.13.2 version = PYO3_VERSION_TAG.lstrip("v") PYO3_DOCS_URL = f"https://docs.rs/pyo3/{version}" PYO3_DOCS_VERSION = version PYO3_CRATE_VERSION = f'version = "{version}"' def replace_section_content(section): if not isinstance(section, dict) or "Chapter" not in section: return # Replace raw and url-encoded forms section["Chapter"]["content"] = ( section["Chapter"]["content"] .replace("{{#PYO3_VERSION_TAG}}", PYO3_VERSION_TAG) .replace("{{#PYO3_DOCS_URL}}", PYO3_DOCS_URL) .replace("{{#PYO3_DOCS_VERSION}}", PYO3_DOCS_VERSION) .replace("{{#PYO3_CRATE_VERSION}}", PYO3_CRATE_VERSION) ) for sub_item in section["Chapter"]["sub_items"]: replace_section_content(sub_item) for line in sys.stdin: if line: [context, book] = json.loads(line) for section in book["sections"]: replace_section_content(section) json.dump(book, fp=sys.stdout) pyo3/guide/book.toml0000644000175000017500000000070515105742312014222 0ustar bdrungbdrung[book] title = "PyO3 user guide" description = "PyO3 user guide" author = "PyO3 Project and Contributors" [preprocessor.pyo3_version] command = "python3 guide/pyo3_version.py" [preprocessor.tabs] [output.html] git-repository-url = "https://github.com/PyO3/pyo3/tree/main/guide" edit-url-template = "https://github.com/PyO3/pyo3/edit/main/guide/{path}" playground.runnable = false additional-css = ["theme/tabs.css"] additional-js = ["theme/tabs.js"] pyo3/guide/pyclass-parameters.md0000644000175000017500000001157715105742312016545 0ustar bdrungbdrung`#[pyclass]` can be used with the following parameters: | Parameter | Description | | :- | :- | | `constructor` | This is currently only allowed on [variants of complex enums][params-constructor]. It allows customization of the generated class constructor for each variant. It uses the same syntax and supports the same options as the `signature` attribute of functions and methods. | | `crate = "some::path"` | Path to import the `pyo3` crate, if it's not accessible at `::pyo3`. | | `dict` | Gives instances of this class an empty `__dict__` to store custom attributes. | | `eq` | Implements `__eq__` using the `PartialEq` implementation of the underlying Rust datatype. | | `eq_int` | Implements `__eq__` using `__int__` for simple enums. | | `extends = BaseType` | Use a custom baseclass. Defaults to [`PyAny`][params-1] | | `freelist = N` | Implements a [free list][params-2] of size N. This can improve performance for types that are often created and deleted in quick succession. Profile your code to see whether `freelist` is right for you. | | `frozen` | Declares that your pyclass is immutable. It removes the borrow checker overhead when retrieving a shared reference to the Rust struct, but disables the ability to get a mutable reference. | | `generic` | Implements runtime parametrization for the class following [PEP 560](https://peps.python.org/pep-0560/). | | `get_all` | Generates getters for all fields of the pyclass. | | `hash` | Implements `__hash__` using the `Hash` implementation of the underlying Rust datatype. | | `immutable_type` | Makes the type object immutable. Supported on 3.14+ with the `abi3` feature active, or 3.10+ otherwise. | | `mapping` | Inform PyO3 that this class is a [`Mapping`][params-mapping], and so leave its implementation of sequence C-API slots empty. | | `module = "module_name"` | Python code will see the class as being defined in this module. Defaults to `builtins`. | | `name = "python_name"` | Sets the name that Python sees this class as. Defaults to the name of the Rust struct. | | `ord` | Implements `__lt__`, `__gt__`, `__le__`, & `__ge__` using the `PartialOrd` implementation of the underlying Rust datatype. *Requires `eq`* | | `rename_all = "renaming_rule"` | Applies renaming rules to every getters and setters of a struct, or every variants of an enum. Possible values are: "camelCase", "kebab-case", "lowercase", "PascalCase", "SCREAMING-KEBAB-CASE", "SCREAMING_SNAKE_CASE", "snake_case", "UPPERCASE". | | `sequence` | Inform PyO3 that this class is a [`Sequence`][params-sequence], and so leave its C-API mapping length slot empty. | | `set_all` | Generates setters for all fields of the pyclass. | | `str` | Implements `__str__` using the `Display` implementation of the underlying Rust datatype or by passing an optional format string `str=""`. *Note: The optional format string is only allowed for structs. `name` and `rename_all` are incompatible with the optional format string. Additional details can be found in the discussion on this [PR](https://github.com/PyO3/pyo3/pull/4233).* | | `subclass` | Allows other Python classes and `#[pyclass]` to inherit from this class. Enums cannot be subclassed. | | `unsendable` | Required if your struct is not [`Send`][params-3]. Rather than using `unsendable`, consider implementing your struct in a thread-safe way by e.g. substituting [`Rc`][params-4] with [`Arc`][params-5]. By using `unsendable`, your class will panic when accessed by another thread. Also note the Python's GC is multi-threaded and while unsendable classes will not be traversed on foreign threads to avoid UB, this can lead to memory leaks. | | `weakref` | Allows this class to be [weakly referenceable][params-6]. | All of these parameters can either be passed directly on the `#[pyclass(...)]` annotation, or as one or more accompanying `#[pyo3(...)]` annotations, e.g.: ```rust,ignore // Argument supplied directly to the `#[pyclass]` annotation. #[pyclass(name = "SomeName", subclass)] struct MyClass {} // Argument supplied as a separate annotation. #[pyclass] #[pyo3(name = "SomeName", subclass)] struct MyClass {} ``` [params-1]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyAny.html [params-2]: https://en.wikipedia.org/wiki/Free_list [params-3]: https://doc.rust-lang.org/std/marker/trait.Send.html [params-4]: https://doc.rust-lang.org/std/rc/struct.Rc.html [params-5]: https://doc.rust-lang.org/std/sync/struct.Arc.html [params-6]: https://docs.python.org/3/library/weakref.html [params-constructor]: https://pyo3.rs/latest/class.html#complex-enums [params-mapping]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types [params-sequence]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types pyo3/guide/src/0000775000175000017500000000000015105742312013162 5ustar bdrungbdrungpyo3/guide/src/python-typing-hints.md0000644000175000017500000002627715105742312017474 0ustar bdrungbdrung# Typing and IDE hints for your Python package PyO3 provides an easy to use interface to code native Python libraries in Rust. The accompanying Maturin allows you to build and publish them as a package. Yet, for a better user experience, Python libraries should provide typing hints and documentation for all public entities, so that IDEs can show them during development and type analyzing tools such as `mypy` can use them to properly verify the code. Currently the best solution for the problem is to manually maintain `*.pyi` files and ship them along with the package. There is a sketch of a roadmap towards completing [the `experimental-inspect` feature](./features.md#experimental-inspect) which may eventually lead to automatic type annotations generated by PyO3. This needs more testing and implementation, please see [issue #2454](https://github.com/PyO3/pyo3/issues/2454). ## Introduction to `pyi` files `pyi` files (an abbreviation for `Python Interface`) are called "stub files" in most of the documentation related to them. A very good definition of what it is can be found in [old MyPy documentation](https://github.com/python/mypy/wiki/Creating-Stubs-For-Python-Modules): > A stubs file only contains a description of the public interface of the module without any implementations. There is also [extensive documentation on type stubs on the official Python typing documentation](https://typing.readthedocs.io/en/latest/source/stubs.html). Most Python developers probably already encountered them when trying to use their IDE's "Go to Definition" function on any builtin type. For example, the definitions of a few standard exceptions look like this: ```python class BaseException(object): args: Tuple[Any, ...] __cause__: BaseException | None __context__: BaseException | None __suppress_context__: bool __traceback__: TracebackType | None def __init__(self, *args: object) -> None: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... def with_traceback(self: _TBE, tb: TracebackType | None) -> _TBE: ... class SystemExit(BaseException): code: int class Exception(BaseException): ... class StopIteration(Exception): value: Any ``` As we can see, those are not full definitions containing implementation, but just a description of the interface. It is usually all that the user of the library needs. ### What do the PEPs say? At the time of writing this documentation, the `pyi` files are referenced in four PEPs. [PEP8 - Style Guide for Python Code - #Function Annotations](https://www.python.org/dev/peps/pep-0008/#function-annotations) (last point) recommends all third party library creators to provide stub files as the source of knowledge about the package for type checker tools. > (...) it is expected that users of third party library packages may want to run type checkers over those packages. For this purpose [PEP 484](https://www.python.org/dev/peps/pep-0484) recommends the use of stub files: .pyi files that are read by the type checker in preference of the corresponding .py files. (...) [PEP484 - Type Hints - #Stub Files](https://www.python.org/dev/peps/pep-0484/#stub-files) defines stub files as follows. > Stub files are files containing type hints that are only for use by the type checker, not at runtime. It contains a specification for them (highly recommended reading, since it contains at least one thing that is not used in normal Python code) and also some general information about where to store the stub files. [PEP561 - Distributing and Packaging Type Information](https://www.python.org/dev/peps/pep-0561/) describes in detail how to build packages that will enable type checking. In particular it contains information about how the stub files must be distributed in order for type checkers to use them. [PEP560 - Core support for typing module and generic types](https://www.python.org/dev/peps/pep-0560/) describes the details on how Python's type system internally supports generics, including both runtime behavior and integration with static type checkers. ## How to do it? [PEP561](https://www.python.org/dev/peps/pep-0561/) recognizes three ways of distributing type information: * `inline` - the typing is placed directly in source (`py`) files; * `separate package with stub files` - the typing is placed in `pyi` files distributed in their own, separate package; * `in-package stub files` - the typing is placed in `pyi` files distributed in the same package as source files. The first way is tricky with PyO3 since we do not have `py` files. When it has been investigated and necessary changes are implemented, this document will be updated. The second way is easy to do, and the whole work can be fully separated from the main library code. The example repo for the package with stub files can be found in [PEP561 references section](https://www.python.org/dev/peps/pep-0561/#references): [Stub package repository](https://github.com/ethanhs/stub-package) The third way is described below. ### Including `pyi` files in your PyO3/Maturin build package When source files are in the same package as stub files, they should be placed next to each other. We need a way to do that with Maturin. Also, in order to mark our package as typing-enabled we need to add an empty file named `py.typed` to the package. #### If you do not have other Python files If you do not need to add any other Python files apart from `pyi` to the package, Maturin provides a way to do most of the work for you. As documented in the [Maturin Guide](https://github.com/PyO3/maturin/#mixed-rustpython-projects), the only thing you need to do is to create a stub file for your module named `.pyi` in your project root and Maturin will do the rest. ```text my-rust-project/ ├── Cargo.toml ├── my_project.pyi # <<< add type stubs for Rust functions in the my_project module here ├── pyproject.toml └── src └── lib.rs ``` For an example `pyi` file see the [`my_project.pyi` content](#my_projectpyi-content) section. #### If you need other Python files If you need to add other Python files apart from `pyi` to the package, you can do it also, but that requires some more work. Maturin provides an easy way to add files to a package ([documentation](https://github.com/PyO3/maturin/blob/0dee40510083c03607834c821eea76964140a126/Readme.md#mixed-rustpython-projects)). You just need to create a folder with the name of your module next to the `Cargo.toml` file (for customization see documentation linked above). The folder structure would be: ```text my-project ├── Cargo.toml ├── my_project │ ├── __init__.py │ ├── my_project.pyi │ ├── other_python_file.py │ └── py.typed ├── pyproject.toml ├── Readme.md └── src └── lib.rs ``` Let's go a little bit more into detail regarding the files inside the package folder. ##### `__init__.py` content As we now specify our own package content, we have to provide the `__init__.py` file, so the folder is treated as a package and we can import things from it. We can always use the same content that Maturin creates for us if we do not specify a Python source folder. For PyO3 bindings it would be: ```python from .my_project import * ``` That way everything that is exposed by our native module can be imported directly from the package. ##### `py.typed` requirement As stated in [PEP561](https://www.python.org/dev/peps/pep-0561/): > Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing. This marker applies recursively: if a top-level package includes it, all its sub-packages MUST support type checking as well. If we do not include that file, some IDEs might still use our `pyi` files to show hints, but the type checkers might not. MyPy will raise an error in this situation: ```text error: Skipping analyzing "my_project": found module but no type hints or library stubs ``` The file is just a marker file, so it should be empty. ##### `my_project.pyi` content Our module stub file. This document does not aim at describing how to write them, since you can find a lot of documentation on it, starting from the already quoted [PEP484](https://www.python.org/dev/peps/pep-0484/#stub-files). The example can look like this: ```python class Car: """ A class representing a car. :param body_type: the name of body type, e.g. hatchback, sedan :param horsepower: power of the engine in horsepower """ def __init__(self, body_type: str, horsepower: int) -> None: ... @classmethod def from_unique_name(cls, name: str) -> 'Car': """ Creates a Car based on unique name :param name: model name of a car to be created :return: a Car instance with default data """ def best_color(self) -> str: """ Gets the best color for the car. :return: the name of the color our great algorithm thinks is the best for this car """ ``` ### Supporting Generics Type annotations can also be made generic in Python. They are useful for working with different types while maintaining type safety. Usually, generic classes inherit from the `typing.Generic` metaclass. Take for example the following `.pyi` file that specifies a `Car` that can accept multiple types of wheels: ```python from typing import Generic, TypeVar W = TypeVar('W') class Car(Generic[W]): def __init__(self, wheels: list[W]) -> None: ... def get_wheels(self) -> list[W]: ... def change_wheel(self, wheel_number: int, wheel: W) -> None: ... ``` This way, the end-user can specify the type with variables such as `truck: Car[SteelWheel] = ...` and `f1_car: Car[AlloyWheel] = ...`. There is also a special syntax for specifying generic types in Python 3.12+: ```python class Car[W]: def __init__(self, wheels: list[W]) -> None: ... def get_wheels(self) -> list[W]: ... ``` #### Runtime Behaviour Stub files (`pyi`) are only useful for static type checkers and ignored at runtime. Therefore, PyO3 classes do not inherit from `typing.Generic` even if specified in the stub files. This can cause some runtime issues, as annotating a variable like `f1_car: Car[AlloyWheel] = ...` can make Python call magic methods that are not defined. To overcome this limitation, implementers can pass the `generic` parameter to `pyclass` in Rust: ```rust ignore #[pyclass(generic)] ``` #### Advanced Users `#[pyclass(generic)]` implements a very simple runtime behavior that accepts any generic argument. Advanced users can opt to manually implement [`__class_geitem__`](https://docs.python.org/3/reference/datamodel.html#emulating-generic-types) for the generic class to have more control. ```rust ignore impl MyClass { #[classmethod] #[pyo3(signature = (key, /))] pub fn __class_getitem__( cls: &Bound<'_, PyType>, key: &Bound<'_, PyAny>, ) -> PyResult { /* implementation details */ } } ``` Note that [`pyo3::types::PyGenericAlias`][pygenericalias] can be helfpul when implementing `__class_geitem__` as it can create [`types.GenericAlias`][genericalias] objects from Rust. [pygenericalias]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.pygenericalias [genericalias]: https://docs.python.org/3/library/types.html#types.GenericAliaspyo3/guide/src/index.md0000644000175000017500000000115115105742312014607 0ustar bdrungbdrung# The PyO3 user guide Welcome to the PyO3 user guide! This book is a companion to [PyO3's API docs](https://docs.rs/pyo3). It contains examples and documentation to explain all of PyO3's use cases in detail. The rough order of material in this user guide is as follows: 1. Getting started 2. Wrapping Rust code for use from Python 3. How to use Python code from Rust 4. Remaining topics which go into advanced concepts in detail Please choose from the chapters on the left to jump to individual topics, or continue below to start with PyO3's README.
{{#include ../../README.md}} pyo3/guide/src/python-from-rust/0000775000175000017500000000000015105742312016437 5ustar bdrungbdrungpyo3/guide/src/python-from-rust/calling-existing-code.md0000644000175000017500000002670015105742312023135 0ustar bdrungbdrung# Executing existing Python code If you already have some existing Python code that you need to execute from Rust, the following FAQs can help you select the right PyO3 functionality for your situation: ## Want to access Python APIs? Then use `PyModule::import`. [`PyModule::import`] can be used to get handle to a Python module from Rust. You can use this to import and use any Python module available in your environment. ```rust use pyo3::prelude::*; fn main() -> PyResult<()> { Python::with_gil(|py| { let builtins = PyModule::import(py, "builtins")?; let total: i32 = builtins .getattr("sum")? .call1((vec![1, 2, 3],))? .extract()?; assert_eq!(total, 6); Ok(()) }) } ``` [`PyModule::import`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.import ## Want to run just an expression? Then use `eval`. [`Python::eval`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval) is a method to execute a [Python expression](https://docs.python.org/3/reference/expressions.html) and return the evaluated value as a `Bound<'py, PyAny>` object. ```rust use pyo3::prelude::*; use pyo3::ffi::c_str; # fn main() -> Result<(), ()> { Python::with_gil(|py| { let result = py .eval(c_str!("[i * 10 for i in range(5)]"), None, None) .map_err(|e| { e.print_and_set_sys_last_vars(py); })?; let res: Vec = result.extract().unwrap(); assert_eq!(res, vec![0, 10, 20, 30, 40]); Ok(()) }) # } ``` ## Want to run statements? Then use `run`. [`Python::run`] is a method to execute one or more [Python statements](https://docs.python.org/3/reference/simple_stmts.html). This method returns nothing (like any Python statement), but you can get access to manipulated objects via the `locals` dict. You can also use the [`py_run!`] macro, which is a shorthand for [`Python::run`]. Since [`py_run!`] panics on exceptions, we recommend you use this macro only for quickly testing your Python extensions. [`Python::run`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.run ```rust use pyo3::prelude::*; use pyo3::py_run; # fn main() { #[pyclass] struct UserData { id: u32, name: String, } #[pymethods] impl UserData { fn as_tuple(&self) -> (u32, String) { (self.id, self.name.clone()) } fn __repr__(&self) -> PyResult { Ok(format!("User {}(id: {})", self.name, self.id)) } } Python::with_gil(|py| { let userdata = UserData { id: 34, name: "Yu".to_string(), }; let userdata = Py::new(py, userdata).unwrap(); let userdata_as_tuple = (34, "Yu"); py_run!(py, userdata userdata_as_tuple, r#" assert repr(userdata) == "User Yu(id: 34)" assert userdata.as_tuple() == userdata_as_tuple "#); }) # } ``` ## You have a Python file or code snippet? Then use `PyModule::from_code`. [`PyModule::from_code`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.from_code) can be used to generate a Python module which can then be used just as if it was imported with `PyModule::import`. **Warning**: This will compile and execute code. **Never** pass untrusted code to this function! ```rust use pyo3::{prelude::*, types::IntoPyDict}; use pyo3_ffi::c_str; # fn main() -> PyResult<()> { Python::with_gil(|py| { let activators = PyModule::from_code( py, c_str!(r#" def relu(x): """see https://en.wikipedia.org/wiki/Rectifier_(neural_networks)""" return max(0.0, x) def leaky_relu(x, slope=0.01): return x if x >= 0 else x * slope "#), c_str!("activators.py"), c_str!("activators"), )?; let relu_result: f64 = activators.getattr("relu")?.call1((-1.0,))?.extract()?; assert_eq!(relu_result, 0.0); let kwargs = [("slope", 0.2)].into_py_dict(py)?; let lrelu_result: f64 = activators .getattr("leaky_relu")? .call((-1.0,), Some(&kwargs))? .extract()?; assert_eq!(lrelu_result, -0.2); # Ok(()) }) # } ``` ## Want to embed Python in Rust with additional modules? Python maintains the `sys.modules` dict as a cache of all imported modules. An import in Python will first attempt to lookup the module from this dict, and if not present will use various strategies to attempt to locate and load the module. The [`append_to_inittab`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) macro can be used to add additional `#[pymodule]` modules to an embedded Python interpreter. The macro **must** be invoked _before_ initializing Python. As an example, the below adds the module `foo` to the embedded interpreter: ```rust use pyo3::prelude::*; use pyo3::ffi::c_str; #[pyfunction] fn add_one(x: i64) -> i64 { x + 1 } #[pymodule] fn foo(foo_module: &Bound<'_, PyModule>) -> PyResult<()> { foo_module.add_function(wrap_pyfunction!(add_one, foo_module)?)?; Ok(()) } fn main() -> PyResult<()> { pyo3::append_to_inittab!(foo); Python::with_gil(|py| Python::run(py, c_str!("import foo; foo.add_one(6)"), None, None)) } ``` If `append_to_inittab` cannot be used due to constraints in the program, an alternative is to create a module using [`PyModule::new`] and insert it manually into `sys.modules`: ```rust use pyo3::prelude::*; use pyo3::types::PyDict; use pyo3::ffi::c_str; #[pyfunction] pub fn add_one(x: i64) -> i64 { x + 1 } fn main() -> PyResult<()> { Python::with_gil(|py| { // Create new module let foo_module = PyModule::new(py, "foo")?; foo_module.add_function(wrap_pyfunction!(add_one, &foo_module)?)?; // Import and get sys.modules let sys = PyModule::import(py, "sys")?; let py_modules: Bound<'_, PyDict> = sys.getattr("modules")?.downcast_into()?; // Insert foo into sys.modules py_modules.set_item("foo", foo_module)?; // Now we can import + run our python code Python::run(py, c_str!("import foo; foo.add_one(6)"), None, None) }) } ``` ## Include multiple Python files You can include a file at compile time by using [`std::include_str`](https://doc.rust-lang.org/std/macro.include_str.html) macro. Or you can load a file at runtime by using [`std::fs::read_to_string`](https://doc.rust-lang.org/std/fs/fn.read_to_string.html) function. Many Python files can be included and loaded as modules. If one file depends on another you must preserve correct order while declaring `PyModule`. Example directory structure: ```text . ├── Cargo.lock ├── Cargo.toml ├── python_app │ ├── app.py │ └── utils │ └── foo.py └── src └── main.rs ``` `python_app/app.py`: ```python from utils.foo import bar def run(): return bar() ``` `python_app/utils/foo.py`: ```python def bar(): return "baz" ``` The example below shows: * how to include content of `app.py` and `utils/foo.py` into your rust binary * how to call function `run()` (declared in `app.py`) that needs function imported from `utils/foo.py` `src/main.rs`: ```rust,ignore use pyo3::prelude::*; use pyo3_ffi::c_str; fn main() -> PyResult<()> { let py_foo = c_str!(include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/python_app/utils/foo.py" ))); let py_app = c_str!(include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/python_app/app.py"))); let from_python = Python::with_gil(|py| -> PyResult> { PyModule::from_code(py, py_foo, c_str!("utils.foo"), c_str!("utils.foo"))?; let app: Py = PyModule::from_code(py, py_app, c_str!(""), c_str!(""))? .getattr("run")? .into(); app.call0(py) }); println!("py: {}", from_python?); Ok(()) } ``` The example below shows: * how to load content of `app.py` at runtime so that it sees its dependencies automatically * how to call function `run()` (declared in `app.py`) that needs function imported from `utils/foo.py` It is recommended to use absolute paths because then your binary can be run from anywhere as long as your `app.py` is in the expected directory (in this example that directory is `/usr/share/python_app`). `src/main.rs`: ```rust,no_run use pyo3::prelude::*; use pyo3::types::PyList; use pyo3_ffi::c_str; use std::fs; use std::path::Path; use std::ffi::CString; fn main() -> PyResult<()> { let path = Path::new("/usr/share/python_app"); let py_app = CString::new(fs::read_to_string(path.join("app.py"))?)?; let from_python = Python::with_gil(|py| -> PyResult> { let syspath = py .import("sys")? .getattr("path")? .downcast_into::()?; syspath.insert(0, path)?; let app: Py = PyModule::from_code(py, py_app.as_c_str(), c_str!(""), c_str!(""))? .getattr("run")? .into(); app.call0(py) }); println!("py: {}", from_python?); Ok(()) } ``` [`Python::run`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.run [`py_run!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.py_run.html ## Need to use a context manager from Rust? Use context managers by directly invoking `__enter__` and `__exit__`. ```rust use pyo3::prelude::*; use pyo3::ffi::c_str; fn main() { Python::with_gil(|py| { let custom_manager = PyModule::from_code( py, c_str!(r#" class House(object): def __init__(self, address): self.address = address def __enter__(self): print(f"Welcome to {self.address}!") def __exit__(self, type, value, traceback): if type: print(f"Sorry you had {type} trouble at {self.address}") else: print(f"Thank you for visiting {self.address}, come again soon!") "#), c_str!("house.py"), c_str!("house"), ) .unwrap(); let house_class = custom_manager.getattr("House").unwrap(); let house = house_class.call1(("123 Main Street",)).unwrap(); house.call_method0("__enter__").unwrap(); let result = py.eval(c_str!("undefined_variable + 1"), None, None); // If the eval threw an exception we'll pass it through to the context manager. // Otherwise, __exit__ is called with empty arguments (Python "None"). match result { Ok(_) => { let none = py.None(); house .call_method1("__exit__", (&none, &none, &none)) .unwrap(); } Err(e) => { house .call_method1( "__exit__", ( e.get_type(py), e.value(py), e.traceback(py), ), ) .unwrap(); } } }) } ``` ## Handling system signals/interrupts (Ctrl-C) The best way to handle system signals when running Rust code is to periodically call `Python::check_signals` to handle any signals captured by Python's signal handler. See also [the FAQ entry](../faq.md#ctrl-c-doesnt-do-anything-while-my-rust-code-is-executing). Alternatively, set Python's `signal` module to take the default action for a signal: ```rust use pyo3::prelude::*; # fn main() -> PyResult<()> { Python::with_gil(|py| -> PyResult<()> { let signal = py.import("signal")?; // Set SIGINT to have the default action signal .getattr("signal")? .call1((signal.getattr("SIGINT")?, signal.getattr("SIG_DFL")?))?; Ok(()) }) # } ``` [`PyModule::new`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.new pyo3/guide/src/python-from-rust/function-calls.md0000644000175000017500000001044415105742312021703 0ustar bdrungbdrung# Calling Python functions The `Bound<'py, T>` smart pointer (such as `Bound<'py, PyAny>`, `Bound<'py, PyList>`, or `Bound<'py, MyClass>`) can be used to call Python functions. PyO3 offers two APIs to make function calls: * [`call`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call) - call any callable Python object. * [`call_method`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method) - call a method on the Python object. Both of these APIs take `args` and `kwargs` arguments (for positional and keyword arguments respectively). There are variants for less complex calls: * [`call1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call1) and [`call_method1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method1) to call only with positional `args`. * [`call0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call0) and [`call_method0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method0) to call with no arguments. For convenience the [`Py`](../types.md#pyt-and-pyobject) smart pointer also exposes these same six API methods, but needs a `Python` token as an additional first argument to prove the GIL is held. The example below calls a Python function behind a `PyObject` (aka `Py`) reference: ```rust use pyo3::prelude::*; use pyo3::types::PyTuple; use pyo3_ffi::c_str; fn main() -> PyResult<()> { let arg1 = "arg1"; let arg2 = "arg2"; let arg3 = "arg3"; Python::with_gil(|py| { let fun: Py = PyModule::from_code( py, c_str!("def example(*args, **kwargs): if args != (): print('called with args', args) if kwargs != {}: print('called with kwargs', kwargs) if args == () and kwargs == {}: print('called with no arguments')"), c_str!(""), c_str!(""), )? .getattr("example")? .into(); // call object without any arguments fun.call0(py)?; // pass object with Rust tuple of positional arguments let args = (arg1, arg2, arg3); fun.call1(py, args)?; // call object with Python tuple of positional arguments let args = PyTuple::new(py, &[arg1, arg2, arg3])?; fun.call1(py, args)?; Ok(()) }) } ``` ## Creating keyword arguments For the `call` and `call_method` APIs, `kwargs` are `Option<&Bound<'py, PyDict>>`, so can either be `None` or `Some(&dict)`. You can use the [`IntoPyDict`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.IntoPyDict.html) trait to convert other dict-like containers, e.g. `HashMap` or `BTreeMap`, as well as tuples with up to 10 elements and `Vec`s where each element is a two-element tuple. To pass keyword arguments of different types, construct a `PyDict` object. ```rust use pyo3::prelude::*; use pyo3::types::{PyDict, IntoPyDict}; use std::collections::HashMap; use pyo3::ffi::c_str; fn main() -> PyResult<()> { let key1 = "key1"; let val1 = 1; let key2 = "key2"; let val2 = 2; Python::with_gil(|py| { let fun: Py = PyModule::from_code( py, c_str!("def example(*args, **kwargs): if args != (): print('called with args', args) if kwargs != {}: print('called with kwargs', kwargs) if args == () and kwargs == {}: print('called with no arguments')"), c_str!(""), c_str!(""), )? .getattr("example")? .into(); // call object with PyDict let kwargs = [(key1, val1)].into_py_dict(py)?; fun.call(py, (), Some(&kwargs))?; // pass arguments as Vec let kwargs = vec![(key1, val1), (key2, val2)]; fun.call(py, (), Some(&kwargs.into_py_dict(py)?))?; // pass arguments as HashMap let mut kwargs = HashMap::<&str, i32>::new(); kwargs.insert(key1, 1); fun.call(py, (), Some(&kwargs.into_py_dict(py)?))?; // pass arguments of different types as PyDict let kwargs = PyDict::new(py); kwargs.set_item(key1, val1)?; kwargs.set_item(key2, "string")?; fun.call(py, (), Some(&kwargs))?; Ok(()) }) } ``` pyo3/guide/src/trait-bounds.md0000644000175000017500000004066615105742312016131 0ustar bdrungbdrung# Using in Python a Rust function with trait bounds PyO3 allows for easy conversion from Rust to Python for certain functions and classes (see the [conversion table](conversions/tables.md)). However, it is not always straightforward to convert Rust code that requires a given trait implementation as an argument. This tutorial explains how to convert a Rust function that takes a trait as argument for use in Python with classes implementing the same methods as the trait. Why is this useful? ### Pros - Make your Rust code available to Python users - Code complex algorithms in Rust with the help of the borrow checker ### Cons - Not as fast as native Rust (type conversion has to be performed and one part of the code runs in Python) - You need to adapt your code to expose it ## Example Let's work with the following basic example of an implementation of a optimization solver operating on a given model. Let's say we have a function `solve` that operates on a model and mutates its state. The argument of the function can be any model that implements the `Model` trait : ```rust,no_run # #![allow(dead_code)] pub trait Model { fn set_variables(&mut self, inputs: &Vec); fn compute(&mut self); fn get_results(&self) -> Vec; } pub fn solve(model: &mut T) { println!("Magic solver that mutates the model into a resolved state"); } ``` Let's assume we have the following constraints: - We cannot change that code as it runs on many Rust models. - We also have many Python models that cannot be solved as this solver is not available in that language. Rewriting it in Python would be cumbersome and error-prone, as everything is already available in Rust. How could we expose this solver to Python thanks to PyO3 ? ## Implementation of the trait bounds for the Python class If a Python class implements the same three methods as the `Model` trait, it seems logical it could be adapted to use the solver. However, it is not possible to pass a `PyObject` to it as it does not implement the Rust trait (even if the Python model has the required methods). In order to implement the trait, we must write a wrapper around the calls in Rust to the Python model. The method signatures must be the same as the trait, keeping in mind that the Rust trait cannot be changed for the purpose of making the code available in Python. The Python model we want to expose is the following one, which already contains all the required methods: ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 - 3 for elt in self.inputs] def get_results(self): return self.results ``` The following wrapper will call the Python model from Rust, using a struct to hold the model as a `PyAny` object: ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; use pyo3::types::PyList; # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } struct UserModel { model: Py, } impl Model for UserModel { fn set_variables(&mut self, var: &Vec) { println!("Rust calling Python to set the variables"); Python::with_gil(|py| { self.model .bind(py) .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) .unwrap(); }) } fn get_results(&self) -> Vec { println!("Rust calling Python to get the results"); Python::with_gil(|py| { self.model .bind(py) .call_method("get_results", (), None) .unwrap() .extract() .unwrap() }) } fn compute(&mut self) { println!("Rust calling Python to perform the computation"); Python::with_gil(|py| { self.model .bind(py) .call_method("compute", (), None) .unwrap(); }) } } ``` Now that this bit is implemented, let's expose the model wrapper to Python. Let's add the PyO3 annotations and add a constructor: ```rust,no_run # #![allow(dead_code)] # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # use pyo3::prelude::*; #[pyclass] struct UserModel { model: Py, } #[pymodule] fn trait_exposure(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } #[pymethods] impl UserModel { #[new] pub fn new(model: Py) -> Self { UserModel { model } } } ``` Now we add the PyO3 annotations to the trait implementation: ```rust,ignore #[pymethods] impl Model for UserModel { // the previous trait implementation } ``` However, the previous code will not compile. The compilation error is the following one: `error: #[pymethods] cannot be used on trait impl blocks` That's a bummer! However, we can write a second wrapper around these functions to call them directly. This wrapper will also perform the type conversions between Python and Rust. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } # # impl Model for UserModel { # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::with_gil(|py| { # self.model.bind(py) # .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) # .unwrap(); # }) # } # # fn get_results(&self) -> Vec { # println!("Rust calling Python to get the results"); # Python::with_gil(|py| { # self.model # .bind(py) # .call_method("get_results", (), None) # .unwrap() # .extract() # .unwrap() # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::with_gil(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # # } # } #[pymethods] impl UserModel { pub fn set_variables(&mut self, var: Vec) { println!("Set variables from Python calling Rust"); Model::set_variables(self, &var) } pub fn get_results(&mut self) -> Vec { println!("Get results from Python calling Rust"); Model::get_results(self) } pub fn compute(&mut self) { println!("Compute from Python calling Rust"); Model::compute(self) } } ``` This wrapper handles the type conversion between the PyO3 requirements and the trait. In order to meet PyO3 requirements, this wrapper must: - return an object of type `PyResult` - use only values, not references in the method signatures Let's run the file python file: ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 - 3 for elt in self.inputs] def get_results(self): return self.results if __name__=="__main__": import trait_exposure myModel = Model() my_rust_model = trait_exposure.UserModel(myModel) my_rust_model.set_variables([2.0]) print("Print value from Python: ", myModel.inputs) my_rust_model.compute() print("Print value from Python through Rust: ", my_rust_model.get_results()) print("Print value directly from Python: ", myModel.get_results()) ``` This outputs: ```block Set variables from Python calling Rust Set variables from Rust calling Python Print value from Python: [2.0] Compute from Python calling Rust Compute from Rust calling Python Get results from Python calling Rust Get results from Rust calling Python Print value from Python through Rust: [1.0] Print value directly from Python: [1.0] ``` We have now successfully exposed a Rust model that implements the `Model` trait to Python! We will now expose the `solve` function, but before, let's talk about types errors. ## Type errors in Python What happens if you have type errors when using Python and how can you improve the error messages? ### Wrong types in Python function arguments Let's assume in the first case that you will use in your Python file `my_rust_model.set_variables(2.0)` instead of `my_rust_model.set_variables([2.0])`. The Rust signature expects a vector, which corresponds to a list in Python. What happens if instead of a vector, we pass a single value ? At the execution of Python, we get : ```block File "main.py", line 15, in my_rust_model.set_variables(2) TypeError ``` It is a type error and Python points to it, so it's easy to identify and solve. ### Wrong types in Python method signatures Let's assume now that the return type of one of the methods of our Model class is wrong, for example the `get_results` method that is expected to return a `Vec` in Rust, a list in Python. ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 -3 for elt in self.inputs] def get_results(self): return self.results[0] #return self.results <-- this is the expected output ``` This call results in the following panic: ```block pyo3_runtime.PanicException: called `Result::unwrap()` on an `Err` value: PyErr { type: Py(0x10dcf79f0, PhantomData) } ``` This error code is not helpful for a Python user that does not know anything about Rust, or someone that does not know PyO3 was used to interface the Rust code. However, as we are responsible for making the Rust code available to Python, we can do something about it. The issue is that we called `unwrap` anywhere we could, and therefore any panic from PyO3 will be directly forwarded to the end user. Let's modify the code performing the type conversion to give a helpful error message to the Python user: We used in our `get_results` method the following call that performs the type conversion: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } impl Model for UserModel { fn get_results(&self) -> Vec { println!("Rust calling Python to get the results"); Python::with_gil(|py| { self.model .bind(py) .call_method("get_results", (), None) .unwrap() .extract() .unwrap() }) } # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::with_gil(|py| { # self.model.bind(py) # .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) # .unwrap(); # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::with_gil(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # } } ``` Let's break it down in order to perform better error handling: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } impl Model for UserModel { fn get_results(&self) -> Vec { println!("Get results from Rust calling Python"); Python::with_gil(|py| { let py_result: Bound<'_, PyAny> = self .model .bind(py) .call_method("get_results", (), None) .unwrap(); if py_result.get_type().name().unwrap() != "list" { panic!( "Expected a list for the get_results() method signature, got {}", py_result.get_type().name().unwrap() ); } py_result.extract() }) .unwrap() } # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::with_gil(|py| { # let py_model = self.model.bind(py) # .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) # .unwrap(); # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::with_gil(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # } } ``` By doing so, you catch the result of the Python computation and check its type in order to be able to deliver a better error message before performing the unwrapping. Of course, it does not cover all the possible wrong outputs: the user could return a list of strings instead of a list of floats. In this case, a runtime panic would still occur due to PyO3, but with an error message much more difficult to decipher for non-rust user. It is up to the developer exposing the rust code to decide how much effort to invest into Python type error handling and improved error messages. ## The final code Now let's expose the `solve()` function to make it available from Python. It is not possible to directly expose the `solve` function to Python, as the type conversion cannot be performed. It requires an object implementing the `Model` trait as input. However, the `UserModel` already implements this trait. Because of this, we can write a function wrapper that takes the `UserModel`--which has already been exposed to Python--as an argument in order to call the core function `solve`. It is also required to make the struct public. ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; use pyo3::types::PyList; pub trait Model { fn set_variables(&mut self, var: &Vec); fn get_results(&self) -> Vec; fn compute(&mut self); } pub fn solve(model: &mut T) { println!("Magic solver that mutates the model into a resolved state"); } #[pyfunction] #[pyo3(name = "solve")] pub fn solve_wrapper(model: &mut UserModel) { solve(model); } #[pyclass] pub struct UserModel { model: Py, } #[pymodule] fn trait_exposure(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_function(wrap_pyfunction!(solve_wrapper, m)?)?; Ok(()) } #[pymethods] impl UserModel { #[new] pub fn new(model: Py) -> Self { UserModel { model } } pub fn set_variables(&mut self, var: Vec) { println!("Set variables from Python calling Rust"); Model::set_variables(self, &var) } pub fn get_results(&mut self) -> Vec { println!("Get results from Python calling Rust"); Model::get_results(self) } pub fn compute(&mut self) { Model::compute(self) } } impl Model for UserModel { fn set_variables(&mut self, var: &Vec) { println!("Rust calling Python to set the variables"); Python::with_gil(|py| { self.model .bind(py) .call_method("set_variables", (PyList::new(py, var).unwrap(),), None) .unwrap(); }) } fn get_results(&self) -> Vec { println!("Get results from Rust calling Python"); Python::with_gil(|py| { let py_result: Bound<'_, PyAny> = self .model .bind(py) .call_method("get_results", (), None) .unwrap(); if py_result.get_type().name().unwrap() != "list" { panic!( "Expected a list for the get_results() method signature, got {}", py_result.get_type().name().unwrap() ); } py_result.extract() }) .unwrap() } fn compute(&mut self) { println!("Rust calling Python to perform the computation"); Python::with_gil(|py| { self.model .bind(py) .call_method("compute", (), None) .unwrap(); }) } } ``` pyo3/guide/src/types.md0000644000175000017500000004316715105742312014661 0ustar bdrungbdrung# Python object types PyO3 offers two main sets of types to interact with Python objects. This section of the guide expands into detail about these types and how to choose which to use. The first set of types are the [smart pointers][smart-pointers] which all Python objects are wrapped in. These are `Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`. The [first section below](#pyo3s-smart-pointers) expands on each of these in detail and why there are three of them. The second set of types are types which fill in the generic parameter `T` of the smart pointers. The most common is `PyAny`, which represents any Python object (similar to Python's `typing.Any`). There are also concrete types for many Python built-in types, such as `PyList`, `PyDict`, and `PyTuple`. User defined `#[pyclass]` types also fit this category. The [second section below](#concrete-python-types) expands on how to use these types. ## PyO3's smart pointers PyO3's API offers three generic smart pointers: `Py`, `Bound<'py, T>` and `Borrowed<'a, 'py, T>`. For each of these the type parameter `T` will be filled by a [concrete Python type](#concrete-python-types). For example, a Python list object can be represented by `Py`, `Bound<'py, PyList>`, and `Borrowed<'a, 'py, PyList>`. These smart pointers behave differently due to their lifetime parameters. `Py` has no lifetime parameters, `Bound<'py, T>` has [the `'py` lifetime](./python-from-rust.md#the-py-lifetime) as a parameter, and `Borrowed<'a, 'py, T>` has the `'py` lifetime plus an additional lifetime `'a` to denote the lifetime it is borrowing data for. (You can read more about these lifetimes in the subsections below). Python objects are reference counted, like [`std::sync::Arc`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html). A major reason for these smart pointers is to bring Python's reference counting to a Rust API. The recommendation of when to use each of these smart pointers is as follows: - Use `Bound<'py, T>` for as much as possible, as it offers the most efficient and complete API. - Use `Py` mostly just for storage inside Rust `struct`s which do not want to or can't add a lifetime parameter for `Bound<'py, T>`. - `Borrowed<'a, 'py, T>` is almost never used. It is occasionally present at the boundary between Rust and the Python interpreter, for example when borrowing data from Python tuples (which is safe because they are immutable). The sections below also explain these smart pointers in a little more detail. ### `Py` (and `PyObject`) [`Py`][Py] is the foundational smart pointer in PyO3's API. The type parameter `T` denotes the type of the Python object. Very frequently this is `PyAny`, meaning any Python object. This is so common that `Py` has a type alias `PyObject`. Because `Py` is not bound to [the `'py` lifetime](./python-from-rust.md#the-py-lifetime), it is the type to use when storing a Python object inside a Rust `struct` or `enum` which do not want to have a lifetime parameter. In particular, [`#[pyclass]`][pyclass] types are not permitted to have a lifetime, so `Py` is the correct type to store Python objects inside them. The lack of binding to the `'py` lifetime also carries drawbacks: - Almost all methods on `Py` require a `Python<'py>` token as the first argument - Other functionality, such as [`Drop`][Drop], needs to check at runtime for attachment to the Python GIL, at a small performance cost Because of the drawbacks `Bound<'py, T>` is preferred for many of PyO3's APIs. In particular, `Bound<'py, T>` is better for function arguments. To convert a `Py` into a `Bound<'py, T>`, the `Py::bind` and `Py::into_bound` methods are available. `Bound<'py, T>` can be converted back into `Py` using [`Bound::unbind`]. ### `Bound<'py, T>` [`Bound<'py, T>`][Bound] is the counterpart to `Py` which is also bound to the `'py` lifetime. It can be thought of as equivalent to the Rust tuple `(Python<'py>, Py)`. By having the binding to the `'py` lifetime, `Bound<'py, T>` can offer the complete PyO3 API at maximum efficiency. This means that `Bound<'py, T>` should usually be used whenever carrying this lifetime is acceptable, and `Py` otherwise. `Bound<'py, T>` engages in Python reference counting. This means that `Bound<'py, T>` owns a Python object. Rust code which just wants to borrow a Python object should use a shared reference `&Bound<'py, T>`. Just like `std::sync::Arc`, using `.clone()` and `drop()` will cheaply increment and decrement the reference count of the object (just in this case, the reference counting is implemented by the Python interpreter itself). To give an example of how `Bound<'py, T>` is PyO3's primary API type, consider the following Python code: ```python def example(): x = list() # create a Python list x.append(1) # append the integer 1 to it y = x # create a second reference to the list del x # delete the original reference ``` Using PyO3's API, and in particular `Bound<'py, PyList>`, this code translates into the following Rust code: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn example<'py>(py: Python<'py>) -> PyResult<()> { let x: Bound<'py, PyList> = PyList::empty(py); x.append(1)?; let y: Bound<'py, PyList> = x.clone(); // y is a new reference to the same list drop(x); // release the original reference x Ok(()) } # Python::with_gil(example).unwrap(); ``` Or, without the type annotations: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn example(py: Python<'_>) -> PyResult<()> { let x = PyList::empty(py); x.append(1)?; let y = x.clone(); drop(x); Ok(()) } # Python::with_gil(example).unwrap(); ``` #### Function argument lifetimes Because the `'py` lifetime often appears in many function arguments as part of the `Bound<'py, T>` smart pointer, the Rust compiler will often require annotations of input and output lifetimes. This occurs when the function output has at least one lifetime, and there is more than one lifetime present on the inputs. To demonstrate, consider this function which takes accepts Python objects and applies the [Python `+` operation][PyAnyMethods::add] to them: ```rust,compile_fail # use pyo3::prelude::*; fn add(left: &'_ Bound<'_, PyAny>, right: &'_ Bound<'_, PyAny>) -> PyResult> { left.add(right) } ``` Because the Python `+` operation might raise an exception, this function returns `PyResult>`. It doesn't need ownership of the inputs, so it takes `&Bound<'_, PyAny>` shared references. To demonstrate the point, all lifetimes have used the wildcard `'_` to allow the Rust compiler to attempt to infer them. Because there are four input lifetimes (two lifetimes of the shared references, and two `'py` lifetimes unnamed inside the `Bound<'_, PyAny>` pointers), the compiler cannot reason about which must be connected to the output. The correct way to solve this is to add the `'py` lifetime as a parameter for the function, and name all the `'py` lifetimes inside the `Bound<'py, PyAny>` smart pointers. For the shared references, it's also fine to reduce `&'_` to just `&`. The working end result is below: ```rust # use pyo3::prelude::*; fn add<'py>( left: &Bound<'py, PyAny>, right: &Bound<'py, PyAny>, ) -> PyResult> { left.add(right) } # Python::with_gil(|py| { # let s = pyo3::types::PyString::new(py, "s"); # assert!(add(&s, &s).unwrap().eq("ss").unwrap()); # }) ``` If naming the `'py` lifetime adds unwanted complexity to the function signature, it is also acceptable to return `PyObject` (aka `Py`), which has no lifetime. The cost is instead paid by a slight increase in implementation complexity, as seen by the introduction of a call to [`Bound::unbind`]: ```rust # use pyo3::prelude::*; fn add(left: &Bound<'_, PyAny>, right: &Bound<'_, PyAny>) -> PyResult { let output: Bound<'_, PyAny> = left.add(right)?; Ok(output.unbind()) } # Python::with_gil(|py| { # let s = pyo3::types::PyString::new(py, "s"); # assert!(add(&s, &s).unwrap().bind(py).eq("ss").unwrap()); # }) ``` ### `Borrowed<'a, 'py, T>` [`Borrowed<'a, 'py, T>`][Borrowed] is an advanced type used just occasionally at the edge of interaction with the Python interpreter. It can be thought of as analogous to the shared reference `&'a Bound<'py, T>`. The difference is that `Borrowed<'a, 'py, T>` is just a smart pointer rather than a reference-to-a-smart-pointer, which is a helpful reduction in indirection in specific interactions with the Python interpreter. `Borrowed<'a, 'py, T>` dereferences to `Bound<'py, T>`, so all methods on `Bound<'py, T>` are available on `Borrowed<'a, 'py, T>`. An example where `Borrowed<'a, 'py, T>` is used is in [`PyTupleMethods::get_borrowed_item`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyTupleMethods.html#tymethod.get_item): ```rust use pyo3::prelude::*; use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // Create a new tuple with the elements (0, 1, 2) let t = PyTuple::new(py, [0, 1, 2])?; for i in 0..=2 { let entry: Borrowed<'_, 'py, PyAny> = t.get_borrowed_item(i)?; // `PyAnyMethods::extract` is available on `Borrowed` // via the dereference to `Bound` let value: usize = entry.extract()?; assert_eq!(i, value); } # Ok(()) # } # Python::with_gil(example).unwrap(); ``` ### Casting between smart pointer types To convert between `Py` and `Bound<'py, T>` use the `bind()` / `into_bound()` methods. Use the `as_unbound()` / `unbind()` methods to go back from `Bound<'py, T>` to `Py`. ```rust,ignore let obj: Py = ...; let bound: &Bound<'py, PyAny> = obj.bind(py); let bound: Bound<'py, PyAny> = obj.into_bound(py); let obj: &Py = bound.as_unbound(); let obj: Py = bound.unbind(); ``` To convert between `Bound<'py, T>` and `Borrowed<'a, 'py, T>` use the `as_borrowed()` method. `Borrowed<'a, 'py, T>` has a deref coercion to `Bound<'py, T>`. Use the `to_owned()` method to increment the Python reference count and to create a new `Bound<'py, T>` from the `Borrowed<'a, 'py, T>`. ```rust,ignore let bound: Bound<'py, PyAny> = ...; let borrowed: Borrowed<'_, 'py, PyAny> = bound.as_borrowed(); // deref coercion let bound: &Bound<'py, PyAny> = &borrowed; // create a new Bound by increase the Python reference count let bound: Bound<'py, PyAny> = borrowed.to_owned(); ``` To convert between `Py` and `Borrowed<'a, 'py, T>` use the `bind_borrowed()` method. Use either `as_unbound()` or `.to_owned().unbind()` to go back to `Py` from `Borrowed<'a, 'py, T>`, via `Bound<'py, T>`. ```rust,ignore let obj: Py = ...; let borrowed: Borrowed<'_, 'py, PyAny> = bound.as_borrowed(); // via deref coercion to Bound and then using Bound::as_unbound let obj: &Py = borrowed.as_unbound(); // via a new Bound by increasing the Python reference count, and unbind it let obj: Py = borrowed.to_owned().unbind(). ``` ## Concrete Python types In all of `Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`, the type parameter `T` denotes the type of the Python object referred to by the smart pointer. This parameter `T` can be filled by: - [`PyAny`][PyAny], which represents any Python object, - Native Python types such as `PyList`, `PyTuple`, and `PyDict`, and - [`#[pyclass]`][pyclass] types defined from Rust The following subsections covers some further detail about how to work with these types: - the APIs that are available for these concrete types, - how to cast `Bound<'py, T>` to a specific concrete type, and - how to get Rust data out of a `Bound<'py, T>`. ### Using APIs for concrete Python types Each concrete Python type such as `PyAny`, `PyTuple` and `PyDict` exposes its API on the corresponding bound smart pointer `Bound<'py, PyAny>`, `Bound<'py, PyTuple>` and `Bound<'py, PyDict>`. Each type's API is exposed as a trait: [`PyAnyMethods`], [`PyTupleMethods`], [`PyDictMethods`], and so on for all concrete types. Using traits rather than associated methods on the `Bound` smart pointer is done for a couple of reasons: - Clarity of documentation: each trait gets its own documentation page in the PyO3 API docs. If all methods were on the `Bound` smart pointer directly, the vast majority of PyO3's API would be on a single, extremely long, documentation page. - Consistency: downstream code implementing Rust APIs for existing Python types can also follow this pattern of using a trait. Downstream code would not be allowed to add new associated methods directly on the `Bound` type. - Future design: it is hoped that a future Rust with [arbitrary self types](https://github.com/rust-lang/rust/issues/44874) will remove the need for these traits in favour of placing the methods directly on `PyAny`, `PyTuple`, `PyDict`, and so on. These traits are all included in the `pyo3::prelude` module, so with the glob import `use pyo3::prelude::*` the full PyO3 API is made available to downstream code. The following function accesses the first item in the input Python list, using the `.get_item()` method from the `PyListMethods` trait: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn get_first_item<'py>(list: &Bound<'py, PyList>) -> PyResult> { list.get_item(0) } # Python::with_gil(|py| { # let l = PyList::new(py, ["hello world"]).unwrap(); # assert!(get_first_item(&l).unwrap().eq("hello world").unwrap()); # }) ``` ### Casting between Python object types To cast `Bound<'py, T>` smart pointers to some other type, use the [`.downcast()`][PyAnyMethods::downcast] family of functions. This converts `&Bound<'py, T>` to a different `&Bound<'py, U>`, without transferring ownership. There is also [`.downcast_into()`][PyAnyMethods::downcast_into] to convert `Bound<'py, T>` to `Bound<'py, U>` with transfer of ownership. These methods are available for all types `T` which implement the [`PyTypeCheck`] trait. Casting to `Bound<'py, PyAny>` can be done with `.as_any()` or `.into_any()`. For example, the following snippet shows how to cast `Bound<'py, PyAny>` to `Bound<'py, PyTuple>`: ```rust # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = PyTuple::empty(py).into_any(); // use `.downcast()` to cast to `PyTuple` without transferring ownership let _: &Bound<'py, PyTuple> = obj.downcast()?; // use `.downcast_into()` to cast to `PyTuple` with transfer of ownership let _: Bound<'py, PyTuple> = obj.downcast_into()?; # Ok(()) # } # Python::with_gil(example).unwrap() ``` Custom [`#[pyclass]`][pyclass] types implement [`PyTypeCheck`], so `.downcast()` also works for these types. The snippet below is the same as the snippet above casting instead to a custom type `MyClass`: ```rust use pyo3::prelude::*; #[pyclass] struct MyClass {} # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = Bound::new(py, MyClass {})?.into_any(); // use `.downcast()` to cast to `MyClass` without transferring ownership let _: &Bound<'py, MyClass> = obj.downcast()?; // use `.downcast_into()` to cast to `MyClass` with transfer of ownership let _: Bound<'py, MyClass> = obj.downcast_into()?; # Ok(()) # } # Python::with_gil(example).unwrap() ``` ### Extracting Rust data from Python objects To extract Rust data from Python objects, use [`.extract()`][PyAnyMethods::extract] instead of `.downcast()`. This method is available for all types which implement the [`FromPyObject`] trait. For example, the following snippet extracts a Rust tuple of integers from a Python tuple: ```rust # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = PyTuple::new(py, [1, 2, 3])?.into_any(); // extracting the Python `tuple` to a rust `(i32, i32, i32)` tuple let (x, y, z) = obj.extract::<(i32, i32, i32)>()?; assert_eq!((x, y, z), (1, 2, 3)); # Ok(()) # } # Python::with_gil(example).unwrap() ``` To avoid copying data, [`#[pyclass]`][pyclass] types can directly reference Rust data stored within the Python objects without needing to `.extract()`. See the [corresponding documentation in the class section of the guide](./class.md#bound-and-interior-mutability) for more detail. [Bound]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html [`Bound::unbind`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html#method.unbind [Py]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html [PyAnyMethods::add]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.add [PyAnyMethods::extract]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.extract [PyAnyMethods::downcast]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.downcast [PyAnyMethods::downcast_into]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.downcast_into [`PyTypeCheck`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeCheck.html [`PyAnyMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html [`PyDictMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyDictMethods.html [`PyTupleMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyTupleMethods.html [pyclass]: class.md [Borrowed]: {{#PYO3_DOCS_URL}}/pyo3/struct.Borrowed.html [Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html [eval]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval [clone_ref]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html#method.clone_ref [pyo3::types]: {{#PYO3_DOCS_URL}}/pyo3/types/index.html [PyAny]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html [PyList_append]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyList.html#method.append [RefCell]: https://doc.rust-lang.org/std/cell/struct.RefCell.html [smart-pointers]: https://doc.rust-lang.org/book/ch15-00-smart-pointers.html pyo3/guide/src/debugging.md0000644000175000017500000003564315105742312015450 0ustar bdrungbdrung# Debugging ## Macros PyO3's attributes (`#[pyclass]`, `#[pymodule]`, etc.) are [procedural macros](https://doc.rust-lang.org/reference/procedural-macros.html), which means that they rewrite the source of the annotated item. You can view the generated source with the following command, which also expands a few other things: ```bash cargo rustc --profile=check -- -Z unstable-options --pretty=expanded > expanded.rs; rustfmt expanded.rs ``` (You might need to install [rustfmt](https://github.com/rust-lang-nursery/rustfmt) if you don't already have it.) You can also debug classic `!`-macros by adding `-Z trace-macros`: ```bash cargo rustc --profile=check -- -Z unstable-options --pretty=expanded -Z trace-macros > expanded.rs; rustfmt expanded.rs ``` Note that those commands require using the nightly build of rust and may occasionally have bugs. See [cargo expand](https://github.com/dtolnay/cargo-expand) for a more elaborate and stable version of those commands. ## Running with Valgrind Valgrind is a tool to detect memory management bugs such as memory leaks. You first need to install a debug build of Python, otherwise Valgrind won't produce usable results. In Ubuntu there's e.g. a `python3-dbg` package. Activate an environment with the debug interpreter and recompile. If you're on Linux, use `ldd` with the name of your binary and check that you're linking e.g. `libpython3.7d.so.1.0` instead of `libpython3.7.so.1.0`. [Download the suppressions file for CPython](https://raw.githubusercontent.com/python/cpython/master/Misc/valgrind-python.supp). Run Valgrind with `valgrind --suppressions=valgrind-python.supp ./my-command --with-options` ## Getting a stacktrace The best start to investigate a crash such as an segmentation fault is a backtrace. You can set `RUST_BACKTRACE=1` as an environment variable to get the stack trace on a `panic!`. Alternatively you can use a debugger such as `gdb` to explore the issue. Rust provides a wrapper, `rust-gdb`, which has pretty-printers for inspecting Rust variables. Since PyO3 uses `cdylib` for Python shared objects, it does not receive the pretty-print debug hooks in `rust-gdb` ([rust-lang/rust#96365](https://github.com/rust-lang/rust/issues/96365)). The mentioned issue contains a workaround for enabling pretty-printers in this case. * Link against a debug build of python as described in the previous chapter * Run `rust-gdb ` * Set a breakpoint (`b`) on `rust_panic` if you are investigating a `panic!` * Enter `r` to run * After the crash occurred, enter `bt` or `bt full` to print the stacktrace Often it is helpful to run a small piece of Python code to exercise a section of Rust. ```console rust-gdb --args python -c "import my_package; my_package.sum_to_string(1, 2)" ``` ## Setting breakpoints in your Rust code One of the preferred ways by developers to debug their code is by setting breakpoints. This can be achieved in PyO3 by using a debugger like `rust-gdb` or `rust-lldb` with your Python interpreter. For more information about how to use both `lldb` and `gdb` you can read the [gdb to lldb command map](https://lldb.llvm.org/use/map.html) from the lldb documentation. ### Common setup 1. Compile your extension with debug symbols: ```bash # Debug is the default for maturin, but you can explicitly ensure debug symbols with: RUSTFLAGS="-g" maturin develop # For setuptools-rust users: pip install -e . ``` > **Note**: When using debuggers, make sure that `python` resolves to an actual Python binary or symlink and not a shim script. Some tools like pyenv use shim scripts which can interfere with debugging. ### Debugger specific setup Depending on your OS and your preferences you can use two different debuggers, `rust-gdb` or `rust-lldb`. {{#tabs }} {{#tab name="Using rust-gdb" }} 1. Launch rust-gdb with the Python interpreter: ```bash rust-gdb --args python ``` 2. Once in gdb, set a breakpoint in your Rust code: ```bash (gdb) break your_module.rs:42 ``` 3. Run your Python script that imports and uses your Rust extension: ```bash # Option 1: Run an inline Python command (gdb) run -c "import your_module; your_module.your_function()" # Option 2: Run a Python script (gdb) run your_script.py # Option 3: Run pytest tests (gdb) run -m pytest tests/test_something.py::TestName ``` {{#endtab }} {{#tab name="Using rust-lldb (for macOS users)" }} 1. Start rust-lldb with Python: ```bash rust-lldb -- python ``` 2. Set breakpoints in your Rust code: ```bash (lldb) breakpoint set --file your_module.rs --line 42 ``` 3. Run your Python script: ```bash # Option 1: Run an inline Python command (lldb) run -c "import your_module; your_module.your_function()" # Option 2: Run a Python script (lldb) run your_script.py # Option 3: Run pytest tests (lldb) run -m pytest tests/test_something.py::TestName ``` {{#endtab }} {{#endtabs }} ### Using VS Code VS Code with the Rust and Python extensions provides an integrated debugging experience: 1. First, install the necessary VS Code extensions: * [Rust Analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) * [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) * [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) 2. Create a `.vscode/launch.json` file with a configuration that uses the LLDB Debug Launcher: ```json { "version": "0.2.0", "configurations": [ { "name": "Debug PyO3", "type": "lldb", "request": "attach", "program": "${workspaceFolder}/.venv/bin/python", "pid": "${command:pickProcess}", "sourceLanguages": [ "rust" ] }, { "name": "Launch Python with PyO3", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/.venv/bin/python", "args": ["${file}"], "cwd": "${workspaceFolder}", "sourceLanguages": ["rust"] }, { "name": "Debug PyO3 with Args", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/.venv/bin/python", "args": ["path/to/your/script.py", "arg1", "arg2"], "cwd": "${workspaceFolder}", "sourceLanguages": ["rust"] }, { "name": "Debug PyO3 Tests", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/.venv/bin/python", "args": ["-m", "pytest", "tests/your_test.py::test_function", "-v"], "cwd": "${workspaceFolder}", "sourceLanguages": ["rust"] } ] } ``` This configuration supports multiple debugging scenarios: * Attaching to a running Python process * Launching the currently open Python file * Running a specific script with command-line arguments * Running pytest tests 3. Set breakpoints in your Rust code by clicking in the gutter next to line numbers. 4. Start debugging: * For attaching to a running Python process: First start the process, then select the "Debug PyO3" configuration and click Start Debugging (F5). You'll be prompted to select the Python process to attach to. * For launching a Python script: Open your Python script, select the "Launch Python with PyO3" configuration and click Start Debugging (F5). * For running with arguments: Select "Debug PyO3 with Args" (remember to edit the configuration with your actual script path and arguments). * For running tests: Select "Debug PyO3 Tests" (edit the test path as needed). 5. When debugging PyO3 code: * You can inspect Rust variables and data structures * Use the debug console to evaluate expressions * Step through Rust code line by line using the step controls * Set conditional breakpoints for more complex debugging scenarios ### Advanced Debugging Configurations For advanced debugging scenarios, you might want to add environment variables or enable specific Rust debug flags: ```json { "name": "Debug PyO3 with Environment", "type": "lldb", "request": "launch", "program": "${workspaceFolder}/.venv/bin/python", "args": ["${file}"], "env": { "RUST_BACKTRACE": "1", "PYTHONPATH": "${workspaceFolder}" }, "sourceLanguages": ["rust"] } ``` ### Debugging from Jupyter Notebooks For Jupyter Notebooks run from VS Code, you can use the following helper functions to automate the launch configuration: ```python from pathlib import Path import os import json import sys def update_launch_json(vscode_config_file_path=None): """Update VSCode launch.json with the correct Jupyter kernel PID. Args: vscode_config_file_path (str, optional): Path to the .vscode/launch.json file. If not provided, will use the current working directory. """ pid = get_jupyter_kernel_pid() if not pid: print("Could not determine Jupyter kernel PID.") return # Determine launch.json path if vscode_config_file_path: launch_json_path = vscode_config_file_path else: launch_json_path = os.path.join(Path(os.getcwd()), ".vscode", "launch.json") # Get Python interpreter path python_path = sys.executable # Default debugger config debug_config = { "version": "0.2.0", "configurations": [ { "name": "Debug PyO3 (Jupyter)", "type": "lldb", "request": "attach", "program": python_path, "pid": pid, "sourceLanguages": ["rust"], }, { "name": "Launch Python with PyO3", "type": "lldb", "request": "launch", "program": python_path, "args": ["${file}"], "cwd": "${workspaceFolder}", "sourceLanguages": ["rust"] } ], } # Create .vscode directory if it doesn't exist try: os.makedirs(os.path.dirname(launch_json_path), exist_ok=True) # If launch.json already exists, try to update it instead of overwriting if os.path.exists(launch_json_path): try: with open(launch_json_path, "r") as f: existing_config = json.load(f) # Check if our configuration already exists config_exists = False for config in existing_config.get("configurations", []): if config.get("name") == "Debug PyO3 (Jupyter)": config["pid"] = pid config["program"] = python_path config_exists = True if not config_exists: existing_config.setdefault("configurations", []).append(debug_config["configurations"][0]) debug_config = existing_config except Exception: # If reading fails, we'll just overwrite with our new configuration pass with open(launch_json_path, "w") as f: json.dump(debug_config, f, indent=4) print(f"Updated launch.json with PID: {pid} at {launch_json_path}") except Exception as e: print(f"Error updating launch.json: {e}") def get_jupyter_kernel_pid(): """Find the process ID (PID) of the running Jupyter kernel. Returns: int: The process ID of the Jupyter kernel, or None if not found. """ # Check if we're running in a Jupyter environment if 'ipykernel' in sys.modules: pid = os.getpid() print(f"Jupyter kernel PID: {pid}") return pid else: print("Not running in a Jupyter environment.") return None ``` To use these functions: 1. Run the cell containing these functions in your Jupyter notebook 2. Run `update_launch_json()` in a cell 3. In VS Code, select the "Debug PyO3 (Jupyter)" configuration and start debugging ## Thread Safety and Compiler Sanitizers PyO3 attempts to match the Rust language-level guarantees for thread safety, but that does not preclude other code outside of the control of PyO3 or buggy code managed by a PyO3 extension from creating a thread safety issue. Analyzing whether or not a piece of Rust code that uses the CPython C API is thread safe can be quite complicated, since many Python operations can lead to arbitrary Python code execution. Automated ways to discover thread safety issues can often be more fruitful than code analysis. [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html) is a thread safety checking runtime that can be used to detect data races triggered by thread safety bugs or incorrect use of thread-unsafe data structures. While it can only detect data races triggered by code at runtime, if it does detect something the reports often point to exactly where the problem is happening. To use `ThreadSanitizer` with a library that depends on PyO3, you will need to install a nightly Rust toolchain, along with the `rust-src` component, since you will need to compile the Rust standard library: ```bash rustup install nightly rustup override set nighty rustup component add rust-src ``` You will also need a version of CPython compiled using LLVM/Clang with the same major version of LLVM as is currently used to compile nightly Rust. As of March 2025, Rust nightly uses LLVM 20. The [cpython_sanity docker images](https://github.com/nascheme/cpython_sanity) contain a development environment with a pre-compiled version of CPython 3.13 or 3.14 as well as optionally NumPy and SciPy, all compiled using LLVM 20 and ThreadSanitizer. After activating a nightly Rust toolchain, you can build your project using `ThreadSanitizer` with the following command: ```bash RUSTFLAGS="-Zsanitizer=thread" maturin develop -Zbuild-std --target x86_64-unknown-linux-gnu ``` If you are not running on an x86_64 Linux machine, you should replace `x86_64-unknown-linux-gnu` with the [target triple](https://doc.rust-lang.org/rustc/platform-support.html#tier-1-with-host-tools) that is appropriate for your system. You can also replace `maturin develop` with `cargo test` to run `cargo` tests. Note that `cargo` runs tests in a thread pool, so `cargo` tests can be a good way to find thread safety issues. You can also replace `-Zsanitizer=thread` with `-Zsanitizer=address` or any of the other sanitizers that are [supported by Rust](https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html). Note that you'll need to build CPython from source with the appropriate [configure script flags](https://docs.python.org/3/using/configure.html#cmdoption-with-address-sanitizer) to use the same sanitizer environment as you want to use for your Rust code.pyo3/guide/src/function-calls.md0000644000175000017500000000003315105742312016417 0ustar bdrungbdrung# Calling Python functions pyo3/guide/src/ecosystem/0000775000175000017500000000000015105742312015175 5ustar bdrungbdrungpyo3/guide/src/ecosystem/logging.md0000644000175000017500000000617215105742312017151 0ustar bdrungbdrung# Logging It is desirable if both the Python and Rust parts of the application end up logging using the same configuration into the same place. This section of the guide briefly discusses how to connect the two languages' logging ecosystems together. The recommended way for Python extension modules is to configure Rust's logger to send log messages to Python using the `pyo3-log` crate. For users who want to do the opposite and send Python log messages to Rust, see the note at the end of this guide. ## Using `pyo3-log` to send Rust log messages to Python The [pyo3-log] crate allows sending the messages from the Rust side to Python's [logging] system. This is mostly suitable for writing native extensions for Python programs. Use [`pyo3_log::init`][init] to install the logger in its default configuration. It's also possible to tweak its configuration (mostly to tune its performance). ```rust,no_run use log::info; use pyo3::prelude::*; #[pyfunction] fn log_something() { // This will use the logger installed in `my_module` to send the `info` // message to the Python logging facilities. info!("Something!"); } #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { // A good place to install the Rust -> Python logger. pyo3_log::init(); m.add_function(wrap_pyfunction!(log_something, m)?)?; Ok(()) } ``` Then it is up to the Python side to actually output the messages somewhere. ```python import logging import my_module FORMAT = '%(levelname)s %(name)s %(asctime)-15s %(filename)s:%(lineno)d %(message)s' logging.basicConfig(format=FORMAT) logging.getLogger().setLevel(logging.INFO) my_module.log_something() ``` It is important to initialize the Python loggers first, before calling any Rust functions that may log. This limitation can be worked around if it is not possible to satisfy, read the documentation about [caching]. ## The Python to Rust direction To have python logs be handled by Rust, one need only register a rust function to handle logs emitted from the core python logging module. This has been implemented within the [pyo3-pylogger] crate. ```rust,no_run use log::{info, warn}; use pyo3::prelude::*; fn main() -> PyResult<()> { // register the host handler with python logger, providing a logger target // set the name here to something appropriate for your application pyo3_pylogger::register("example_application_py_logger"); // initialize up a logger env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init(); // Log some messages from Rust. info!("Just some normal information!"); warn!("Something spooky happened!"); // Log some messages from Python Python::with_gil(|py| { py.run( " import logging logging.error('Something bad happened') ", None, None, ) }) } ``` [logging]: https://docs.python.org/3/library/logging.html [pyo3-log]: https://crates.io/crates/pyo3-log [init]: https://docs.rs/pyo3-log/*/pyo3_log/fn.init.html [caching]: https://docs.rs/pyo3-log/*/pyo3_log/#performance-filtering-and-caching [pyo3-pylogger]: https://crates.io/crates/pyo3-pylogger pyo3/guide/src/ecosystem/async-await.md0000644000175000017500000000250515105742312017737 0ustar bdrungbdrung# Using `async` and `await` *`async`/`await` support is currently being integrated in PyO3. See the [dedicated documentation](../async-await.md)* If you are working with a Python library that makes use of async functions or wish to provide Python bindings for an async Rust library, [`pyo3-async-runtimes`](https://github.com/PyO3/pyo3-async-runtimes) likely has the tools you need. It provides conversions between async functions in both Python and Rust and was designed with first-class support for popular Rust runtimes such as [`tokio`](https://tokio.rs/) and [`async-std`](https://async.rs/). In addition, all async Python code runs on the default `asyncio` event loop, so `pyo3-async-runtimes` should work just fine with existing Python libraries. ## Additional Information - Managing event loop references can be tricky with `pyo3-async-runtimes`. See [Event Loop References](https://docs.rs/pyo3-async-runtimes/#event-loop-references-and-contextvars) in the API docs to get a better intuition for how event loop references are managed in this library. - Testing `pyo3-async-runtimes` libraries and applications requires a custom test harness since Python requires control over the main thread. You can find a testing guide in the [API docs for the `testing` module](https://docs.rs/pyo3-async-runtimes/latest/pyo3_async_runtimes/testing) pyo3/guide/src/ecosystem/tracing.md0000644000175000017500000001122715105742312017147 0ustar bdrungbdrung# Tracing Python projects that write extension modules for performance reasons may want to tap into [Rust's `tracing` ecosystem] to gain insight into the performance of their extension module. This section of the guide describes a few crates that provide ways to do that. They build on [`tracing_subscriber`][tracing-subscriber] and require code changes in both Python and Rust to integrate. Note that each extension module must configure its own `tracing` integration; one extension module will not see `tracing` data from a different module. ## `pyo3-tracing-subscriber` ([documentation][pyo3-tracing-subscriber-docs]) [`pyo3-tracing-subscriber`][pyo3-tracing-subscriber] provides a way for Python projects to configure `tracing_subscriber`. It exposes a few `tracing_subscriber` layers: - `tracing_subscriber::fmt` for writing human-readable output to file or stdout - `opentelemetry-stdout` for writing OTLP output to file or stdout - `opentelemetry-otlp` for writing OTLP output to an OTLP endpoint The extension module must call [`pyo3_tracing_subscriber::add_submodule`][add-submodule] to export the Python classes needed to configure and initialize `tracing`. On the Python side, use the `Tracing` context manager to initialize tracing and run Rust code inside the context manager's block. `Tracing` takes a `GlobalTracingConfig` instance describing the layers to be used. See [the README on crates.io][pyo3-tracing-subscriber] for example code. ## `pyo3-python-tracing-subscriber` ([documentation][pyo3-python-tracing-subscriber-docs]) The similarly-named [`pyo3-python-tracing-subscriber`][pyo3-python-tracing-subscriber] implements a shim in Rust that forwards `tracing` data to a `Layer` implementation defined in and passed in from Python. There are many ways an extension module could integrate `pyo3-python-tracing-subscriber` but a simple one may look something like this: ```rust,no_run #[tracing::instrument] #[pyfunction] fn fibonacci(index: usize, use_memoized: bool) -> PyResult { // ... } #[pyfunction] pub fn initialize_tracing(py_impl: Bound<'_, PyAny>) { tracing_subscriber::registry() .with(pyo3_python_tracing_subscriber::PythonCallbackLayerBridge::new(py_impl)) .init(); } ``` The extension module must provide some way for Python to pass in one or more Python objects that implement [the `Layer` interface]. Then it should construct [`pyo3_python_tracing_subscriber::PythonCallbackLayerBridge`][PythonCallbackLayerBridge] instances with each of those Python objects and initialize `tracing_subscriber` as shown above. The Python objects implement a modified version of the `Layer` interface: - `on_new_span()` may return some state that will stored inside the Rust span - other callbacks will be given that state as an additional positional argument A dummy `Layer` implementation may look like this: ```python import rust_extension class MyPythonLayer: def __init__(self): pass # `on_new_span` can return some state def on_new_span(self, span_attrs: str, span_id: str) -> int: print(f"[on_new_span]: {span_attrs} | {span_id}") return random.randint(1, 1000) # The state from `on_new_span` is passed back into other trait methods def on_event(self, event: str, state: int): print(f"[on_event]: {event} | {state}") def on_close(self, span_id: str, state: int): print(f"[on_close]: {span_id} | {state}") def on_record(self, span_id: str, values: str, state: int): print(f"[on_record]: {span_id} | {values} | {state}") def main(): rust_extension.initialize_tracing(MyPythonLayer()) print("10th fibonacci number: ", rust_extension.fibonacci(10, True)) ``` `pyo3-python-tracing-subscriber` has [working examples] showing both the Rust side and the Python side of an integration. [pyo3-tracing-subscriber]: https://crates.io/crates/pyo3-tracing-subscriber [pyo3-tracing-subscriber-docs]: https://docs.rs/pyo3-tracing-subscriber [add-submodule]: https://docs.rs/pyo3-tracing-subscriber/*/pyo3_tracing_subscriber/fn.add_submodule.html [pyo3-python-tracing-subscriber]: https://crates.io/crates/pyo3-python-tracing-subscriber [pyo3-python-tracing-subscriber-docs]: https://docs.rs/pyo3-python-tracing-subscriber [PythonCallbackLayerBridge]: https://docs.rs/pyo3-python-tracing-subscriber/*/pyo3_python_tracing_subscriber/struct.PythonCallbackLayerBridge.html [working examples]: https://github.com/getsentry/pyo3-python-tracing-subscriber/tree/main/demo [Rust's `tracing` ecosystem]: https://crates.io/crates/tracing [tracing-subscriber]: https://docs.rs/tracing-subscriber/*/tracing_subscriber/ [the `Layer` interface]: https://docs.rs/tracing-subscriber/*/tracing_subscriber/layer/trait.Layer.html pyo3/guide/src/rust-from-python.md0000644000175000017500000000106315105742312016757 0ustar bdrungbdrung# Using Rust from Python This chapter of the guide is dedicated to explaining how to wrap Rust code into Python objects. PyO3 uses Rust's "procedural macros" to provide a powerful yet simple API to denote what Rust code should map into Python objects. PyO3 can create three types of Python objects: - Python modules, via the `#[pymodule]` macro - Python functions, via the `#[pyfunction]` macro - Python classes, via the `#[pyclass]` macro (plus `#[pymethods]` to define methods for those classes) The following subchapters go through each of these in turn. pyo3/guide/src/function/0000775000175000017500000000000015105742312015007 5ustar bdrungbdrungpyo3/guide/src/function/error-handling.md0000644000175000017500000002154215105742312020246 0ustar bdrungbdrung# Error handling This chapter contains a little background of error handling in Rust and how PyO3 integrates this with Python exceptions. This covers enough detail to create a `#[pyfunction]` which raises Python exceptions from errors originating in Rust. There is a later section of the guide on [Python exceptions](../exception.md) which covers exception types in more detail. ## Representing Python exceptions Rust code uses the generic [`Result`] enum to propagate errors. The error type `E` is chosen by the code author to describe the possible errors which can happen. PyO3 has the [`PyErr`] type which represents a Python exception. If a PyO3 API could result in a Python exception being raised, the return type of that `API` will be [`PyResult`], which is an alias for the type `Result`. In summary: - When Python exceptions are raised and caught by PyO3, the exception will be stored in the `Err` variant of the `PyResult`. - Passing Python exceptions through Rust code then uses all the "normal" techniques such as the `?` operator, with `PyErr` as the error type. - Finally, when a `PyResult` crosses from Rust back to Python via PyO3, if the result is an `Err` variant the contained exception will be raised. (There are many great tutorials on Rust error handling and the `?` operator, so this guide will not go into detail on Rust-specific topics.) ## Raising an exception from a function As indicated in the previous section, when a `PyResult` containing an `Err` crosses from Rust to Python, PyO3 will raise the exception contained within. Accordingly, to raise an exception from a `#[pyfunction]`, change the return type `T` to `PyResult`. When the function returns an `Err` it will raise a Python exception. (Other `Result` types can be used as long as the error `E` has a `From` conversion for `PyErr`, see [custom Rust error types](#custom-rust-error-types) below.) This also works for functions in `#[pymethods]`. For example, the following `check_positive` function raises a `ValueError` when the input is negative: ```rust use pyo3::exceptions::PyValueError; use pyo3::prelude::*; #[pyfunction] fn check_positive(x: i32) -> PyResult<()> { if x < 0 { Err(PyValueError::new_err("x is negative")) } else { Ok(()) } } # # fn main(){ # Python::with_gil(|py|{ # let fun = pyo3::wrap_pyfunction!(check_positive, py).unwrap(); # fun.call1((-1,)).unwrap_err(); # fun.call1((1,)).unwrap(); # }); # } ``` All built-in Python exception types are defined in the [`pyo3::exceptions`] module. They have a `new_err` constructor to directly build a `PyErr`, as seen in the example above. ## Custom Rust error types PyO3 will automatically convert a `Result` returned by a `#[pyfunction]` into a `PyResult` as long as there is an implementation of `std::from::From for PyErr`. Many error types in the Rust standard library have a [`From`] conversion defined in this way. If the type `E` you are handling is defined in a third-party crate, see the section on [foreign rust error types](#foreign-rust-error-types) below for ways to work with this error. The following example makes use of the implementation of `From for PyErr` to raise exceptions encountered when parsing strings as integers: ```rust # use pyo3::prelude::*; use std::num::ParseIntError; #[pyfunction] fn parse_int(x: &str) -> Result { x.parse() } # fn main() { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction!(parse_int, py).unwrap(); # let value: usize = fun.call1(("5",)).unwrap().extract().unwrap(); # assert_eq!(value, 5); # }); # } ``` When passed a string which doesn't contain a floating-point number, the exception raised will look like the below: ```python >>> parse_int("bar") Traceback (most recent call last): File "", line 1, in ValueError: invalid digit found in string ``` As a more complete example, the following snippet defines a Rust error named `CustomIOError`. It then defines a `From for PyErr`, which returns a `PyErr` representing Python's `OSError`. Therefore, it can use this error in the result of a `#[pyfunction]` directly, relying on the conversion if it has to be propagated into a Python exception. ```rust use pyo3::exceptions::PyOSError; use pyo3::prelude::*; use std::fmt; #[derive(Debug)] struct CustomIOError; impl std::error::Error for CustomIOError {} impl fmt::Display for CustomIOError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Oh no!") } } impl std::convert::From for PyErr { fn from(err: CustomIOError) -> PyErr { PyOSError::new_err(err.to_string()) } } pub struct Connection {/* ... */} fn bind(addr: String) -> Result { if &addr == "0.0.0.0" { Err(CustomIOError) } else { Ok(Connection{ /* ... */}) } } #[pyfunction] fn connect(s: String) -> Result<(), CustomIOError> { bind(s)?; // etc. Ok(()) } fn main() { Python::with_gil(|py| { let fun = pyo3::wrap_pyfunction!(connect, py).unwrap(); let err = fun.call1(("0.0.0.0",)).unwrap_err(); assert!(err.is_instance_of::(py)); }); } ``` If lazy construction of the Python exception instance is desired, the [`PyErrArguments`]({{#PYO3_DOCS_URL}}/pyo3/trait.PyErrArguments.html) trait can be implemented instead of `From`. In that case, actual exception argument creation is delayed until the `PyErr` is needed. A final note is that any errors `E` which have a `From` conversion can be used with the `?` ("try") operator with them. An alternative implementation of the above `parse_int` which instead returns `PyResult` is below: ```rust use pyo3::prelude::*; fn parse_int(s: String) -> PyResult { let x = s.parse()?; Ok(x) } # # use pyo3::exceptions::PyValueError; # # fn main() { # Python::with_gil(|py| { # assert_eq!(parse_int(String::from("1")).unwrap(), 1); # assert_eq!(parse_int(String::from("1337")).unwrap(), 1337); # # assert!(parse_int(String::from("-1")) # .unwrap_err() # .is_instance_of::(py)); # assert!(parse_int(String::from("foo")) # .unwrap_err() # .is_instance_of::(py)); # assert!(parse_int(String::from("13.37")) # .unwrap_err() # .is_instance_of::(py)); # }) # } ``` ## Foreign Rust error types The Rust compiler will not permit implementation of traits for types outside of the crate where the type is defined. (This is known as the "orphan rule".) Given a type `OtherError` which is defined in third-party code, there are two main strategies available to integrate it with PyO3: - Create a newtype wrapper, e.g. `MyOtherError`. Then implement `From for PyErr` (or `PyErrArguments`), as well as `From` for `MyOtherError`. - Use Rust's Result combinators such as `map_err` to write code freely to convert `OtherError` into whatever is needed. This requires boilerplate at every usage however gives unlimited flexibility. To detail the newtype strategy a little further, the key trick is to return `Result` from the `#[pyfunction]`. This means that PyO3 will make use of `From for PyErr` to create Python exceptions while the `#[pyfunction]` implementation can use `?` to convert `OtherError` to `MyOtherError` automatically. The following example demonstrates this for some imaginary third-party crate `some_crate` with a function `get_x` returning `Result`: ```rust # mod some_crate { # pub struct OtherError(()); # impl OtherError { # pub fn message(&self) -> &'static str { "some error occurred" } # } # pub fn get_x() -> Result { Ok(5) } # } use pyo3::prelude::*; use pyo3::exceptions::PyValueError; use some_crate::{OtherError, get_x}; struct MyOtherError(OtherError); impl From for PyErr { fn from(error: MyOtherError) -> Self { PyValueError::new_err(error.0.message()) } } impl From for MyOtherError { fn from(other: OtherError) -> Self { Self(other) } } #[pyfunction] fn wrapped_get_x() -> Result { // get_x is a function returning Result let x: i32 = get_x()?; Ok(x) } # fn main() { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction!(wrapped_get_x, py).unwrap(); # let value: usize = fun.call0().unwrap().extract().unwrap(); # assert_eq!(value, 5); # }); # } ``` [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html [`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html [`PyResult`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/type.PyResult.html [`PyErr`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html [`pyo3::exceptions`]: {{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html pyo3/guide/src/function/signature.md0000644000175000017500000002077515105742312017343 0ustar bdrungbdrung# Function signatures The `#[pyfunction]` attribute also accepts parameters to control how the generated Python function accepts arguments. Just like in Python, arguments can be positional-only, keyword-only, or accept either. `*args` lists and `**kwargs` dicts can also be accepted. These parameters also work for `#[pymethods]` which will be introduced in the [Python Classes](../class.md) section of the guide. Like Python, by default PyO3 accepts all arguments as either positional or keyword arguments. All arguments are required by default. This behaviour can be configured by the `#[pyo3(signature = (...))]` option which allows writing a signature in Python syntax. This section of the guide goes into detail about use of the `#[pyo3(signature = (...))]` option and its related option `#[pyo3(text_signature = "...")]` ## Using `#[pyo3(signature = (...))]` For example, below is a function that accepts arbitrary keyword arguments (`**kwargs` in Python syntax) and returns the number that was passed: ```rust,no_run use pyo3::prelude::*; use pyo3::types::PyDict; #[pyfunction] #[pyo3(signature = (**kwds))] fn num_kwds(kwds: Option<&Bound<'_, PyDict>>) -> usize { kwds.map_or(0, |dict| dict.len()) } #[pymodule] fn module_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(num_kwds, m)?) } ``` Just like in Python, the following constructs can be part of the signature:: * `/`: positional-only arguments separator, each parameter defined before `/` is a positional-only parameter. * `*`: var arguments separator, each parameter defined after `*` is a keyword-only parameter. * `*args`: "args" is var args. Type of the `args` parameter has to be `&Bound<'_, PyTuple>`. * `**kwargs`: "kwargs" receives keyword arguments. The type of the `kwargs` parameter has to be `Option<&Bound<'_, PyDict>>`. * `arg=Value`: arguments with default value. If the `arg` argument is defined after var arguments, it is treated as a keyword-only argument. Note that `Value` has to be valid rust code, PyO3 just inserts it into the generated code unmodified. Example: ```rust,no_run # use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; # # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[new] #[pyo3(signature = (num=-1))] fn new(num: i32) -> Self { MyClass { num } } #[pyo3(signature = (num=10, *py_args, name="Hello", **py_kwargs))] fn method( &mut self, num: i32, py_args: &Bound<'_, PyTuple>, name: &str, py_kwargs: Option<&Bound<'_, PyDict>>, ) -> String { let num_before = self.num; self.num = num; format!( "num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} ", num, num_before, py_args, name, py_kwargs, ) } fn make_change(&mut self, num: i32) -> PyResult { self.num = num; Ok(format!("num={}", self.num)) } } ``` Arguments of type `Python` must not be part of the signature: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (lambda))] pub fn simple_python_bound_function(py: Python<'_>, lambda: PyObject) -> PyResult<()> { Ok(()) } ``` N.B. the position of the `/` and `*` arguments (if included) control the system of handling positional and keyword arguments. In Python: ```python import mymodule mc = mymodule.MyClass() print(mc.method(44, False, "World", 666, x=44, y=55)) print(mc.method(num=-1, name="World")) print(mc.make_change(44, False)) ``` Produces output: ```text py_args=('World', 666), py_kwargs=Some({'x': 44, 'y': 55}), name=Hello, num=44 py_args=(), py_kwargs=None, name=World, num=-1 num=44 num=-1 ``` > Note: to use keywords like `struct` as a function argument, use "raw identifier" syntax `r#struct` in both the signature and the function definition: > > ```rust,no_run > # #![allow(dead_code)] > # use pyo3::prelude::*; > #[pyfunction(signature = (r#struct = "foo"))] > fn function_with_keyword(r#struct: &str) { > # let _ = r#struct; > /* ... */ > } > ``` ## Making the function signature available to Python The function signature is exposed to Python via the `__text_signature__` attribute. PyO3 automatically generates this for every `#[pyfunction]` and all `#[pymethods]` directly from the Rust function, taking into account any override done with the `#[pyo3(signature = (...))]` option. This automatic generation can only display the value of default arguments for strings, integers, boolean types, and `None`. Any other default arguments will be displayed as `...`. (`.pyi` type stub files commonly also use `...` for default arguments in the same way.) In cases where the automatically-generated signature needs adjusting, it can [be overridden](#overriding-the-generated-signature) using the `#[pyo3(text_signature)]` option.) The example below creates a function `add` which accepts two positional-only arguments `a` and `b`, where `b` has a default value of zero. ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /))] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # # let inspect = PyModule::import(py, "inspect")?.getattr("signature")?; # let sig: String = inspect # .call1((fun,))? # .call_method0("__str__")? # .extract()?; # # #[cfg(Py_3_8)] // on 3.7 the signature doesn't render b, upstream bug? # assert_eq!(sig, "(a, b=0, /)"); # # Ok(()) # }) # } ``` The following IPython output demonstrates how this generated signature will be seen from Python tooling: ```text >>> pyo3_test.add.__text_signature__ '(a, b=..., /)' >>> pyo3_test.add? Signature: pyo3_test.add(a, b=0, /) Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` ### Overriding the generated signature The `#[pyo3(text_signature = "()")]` attribute can be used to override the default generated signature. In the snippet below, the text signature attribute is used to include the default value of `0` for the argument `b`, instead of the automatically-generated default value of `...`: ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /), text_signature = "(a, b=0, /)")] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # # let inspect = PyModule::import(py, "inspect")?.getattr("signature")?; # let sig: String = inspect # .call1((fun,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(a, b=0, /)"); # # Ok(()) # }) # } ``` PyO3 will include the contents of the annotation unmodified as the `__text_signature__`. Below shows how IPython will now present this (see the default value of 0 for b): ```text >>> pyo3_test.add.__text_signature__ '(a, b=0, /)' >>> pyo3_test.add? Signature: pyo3_test.add(a, b=0, /) Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` If no signature is wanted at all, `#[pyo3(text_signature = None)]` will disable the built-in signature. The snippet below demonstrates use of this: ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /), text_signature = None)] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # assert!(fun.getattr("__text_signature__")?.is_none()); # # Ok(()) # }) # } ``` Now the function's `__text_signature__` will be set to `None`, and IPython will not display any signature in the help: ```text >>> pyo3_test.add.__text_signature__ == None True >>> pyo3_test.add? Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` pyo3/guide/src/migration.md0000644000175000017500000023666515105742312015515 0ustar bdrungbdrung# Migrating from older PyO3 versions This guide can help you upgrade code through breaking changes from one PyO3 version to the next. For a detailed list of all changes, see the [CHANGELOG](changelog.md). ## from 0.24.* to 0.25 ### `AsPyPointer` removal
Click to expand The `AsPyPointer` trait is mostly a leftover from the now removed gil-refs API. The last remaining uses were the GC API, namely `PyVisit::call`, and identity comparison (`PyAnyMethods::is` and `Py::is`). `PyVisit::call` has been updated to take `T: Into>>`, which allows for arguments of type `&Py`, `&Option>` and `Option<&Py>`. It is unlikely any changes are needed here to migrate. `PyAnyMethods::is`/`Py::is` has been updated to take `T: AsRef>>`. Additionally `AsRef>>` implementations were added for `Py`, `Bound` and `Borrowed`. Because of the existing `AsRef> for Bound` implementation this may cause inference issues in non-generic code. This can be easily migrated by switching to `as_any` instead of `as_ref` for these calls.
## from 0.23.* to 0.24
Click to expand There were no significant changes from 0.23 to 0.24 which required documenting in this guide.
## from 0.22.* to 0.23
Click to expand PyO3 0.23 is a significant rework of PyO3's internals for two major improvements: - Support of Python 3.13's new freethreaded build (aka "3.13t") - Rework of to-Python conversions with a new `IntoPyObject` trait. These changes are both substantial and reasonable efforts have been made to allow as much code as possible to continue to work as-is despite the changes. The impacts are likely to be seen in three places when upgrading: - PyO3's data structures [are now thread-safe](#free-threaded-python-support) instead of reliant on the GIL for synchronization. In particular, `#[pyclass]` types are [now required to be `Sync`](./class/thread-safety.md). - The [`IntoPyObject` trait](#new-intopyobject-trait-unifies-to-python-conversions) may need to be implemented for types in your codebase. In most cases this can simply be done with [`#[derive(IntoPyObject)]`](#intopyobject-and-intopyobjectref-derive-macros). There will be many deprecation warnings from the replacement of `IntoPy` and `ToPyObject` traits. - There will be many deprecation warnings from the [final removal of the `gil-refs` feature](#gil-refs-feature-removed), which opened up API space for a cleanup and simplification to PyO3's "Bound" API. The sections below discuss the rationale and details of each change in more depth.
### Free-threaded Python Support
Click to expand PyO3 0.23 introduces initial support for the new free-threaded build of CPython 3.13, aka "3.13t". Because this build allows multiple Python threads to operate simultaneously on underlying Rust data, the `#[pyclass]` macro now requires that types it operates on implement `Sync`. Aside from the change to `#[pyclass]`, most features of PyO3 work unchanged, as the changes have been to the internal data structures to make them thread-safe. An example of this is the `GILOnceCell` type, which used the GIL to synchronize single-initialization. It now uses internal locks to guarantee that only one write ever succeeds, however it allows for multiple racing runs of the initialization closure. It may be preferable to instead use `std::sync::OnceLock` in combination with the `pyo3::sync::OnceLockExt` trait which adds `OnceLock::get_or_init_py_attached` for single-initialization where the initialization closure is guaranteed only ever to run once and without deadlocking with the GIL. Future PyO3 versions will likely add more traits and data structures to make working with free-threaded Python easier. Some features are unaccessible on the free-threaded build: - The `GILProtected` type, which relied on the GIL to expose synchronized access to inner contents - `PyList::get_item_unchecked`, which cannot soundly be used due to races between time-of-check and time-of-use If you make use of these features then you will need to account for the unavailability of the API in the free-threaded build. One way to handle it is via conditional compilation -- extensions can use `pyo3-build-config` to get access to a `#[cfg(Py_GIL_DISABLED)]` guard. See [the guide section on free-threaded Python](free-threading.md) for more details about supporting free-threaded Python in your PyO3 extensions.
### New `IntoPyObject` trait unifies to-Python conversions
Click to expand PyO3 0.23 introduces a new `IntoPyObject` trait to convert Rust types into Python objects which replaces both `IntoPy` and `ToPyObject`. Notable features of this new trait include: - conversions can now return an error - it is designed to work efficiently for both `T` owned types and `&T` references - compared to `IntoPy` the generic `T` moved into an associated type, so - there is now only one way to convert a given type - the output type is stronger typed and may return any Python type instead of just `PyAny` - byte collections are specialized to convert into `PyBytes` now, see [below](#to-python-conversions-changed-for-byte-collections-vecu8-u8-n-and-smallvecu8-n) - `()` (unit) is now only specialized in return position of `#[pyfunction]` and `#[pymethods]` to return `None`, in normal usage it converts into an empty `PyTuple` All PyO3 provided types as well as `#[pyclass]`es already implement `IntoPyObject`. Other types will need to adapt an implementation of `IntoPyObject` to stay compatible with the Python APIs. In many cases the new [`#[derive(IntoPyObject)]`](#intopyobject-and-intopyobjectref-derive-macros) macro can be used instead of [manual implementations](#intopyobject-manual-implementation). Since `IntoPyObject::into_pyobject` may return either a `Bound` or `Borrowed`, you may find the [`BoundObject`](conversions/traits.md#boundobject-for-conversions-that-may-be-bound-or-borrowed) trait to be useful to write code that generically handles either type of smart pointer. Together with the introduction of `IntoPyObject` the old conversion traits `ToPyObject` and `IntoPy` are deprecated and will be removed in a future PyO3 version. #### `IntoPyObject` and `IntoPyObjectRef` derive macros To implement the new trait you may use the new `IntoPyObject` and `IntoPyObjectRef` derive macros as below. ```rust,no_run # use pyo3::prelude::*; #[derive(IntoPyObject, IntoPyObjectRef)] struct Struct { count: usize, obj: Py, } ``` The `IntoPyObjectRef` derive macro derives implementations for references (e.g. for `&Struct` in the example above), which is a replacement for the `ToPyObject` trait. #### `IntoPyObject` manual implementation Before: ```rust,ignore # use pyo3::prelude::*; # #[allow(dead_code)] struct MyPyObjectWrapper(PyObject); impl IntoPy for MyPyObjectWrapper { fn into_py(self, py: Python<'_>) -> PyObject { self.0 } } impl ToPyObject for MyPyObjectWrapper { fn to_object(&self, py: Python<'_>) -> PyObject { self.0.clone_ref(py) } } ``` After: ```rust,no_run # use pyo3::prelude::*; # #[allow(dead_code)] # struct MyPyObjectWrapper(PyObject); impl<'py> IntoPyObject<'py> for MyPyObjectWrapper { type Target = PyAny; // the Python type type Output = Bound<'py, Self::Target>; // in most cases this will be `Bound` type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.into_bound(py)) } } // `ToPyObject` implementations should be converted to implementations on reference types impl<'a, 'py> IntoPyObject<'py> for &'a MyPyObjectWrapper { type Target = PyAny; type Output = Borrowed<'a, 'py, Self::Target>; // `Borrowed` can be used to optimized reference counting type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.bind_borrowed(py)) } } ```
### To-Python conversions changed for byte collections (`Vec`, `[u8; N]` and `SmallVec<[u8; N]>`).
Click to expand With the introduction of the `IntoPyObject` trait, PyO3's macros now prefer `IntoPyObject` implementations over `IntoPy` when producing Python values. This applies to `#[pyfunction]` and `#[pymethods]` return values and also fields accessed via `#[pyo3(get)]`. This change has an effect on functions and methods returning _byte_ collections like - `Vec` - `[u8; N]` - `SmallVec<[u8; N]>` In their new `IntoPyObject` implementation these will now turn into `PyBytes` rather than a `PyList`. All other `T`s are unaffected and still convert into a `PyList`. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] fn foo() -> Vec { // would previously turn into a `PyList`, now `PyBytes` vec![0, 1, 2, 3] } #[pyfunction] fn bar() -> Vec { // unaffected, returns `PyList` vec![0, 1, 2, 3] } ``` If this conversion is _not_ desired, consider building a list manually using `PyList::new`. The following types were previously _only_ implemented for `u8` and now allow other `T`s turn into `PyList`: - `&[T]` - `Cow<[T]>` This is purely additional and should just extend the possible return types.
### `gil-refs` feature removed
Click to expand PyO3 0.23 completes the removal of the "GIL Refs" API in favour of the new "Bound" API introduced in PyO3 0.21. With the removal of the old API, many "Bound" API functions which had been introduced with `_bound` suffixes no longer need the suffixes as these names have been freed up. For example, `PyTuple::new_bound` is now just `PyTuple::new` (the existing name remains but is deprecated). Before: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn main() { # Python::with_gil(|py| { // For example, for PyTuple. Many such APIs have been changed. let tup = PyTuple::new_bound(py, [1, 2, 3]); # }) # } ``` After: ```rust # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn main() { # Python::with_gil(|py| { // For example, for PyTuple. Many such APIs have been changed. let tup = PyTuple::new(py, [1, 2, 3]); # }) # } ``` #### `IntoPyDict` trait adjusted for removal of `gil-refs` As part of this API simplification, the `IntoPyDict` trait has had a small breaking change: `IntoPyDict::into_py_dict_bound` method has been renamed to `IntoPyDict::into_py_dict`. It is also now fallible as part of the `IntoPyObject` trait addition. If you implemented `IntoPyDict` for your type, you should implement `into_py_dict` instead of `into_py_dict_bound`. The old name is still available for calling but deprecated. Before: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::{PyDict, IntoPyDict}; # use std::collections::HashMap; struct MyMap(HashMap); impl IntoPyDict for MyMap where K: ToPyObject, V: ToPyObject, { fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> { let dict = PyDict::new_bound(py); for (key, value) in self.0 { dict.set_item(key, value) .expect("Failed to set_item on dict"); } dict } } ``` After: ```rust,no_run # use pyo3::prelude::*; # use pyo3::types::{PyDict, IntoPyDict}; # use std::collections::HashMap; # #[allow(dead_code)] struct MyMap(HashMap); impl<'py, K, V> IntoPyDict<'py> for MyMap where K: IntoPyObject<'py>, V: IntoPyObject<'py>, { fn into_py_dict(self, py: Python<'py>) -> PyResult> { let dict = PyDict::new(py); for (key, value) in self.0 { dict.set_item(key, value)?; } Ok(dict) } } ```
## from 0.21.* to 0.22 ### Deprecation of `gil-refs` feature continues
Click to expand Following the introduction of the "Bound" API in PyO3 0.21 and the planned removal of the "GIL Refs" API, all functionality related to GIL Refs is now gated behind the `gil-refs` feature and emits a deprecation warning on use. See the 0.21 migration entry for help upgrading.
### Deprecation of implicit default for trailing optional arguments
Click to expand With `pyo3` 0.22 the implicit `None` default for trailing `Option` type argument is deprecated. To migrate, place a `#[pyo3(signature = (...))]` attribute on affected functions or methods and specify the desired behavior. The migration warning specifies the corresponding signature to keep the current behavior. With 0.23 the signature will be required for any function containing `Option` type parameters to prevent accidental and unnoticed changes in behavior. With 0.24 this restriction will be lifted again and `Option` type arguments will be treated as any other argument _without_ special handling. Before: ```rust,no_run # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; #[pyfunction] fn increment(x: u64, amount: Option) -> u64 { x + amount.unwrap_or(1) } ``` After: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (x, amount=None))] fn increment(x: u64, amount: Option) -> u64 { x + amount.unwrap_or(1) } ```
### `Py::clone` is now gated behind the `py-clone` feature
Click to expand If you rely on `impl Clone for Py` to fulfil trait requirements imposed by existing Rust code written without PyO3-based code in mind, the newly introduced feature `py-clone` must be enabled. However, take care to note that the behaviour is different from previous versions. If `Clone` was called without the GIL being held, we tried to delay the application of these reference count increments until PyO3-based code would re-acquire it. This turned out to be impossible to implement in a sound manner and hence was removed. Now, if `Clone` is called without the GIL being held, we panic instead for which calling code might not be prepared. It is advised to migrate off the `py-clone` feature. The simplest way to remove dependency on `impl Clone for Py` is to wrap `Py` as `Arc>` and use cloning of the arc. Related to this, we also added a `pyo3_disable_reference_pool` conditional compilation flag which removes the infrastructure necessary to apply delayed reference count decrements implied by `impl Drop for Py`. They do not appear to be a soundness hazard as they should lead to memory leaks in the worst case. However, the global synchronization adds significant overhead to cross the Python-Rust boundary. Enabling this feature will remove these costs and make the `Drop` implementation abort the process if called without the GIL being held instead.
### Require explicit opt-in for comparison for simple enums
Click to expand With `pyo3` 0.22 the new `#[pyo3(eq)]` options allows automatic implementation of Python equality using Rust's `PartialEq`. Previously simple enums automatically implemented equality in terms of their discriminants. To make PyO3 more consistent, this automatic equality implementation is deprecated in favour of having opt-ins for all `#[pyclass]` types. Similarly, simple enums supported comparison with integers, which is not covered by Rust's `PartialEq` derive, so has been split out into the `#[pyo3(eq_int)]` attribute. To migrate, place a `#[pyo3(eq, eq_int)]` attribute on simple enum classes. Before: ```rust,no_run # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; #[pyclass] enum SimpleEnum { VariantA, VariantB = 42, } ``` After: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum SimpleEnum { VariantA, VariantB = 42, } ```
### `PyType::name` reworked to better match Python `__name__`
Click to expand This function previously would try to read directly from Python type objects' C API field (`tp_name`), in which case it would return a `Cow::Borrowed`. However the contents of `tp_name` don't have well-defined semantics. Instead `PyType::name()` now returns the equivalent of Python `__name__` and returns `PyResult>`. The closest equivalent to PyO3 0.21's version of `PyType::name()` has been introduced as a new function `PyType::fully_qualified_name()`, which is equivalent to `__module__` and `__qualname__` joined as `module.qualname`. Before: ```rust,ignore # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; # use pyo3::types::{PyBool}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let bool_type = py.get_type_bound::(); let name = bool_type.name()?.into_owned(); println!("Hello, {}", name); let mut name_upper = bool_type.name()?; name_upper.to_mut().make_ascii_uppercase(); println!("Hello, {}", name_upper); Ok(()) }) # } ``` After: ```rust,ignore # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::{PyBool}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let bool_type = py.get_type_bound::(); let name = bool_type.name()?; println!("Hello, {}", name); // (if the full dotted path was desired, switch from `name()` to `fully_qualified_name()`) let mut name_upper = bool_type.fully_qualified_name()?.to_string(); name_upper.make_ascii_uppercase(); println!("Hello, {}", name_upper); Ok(()) }) # } ```
## from 0.20.* to 0.21
Click to expand PyO3 0.21 introduces a new `Bound<'py, T>` smart pointer which replaces the existing "GIL Refs" API to interact with Python objects. For example, in PyO3 0.20 the reference `&'py PyAny` would be used to interact with Python objects. In PyO3 0.21 the updated type is `Bound<'py, PyAny>`. Making this change moves Rust ownership semantics out of PyO3's internals and into user code. This change fixes [a known soundness edge case of interaction with gevent](https://github.com/PyO3/pyo3/issues/3668) as well as improves CPU and [memory performance](https://github.com/PyO3/pyo3/issues/1056). For a full history of discussion see https://github.com/PyO3/pyo3/issues/3382. The "GIL Ref" `&'py PyAny` and similar types such as `&'py PyDict` continue to be available as a deprecated API. Due to the advantages of the new API it is advised that all users make the effort to upgrade as soon as possible. In addition to the major API type overhaul, PyO3 has needed to make a few small breaking adjustments to other APIs to close correctness and soundness gaps. The recommended steps to update to PyO3 0.21 is as follows: 1. Enable the `gil-refs` feature to silence deprecations related to the API change 2. Fix all other PyO3 0.21 migration steps 3. Disable the `gil-refs` feature and migrate off the deprecated APIs The following sections are laid out in this order.
### Enable the `gil-refs` feature
Click to expand To make the transition for the PyO3 ecosystem away from the GIL Refs API as smooth as possible, in PyO3 0.21 no APIs consuming or producing GIL Refs have been altered. Instead, variants using `Bound` smart pointers have been introduced, for example `PyTuple::new_bound` which returns `Bound` is the replacement form of `PyTuple::new`. The GIL Ref APIs have been deprecated, but to make migration easier it is possible to disable these deprecation warnings by enabling the `gil-refs` feature. > The one single exception where an existing API was changed in-place is the `pyo3::intern!` macro. Almost all uses of this macro did not need to update code to account it changing to return `&Bound` immediately, and adding an `intern_bound!` replacement was perceived as adding more work for users. It is recommended that users do this as a first step of updating to PyO3 0.21 so that the deprecation warnings do not get in the way of resolving the rest of the migration steps. Before: ```toml # Cargo.toml [dependencies] pyo3 = "0.20" ``` After: ```toml # Cargo.toml [dependencies] pyo3 = { version = "0.21", features = ["gil-refs"] } ```
### `PyTypeInfo` and `PyTryFrom` have been adjusted
Click to expand The `PyTryFrom` trait has aged poorly, its `try_from` method now conflicts with `TryFrom::try_from` in the 2021 edition prelude. A lot of its functionality was also duplicated with `PyTypeInfo`. To tighten up the PyO3 traits as part of the deprecation of the GIL Refs API the `PyTypeInfo` trait has had a simpler companion `PyTypeCheck`. The methods `PyAny::downcast` and `PyAny::downcast_exact` no longer use `PyTryFrom` as a bound, instead using `PyTypeCheck` and `PyTypeInfo` respectively. To migrate, switch all type casts to use `obj.downcast()` instead of `try_from(obj)` (and similar for `downcast_exact`). Before: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # use pyo3::types::{PyInt, PyList}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let list = PyList::new(py, 0..5); let b = ::try_from(list.get_item(0).unwrap())?; Ok(()) }) # } ``` After: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::{PyInt, PyList}; # fn main() -> PyResult<()> { Python::with_gil(|py| { // Note that PyList::new is deprecated for PyList::new_bound as part of the GIL Refs API removal, // see the section below on migration to Bound. #[allow(deprecated)] let list = PyList::new(py, 0..5); let b = list.get_item(0).unwrap().downcast::()?; Ok(()) }) # } ```
### `Iter(A)NextOutput` are deprecated
Click to expand The `__next__` and `__anext__` magic methods can now return any type convertible into Python objects directly just like all other `#[pymethods]`. The `IterNextOutput` used by `__next__` and `IterANextOutput` used by `__anext__` are subsequently deprecated. Most importantly, this change allows returning an awaitable from `__anext__` without non-sensically wrapping it into `Yield` or `Some`. Only the return types `Option` and `Result, E>` are still handled in a special manner where `Some(val)` yields `val` and `None` stops iteration. Starting with an implementation of a Python iterator using `IterNextOutput`, e.g. ```rust,ignore use pyo3::prelude::*; use pyo3::iter::IterNextOutput; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> IterNextOutput { if self.count < 5 { self.count += 1; IterNextOutput::Yield(self.count) } else { IterNextOutput::Return("done") } } } ``` If returning `"done"` via `StopIteration` is not really required, this should be written as ```rust,no_run use pyo3::prelude::*; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> Option { if self.count < 5 { self.count += 1; Some(self.count) } else { None } } } ``` This form also has additional benefits: It has already worked in previous PyO3 versions, it matches the signature of Rust's [`Iterator` trait](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) and it allows using a fast path in CPython which completely avoids the cost of raising a `StopIteration` exception. Note that using [`Option::transpose`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose) and the `Result, E>` variant, this form can also be used to wrap fallible iterators. Alternatively, the implementation can also be done as it would in Python itself, i.e. by "raising" a `StopIteration` exception ```rust,no_run use pyo3::prelude::*; use pyo3::exceptions::PyStopIteration; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> PyResult { if self.count < 5 { self.count += 1; Ok(self.count) } else { Err(PyStopIteration::new_err("done")) } } } ``` Finally, an asynchronous iterator can directly return an awaitable without confusing wrapping ```rust,no_run use pyo3::prelude::*; #[pyclass] struct PyClassAwaitable { number: usize, } #[pymethods] impl PyClassAwaitable { fn __next__(&self) -> usize { self.number } fn __await__(slf: Py) -> Py { slf } } #[pyclass] struct PyClassAsyncIter { number: usize, } #[pymethods] impl PyClassAsyncIter { fn __anext__(&mut self) -> PyClassAwaitable { self.number += 1; PyClassAwaitable { number: self.number, } } fn __aiter__(slf: Py) -> Py { slf } } ```
### `PyType::name` has been renamed to `PyType::qualname`
Click to expand `PyType::name` has been renamed to `PyType::qualname` to indicate that it does indeed return the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name), matching the `__qualname__` attribute. The newly added `PyType::name` yields the full name including the module name now which corresponds to `__module__.__name__` on the level of attributes.
### `PyCell` has been deprecated
Click to expand Interactions with Python objects implemented in Rust no longer need to go though `PyCell`. Instead interactions with Python object now consistently go through `Bound` or `Py` independently of whether `T` is native Python object or a `#[pyclass]` implemented in Rust. Use `Bound::new` or `Py::new` respectively to create and `Bound::borrow(_mut)` / `Py::borrow(_mut)` to borrow the Rust object.
### Migrating from the GIL Refs API to `Bound`
Click to expand To minimise breakage of code using the GIL Refs API, the `Bound` smart pointer has been introduced by adding complements to all functions which accept or return GIL Refs. This allows code to migrate by replacing the deprecated APIs with the new ones. To identify what to migrate, temporarily switch off the `gil-refs` feature to see deprecation warnings on [almost](#cases-where-pyo3-cannot-emit-gil-ref-deprecation-warnings) all uses of APIs accepting and producing GIL Refs . Over one or more PRs it should be possible to follow the deprecation hints to update code. Depending on your development environment, switching off the `gil-refs` feature may introduce [some very targeted breakages](#deactivating-the-gil-refs-feature), so you may need to fixup those first. For example, the following APIs have gained updated variants: - `PyList::new`, `PyTuple::new` and similar constructors have replacements `PyList::new_bound`, `PyTuple::new_bound` etc. - `FromPyObject::extract` has a new `FromPyObject::extract_bound` (see the section below) - The `PyTypeInfo` trait has had new `_bound` methods added to accept / return `Bound`. Because the new `Bound` API brings ownership out of the PyO3 framework and into user code, there are a few places where user code is expected to need to adjust while switching to the new API: - Code will need to add the occasional `&` to borrow the new smart pointer as `&Bound` to pass these types around (or use `.clone()` at the very small cost of increasing the Python reference count) - `Bound` and `Bound` cannot support indexing with `list[0]`, you should use `list.get_item(0)` instead. - `Bound::iter_borrowed` is slightly more efficient than `Bound::iter`. The default iteration of `Bound` cannot return borrowed references because Rust does not (yet) have "lending iterators". Similarly `Bound::get_borrowed_item` is more efficient than `Bound::get_item` for the same reason. - `&Bound` does not implement `FromPyObject` (although it might be possible to do this in the future once the GIL Refs API is completely removed). Use `bound_any.downcast::()` instead of `bound_any.extract::<&Bound>()`. - `Bound::to_str` now borrows from the `Bound` rather than from the `'py` lifetime, so code will need to store the smart pointer as a value in some cases where previously `&PyString` was just used as a temporary. (There are some more details relating to this in [the section below](#deactivating-the-gil-refs-feature).) - `.extract::<&str>()` now borrows from the source Python object. The simplest way to update is to change to `.extract::()`, which retains ownership of the Python reference. See more information [in the section on deactivating the `gil-refs` feature](#deactivating-the-gil-refs-feature). To convert between `&PyAny` and `&Bound` use the `as_borrowed()` method: ```rust,ignore let gil_ref: &PyAny = ...; let bound: &Bound = &gil_ref.as_borrowed(); ``` To convert between `Py` and `Bound` use the `bind()` / `into_bound()` methods, and `as_unbound()` / `unbind()` to go back from `Bound` to `Py`. ```rust,ignore let obj: Py = ...; let bound: &Bound<'py, PyList> = obj.bind(py); let bound: Bound<'py, PyList> = obj.into_bound(py); let obj: &Py = bound.as_unbound(); let obj: Py = bound.unbind(); ```
⚠️ Warning: dangling pointer trap 💣 > Because of the ownership changes, code which uses `.as_ptr()` to convert `&PyAny` and other GIL Refs to a `*mut pyo3_ffi::PyObject` should take care to avoid creating dangling pointers now that `Bound` carries ownership. > > For example, the following pattern with `Option<&PyAny>` can easily create a dangling pointer when migrating to the `Bound` smart pointer: > > ```rust,ignore > let opt: Option<&PyAny> = ...; > let p: *mut ffi::PyObject = opt.map_or(std::ptr::null_mut(), |any| any.as_ptr()); > ``` > > The correct way to migrate this code is to use `.as_ref()` to avoid dropping the `Bound` in the `map_or` closure: > > ```rust,ignore > let opt: Option> = ...; > let p: *mut ffi::PyObject = opt.as_ref().map_or(std::ptr::null_mut(), Bound::as_ptr); > ```
#### Migrating `FromPyObject` implementations `FromPyObject` has had a new method `extract_bound` which takes `&Bound<'py, PyAny>` as an argument instead of `&PyAny`. Both `extract` and `extract_bound` have been given default implementations in terms of the other, to avoid breaking code immediately on update to 0.21. All implementations of `FromPyObject` should be switched from `extract` to `extract_bound`. Before: ```rust,ignore impl<'py> FromPyObject<'py> for MyType { fn extract(obj: &'py PyAny) -> PyResult { /* ... */ } } ``` After: ```rust,ignore impl<'py> FromPyObject<'py> for MyType { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { /* ... */ } } ``` The expectation is that in 0.22 `extract_bound` will have the default implementation removed and in 0.23 `extract` will be removed. #### Cases where PyO3 cannot emit GIL Ref deprecation warnings Despite a large amount of deprecations warnings produced by PyO3 to aid with the transition from GIL Refs to the Bound API, there are a few cases where PyO3 cannot automatically warn on uses of GIL Refs. It is worth checking for these cases manually after the deprecation warnings have all been addressed: - Individual implementations of the `FromPyObject` trait cannot be deprecated, so PyO3 cannot warn about uses of code patterns like `.extract<&PyAny>()` which produce a GIL Ref. - GIL Refs in `#[pyfunction]` arguments emit a warning, but if the GIL Ref is wrapped inside another container such as `Vec<&PyAny>` then PyO3 cannot warn against this. - The `wrap_pyfunction!(function)(py)` deferred argument form of the `wrap_pyfunction` macro taking `py: Python<'py>` produces a GIL Ref, and due to limitations in type inference PyO3 cannot warn against this specific case.
### Deactivating the `gil-refs` feature
Click to expand As a final step of migration, deactivating the `gil-refs` feature will set up code for best performance and is intended to set up a forward-compatible API for PyO3 0.22. At this point code that needed to manage GIL Ref memory can safely remove uses of `GILPool` (which are constructed by calls to `Python::new_pool` and `Python::with_pool`). Deprecation warnings will highlight these cases. There is just one case of code that changes upon disabling these features: `FromPyObject` trait implementations for types that borrow directly from the input data cannot be implemented by PyO3 without GIL Refs (while the GIL Refs API is in the process of being removed). The main types affected are `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>`. To make PyO3's core functionality continue to work while the GIL Refs API is in the process of being removed, disabling the `gil-refs` feature moves the implementations of `FromPyObject` for `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>` to a new temporary trait `FromPyObjectBound`. This trait is the expected future form of `FromPyObject` and has an additional lifetime `'a` to enable these types to borrow data from Python objects. PyO3 0.21 has introduced the [`PyBackedStr`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedStr.html) and [`PyBackedBytes`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedBytes.html) types to help with this case. The easiest way to avoid lifetime challenges from extracting `&str` is to use these. For more complex types like `Vec<&str>`, is now impossible to extract directly from a Python object and `Vec` is the recommended upgrade path. A key thing to note here is because extracting to these types now ties them to the input lifetime, some extremely common patterns may need to be split into multiple Rust lines. For example, the following snippet of calling `.extract::<&str>()` directly on the result of `.getattr()` needs to be adjusted when deactivating the `gil-refs` feature. Before: ```rust,ignore # #[cfg(feature = "gil-refs")] { # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { #[allow(deprecated)] // GIL Ref API let obj: &'py PyType = py.get_type::(); let name: &'py str = obj.getattr("__name__")?.extract()?; assert_eq!(name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); # } ``` After: ```rust,ignore # #[cfg(any(not(Py_LIMITED_API), Py_3_10))] { # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { let obj: Bound<'py, PyType> = py.get_type_bound::(); let name_obj: Bound<'py, PyAny> = obj.getattr("__name__")?; // the lifetime of the data is no longer `'py` but the much shorter // lifetime of the `name_obj` smart pointer above let name: &'_ str = name_obj.extract()?; assert_eq!(name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); # } ``` To avoid needing to worry about lifetimes at all, it is also possible to use the new `PyBackedStr` type, which stores a reference to the Python `str` without a lifetime attachment. In particular, `PyBackedStr` helps for `abi3` builds for Python older than 3.10. Due to limitations in the `abi3` CPython API for those older versions, PyO3 cannot offer a `FromPyObjectBound` implementation for `&str` on those versions. The easiest way to migrate for older `abi3` builds is to replace any cases of `.extract::<&str>()` with `.extract::()`. Alternatively, use `.extract::>()`, `.extract::()` to copy the data into Rust. The following example uses the same snippet as those just above, but this time the final extracted type is `PyBackedStr`: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { use pyo3::pybacked::PyBackedStr; let obj: Bound<'py, PyType> = py.get_type_bound::(); let name: PyBackedStr = obj.getattr("__name__")?.extract()?; assert_eq!(&*name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); ```
## from 0.19.* to 0.20 ### Drop support for older technologies
Click to expand PyO3 0.20 has increased minimum Rust version to 1.56. This enables use of newer language features and simplifies maintenance of the project.
### `PyDict::get_item` now returns a `Result`
Click to expand `PyDict::get_item` in PyO3 0.19 and older was implemented using a Python API which would suppress all exceptions and return `None` in those cases. This included errors in `__hash__` and `__eq__` implementations of the key being looked up. Newer recommendations by the Python core developers advise against using these APIs which suppress exceptions, instead allowing exceptions to bubble upwards. `PyDict::get_item_with_error` already implemented this recommended behavior, so that API has been renamed to `PyDict::get_item`. Before: ```rust,ignore use pyo3::prelude::*; use pyo3::exceptions::PyTypeError; use pyo3::types::{PyDict, IntoPyDict}; # fn main() { # let _ = Python::with_gil(|py| { let dict: &PyDict = [("a", 1)].into_py_dict(py); // `a` is in the dictionary, with value 1 assert!(dict.get_item("a").map_or(Ok(false), |x| x.eq(1))?); // `b` is not in the dictionary assert!(dict.get_item("b").is_none()); // `dict` is not hashable, so this fails with a `TypeError` assert!(dict .get_item_with_error(dict) .unwrap_err() .is_instance_of::(py)); }); # } ``` After: ```rust,ignore use pyo3::prelude::*; use pyo3::exceptions::PyTypeError; use pyo3::types::{PyDict, IntoPyDict}; # fn main() { # let _ = Python::with_gil(|py| -> PyResult<()> { let dict: &PyDict = [("a", 1)].into_py_dict(py); // `a` is in the dictionary, with value 1 assert!(dict.get_item("a")?.map_or(Ok(false), |x| x.eq(1))?); // `b` is not in the dictionary assert!(dict.get_item("b")?.is_none()); // `dict` is not hashable, so this fails with a `TypeError` assert!(dict .get_item(dict) .unwrap_err() .is_instance_of::(py)); Ok(()) }); # } ```
### Required arguments are no longer accepted after optional arguments
Click to expand Trailing `Option` arguments have an automatic default of `None`. To avoid unwanted changes when modifying function signatures, in PyO3 0.18 it was deprecated to have a required argument after an `Option` argument without using `#[pyo3(signature = (...))]` to specify the intended defaults. In PyO3 0.20, this becomes a hard error. Before: ```rust,ignore #[pyfunction] fn x_or_y(x: Option, y: u64) -> u64 { x.unwrap_or(y) } ``` After: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (x, y))] // both x and y have no defaults and are required fn x_or_y(x: Option, y: u64) -> u64 { x.unwrap_or(y) } ```
### Remove deprecated function forms
Click to expand In PyO3 0.18 the `#[args]` attribute for `#[pymethods]`, and directly specifying the function signature in `#[pyfunction]`, was deprecated. This functionality has been removed in PyO3 0.20. Before: ```rust,ignore #[pyfunction] #[pyo3(a, b = "0", "/")] fn add(a: u64, b: u64) -> u64 { a + b } ``` After: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (a, b=0, /))] fn add(a: u64, b: u64) -> u64 { a + b } ```
### `IntoPyPointer` trait removed
Click to expand The trait `IntoPyPointer`, which provided the `into_ptr` method on many types, has been removed. `into_ptr` is now available as an inherent method on all types that previously implemented this trait.
### `AsPyPointer` now `unsafe` trait
Click to expand The trait `AsPyPointer` is now `unsafe trait`, meaning any external implementation of it must be marked as `unsafe impl`, and ensure that they uphold the invariant of returning valid pointers.
## from 0.18.* to 0.19 ### Access to `Python` inside `__traverse__` implementations are now forbidden
Click to expand During `__traverse__` implementations for Python's Garbage Collection it is forbidden to do anything other than visit the members of the `#[pyclass]` being traversed. This means making Python function calls or other API calls are forbidden. Previous versions of PyO3 would allow access to `Python` (e.g. via `Python::with_gil`), which could cause the Python interpreter to crash or otherwise confuse the garbage collection algorithm. Attempts to acquire the GIL will now panic. See [#3165](https://github.com/PyO3/pyo3/issues/3165) for more detail. ```rust,ignore # use pyo3::prelude::*; #[pyclass] struct SomeClass {} impl SomeClass { fn __traverse__(&self, pyo3::class::gc::PyVisit<'_>) -> Result<(), pyo3::class::gc::PyTraverseError>` { Python::with_gil(|| { /*...*/ }) // ERROR: this will panic } } ```
### Smarter `anyhow::Error` / `eyre::Report` conversion when inner error is "simple" `PyErr`
Click to expand When converting from `anyhow::Error` or `eyre::Report` to `PyErr`, if the inner error is a "simple" `PyErr` (with no source error), then the inner error will be used directly as the `PyErr` instead of wrapping it in a new `PyRuntimeError` with the original information converted into a string. ```rust,ignore # #[cfg(feature = "anyhow")] # #[allow(dead_code)] # mod anyhow_only { # use pyo3::prelude::*; # use pyo3::exceptions::PyValueError; #[pyfunction] fn raise_err() -> anyhow::Result<()> { Err(PyValueError::new_err("original error message").into()) } fn main() { Python::with_gil(|py| { let rs_func = wrap_pyfunction!(raise_err, py).unwrap(); pyo3::py_run!( py, rs_func, r" try: rs_func() except Exception as e: print(repr(e)) " ); }) } # } ``` Before, the above code would have printed `RuntimeError('ValueError: original error message')`, which might be confusing. After, the same code will print `ValueError: original error message`, which is more straightforward. However, if the `anyhow::Error` or `eyre::Report` has a source, then the original exception will still be wrapped in a `PyRuntimeError`.
### The deprecated `Python::acquire_gil` was removed and `Python::with_gil` must be used instead
Click to expand While the API provided by [`Python::acquire_gil`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html#method.acquire_gil) seems convenient, it is somewhat brittle as the design of the GIL token [`Python`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html) relies on proper nesting and panics if not used correctly, e.g. ```rust,ignore # #![allow(dead_code, deprecated)] # use pyo3::prelude::*; #[pyclass] struct SomeClass {} struct ObjectAndGuard { object: Py, guard: GILGuard, } impl ObjectAndGuard { fn new() -> Self { let guard = Python::acquire_gil(); let object = Py::new(guard.python(), SomeClass {}).unwrap(); Self { object, guard } } } let first = ObjectAndGuard::new(); let second = ObjectAndGuard::new(); // Panics because the guard within `second` is still alive. drop(first); drop(second); ``` The replacement is [`Python::with_gil`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html#method.with_gil) which is more cumbersome but enforces the proper nesting by design, e.g. ```rust,ignore # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] struct SomeClass {} struct Object { object: Py, } impl Object { fn new(py: Python<'_>) -> Self { let object = Py::new(py, SomeClass {}).unwrap(); Self { object } } } // It either forces us to release the GIL before acquiring it again. let first = Python::with_gil(|py| Object::new(py)); let second = Python::with_gil(|py| Object::new(py)); drop(first); drop(second); // Or it ensures releasing the inner lock before the outer one. Python::with_gil(|py| { let first = Object::new(py); let second = Python::with_gil(|py| Object::new(py)); drop(first); drop(second); }); ``` Furthermore, `Python::acquire_gil` provides ownership of a `GILGuard` which can be freely stored and passed around. This is usually not helpful as it may keep the lock held for a long time thereby blocking progress in other parts of the program. Due to the generative lifetime attached to the GIL token supplied by `Python::with_gil`, the problem is avoided as the GIL token can only be passed down the call chain. Often, this issue can also be avoided entirely as any GIL-bound reference `&'py PyAny` implies access to a GIL token `Python<'py>` via the [`PyAny::py`](https://docs.rs/pyo3/0.22.5/pyo3/types/struct.PyAny.html#method.py) method.
## from 0.17.* to 0.18 ### Required arguments after `Option<_>` arguments will no longer be automatically inferred
Click to expand In `#[pyfunction]` and `#[pymethods]`, if a "required" function input such as `i32` came after an `Option<_>` input, then the `Option<_>` would be implicitly treated as required. (All trailing `Option<_>` arguments were treated as optional with a default value of `None`). Starting with PyO3 0.18, this is deprecated and a future PyO3 version will require a [`#[pyo3(signature = (...))]` option](./function/signature.md) to explicitly declare the programmer's intention. Before, x in the below example would be required to be passed from Python code: ```rust,compile_fail,ignore # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] fn required_argument_after_option(x: Option, y: i32) {} ``` After, specify the intended Python signature explicitly: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; // If x really was intended to be required #[pyfunction(signature = (x, y))] fn required_argument_after_option_a(x: Option, y: i32) {} // If x was intended to be optional, y needs a default too #[pyfunction(signature = (x=None, y=0))] fn required_argument_after_option_b(x: Option, y: i32) {} ```
### `__text_signature__` is now automatically generated for `#[pyfunction]` and `#[pymethods]`
Click to expand The [`#[pyo3(text_signature = "...")]` option](./function/signature.md#making-the-function-signature-available-to-python) was previously the only supported way to set the `__text_signature__` attribute on generated Python functions. PyO3 is now able to automatically populate `__text_signature__` for all functions automatically based on their Rust signature (or the [new `#[pyo3(signature = (...))]` option](./function/signature.md)). These automatically-generated `__text_signature__` values will currently only render `...` for all default values. Many `#[pyo3(text_signature = "...")]` options can be removed from functions when updating to PyO3 0.18, however in cases with default values a manual implementation may still be preferred for now. As examples: ```rust # use pyo3::prelude::*; // The `text_signature` option here is no longer necessary, as PyO3 will automatically // generate exactly the same value. #[pyfunction(text_signature = "(a, b, c)")] fn simple_function(a: i32, b: i32, c: i32) {} // The `text_signature` still provides value here as of PyO3 0.18, because the automatically // generated signature would be "(a, b=..., c=...)". #[pyfunction(signature = (a, b = 1, c = 2), text_signature = "(a, b=1, c=2)")] fn function_with_defaults(a: i32, b: i32, c: i32) {} # fn main() { # Python::with_gil(|py| { # let simple = wrap_pyfunction!(simple_function, py).unwrap(); # assert_eq!(simple.getattr("__text_signature__").unwrap().to_string(), "(a, b, c)"); # let defaulted = wrap_pyfunction!(function_with_defaults, py).unwrap(); # assert_eq!(defaulted.getattr("__text_signature__").unwrap().to_string(), "(a, b=1, c=2)"); # }) # } ```
## from 0.16.* to 0.17 ### Type checks have been changed for `PyMapping` and `PySequence` types
Click to expand Previously the type checks for `PyMapping` and `PySequence` (implemented in `PyTryFrom`) used the Python C-API functions `PyMapping_Check` and `PySequence_Check`. Unfortunately these functions are not sufficient for distinguishing such types, leading to inconsistent behavior (see [pyo3/pyo3#2072](https://github.com/PyO3/pyo3/issues/2072)). PyO3 0.17 changes these downcast checks to explicitly test if the type is a subclass of the corresponding abstract base class `collections.abc.Mapping` or `collections.abc.Sequence`. Note this requires calling into Python, which may incur a performance penalty over the previous method. If this performance penalty is a problem, you may be able to perform your own checks and use `try_from_unchecked` (unsafe). Another side-effect is that a pyclass defined in Rust with PyO3 will need to be _registered_ with the corresponding Python abstract base class for downcasting to succeed. `PySequence::register` and `PyMapping:register` have been added to make it easy to do this from Rust code. These are equivalent to calling `collections.abc.Mapping.register(MappingPyClass)` or `collections.abc.Sequence.register(SequencePyClass)` from Python. For example, for a mapping class defined in Rust: ```rust,compile_fail use pyo3::prelude::*; use std::collections::HashMap; #[pyclass(mapping)] struct Mapping { index: HashMap, } #[pymethods] impl Mapping { #[new] fn new(elements: Option<&PyList>) -> PyResult { // ... // truncated implementation of this mapping pyclass - basically a wrapper around a HashMap } ``` You must register the class with `collections.abc.Mapping` before the downcast will work: ```rust,compile_fail let m = Py::new(py, Mapping { index }).unwrap(); assert!(m.as_ref(py).downcast::().is_err()); PyMapping::register::(py).unwrap(); assert!(m.as_ref(py).downcast::().is_ok()); ``` Note that this requirement may go away in the future when a pyclass is able to inherit from the abstract base class directly (see [pyo3/pyo3#991](https://github.com/PyO3/pyo3/issues/991)).
### The `multiple-pymethods` feature now requires Rust 1.62
Click to expand Due to limitations in the `inventory` crate which the `multiple-pymethods` feature depends on, this feature now requires Rust 1.62. For more information see [dtolnay/inventory#32](https://github.com/dtolnay/inventory/issues/32).
### Added `impl IntoPy> for &str`
Click to expand This may cause inference errors. Before: ```rust,compile_fail # use pyo3::prelude::*; # # fn main() { Python::with_gil(|py| { // Cannot infer either `Py` or `Py` let _test = "test".into_py(py); }); # } ``` After, some type annotations may be necessary: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # # fn main() { Python::with_gil(|py| { let _test: Py = "test".into_py(py); }); # } ```
### The `pyproto` feature is now disabled by default
Click to expand In preparation for removing the deprecated `#[pyproto]` attribute macro in a future PyO3 version, it is now gated behind an opt-in feature flag. This also gives a slight saving to compile times for code which does not use the deprecated macro.
### `PyTypeObject` trait has been deprecated
Click to expand The `PyTypeObject` trait already was near-useless; almost all functionality was already on the `PyTypeInfo` trait, which `PyTypeObject` had a blanket implementation based upon. In PyO3 0.17 the final method, `PyTypeObject::type_object` was moved to `PyTypeInfo::type_object`. To migrate, update trait bounds and imports from `PyTypeObject` to `PyTypeInfo`. Before: ```rust,ignore use pyo3::Python; use pyo3::type_object::PyTypeObject; use pyo3::types::PyType; fn get_type_object(py: Python<'_>) -> &PyType { T::type_object(py) } ``` After ```rust,ignore use pyo3::{Python, PyTypeInfo}; use pyo3::types::PyType; fn get_type_object(py: Python<'_>) -> &PyType { T::type_object(py) } # Python::with_gil(|py| { get_type_object::(py); }); ```
### `impl IntoPy for [T; N]` now requires `T: IntoPy` rather than `T: ToPyObject`
Click to expand If this leads to errors, simply implement `IntoPy`. Because pyclasses already implement `IntoPy`, you probably don't need to worry about this.
### Each `#[pymodule]` can now only be initialized once per process
Click to expand To make PyO3 modules sound in the presence of Python sub-interpreters, for now it has been necessary to explicitly disable the ability to initialize a `#[pymodule]` more than once in the same process. Attempting to do this will now raise an `ImportError`.
## from 0.15.* to 0.16 ### Drop support for older technologies
Click to expand PyO3 0.16 has increased minimum Rust version to 1.48 and minimum Python version to 3.7. This enables use of newer language features (enabling some of the other additions in 0.16) and simplifies maintenance of the project.
### `#[pyproto]` has been deprecated
Click to expand In PyO3 0.15, the `#[pymethods]` attribute macro gained support for implementing "magic methods" such as `__str__` (aka "dunder" methods). This implementation was not quite finalized at the time, with a few edge cases to be decided upon. The existing `#[pyproto]` attribute macro was left untouched, because it covered these edge cases. In PyO3 0.16, the `#[pymethods]` implementation has been completed and is now the preferred way to implement magic methods. To allow the PyO3 project to move forward, `#[pyproto]` has been deprecated (with expected removal in PyO3 0.18). Migration from `#[pyproto]` to `#[pymethods]` is straightforward; copying the existing methods directly from the `#[pyproto]` trait implementation is all that is needed in most cases. Before: ```rust,compile_fail use pyo3::prelude::*; use pyo3::class::{PyObjectProtocol, PyIterProtocol}; use pyo3::types::PyString; #[pyclass] struct MyClass {} #[pyproto] impl PyObjectProtocol for MyClass { fn __str__(&self) -> &'static [u8] { b"hello, world" } } #[pyproto] impl PyIterProtocol for MyClass { fn __iter__(slf: PyRef) -> PyResult<&PyAny> { PyString::new(slf.py(), "hello, world").iter() } } ``` After ```rust,compile_fail use pyo3::prelude::*; use pyo3::types::PyString; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { fn __str__(&self) -> &'static [u8] { b"hello, world" } fn __iter__(slf: PyRef) -> PyResult<&PyAny> { PyString::new(slf.py(), "hello, world").iter() } } ```
### Removed `PartialEq` for object wrappers
Click to expand The Python object wrappers `Py` and `PyAny` had implementations of `PartialEq` so that `object_a == object_b` would compare the Python objects for pointer equality, which corresponds to the `is` operator, not the `==` operator in Python. This has been removed in favor of a new method: use `object_a.is(object_b)`. This also has the advantage of not requiring the same wrapper type for `object_a` and `object_b`; you can now directly compare a `Py` with a `&PyAny` without having to convert. To check for Python object equality (the Python `==` operator), use the new method `eq()`.
### Container magic methods now match Python behavior
Click to expand In PyO3 0.15, `__getitem__`, `__setitem__` and `__delitem__` in `#[pymethods]` would generate only the _mapping_ implementation for a `#[pyclass]`. To match the Python behavior, these methods now generate both the _mapping_ **and** _sequence_ implementations. This means that classes implementing these `#[pymethods]` will now also be treated as sequences, same as a Python `class` would be. Small differences in behavior may result: - PyO3 will allow instances of these classes to be cast to `PySequence` as well as `PyMapping`. - Python will provide a default implementation of `__iter__` (if the class did not have one) which repeatedly calls `__getitem__` with integers (starting at 0) until an `IndexError` is raised. To explain this in detail, consider the following Python class: ```python class ExampleContainer: def __len__(self): return 5 def __getitem__(self, idx: int) -> int: if idx < 0 or idx > 5: raise IndexError() return idx ``` This class implements a Python [sequence](https://docs.python.org/3/glossary.html#term-sequence). The `__len__` and `__getitem__` methods are also used to implement a Python [mapping](https://docs.python.org/3/glossary.html#term-mapping). In the Python C-API, these methods are not shared: the sequence `__len__` and `__getitem__` are defined by the `sq_length` and `sq_item` slots, and the mapping equivalents are `mp_length` and `mp_subscript`. There are similar distinctions for `__setitem__` and `__delitem__`. Because there is no such distinction from Python, implementing these methods will fill the mapping and sequence slots simultaneously. A Python class with `__len__` implemented, for example, will have both the `sq_length` and `mp_length` slots filled. The PyO3 behavior in 0.16 has been changed to be closer to this Python behavior by default.
### `wrap_pymodule!` and `wrap_pyfunction!` now respect privacy correctly
Click to expand Prior to PyO3 0.16 the `wrap_pymodule!` and `wrap_pyfunction!` macros could use modules and functions whose defining `fn` was not reachable according Rust privacy rules. For example, the following code was legal before 0.16, but in 0.16 is rejected because the `wrap_pymodule!` macro cannot access the `private_submodule` function: ```rust,compile_fail mod foo { use pyo3::prelude::*; #[pymodule] fn private_submodule(_py: Python<'_>, m: &PyModule) -> PyResult<()> { Ok(()) } } use pyo3::prelude::*; use foo::*; #[pymodule] fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(private_submodule))?; Ok(()) } ``` To fix it, make the private submodule visible, e.g. with `pub` or `pub(crate)`. ```rust,ignore mod foo { use pyo3::prelude::*; #[pymodule] pub(crate) fn private_submodule(_py: Python<'_>, m: &PyModule) -> PyResult<()> { Ok(()) } } use pyo3::prelude::*; use pyo3::wrap_pymodule; use foo::*; #[pymodule] fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(private_submodule))?; Ok(()) } ```
## from 0.14.* to 0.15 ### Changes in sequence indexing
Click to expand For all types that take sequence indices (`PyList`, `PyTuple` and `PySequence`), the API has been made consistent to only take `usize` indices, for consistency with Rust's indexing conventions. Negative indices, which were only sporadically supported even in APIs that took `isize`, now aren't supported anywhere. Further, the `get_item` methods now always return a `PyResult` instead of panicking on invalid indices. The `Index` trait has been implemented instead, and provides the same panic behavior as on Rust vectors. Note that *slice* indices (accepted by `PySequence::get_slice` and other) still inherit the Python behavior of clamping the indices to the actual length, and not panicking/returning an error on out of range indices. An additional advantage of using Rust's indexing conventions for these types is that these types can now also support Rust's indexing operators as part of a consistent API: ```rust,ignore #![allow(deprecated)] use pyo3::{Python, types::PyList}; Python::with_gil(|py| { let list = PyList::new(py, &[1, 2, 3]); assert_eq!(list[0..2].to_string(), "[1, 2]"); }); ```
## from 0.13.* to 0.14 ### `auto-initialize` feature is now opt-in
Click to expand For projects embedding Python in Rust, PyO3 no longer automatically initializes a Python interpreter on the first call to `Python::with_gil` (or `Python::acquire_gil`) unless the [`auto-initialize` feature](features.md#auto-initialize) is enabled.
### New `multiple-pymethods` feature
Click to expand `#[pymethods]` have been reworked with a simpler default implementation which removes the dependency on the `inventory` crate. This reduces dependencies and compile times for the majority of users. The limitation of the new default implementation is that it cannot support multiple `#[pymethods]` blocks for the same `#[pyclass]`. If you need this functionality, you must enable the `multiple-pymethods` feature which will switch `#[pymethods]` to the inventory-based implementation.
### Deprecated `#[pyproto]` methods
Click to expand Some protocol (aka `__dunder__`) methods such as `__bytes__` and `__format__` have been possible to implement two ways in PyO3 for some time: via a `#[pyproto]` (e.g. `PyObjectProtocol` for the methods listed here), or by writing them directly in `#[pymethods]`. This is only true for a handful of the `#[pyproto]` methods (for technical reasons to do with the way PyO3 currently interacts with the Python C-API). In the interest of having only one way to do things, the `#[pyproto]` forms of these methods have been deprecated. To migrate just move the affected methods from a `#[pyproto]` to a `#[pymethods]` block. Before: ```rust,compile_fail use pyo3::prelude::*; use pyo3::class::basic::PyObjectProtocol; #[pyclass] struct MyClass {} #[pyproto] impl PyObjectProtocol for MyClass { fn __bytes__(&self) -> &'static [u8] { b"hello, world" } } ``` After: ```rust,no_run use pyo3::prelude::*; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { fn __bytes__(&self) -> &'static [u8] { b"hello, world" } } ```
## from 0.12.* to 0.13 ### Minimum Rust version increased to Rust 1.45
Click to expand PyO3 `0.13` makes use of new Rust language features stabilized between Rust 1.40 and Rust 1.45. If you are using a Rust compiler older than Rust 1.45, you will need to update your toolchain to be able to continue using PyO3.
### Runtime changes to support the CPython limited API
Click to expand In PyO3 `0.13` support was added for compiling against the CPython limited API. This had a number of implications for _all_ PyO3 users, described here. The largest of these is that all types created from PyO3 are what CPython calls "heap" types. The specific implications of this are: - If you wish to subclass one of these types _from Rust_ you must mark it `#[pyclass(subclass)]`, as you would if you wished to allow subclassing it from Python code. - Type objects are now mutable - Python code can set attributes on them. - `__module__` on types without `#[pyclass(module="mymodule")]` no longer returns `builtins`, it now raises `AttributeError`.
## from 0.11.* to 0.12 ### `PyErr` has been reworked
Click to expand In PyO3 `0.12` the `PyErr` type has been re-implemented to be significantly more compatible with the standard Rust error handling ecosystem. Specifically `PyErr` now implements `Error + Send + Sync`, which are the standard traits used for error types. While this has necessitated the removal of a number of APIs, the resulting `PyErr` type should now be much more easier to work with. The following sections list the changes in detail and how to migrate to the new APIs.
#### `PyErr::new` and `PyErr::from_type` now require `Send + Sync` for their argument
Click to expand For most uses no change will be needed. If you are trying to construct `PyErr` from a value that is not `Send + Sync`, you will need to first create the Python object and then use `PyErr::from_instance`. Similarly, any types which implemented `PyErrArguments` will now need to be `Send + Sync`.
#### `PyErr`'s contents are now private
Click to expand It is no longer possible to access the fields `.ptype`, `.pvalue` and `.ptraceback` of a `PyErr`. You should instead now use the new methods `PyErr::ptype`, `PyErr::pvalue` and `PyErr::ptraceback`.
#### `PyErrValue` and `PyErr::from_value` have been removed
Click to expand As these were part the internals of `PyErr` which have been reworked, these APIs no longer exist. If you used this API, it is recommended to use `PyException::new_err` (see [the section on Exception types](#exception-types-have-been-reworked)).
#### `Into>` for `PyErr` has been removed
Click to expand This implementation was redundant. Just construct the `Result::Err` variant directly. Before: ```rust,compile_fail let result: PyResult<()> = PyErr::new::("error message").into(); ``` After (also using the new reworked exception types; see the following section): ```rust,no_run # use pyo3::{PyResult, exceptions::PyTypeError}; let result: PyResult<()> = Err(PyTypeError::new_err("error message")); ```
### Exception types have been reworked
Click to expand Previously exception types were zero-sized marker types purely used to construct `PyErr`. In PyO3 0.12, these types have been replaced with full definitions and are usable in the same way as `PyAny`, `PyDict` etc. This makes it possible to interact with Python exception objects. The new types also have names starting with the "Py" prefix. For example, before: ```rust,ignore let err: PyErr = TypeError::py_err("error message"); ``` After: ```rust,ignore # use pyo3::{PyErr, PyResult, Python, type_object::PyTypeObject}; # use pyo3::exceptions::{PyBaseException, PyTypeError}; # Python::with_gil(|py| -> PyResult<()> { let err: PyErr = PyTypeError::new_err("error message"); // Uses Display for PyErr, new for PyO3 0.12 assert_eq!(err.to_string(), "TypeError: error message"); // Now possible to interact with exception instances, new for PyO3 0.12 let instance: &PyBaseException = err.instance(py); assert_eq!( instance.getattr("__class__")?, PyTypeError::type_object(py).as_ref() ); # Ok(()) # }).unwrap(); ```
### `FromPy` has been removed
Click to expand To simplify the PyO3 conversion traits, the `FromPy` trait has been removed. Previously there were two ways to define the to-Python conversion for a type: `FromPy for PyObject` and `IntoPy for T`. Now there is only one way to define the conversion, `IntoPy`, so downstream crates may need to adjust accordingly. Before: ```rust,compile_fail # use pyo3::prelude::*; struct MyPyObjectWrapper(PyObject); impl FromPy for PyObject { fn from_py(other: MyPyObjectWrapper, _py: Python<'_>) -> Self { other.0 } } ``` After ```rust,ignore # use pyo3::prelude::*; # #[allow(dead_code)] struct MyPyObjectWrapper(PyObject); # #[allow(deprecated)] impl IntoPy for MyPyObjectWrapper { fn into_py(self, _py: Python<'_>) -> PyObject { self.0 } } ``` Similarly, code which was using the `FromPy` trait can be trivially rewritten to use `IntoPy`. Before: ```rust,compile_fail # use pyo3::prelude::*; # Python::with_gil(|py| { let obj = PyObject::from_py(1.234, py); # }) ``` After: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # Python::with_gil(|py| { let obj: PyObject = 1.234.into_py(py); # }) ```
### `PyObject` is now a type alias of `Py`
Click to expand This should change very little from a usage perspective. If you implemented traits for both `PyObject` and `Py`, you may find you can just remove the `PyObject` implementation.
### `AsPyRef` has been removed
Click to expand As `PyObject` has been changed to be just a type alias, the only remaining implementor of `AsPyRef` was `Py`. This removed the need for a trait, so the `AsPyRef::as_ref` method has been moved to `Py::as_ref`. This should require no code changes except removing `use pyo3::AsPyRef` for code which did not use `pyo3::prelude::*`. Before: ```rust,ignore use pyo3::{AsPyRef, Py, types::PyList}; # pyo3::Python::with_gil(|py| { let list_py: Py = PyList::empty(py).into(); let list_ref: &PyList = list_py.as_ref(py); # }) ``` After: ```rust,ignore use pyo3::{Py, types::PyList}; # pyo3::Python::with_gil(|py| { let list_py: Py = PyList::empty(py).into(); let list_ref: &PyList = list_py.as_ref(py); # }) ```
## from 0.10.* to 0.11 ### Stable Rust
Click to expand PyO3 now supports the stable Rust toolchain. The minimum required version is 1.39.0.
### `#[pyclass]` structs must now be `Send` or `unsendable`
Click to expand Because `#[pyclass]` structs can be sent between threads by the Python interpreter, they must implement `Send` or declared as `unsendable` (by `#[pyclass(unsendable)]`). Note that `unsendable` is added in PyO3 `0.11.1` and `Send` is always required in PyO3 `0.11.0`. This may "break" some code which previously was accepted, even though it could be unsound. There can be two fixes: 1. If you think that your `#[pyclass]` actually must be `Send`able, then let's implement `Send`. A common, safer way is using thread-safe types. E.g., `Arc` instead of `Rc`, `Mutex` instead of `RefCell`, and `Box` instead of `Box`. Before: ```rust,compile_fail use pyo3::prelude::*; use std::rc::Rc; use std::cell::RefCell; #[pyclass] struct NotThreadSafe { shared_bools: Rc>>, closure: Box, } ``` After: ```rust,ignore # #![allow(dead_code)] use pyo3::prelude::*; use std::sync::{Arc, Mutex}; #[pyclass] struct ThreadSafe { shared_bools: Arc>>, closure: Box, } ``` In situations where you cannot change your `#[pyclass]` to automatically implement `Send` (e.g., when it contains a raw pointer), you can use `unsafe impl Send`. In such cases, care should be taken to ensure the struct is actually thread safe. See [the Rustonomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html) for more. 2. If you think that your `#[pyclass]` should not be accessed by another thread, you can use `unsendable` flag. A class marked with `unsendable` panics when accessed by another thread, making it thread-safe to expose an unsendable object to the Python interpreter. Before: ```rust,compile_fail use pyo3::prelude::*; #[pyclass] struct Unsendable { pointers: Vec<*mut std::os::raw::c_char>, } ``` After: ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; #[pyclass(unsendable)] struct Unsendable { pointers: Vec<*mut std::os::raw::c_char>, } ```
### All `PyObject` and `Py` methods now take `Python` as an argument
Click to expand Previously, a few methods such as `Object::get_refcnt` did not take `Python` as an argument (to ensure that the Python GIL was held by the current thread). Technically, this was not sound. To migrate, just pass a `py` argument to any calls to these methods. Before: ```rust,compile_fail # pyo3::Python::with_gil(|py| { py.None().get_refcnt(); # }) ``` After: ```rust # pyo3::Python::with_gil(|py| { py.None().get_refcnt(py); # }) ```
## from 0.9.* to 0.10 ### `ObjectProtocol` is removed
Click to expand All methods are moved to [`PyAny`]. And since now all native types (e.g., `PyList`) implements `Deref`, all you need to do is remove `ObjectProtocol` from your code. Or if you use `ObjectProtocol` by `use pyo3::prelude::*`, you have to do nothing. Before: ```rust,compile_fail,ignore use pyo3::ObjectProtocol; # pyo3::Python::with_gil(|py| { let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap(); let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap(); assert_eq!(hi.len().unwrap(), 5); # }) ``` After: ```rust,ignore # pyo3::Python::with_gil(|py| { let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap(); let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap(); assert_eq!(hi.len().unwrap(), 5); # }) ```
### No `#![feature(specialization)]` in user code
Click to expand While PyO3 itself still requires specialization and nightly Rust, now you don't have to use `#![feature(specialization)]` in your crate.
## from 0.8.* to 0.9 ### `#[new]` interface
Click to expand [`PyRawObject`](https://docs.rs/pyo3/0.8.5/pyo3/type_object/struct.PyRawObject.html) is now removed and our syntax for constructors has changed. Before: ```rust,compile_fail #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] fn new(obj: &PyRawObject) { obj.init(MyClass {}) } } ``` After: ```rust,no_run # use pyo3::prelude::*; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] fn new() -> Self { MyClass {} } } ``` Basically you can return `Self` or `Result` directly. For more, see [the constructor section](class.md#constructor) of this guide.
### PyCell
Click to expand PyO3 0.9 introduces `PyCell`, which is a [`RefCell`]-like object wrapper for ensuring Rust's rules regarding aliasing of references are upheld. For more detail, see the [Rust Book's section on Rust's rules of references](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references) For `#[pymethods]` or `#[pyfunction]`s, your existing code should continue to work without any change. Python exceptions will automatically be raised when your functions are used in a way which breaks Rust's rules of references. Here is an example. ```rust # use pyo3::prelude::*; #[pyclass] struct Names { names: Vec, } #[pymethods] impl Names { #[new] fn new() -> Self { Names { names: vec![] } } fn merge(&mut self, other: &mut Names) { self.names.append(&mut other.names) } } # Python::with_gil(|py| { # let names = Py::new(py, Names::new()).unwrap(); # pyo3::py_run!(py, names, r" # try: # names.merge(names) # assert False, 'Unreachable' # except RuntimeError as e: # assert str(e) == 'Already borrowed' # "); # }) ``` `Names` has a `merge` method, which takes `&mut self` and another argument of type `&mut Self`. Given this `#[pyclass]`, calling `names.merge(names)` in Python raises a [`PyBorrowMutError`] exception, since it requires two mutable borrows of `names`. However, for `#[pyproto]` and some functions, you need to manually fix the code. #### Object creation In 0.8 object creation was done with `PyRef::new` and `PyRefMut::new`. In 0.9 these have both been removed. To upgrade code, please use `PyCell::new` instead. If you need [`PyRef`] or [`PyRefMut`], just call `.borrow()` or `.borrow_mut()` on the newly-created `PyCell`. Before: ```rust,compile_fail # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} # Python::with_gil(|py| { let obj_ref = PyRef::new(py, MyClass {}).unwrap(); # }) ``` After: ```rust,ignore # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} # Python::with_gil(|py| { let obj = PyCell::new(py, MyClass {}).unwrap(); let obj_ref = obj.borrow(); # }) ``` #### Object extraction For `PyClass` types `T`, `&T` and `&mut T` no longer have [`FromPyObject`] implementations. Instead you should extract `PyRef` or `PyRefMut`, respectively. If `T` implements `Clone`, you can extract `T` itself. In addition, you can also extract `&PyCell`, though you rarely need it. Before: ```compile_fail let obj: &PyAny = create_obj(); let obj_ref: &MyClass = obj.extract().unwrap(); let obj_ref_mut: &mut MyClass = obj.extract().unwrap(); ``` After: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::IntoPyDict; # #[pyclass] #[derive(Clone)] struct MyClass {} # #[pymethods] impl MyClass { #[new]fn new() -> Self { MyClass {} }} # Python::with_gil(|py| { # let typeobj = py.get_type::(); # let d = [("c", typeobj)].into_py_dict(py); # let create_obj = || py.eval("c()", None, Some(d)).unwrap(); let obj: &PyAny = create_obj(); let obj_cell: &PyCell = obj.extract().unwrap(); let obj_cloned: MyClass = obj.extract().unwrap(); // extracted by cloning the object { let obj_ref: PyRef<'_, MyClass> = obj.extract().unwrap(); // we need to drop obj_ref before we can extract a PyRefMut due to Rust's rules of references } let obj_ref_mut: PyRefMut<'_, MyClass> = obj.extract().unwrap(); # }) ``` #### `#[pyproto]` Most of the arguments to methods in `#[pyproto]` impls require a [`FromPyObject`] implementation. So if your protocol methods take `&T` or `&mut T` (where `T: PyClass`), please use [`PyRef`] or [`PyRefMut`] instead. Before: ```rust,compile_fail # use pyo3::prelude::*; # use pyo3::class::PySequenceProtocol; #[pyclass] struct ByteSequence { elements: Vec, } #[pyproto] impl PySequenceProtocol for ByteSequence { fn __concat__(&self, other: &Self) -> PyResult { let mut elements = self.elements.clone(); elements.extend_from_slice(&other.elements); Ok(Self { elements }) } } ``` After: ```rust,compile_fail # use pyo3::prelude::*; # use pyo3::class::PySequenceProtocol; #[pyclass] struct ByteSequence { elements: Vec, } #[pyproto] impl PySequenceProtocol for ByteSequence { fn __concat__(&self, other: PyRef<'p, Self>) -> PyResult { let mut elements = self.elements.clone(); elements.extend_from_slice(&other.elements); Ok(Self { elements }) } } ```
[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`PyAny`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html [`PyBorrowMutError`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyBorrowMutError.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html pyo3/guide/src/building-and-distribution/0000775000175000017500000000000015105742312020234 5ustar bdrungbdrungpyo3/guide/src/building-and-distribution/multiple-python-versions.md0000644000175000017500000001212615105742312025576 0ustar bdrungbdrung# Supporting multiple Python versions PyO3 supports all actively-supported Python 3 and PyPy versions. As much as possible, this is done internally to PyO3 so that your crate's code does not need to adapt to the differences between each version. However, as Python features grow and change between versions, PyO3 cannot offer a completely identical API for every Python version. This may require you to add conditional compilation to your crate or runtime checks for the Python version. This section of the guide first introduces the `pyo3-build-config` crate, which you can use as a `build-dependency` to add additional `#[cfg]` flags which allow you to support multiple Python versions at compile-time. Second, we'll show how to check the Python version at runtime. This can be useful when building for multiple versions with the `abi3` feature, where the Python API compiled against is not always the same as the one in use. ## Conditional compilation for different Python versions The `pyo3-build-config` exposes multiple [`#[cfg]` flags](https://doc.rust-lang.org/rust-by-example/attribute/cfg.html) which can be used to conditionally compile code for a given Python version. PyO3 itself depends on this crate, so by using it you can be sure that you are configured correctly for the Python version PyO3 is building against. This allows us to write code like the following ```rust,ignore #[cfg(Py_3_7)] fn function_only_supported_on_python_3_7_and_up() {} #[cfg(not(Py_3_8))] fn function_only_supported_before_python_3_8() {} #[cfg(not(Py_LIMITED_API))] fn function_incompatible_with_abi3_feature() {} ``` The following sections first show how to add these `#[cfg]` flags to your build process, and then cover some common patterns flags in a little more detail. To see a full reference of all the `#[cfg]` flags provided, see the [`pyo3-build-cfg` docs](https://docs.rs/pyo3-build-config). ### Using `pyo3-build-config` You can use the `#[cfg]` flags in just two steps: 1. Add `pyo3-build-config` with the [`resolve-config`](../features.md#resolve-config) feature enabled to your crate's build dependencies in `Cargo.toml`: ```toml [build-dependencies] pyo3-build-config = { {{#PYO3_CRATE_VERSION}}, features = ["resolve-config"] } ``` 2. Add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) file to your crate with the following contents: ```rust,ignore fn main() { // If you have an existing build.rs file, just add this line to it. pyo3_build_config::use_pyo3_cfgs(); } ``` After these steps you are ready to annotate your code! ### Common usages of `pyo3-build-cfg` flags The `#[cfg]` flags added by `pyo3-build-cfg` can be combined with all of Rust's logic in the `#[cfg]` attribute to create very precise conditional code generation. The following are some common patterns implemented using these flags: ```text #[cfg(Py_3_7)] ``` This `#[cfg]` marks code that will only be present on Python 3.7 and upwards. There are similar options `Py_3_8`, `Py_3_9`, `Py_3_10` and so on for each minor version. ```text #[cfg(not(Py_3_7))] ``` This `#[cfg]` marks code that will only be present on Python versions before (but not including) Python 3.7. ```text #[cfg(not(Py_LIMITED_API))] ``` This `#[cfg]` marks code that is only available when building for the unlimited Python API (i.e. PyO3's `abi3` feature is not enabled). This might be useful if you want to ship your extension module as an `abi3` wheel and also allow users to compile it from source to make use of optimizations only possible with the unlimited API. ```text #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] ``` This `#[cfg]` marks code which is available when running Python 3.9 or newer, or when using the unlimited API with an older Python version. Patterns like this are commonly seen on Python APIs which were added to the limited Python API in a specific minor version. ```text #[cfg(PyPy)] ``` This `#[cfg]` marks code which is running on PyPy. ## Checking the Python version at runtime When building with PyO3's `abi3` feature, your extension module will be compiled against a specific [minimum version](../building-and-distribution.md#minimum-python-version-for-abi3) of Python, but may be running on newer Python versions. For example with PyO3's `abi3-py38` feature, your extension will be compiled as if it were for Python 3.8. If you were using `pyo3-build-config`, `#[cfg(Py_3_8)]` would be present. Your user could freely install and run your abi3 extension on Python 3.9. There's no way to detect your user doing that at compile time, so instead you need to fall back to runtime checks. PyO3 provides the APIs [`Python::version()`] and [`Python::version_info()`] to query the running Python version. This allows you to do the following, for example: ```rust use pyo3::Python; Python::with_gil(|py| { // PyO3 supports Python 3.7 and up. assert!(py.version_info() >= (3, 7)); assert!(py.version_info() >= (3, 7, 0)); }); ``` [`Python::version()`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.version [`Python::version_info()`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.version_info pyo3/guide/src/python-from-rust.md0000644000175000017500000000652015105742312016762 0ustar bdrungbdrung# Calling Python in Rust code This chapter of the guide documents some ways to interact with Python code from Rust. Below is an introduction to the `'py` lifetime and some general remarks about how PyO3's API reasons about Python code. The subchapters also cover the following topics: - Python object types available in PyO3's API - How to work with Python exceptions - How to call Python functions - How to execute existing Python code ## The `'py` lifetime To safely interact with the Python interpreter a Rust thread must have a corresponding Python thread state and hold the [Global Interpreter Lock (GIL)](#the-global-interpreter-lock). PyO3 has a `Python<'py>` token that is used to prove that these conditions are met. Its lifetime `'py` is a central part of PyO3's API. The `Python<'py>` token serves three purposes: * It provides global APIs for the Python interpreter, such as [`py.eval()`][eval] and [`py.import()`][import]. * It can be passed to functions that require a proof of holding the GIL, such as [`Py::clone_ref`][clone_ref]. * Its lifetime `'py` is used to bind many of PyO3's types to the Python interpreter, such as [`Bound<'py, T>`][Bound]. PyO3's types that are bound to the `'py` lifetime, for example `Bound<'py, T>`, all contain a `Python<'py>` token. This means they have full access to the Python interpreter and offer a complete API for interacting with Python objects. Consult [PyO3's API documentation][obtaining-py] to learn how to acquire one of these tokens. ### The Global Interpreter Lock Concurrent programming in Python is aided by the Global Interpreter Lock (GIL), which ensures that only one Python thread can use the Python interpreter and its API at the same time. This allows it to be used to synchronize code. See the [`pyo3::sync`] module for synchronization tools PyO3 offers that are based on the GIL's guarantees. Non-Python operations (system calls and native Rust code) can unlock the GIL. See [the section on parallelism](parallelism.md) for how to do that using PyO3's API. ## Python's memory model Python's memory model differs from Rust's memory model in two key ways: - There is no concept of ownership; all Python objects are shared and usually implemented via reference counting - There is no concept of exclusive (`&mut`) references; any reference can mutate a Python object PyO3's API reflects this by providing [smart pointer][smart-pointers] types, `Py`, `Bound<'py, T>`, and (the very rarely used) `Borrowed<'a, 'py, T>`. These smart pointers all use Python reference counting. See the [subchapter on types](./types.md) for more detail on these types. Because of the lack of exclusive `&mut` references, PyO3's APIs for Python objects, for example [`PyListMethods::append`], use shared references. This is safe because Python objects have internal mechanisms to prevent data races (as of time of writing, the Python GIL). [smart-pointers]: https://doc.rust-lang.org/book/ch15-00-smart-pointers.html [obtaining-py]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#obtaining-a-python-token [`pyo3::sync`]: {{#PYO3_DOCS_URL}}/pyo3/sync/index.html [eval]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval [import]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.import [clone_ref]: {{#PYO3_DOCS_URL}}/pyo3/prelude/struct.Py.html#method.clone_ref [Bound]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html pyo3/guide/src/contributing.md0000644000175000017500000000004315105742312016206 0ustar bdrungbdrung{{#include ../../Contributing.md}} pyo3/guide/src/faq.md0000644000175000017500000002175415105742312014262 0ustar bdrungbdrung# Frequently Asked Questions and troubleshooting Sorry that you're having trouble using PyO3. If you can't find the answer to your problem in the list below, you can also reach out for help on [GitHub Discussions](https://github.com/PyO3/pyo3/discussions) and on [Discord](https://discord.gg/33kcChzH7f). ## I'm experiencing deadlocks using PyO3 with `std::sync::OnceLock`, `std::sync::LazyLock`, `lazy_static`, and `once_cell`! `OnceLock`, `LazyLock`, and their thirdparty predecessors use blocking to ensure only one thread ever initializes them. Because the Python GIL is an additional lock this can lead to deadlocks in the following way: 1. A thread (thread A) which has acquired the Python GIL starts initialization of a `OnceLock` value. 2. The initialization code calls some Python API which temporarily releases the GIL e.g. `Python::import`. 3. Another thread (thread B) acquires the Python GIL and attempts to access the same `OnceLock` value. 4. Thread B is blocked, because it waits for `OnceLock`'s initialization to lock to release. 5. Thread A is blocked, because it waits to re-acquire the GIL which thread B still holds. 6. Deadlock. PyO3 provides a struct [`GILOnceCell`] which implements a single-initialization API based on these types that relies on the GIL for locking. If the GIL is released or there is no GIL, then this type allows the initialization function to race but ensures that the data is only ever initialized once. If you need to ensure that the initialization function is called once and only once, you can make use of the [`OnceExt`] and [`OnceLockExt`] extension traits that enable using the standard library types for this purpose but provide new methods for these types that avoid the risk of deadlocking with the Python GIL. This means they can be used in place of other choices when you are experiencing the deadlock described above. See the documentation for [`GILOnceCell`] and [`OnceExt`] for further details and an example how to use them. [`GILOnceCell`]: {{#PYO3_DOCS_URL}}/pyo3/sync/struct.GILOnceCell.html [`OnceExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html [`OnceLockExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html ## I can't run `cargo test`; or I can't build in a Cargo workspace: I'm having linker issues like "Symbol not found" or "Undefined reference to _PyExc_SystemError"! Currently, [#340](https://github.com/PyO3/pyo3/issues/340) causes `cargo test` to fail with linking errors when the `extension-module` feature is activated. Linking errors can also happen when building in a cargo workspace where a different crate also uses PyO3 (see [#2521](https://github.com/PyO3/pyo3/issues/2521)). For now, there are three ways we can work around these issues. 1. Make the `extension-module` feature optional. Build with `maturin develop --features "extension-module"` ```toml [dependencies.pyo3] {{#PYO3_CRATE_VERSION}} [features] extension-module = ["pyo3/extension-module"] ``` 2. Make the `extension-module` feature optional and default. Run tests with `cargo test --no-default-features`: ```toml [dependencies.pyo3] {{#PYO3_CRATE_VERSION}} [features] extension-module = ["pyo3/extension-module"] default = ["extension-module"] ``` 3. If you are using a [`pyproject.toml`](https://maturin.rs/metadata.html) file to control maturin settings, add the following section: ```toml [tool.maturin] features = ["pyo3/extension-module"] # Or for maturin 0.12: # cargo-extra-args = ["--features", "pyo3/extension-module"] ``` ## I can't run `cargo test`: my crate cannot be found for tests in `tests/` directory! The Rust book suggests to [put integration tests inside a `tests/` directory](https://doc.rust-lang.org/book/ch11-03-test-organization.html#integration-tests). For a PyO3 `extension-module` project where the `crate-type` is set to `"cdylib"` in your `Cargo.toml`, the compiler won't be able to find your crate and will display errors such as `E0432` or `E0463`: ```text error[E0432]: unresolved import `my_crate` --> tests/test_my_crate.rs:1:5 | 1 | use my_crate; | ^^^^^^^^^^^^ no external crate `my_crate` ``` The best solution is to make your crate types include both `rlib` and `cdylib`: ```toml # Cargo.toml [lib] crate-type = ["cdylib", "rlib"] ``` ## Ctrl-C doesn't do anything while my Rust code is executing! This is because Ctrl-C raises a SIGINT signal, which is handled by the calling Python process by simply setting a flag to action upon later. This flag isn't checked while Rust code called from Python is executing, only once control returns to the Python interpreter. You can give the Python interpreter a chance to process the signal properly by calling `Python::check_signals`. It's good practice to call this function regularly if you have a long-running Rust function so that your users can cancel it. ## `#[pyo3(get)]` clones my field! You may have a nested struct similar to this: ```rust,no_run # use pyo3::prelude::*; #[pyclass] #[derive(Clone)] struct Inner {/* fields omitted */} #[pyclass] struct Outer { #[pyo3(get)] inner: Inner, } #[pymethods] impl Outer { #[new] fn __new__() -> Self { Self { inner: Inner {} } } } ``` When Python code accesses `Outer`'s field, PyO3 will return a new object on every access (note that their addresses are different): ```python outer = Outer() a = outer.inner b = outer.inner assert a is b, f"a: {a}\nb: {b}" ``` ```text AssertionError: a: b: ``` This can be especially confusing if the field is mutable, as getting the field and then mutating it won't persist - you'll just get a fresh clone of the original on the next access. Unfortunately Python and Rust don't agree about ownership - if PyO3 gave out references to (possibly) temporary Rust objects to Python code, Python code could then keep that reference alive indefinitely. Therefore returning Rust objects requires cloning. If you don't want that cloning to happen, a workaround is to allocate the field on the Python heap and store a reference to that, by using [`Py<...>`]({{#PYO3_DOCS_URL}}/pyo3/struct.Py.html): ```rust,no_run # use pyo3::prelude::*; #[pyclass] struct Inner {/* fields omitted */} #[pyclass] struct Outer { inner: Py, } #[pymethods] impl Outer { #[new] fn __new__(py: Python<'_>) -> PyResult { Ok(Self { inner: Py::new(py, Inner {})?, }) } #[getter] fn inner(&self, py: Python<'_>) -> Py { self.inner.clone_ref(py) } } ``` This time `a` and `b` *are* the same object: ```python outer = Outer() a = outer.inner b = outer.inner assert a is b, f"a: {a}\nb: {b}" print(f"a: {a}\nb: {b}") ``` ```text a: b: ``` The downside to this approach is that any Rust code working on the `Outer` struct now has to acquire the GIL to do anything with its field. ## I want to use the `pyo3` crate re-exported from dependency but the proc-macros fail! All PyO3 proc-macros (`#[pyclass]`, `#[pyfunction]`, `#[derive(FromPyObject)]` and so on) expect the `pyo3` crate to be available under that name in your crate root, which is the normal situation when `pyo3` is a direct dependency of your crate. However, when the dependency is renamed, or your crate only indirectly depends on `pyo3`, you need to let the macro code know where to find the crate. This is done with the `crate` attribute: ```rust,no_run # use pyo3::prelude::*; # pub extern crate pyo3; # mod reexported { pub use ::pyo3; } # #[allow(dead_code)] #[pyclass] #[pyo3(crate = "reexported::pyo3")] struct MyClass; ``` ## I'm trying to call Python from Rust but I get `STATUS_DLL_NOT_FOUND` or `STATUS_ENTRYPOINT_NOT_FOUND`! This happens on Windows when linking to the python DLL fails or the wrong one is linked. The Python DLL on Windows will usually be called something like: - `python3X.dll` for Python 3.X, e.g. `python310.dll` for Python 3.10 - `python3.dll` when using PyO3's `abi3` feature The DLL needs to be locatable using the [Windows DLL search order](https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-unpackaged-apps). Some ways to achieve this are: - Put the Python DLL in the same folder as your build artifacts - Add the directory containing the Python DLL to your `PATH` environment variable, for example `C:\Users\\AppData\Local\Programs\Python\Python310` - If this happens when you are *distributing* your program, consider using [PyOxidizer](https://github.com/indygreg/PyOxidizer) to package it with your binary. If the wrong DLL is linked it is possible that this happened because another program added itself and its own Python DLLs to `PATH`. Rearrange your `PATH` variables to give the correct DLL priority. > **Note**: Changes to `PATH` (or any other environment variable) are not visible to existing shells. Restart it for changes to take effect. For advanced troubleshooting, [Dependency Walker](https://www.dependencywalker.com/) can be used to diagnose linking errors. pyo3/guide/src/ecosystem.md0000644000175000017500000000060315105742312015514 0ustar bdrungbdrung# The PyO3 ecosystem This portion of the guide is dedicated to crates which are external to the main PyO3 project and provide additional functionality you might find useful. Because these projects evolve independently of the PyO3 repository the content of these articles may fall out of date over time; please file issues on the PyO3 GitHub to alert maintainers when this is the case. pyo3/guide/src/features.md0000644000175000017500000003521115105742312015322 0ustar bdrungbdrung# Features reference PyO3 provides a number of Cargo features to customize functionality. This chapter of the guide provides detail on each of them. By default, only the `macros` feature is enabled. ## Features for extension module authors ### `extension-module` This feature is required when building a Python extension module using PyO3. It tells PyO3's build script to skip linking against `libpython.so` on Unix platforms, where this must not be done. See the [building and distribution](building-and-distribution.md#the-extension-module-feature) section for further detail. ### `abi3` This feature is used when building Python extension modules to create wheels which are compatible with multiple Python versions. It restricts PyO3's API to a subset of the full Python API which is guaranteed by [PEP 384](https://www.python.org/dev/peps/pep-0384/) to be forwards-compatible with future Python versions. See the [building and distribution](building-and-distribution.md#py_limited_apiabi3) section for further detail. ### The `abi3-pyXY` features (`abi3-py37`, `abi3-py38`, `abi3-py39`, `abi3-py310` and `abi3-py311`) These features are extensions of the `abi3` feature to specify the exact minimum Python version which the multiple-version-wheel will support. See the [building and distribution](building-and-distribution.md#minimum-python-version-for-abi3) section for further detail. ### `generate-import-lib` This experimental feature is used to generate import libraries for Python DLL for MinGW-w64 and MSVC (cross-)compile targets. Enabling it allows to (cross-)compile extension modules to any Windows targets without having to install the Windows Python distribution files for the target. See the [building and distribution](building-and-distribution.md#building-abi3-extensions-without-a-python-interpreter) section for further detail. ## Features for embedding Python in Rust ### `auto-initialize` This feature changes [`Python::with_gil`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.with_gil) to automatically initialize a Python interpreter (by calling [`prepare_freethreaded_python`]({{#PYO3_DOCS_URL}}/pyo3/fn.prepare_freethreaded_python.html)) if needed. If you do not enable this feature, you should call `pyo3::prepare_freethreaded_python()` before attempting to call any other Python APIs. ## Advanced Features ### `experimental-async` This feature adds support for `async fn` in `#[pyfunction]` and `#[pymethods]`. The feature has some unfinished refinements and performance improvements. To help finish this off, see [issue #1632](https://github.com/PyO3/pyo3/issues/1632) and its associated draft PRs. ### `experimental-inspect` This feature adds to the built binaries introspection data that can be then retrieved using the `pyo3-introspection` crate to generate [type stubs](https://typing.readthedocs.io/en/latest/source/stubs.html). Also, this feature adds the `pyo3::inspect` module, as well as `IntoPy::type_output` and `FromPyObject::type_input` APIs to produce Python type "annotations" for Rust types. This is a first step towards adding first-class support for generating type annotations automatically in PyO3, however work is needed to finish this off. All feedback and offers of help welcome on [issue #2454](https://github.com/PyO3/pyo3/issues/2454). ### `gil-refs` This feature is a backwards-compatibility feature to allow continued use of the "GIL Refs" APIs deprecated in PyO3 0.21. These APIs have performance drawbacks and soundness edge cases which the newer `Bound` smart pointer and accompanying APIs resolve. This feature and the APIs it enables is expected to be removed in a future PyO3 version. ### `py-clone` This feature was introduced to ease migration. It was found that delayed reference counts cannot be made sound and hence `Clon`ing an instance of `Py` must panic without the GIL being held. To avoid migrations introducing new panics without warning, the `Clone` implementation itself is now gated behind this feature. ### `pyo3_disable_reference_pool` This is a performance-oriented conditional compilation flag, e.g. [set via `$RUSTFLAGS`][set-configuration-options], which disabled the global reference pool and the associated overhead for the crossing the Python-Rust boundary. However, if enabled, `Drop`ping an instance of `Py` without the GIL being held will abort the process. ### `macros` This feature enables a dependency on the `pyo3-macros` crate, which provides the procedural macros portion of PyO3's API: - `#[pymodule]` - `#[pyfunction]` - `#[pyclass]` - `#[pymethods]` - `#[derive(FromPyObject)]` It also provides the `py_run!` macro. These macros require a number of dependencies which may not be needed by users who just need PyO3 for Python FFI. Disabling this feature enables faster builds for those users, as these dependencies will not be built if this feature is disabled. > This feature is enabled by default. To disable it, set `default-features = false` for the `pyo3` entry in your Cargo.toml. ### `multiple-pymethods` This feature enables each `#[pyclass]` to have more than one `#[pymethods]` block. Most users should only need a single `#[pymethods]` per `#[pyclass]`. In addition, not all platforms (e.g. Wasm) are supported by `inventory`, which is used in the implementation of the feature. For this reason this feature is not enabled by default, meaning fewer dependencies and faster compilation for the majority of users. See [the `#[pyclass]` implementation details](class.md#implementation-details) for more information. ### `nightly` The `nightly` feature needs the nightly Rust compiler. This allows PyO3 to use the `auto_traits` and `negative_impls` features to fix the `Python::allow_threads` function. ### `resolve-config` The `resolve-config` feature of the `pyo3-build-config` crate controls whether that crate's build script automatically resolves a Python interpreter / build configuration. This feature is primarily useful when building PyO3 itself. By default this feature is not enabled, meaning you can freely use `pyo3-build-config` as a standalone library to read or write PyO3 build configuration files or resolve metadata about a Python interpreter. ## Optional Dependencies These features enable conversions between Python types and types from other Rust crates, enabling easy access to the rest of the Rust ecosystem. ### `anyhow` Adds a dependency on [anyhow](https://docs.rs/anyhow). Enables a conversion from [anyhow](https://docs.rs/anyhow)’s [`Error`](https://docs.rs/anyhow/latest/anyhow/struct.Error.html) type to [`PyErr`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html), for easy error handling. ### `arc_lock` Enables Pyo3's `MutexExt` trait for all Mutexes that extend on [`lock_api::Mutex`](https://docs.rs/lock_api/latest/lock_api/struct.Mutex.html) and are wrapped in an [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) type. Like [`Arc`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html#method.lock_arc) ### `bigdecimal` Adds a dependency on [bigdecimal](https://docs.rs/bigdecimal) and enables conversions into its [`BigDecimal`](https://docs.rs/bigdecimal/latest/bigdecimal/struct.BigDecimal.html) type. ### `chrono` Adds a dependency on [chrono](https://docs.rs/chrono). Enables a conversion from [chrono](https://docs.rs/chrono)'s types to python: - [TimeDelta](https://docs.rs/chrono/latest/chrono/struct.TimeDelta.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [FixedOffset](https://docs.rs/chrono/latest/chrono/offset/struct.FixedOffset.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [Utc](https://docs.rs/chrono/latest/chrono/offset/struct.Utc.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [NaiveDate](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveDate.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html) - [NaiveTime](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveTime.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html) - [DateTime](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) ### `chrono-local` Enables conversion from and to [Local](https://docs.rs/chrono/latest/chrono/struct.Local.html) timezones. ### `chrono-tz` Adds a dependency on [chrono-tz](https://docs.rs/chrono-tz). Enables conversion from and to [`Tz`](https://docs.rs/chrono-tz/latest/chrono_tz/enum.Tz.html). It requires at least Python 3.9. ### `either` Adds a dependency on [either](https://docs.rs/either). Enables a conversions into [either](https://docs.rs/either)’s [`Either`](https://docs.rs/either/latest/either/enum.Either.html) type. ### `eyre` Adds a dependency on [eyre](https://docs.rs/eyre). Enables a conversion from [eyre](https://docs.rs/eyre)’s [`Report`](https://docs.rs/eyre/latest/eyre/struct.Report.html) type to [`PyErr`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html), for easy error handling. ### `hashbrown` Adds a dependency on [hashbrown](https://docs.rs/hashbrown) and enables conversions into its [`HashMap`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html) and [`HashSet`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html) types. ### `indexmap` Adds a dependency on [indexmap](https://docs.rs/indexmap) and enables conversions into its [`IndexMap`](https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html) type. ### `jiff-02` Adds a dependency on [jiff@0.2](https://docs.rs/jiff/0.2) and requires MSRV 1.70. Enables a conversion from [jiff](https://docs.rs/jiff)'s types to python: - [SignedDuration](https://docs.rs/jiff/0.2/jiff/struct.SignedDuration.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [TimeZone](https://docs.rs/jiff/0.2/jiff/tz/struct.TimeZone.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [Offset](https://docs.rs/jiff/0.2/jiff/tz/struct.Offset.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [Date](https://docs.rs/jiff/0.2/jiff/civil/struct.Date.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html) - [Time](https://docs.rs/jiff/0.2/jiff/civil/struct.Time.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html) - [DateTime](https://docs.rs/jiff/0.2/jiff/civil/struct.DateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [Zoned](https://docs.rs/jiff/0.2/jiff/struct.Zoned.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [Timestamp](https://docs.rs/jiff/0.2/jiff/struct.Timestamp.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) ### `lock_api` Adds a dependency on [lock_api](https://docs.rs/lock_api) and enables Pyo3's `MutexExt` trait for all mutexes that extend on [`lock_api::Mutex`](https://docs.rs/lock_api/latest/lock_api/struct.Mutex.html) (like `parking_lot` or `spin`). ### `num-bigint` Adds a dependency on [num-bigint](https://docs.rs/num-bigint) and enables conversions into its [`BigInt`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html) and [`BigUint`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html) types. ### `num-complex` Adds a dependency on [num-complex](https://docs.rs/num-complex) and enables conversions into its [`Complex`](https://docs.rs/num-complex/latest/num_complex/struct.Complex.html) type. ### `num-rational` Adds a dependency on [num-rational](https://docs.rs/num-rational) and enables conversions into its [`Ratio`](https://docs.rs/num-rational/latest/num_rational/struct.Ratio.html) type. ### `ordered-float` Adds a dependency on [ordered-float](https://docs.rs/ordered-float) and enables conversions between [ordered-float](https://docs.rs/ordered-float)'s types and Python: - [NotNan](https://docs.rs/ordered-float/latest/ordered_float/struct.NotNan.html) -> [`PyFloat`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFloat.html) - [OrderedFloat](https://docs.rs/ordered-float/latest/ordered_float/struct.OrderedFloat.html) -> [`PyFloat`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFloat.html) ### `parking-lot` Adds a dependency on [parking_lot](https://docs.rs/parking_lot) and enables Pyo3's `OnceExt` & `MutexExt` traits for [`parking_lot::Once`](https://docs.rs/parking_lot/latest/parking_lot/struct.Once.html) and [`parking_lot::Mutex`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html) types. ### `rust_decimal` Adds a dependency on [rust_decimal](https://docs.rs/rust_decimal) and enables conversions into its [`Decimal`](https://docs.rs/rust_decimal/latest/rust_decimal/struct.Decimal.html) type. ### `time` Adds a dependency on [time](https://docs.rs/time) and requires MSRV 1.67.1. Enables conversions between [time](https://docs.rs/time)'s types and Python: - [Date](https://docs.rs/time/0.3.38/time/struct.Date.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html) - [Time](https://docs.rs/time/0.3.38/time/struct.Time.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html) - [OffsetDateTime](https://docs.rs/time/0.3.38/time/struct.OffsetDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [PrimitiveDateTime](https://docs.rs/time/0.3.38/time/struct.PrimitiveDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) - [Duration](https://docs.rs/time/0.3.38/time/struct.Duration.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [UtcOffset](https://docs.rs/time/0.3.38/time/struct.UtcOffset.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [UtcDateTime](https://docs.rs/time/0.3.38/time/struct.UtcDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) ### `serde` Enables (de)serialization of `Py` objects via [serde](https://serde.rs/). This allows to use [`#[derive(Serialize, Deserialize)`](https://serde.rs/derive.html) on structs that hold references to `#[pyclass]` instances ```rust,no_run # #[cfg(feature = "serde")] # #[allow(dead_code)] # mod serde_only { # use pyo3::prelude::*; # use serde::{Deserialize, Serialize}; #[pyclass] #[derive(Serialize, Deserialize)] struct Permission { name: String, } #[pyclass] #[derive(Serialize, Deserialize)] struct User { username: String, permissions: Vec>, } # } ``` ### `smallvec` Adds a dependency on [smallvec](https://docs.rs/smallvec) and enables conversions into its [`SmallVec`](https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html) type. [set-configuration-options]: https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options ### `uuid` Adds a dependency on [uuid](https://docs.rs/uuid) and enables conversions into its [`Uuid`](https://docs.rs/uuid/latest/uuid/struct.Uuid.html) type. pyo3/guide/src/building-and-distribution.md0000644000175000017500000006627715105742312020576 0ustar bdrungbdrung# Building and distribution This chapter of the guide goes into detail on how to build and distribute projects using PyO3. The way to achieve this is very different depending on whether the project is a Python module implemented in Rust, or a Rust binary embedding Python. For both types of project there are also common problems such as the Python version to build for and the [linker](https://en.wikipedia.org/wiki/Linker_(computing)) arguments to use. The material in this chapter is intended for users who have already read the PyO3 [README](./index.md). It covers in turn the choices that can be made for Python modules and for Rust binaries. There is also a section at the end about cross-compiling projects using PyO3. There is an additional sub-chapter dedicated to [supporting multiple Python versions](./building-and-distribution/multiple-python-versions.md). ## Configuring the Python version PyO3 uses a build script (backed by the [`pyo3-build-config`] crate) to determine the Python version and set the correct linker arguments. By default it will attempt to use the following in order: - Any active Python virtualenv. - The `python` executable (if it's a Python 3 interpreter). - The `python3` executable. You can override the Python interpreter by setting the `PYO3_PYTHON` environment variable, e.g. `PYO3_PYTHON=python3.7`, `PYO3_PYTHON=/usr/bin/python3.9`, or even a PyPy interpreter `PYO3_PYTHON=pypy3`. Once the Python interpreter is located, `pyo3-build-config` executes it to query the information in the `sysconfig` module which is needed to configure the rest of the compilation. To validate the configuration which PyO3 will use, you can run a compilation with the environment variable `PYO3_PRINT_CONFIG=1` set. An example output of doing this is shown below: ```console $ PYO3_PRINT_CONFIG=1 cargo build Compiling pyo3 v0.14.1 (/home/david/dev/pyo3) error: failed to run custom build command for `pyo3 v0.14.1 (/home/david/dev/pyo3)` Caused by: process didn't exit successfully: `/home/david/dev/pyo3/target/debug/build/pyo3-7a8cf4fe22e959b7/build-script-build` (exit status: 101) --- stdout cargo:rerun-if-env-changed=PYO3_CROSS cargo:rerun-if-env-changed=PYO3_CROSS_LIB_DIR cargo:rerun-if-env-changed=PYO3_CROSS_PYTHON_VERSION cargo:rerun-if-env-changed=PYO3_PRINT_CONFIG -- PYO3_PRINT_CONFIG=1 is set, printing configuration and halting compile -- implementation=CPython version=3.8 shared=true abi3=false lib_name=python3.8 lib_dir=/usr/lib executable=/usr/bin/python pointer_width=64 build_flags= suppress_build_script_link_lines=false ``` The `PYO3_ENVIRONMENT_SIGNATURE` environment variable can be used to trigger rebuilds when its value changes, it has no other effect. ### Advanced: config files If you save the above output config from `PYO3_PRINT_CONFIG` to a file, it is possible to manually override the contents and feed it back into PyO3 using the `PYO3_CONFIG_FILE` env var. If your build environment is unusual enough that PyO3's regular configuration detection doesn't work, using a config file like this will give you the flexibility to make PyO3 work for you. To see the full set of options supported, see the documentation for the [`InterpreterConfig` struct](https://docs.rs/pyo3-build-config/{{#PYO3_DOCS_VERSION}}/pyo3_build_config/struct.InterpreterConfig.html). ## Building Python extension modules Python extension modules need to be compiled differently depending on the OS (and architecture) that they are being compiled for. As well as multiple OSes (and architectures), there are also many different Python versions which are actively supported. Packages uploaded to [PyPI](https://pypi.org/) usually want to upload prebuilt "wheels" covering many OS/arch/version combinations so that users on all these different platforms don't have to compile the package themselves. Package vendors can opt-in to the "abi3" limited Python API which allows their wheels to be used on multiple Python versions, reducing the number of wheels they need to compile, but restricts the functionality they can use. There are many ways to go about this: it is possible to use `cargo` to build the extension module (along with some manual work, which varies with OS). The PyO3 ecosystem has two packaging tools, [`maturin`] and [`setuptools-rust`], which abstract over the OS difference and also support building wheels for PyPI upload. PyO3 has some Cargo features to configure projects for building Python extension modules: - The `extension-module` feature, which must be enabled when building Python extension modules. - The `abi3` feature and its version-specific `abi3-pyXY` companions, which are used to opt-in to the limited Python API in order to support multiple Python versions in a single wheel. This section describes each of these packaging tools before describing how to build manually without them. It then proceeds with an explanation of the `extension-module` feature. Finally, there is a section describing PyO3's `abi3` features. ### Packaging tools The PyO3 ecosystem has two main choices to abstract the process of developing Python extension modules: - [`maturin`] is a command-line tool to build, package and upload Python modules. It makes opinionated choices about project layout meaning it needs very little configuration. This makes it a great choice for users who are building a Python extension from scratch and don't need flexibility. - [`setuptools-rust`] is an add-on for `setuptools` which adds extra keyword arguments to the `setup.py` configuration file. It requires more configuration than `maturin`, however this gives additional flexibility for users adding Rust to an existing Python package that can't satisfy `maturin`'s constraints. Consult each project's documentation for full details on how to get started using them and how to upload wheels to PyPI. It should be noted that while `maturin` is able to build [manylinux](https://github.com/pypa/manylinux)-compliant wheels out-of-the-box, `setuptools-rust` requires a bit more effort, [relying on Docker](https://setuptools-rust.readthedocs.io/en/latest/building_wheels.html) for this purpose. There are also [`maturin-starter`] and [`setuptools-rust-starter`] examples in the PyO3 repository. ### Manual builds To build a PyO3-based Python extension manually, start by running `cargo build` as normal in a library project which uses PyO3's `extension-module` feature and has the [`cdylib` crate type](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field). Once built, symlink (or copy) and rename the shared library from Cargo's `target/` directory to your desired output directory: - on macOS, rename `libyour_module.dylib` to `your_module.so`. - on Windows, rename `libyour_module.dll` to `your_module.pyd`. - on Linux, rename `libyour_module.so` to `your_module.so`. You can then open a Python shell in the output directory and you'll be able to run `import your_module`. If you're packaging your library for redistribution, you should indicate the Python interpreter your library is compiled for by including the [platform tag](#platform-tags) in its name. This prevents incompatible interpreters from trying to import your library. If you're compiling for PyPy you *must* include the platform tag, or PyPy will ignore the module. #### Bazel builds To use PyO3 with bazel one needs to manually configure PyO3, PyO3-ffi and PyO3-macros. In particular, one needs to make sure that it is compiled with the right python flags for the version you intend to use. For example see: 1. [github.com/abrisco/rules_pyo3](https://github.com/abrisco/rules_pyo3) -- General rules for building extension modules. 2. [github.com/OliverFM/pytorch_with_gazelle](https://github.com/OliverFM/pytorch_with_gazelle) -- for a minimal example of a repo that can use PyO3, PyTorch and Gazelle to generate python Build files. 3. [github.com/TheButlah/rules_pyo3](https://github.com/TheButlah/rules_pyo3) -- is somewhat dated. #### Platform tags Rather than using just the `.so` or `.pyd` extension suggested above (depending on OS), you can prefix the shared library extension with a platform tag to indicate the interpreter it is compatible with. You can query your interpreter's platform tag from the `sysconfig` module. Some example outputs of this are seen below: ```bash # CPython 3.10 on macOS .cpython-310-darwin.so # PyPy 7.3 (Python 3.9) on Linux $ python -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX"))' .pypy39-pp73-x86_64-linux-gnu.so ``` So, for example, a valid module library name on CPython 3.10 for macOS is `your_module.cpython-310-darwin.so`, and its equivalent when compiled for PyPy 7.3 on Linux would be `your_module.pypy38-pp73-x86_64-linux-gnu.so`. See [PEP 3149](https://peps.python.org/pep-3149/) for more background on platform tags. #### macOS On macOS, because the `extension-module` feature disables linking to `libpython` ([see the next section](#the-extension-module-feature)), some additional linker arguments need to be set. `maturin` and `setuptools-rust` both pass these arguments for PyO3 automatically, but projects using manual builds will need to set these directly in order to support macOS. The easiest way to set the correct linker arguments is to add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) with the following content: ```rust,ignore fn main() { pyo3_build_config::add_extension_module_link_args(); } ``` Remember to also add `pyo3-build-config` to the `build-dependencies` section in `Cargo.toml`. An alternative to using `pyo3-build-config` is add the following to a cargo configuration file (e.g. `.cargo/config.toml`): ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` Using the MacOS system python3 (`/usr/bin/python3`, as opposed to python installed via homebrew, pyenv, nix, etc.) may result in runtime errors such as `Library not loaded: @rpath/Python3.framework/Versions/3.8/Python3`. The easiest way to set the correct linker arguments is to add a `build.rs` with the following content: ```rust,ignore fn main() { pyo3_build_config::add_python_framework_link_args(); } ``` Alternatively it can be resolved with another addition to `.cargo/config.toml`: ```toml [build] rustflags = [ "-C", "link-args=-Wl,-rpath,/Library/Developer/CommandLineTools/Library/Frameworks", ] ``` For more discussion on and workarounds for MacOS linking problems [see this issue](https://github.com/PyO3/pyo3/issues/1800#issuecomment-906786649). Finally, don't forget that on MacOS the `extension-module` feature will cause `cargo test` to fail without the `--no-default-features` flag (see [the FAQ](https://pyo3.rs/main/faq.html#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror)). ### The `extension-module` feature PyO3's `extension-module` feature is used to disable [linking](https://en.wikipedia.org/wiki/Linker_(computing)) to `libpython` on Unix targets. This is necessary because by default PyO3 links to `libpython`. This makes binaries, tests, and examples "just work". However, Python extensions on Unix must not link to libpython for [manylinux](https://www.python.org/dev/peps/pep-0513/) compliance. The downside of not linking to `libpython` is that binaries, tests, and examples (which usually embed Python) will fail to build. If you have an extension module as well as other outputs in a single project, you need to use optional Cargo features to disable the `extension-module` when you're not building the extension module. See [the FAQ](faq.md#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror) for an example workaround. ### `Py_LIMITED_API`/`abi3` By default, Python extension modules can only be used with the same Python version they were compiled against. For example, an extension module built for Python 3.5 can't be imported in Python 3.8. [PEP 384](https://www.python.org/dev/peps/pep-0384/) introduced the idea of the limited Python API, which would have a stable ABI enabling extension modules built with it to be used against multiple Python versions. This is also known as `abi3`. The advantage of building extension modules using the limited Python API is that package vendors only need to build and distribute a single copy (for each OS / architecture), and users can install it on all Python versions from the [minimum version](#minimum-python-version-for-abi3) and up. The downside of this is that PyO3 can't use optimizations which rely on being compiled against a known exact Python version. It's up to you to decide whether this matters for your extension module. It's also possible to design your extension module such that you can distribute `abi3` wheels but allow users compiling from source to benefit from additional optimizations - see the [support for multiple python versions](./building-and-distribution/multiple-python-versions.md) section of this guide, in particular the `#[cfg(Py_LIMITED_API)]` flag. There are three steps involved in making use of `abi3` when building Python packages as wheels: 1. Enable the `abi3` feature in `pyo3`. This ensures `pyo3` only calls Python C-API functions which are part of the stable API, and on Windows also ensures that the project links against the correct shared object (no special behavior is required on other platforms): ```toml [dependencies] pyo3 = { {{#PYO3_CRATE_VERSION}}, features = ["abi3"] } ``` 2. Ensure that the built shared objects are correctly marked as `abi3`. This is accomplished by telling your build system that you're using the limited API. [`maturin`] >= 0.9.0 and [`setuptools-rust`] >= 0.11.4 support `abi3` wheels. See the [corresponding](https://github.com/PyO3/maturin/pull/353) [PRs](https://github.com/PyO3/setuptools-rust/pull/82) for more. 3. Ensure that the `.whl` is correctly marked as `abi3`. For projects using `setuptools`, this is accomplished by passing `--py-limited-api=cp3x` (where `x` is the minimum Python version supported by the wheel, e.g. `--py-limited-api=cp35` for Python 3.5) to `setup.py bdist_wheel`. #### Minimum Python version for `abi3` Because a single `abi3` wheel can be used with many different Python versions, PyO3 has feature flags `abi3-py37`, `abi3-py38`, `abi3-py39` etc. to set the minimum required Python version for your `abi3` wheel. For example, if you set the `abi3-py37` feature, your extension wheel can be used on all Python 3 versions from Python 3.7 and up. `maturin` and `setuptools-rust` will give the wheel a name like `my-extension-1.0-cp37-abi3-manylinux2020_x86_64.whl`. As your extension module may be run with multiple different Python versions you may occasionally find you need to check the Python version at runtime to customize behavior. See [the relevant section of this guide](./building-and-distribution/multiple-python-versions.md#checking-the-python-version-at-runtime) on supporting multiple Python versions at runtime. PyO3 is only able to link your extension module to abi3 version up to and including your host Python version. E.g., if you set `abi3-py38` and try to compile the crate with a host of Python 3.7, the build will fail. > Note: If you set more that one of these `abi3` version feature flags the lowest version always wins. For example, with both `abi3-py37` and `abi3-py38` set, PyO3 would build a wheel which supports Python 3.7 and up. #### Building `abi3` extensions without a Python interpreter As an advanced feature, you can build PyO3 wheel without calling Python interpreter with the environment variable `PYO3_NO_PYTHON` set. Also, if the build host Python interpreter is not found or is too old or otherwise unusable, PyO3 will still attempt to compile `abi3` extension modules after displaying a warning message. On Unix-like systems this works unconditionally; on Windows you must also set the `RUSTFLAGS` environment variable to contain `-L native=/path/to/python/libs` so that the linker can find `python3.lib`. If the `python3.dll` import library is not available, an experimental `generate-import-lib` crate feature may be enabled, and the required library will be created and used by PyO3 automatically. *Note*: MSVC targets require LLVM binutils (`llvm-dlltool`) to be available in `PATH` for the automatic import library generation feature to work. #### Missing features Due to limitations in the Python API, there are a few `pyo3` features that do not work when compiling for `abi3`. These are: - `#[pyo3(text_signature = "...")]` does not work on classes until Python 3.10 or greater. - The `dict` and `weakref` options on classes are not supported until Python 3.9 or greater. - The buffer API is not supported until Python 3.11 or greater. - Optimizations which rely on knowledge of the exact Python version compiled against. ## Embedding Python in Rust If you want to embed the Python interpreter inside a Rust program, there are two modes in which this can be done: dynamically and statically. We'll cover each of these modes in the following sections. Each of them affect how you must distribute your program. Instead of learning how to do this yourself, you might want to consider using a project like [PyOxidizer] to ship your application and all of its dependencies in a single file. PyO3 automatically switches between the two linking modes depending on whether the Python distribution you have configured PyO3 to use ([see above](#configuring-the-python-version)) contains a shared library or a static library. The static library is most often seen in Python distributions compiled from source without the `--enable-shared` configuration option. ### Dynamically embedding the Python interpreter Embedding the Python interpreter dynamically is much easier than doing so statically. This is done by linking your program against a Python shared library (such as `libpython.3.9.so` on UNIX, or `python39.dll` on Windows). The implementation of the Python interpreter resides inside the shared library. This means that when the OS runs your Rust program it also needs to be able to find the Python shared library. This mode of embedding works well for Rust tests which need access to the Python interpreter. It is also great for Rust software which is installed inside a Python virtualenv, because the virtualenv sets up appropriate environment variables to locate the correct Python shared library. For distributing your program to non-technical users, you will have to consider including the Python shared library in your distribution as well as setting up wrapper scripts to set the right environment variables (such as `LD_LIBRARY_PATH` on UNIX, or `PATH` on Windows). Note that PyPy cannot be embedded in Rust (or any other software). Support for this is tracked on the [PyPy issue tracker](https://github.com/pypy/pypy/issues/3836). ### Statically embedding the Python interpreter Embedding the Python interpreter statically means including the contents of a Python static library directly inside your Rust binary. This means that to distribute your program you only need to ship your binary file: it contains the Python interpreter inside the binary! On Windows static linking is almost never done, so Python distributions don't usually include a static library. The information below applies only to UNIX. The Python static library is usually called `libpython.a`. Static linking has a lot of complications, listed below. For these reasons PyO3 does not yet have first-class support for this embedding mode. See [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416) for more information and to discuss any issues you encounter. The [`auto-initialize`](features.md#auto-initialize) feature is deliberately disabled when embedding the interpreter statically because this is often unintentionally done by new users to PyO3 running test programs. Trying out PyO3 is much easier using dynamic embedding. The known complications are: - To import compiled extension modules (such as other Rust extension modules, or those written in C), your binary must have the correct linker flags set during compilation to export the original contents of `libpython.a` so that extensions can use them (e.g. `-Wl,--export-dynamic`). - The C compiler and flags which were used to create `libpython.a` must be compatible with your Rust compiler and flags, else you will experience compilation failures. Significantly different compiler versions may see errors like this: ```text lto1: fatal error: bytecode stream in file 'rust-numpy/target/release/deps/libpyo3-6a7fb2ed970dbf26.rlib' generated with LTO version 6.0 instead of the expected 6.2 ``` Mismatching flags may lead to errors like this: ```text /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpython3.9.a(zlibmodule.o): relocation R_X86_64_32 against `.data' can not be used when making a PIE object; recompile with -fPIE ``` If you encounter these or other complications when linking the interpreter statically, discuss them on [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416). It is hoped that eventually that discussion will contain enough information and solutions that PyO3 can offer first-class support for static embedding. ### Import your module when embedding the Python interpreter When you run your Rust binary with an embedded interpreter, any `#[pymodule]` created modules won't be accessible to import unless added to a table called `PyImport_Inittab` before the embedded interpreter is initialized. This will cause Python statements in your embedded interpreter such as `import your_new_module` to fail. You can call the macro [`append_to_inittab`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) with your module before initializing the Python interpreter to add the module function into that table. (The Python interpreter will be initialized by calling `prepare_freethreaded_python`, `with_embedded_python_interpreter`, or `Python::with_gil` with the [`auto-initialize`](features.md#auto-initialize) feature enabled.) ## Cross Compiling Thanks to Rust's great cross-compilation support, cross-compiling using PyO3 is relatively straightforward. To get started, you'll need a few pieces of software: * A toolchain for your target. * The appropriate options in your Cargo `.config` for the platform you're targeting and the toolchain you are using. * A Python interpreter that's already been compiled for your target (optional when building "abi3" extension modules). * A Python interpreter that is built for your host and available through the `PATH` or setting the [`PYO3_PYTHON`](#configuring-the-python-version) variable (optional when building "abi3" extension modules). After you've obtained the above, you can build a cross-compiled PyO3 module by using Cargo's `--target` flag. PyO3's build script will detect that you are attempting a cross-compile based on your host machine and the desired target. When cross-compiling, PyO3's build script cannot execute the target Python interpreter to query the configuration, so there are a few additional environment variables you may need to set: * `PYO3_CROSS`: If present this variable forces PyO3 to configure as a cross-compilation. * `PYO3_CROSS_LIB_DIR`: This variable can be set to the directory containing the target's libpython DSO and the associated `_sysconfigdata*.py` file for Unix-like targets, or the Python DLL import libraries for the Windows target. This variable is only needed when the output binary must link to libpython explicitly (e.g. when targeting Windows and Android or embedding a Python interpreter), or when it is absolutely required to get the interpreter configuration from `_sysconfigdata*.py`. * `PYO3_CROSS_PYTHON_VERSION`: Major and minor version (e.g. 3.9) of the target Python installation. This variable is only needed if PyO3 cannot determine the version to target from `abi3-py3*` features, or if `PYO3_CROSS_LIB_DIR` is not set, or if there are multiple versions of Python present in `PYO3_CROSS_LIB_DIR`. * `PYO3_CROSS_PYTHON_IMPLEMENTATION`: Python implementation name ("CPython" or "PyPy") of the target Python installation. CPython is assumed by default when this variable is not set, unless `PYO3_CROSS_LIB_DIR` is set for a Unix-like target and PyO3 can get the interpreter configuration from `_sysconfigdata*.py`. An experimental `pyo3` crate feature `generate-import-lib` enables the user to cross-compile extension modules for Windows targets without setting the `PYO3_CROSS_LIB_DIR` environment variable or providing any Windows Python library files. It uses an external [`python3-dll-a`] crate to generate import libraries for the Python DLL for MinGW-w64 and MSVC compile targets. `python3-dll-a` uses the binutils `dlltool` program to generate DLL import libraries for MinGW-w64 targets. It is possible to override the default `dlltool` command name for the cross target by setting `PYO3_MINGW_DLLTOOL` environment variable. *Note*: MSVC targets require LLVM binutils or MSVC build tools to be available on the host system. More specifically, `python3-dll-a` requires `llvm-dlltool` or `lib.exe` executable to be present in `PATH` when targeting `*-pc-windows-msvc`. The Zig compiler executable can be used in place of `llvm-dlltool` when the `ZIG_COMMAND` environment variable is set to the installed Zig program name (`"zig"` or `"python -m ziglang"`). An example might look like the following (assuming your target's sysroot is at `/home/pyo3/cross/sysroot` and that your target is `armv7`): ```sh export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target armv7-unknown-linux-gnueabihf ``` If there are multiple python versions at the cross lib directory and you cannot set a more precise location to include both the `libpython` DSO and `_sysconfigdata*.py` files, you can set the required version: ```sh export PYO3_CROSS_PYTHON_VERSION=3.8 export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target armv7-unknown-linux-gnueabihf ``` Or another example with the same sys root but building for Windows: ```sh export PYO3_CROSS_PYTHON_VERSION=3.9 export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target x86_64-pc-windows-gnu ``` Any of the `abi3-py3*` features can be enabled instead of setting `PYO3_CROSS_PYTHON_VERSION` in the above examples. `PYO3_CROSS_LIB_DIR` can often be omitted when cross compiling extension modules for Unix and macOS targets, or when cross compiling extension modules for Windows and the experimental `generate-import-lib` crate feature is enabled. The following resources may also be useful for cross-compiling: - [github.com/japaric/rust-cross](https://github.com/japaric/rust-cross) is a primer on cross compiling Rust. - [github.com/rust-embedded/cross](https://github.com/rust-embedded/cross) uses Docker to make Rust cross-compilation easier. [`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config [`maturin-starter`]: https://github.com/PyO3/pyo3/tree/main/examples/maturin-starter [`setuptools-rust-starter`]: https://github.com/PyO3/pyo3/tree/main/examples/setuptools-rust-starter [`maturin`]: https://github.com/PyO3/maturin [`setuptools-rust`]: https://github.com/PyO3/setuptools-rust [PyOxidizer]: https://github.com/indygreg/PyOxidizer [`python3-dll-a`]: https://docs.rs/python3-dll-a/latest/python3_dll_a/ pyo3/guide/src/async-await.md0000644000175000017500000001075415105742312015731 0ustar bdrungbdrung# Using `async` and `await` *This feature is still in active development. See [the related issue](https://github.com/PyO3/pyo3/issues/1632).* `#[pyfunction]` and `#[pymethods]` attributes also support `async fn`. ```rust,no_run # #![allow(dead_code)] # #[cfg(feature = "experimental-async")] { use std::{thread, time::Duration}; use futures::channel::oneshot; use pyo3::prelude::*; #[pyfunction] #[pyo3(signature=(seconds, result=None))] async fn sleep(seconds: f64, result: Option) -> Option { let (tx, rx) = oneshot::channel(); thread::spawn(move || { thread::sleep(Duration::from_secs_f64(seconds)); tx.send(()).unwrap(); }); rx.await.unwrap(); result } # } ``` *Python awaitables instantiated with this method can only be awaited in *asyncio* context. Other Python async runtime may be supported in the future.* ## `Send + 'static` constraint Resulting future of an `async fn` decorated by `#[pyfunction]` must be `Send + 'static` to be embedded in a Python object. As a consequence, `async fn` parameters and return types must also be `Send + 'static`, so it is not possible to have a signature like `async fn does_not_compile<'py>(arg: Bound<'py, PyAny>) -> Bound<'py, PyAny>`. However, there is an exception for method receivers, so async methods can accept `&self`/`&mut self`. Note that this means that the class instance is borrowed for as long as the returned future is not completed, even across yield points and while waiting for I/O operations to complete. Hence, other methods cannot obtain exclusive borrows while the future is still being polled. This is the same as how async methods in Rust generally work but it is more problematic for Rust code interfacing with Python code due to pervasive shared mutability. This strongly suggests to prefer shared borrows `&self` over exclusive ones `&mut self` to avoid racy borrow check failures at runtime. ## Implicit GIL holding Even if it is not possible to pass a `py: Python<'py>` parameter to `async fn`, the GIL is still held during the execution of the future – it's also the case for regular `fn` without `Python<'py>`/`Bound<'py, PyAny>` parameter, yet the GIL is held. It is still possible to get a `Python` marker using [`Python::with_gil`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.with_gil); because `with_gil` is reentrant and optimized, the cost will be negligible. ## Release the GIL across `.await` There is currently no simple way to release the GIL when awaiting a future, *but solutions are currently in development*. Here is the advised workaround for now: ```rust,ignore use std::{ future::Future, pin::{Pin, pin}, task::{Context, Poll}, }; use pyo3::prelude::*; struct AllowThreads(F); impl Future for AllowThreads where F: Future + Unpin + Send, F::Output: Send, { type Output = F::Output; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let waker = cx.waker(); Python::with_gil(|py| { py.allow_threads(|| pin!(&mut self.0).poll(&mut Context::from_waker(waker))) }) } } ``` ## Cancellation Cancellation on the Python side can be caught using [`CancelHandle`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html) type, by annotating a function parameter with `#[pyo3(cancel_handle)]`. ```rust,no_run # #![allow(dead_code)] # #[cfg(feature = "experimental-async")] { use futures::FutureExt; use pyo3::prelude::*; use pyo3::coroutine::CancelHandle; #[pyfunction] async fn cancellable(#[pyo3(cancel_handle)] mut cancel: CancelHandle) { futures::select! { /* _ = ... => println!("done"), */ _ = cancel.cancelled().fuse() => println!("cancelled"), } } # } ``` ## The `Coroutine` type To make a Rust future awaitable in Python, PyO3 defines a [`Coroutine`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.Coroutine.html) type, which implements the Python [coroutine protocol](https://docs.python.org/3/library/collections.abc.html#collections.abc.Coroutine). Each `coroutine.send` call is translated to a `Future::poll` call. If a [`CancelHandle`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html) parameter is declared, the exception passed to `coroutine.throw` call is stored in it and can be retrieved with [`CancelHandle::cancelled`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html#method.cancelled); otherwise, it cancels the Rust future, and the exception is reraised; *The type does not yet have a public constructor until the design is finalized.* pyo3/guide/src/changelog.md0000644000175000017500000000004015105742312015423 0ustar bdrungbdrung{{#include ../../CHANGELOG.md}} pyo3/guide/src/SUMMARY.md0000644000175000017500000000345715105742312014650 0ustar bdrungbdrung# Summary [Introduction](index.md) --- - [Getting started](getting-started.md) - [Using Rust from Python](rust-from-python.md) - [Python modules](module.md) - [Python functions](function.md) - [Function signatures](function/signature.md) - [Error handling](function/error-handling.md) - [Python classes](class.md) - [Class customizations](class/protocols.md) - [Basic object customization](class/object.md) - [Emulating numeric types](class/numeric.md) - [Emulating callable objects](class/call.md) - [Thread safety](class/thread-safety.md) - [Calling Python from Rust](python-from-rust.md) - [Python object types](types.md) - [Python exceptions](exception.md) - [Calling Python functions](python-from-rust/function-calls.md) - [Executing existing Python code](python-from-rust/calling-existing-code.md) - [Type conversions](conversions.md) - [Mapping of Rust types to Python types](conversions/tables.md) - [Conversion traits](conversions/traits.md) - [Using `async` and `await`](async-await.md) - [Parallelism](parallelism.md) - [Supporting Free-Threaded Python](free-threading.md) - [Debugging](debugging.md) - [Features reference](features.md) - [Performance](performance.md) - [Advanced topics](advanced.md) - [Building and distribution](building-and-distribution.md) - [Supporting multiple Python versions](building-and-distribution/multiple-python-versions.md) - [Useful crates](ecosystem.md) - [Logging](ecosystem/logging.md) - [Tracing](ecosystem/tracing.md) - [Using `async` and `await`](ecosystem/async-await.md) - [FAQ and troubleshooting](faq.md) --- [Appendix A: Migration guide](migration.md) [Appendix B: Trait bounds](trait-bounds.md) [Appendix C: Python typing hints](python-typing-hints.md) [CHANGELOG](changelog.md) --- [Contributing](contributing.md) pyo3/guide/src/class.md0000644000175000017500000013727015105742312014621 0ustar bdrungbdrung# Python classes PyO3 exposes a group of attributes powered by Rust's proc macro system for defining Python classes as Rust structs. The main attribute is `#[pyclass]`, which is placed upon a Rust `struct` or `enum` to generate a Python type for it. They will usually also have *one* `#[pymethods]`-annotated `impl` block for the struct, which is used to define Python methods and constants for the generated Python type. (If the [`multiple-pymethods`] feature is enabled, each `#[pyclass]` is allowed to have multiple `#[pymethods]` blocks.) `#[pymethods]` may also have implementations for Python magic methods such as `__str__`. This chapter will discuss the functionality and configuration these attributes offer. Below is a list of links to the relevant section of this chapter for each: - [`#[pyclass]`](#defining-a-new-class) - [`#[pyo3(get, set)]`](#object-properties-using-pyo3get-set) - [`#[pymethods]`](#instance-methods) - [`#[new]`](#constructor) - [`#[getter]`](#object-properties-using-getter-and-setter) - [`#[setter]`](#object-properties-using-getter-and-setter) - [`#[staticmethod]`](#static-methods) - [`#[classmethod]`](#class-methods) - [`#[classattr]`](#class-attributes) - [`#[args]`](#method-arguments) - [Magic methods and slots](class/protocols.md) - [Classes as function arguments](#classes-as-function-arguments) ## Defining a new class To define a custom Python class, add the `#[pyclass]` attribute to a Rust struct or enum. ```rust # #![allow(dead_code)] use pyo3::prelude::*; #[pyclass] struct MyClass { inner: i32, } // A "tuple" struct #[pyclass] struct Number(i32); // PyO3 supports unit-only enums (which contain only unit variants) // These simple enums behave similarly to Python's enumerations (enum.Enum) #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant = 30, // PyO3 supports custom discriminants. } // PyO3 supports custom discriminants in unit-only enums #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum HttpResponse { Ok = 200, NotFound = 404, Teapot = 418, // ... } // PyO3 also supports enums with Struct and Tuple variants // These complex enums have slightly different behavior from the simple enums above // They are meant to work with instance checks and match statement patterns // The variants can be mixed and matched // Struct variants have named fields while tuple enums generate generic names for fields in order _0, _1, _2, ... // Apart from this both types are functionally identical #[pyclass] enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 }, RegularPolygon(u32, f64), Nothing(), } ``` The above example generates implementations for [`PyTypeInfo`] and [`PyClass`] for `MyClass`, `Number`, `MyEnum`, `HttpResponse`, and `Shape`. To see these generated implementations, refer to the [implementation details](#implementation-details) at the end of this chapter. ### Restrictions To integrate Rust types with Python, PyO3 needs to place some restrictions on the types which can be annotated with `#[pyclass]`. In particular, they must have no lifetime parameters, no generic parameters, and must be thread-safe. The reason for each of these is explained below. #### No lifetime parameters Rust lifetimes are used by the Rust compiler to reason about a program's memory safety. They are a compile-time only concept; there is no way to access Rust lifetimes at runtime from a dynamic language like Python. As soon as Rust data is exposed to Python, there is no guarantee that the Rust compiler can make on how long the data will live. Python is a reference-counted language and those references can be held for an arbitrarily long time which is untraceable by the Rust compiler. The only possible way to express this correctly is to require that any `#[pyclass]` does not borrow data for any lifetime shorter than the `'static` lifetime, i.e. the `#[pyclass]` cannot have any lifetime parameters. When you need to share ownership of data between Python and Rust, instead of using borrowed references with lifetimes consider using reference-counted smart pointers such as [`Arc`] or [`Py`]. #### No generic parameters A Rust `struct Foo` with a generic parameter `T` generates new compiled implementations each time it is used with a different concrete type for `T`. These new implementations are generated by the compiler at each usage site. This is incompatible with wrapping `Foo` in Python, where there needs to be a single compiled implementation of `Foo` which is integrated with the Python interpreter. Currently, the best alternative is to write a macro which expands to a new `#[pyclass]` for each instantiation you want: ```rust # #![allow(dead_code)] use pyo3::prelude::*; struct GenericClass { data: T, } macro_rules! create_interface { ($name: ident, $type: ident) => { #[pyclass] pub struct $name { inner: GenericClass<$type>, } #[pymethods] impl $name { #[new] pub fn new(data: $type) -> Self { Self { inner: GenericClass { data: data }, } } } }; } create_interface!(IntClass, i64); create_interface!(FloatClass, String); ``` #### Must be thread-safe Python objects are freely shared between threads by the Python interpreter. This means that: - Python objects may be created and destroyed by different Python threads; therefore `#[pyclass]` objects must be `Send`. - Python objects may be accessed by multiple Python threads simultaneously; therefore `#[pyclass]` objects must be `Sync`. For now, don't worry about these requirements; simple classes will already be thread-safe. There is a [detailed discussion on thread-safety](./class/thread-safety.md) later in the guide. ## Constructor By default, it is not possible to create an instance of a custom class from Python code. To declare a constructor, you need to define a method and annotate it with the `#[new]` attribute. Only Python's `__new__` method can be specified, `__init__` is not available. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Number(value) } } ``` Alternatively, if your `new` method may fail you can return `PyResult`. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::exceptions::PyValueError; # #[pyclass] # struct Nonzero(i32); # #[pymethods] impl Nonzero { #[new] fn py_new(value: i32) -> PyResult { if value == 0 { Err(PyValueError::new_err("cannot be zero")) } else { Ok(Nonzero(value)) } } } ``` If you want to return an existing object (for example, because your `new` method caches the values it returns), `new` can return `pyo3::Py`. As you can see, the Rust method name is not important here; this way you can still, use `new()` for a Rust-level constructor. If no method marked with `#[new]` is declared, object instances can only be created from Rust, but not from Python. For arguments, see the [`Method arguments`](#method-arguments) section below. ## Adding the class to a module The next step is to create the module initializer and add our class to it: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # #[pyclass] # struct Number(i32); # #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } ``` ## Bound and interior mutability It is often useful to turn a `#[pyclass]` type `T` into a Python object and access it from Rust code. The [`Py`] and [`Bound<'py, T>`] smart pointers are the ways to represent a Python object in PyO3's API. More detail can be found about them [in the Python objects](./types.md#pyo3s-smart-pointers) section of the guide. Most Python objects do not offer exclusive (`&mut`) access (see the [section on Python's memory model](./python-from-rust.md#pythons-memory-model)). However, Rust structs wrapped as Python objects (called `pyclass` types) often *do* need `&mut` access. Due to the GIL, PyO3 *can* guarantee exclusive access to them. The Rust borrow checker cannot reason about `&mut` references once an object's ownership has been passed to the Python interpreter. This means that borrow checking is done at runtime using with a scheme very similar to `std::cell::RefCell`. This is known as [interior mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html). Users who are familiar with `RefCell` can use `Py` and `Bound<'py, T>` just like `RefCell`. For users who are not very familiar with `RefCell`, here is a reminder of Rust's rules of borrowing: - At any given time, you can have either (but not both of) one mutable reference or any number of immutable references. - References can never outlast the data they refer to. `Py` and `Bound<'py, T>`, like `RefCell`, ensure these borrowing rules by tracking references at runtime. ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { #[pyo3(get)] num: i32, } Python::with_gil(|py| { let obj = Bound::new(py, MyClass { num: 3 }).unwrap(); { let obj_ref = obj.borrow(); // Get PyRef assert_eq!(obj_ref.num, 3); // You cannot get PyRefMut unless all PyRefs are dropped assert!(obj.try_borrow_mut().is_err()); } { let mut obj_mut = obj.borrow_mut(); // Get PyRefMut obj_mut.num = 5; // You cannot get any other refs until the PyRefMut is dropped assert!(obj.try_borrow().is_err()); assert!(obj.try_borrow_mut().is_err()); } // You can convert `Bound` to a Python object pyo3::py_run!(py, obj, "assert obj.num == 5"); }); ``` A `Bound<'py, T>` is restricted to the GIL lifetime `'py`. To make the object longer lived (for example, to store it in a struct on the Rust side), use `Py`. `Py` needs a `Python<'_>` token to allow access: ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { num: i32, } fn return_myclass() -> Py { Python::with_gil(|py| Py::new(py, MyClass { num: 1 }).unwrap()) } let obj = return_myclass(); Python::with_gil(move |py| { let bound = obj.bind(py); // Py::bind returns &Bound<'py, MyClass> let obj_ref = bound.borrow(); // Get PyRef assert_eq!(obj_ref.num, 1); }); ``` ### frozen classes: Opting out of interior mutability As detailed above, runtime borrow checking is currently enabled by default. But a class can opt of out it by declaring itself `frozen`. It can still use interior mutability via standard Rust types like `RefCell` or `Mutex`, but it is not bound to the implementation provided by PyO3 and can choose the most appropriate strategy on field-by-field basis. Classes which are `frozen` and also `Sync`, e.g. they do use `Mutex` but not `RefCell`, can be accessed without needing the Python GIL via the `Bound::get` and `Py::get` methods: ```rust use std::sync::atomic::{AtomicUsize, Ordering}; # use pyo3::prelude::*; #[pyclass(frozen)] struct FrozenCounter { value: AtomicUsize, } let py_counter: Py = Python::with_gil(|py| { let counter = FrozenCounter { value: AtomicUsize::new(0), }; Py::new(py, counter).unwrap() }); py_counter.get().value.fetch_add(1, Ordering::Relaxed); Python::with_gil(move |_py| drop(py_counter)); ``` Frozen classes are likely to become the default thereby guiding the PyO3 ecosystem towards a more deliberate application of interior mutability. Eventually, this should enable further optimizations of PyO3's internals and avoid downstream code paying the cost of interior mutability when it is not actually required. ## Customizing the class {{#include ../pyclass-parameters.md}} These parameters are covered in various sections of this guide. ### Return type Generally, `#[new]` methods have to return `T: Into>` or `PyResult where T: Into>`. For constructors that may fail, you should wrap the return type in a PyResult as well. Consult the table below to determine which type your constructor should return: | | **Cannot fail** | **May fail** | |-----------------------------|---------------------------|-----------------------------------| |**No inheritance** | `T` | `PyResult` | |**Inheritance(T Inherits U)**| `(T, U)` | `PyResult<(T, U)>` | |**Inheritance(General Case)**| [`PyClassInitializer`] | `PyResult>` | ## Inheritance By default, `object`, i.e. `PyAny` is used as the base class. To override this default, use the `extends` parameter for `pyclass` with the full path to the base class. Currently, only classes defined in Rust and builtins provided by PyO3 can be inherited from; inheriting from other classes defined in Python is not yet supported ([#991](https://github.com/PyO3/pyo3/issues/991)). For convenience, `(T, U)` implements `Into>` where `U` is the base class of `T`. But for a more deeply nested inheritance, you have to return `PyClassInitializer` explicitly. To get a parent class from a child, use [`PyRef`] instead of `&self` for methods, or [`PyRefMut`] instead of `&mut self`. Then you can access a parent class by `self_.as_super()` as `&PyRef`, or by `self_.into_super()` as `PyRef` (and similar for the `PyRefMut` case). For convenience, `self_.as_ref()` can also be used to get `&Self::BaseClass` directly; however, this approach does not let you access base classes higher in the inheritance hierarchy, for which you would need to chain multiple `as_super` or `into_super` calls. ```rust # use pyo3::prelude::*; #[pyclass(subclass)] struct BaseClass { val1: usize, } #[pymethods] impl BaseClass { #[new] fn new() -> Self { BaseClass { val1: 10 } } pub fn method1(&self) -> PyResult { Ok(self.val1) } } #[pyclass(extends=BaseClass, subclass)] struct SubClass { val2: usize, } #[pymethods] impl SubClass { #[new] fn new() -> (Self, BaseClass) { (SubClass { val2: 15 }, BaseClass::new()) } fn method2(self_: PyRef<'_, Self>) -> PyResult { let super_ = self_.as_super(); // Get &PyRef super_.method1().map(|x| x * self_.val2) } } #[pyclass(extends=SubClass)] struct SubSubClass { val3: usize, } #[pymethods] impl SubSubClass { #[new] fn new() -> PyClassInitializer { PyClassInitializer::from(SubClass::new()).add_subclass(SubSubClass { val3: 20 }) } fn method3(self_: PyRef<'_, Self>) -> PyResult { let base = self_.as_super().as_super(); // Get &PyRef<'_, BaseClass> base.method1().map(|x| x * self_.val3) } fn method4(self_: PyRef<'_, Self>) -> PyResult { let v = self_.val3; let super_ = self_.into_super(); // Get PyRef<'_, SubClass> SubClass::method2(super_).map(|x| x * v) } fn get_values(self_: PyRef<'_, Self>) -> (usize, usize, usize) { let val1 = self_.as_super().as_super().val1; let val2 = self_.as_super().val2; (val1, val2, self_.val3) } fn double_values(mut self_: PyRefMut<'_, Self>) { self_.as_super().as_super().val1 *= 2; self_.as_super().val2 *= 2; self_.val3 *= 2; } #[staticmethod] fn factory_method(py: Python<'_>, val: usize) -> PyResult { let base = PyClassInitializer::from(BaseClass::new()); let sub = base.add_subclass(SubClass { val2: val }); if val % 2 == 0 { Ok(Py::new(py, sub)?.into_any()) } else { let sub_sub = sub.add_subclass(SubSubClass { val3: val }); Ok(Py::new(py, sub_sub)?.into_any()) } } } # Python::with_gil(|py| { # let subsub = pyo3::Py::new(py, SubSubClass::new()).unwrap(); # pyo3::py_run!(py, subsub, "assert subsub.method1() == 10"); # pyo3::py_run!(py, subsub, "assert subsub.method2() == 150"); # pyo3::py_run!(py, subsub, "assert subsub.method3() == 200"); # pyo3::py_run!(py, subsub, "assert subsub.method4() == 3000"); # pyo3::py_run!(py, subsub, "assert subsub.get_values() == (10, 15, 20)"); # pyo3::py_run!(py, subsub, "assert subsub.double_values() == None"); # pyo3::py_run!(py, subsub, "assert subsub.get_values() == (20, 30, 40)"); # let subsub = SubSubClass::factory_method(py, 2).unwrap(); # let subsubsub = SubSubClass::factory_method(py, 3).unwrap(); # let cls = py.get_type::(); # pyo3::py_run!(py, subsub cls, "assert not isinstance(subsub, cls)"); # pyo3::py_run!(py, subsubsub cls, "assert isinstance(subsubsub, cls)"); # }); ``` You can inherit native types such as `PyDict`, if they implement [`PySizedLayout`]({{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PySizedLayout.html). This is not supported when building for the Python limited API (aka the `abi3` feature of PyO3). To convert between the Rust type and its native base class, you can take `slf` as a Python object. To access the Rust fields use `slf.borrow()` or `slf.borrow_mut()`, and to access the base class use `slf.downcast::()`. ```rust # #[cfg(not(Py_LIMITED_API))] { # use pyo3::prelude::*; use pyo3::types::PyDict; use std::collections::HashMap; #[pyclass(extends=PyDict)] #[derive(Default)] struct DictWithCounter { counter: HashMap, } #[pymethods] impl DictWithCounter { #[new] fn new() -> Self { Self::default() } fn set(slf: &Bound<'_, Self>, key: String, value: Bound<'_, PyAny>) -> PyResult<()> { slf.borrow_mut().counter.entry(key.clone()).or_insert(0); let dict = slf.downcast::()?; dict.set_item(key, value) } } # Python::with_gil(|py| { # let cnt = pyo3::Py::new(py, DictWithCounter::new()).unwrap(); # pyo3::py_run!(py, cnt, "cnt.set('abc', 10); assert cnt['abc'] == 10") # }); # } ``` If `SubClass` does not provide a base class initialization, the compilation fails. ```rust,compile_fail # use pyo3::prelude::*; #[pyclass] struct BaseClass { val1: usize, } #[pyclass(extends=BaseClass)] struct SubClass { val2: usize, } #[pymethods] impl SubClass { #[new] fn new() -> Self { SubClass { val2: 15 } } } ``` The `__new__` constructor of a native base class is called implicitly when creating a new instance from Python. Be sure to accept arguments in the `#[new]` method that you want the base class to get, even if they are not used in that `fn`: ```rust # #[allow(dead_code)] # #[cfg(not(Py_LIMITED_API))] { # use pyo3::prelude::*; use pyo3::types::PyDict; #[pyclass(extends=PyDict)] struct MyDict { private: i32, } #[pymethods] impl MyDict { #[new] #[pyo3(signature = (*args, **kwargs))] fn new(args: &Bound<'_, PyAny>, kwargs: Option<&Bound<'_, PyAny>>) -> Self { Self { private: 0 } } // some custom methods that use `private` here... } # Python::with_gil(|py| { # let cls = py.get_type::(); # pyo3::py_run!(py, cls, "cls(a=1, b=2)") # }); # } ``` Here, the `args` and `kwargs` allow creating instances of the subclass passing initial items, such as `MyDict(item_sequence)` or `MyDict(a=1, b=2)`. ## Object properties PyO3 supports two ways to add properties to your `#[pyclass]`: - For simple struct fields with no side effects, a `#[pyo3(get, set)]` attribute can be added directly to the field definition in the `#[pyclass]`. - For properties which require computation you can define `#[getter]` and `#[setter]` functions in the [`#[pymethods]`](#instance-methods) block. We'll cover each of these in the following sections. ### Object properties using `#[pyo3(get, set)]` For simple cases where a member variable is just read and written with no side effects, you can declare getters and setters in your `#[pyclass]` field definition using the `pyo3` attribute, like in the example below: ```rust # use pyo3::prelude::*; # #[allow(dead_code)] #[pyclass] struct MyClass { #[pyo3(get, set)] num: i32, } ``` The above would make the `num` field available for reading and writing as a `self.num` Python property. To expose the property with a different name to the field, specify this alongside the rest of the options, e.g. `#[pyo3(get, set, name = "custom_name")]`. Properties can be readonly or writeonly by using just `#[pyo3(get)]` or `#[pyo3(set)]` respectively. To use these annotations, your field type must implement some conversion traits: - For `get` the field type must implement both `IntoPy` and `Clone`. - For `set` the field type must implement `FromPyObject`. For example, implementations of those traits are provided for the `Cell` type, if the inner type also implements the trait. This means you can use `#[pyo3(get, set)]` on fields wrapped in a `Cell`. ### Object properties using `#[getter]` and `#[setter]` For cases which don't satisfy the `#[pyo3(get, set)]` trait requirements, or need side effects, descriptor methods can be defined in a `#[pymethods]` `impl` block. This is done using the `#[getter]` and `#[setter]` attributes, like in the example below: ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { num: i32, } #[pymethods] impl MyClass { #[getter] fn num(&self) -> PyResult { Ok(self.num) } } ``` A getter or setter's function name is used as the property name by default. There are several ways how to override the name. If a function name starts with `get_` or `set_` for getter or setter respectively, the descriptor name becomes the function name with this prefix removed. This is also useful in case of Rust keywords like `type` ([raw identifiers](https://doc.rust-lang.org/edition-guide/rust-2018/module-system/raw-identifiers.html) can be used since Rust 2018). ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[getter] fn get_num(&self) -> PyResult { Ok(self.num) } #[setter] fn set_num(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` In this case, a property `num` is defined and available from Python code as `self.num`. Both the `#[getter]` and `#[setter]` attributes accept one parameter. If this parameter is specified, it is used as the property name, i.e. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[getter(number)] fn num(&self) -> PyResult { Ok(self.num) } #[setter(number)] fn set_num(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` In this case, the property `number` is defined and available from Python code as `self.number`. Attributes defined by `#[setter]` or `#[pyo3(set)]` will always raise `AttributeError` on `del` operations. Support for defining custom `del` behavior is tracked in [#1778](https://github.com/PyO3/pyo3/issues/1778). ## Instance methods To define a Python compatible method, an `impl` block for your struct has to be annotated with the `#[pymethods]` attribute. PyO3 generates Python compatible wrappers for all functions in this block with some variations, like descriptors, class method static methods, etc. Since Rust allows any number of `impl` blocks, you can easily split methods between those accessible to Python (and Rust) and those accessible only to Rust. However to have multiple `#[pymethods]`-annotated `impl` blocks for the same struct you must enable the [`multiple-pymethods`] feature of PyO3. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { fn method1(&self) -> PyResult { Ok(10) } fn set_method(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` Calls to these methods are protected by the GIL, so both `&self` and `&mut self` can be used. The return type must be `PyResult` or `T` for some `T` that implements `IntoPy`; the latter is allowed if the method cannot raise Python exceptions. A `Python` parameter can be specified as part of method signature, in this case the `py` argument gets injected by the method wrapper, e.g. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { fn method2(&self, py: Python<'_>) -> PyResult { Ok(10) } } ``` From the Python perspective, the `method2` in this example does not accept any arguments. ## Class methods To create a class method for a custom class, the method needs to be annotated with the `#[classmethod]` attribute. This is the equivalent of the Python decorator `@classmethod`. ```rust # use pyo3::prelude::*; # use pyo3::types::PyType; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { #[classmethod] fn cls_method(cls: &Bound<'_, PyType>) -> PyResult { Ok(10) } } ``` Declares a class method callable from Python. * The first parameter is the type object of the class on which the method is called. This may be the type object of a derived class. * The first parameter implicitly has type `&Bound<'_, PyType>`. * For details on `parameter-list`, see the documentation of `Method arguments` section. * The return type must be `PyResult` or `T` for some `T` that implements `IntoPy`. ### Constructors which accept a class argument To create a constructor which takes a positional class argument, you can combine the `#[classmethod]` and `#[new]` modifiers: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyType; # #[pyclass] # struct BaseClass(PyObject); # #[pymethods] impl BaseClass { #[new] #[classmethod] fn py_new(cls: &Bound<'_, PyType>) -> PyResult { // Get an abstract attribute (presumably) declared on a subclass of this class. let subclass_attr: Bound<'_, PyAny> = cls.getattr("a_class_attr")?; Ok(Self(subclass_attr.unbind())) } } ``` ## Static methods To create a static method for a custom class, the method needs to be annotated with the `#[staticmethod]` attribute. The return type must be `T` or `PyResult` for some `T` that implements `IntoPy`. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { #[staticmethod] fn static_method(param1: i32, param2: &str) -> PyResult { Ok(10) } } ``` ## Class attributes To create a class attribute (also called [class variable][classattr]), a method without any arguments can be annotated with the `#[classattr]` attribute. ```rust,no_run # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} #[pymethods] impl MyClass { #[classattr] fn my_attribute() -> String { "hello".to_string() } } Python::with_gil(|py| { let my_class = py.get_type::(); pyo3::py_run!(py, my_class, "assert my_class.my_attribute == 'hello'") }); ``` > Note: if the method has a `Result` return type and returns an `Err`, PyO3 will panic during class creation. If the class attribute is defined with `const` code only, one can also annotate associated constants: ```rust,no_run # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} #[pymethods] impl MyClass { #[classattr] const MY_CONST_ATTRIBUTE: &'static str = "foobar"; } ``` ## Classes as function arguments Free functions defined using `#[pyfunction]` interact with classes through the same mechanisms as the self parameters of instance methods, i.e. they can take GIL-bound references, GIL-bound reference wrappers or GIL-independent references: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] struct MyClass { my_field: i32, } // Take a reference when the underlying `Bound` is irrelevant. #[pyfunction] fn increment_field(my_class: &mut MyClass) { my_class.my_field += 1; } // Take a reference wrapper when borrowing should be automatic, // but interaction with the underlying `Bound` is desired. #[pyfunction] fn print_field(my_class: PyRef<'_, MyClass>) { println!("{}", my_class.my_field); } // Take a reference to the underlying Bound // when borrowing needs to be managed manually. #[pyfunction] fn increment_then_print_field(my_class: &Bound<'_, MyClass>) { my_class.borrow_mut().my_field += 1; println!("{}", my_class.borrow().my_field); } // Take a GIL-independent reference when you want to store the reference elsewhere. #[pyfunction] fn print_refcnt(my_class: Py, py: Python<'_>) { println!("{}", my_class.get_refcnt(py)); } ``` Classes can also be passed by value if they can be cloned, i.e. they automatically implement `FromPyObject` if they implement `Clone`, e.g. via `#[derive(Clone)]`: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] #[derive(Clone)] struct MyClass { my_field: Box, } #[pyfunction] fn dissamble_clone(my_class: MyClass) { let MyClass { mut my_field } = my_class; *my_field += 1; } ``` Note that `#[derive(FromPyObject)]` on a class is usually not useful as it tries to construct a new Rust value by filling in the fields by looking up attributes of any given Python value. ## Method arguments Similar to `#[pyfunction]`, the `#[pyo3(signature = (...))]` attribute can be used to specify the way that `#[pymethods]` accept arguments. Consult the documentation for [`function signatures`](./function/signature.md) to see the parameters this attribute accepts. The following example defines a class `MyClass` with a method `method`. This method has a signature that sets default values for `num` and `name`, and indicates that `py_args` should collect all extra positional arguments and `py_kwargs` all extra keyword arguments: ```rust,no_run # use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; # # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[new] #[pyo3(signature = (num=-1))] fn new(num: i32) -> Self { MyClass { num } } #[pyo3(signature = (num=10, *py_args, name="Hello", **py_kwargs))] fn method( &mut self, num: i32, py_args: &Bound<'_, PyTuple>, name: &str, py_kwargs: Option<&Bound<'_, PyDict>>, ) -> String { let num_before = self.num; self.num = num; format!( "num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} ", num, num_before, py_args, name, py_kwargs, ) } } ``` In Python, this might be used like: ```python >>> import mymodule >>> mc = mymodule.MyClass() >>> print(mc.method(44, False, "World", 666, x=44, y=55)) py_args=('World', 666), py_kwargs=Some({'x': 44, 'y': 55}), name=Hello, num=44, num_before=-1 >>> print(mc.method(num=-1, name="World")) py_args=(), py_kwargs=None, name=World, num=-1, num_before=44 ``` The [`#[pyo3(text_signature = "...")`](./function/signature.md#overriding-the-generated-signature) option for `#[pyfunction]` also works for `#[pymethods]`. ```rust # #![allow(dead_code)] use pyo3::prelude::*; use pyo3::types::PyType; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(text_signature = "(c, d)")] fn new(c: i32, d: &str) -> Self { Self {} } // the self argument should be written $self #[pyo3(text_signature = "($self, e, f)")] fn my_method(&self, e: i32, f: i32) -> i32 { e + f } // similarly for classmethod arguments, use $cls #[classmethod] #[pyo3(text_signature = "($cls, e, f)")] fn my_class_method(cls: &Bound<'_, PyType>, e: i32, f: i32) -> i32 { e + f } #[staticmethod] #[pyo3(text_signature = "(e, f)")] fn my_static_method(e: i32, f: i32) -> i32 { e + f } } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let inspect = PyModule::import(py, "inspect")?.getattr("signature")?; # let module = PyModule::new(py, "my_module")?; # module.add_class::()?; # let class = module.getattr("MyClass")?; # # if cfg!(not(Py_LIMITED_API)) || py.version_info() >= (3, 10) { # let doc: String = class.getattr("__doc__")?.extract()?; # assert_eq!(doc, ""); # # let sig: String = inspect # .call1((&class,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(c, d)"); # } else { # let doc: String = class.getattr("__doc__")?.extract()?; # assert_eq!(doc, ""); # # inspect.call1((&class,)).expect_err("`text_signature` on classes is not compatible with compilation in `abi3` mode until Python 3.10 or greater"); # } # # { # let method = class.getattr("my_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(self, /, e, f)"); # } # # { # let method = class.getattr("my_class_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(e, f)"); // inspect.signature skips the $cls arg # } # # { # let method = class.getattr("my_static_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(e, f)"); # } # # Ok(()) # }) # } ``` Note that `text_signature` on `#[new]` is not compatible with compilation in `abi3` mode until Python 3.10 or greater. ### Method receivers and lifetime elision PyO3 supports writing instance methods using the normal method receivers for shared `&self` and unique `&mut self` references. This interacts with [lifetime elision][lifetime-elision] insofar as the lifetime of a such a receiver is assigned to all elided output lifetime parameters. This is a good default for general Rust code where return values are more likely to borrow from the receiver than from the other arguments, if they contain any lifetimes at all. However, when returning bound references `Bound<'py, T>` in PyO3-based code, the GIL lifetime `'py` should usually be derived from a GIL token `py: Python<'py>` passed as an argument instead of the receiver. Specifically, signatures like ```rust,ignore fn frobnicate(&self, py: Python) -> Bound; ``` will not work as they are inferred as ```rust,ignore fn frobnicate<'a, 'py>(&'a self, py: Python<'py>) -> Bound<'a, Foo>; ``` instead of the intended ```rust,ignore fn frobnicate<'a, 'py>(&'a self, py: Python<'py>) -> Bound<'py, Foo>; ``` and should usually be written as ```rust,ignore fn frobnicate<'py>(&self, py: Python<'py>) -> Bound<'py, Foo>; ``` The same problem does not exist for `#[pyfunction]`s as the special case for receiver lifetimes does not apply and indeed a signature like ```rust,ignore fn frobnicate(bar: &Bar, py: Python) -> Bound; ``` will yield compiler error [E0106 "missing lifetime specifier"][compiler-error-e0106]. ## `#[pyclass]` enums Enum support in PyO3 comes in two flavors, depending on what kind of variants the enum has: simple and complex. ### Simple enums A simple enum (a.k.a. C-like enum) has only unit variants. PyO3 adds a class attribute for each variant, so you can access them in Python without defining `#[new]`. PyO3 also provides default implementations of `__richcmp__` and `__int__`, so they can be compared using `==`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant, } Python::with_gil(|py| { let x = Py::new(py, MyEnum::Variant).unwrap(); let y = Py::new(py, MyEnum::OtherVariant).unwrap(); let cls = py.get_type::(); pyo3::py_run!(py, x y cls, r#" assert x == cls.Variant assert y == cls.OtherVariant assert x != y "#) }) ``` You can also convert your simple enums into `int`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant = 10, } Python::with_gil(|py| { let cls = py.get_type::(); let x = MyEnum::Variant as i32; // The exact value is assigned by the compiler. pyo3::py_run!(py, cls x, r#" assert int(cls.Variant) == x assert int(cls.OtherVariant) == 10 "#) }) ``` PyO3 also provides `__repr__` for enums: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum{ Variant, OtherVariant, } Python::with_gil(|py| { let cls = py.get_type::(); let x = Py::new(py, MyEnum::Variant).unwrap(); pyo3::py_run!(py, cls x, r#" assert repr(x) == 'MyEnum.Variant' assert repr(cls.OtherVariant) == 'MyEnum.OtherVariant' "#) }) ``` All methods defined by PyO3 can be overridden. For example here's how you override `__repr__`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Answer = 42, } #[pymethods] impl MyEnum { fn __repr__(&self) -> &'static str { "42" } } Python::with_gil(|py| { let cls = py.get_type::(); pyo3::py_run!(py, cls, "assert repr(cls.Answer) == '42'") }) ``` Enums and their variants can also be renamed using `#[pyo3(name)]`. ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int, name = "RenamedEnum")] #[derive(PartialEq)] enum MyEnum { #[pyo3(name = "UPPERCASE")] Variant, } Python::with_gil(|py| { let x = Py::new(py, MyEnum::Variant).unwrap(); let cls = py.get_type::(); pyo3::py_run!(py, x cls, r#" assert repr(x) == 'RenamedEnum.UPPERCASE' assert x == cls.UPPERCASE "#) }) ``` Ordering of enum variants is optionally added using `#[pyo3(ord)]`. *Note: Implementation of the `PartialOrd` trait is required when passing the `ord` argument. If not implemented, a compile time error is raised.* ```rust # use pyo3::prelude::*; #[pyclass(eq, ord)] #[derive(PartialEq, PartialOrd)] enum MyEnum{ A, B, C, } Python::with_gil(|py| { let cls = py.get_type::(); let a = Py::new(py, MyEnum::A).unwrap(); let b = Py::new(py, MyEnum::B).unwrap(); let c = Py::new(py, MyEnum::C).unwrap(); pyo3::py_run!(py, cls a b c, r#" assert (a < b) == True assert (c <= b) == False assert (c > a) == True "#) }) ``` You may not use enums as a base class or let enums inherit from other classes. ```rust,compile_fail # use pyo3::prelude::*; #[pyclass(subclass)] enum BadBase { Var1, } ``` ```rust,compile_fail # use pyo3::prelude::*; #[pyclass(subclass)] struct Base; #[pyclass(extends=Base)] enum BadSubclass { Var1, } ``` `#[pyclass]` enums are currently not interoperable with `IntEnum` in Python. ### Complex enums An enum is complex if it has any non-unit (struct or tuple) variants. PyO3 supports only struct and tuple variants in a complex enum. Unit variants aren't supported at present (the recommendation is to use an empty tuple enum instead). PyO3 adds a class attribute for each variant, which may be used to construct values and in match patterns. PyO3 also provides getter methods for all fields of each variant. ```rust # use pyo3::prelude::*; #[pyclass] enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 }, RegularPolygon(u32, f64), Nothing { }, } # #[cfg(Py_3_10)] Python::with_gil(|py| { let circle = Shape::Circle { radius: 10.0 }.into_pyobject(py)?; let square = Shape::RegularPolygon(4, 10.0).into_pyobject(py)?; let cls = py.get_type::(); pyo3::py_run!(py, circle square cls, r#" assert isinstance(circle, cls) assert isinstance(circle, cls.Circle) assert circle.radius == 10.0 assert isinstance(square, cls) assert isinstance(square, cls.RegularPolygon) assert square[0] == 4 # Gets _0 field assert square[1] == 10.0 # Gets _1 field def count_vertices(cls, shape): match shape: case cls.Circle(): return 0 case cls.Rectangle(): return 4 case cls.RegularPolygon(n): return n case cls.Nothing(): return 0 assert count_vertices(cls, circle) == 0 assert count_vertices(cls, square) == 4 "#); # Ok::<_, PyErr>(()) }) # .unwrap(); ``` WARNING: `Py::new` and `.into_pyobject` are currently inconsistent. Note how the constructed value is _not_ an instance of the specific variant. For this reason, constructing values is only recommended using `.into_pyobject`. ```rust # use pyo3::prelude::*; #[pyclass] enum MyEnum { Variant { i: i32 }, } Python::with_gil(|py| { let x = Py::new(py, MyEnum::Variant { i: 42 }).unwrap(); let cls = py.get_type::(); pyo3::py_run!(py, x cls, r#" assert isinstance(x, cls) assert not isinstance(x, cls.Variant) "#) }) ``` The constructor of each generated class can be customized using the `#[pyo3(constructor = (...))]` attribute. This uses the same syntax as the [`#[pyo3(signature = (...))]`](function/signature.md) attribute on function and methods and supports the same options. To apply this attribute simply place it on top of a variant in a `#[pyclass]` complex enum as shown below: ```rust # use pyo3::prelude::*; #[pyclass] enum Shape { #[pyo3(constructor = (radius=1.0))] Circle { radius: f64 }, #[pyo3(constructor = (*, width, height))] Rectangle { width: f64, height: f64 }, #[pyo3(constructor = (side_count, radius=1.0))] RegularPolygon { side_count: u32, radius: f64 }, Nothing { }, } # #[cfg(Py_3_10)] Python::with_gil(|py| { let cls = py.get_type::(); pyo3::py_run!(py, cls, r#" circle = cls.Circle() assert isinstance(circle, cls) assert isinstance(circle, cls.Circle) assert circle.radius == 1.0 square = cls.Rectangle(width = 1, height = 1) assert isinstance(square, cls) assert isinstance(square, cls.Rectangle) assert square.width == 1 assert square.height == 1 hexagon = cls.RegularPolygon(6) assert isinstance(hexagon, cls) assert isinstance(hexagon, cls.RegularPolygon) assert hexagon.side_count == 6 assert hexagon.radius == 1 "#) }) ``` ## Implementation details The `#[pyclass]` macros rely on a lot of conditional code generation: each `#[pyclass]` can optionally have a `#[pymethods]` block. To support this flexibility the `#[pyclass]` macro expands to a blob of boilerplate code which sets up the structure for ["dtolnay specialization"](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md). This implementation pattern enables the Rust compiler to use `#[pymethods]` implementations when they are present, and fall back to default (empty) definitions when they are not. This simple technique works for the case when there is zero or one implementations. To support multiple `#[pymethods]` for a `#[pyclass]` (in the [`multiple-pymethods`] feature), a registry mechanism provided by the [`inventory`](https://github.com/dtolnay/inventory) crate is used instead. This collects `impl`s at library load time, but isn't supported on all platforms. See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) for more details. The `#[pyclass]` macro expands to roughly the code seen below. The `PyClassImplCollector` is the type used internally by PyO3 for dtolnay specialization: ```rust # #[cfg(not(feature = "multiple-pymethods"))] { # use pyo3::prelude::*; // Note: the implementation differs slightly with the `multiple-pymethods` feature enabled. # #[allow(dead_code)] struct MyClass { # #[allow(dead_code)] num: i32, } impl pyo3::types::DerefToPyAny for MyClass {} unsafe impl pyo3::type_object::PyTypeInfo for MyClass { const NAME: &'static str = "MyClass"; const MODULE: ::std::option::Option<&'static str> = ::std::option::Option::None; #[inline] fn type_object_raw(py: pyo3::Python<'_>) -> *mut pyo3::ffi::PyTypeObject { ::lazy_type_object() .get_or_init(py) .as_type_ptr() } } impl pyo3::PyClass for MyClass { type Frozen = pyo3::pyclass::boolean_struct::False; } impl<'a, 'py> pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py, false> for &'a MyClass { type Holder = ::std::option::Option>; #[inline] fn extract(obj: &'a pyo3::Bound<'py, PyAny>, holder: &'a mut Self::Holder) -> pyo3::PyResult { pyo3::impl_::extract_argument::extract_pyclass_ref(obj, holder) } } impl<'a, 'py> pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py, false> for &'a mut MyClass { type Holder = ::std::option::Option>; #[inline] fn extract(obj: &'a pyo3::Bound<'py, PyAny>, holder: &'a mut Self::Holder) -> pyo3::PyResult { pyo3::impl_::extract_argument::extract_pyclass_ref_mut(obj, holder) } } impl pyo3::impl_::pyclass::PyClassImpl for MyClass { const IS_BASETYPE: bool = false; const IS_SUBCLASS: bool = false; const IS_MAPPING: bool = false; const IS_SEQUENCE: bool = false; type BaseType = PyAny; type ThreadChecker = pyo3::impl_::pyclass::SendablePyClass; type PyClassMutability = <::PyClassMutability as pyo3::impl_::pycell::PyClassMutability>::MutableChild; type Dict = pyo3::impl_::pyclass::PyClassDummySlot; type WeakRef = pyo3::impl_::pyclass::PyClassDummySlot; type BaseNativeType = pyo3::PyAny; fn items_iter() -> pyo3::impl_::pyclass::PyClassItemsIter { use pyo3::impl_::pyclass::*; let collector = PyClassImplCollector::::new(); static INTRINSIC_ITEMS: PyClassItems = PyClassItems { slots: &[], methods: &[] }; PyClassItemsIter::new(&INTRINSIC_ITEMS, collector.py_methods()) } fn lazy_type_object() -> &'static pyo3::impl_::pyclass::LazyTypeObject { use pyo3::impl_::pyclass::LazyTypeObject; static TYPE_OBJECT: LazyTypeObject = LazyTypeObject::new(); &TYPE_OBJECT } fn doc(py: Python<'_>) -> pyo3::PyResult<&'static ::std::ffi::CStr> { use pyo3::impl_::pyclass::*; static DOC: pyo3::sync::GILOnceCell<::std::borrow::Cow<'static, ::std::ffi::CStr>> = pyo3::sync::GILOnceCell::new(); DOC.get_or_try_init(py, || { let collector = PyClassImplCollector::::new(); build_pyclass_doc(::NAME, pyo3::ffi::c_str!(""), collector.new_text_signature()) }).map(::std::ops::Deref::deref) } } # Python::with_gil(|py| { # let cls = py.get_type::(); # pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'") # }); # } ``` [`PyTypeInfo`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeInfo.html [`Py`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html [`Bound<'_, T>`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html [`PyClass`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/trait.PyClass.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html [`PyClassInitializer`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass_init/struct.PyClassInitializer.html [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html [classattr]: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables [`multiple-pymethods`]: features.md#multiple-pymethods [lifetime-elision]: https://doc.rust-lang.org/reference/lifetime-elision.html [compiler-error-e0106]: https://doc.rust-lang.org/error_codes/E0106.html pyo3/guide/src/performance.md0000644000175000017500000001527015105742312016010 0ustar bdrungbdrung# Performance To achieve the best possible performance, it is useful to be aware of several tricks and sharp edges concerning PyO3's API. ## `extract` versus `downcast` Pythonic API implemented using PyO3 are often polymorphic, i.e. they will accept `&Bound<'_, PyAny>` and try to turn this into multiple more concrete types to which the requested operation is applied. This often leads to chains of calls to `extract`, e.g. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::{exceptions::PyTypeError, types::PyList}; fn frobnicate_list<'py>(list: &Bound<'_, PyList>) -> PyResult> { todo!() } fn frobnicate_vec<'py>(vec: Vec>) -> PyResult> { todo!() } #[pyfunction] fn frobnicate<'py>(value: &Bound<'py, PyAny>) -> PyResult> { if let Ok(list) = value.extract::>() { frobnicate_list(&list) } else if let Ok(vec) = value.extract::>>() { frobnicate_vec(vec) } else { Err(PyTypeError::new_err("Cannot frobnicate that type.")) } } ``` This suboptimal as the `FromPyObject` trait requires `extract` to have a `Result` return type. For native types like `PyList`, it faster to use `downcast` (which `extract` calls internally) when the error value is ignored. This avoids the costly conversion of a `PyDowncastError` to a `PyErr` required to fulfil the `FromPyObject` contract, i.e. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::{exceptions::PyTypeError, types::PyList}; # fn frobnicate_list<'py>(list: &Bound<'_, PyList>) -> PyResult> { todo!() } # fn frobnicate_vec<'py>(vec: Vec>) -> PyResult> { todo!() } # #[pyfunction] fn frobnicate<'py>(value: &Bound<'py, PyAny>) -> PyResult> { // Use `downcast` instead of `extract` as turning `PyDowncastError` into `PyErr` is quite costly. if let Ok(list) = value.downcast::() { frobnicate_list(list) } else if let Ok(vec) = value.extract::>>() { frobnicate_vec(vec) } else { Err(PyTypeError::new_err("Cannot frobnicate that type.")) } } ``` ## Access to Bound implies access to GIL token Calling `Python::with_gil` is effectively a no-op when the GIL is already held, but checking that this is the case still has a cost. If an existing GIL token can not be accessed, for example when implementing a pre-existing trait, but a GIL-bound reference is available, this cost can be avoided by exploiting that access to GIL-bound reference gives zero-cost access to a GIL token via `Bound::py`. For example, instead of writing ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; struct Foo(Py); struct FooBound<'py>(Bound<'py, PyList>); impl PartialEq for FooBound<'_> { fn eq(&self, other: &Foo) -> bool { Python::with_gil(|py| { let len = other.0.bind(py).len(); self.0.len() == len }) } } ``` use the more efficient ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # struct Foo(Py); # struct FooBound<'py>(Bound<'py, PyList>); # impl PartialEq for FooBound<'_> { fn eq(&self, other: &Foo) -> bool { // Access to `&Bound<'py, PyAny>` implies access to `Python<'py>`. let py = self.0.py(); let len = other.0.bind(py).len(); self.0.len() == len } } ``` ## Calling Python callables (`__call__`) CPython support multiple calling protocols: [`tp_call`] and [`vectorcall`]. [`vectorcall`] is a more efficient protocol unlocking faster calls. PyO3 will try to dispatch Python `call`s using the [`vectorcall`] calling convention to archive maximum performance if possible and falling back to [`tp_call`] otherwise. This is implemented using the (internal) `PyCallArgs` trait. It defines how Rust types can be used as Python `call` arguments. This trait is currently implemented for - Rust tuples, where each member implements `IntoPyObject`, - `Bound<'_, PyTuple>` - `Py` Rust tuples may make use of [`vectorcall`] where as `Bound<'_, PyTuple>` and `Py` can only use [`tp_call`]. For maximum performance prefer using Rust tuples as arguments. [`tp_call`]: https://docs.python.org/3/c-api/call.html#the-tp-call-protocol [`vectorcall`]: https://docs.python.org/3/c-api/call.html#the-vectorcall-protocol ## Disable the global reference pool PyO3 uses global mutable state to keep track of deferred reference count updates implied by `impl Drop for Py` being called without the GIL being held. The necessary synchronization to obtain and apply these reference count updates when PyO3-based code next acquires the GIL is somewhat expensive and can become a significant part of the cost of crossing the Python-Rust boundary. This functionality can be avoided by setting the `pyo3_disable_reference_pool` conditional compilation flag. This removes the global reference pool and the associated costs completely. However, it does _not_ remove the `Drop` implementation for `Py` which is necessary to interoperate with existing Rust code written without PyO3-based code in mind. To stay compatible with the wider Rust ecosystem in these cases, we keep the implementation but abort when `Drop` is called without the GIL being held. If `pyo3_leak_on_drop_without_reference_pool` is additionally enabled, objects dropped without the GIL being held will be leaked instead which is always sound but might have determinal effects like resource exhaustion in the long term. This limitation is important to keep in mind when this setting is used, especially when embedding Python code into a Rust application as it is quite easy to accidentally drop a `Py` (or types containing it like `PyErr`, `PyBackedStr` or `PyBackedBytes`) returned from `Python::with_gil` without making sure to re-acquire the GIL beforehand. For example, the following code ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::PyList; let numbers: Py = Python::with_gil(|py| PyList::empty(py).unbind()); Python::with_gil(|py| { numbers.bind(py).append(23).unwrap(); }); Python::with_gil(|py| { numbers.bind(py).append(42).unwrap(); }); ``` will abort if the list not explicitly disposed via ```rust # use pyo3::prelude::*; # use pyo3::types::PyList; let numbers: Py = Python::with_gil(|py| PyList::empty(py).unbind()); Python::with_gil(|py| { numbers.bind(py).append(23).unwrap(); }); Python::with_gil(|py| { numbers.bind(py).append(42).unwrap(); }); Python::with_gil(move |py| { drop(numbers); }); ``` [conditional-compilation]: https://doc.rust-lang.org/reference/conditional-compilation.html pyo3/guide/src/conversions/0000775000175000017500000000000015105742312015532 5ustar bdrungbdrungpyo3/guide/src/conversions/traits.md0000644000175000017500000006170015105742312017364 0ustar bdrungbdrung## Conversion traits PyO3 provides some handy traits to convert between Python types and Rust types. ### `.extract()` and the `FromPyObject` trait The easiest way to convert a Python object to a Rust value is using `.extract()`. It returns a `PyResult` with a type error if the conversion fails, so usually you will use something like ```rust # use pyo3::prelude::*; # use pyo3::types::PyList; # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let list = PyList::new(py, b"foo")?; let v: Vec = list.extract()?; # assert_eq!(&v, &[102, 111, 111]); # Ok(()) # }) # } ``` This method is available for many Python object types, and can produce a wide variety of Rust types, which you can check out in the implementor list of [`FromPyObject`]. [`FromPyObject`] is also implemented for your own Rust types wrapped as Python objects (see [the chapter about classes](../class.md)). There, in order to both be able to operate on mutable references *and* satisfy Rust's rules of non-aliasing mutable references, you have to extract the PyO3 reference wrappers [`PyRef`] and [`PyRefMut`]. They work like the reference wrappers of `std::cell::RefCell` and ensure (at runtime) that Rust borrows are allowed. #### Deriving [`FromPyObject`] [`FromPyObject`] can be automatically derived for many kinds of structs and enums if the member types themselves implement `FromPyObject`. This even includes members with a generic type `T: FromPyObject`. Derivation for empty enums, enum variants and structs is not supported. #### Deriving [`FromPyObject`] for structs The derivation generates code that will attempt to access the attribute `my_string` on the Python object, i.e. `obj.getattr("my_string")`, and call `extract()` on the attribute. ```rust use pyo3::prelude::*; use pyo3_ffi::c_str; #[derive(FromPyObject)] struct RustyStruct { my_string: String, } # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let module = PyModule::from_code( # py, # c_str!("class Foo: # def __init__(self): # self.my_string = 'test'"), # c_str!(""), # c_str!(""), # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rustystruct: RustyStruct = instance.extract()?; # assert_eq!(rustystruct.my_string, "test"); # Ok(()) # }) # } ``` By setting the `#[pyo3(item)]` attribute on the field, PyO3 will attempt to extract the value by calling the `get_item` method on the Python object. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyStruct { #[pyo3(item)] my_string: String, } # # use pyo3::types::PyDict; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let dict = PyDict::new(py); # dict.set_item("my_string", "test")?; # # let rustystruct: RustyStruct = dict.extract()?; # assert_eq!(rustystruct.my_string, "test"); # Ok(()) # }) # } ``` The argument passed to `getattr` and `get_item` can also be configured: ```rust use pyo3::prelude::*; use pyo3_ffi::c_str; #[derive(FromPyObject)] struct RustyStruct { #[pyo3(item("key"))] string_in_mapping: String, #[pyo3(attribute("name"))] string_attr: String, } # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let module = PyModule::from_code( # py, # c_str!("class Foo(dict): # def __init__(self): # self.name = 'test' # self['key'] = 'test2'"), # c_str!(""), # c_str!(""), # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rustystruct: RustyStruct = instance.extract()?; # assert_eq!(rustystruct.string_attr, "test"); # assert_eq!(rustystruct.string_in_mapping, "test2"); # # Ok(()) # }) # } ``` This tries to extract `string_attr` from the attribute `name` and `string_in_mapping` from a mapping with the key `"key"`. The arguments for `attribute` are restricted to non-empty string literals while `item` can take any valid literal that implements `ToBorrowedObject`. You can use `#[pyo3(from_item_all)]` on a struct to extract every field with `get_item` method. In this case, you can't use `#[pyo3(attribute)]` or barely use `#[pyo3(item)]` on any field. However, using `#[pyo3(item("key"))]` to specify the key for a field is still allowed. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] #[pyo3(from_item_all)] struct RustyStruct { foo: String, bar: String, #[pyo3(item("foobar"))] baz: String, } # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let py_dict = py.eval(pyo3::ffi::c_str!("{'foo': 'foo', 'bar': 'bar', 'foobar': 'foobar'}"), None, None)?; # let rustystruct: RustyStruct = py_dict.extract()?; # assert_eq!(rustystruct.foo, "foo"); # assert_eq!(rustystruct.bar, "bar"); # assert_eq!(rustystruct.baz, "foobar"); # # Ok(()) # }) # } ``` #### Deriving [`FromPyObject`] for tuple structs Tuple structs are also supported but do not allow customizing the extraction. The input is always assumed to be a Python tuple with the same length as the Rust type, the `n`th field is extracted from the `n`th item in the Python tuple. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTuple(String, String); # use pyo3::types::PyTuple; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let tuple = PyTuple::new(py, vec!["test", "test2"])?; # # let rustytuple: RustyTuple = tuple.extract()?; # assert_eq!(rustytuple.0, "test"); # assert_eq!(rustytuple.1, "test2"); # # Ok(()) # }) # } ``` Tuple structs with a single field are treated as wrapper types which are described in the following section. To override this behaviour and ensure that the input is in fact a tuple, specify the struct as ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTuple((String,)); # use pyo3::types::PyTuple; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let tuple = PyTuple::new(py, vec!["test"])?; # # let rustytuple: RustyTuple = tuple.extract()?; # assert_eq!((rustytuple.0).0, "test"); # # Ok(()) # }) # } ``` #### Deriving [`FromPyObject`] for wrapper types The `pyo3(transparent)` attribute can be used on structs with exactly one field. This results in extracting directly from the input object, i.e. `obj.extract()`, rather than trying to access an item or attribute. This behaviour is enabled per default for newtype structs and tuple-variants with a single field. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTransparentTupleStruct(String); #[derive(FromPyObject)] #[pyo3(transparent)] struct RustyTransparentStruct { inner: String, } # use pyo3::types::PyString; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let s = PyString::new(py, "test"); # # let tup: RustyTransparentTupleStruct = s.extract()?; # assert_eq!(tup.0, "test"); # # let stru: RustyTransparentStruct = s.extract()?; # assert_eq!(stru.inner, "test"); # # Ok(()) # }) # } ``` #### Deriving [`FromPyObject`] for enums The `FromPyObject` derivation for enums generates code that tries to extract the variants in the order of the fields. As soon as a variant can be extracted successfully, that variant is returned. This makes it possible to extract Python union types like `str | int`. The same customizations and restrictions described for struct derivations apply to enum variants, i.e. a tuple variant assumes that the input is a Python tuple, and a struct variant defaults to extracting fields as attributes but can be configured in the same manner. The `transparent` attribute can be applied to single-field-variants. ```rust use pyo3::prelude::*; use pyo3_ffi::c_str; #[derive(FromPyObject)] # #[derive(Debug)] enum RustyEnum<'py> { Int(usize), // input is a positive int String(String), // input is a string IntTuple(usize, usize), // input is a 2-tuple with positive ints StringIntTuple(String, usize), // input is a 2-tuple with String and int Coordinates3d { // needs to be in front of 2d x: usize, y: usize, z: usize, }, Coordinates2d { // only gets checked if the input did not have `z` #[pyo3(attribute("x"))] a: usize, #[pyo3(attribute("y"))] b: usize, }, #[pyo3(transparent)] CatchAll(Bound<'py, PyAny>), // This extraction never fails } # # use pyo3::types::{PyBytes, PyString}; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # { # let thing = 42_u8.into_pyobject(py)?; # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # 42, # match rust_thing { # RustyEnum::Int(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = PyString::new(py, "text"); # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # "text", # match rust_thing { # RustyEnum::String(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = (32_u8, 73_u8).into_pyobject(py)?; # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # (32, 73), # match rust_thing { # RustyEnum::IntTuple(i, j) => (i, j), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = ("foo", 73_u8).into_pyobject(py)?; # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # (String::from("foo"), 73), # match rust_thing { # RustyEnum::StringIntTuple(i, j) => (i, j), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let module = PyModule::from_code( # py, # c_str!("class Foo(dict): # def __init__(self): # self.x = 0 # self.y = 1 # self.z = 2"), # c_str!(""), # c_str!(""), # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rust_thing: RustyEnum<'_> = instance.extract()?; # # assert_eq!( # (0, 1, 2), # match rust_thing { # RustyEnum::Coordinates3d { x, y, z } => (x, y, z), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let module = PyModule::from_code( # py, # c_str!("class Foo(dict): # def __init__(self): # self.x = 3 # self.y = 4"), # c_str!(""), # c_str!(""), # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rust_thing: RustyEnum<'_> = instance.extract()?; # # assert_eq!( # (3, 4), # match rust_thing { # RustyEnum::Coordinates2d { a, b } => (a, b), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = PyBytes::new(py, b"text"); # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # b"text", # match rust_thing { # RustyEnum::CatchAll(ref i) => i.downcast::()?.as_bytes(), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # Ok(()) # }) # } ``` If none of the enum variants match, a `PyTypeError` containing the names of the tested variants is returned. The names reported in the error message can be customized through the `#[pyo3(annotation = "name")]` attribute, e.g. to use conventional Python type names: ```rust use pyo3::prelude::*; #[derive(FromPyObject)] # #[derive(Debug)] enum RustyEnum { #[pyo3(transparent, annotation = "str")] String(String), #[pyo3(transparent, annotation = "int")] Int(isize), } # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # { # let thing = 42_u8.into_pyobject(py)?; # let rust_thing: RustyEnum = thing.extract()?; # # assert_eq!( # 42, # match rust_thing { # RustyEnum::Int(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = "foo".into_pyobject(py)?; # let rust_thing: RustyEnum = thing.extract()?; # # assert_eq!( # "foo", # match rust_thing { # RustyEnum::String(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = b"foo".into_pyobject(py)?; # let error = thing.extract::().unwrap_err(); # assert!(error.is_instance_of::(py)); # } # # Ok(()) # }) # } ``` If the input is neither a string nor an integer, the error message will be: `"'' cannot be converted to 'str | int'"`. #### `#[derive(FromPyObject)]` Container Attributes - `pyo3(transparent)` - extract the field directly from the object as `obj.extract()` instead of `get_item()` or `getattr()` - Newtype structs and tuple-variants are treated as transparent per default. - only supported for single-field structs and enum variants - `pyo3(annotation = "name")` - changes the name of the failed variant in the generated error message in case of failure. - e.g. `pyo3("int")` reports the variant's type as `int`. - only supported for enum variants - `pyo3(rename_all = "...")` - renames all attributes/item keys according to the specified renaming rule - Possible values are: "camelCase", "kebab-case", "lowercase", "PascalCase", "SCREAMING-KEBAB-CASE", "SCREAMING_SNAKE_CASE", "snake_case", "UPPERCASE". - fields with an explicit renaming via `attribute(...)`/`item(...)` are not affected #### `#[derive(FromPyObject)]` Field Attributes - `pyo3(attribute)`, `pyo3(attribute("name"))` - retrieve the field from an attribute, possibly with a custom name specified as an argument - argument must be a string-literal. - `pyo3(item)`, `pyo3(item("key"))` - retrieve the field from a mapping, possibly with the custom key specified as an argument. - can be any literal that implements `ToBorrowedObject` - `pyo3(from_py_with = ...)` - apply a custom function to convert the field from Python the desired Rust type. - the argument must be the path to the function. - the function signature must be `fn(&Bound) -> PyResult` where `T` is the Rust type of the argument. - `pyo3(default)`, `pyo3(default = ...)` - if the argument is set, uses the given default value. - in this case, the argument must be a Rust expression returning a value of the desired Rust type. - if the argument is not set, [`Default::default`](https://doc.rust-lang.org/std/default/trait.Default.html#tymethod.default) is used. - note that the default value is only used if the field is not set. If the field is set and the conversion function from Python to Rust fails, an exception is raised and the default value is not used. - this attribute is only supported on named fields. For example, the code below applies the given conversion function on the `"value"` dict item to compute its length or fall back to the type default value (0): ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyStruct { #[pyo3(item("value"), default, from_py_with = Bound::<'_, PyAny>::len)] len: usize, #[pyo3(item)] other: usize, } # # use pyo3::types::PyDict; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # // Filled case # let dict = PyDict::new(py); # dict.set_item("value", (1,)).unwrap(); # dict.set_item("other", 1).unwrap(); # let result = dict.extract::()?; # assert_eq!(result.len, 1); # assert_eq!(result.other, 1); # # // Empty case # let dict = PyDict::new(py); # dict.set_item("other", 1).unwrap(); # let result = dict.extract::()?; # assert_eq!(result.len, 0); # assert_eq!(result.other, 1); # Ok(()) # }) # } ``` ### `IntoPyObject` The [`IntoPyObject`] trait defines the to-python conversion for a Rust type. All types in PyO3 implement this trait, as does a `#[pyclass]` which doesn't use `extends`. This trait defines a single method, `into_pyobject()`, which returns a [`Result`] with `Ok` and `Err` types depending on the input value. For convenience, there is a companion [`IntoPyObjectExt`] trait which adds methods such as `into_py_any()` which converts the `Ok` and `Err` types to commonly used types (in the case of `into_py_any()`, `Py` and `PyErr` respectively). Occasionally you may choose to implement this for custom types which are mapped to Python types _without_ having a unique python type. #### derive macro `IntoPyObject` can be implemented using our derive macro. Both `struct`s and `enum`s are supported. `struct`s will turn into a `PyDict` using the field names as keys, tuple `struct`s will turn convert into `PyTuple` with the fields in declaration order. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use std::collections::HashMap; # use std::hash::Hash; // structs convert into `PyDict` with field names as keys #[derive(IntoPyObject)] struct Struct { count: usize, obj: Py, } // tuple structs convert into `PyTuple` // lifetimes and generics are supported, the impl will be bounded by // `K: IntoPyObject, V: IntoPyObject` #[derive(IntoPyObject)] struct Tuple<'a, K: Hash + Eq, V>(&'a str, HashMap); ``` For structs with a single field (newtype pattern) the `#[pyo3(transparent)]` option can be used to forward the implementation to the inner type. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; // newtype tuple structs are implicitly `transparent` #[derive(IntoPyObject)] struct TransparentTuple(PyObject); #[derive(IntoPyObject)] #[pyo3(transparent)] struct TransparentStruct<'py> { inner: Bound<'py, PyAny>, // `'py` lifetime will be used as the Python lifetime } ``` For `enum`s each variant is converted according to the rules for `struct`s above. ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # use std::collections::HashMap; # use std::hash::Hash; #[derive(IntoPyObject)] enum Enum<'a, 'py, K: Hash + Eq, V> { // enums are supported and convert using the same TransparentTuple(PyObject), // rules on the variants as the structs above #[pyo3(transparent)] TransparentStruct { inner: Bound<'py, PyAny> }, Tuple(&'a str, HashMap), Struct { count: usize, obj: Py } } ``` Additionally `IntoPyObject` can be derived for a reference to a struct or enum using the `IntoPyObjectRef` derive macro. All the same rules from above apply as well. ##### `#[derive(IntoPyObject)]`/`#[derive(IntoPyObjectRef)]` Field Attributes - `pyo3(into_py_with = ...)` - apply a custom function to convert the field from Rust into Python. - the argument must be the function identifier - the function signature must be `fn(Cow<'_, T>, Python<'py>) -> PyResult>` where `T` is the Rust type of the argument. - `#[derive(IntoPyObject)]` will invoke the function with `Cow::Owned` - `#[derive(IntoPyObjectRef)]` will invoke the function with `Cow::Borrowed` ```rust,no_run # use pyo3::prelude::*; # use pyo3::IntoPyObjectExt; # use std::borrow::Cow; #[derive(Clone)] struct NotIntoPy(usize); #[derive(IntoPyObject, IntoPyObjectRef)] struct MyStruct { #[pyo3(into_py_with = convert)] not_into_py: NotIntoPy, } /// Convert `NotIntoPy` into Python fn convert<'py>(not_into_py: Cow<'_, NotIntoPy>, py: Python<'py>) -> PyResult> { not_into_py.0.into_bound_py_any(py) } ``` #### manual implementation If the derive macro is not suitable for your use case, `IntoPyObject` can be implemented manually as demonstrated below. ```rust,no_run # use pyo3::prelude::*; # #[allow(dead_code)] struct MyPyObjectWrapper(PyObject); impl<'py> IntoPyObject<'py> for MyPyObjectWrapper { type Target = PyAny; // the Python type type Output = Bound<'py, Self::Target>; // in most cases this will be `Bound` type Error = std::convert::Infallible; // the conversion error type, has to be convertible to `PyErr` fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.into_bound(py)) } } // equivalent to former `ToPyObject` implementations impl<'a, 'py> IntoPyObject<'py> for &'a MyPyObjectWrapper { type Target = PyAny; type Output = Borrowed<'a, 'py, Self::Target>; // `Borrowed` can be used to optimized reference counting type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.0.bind_borrowed(py)) } } ``` #### `BoundObject` for conversions that may be `Bound` or `Borrowed` `IntoPyObject::into_py_object` returns either `Bound` or `Borrowed` depending on the implementation for a concrete type. For example, the `IntoPyObject` implementation for `u32` produces a `Bound<'py, PyInt>` and the `bool` implementation produces a `Borrowed<'py, 'py, PyBool>`: ```rust,no_run use pyo3::prelude::*; use pyo3::IntoPyObject; use pyo3::types::{PyBool, PyInt}; let ints: Vec = vec![1, 2, 3, 4]; let bools = vec![true, false, false, true]; Python::with_gil(|py| { let ints_as_pyint: Vec> = ints .iter() .map(|x| Ok(x.into_pyobject(py)?)) .collect::>() .unwrap(); let bools_as_pybool: Vec> = bools .iter() .map(|x| Ok(x.into_pyobject(py)?)) .collect::>() .unwrap(); }); ``` In this example if we wanted to combine `ints_as_pyints` and `bools_as_pybool` into a single `Vec>` to return from the `with_gil` closure, we would have to manually convert the concrete types for the smart pointers and the python types. Instead, we can write a function that generically converts vectors of either integers or bools into a vector of `Py` using the [`BoundObject`] trait: ```rust,no_run # use pyo3::prelude::*; # use pyo3::BoundObject; # use pyo3::IntoPyObject; # let bools = vec![true, false, false, true]; # let ints = vec![1, 2, 3, 4]; fn convert_to_vec_of_pyobj<'py, T>(py: Python<'py>, the_vec: Vec) -> PyResult>> where T: IntoPyObject<'py> + Copy { the_vec.iter() .map(|x| { Ok( // Note: the below is equivalent to `x.into_py_any()` // from the `IntoPyObjectExt` trait x.into_pyobject(py) .map_err(Into::into)? .into_any() .unbind() ) }) .collect() } let vec_of_pyobjs: Vec> = Python::with_gil(|py| { let mut bools_as_pyany = convert_to_vec_of_pyobj(py, bools).unwrap(); let mut ints_as_pyany = convert_to_vec_of_pyobj(py, ints).unwrap(); let mut result: Vec> = vec![]; result.append(&mut bools_as_pyany); result.append(&mut ints_as_pyany); result }); ``` In the example above we used `BoundObject::into_any` and `BoundObject::unbind` to manipulate the python types and smart pointers into the result type we wanted to produce from the function. [`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`IntoPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPyObject.html [`IntoPyObjectExt`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPyObjectExt.html [`PyObject`]: {{#PYO3_DOCS_URL}}/pyo3/type.PyObject.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html [`BoundObject`]: {{#PYO3_DOCS_URL}}/pyo3/instance/trait.BoundObject.html [`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html pyo3/guide/src/conversions/tables.md0000644000175000017500000001755215105742312017336 0ustar bdrungbdrung## Mapping of Rust types to Python types When writing functions callable from Python (such as a `#[pyfunction]` or in a `#[pymethods]` block), the trait `FromPyObject` is required for function arguments, and `IntoPy` is required for function return values. Consult the tables in the following section to find the Rust types provided by PyO3 which implement these traits. ### Argument Types When accepting a function argument, it is possible to either use Rust library types or PyO3's Python-native types. (See the next section for discussion on when to use each.) The table below contains the Python type and the corresponding function argument types that will accept them: | Python | Rust | Rust (Python-native) | | ------------- |:-------------------------------:|:--------------------:| | `object` | - | `PyAny` | | `str` | `String`, `Cow`, `&str`, `char`, `OsString`, `PathBuf`, `Path` | `PyString` | | `bytes` | `Vec`, `&[u8]`, `Cow<[u8]>` | `PyBytes` | | `bool` | `bool` | `PyBool` | | `int` | `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`, `num_bigint::BigInt`[^1], `num_bigint::BigUint`[^1] | `PyInt` | | `float` | `f32`, `f64`, `ordered_float::NotNan`[^10], `ordered_float::OrderedFloat`[^10] | `PyFloat` | | `complex` | `num_complex::Complex`[^2] | `PyComplex` | | `fractions.Fraction`| `num_rational::Ratio`[^8] | - | | `list[T]` | `Vec` | `PyList` | | `dict[K, V]` | `HashMap`, `BTreeMap`, `hashbrown::HashMap`[^3], `indexmap::IndexMap`[^4] | `PyDict` | | `tuple[T, U]` | `(T, U)`, `Vec` | `PyTuple` | | `set[T]` | `HashSet`, `BTreeSet`, `hashbrown::HashSet`[^3] | `PySet` | | `frozenset[T]` | `HashSet`, `BTreeSet`, `hashbrown::HashSet`[^3] | `PyFrozenSet` | | `bytearray` | `Vec`, `Cow<[u8]>` | `PyByteArray` | | `slice` | - | `PySlice` | | `type` | - | `PyType` | | `module` | - | `PyModule` | | `collections.abc.Buffer` | - | `PyBuffer` | | `datetime.datetime` | `SystemTime`, `chrono::DateTime`[^5], `chrono::NaiveDateTime`[^5] | `PyDateTime` | | `datetime.date` | `chrono::NaiveDate`[^5] | `PyDate` | | `datetime.time` | `chrono::NaiveTime`[^5] | `PyTime` | | `datetime.tzinfo` | `chrono::FixedOffset`[^5], `chrono::Utc`[^5], `chrono_tz::TimeZone`[^6] | `PyTzInfo` | | `datetime.timedelta` | `Duration`, `chrono::Duration`[^5] | `PyDelta` | | `decimal.Decimal` | `rust_decimal::Decimal`[^7] | - | | `decimal.Decimal` | `bigdecimal::BigDecimal`[^9] | - | | `ipaddress.IPv4Address` | `std::net::IpAddr`, `std::net::Ipv4Addr` | - | | `ipaddress.IPv6Address` | `std::net::IpAddr`, `std::net::Ipv6Addr` | - | | `os.PathLike ` | `PathBuf`, `Path` | `PyString` | | `pathlib.Path` | `PathBuf`, `Path` | `PyString` | | `typing.Optional[T]` | `Option` | - | | `typing.Sequence[T]` | `Vec` | `PySequence` | | `typing.Mapping[K, V]` | `HashMap`, `BTreeMap`, `hashbrown::HashMap`[^3], `indexmap::IndexMap`[^4] | `&PyMapping` | | `typing.Iterator[Any]` | - | `PyIterator` | | `typing.Union[...]` | See [`#[derive(FromPyObject)]`](traits.md#deriving-frompyobject-for-enums) | - | It is also worth remembering the following special types: | What | Description | | ---------------- | ------------------------------------- | | `Python<'py>` | A GIL token, used to pass to PyO3 constructors to prove ownership of the GIL. | | `Bound<'py, T>` | A Python object connected to the GIL lifetime. This provides access to most of PyO3's APIs. | | `Py` | A Python object isolated from the GIL lifetime. This can be sent to other threads. | | `PyObject` | An alias for `Py` | | `PyRef` | A `#[pyclass]` borrowed immutably. | | `PyRefMut` | A `#[pyclass]` borrowed mutably. | For more detail on accepting `#[pyclass]` values as function arguments, see [the section of this guide on Python Classes](../class.md). #### Using Rust library types vs Python-native types Using Rust library types as function arguments will incur a conversion cost compared to using the Python-native types. Using the Python-native types is almost zero-cost (they just require a type check similar to the Python builtin function `isinstance()`). However, once that conversion cost has been paid, the Rust standard library types offer a number of benefits: - You can write functionality in native-speed Rust code (free of Python's runtime costs). - You get better interoperability with the rest of the Rust ecosystem. - You can use `Python::allow_threads` to release the Python GIL and let other Python threads make progress while your Rust code is executing. - You also benefit from stricter type checking. For example you can specify `Vec`, which will only accept a Python `list` containing integers. The Python-native equivalent, `&PyList`, would accept a Python `list` containing Python objects of any type. For most PyO3 usage the conversion cost is worth paying to get these benefits. As always, if you're not sure it's worth it in your case, benchmark it! ### Returning Rust values to Python When returning values from functions callable from Python, [PyO3's smart pointers](../types.md#pyo3s-smart-pointers) (`Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`) can be used with zero cost. Because `Bound<'py, T>` and `Borrowed<'a, 'py, T>` have lifetime parameters, the Rust compiler may ask for lifetime annotations to be added to your function. See the [section of the guide dedicated to this](../types.md#function-argument-lifetimes). If your function is fallible, it should return `PyResult` or `Result` where `E` implements `From for PyErr`. This will raise a `Python` exception if the `Err` variant is returned. Finally, the following Rust types are also able to convert to Python as return values: | Rust type | Resulting Python Type | | ------------- |:-------------------------------:| | `String` | `str` | | `&str` | `str` | | `bool` | `bool` | | Any integer type (`i32`, `u32`, `usize`, etc) | `int` | | `f32`, `f64` | `float` | | `Option` | `Optional[T]` | | `(T, U)` | `Tuple[T, U]` | | `Vec` | `List[T]` | | `Cow<[u8]>` | `bytes` | | `HashMap` | `Dict[K, V]` | | `BTreeMap` | `Dict[K, V]` | | `HashSet` | `Set[T]` | | `BTreeSet` | `Set[T]` | | `Py` | `T` | | `Bound` | `T` | | `PyRef` | `T` | | `PyRefMut` | `T` | [^1]: Requires the `num-bigint` optional feature. [^2]: Requires the `num-complex` optional feature. [^3]: Requires the `hashbrown` optional feature. [^4]: Requires the `indexmap` optional feature. [^5]: Requires the `chrono` optional feature. [^6]: Requires the `chrono-tz` optional feature. [^7]: Requires the `rust_decimal` optional feature. [^8]: Requires the `num-rational` optional feature. [^9]: Requires the `bigdecimal` optional feature. [^10]: Requires the `ordered-float` optional feature. pyo3/guide/src/exception.md0000644000175000017500000001232015105742312015476 0ustar bdrungbdrung# Python exceptions ## Defining a new exception Use the [`create_exception!`] macro: ```rust use pyo3::create_exception; create_exception!(module, MyError, pyo3::exceptions::PyException); ``` * `module` is the name of the containing module. * `MyError` is the name of the new exception type. For example: ```rust use pyo3::prelude::*; use pyo3::create_exception; use pyo3::types::IntoPyDict; use pyo3::exceptions::PyException; create_exception!(mymodule, CustomError, PyException); # fn main() -> PyResult<()> { Python::with_gil(|py| { let ctx = [("CustomError", py.get_type::())].into_py_dict(py)?; pyo3::py_run!( py, *ctx, "assert str(CustomError) == \"\"" ); pyo3::py_run!(py, *ctx, "assert CustomError('oops').args == ('oops',)"); # Ok(()) }) # } ``` When using PyO3 to create an extension module, you can add the new exception to the module like this, so that it is importable from Python: ```rust,no_run use pyo3::prelude::*; use pyo3::exceptions::PyException; pyo3::create_exception!(mymodule, CustomError, PyException); #[pymodule] fn mymodule(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { // ... other elements added to module ... m.add("CustomError", py.get_type::())?; Ok(()) } ``` ## Raising an exception As described in the [function error handling](./function/error-handling.md) chapter, to raise an exception from a `#[pyfunction]` or `#[pymethods]`, return an `Err(PyErr)`. PyO3 will automatically raise this exception for you when returning the result to Python. You can also manually write and fetch errors in the Python interpreter's global state: ```rust use pyo3::{Python, PyErr}; use pyo3::exceptions::PyTypeError; Python::with_gil(|py| { PyTypeError::new_err("Error").restore(py); assert!(PyErr::occurred(py)); drop(PyErr::fetch(py)); }); ``` ## Checking exception types Python has an [`isinstance`](https://docs.python.org/3/library/functions.html#isinstance) method to check an object's type. In PyO3 every object has the [`PyAny::is_instance`] and [`PyAny::is_instance_of`] methods which do the same thing. ```rust,no_run use pyo3::prelude::*; use pyo3::types::{PyBool, PyList}; # fn main() -> PyResult<()> { Python::with_gil(|py| { assert!(PyBool::new(py, true).is_instance_of::()); let list = PyList::new(py, &[1, 2, 3, 4])?; assert!(!list.is_instance_of::()); assert!(list.is_instance_of::()); # Ok(()) }) # } ``` To check the type of an exception, you can similarly do: ```rust,no_run # use pyo3::exceptions::PyTypeError; # use pyo3::prelude::*; # Python::with_gil(|py| { # let err = PyTypeError::new_err(()); err.is_instance_of::(py); # }); ``` ## Using exceptions defined in Python code It is possible to use an exception defined in Python code as a native Rust type. The `import_exception!` macro allows importing a specific exception class and defines a Rust type for that exception. ```rust,no_run #![allow(dead_code)] use pyo3::prelude::*; mod io { pyo3::import_exception!(io, UnsupportedOperation); } fn tell(file: &Bound<'_, PyAny>) -> PyResult { match file.call_method0("tell") { Err(_) => Err(io::UnsupportedOperation::new_err("not supported: tell")), Ok(x) => x.extract::(), } } ``` [`pyo3::exceptions`]({{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html) defines exceptions for several standard library modules. [`create_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.create_exception.html [`import_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.import_exception.html [`PyErr`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html [`PyResult`]: {{#PYO3_DOCS_URL}}/pyo3/type.PyResult.html [`PyErr::from_value`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html#method.from_value [`PyAny::is_instance`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.is_instance [`PyAny::is_instance_of`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.is_instance_of ## Creating more complex exceptions If you need to create an exception with more complex behavior, you can also manually create a subclass of `PyException`: ```rust #![allow(dead_code)] # #[cfg(any(not(feature = "abi3")))] { use pyo3::prelude::*; use pyo3::types::IntoPyDict; use pyo3::exceptions::PyException; #[pyclass(extends=PyException)] struct CustomError { #[pyo3(get)] url: String, #[pyo3(get)] message: String, } #[pymethods] impl CustomError { #[new] fn new(url: String, message: String) -> Self { Self { url, message } } } # fn main() -> PyResult<()> { Python::with_gil(|py| { let ctx = [("CustomError", py.get_type::())].into_py_dict(py)?; pyo3::py_run!( py, *ctx, "assert str(CustomError) == \"\", repr(CustomError)" ); pyo3::py_run!(py, *ctx, "assert CustomError('https://example.com', 'something went bad').args == ('https://example.com', 'something went bad')"); pyo3::py_run!(py, *ctx, "assert CustomError('https://example.com', 'something went bad').url == 'https://example.com'"); # Ok(()) }) # } # } ``` Note that this is not possible when the ``abi3`` feature is enabled, as that prevents subclassing ``PyException``. pyo3/guide/src/conversions.md0000644000175000017500000000044015105742312016050 0ustar bdrungbdrung# Type conversions In this portion of the guide we'll talk about the mapping of Python types to Rust types offered by PyO3, as well as the traits available to perform conversions between them. See also the conversion [tables](conversions/tables.md) and [traits](conversions/traits.md). pyo3/guide/src/free-threading.md0000644000175000017500000004375715105742312016406 0ustar bdrungbdrung# Supporting Free-Threaded CPython CPython 3.13 introduces an experimental "free-threaded" build of CPython that does not rely on the [global interpreter lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock) (often referred to as the GIL) for thread safety. As of version 0.23, PyO3 also has preliminary support for building Rust extensions for the free-threaded Python build and support for calling into free-threaded Python from Rust. If you want more background on free-threaded Python in general, see the [what's new](https://docs.python.org/3.13/whatsnew/3.13.html#whatsnew313-free-threaded-cpython) entry in the CPython docs, the [HOWTO guide](https://docs.python.org/3.13/howto/free-threading-extensions.html#freethreading-extensions-howto) for porting C extensions, and [PEP 703](https://peps.python.org/pep-0703/), which provides the technical background for the free-threading implementation in CPython. In the GIL-enabled build, the global interpreter lock serializes access to the Python runtime. The GIL is therefore a fundamental limitation to parallel scaling of multithreaded Python workflows, due to [Amdahl's law](https://en.wikipedia.org/wiki/Amdahl%27s_law), because any time spent executing a parallel processing task on only one execution context fundamentally cannot be sped up using parallelism. The free-threaded build removes this limit on multithreaded Python scaling. This means it's much more straightforward to achieve parallelism using the Python [`threading`] module. If you have ever needed to use [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html) to achieve a parallel speedup for some Python code, free-threading will likely allow the use of Python threads instead for the same workflow. PyO3's support for free-threaded Python will enable authoring native Python extensions that are thread-safe by construction, with much stronger safety guarantees than C extensions. Our goal is to enable ["fearless concurrency"](https://doc.rust-lang.org/book/ch16-00-concurrency.html) in the native Python runtime by building on the Rust [`Send` and `Sync`](https://doc.rust-lang.org/nomicon/send-and-sync.html) traits. This document provides advice for porting Rust code using PyO3 to run under free-threaded Python. ## Supporting free-threaded Python with PyO3 Many simple uses of PyO3, like exposing bindings for a "pure" Rust function with no side-effects or defining an immutable Python class, will likely work "out of the box" on the free-threaded build. All that will be necessary is to annotate Python modules declared by rust code in your project to declare that they support free-threaded Python, for example by declaring the module with `#[pymodule(gil_used = false)]`. More complicated `#[pyclass]` types may need to deal with thread-safety directly; there is [a dedicated section of the guide](./class/thread-safety.md) to discuss this. At a low-level, annotating a module sets the `Py_MOD_GIL` slot on modules defined by an extension to `Py_MOD_GIL_NOT_USED`, which allows the interpreter to see at runtime that the author of the extension thinks the extension is thread-safe. You should only do this if you know that your extension is thread-safe. Because of Rust's guarantees, this is already true for many extensions, however see below for more discussion about how to evaluate the thread safety of existing Rust extensions and how to think about the PyO3 API using a Python runtime with no GIL. If you do not explicitly mark that modules are thread-safe, the Python interpreter will re-enable the GIL at runtime while importing your module and print a `RuntimeWarning` with a message containing the name of the module causing it to re-enable the GIL. You can force the GIL to remain disabled by setting the `PYTHON_GIL=0` as an environment variable or passing `-Xgil=0` when starting Python (`0` means the GIL is turned off). If you are sure that all data structures exposed in a `PyModule` are thread-safe, then pass `gil_used = false` as a parameter to the `pymodule` procedural macro declaring the module or call `PyModule::gil_used` on a `PyModule` instance. For example: ```rust,no_run use pyo3::prelude::*; /// This module supports free-threaded Python #[pymodule(gil_used = false)] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { // add members to the module that you know are thread-safe Ok(()) } ``` Or for a module that is set up without using the `pymodule` macro: ```rust,no_run use pyo3::prelude::*; # #[allow(dead_code)] fn register_child_module(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let child_module = PyModule::new(parent_module.py(), "child_module")?; child_module.gil_used(false)?; parent_module.add_submodule(&child_module) } ``` For now you must explicitly opt in to free-threading support by annotating modules defined in your extension. In a future version of `PyO3`, we plan to make `gil_used = false` the default. See the [`string-sum`](https://github.com/PyO3/pyo3/tree/main/pyo3-ffi/examples/string-sum) example for how to declare free-threaded support using raw FFI calls for modules using single-phase initialization and the [`sequential`](https://github.com/PyO3/pyo3/tree/main/pyo3-ffi/examples/sequential) example for modules using multi-phase initialization. If you would like to use conditional compilation to trigger different code paths under the free-threaded build, you can use the `Py_GIL_DISABLED` attribute once you have configured your crate to generate the necessary build configuration data. See [the guide section](./building-and-distribution/multiple-python-versions.md) for more details about supporting multiple different Python versions, including the free-threaded build. ## Special considerations for the free-threaded build The free-threaded interpreter does not have a GIL, and this can make interacting with the PyO3 API confusing, since the API was originally designed around strong assumptions about the GIL providing locking. Additionally, since the GIL provided locking for operations on Python objects, many existing extensions that provide mutable data structures relied on the GIL to make interior mutability thread-safe. Working with PyO3 under the free-threaded interpreter therefore requires some additional care and mental overhead compared with a GIL-enabled interpreter. We discuss how to handle this below. ### Many symbols exposed by PyO3 have `GIL` in the name We are aware that there are some naming issues in the PyO3 API that make it awkward to think about a runtime environment where there is no GIL. We plan to change the names of these types to de-emphasize the role of the GIL in future versions of PyO3, but for now you should remember that the use of the term `GIL` in functions and types like [`Python::with_gil`] and [`GILOnceCell`] is historical. Instead, you should think about whether or not a Rust thread is attached to a Python interpreter runtime. Calling into the CPython C API is only legal when an OS thread is explicitly attached to the interpreter runtime. In the GIL-enabled build, this happens when the GIL is acquired. In the free-threaded build there is no GIL, but the same C macros that release or acquire the GIL in the GIL-enabled build instead ask the interpreter to attach the thread to the Python runtime, and there can be many threads simultaneously attached. See [PEP 703](https://peps.python.org/pep-0703/#thread-states) for more background about how threads can be attached and detached from the interpreter runtime, in a manner analogous to releasing and acquiring the GIL in the GIL-enabled build. In the GIL-enabled build, PyO3 uses the [`Python<'py>`] type and the `'py` lifetime to signify that the global interpreter lock is held. In the freethreaded build, holding a `'py` lifetime means only that the thread is currently attached to the Python interpreter -- other threads can be simultaneously interacting with the interpreter. You still need to obtain a `'py` lifetime is to interact with Python objects or call into the CPython C API. If you are not yet attached to the Python runtime, you can register a thread using the [`Python::with_gil`] function. Threads created via the Python [`threading`] module do not not need to do this, and pyo3 will handle setting up the [`Python<'py>`] token when CPython calls into your extension. ### Global synchronization events can cause hangs and deadlocks The free-threaded build triggers global synchronization events in the following situations: * During garbage collection in order to get a globally consistent view of reference counts and references between objects * In Python 3.13, when the first background thread is started in order to mark certain objects as immortal * When either `sys.settrace` or `sys.setprofile` are called in order to instrument running code objects and threads * Before `os.fork()` is called. This is a non-exhaustive list and there may be other situations in future Python versions that can trigger global synchronization events. This means that you should detach from the interpreter runtime using [`Python::allow_threads`] in exactly the same situations as you should detach from the runtime in the GIL-enabled build: when doing long-running tasks that do not require the CPython runtime or when doing any task that needs to re-attach to the runtime (see the [guide section](parallelism.md#sharing-python-objects-between-rust-threads) that covers this). In the former case, you would observe a hang on threads that are waiting on the long-running task to complete, and in the latter case you would see a deadlock while a thread tries to attach after the runtime triggers a global synchronization event, but the spawning thread prevents the synchronization event from completing. ### Exceptions and panics for multithreaded access of mutable `pyclass` instances Data attached to `pyclass` instances is protected from concurrent access by a `RefCell`-like pattern of runtime borrow checking. Like a `RefCell`, PyO3 will raise exceptions (or in some cases panic) to enforce exclusive access for mutable borrows. It was always possible to generate panics like this in PyO3 in code that releases the GIL with [`Python::allow_threads`] or calling a python method accepting `&self` from a `&mut self` (see [the docs on interior mutability](./class.md#bound-and-interior-mutability),) but now in free-threaded Python there are more opportunities to trigger these panics from Python because there is no GIL to lock concurrent access to mutably borrowed data from Python. The most straightforward way to trigger this problem is to use the Python [`threading`] module to simultaneously call a rust function that mutably borrows a [`pyclass`]({{#PYO3_DOCS_URL}}/pyo3/attr.pyclass.html) in multiple threads. For example, consider the following implementation: ```rust,no_run # use pyo3::prelude::*; #[pyclass] #[derive(Default)] struct ThreadIter { count: usize, } #[pymethods] impl ThreadIter { #[new] pub fn new() -> Self { Default::default() } fn __next__(&mut self, py: Python<'_>) -> usize { self.count += 1; self.count } } ``` And then if we do something like this in Python: ```python import concurrent.futures from my_module import ThreadIter i = ThreadIter() def increment(): next(i) with concurrent.futures.ThreadPoolExecutor(max_workers=16) as tpe: futures = [tpe.submit(increment) for _ in range(100)] [f.result() for f in futures] ``` We will see an exception: ```text Traceback (most recent call last) File "example.py", line 5, in next(i) RuntimeError: Already borrowed ``` We plan to allow user-selectable semantics for mutable pyclass definitions in PyO3 0.24, allowing some form of opt-in locking to emulate the GIL if that is needed. For now you should explicitly add locking, possibly using conditional compilation or using the critical section API, to avoid creating deadlocks with the GIL. ### Cannot build extensions using the limited API The free-threaded build uses a completely new ABI and there is not yet an equivalent to the limited API for the free-threaded ABI. That means if your crate depends on PyO3 using the `abi3` feature or an an `abi3-pyxx` feature, PyO3 will print a warning and ignore that setting when building extensions using the free-threaded interpreter. This means that if your package makes use of the ABI forward compatibility provided by the limited API to upload only one wheel for each release of your package, you will need to update your release procedure to also upload a version-specific free-threaded wheel. See [the guide section](./building-and-distribution/multiple-python-versions.md) for more details about supporting multiple different Python versions, including the free-threaded build. ### Thread-safe single initialization Until version 0.23, PyO3 provided only [`GILOnceCell`] to enable deadlock-free single initialization of data in contexts that might execute arbitrary Python code. While we have updated [`GILOnceCell`] to avoid thread safety issues triggered only under the free-threaded build, the design of [`GILOnceCell`] is inherently thread-unsafe, in a manner that can be problematic even in the GIL-enabled build. If, for example, the function executed by [`GILOnceCell`] releases the GIL or calls code that releases the GIL, then it is possible for multiple threads to race to initialize the cell. While the cell will only ever be initialized once, it can be problematic in some contexts that [`GILOnceCell`] does not block like the standard library [`OnceLock`]. In cases where the initialization function must run exactly once, you can bring the [`OnceExt`] or [`OnceLockExt`] traits into scope. The [`OnceExt`] trait adds [`OnceExt::call_once_py_attached`] and [`OnceExt::call_once_force_py_attached`] functions to the api of `std::sync::Once`, enabling use of [`Once`] in contexts where the GIL is held. Similarly, [`OnceLockExt`] adds [`OnceLockExt::get_or_init_py_attached`]. These functions are analogous to [`Once::call_once`], [`Once::call_once_force`], and [`OnceLock::get_or_init`] except they accept a [`Python<'py>`] token in addition to an `FnOnce`. All of these functions release the GIL and re-acquire it before executing the function, avoiding deadlocks with the GIL that are possible without using the PyO3 extension traits. Here is an example of how to use [`OnceExt`] to enable single-initialization of a runtime cache holding a `Py`. ```rust # use pyo3::prelude::*; use std::sync::Once; use pyo3::sync::OnceExt; use pyo3::types::PyDict; struct RuntimeCache { once: Once, cache: Option> } let mut cache = RuntimeCache { once: Once::new(), cache: None }; Python::with_gil(|py| { // guaranteed to be called once and only once cache.once.call_once_py_attached(py, || { cache.cache = Some(PyDict::new(py).unbind()); }); }); ``` ### `GILProtected` is not exposed [`GILProtected`] is a PyO3 type that allows mutable access to static data by leveraging the GIL to lock concurrent access from other threads. In free-threaded Python there is no GIL, so you will need to replace this type with some other form of locking. In many cases, a type from [`std::sync::atomic`](https://doc.rust-lang.org/std/sync/atomic/) or a [`std::sync::Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) will be sufficient. Before: ```rust # fn main() { # #[cfg(not(Py_GIL_DISABLED))] { # use pyo3::prelude::*; use pyo3::sync::GILProtected; use pyo3::types::{PyDict, PyNone}; use std::cell::RefCell; static OBJECTS: GILProtected>>> = GILProtected::new(RefCell::new(Vec::new())); Python::with_gil(|py| { // stand-in for something that executes arbitrary Python code let d = PyDict::new(py); d.set_item(PyNone::get(py), PyNone::get(py)).unwrap(); OBJECTS.get(py).borrow_mut().push(d.unbind()); }); # }} ``` After: ```rust # use pyo3::prelude::*; # fn main() { use pyo3::types::{PyDict, PyNone}; use std::sync::Mutex; static OBJECTS: Mutex>> = Mutex::new(Vec::new()); Python::with_gil(|py| { // stand-in for something that executes arbitrary Python code let d = PyDict::new(py); d.set_item(PyNone::get(py), PyNone::get(py)).unwrap(); // as with any `Mutex` usage, lock the mutex for as little time as possible // in this case, we do it just while pushing into the `Vec` OBJECTS.lock().unwrap().push(d.unbind()); }); # } ``` If you are executing arbitrary Python code while holding the lock, then you should import the [`MutexExt`] trait and use the `lock_py_attached` method instead of `lock`. This ensures that global synchronization events started by the Python runtime can proceed, avoiding possible deadlocks with the interpreter. [`GILOnceCell`]: {{#PYO3_DOCS_URL}}/pyo3/sync/struct.GILOnceCell.html [`GILProtected`]: https://docs.rs/pyo3/0.22/pyo3/sync/struct.GILProtected.html [`MutexExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.MutexExt.html [`Once`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html [`Once::call_once`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#tymethod.call_once [`Once::call_once_force`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#tymethod.call_once_force [`OnceExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html [`OnceExt::call_once_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html#tymethod.call_once_py_attached [`OnceExt::call_once_force_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html#tymethod.call_once_force_py_attached [`OnceLockExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html [`OnceLockExt::get_or_init_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html#tymethod.get_or_init_py_attached [`OnceLock`]: https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html [`OnceLock::get_or_init`]: https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html#tymethod.get_or_init [`Python::allow_threads`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.allow_threads [`Python::with_gil`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.with_gil [`Python<'py>`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html [`threading`]: https://docs.python.org/3/library/threading.html pyo3/guide/src/parallelism.md0000644000175000017500000002114015105742312016005 0ustar bdrungbdrung# Parallelism CPython has the infamous [Global Interpreter Lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock) (GIL), which prevents several threads from executing Python bytecode in parallel. This makes threading in Python a bad fit for [CPU-bound](https://en.wikipedia.org/wiki/CPU-bound) tasks and often forces developers to accept the overhead of multiprocessing. There is an experimental "free-threaded" version of CPython 3.13 that does not have a GIL, see the PyO3 docs on [free-threaded Python](./free-threading.md) for more information about that. In PyO3 parallelism can be easily achieved in Rust-only code. Let's take a look at our [word-count](https://github.com/PyO3/pyo3/blob/main/examples/word-count/src/lib.rs) example, where we have a `search` function that utilizes the [rayon](https://github.com/rayon-rs/rayon) crate to count words in parallel. ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; // These traits let us use `par_lines` and `map`. use rayon::str::ParallelString; use rayon::iter::ParallelIterator; /// Count the occurrences of needle in line, case insensitive fn count_line(line: &str, needle: &str) -> usize { let mut total = 0; for word in line.split(' ') { if word == needle { total += 1; } } total } #[pyfunction] fn search(contents: &str, needle: &str) -> usize { contents .par_lines() .map(|line| count_line(line, needle)) .sum() } ``` But let's assume you have a long running Rust function which you would like to execute several times in parallel. For the sake of example let's take a sequential version of the word count: ```rust,no_run # #![allow(dead_code)] # fn count_line(line: &str, needle: &str) -> usize { # let mut total = 0; # for word in line.split(' ') { # if word == needle { # total += 1; # } # } # total # } # fn search_sequential(contents: &str, needle: &str) -> usize { contents.lines().map(|line| count_line(line, needle)).sum() } ``` To enable parallel execution of this function, the [`Python::allow_threads`] method can be used to temporarily release the GIL, thus allowing other Python threads to run. We then have a function exposed to the Python runtime which calls `search_sequential` inside a closure passed to [`Python::allow_threads`] to enable true parallelism: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # # fn count_line(line: &str, needle: &str) -> usize { # let mut total = 0; # for word in line.split(' ') { # if word == needle { # total += 1; # } # } # total # } # # fn search_sequential(contents: &str, needle: &str) -> usize { # contents.lines().map(|line| count_line(line, needle)).sum() # } #[pyfunction] fn search_sequential_allow_threads(py: Python<'_>, contents: &str, needle: &str) -> usize { py.allow_threads(|| search_sequential(contents, needle)) } ``` Now Python threads can use more than one CPU core, resolving the limitation which usually makes multi-threading in Python only good for IO-bound tasks: ```Python from concurrent.futures import ThreadPoolExecutor from word_count import search_sequential_allow_threads executor = ThreadPoolExecutor(max_workers=2) future_1 = executor.submit( word_count.search_sequential_allow_threads, contents, needle ) future_2 = executor.submit( word_count.search_sequential_allow_threads, contents, needle ) result_1 = future_1.result() result_2 = future_2.result() ``` ## Benchmark Let's benchmark the `word-count` example to verify that we really did unlock parallelism with PyO3. We are using `pytest-benchmark` to benchmark four word count functions: 1. Pure Python version 2. Rust parallel version 3. Rust sequential version 4. Rust sequential version executed twice with two Python threads The benchmark script can be found [here](https://github.com/PyO3/pyo3/blob/main/examples/word-count/tests/test_word_count.py), and we can run `nox` in the `word-count` folder to benchmark these functions. While the results of the benchmark of course depend on your machine, the relative results should be similar to this (mid 2020): ```text -------------------------------------------------------------------------------------------------- benchmark: 4 tests ------------------------------------------------------------------------------------------------- Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test_word_count_rust_parallel 1.7315 (1.0) 4.6495 (1.0) 1.9972 (1.0) 0.4299 (1.0) 1.8142 (1.0) 0.2049 (1.0) 40;46 500.6943 (1.0) 375 1 test_word_count_rust_sequential 7.3348 (4.24) 10.3556 (2.23) 8.0035 (4.01) 0.7785 (1.81) 7.5597 (4.17) 0.8641 (4.22) 26;5 124.9457 (0.25) 121 1 test_word_count_rust_sequential_twice_with_threads 7.9839 (4.61) 10.3065 (2.22) 8.4511 (4.23) 0.4709 (1.10) 8.2457 (4.55) 0.3927 (1.92) 17;17 118.3274 (0.24) 114 1 test_word_count_python_sequential 27.3985 (15.82) 45.4527 (9.78) 28.9604 (14.50) 4.1449 (9.64) 27.5781 (15.20) 0.4638 (2.26) 3;5 34.5299 (0.07) 35 1 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ``` You can see that the Python threaded version is not much slower than the Rust sequential version, which means compared to an execution on a single CPU core the speed has doubled. ## Sharing Python objects between Rust threads In the example above we made a Python interface to a low-level rust function, and then leveraged the python `threading` module to run the low-level function in parallel. It is also possible to spawn threads in Rust that acquire the GIL and operate on Python objects. However, care must be taken to avoid writing code that deadlocks with the GIL in these cases. * Note: This example is meant to illustrate how to drop and re-acquire the GIL to avoid creating deadlocks. Unless the spawned threads subsequently release the GIL or you are using the free-threaded build of CPython, you will not see any speedups due to multi-threaded parallelism using `rayon` to parallelize code that acquires and holds the GIL for the entire execution of the spawned thread. In the example below, we share a `Vec` of User ID objects defined using the `pyclass` macro and spawn threads to process the collection of data into a `Vec` of booleans based on a predicate using a rayon parallel iterator: ```rust,no_run use pyo3::prelude::*; // These traits let us use int_par_iter and map use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; #[pyclass] struct UserID { id: i64, } let allowed_ids: Vec = Python::with_gil(|outer_py| { let instances: Vec> = (0..10).map(|x| Py::new(outer_py, UserID { id: x }).unwrap()).collect(); outer_py.allow_threads(|| { instances.par_iter().map(|instance| { Python::with_gil(|inner_py| { instance.borrow(inner_py).id > 5 }) }).collect() }) }); assert!(allowed_ids.into_iter().filter(|b| *b).count() == 4); ``` It's important to note that there is an `outer_py` GIL lifetime token as well as an `inner_py` token. Sharing GIL lifetime tokens between threads is not allowed and threads must individually acquire the GIL to access data wrapped by a python object. It's also important to see that this example uses [`Python::allow_threads`] to wrap the code that spawns OS threads via `rayon`. If this example didn't use `allow_threads`, a rayon worker thread would block on acquiring the GIL while a thread that owns the GIL spins forever waiting for the result of the rayon thread. Calling `allow_threads` allows the GIL to be released in the thread collecting the results from the worker threads. You should always call `allow_threads` in situations that spawn worker threads, but especially so in cases where worker threads need to acquire the GIL, to prevent deadlocks. [`Python::allow_threads`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.allow_threads pyo3/guide/src/getting-started.md0000644000175000017500000001504115105742312016610 0ustar bdrungbdrung# Installation To get started using PyO3 you will need three things: a Rust toolchain, a Python environment, and a way to build. We'll cover each of these below. > If you'd like to chat to the PyO3 maintainers and other PyO3 users, consider joining the [PyO3 Discord server](https://discord.gg/33kcChzH7f). We're keen to hear about your experience getting started, so we can make PyO3 as accessible as possible for everyone! ## Rust First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.63. If you can run `rustc --version` and the version is new enough you're good to go! ## Python To use PyO3, you need at least Python 3.7. While you can simply use the default Python interpreter on your system, it is recommended to use a virtual environment. ## Virtualenvs While you can use any virtualenv manager you like, we recommend the use of `pyenv` in particular if you want to develop or test for multiple different Python versions, so that is what the examples in this book will use. The installation instructions for `pyenv` can be found [here](https://github.com/pyenv/pyenv#getting-pyenv). (Note: To get the `pyenv activate` and `pyenv virtualenv` commands, you will also need to install the [`pyenv-virtualenv`](https://github.com/pyenv/pyenv-virtualenv) plugin. The [pyenv installer](https://github.com/pyenv/pyenv-installer#installation--update--uninstallation) will install both together.) It can be useful to keep the sources used when installing using `pyenv` so that future debugging can see the original source files. This can be done by passing the `--keep` flag as part of the `pyenv install` command. For example: ```bash pyenv install 3.12 --keep ``` ### Building There are a number of build and Python package management systems such as [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](./building-and-distribution.md#manual-builds). We recommend the use of `maturin`, which you can install [here](https://maturin.rs/installation.html). It is developed to work with PyO3 and provides the most "batteries included" experience, especially if you are aiming to publish to PyPI. `maturin` is just a Python package, so you can add it in the same way you already install Python packages. System Python: ```bash pip install maturin --user ``` pipx: ```bash pipx install maturin ``` pyenv: ```bash pyenv activate pyo3 pip install maturin ``` poetry: ```bash poetry add -G dev maturin ``` After installation, you can run `maturin --version` to check that you have correctly installed it. # Starting a new project First you should create the folder and virtual environment that are going to contain your new project. Here we will use the recommended `pyenv`: ```bash mkdir pyo3-example cd pyo3-example pyenv virtualenv pyo3 pyenv local pyo3 ``` After this, you should install your build manager. In this example, we will use `maturin`. After you've activated your virtualenv, add `maturin` to it: ```bash pip install maturin ``` Now you can initialize the new project: ```bash maturin init ``` If `maturin` is already installed, you can create a new project using that directly as well: ```bash maturin new -b pyo3 pyo3-example cd pyo3-example pyenv virtualenv pyo3 pyenv local pyo3 ``` # Adding to an existing project Sadly, `maturin` cannot currently be run in existing projects, so if you want to use Python in an existing project you basically have two options: 1. Create a new project as above and move your existing code into that project 2. Manually edit your project configuration as necessary If you opt for the second option, here are the things you need to pay attention to: ## Cargo.toml Make sure that the Rust crate you want to be able to access from Python is compiled into a library. You can have a binary output as well, but the code you want to access from Python has to be in the library part. Also, make sure that the crate type is `cdylib` and add PyO3 as a dependency as so: ```toml # If you already have [package] information in `Cargo.toml`, you can ignore # this section! [package] # `name` here is name of the package. name = "pyo3_start" # these are good defaults: version = "0.1.0" edition = "2021" [lib] # The name of the native library. This is the name which will be used in Python to import the # library (i.e. `import string_sum`). If you change this, you must also change the name of the # `#[pymodule]` in `src/lib.rs`. name = "pyo3_example" # "cdylib" is necessary to produce a shared library for Python to import from. crate-type = ["cdylib"] [dependencies] pyo3 = { {{#PYO3_CRATE_VERSION}}, features = ["extension-module"] } ``` ## pyproject.toml You should also create a `pyproject.toml` with the following contents: ```toml [build-system] requires = ["maturin>=1,<2"] build-backend = "maturin" [project] name = "pyo3_example" requires-python = ">=3.7" classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] ``` ## Running code After this you can setup Rust code to be available in Python as below; for example, you can place this code in `src/lib.rs`: ```rust,no_run use pyo3::prelude::*; /// Formats the sum of two numbers as string. #[pyfunction] fn sum_as_string(a: usize, b: usize) -> PyResult { Ok((a + b).to_string()) } /// A Python module implemented in Rust. The name of this function must match /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to /// import the module. #[pymodule] fn pyo3_example(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(sum_as_string, m)?) } ``` Now you can run `maturin develop` to prepare the Python package, after which you can use it like so: ```bash $ maturin develop # lots of progress output as maturin runs the compilation... $ python >>> import pyo3_example >>> pyo3_example.sum_as_string(5, 20) '25' ``` For more instructions on how to use Python code from Rust, see the [Python from Rust](python-from-rust.md) page. ## Maturin Import Hook In development, any changes in the code would require running `maturin develop` before testing. To streamline the development process, you may want to install [Maturin Import Hook](https://github.com/PyO3/maturin-import-hook) which will run `maturin develop` automatically when the library with code changes is being imported. pyo3/guide/src/class/0000775000175000017500000000000015105742312014267 5ustar bdrungbdrungpyo3/guide/src/class/call.md0000644000175000017500000001111015105742312015514 0ustar bdrungbdrung# Emulating callable objects Classes can be callable if they have a `#[pymethod]` named `__call__`. This allows instances of a class to behave similar to functions. This method's signature must look like `__call__(, ...) -> object` - here, any argument list can be defined as for normal pymethods ### Example: Implementing a call counter The following pyclass is a basic decorator - its constructor takes a Python object as argument and calls that object when called. An equivalent Python implementation is linked at the end. An example crate containing this pyclass can be found [here](https://github.com/PyO3/pyo3/tree/main/examples/decorator) ```rust,ignore {{#include ../../../examples/decorator/src/lib.rs}} ``` Python code: ```python {{#include ../../../examples/decorator/tests/example.py}} ``` Output: ```text say_hello has been called 1 time(s). hello say_hello has been called 2 time(s). hello say_hello has been called 3 time(s). hello say_hello has been called 4 time(s). hello ``` ### Pure Python implementation A Python implementation of this looks similar to the Rust version: ```python class Counter: def __init__(self, wraps): self.count = 0 self.wraps = wraps def __call__(self, *args, **kwargs): self.count += 1 print(f"{self.wraps.__name__} has been called {self.count} time(s)") self.wraps(*args, **kwargs) ``` Note that it can also be implemented as a higher order function: ```python def Counter(wraps): count = 0 def call(*args, **kwargs): nonlocal count count += 1 print(f"{wraps.__name__} has been called {count} time(s)") return wraps(*args, **kwargs) return call ``` ### What is the `AtomicU64` for? A [previous implementation] used a normal `u64`, which meant it required a `&mut self` receiver to update the count: ```rust,ignore #[pyo3(signature = (*args, **kwargs))] fn __call__( &mut self, py: Python<'_>, args: &Bound<'_, PyTuple>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult> { self.count += 1; let name = self.wraps.getattr(py, "__name__")?; println!("{} has been called {} time(s).", name, self.count); // After doing something, we finally forward the call to the wrapped function let ret = self.wraps.call(py, args, kwargs)?; // We could do something with the return value of // the function before returning it Ok(ret) } ``` The problem with this is that the `&mut self` receiver means PyO3 has to borrow it exclusively, and hold this borrow across the`self.wraps.call(py, args, kwargs)` call. This call returns control to the user's Python code which is free to call arbitrary things, *including* the decorated function. If that happens PyO3 is unable to create a second unique borrow and will be forced to raise an exception. As a result, something innocent like this will raise an exception: ```py @Counter def say_hello(): if say_hello.count < 2: print(f"hello from decorator") say_hello() # RuntimeError: Already borrowed ``` The implementation in this chapter fixes that by never borrowing exclusively; all the methods take `&self` as receivers, of which multiple may exist simultaneously. This requires a shared counter and the most straightforward way to implement thread-safe interior mutability (e.g. the type does not need to accept `&mut self` to modify the "interior" state) for a `u64` is to use [`AtomicU64`], so that's what is used here. This shows the dangers of running arbitrary Python code - note that "running arbitrary Python code" can be far more subtle than the example above: - Python's asynchronous executor may park the current thread in the middle of Python code, even in Python code that *you* control, and let other Python code run. - Dropping arbitrary Python objects may invoke destructors defined in Python (`__del__` methods). - Calling Python's C-api (most PyO3 apis call C-api functions internally) may raise exceptions, which may allow Python code in signal handlers to run. - On the free-threaded build, users might use Python's `threading` module to work with your types simultaneously from multiple OS threads. This is especially important if you are writing unsafe code; Python code must never be able to cause undefined behavior. You must ensure that your Rust code is in a consistent state before doing any of the above things. [previous implementation]: https://github.com/PyO3/pyo3/discussions/2598 "Thread Safe Decorator · Discussion #2598 · PyO3/pyo3" [`AtomicU64`]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicU64.html "AtomicU64 in std::sync::atomic - Rust" pyo3/guide/src/class/thread-safety.md0000644000175000017500000001121615105742312017350 0ustar bdrungbdrung# `#[pyclass]` thread safety Python objects are freely shared between threads by the Python interpreter. This means that: - there is no control which thread might eventually drop the `#[pyclass]` object, meaning `Send` is required. - multiple threads can potentially be reading the `#[pyclass]` data simultaneously, meaning `Sync` is required. This section of the guide discusses various data structures which can be used to make types satisfy these requirements. In special cases where it is known that your Python application is never going to use threads (this is rare!), these thread-safety requirements can be opted-out with [`#[pyclass(unsendable)]`](../class.md#customizing-the-class), at the cost of making concurrent access to the Rust data be runtime errors. This is only for very specific use cases; it is almost always better to make proper thread-safe types. ## Making `#[pyclass]` types thread-safe The general challenge with thread-safety is to make sure that two threads cannot produce a data race, i.e. unsynchronized writes to the same data at the same time. A data race produces an unpredictable result and is forbidden by Rust. By default, `#[pyclass]` employs an ["interior mutability" pattern](../class.md#bound-and-interior-mutability) to allow for either multiple `&T` references or a single exclusive `&mut T` reference to access the data. This allows for simple `#[pyclass]` types to be thread-safe automatically, at the cost of runtime checking for concurrent access. Errors will be raised if the usage overlaps. For example, the below simple class is thread-safe: ```rust,no_run # use pyo3::prelude::*; #[pyclass] struct MyClass { x: i32, y: i32, } #[pymethods] impl MyClass { fn get_x(&self) -> i32 { self.x } fn set_y(&mut self, value: i32) { self.y = value; } } ``` In the above example, if calls to `get_x` and `set_y` overlap (from two different threads) then at least one of those threads will experience a runtime error indicating that the data was "already borrowed". To avoid these errors, you can take control of the interior mutability yourself in one of the following ways. ### Using atomic data structures To remove the possibility of having overlapping `&self` and `&mut self` references produce runtime errors, consider using `#[pyclass(frozen)]` and use [atomic data structures](https://doc.rust-lang.org/std/sync/atomic/) to control modifications directly. For example, a thread-safe version of the above `MyClass` using atomic integers would be as follows: ```rust,no_run # use pyo3::prelude::*; use std::sync::atomic::{AtomicI32, Ordering}; #[pyclass(frozen)] struct MyClass { x: AtomicI32, y: AtomicI32, } #[pymethods] impl MyClass { fn get_x(&self) -> i32 { self.x.load(Ordering::Relaxed) } fn set_y(&self, value: i32) { self.y.store(value, Ordering::Relaxed) } } ``` ### Using locks An alternative to atomic data structures is to use [locks](https://doc.rust-lang.org/std/sync/struct.Mutex.html) to make threads wait for access to shared data. For example, a thread-safe version of the above `MyClass` using locks would be as follows: ```rust,no_run # use pyo3::prelude::*; use std::sync::Mutex; struct MyClassInner { x: i32, y: i32, } #[pyclass(frozen)] struct MyClass { inner: Mutex } #[pymethods] impl MyClass { fn get_x(&self) -> i32 { self.inner.lock().expect("lock not poisoned").x } fn set_y(&self, value: i32) { self.inner.lock().expect("lock not poisoned").y = value; } } ``` If you need to lock around state stored in the Python interpreter or otherwise call into the Python C API while a lock is held, you might find the `MutexExt` trait useful. It provides a `lock_py_attached` method for `std::sync::Mutex` that avoids deadlocks with the GIL or other global synchronization events in the interpreter. Additionally, support for the `parking_lot` and `lock_api` synchronization libraries is gated behind the `parking_lot` and `lock_api` features. You can also enable the `arc_lock` feature if you need the `arc_lock` features of either library. ### Wrapping unsynchronized data In some cases, the data structures stored within a `#[pyclass]` may themselves not be thread-safe. Rust will therefore not implement `Send` and `Sync` on the `#[pyclass]` type. To achieve thread-safety, a manual `Send` and `Sync` implementation is required which is `unsafe` and should only be done following careful review of the soundness of the implementation. Doing this for PyO3 types is no different than for any other Rust code, [the Rustonomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html) has a great discussion on this. pyo3/guide/src/class/numeric.md0000644000175000017500000003046215105742312016256 0ustar bdrungbdrung# Emulating numeric types At this point we have a `Number` class that we can't actually do any math on! Before proceeding, we should think about how we want to handle overflows. There are three obvious solutions: - We can have infinite precision just like Python's `int`. However that would be quite boring - we'd be reinventing the wheel. - We can raise exceptions whenever `Number` overflows, but that makes the API painful to use. - We can wrap around the boundary of `i32`. This is the approach we'll take here. To do that we'll just forward to `i32`'s `wrapping_*` methods. ### Fixing our constructor Let's address the first overflow, in `Number`'s constructor: ```python from my_module import Number n = Number(1 << 1337) ``` ```text Traceback (most recent call last): File "example.py", line 3, in n = Number(1 << 1337) OverflowError: Python int too large to convert to C long ``` Instead of relying on the default [`FromPyObject`] extraction to parse arguments, we can specify our own extraction function, using the `#[pyo3(from_py_with = ...)]` attribute. Unfortunately PyO3 doesn't provide a way to wrap Python integers out of the box, but we can do a Python call to mask it and cast it to an `i32`. ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; // 👇 This intentionally overflows! Ok(val as i32) } ``` We also add documentation, via `///` comments, which are visible to Python users. ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; Ok(val as i32) } /// Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not. /// It's not a story C would tell you. It's a Rust legend. #[pyclass(module = "my_module")] struct Number(i32); #[pymethods] impl Number { #[new] fn new(#[pyo3(from_py_with = wrap)] value: i32) -> Self { Self(value) } } ``` With that out of the way, let's implement some operators: ```rust,no_run use pyo3::exceptions::{PyZeroDivisionError, PyValueError}; # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __add__(&self, other: &Self) -> Self { Self(self.0.wrapping_add(other.0)) } fn __sub__(&self, other: &Self) -> Self { Self(self.0.wrapping_sub(other.0)) } fn __mul__(&self, other: &Self) -> Self { Self(self.0.wrapping_mul(other.0)) } fn __truediv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __floordiv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __rshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shr(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __lshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shl(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } } ``` ### Unary arithmetic operations ```rust,no_run # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __pos__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __neg__(&self) -> Self { Self(-self.0) } fn __abs__(&self) -> Self { Self(self.0.abs()) } fn __invert__(&self) -> Self { Self(!self.0) } } ``` ### Support for the `complex()`, `int()` and `float()` built-in functions. ```rust,no_run # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # use pyo3::types::PyComplex; #[pymethods] impl Number { fn __int__(&self) -> i32 { self.0 } fn __float__(&self) -> f64 { self.0 as f64 } fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> { PyComplex::from_doubles(py, self.0 as f64, 0.0) } } ``` We do not implement the in-place operations like `__iadd__` because we do not wish to mutate `Number`. Similarly we're not interested in supporting operations with different types, so we do not implement the reflected operations like `__radd__` either. Now Python can use our `Number` class: ```python from my_module import Number def hash_djb2(s: str): ''' A version of Daniel J. Bernstein's djb2 string hashing algorithm Like many hashing algorithms, it relies on integer wrapping. ''' n = Number(0) five = Number(5) for x in s: n = Number(ord(x)) + ((n << five) - n) return n assert hash_djb2('l50_50') == Number(-1152549421) ``` ### Final code ```rust use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use pyo3::exceptions::{PyValueError, PyZeroDivisionError}; use pyo3::prelude::*; use pyo3::class::basic::CompareOp; use pyo3::types::{PyComplex, PyString}; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; Ok(val as i32) } /// Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not. /// It's not a story C would tell you. It's a Rust legend. #[pyclass(module = "my_module")] struct Number(i32); #[pymethods] impl Number { #[new] fn new(#[pyo3(from_py_with = wrap)] value: i32) -> Self { Self(value) } fn __repr__(slf: &Bound<'_, Self>) -> PyResult { // Get the class name dynamically in case `Number` is subclassed let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; Ok(format!("{}({})", class_name, slf.borrow().0)) } fn __str__(&self) -> String { self.0.to_string() } fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } fn __bool__(&self) -> bool { self.0 != 0 } fn __add__(&self, other: &Self) -> Self { Self(self.0.wrapping_add(other.0)) } fn __sub__(&self, other: &Self) -> Self { Self(self.0.wrapping_sub(other.0)) } fn __mul__(&self, other: &Self) -> Self { Self(self.0.wrapping_mul(other.0)) } fn __truediv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __floordiv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __rshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shr(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __lshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shl(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __xor__(&self, other: &Self) -> Self { Self(self.0 ^ other.0) } fn __or__(&self, other: &Self) -> Self { Self(self.0 | other.0) } fn __and__(&self, other: &Self) -> Self { Self(self.0 & other.0) } fn __int__(&self) -> i32 { self.0 } fn __float__(&self) -> f64 { self.0 as f64 } fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> { PyComplex::from_doubles(py, self.0 as f64, 0.0) } } #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } # const SCRIPT: &'static std::ffi::CStr = pyo3::ffi::c_str!(r#" # def hash_djb2(s: str): # n = Number(0) # five = Number(5) # # for x in s: # n = Number(ord(x)) + ((n << five) - n) # return n # # assert hash_djb2('l50_50') == Number(-1152549421) # assert hash_djb2('logo') == Number(3327403) # assert hash_djb2('horizon') == Number(1097468315) # # # assert Number(2) + Number(2) == Number(4) # assert Number(2) + Number(2) != Number(5) # # assert Number(13) - Number(7) == Number(6) # assert Number(13) - Number(-7) == Number(20) # # assert Number(13) / Number(7) == Number(1) # assert Number(13) // Number(7) == Number(1) # # assert Number(13) * Number(7) == Number(13*7) # # assert Number(13) > Number(7) # assert Number(13) < Number(20) # assert Number(13) == Number(13) # assert Number(13) >= Number(7) # assert Number(13) <= Number(20) # assert Number(13) == Number(13) # # # assert (True if Number(1) else False) # assert (False if Number(0) else True) # # # assert int(Number(13)) == 13 # assert float(Number(13)) == 13 # assert Number.__doc__ == "Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not.\nIt's not a story C would tell you. It's a Rust legend." # assert Number(12345234523452) == Number(1498514748) # try: # import inspect # assert inspect.signature(Number).__str__() == '(value)' # except ValueError: # # Not supported with `abi3` before Python 3.10 # pass # assert Number(1337).__str__() == '1337' # assert Number(1337).__repr__() == 'Number(1337)' "#); # # use pyo3::PyTypeInfo; # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let globals = PyModule::import(py, "__main__")?.dict(); # globals.set_item("Number", Number::type_object(py))?; # # py.run(SCRIPT, Some(&globals), None)?; # Ok(()) # }) # } ``` ## Appendix: Writing some unsafe code At the beginning of this chapter we said that PyO3 doesn't provide a way to wrap Python integers out of the box but that's a half truth. There's not a PyO3 API for it, but there's a Python C API function that does: ```c unsigned long PyLong_AsUnsignedLongMask(PyObject *obj) ``` We can call this function from Rust by using [`pyo3::ffi::PyLong_AsUnsignedLongMask`]. This is an *unsafe* function, which means we have to use an unsafe block to call it and take responsibility for upholding the contracts of this function. Let's review those contracts: - The GIL must be held. If it's not, calling this function causes a data race. - The pointer must be valid, i.e. it must be properly aligned and point to a valid Python object. Let's create that helper function. The signature has to be `fn(&Bound<'_, PyAny>) -> PyResult`. - `&Bound<'_, PyAny>` represents a checked borrowed reference, so the pointer derived from it is valid (and not null). - Whenever we have borrowed references to Python objects in scope, it is guaranteed that the GIL is held. This reference is also where we can get a [`Python`] token to use in our call to [`PyErr::take`]. ```rust,no_run # #![allow(dead_code)] use std::os::raw::c_ulong; use pyo3::prelude::*; use pyo3::ffi; fn wrap(obj: &Bound<'_, PyAny>) -> Result { let py: Python<'_> = obj.py(); unsafe { let ptr = obj.as_ptr(); let ret: c_ulong = ffi::PyLong_AsUnsignedLongMask(ptr); if ret == c_ulong::MAX { if let Some(err) = PyErr::take(py) { return Err(err); } } Ok(ret as i32) } } ``` [`PyErr::take`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/struct.PyErr.html#method.take [`Python`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html [`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`pyo3::ffi::PyLong_AsUnsignedLongMask`]: {{#PYO3_DOCS_URL}}/pyo3/ffi/fn.PyLong_AsUnsignedLongMask.html pyo3/guide/src/class/object.md0000644000175000017500000002430015105742312016054 0ustar bdrungbdrung# Basic object customization Recall the `Number` class from the previous chapter: ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; #[pyclass] struct Number(i32); #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Self(value) } } #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } ``` At this point Python code can import the module, access the class and create class instances - but nothing else. ```python from my_module import Number n = Number(5) print(n) ``` ```text ``` ### String representations It can't even print an user-readable representation of itself! We can fix that by defining the `__repr__` and `__str__` methods inside a `#[pymethods]` block. We do this by accessing the value contained inside `Number`. ```rust,no_run # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { // For `__repr__` we want to return a string that Python code could use to recreate // the `Number`, like `Number(5)` for example. fn __repr__(&self) -> String { // We use the `format!` macro to create a string. Its first argument is a // format string, followed by any number of parameters which replace the // `{}`'s in the format string. // // 👇 Tuple field access in Rust uses a dot format!("Number({})", self.0) } // `__str__` is generally used to create an "informal" representation, so we // just forward to `i32`'s `ToString` trait implementation to print a bare number. fn __str__(&self) -> String { self.0.to_string() } } ``` To automatically generate the `__str__` implementation using a `Display` trait implementation, pass the `str` argument to `pyclass`. ```rust,no_run # use std::fmt::{Display, Formatter}; # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(str)] struct Coordinate { x: i32, y: i32, z: i32, } impl Display for Coordinate { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "({}, {}, {})", self.x, self.y, self.z) } } ``` For convenience, a shorthand format string can be passed to `str` as `str=""` for **structs only**. It expands and is passed into the `format!` macro in the following ways: * `"{x}"` -> `"{}", self.x` * `"{0}"` -> `"{}", self.0` * `"{x:?}"` -> `"{:?}", self.x` *Note: Depending upon the format string you use, this may require implementation of the `Display` or `Debug` traits for the given Rust types.* *Note: the pyclass args `name` and `rename_all` are incompatible with the shorthand format string and will raise a compile time error.* ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(str="({x}, {y}, {z})")] struct Coordinate { x: i32, y: i32, z: i32, } ``` #### Accessing the class name In the `__repr__`, we used a hard-coded class name. This is sometimes not ideal, because if the class is subclassed in Python, we would like the repr to reflect the subclass name. This is typically done in Python code by accessing `self.__class__.__name__`. In order to be able to access the Python type information *and* the Rust struct, we need to use a `Bound` as the `self` argument. ```rust,no_run # use pyo3::prelude::*; # use pyo3::types::PyString; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __repr__(slf: &Bound<'_, Self>) -> PyResult { // This is the equivalent of `self.__class__.__name__` in Python. let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; // To access fields of the Rust struct, we need to borrow the `PyCell`. Ok(format!("{}({})", class_name, slf.borrow().0)) } } ``` ### Hashing Let's also implement hashing. We'll just hash the `i32`. For that we need a [`Hasher`]. The one provided by `std` is [`DefaultHasher`], which uses the [SipHash] algorithm. ```rust,no_run use std::collections::hash_map::DefaultHasher; // Required to call the `.hash` and `.finish` methods, which are defined on traits. use std::hash::{Hash, Hasher}; # use pyo3::prelude::*; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } } ``` To implement `__hash__` using the Rust [`Hash`] trait implementation, the `hash` option can be used. This option is only available for `frozen` classes to prevent accidental hash changes from mutating the object. If you need an `__hash__` implementation for a mutable class, use the manual method from above. This option also requires `eq`: According to the [Python docs](https://docs.python.org/3/reference/datamodel.html#object.__hash__) "If a class does not define an `__eq__()` method it should not define a `__hash__()` operation either" ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(frozen, eq, hash)] #[derive(PartialEq, Hash)] struct Number(i32); ``` > **Note**: When implementing `__hash__` and comparisons, it is important that the following property holds: > > ```text > k1 == k2 -> hash(k1) == hash(k2) > ``` > > In other words, if two keys are equal, their hashes must also be equal. In addition you must take > care that your classes' hash doesn't change during its lifetime. In this tutorial we do that by not > letting Python code change our `Number` class. In other words, it is immutable. > > By default, all `#[pyclass]` types have a default hash implementation from Python. > Types which should not be hashable can override this by setting `__hash__` to None. > This is the same mechanism as for a pure-Python class. This is done like so: > > ```rust,no_run > # use pyo3::prelude::*; > #[pyclass] > struct NotHashable {} > > #[pymethods] > impl NotHashable { > #[classattr] > const __hash__: Option> = None; > } > ``` ### Comparisons PyO3 supports the usual magic comparison methods available in Python such as `__eq__`, `__lt__` and so on. It is also possible to support all six operations at once with `__richcmp__`. This method will be called with a value of `CompareOp` depending on the operation. ```rust,no_run use pyo3::class::basic::CompareOp; # use pyo3::prelude::*; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } } ``` If you obtain the result by comparing two Rust values, as in this example, you can take a shortcut using `CompareOp::matches`: ```rust,no_run use pyo3::class::basic::CompareOp; # use pyo3::prelude::*; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool { op.matches(self.0.cmp(&other.0)) } } ``` It checks that the `std::cmp::Ordering` obtained from Rust's `Ord` matches the given `CompareOp`. Alternatively, you can implement just equality using `__eq__`: ```rust # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __eq__(&self, other: &Self) -> bool { self.0 == other.0 } } # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let x = &Bound::new(py, Number(4))?; # let y = &Bound::new(py, Number(4))?; # assert!(x.eq(y)?); # assert!(!x.ne(y)?); # Ok(()) # }) # } ``` To implement `__eq__` using the Rust [`PartialEq`] trait implementation, the `eq` option can be used. ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(eq)] #[derive(PartialEq)] struct Number(i32); ``` To implement `__lt__`, `__le__`, `__gt__`, & `__ge__` using the Rust `PartialOrd` trait implementation, the `ord` option can be used. *Note: Requires `eq`.* ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] #[pyclass(eq, ord)] #[derive(PartialEq, PartialOrd)] struct Number(i32); ``` ### Truthyness We'll consider `Number` to be `True` if it is nonzero: ```rust,no_run # use pyo3::prelude::*; # # #[allow(dead_code)] # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __bool__(&self) -> bool { self.0 != 0 } } ``` ### Final code ```rust,no_run use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use pyo3::prelude::*; use pyo3::class::basic::CompareOp; use pyo3::types::PyString; #[pyclass] struct Number(i32); #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Self(value) } fn __repr__(slf: &Bound<'_, Self>) -> PyResult { let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; Ok(format!("{}({})", class_name, slf.borrow().0)) } fn __str__(&self) -> String { self.0.to_string() } fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } fn __bool__(&self) -> bool { self.0 != 0 } } #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } ``` [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html [`Hasher`]: https://doc.rust-lang.org/std/hash/trait.Hasher.html [`DefaultHasher`]: https://doc.rust-lang.org/std/collections/hash_map/struct.DefaultHasher.html [SipHash]: https://en.wikipedia.org/wiki/SipHash [`PartialEq`]: https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html pyo3/guide/src/class/protocols.md0000644000175000017500000004723115105742312016642 0ustar bdrungbdrung# Class customizations Python's object model defines several protocols for different object behavior, such as the sequence, mapping, and number protocols. Python classes support these protocols by implementing "magic" methods, such as `__str__` or `__repr__`. Because of the double-underscores surrounding their name, these are also known as "dunder" methods. PyO3 makes it possible for every magic method to be implemented in `#[pymethods]` just as they would be done in a regular Python class, with a few notable differences: - `__new__` and `__init__` are replaced by the [`#[new]` attribute](../class.md#constructor). - `__del__` is not yet supported, but may be in the future. - `__buffer__` and `__release_buffer__` are currently not supported and instead PyO3 supports [`__getbuffer__` and `__releasebuffer__`](#buffer-objects) methods (these predate [PEP 688](https://peps.python.org/pep-0688/#python-level-buffer-protocol)), again this may change in the future. - PyO3 adds [`__traverse__` and `__clear__`](#garbage-collector-integration) methods for controlling garbage collection. - The Python C-API which PyO3 is implemented upon requires many magic methods to have a specific function signature in C and be placed into special "slots" on the class type object. This limits the allowed argument and return types for these methods. They are listed in detail in the section below. If a magic method is not on the list above (for example `__init_subclass__`), then it should just work in PyO3. If this is not the case, please file a bug report. ## Magic Methods handled by PyO3 If a function name in `#[pymethods]` is a magic method which is known to need special handling, it will be automatically placed into the correct slot in the Python type object. The function name is taken from the usual rules for naming `#[pymethods]`: the `#[pyo3(name = "...")]` attribute is used if present, otherwise the Rust function name is used. The magic methods handled by PyO3 are very similar to the standard Python ones on [this page](https://docs.python.org/3/reference/datamodel.html#special-method-names) - in particular they are the subset which have slots as [defined here](https://docs.python.org/3/c-api/typeobj.html). When PyO3 handles a magic method, a couple of changes apply compared to other `#[pymethods]`: - The Rust function signature is restricted to match the magic method. - The `#[pyo3(signature = (...)]` and `#[pyo3(text_signature = "...")]` attributes are not allowed. The following sections list all magic methods for which PyO3 implements the necessary special handling. The given signatures should be interpreted as follows: - All methods take a receiver as first argument, shown as ``. It can be `&self`, `&mut self` or a `Bound` reference like `self_: PyRef<'_, Self>` and `self_: PyRefMut<'_, Self>`, as described [here](../class.md#inheritance). - An optional `Python<'py>` argument is always allowed as the first argument. - Return values can be optionally wrapped in `PyResult`. - `object` means that any type is allowed that can be extracted from a Python object (if argument) or converted to a Python object (if return value). - Other types must match what's given, e.g. `pyo3::basic::CompareOp` for `__richcmp__`'s second argument. - For the comparison and arithmetic methods, extraction errors are not propagated as exceptions, but lead to a return of `NotImplemented`. - For some magic methods, the return values are not restricted by PyO3, but checked by the Python interpreter. For example, `__str__` needs to return a string object. This is indicated by `object (Python type)`. ### Basic object customization - `__str__() -> object (str)` - `__repr__() -> object (str)` - `__hash__() -> isize` Objects that compare equal must have the same hash value. Any type up to 64 bits may be returned instead of `isize`, PyO3 will convert to an isize automatically (wrapping unsigned types like `u64` and `usize`).
Disabling Python's default hash By default, all `#[pyclass]` types have a default hash implementation from Python. Types which should not be hashable can override this by setting `__hash__` to `None`. This is the same mechanism as for a pure-Python class. This is done like so: ```rust,no_run # use pyo3::prelude::*; # #[pyclass] struct NotHashable {} #[pymethods] impl NotHashable { #[classattr] const __hash__: Option = None; } ```
- `__lt__(, object) -> object` - `__le__(, object) -> object` - `__eq__(, object) -> object` - `__ne__(, object) -> object` - `__gt__(, object) -> object` - `__ge__(, object) -> object` The implementations of Python's "rich comparison" operators `<`, `<=`, `==`, `!=`, `>` and `>=` respectively. _Note that implementing any of these methods will cause Python not to generate a default `__hash__` implementation, so consider also implementing `__hash__`._
Return type The return type will normally be `bool` or `PyResult`, however any Python object can be returned.
- `__richcmp__(, object, pyo3::basic::CompareOp) -> object` Implements Python comparison operations (`==`, `!=`, `<`, `<=`, `>`, and `>=`) in a single method. The `CompareOp` argument indicates the comparison operation being performed. You can use [`CompareOp::matches`] to adapt a Rust `std::cmp::Ordering` result to the requested comparison. _This method cannot be implemented in combination with any of `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__`, or `__ge__`._ _Note that implementing `__richcmp__` will cause Python not to generate a default `__hash__` implementation, so consider implementing `__hash__` when implementing `__richcmp__`._
Return type The return type will normally be `PyResult`, but any Python object can be returned. If you want to leave some operations unimplemented, you can return `py.NotImplemented()` for some of the operations: ```rust,no_run use pyo3::class::basic::CompareOp; use pyo3::types::PyNotImplemented; # use pyo3::prelude::*; # use pyo3::BoundObject; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__<'py>(&self, other: &Self, op: CompareOp, py: Python<'py>) -> PyResult> { match op { CompareOp::Eq => Ok((self.0 == other.0).into_pyobject(py)?.into_any()), CompareOp::Ne => Ok((self.0 != other.0).into_pyobject(py)?.into_any()), _ => Ok(PyNotImplemented::get(py).into_any()), } } } ``` If the second argument `object` is not of the type specified in the signature, the generated code will automatically `return NotImplemented`.
- `__getattr__(, object) -> object` - `__getattribute__(, object) -> object`
Differences between `__getattr__` and `__getattribute__` As in Python, `__getattr__` is only called if the attribute is not found by normal attribute lookup. `__getattribute__`, on the other hand, is called for *every* attribute access. If it wants to access existing attributes on `self`, it needs to be very careful not to introduce infinite recursion, and use `baseclass.__getattribute__()`.
- `__setattr__(, value: object) -> ()` - `__delattr__(, object) -> ()` Overrides attribute access. - `__bool__() -> bool` Determines the "truthyness" of an object. - `__call__(, ...) -> object` - here, any argument list can be defined as for normal `pymethods` ### Iterable objects Iterators can be defined using these methods: - `__iter__() -> object` - `__next__() -> Option or IterNextOutput` ([see details](#returning-a-value-from-iteration)) Returning `None` from `__next__` indicates that that there are no further items. Example: ```rust,no_run use pyo3::prelude::*; use std::sync::Mutex; #[pyclass] struct MyIterator { iter: Mutex + Send>>, } #[pymethods] impl MyIterator { fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(slf: PyRefMut<'_, Self>) -> Option { slf.iter.lock().unwrap().next() } } ``` In many cases you'll have a distinction between the type being iterated over (i.e. the *iterable*) and the iterator it provides. In this case, the iterable only needs to implement `__iter__()` while the iterator must implement both `__iter__()` and `__next__()`. For example: ```rust,no_run # use pyo3::prelude::*; #[pyclass] struct Iter { inner: std::vec::IntoIter, } #[pymethods] impl Iter { fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { slf.inner.next() } } #[pyclass] struct Container { iter: Vec, } #[pymethods] impl Container { fn __iter__(slf: PyRef<'_, Self>) -> PyResult> { let iter = Iter { inner: slf.iter.clone().into_iter(), }; Py::new(slf.py(), iter) } } # Python::with_gil(|py| { # let container = Container { iter: vec![1, 2, 3, 4] }; # let inst = pyo3::Py::new(py, container).unwrap(); # pyo3::py_run!(py, inst, "assert list(inst) == [1, 2, 3, 4]"); # pyo3::py_run!(py, inst, "assert list(iter(iter(inst))) == [1, 2, 3, 4]"); # }); ``` For more details on Python's iteration protocols, check out [the "Iterator Types" section of the library documentation](https://docs.python.org/library/stdtypes.html#iterator-types). #### Returning a value from iteration This guide has so far shown how to use `Option` to implement yielding values during iteration. In Python a generator can also return a value. This is done by raising a `StopIteration` exception. To express this in Rust, return `PyResult::Err` with a `PyStopIteration` as the error. ### Awaitable objects - `__await__() -> object` - `__aiter__() -> object` - `__anext__() -> Option` ### Mapping & Sequence types The magic methods in this section can be used to implement Python container types. They are two main categories of container in Python: "mappings" such as `dict`, with arbitrary keys, and "sequences" such as `list` and `tuple`, with integer keys. The Python C-API which PyO3 is built upon has separate "slots" for sequences and mappings. When writing a `class` in pure Python, there is no such distinction in the implementation - a `__getitem__` implementation will fill the slots for both the mapping and sequence forms, for example. By default PyO3 reproduces the Python behaviour of filling both mapping and sequence slots. This makes sense for the "simple" case which matches Python, and also for sequences, where the mapping slot is used anyway to implement slice indexing. Mapping types usually will not want the sequence slots filled. Having them filled will lead to outcomes which may be unwanted, such as: - The mapping type will successfully cast to [`PySequence`]. This may lead to consumers of the type handling it incorrectly. - Python provides a default implementation of `__iter__` for sequences, which calls `__getitem__` with consecutive positive integers starting from 0 until an `IndexError` is returned. Unless the mapping only contains consecutive positive integer keys, this `__iter__` implementation will likely not be the intended behavior. Use the `#[pyclass(mapping)]` annotation to instruct PyO3 to only fill the mapping slots, leaving the sequence ones empty. This will apply to `__getitem__`, `__setitem__`, and `__delitem__`. Use the `#[pyclass(sequence)]` annotation to instruct PyO3 to fill the `sq_length` slot instead of the `mp_length` slot for `__len__`. This will help libraries such as `numpy` recognise the class as a sequence, however will also cause CPython to automatically add the sequence length to any negative indices before passing them to `__getitem__`. (`__getitem__`, `__setitem__` and `__delitem__` mapping slots are still used for sequences, for slice operations.) - `__len__() -> usize` Implements the built-in function `len()`. - `__contains__(, object) -> bool` Implements membership test operators. Should return true if `item` is in `self`, false otherwise. For objects that don’t define `__contains__()`, the membership test simply traverses the sequence until it finds a match.
Disabling Python's default contains By default, all `#[pyclass]` types with an `__iter__` method support a default implementation of the `in` operator. Types which do not want this can override this by setting `__contains__` to `None`. This is the same mechanism as for a pure-Python class. This is done like so: ```rust,no_run # use pyo3::prelude::*; # #[pyclass] struct NoContains {} #[pymethods] impl NoContains { #[classattr] const __contains__: Option = None; } ```
- `__getitem__(, object) -> object` Implements retrieval of the `self[a]` element. *Note:* Negative integer indexes are not handled specially by PyO3. However, for classes with `#[pyclass(sequence)]`, when a negative index is accessed via `PySequence::get_item`, the underlying C API already adjusts the index to be positive. - `__setitem__(, object, object) -> ()` Implements assignment to the `self[a]` element. Should only be implemented if elements can be replaced. Same behavior regarding negative indices as for `__getitem__`. - `__delitem__(, object) -> ()` Implements deletion of the `self[a]` element. Should only be implemented if elements can be deleted. Same behavior regarding negative indices as for `__getitem__`. * `fn __concat__(&self, other: impl FromPyObject) -> PyResult` Concatenates two sequences. Used by the `+` operator, after trying the numeric addition via the `__add__` and `__radd__` methods. * `fn __repeat__(&self, count: isize) -> PyResult` Repeats the sequence `count` times. Used by the `*` operator, after trying the numeric multiplication via the `__mul__` and `__rmul__` methods. * `fn __inplace_concat__(&self, other: impl FromPyObject) -> PyResult` Concatenates two sequences. Used by the `+=` operator, after trying the numeric addition via the `__iadd__` method. * `fn __inplace_repeat__(&self, count: isize) -> PyResult` Concatenates two sequences. Used by the `*=` operator, after trying the numeric multiplication via the `__imul__` method. ### Descriptors - `__get__(, object, object) -> object` - `__set__(, object, object) -> ()` - `__delete__(, object) -> ()` ### Numeric types Binary arithmetic operations (`+`, `-`, `*`, `@`, `/`, `//`, `%`, `divmod()`, `pow()` and `**`, `<<`, `>>`, `&`, `^`, and `|`) and their reflected versions: (If the `object` is not of the type specified in the signature, the generated code will automatically `return NotImplemented`.) - `__add__(, object) -> object` - `__radd__(, object) -> object` - `__sub__(, object) -> object` - `__rsub__(, object) -> object` - `__mul__(, object) -> object` - `__rmul__(, object) -> object` - `__matmul__(, object) -> object` - `__rmatmul__(, object) -> object` - `__floordiv__(, object) -> object` - `__rfloordiv__(, object) -> object` - `__truediv__(, object) -> object` - `__rtruediv__(, object) -> object` - `__divmod__(, object) -> object` - `__rdivmod__(, object) -> object` - `__mod__(, object) -> object` - `__rmod__(, object) -> object` - `__lshift__(, object) -> object` - `__rlshift__(, object) -> object` - `__rshift__(, object) -> object` - `__rrshift__(, object) -> object` - `__and__(, object) -> object` - `__rand__(, object) -> object` - `__xor__(, object) -> object` - `__rxor__(, object) -> object` - `__or__(, object) -> object` - `__ror__(, object) -> object` - `__pow__(, object, object) -> object` - `__rpow__(, object, object) -> object` In-place assignment operations (`+=`, `-=`, `*=`, `@=`, `/=`, `//=`, `%=`, `**=`, `<<=`, `>>=`, `&=`, `^=`, `|=`): - `__iadd__(, object) -> ()` - `__isub__(, object) -> ()` - `__imul__(, object) -> ()` - `__imatmul__(, object) -> ()` - `__itruediv__(, object) -> ()` - `__ifloordiv__(, object) -> ()` - `__imod__(, object) -> ()` - `__ipow__(, object, object) -> ()` - `__ilshift__(, object) -> ()` - `__irshift__(, object) -> ()` - `__iand__(, object) -> ()` - `__ixor__(, object) -> ()` - `__ior__(, object) -> ()` Unary operations (`-`, `+`, `abs()` and `~`): - `__pos__() -> object` - `__neg__() -> object` - `__abs__() -> object` - `__invert__() -> object` Coercions: - `__index__() -> object (int)` - `__int__() -> object (int)` - `__float__() -> object (float)` ### Buffer objects - `__getbuffer__(, *mut ffi::Py_buffer, flags) -> ()` - `__releasebuffer__(, *mut ffi::Py_buffer) -> ()` Errors returned from `__releasebuffer__` will be sent to `sys.unraiseablehook`. It is strongly advised to never return an error from `__releasebuffer__`, and if it really is necessary, to make best effort to perform any required freeing operations before returning. `__releasebuffer__` will not be called a second time; anything not freed will be leaked. ### Garbage Collector Integration If your type owns references to other Python objects, you will need to integrate with Python's garbage collector so that the GC is aware of those references. To do this, implement the two methods `__traverse__` and `__clear__`. These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API. `__traverse__` must call `visit.call()` for each reference to another Python object. `__clear__` must clear out any mutable references to other Python objects (thus breaking reference cycles). Immutable references do not have to be cleared, as every cycle must contain at least one mutable reference. - `__traverse__(, pyo3::class::gc::PyVisit<'_>) -> Result<(), pyo3::class::gc::PyTraverseError>` - `__clear__() -> ()` Example: ```rust,no_run use pyo3::prelude::*; use pyo3::PyTraverseError; use pyo3::gc::PyVisit; #[pyclass] struct ClassWithGCSupport { obj: Option, } #[pymethods] impl ClassWithGCSupport { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.obj)?; Ok(()) } fn __clear__(&mut self) { // Clear reference, this decrements ref counter. self.obj = None; } } ``` Usually, an implementation of `__traverse__` should do nothing but calls to `visit.call`. Most importantly, safe access to the GIL is prohibited inside implementations of `__traverse__`, i.e. `Python::with_gil` will panic. > Note: these methods are part of the C API, PyPy does not necessarily honor them. If you are building for PyPy you should measure memory consumption to make sure you do not have runaway memory growth. See [this issue on the PyPy bug tracker](https://github.com/pypy/pypy/issues/3848). [`PySequence`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PySequence.html [`CompareOp::matches`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/enum.CompareOp.html#method.matches pyo3/guide/src/advanced.md0000644000175000017500000000062115105742312015246 0ustar bdrungbdrung# Advanced topics ## FFI PyO3 exposes much of Python's C API through the `ffi` module. The C API is naturally unsafe and requires you to manage reference counts, errors and specific invariants yourself. Please refer to the [C API Reference Manual](https://docs.python.org/3/c-api/) and [The Rustonomicon](https://doc.rust-lang.org/nightly/nomicon/ffi.html) before using any function from that API. pyo3/guide/src/module.md0000644000175000017500000001243515105742312014774 0ustar bdrungbdrung# Python modules You can create a module using `#[pymodule]`: ```rust,no_run use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } /// This module is implemented in Rust. #[pymodule] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(double, m)?) } ``` The `#[pymodule]` procedural macro takes care of exporting the initialization function of your module to Python. The module's name defaults to the name of the Rust function. You can override the module name by using `#[pyo3(name = "custom_name")]`: ```rust,no_run use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } #[pymodule(name = "custom_name")] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(double, m)?) } ``` The name of the module must match the name of the `.so` or `.pyd` file. Otherwise, you will get an import error in Python with the following message: `ImportError: dynamic module does not define module export function (PyInit_name_of_your_module)` To import the module, either: - copy the shared library as described in [Manual builds](building-and-distribution.md#manual-builds), or - use a tool, e.g. `maturin develop` with [maturin](https://github.com/PyO3/maturin) or `python setup.py develop` with [setuptools-rust](https://github.com/PyO3/setuptools-rust). ## Documentation The [Rust doc comments](https://doc.rust-lang.org/stable/book/ch03-04-comments.html) of the module initialization function will be applied automatically as the Python docstring of your module. For example, building off of the above code, this will print `This module is implemented in Rust.`: ```python import my_extension print(my_extension.__doc__) ``` ## Python submodules You can create a module hierarchy within a single extension module by using [`Bound<'_, PyModule>::add_submodule()`]({{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyModuleMethods.html#tymethod.add_submodule). For example, you could define the modules `parent_module` and `parent_module.child_module`. ```rust use pyo3::prelude::*; #[pymodule] fn parent_module(m: &Bound<'_, PyModule>) -> PyResult<()> { register_child_module(m)?; Ok(()) } fn register_child_module(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let child_module = PyModule::new(parent_module.py(), "child_module")?; child_module.add_function(wrap_pyfunction!(func, &child_module)?)?; parent_module.add_submodule(&child_module) } #[pyfunction] fn func() -> String { "func".to_string() } # Python::with_gil(|py| { # use pyo3::wrap_pymodule; # use pyo3::types::IntoPyDict; # use pyo3::ffi::c_str; # let parent_module = wrap_pymodule!(parent_module)(py); # let ctx = [("parent_module", parent_module)].into_py_dict(py).unwrap(); # # py.run(c_str!("assert parent_module.child_module.func() == 'func'"), None, Some(&ctx)).unwrap(); # }) ``` Note that this does not define a package, so this won’t allow Python code to directly import submodules by using `from parent_module import child_module`. For more information, see [#759](https://github.com/PyO3/pyo3/issues/759) and [#1517](https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021). It is not necessary to add `#[pymodule]` on nested modules, which is only required on the top-level module. ## Declarative modules Another syntax based on Rust inline modules is also available to declare modules. For example: ```rust,no_run # mod declarative_module_test { use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } #[pymodule] mod my_extension { use super::*; #[pymodule_export] use super::double; // Exports the double function as part of the module #[pymodule_export] const PI: f64 = std::f64::consts::PI; // Exports PI constant as part of the module #[pyfunction] // This will be part of the module fn triple(x: usize) -> usize { x * 3 } #[pyclass] // This will be part of the module struct Unit; #[pymodule] mod submodule { // This is a submodule } #[pymodule_init] fn init(m: &Bound<'_, PyModule>) -> PyResult<()> { // Arbitrary code to run at the module initialization m.add("double2", m.getattr("double")?) } } # } ``` The `#[pymodule]` macro automatically sets the `module` attribute of the `#[pyclass]` macros declared inside of it with its name. For nested modules, the name of the parent module is automatically added. In the following example, the `Unit` class will have for `module` `my_extension.submodule` because it is properly nested but the `Ext` class will have for `module` the default `builtins` because it not nested. ```rust,no_run # mod declarative_module_module_attr_test { use pyo3::prelude::*; #[pyclass] struct Ext; #[pymodule] mod my_extension { use super::*; #[pymodule_export] use super::Ext; #[pymodule] mod submodule { use super::*; // This is a submodule #[pyclass] // This will be part of the module struct Unit; } } # } ``` It is possible to customize the `module` value for a `#[pymodule]` with the `#[pyo3(module = "MY_MODULE")]` option. You can provide the `submodule` argument to `pymodule()` for modules that are not top-level modules -- it is automatically set for modules nested inside of a `#[pymodule]`. pyo3/guide/src/function.md0000644000175000017500000001764215105742312015341 0ustar bdrungbdrung# Python functions The `#[pyfunction]` attribute is used to define a Python function from a Rust function. Once defined, the function needs to be added to a [module](./module.md) using the `wrap_pyfunction!` macro. The following example defines a function called `double` in a Python module called `my_extension`: ```rust,no_run use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } #[pymodule] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(double, m)?) } ``` This chapter of the guide explains full usage of the `#[pyfunction]` attribute. In this first section, the following topics are covered: - [Function options](#function-options) - [`#[pyo3(name = "...")]`](#name) - [`#[pyo3(signature = (...))]`](#signature) - [`#[pyo3(text_signature = "...")]`](#text_signature) - [`#[pyo3(pass_module)]`](#pass_module) - [Per-argument options](#per-argument-options) - [Advanced function patterns](#advanced-function-patterns) - [`#[pyfn]` shorthand](#pyfn-shorthand) There are also additional sections on the following topics: - [Function Signatures](./function/signature.md) ## Function options The `#[pyo3]` attribute can be used to modify properties of the generated Python function. It can take any combination of the following options: - `#[pyo3(name = "...")]` Overrides the name exposed to Python. In the following example, the Rust function `no_args_py` will be added to the Python module `module_with_functions` as the Python function `no_args`: ```rust use pyo3::prelude::*; #[pyfunction] #[pyo3(name = "no_args")] fn no_args_py() -> usize { 42 } #[pymodule] fn module_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(no_args_py, m)?) } # Python::with_gil(|py| { # let m = pyo3::wrap_pymodule!(module_with_functions)(py); # assert!(m.getattr(py, "no_args").is_ok()); # assert!(m.getattr(py, "no_args_py").is_err()); # }); ``` - `#[pyo3(signature = (...))]` Defines the function signature in Python. See [Function Signatures](./function/signature.md). - `#[pyo3(text_signature = "...")]` Overrides the PyO3-generated function signature visible in Python tooling (such as via [`inspect.signature`]). See the [corresponding topic in the Function Signatures subchapter](./function/signature.md#making-the-function-signature-available-to-python). - `#[pyo3(pass_module)]` Set this option to make PyO3 pass the containing module as the first argument to the function. It is then possible to use the module in the function body. The first argument **must** be of type `&Bound<'_, PyModule>`, `Bound<'_, PyModule>`, or `Py`. The following example creates a function `pyfunction_with_module` which returns the containing module's name (i.e. `module_with_fn`): ```rust,no_run use pyo3::prelude::*; use pyo3::types::PyString; #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module<'py>( module: &Bound<'py, PyModule>, ) -> PyResult> { module.name() } #[pymodule] fn module_with_fn(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?) } ``` ## Per-argument options The `#[pyo3]` attribute can be used on individual arguments to modify properties of them in the generated function. It can take any combination of the following options: - `#[pyo3(from_py_with = ...)]` Set this on an option to specify a custom function to convert the function argument from Python to the desired Rust type, instead of using the default `FromPyObject` extraction. The function signature must be `fn(&Bound<'_, PyAny>) -> PyResult` where `T` is the Rust type of the argument. The following example uses `from_py_with` to convert the input Python object to its length: ```rust use pyo3::prelude::*; fn get_length(obj: &Bound<'_, PyAny>) -> PyResult { obj.len() } #[pyfunction] fn object_length(#[pyo3(from_py_with = get_length)] argument: usize) -> usize { argument } # Python::with_gil(|py| { # let f = pyo3::wrap_pyfunction!(object_length)(py).unwrap(); # assert_eq!(f.call1((vec![1, 2, 3],)).unwrap().extract::().unwrap(), 3); # }); ``` ## Advanced function patterns ### Calling Python functions in Rust You can pass Python `def`'d functions and built-in functions to Rust functions [`PyFunction`] corresponds to regular Python functions while [`PyCFunction`] describes built-ins such as `repr()`. You can also use [`Bound<'_, PyAny>::is_callable`] to check if you have a callable object. `is_callable` will return `true` for functions (including lambdas), methods and objects with a `__call__` method. You can call the object with [`Bound<'_, PyAny>::call`] with the args as first parameter and the kwargs (or `None`) as second parameter. There are also [`Bound<'_, PyAny>::call0`] with no args and [`Bound<'_, PyAny>::call1`] with only positional args. ### Calling Rust functions in Python The ways to convert a Rust function into a Python object vary depending on the function: - Named functions, e.g. `fn foo()`: add `#[pyfunction]` and then use [`wrap_pyfunction!`] to get the corresponding [`PyCFunction`]. - Anonymous functions (or closures), e.g. `foo: fn()` either: - use a `#[pyclass]` struct which stores the function as a field and implement `__call__` to call the stored function. - use `PyCFunction::new_closure` to create an object directly from the function. [`Bound<'_, PyAny>::is_callable`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.is_callable [`Bound<'_, PyAny>::call`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call [`Bound<'_, PyAny>::call0`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call0 [`Bound<'_, PyAny>::call1`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call1 [`wrap_pyfunction!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.wrap_pyfunction.html [`PyFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFunction.html [`PyCFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyCFunction.html ### Accessing the FFI functions In order to make Rust functions callable from Python, PyO3 generates an `extern "C"` function whose exact signature depends on the Rust signature. (PyO3 chooses the optimal Python argument passing convention.) It then embeds the call to the Rust function inside this FFI-wrapper function. This wrapper handles extraction of the regular arguments and the keyword arguments from the input `PyObject`s. The `wrap_pyfunction` macro can be used to directly get a `Bound` given a `#[pyfunction]` and a `Bound`: `wrap_pyfunction!(rust_fun, module)`. ## `#[pyfn]` shorthand There is a shorthand to `#[pyfunction]` and `wrap_pymodule!`: the function can be placed inside the module definition and annotated with `#[pyfn]`. To simplify PyO3, it is expected that `#[pyfn]` may be removed in a future release (See [#694](https://github.com/PyO3/pyo3/issues/694)). An example of `#[pyfn]` is below: ```rust,no_run use pyo3::prelude::*; #[pymodule] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m)] fn double(x: usize) -> usize { x * 2 } Ok(()) } ``` `#[pyfn(m)]` is just syntactic sugar for `#[pyfunction]`, and takes all the same options documented in the rest of this chapter. The code above is expanded to the following: ```rust,no_run use pyo3::prelude::*; #[pymodule] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfunction] fn double(x: usize) -> usize { x * 2 } m.add_function(wrap_pyfunction!(double, m)?) } ``` [`inspect.signature`]: https://docs.python.org/3/library/inspect.html#inspect.signature pyo3/guide/theme/0000775000175000017500000000000015105742312013475 5ustar bdrungbdrungpyo3/guide/theme/tabs.css0000644000175000017500000000062715105742312015143 0ustar bdrungbdrung.mdbook-tabs { display: flex; } .mdbook-tab { background-color: var(--table-alternate-bg); padding: 0.5rem 1rem; cursor: pointer; border: none; font-size: 1.6rem; line-height: 1.45em; } .mdbook-tab.active { background-color: var(--table-header-bg); font-weight: bold; } .mdbook-tab-content { padding: 1rem 0rem; } .mdbook-tab-content table { margin: unset; } pyo3/guide/theme/tabs.js0000644000175000017500000000450215105742312014763 0ustar bdrungbdrung/** * Change active tab of tabs. * * @param {Element} container * @param {string} name */ const changeTab = (container, name) => { for (const child of container.children) { if (!(child instanceof HTMLElement)) { continue; } if (child.classList.contains('mdbook-tabs')) { for (const tab of child.children) { if (!(tab instanceof HTMLElement)) { continue; } if (tab.dataset.tabname === name) { tab.classList.add('active'); } else { tab.classList.remove('active'); } } } else if (child.classList.contains('mdbook-tab-content')) { if (child.dataset.tabname === name) { child.classList.remove('hidden'); } else { child.classList.add('hidden'); } } } }; document.addEventListener('DOMContentLoaded', () => { const tabs = document.querySelectorAll('.mdbook-tab'); for (const tab of tabs) { tab.addEventListener('click', () => { if (!(tab instanceof HTMLElement)) { return; } if (!tab.parentElement || !tab.parentElement.parentElement) { return; } const container = tab.parentElement.parentElement; const name = tab.dataset.tabname; const global = container.dataset.tabglobal; changeTab(container, name); if (global) { localStorage.setItem(`mdbook-tabs-${global}`, name); const globalContainers = document.querySelectorAll( `.mdbook-tabs-container[data-tabglobal="${global}"]` ); for (const globalContainer of globalContainers) { changeTab(globalContainer, name); } } }); } const containers = document.querySelectorAll('.mdbook-tabs-container[data-tabglobal]'); for (const container of containers) { const global = container.dataset.tabglobal; const name = localStorage.getItem(`mdbook-tabs-${global}`); if (name && document.querySelector(`.mdbook-tab[data-tabname=${name}]`)) { changeTab(container, name); } } }); pyo3/Architecture.md0000644000175000017500000002357115105742312014250 0ustar bdrungbdrung # PyO3: Architecture This document roughly describes the high-level architecture of PyO3. If you want to become familiar with the codebase you are in the right place! ## Overview PyO3 provides a bridge between Rust and Python, based on the [Python/C API]. Thus, PyO3 has low-level bindings of these API as its core. On top of that, we have higher-level bindings to operate Python objects safely. Also, to define Python classes and functions in Rust code, we have `trait PyClass` and a set of protocol traits (e.g., `PyIterProtocol`) for supporting object protocols (i.e., `__dunder__` methods). Since implementing `PyClass` requires lots of boilerplate, we have a proc-macro `#[pyclass]`. To summarize, there are six main parts to the PyO3 codebase. 1. [Low-level bindings of Python/C API.](#1-low-level-bindings-of-python-capi) - [`pyo3-ffi`] and [`src/ffi`] 2. [Bindings to Python objects.](#2-bindings-to-python-objects) - [`src/instance.rs`] and [`src/types`] 3. [`PyClass` and related functionalities.](#3-pyclass-and-related-functionalities) - [`src/pycell.rs`], [`src/pyclass.rs`], and more 4. [Procedural macros to simplify usage for users.](#4-procedural-macros-to-simplify-usage-for-users) - [`src/impl_`], [`pyo3-macros`] and [`pyo3-macros-backend`] 5. [`build.rs` and `pyo3-build-config`](#5-buildrs-and-pyo3-build-config) - [`build.rs`](https://github.com/PyO3/pyo3/tree/main/build.rs) - [`pyo3-build-config`] ## 1. Low-level bindings of Python/C API [`pyo3-ffi`] contains wrappers of the [Python/C API]. This is currently done by hand rather than automated tooling because: - it gives us best control about how to adapt C conventions to Rust, and - there are many Python interpreter versions we support in a single set of files. We aim to provide straight-forward Rust wrappers resembling the file structure of [`cpython/Include`](https://github.com/python/cpython/tree/3.13/Include). We are continuously updating the module to match the latest CPython version which PyO3 supports (i.e. as of time of writing Python 3.13). The tracking issue is [#1289](https://github.com/PyO3/pyo3/issues/1289), and contribution is welcome. In the [`pyo3-ffi`] crate, there is lots of conditional compilation such as `#[cfg(Py_LIMITED_API)]`, `#[cfg(Py_3_7)]`, and `#[cfg(PyPy)]`. `Py_LIMITED_API` corresponds to `#define Py_LIMITED_API` macro in Python/C API. With `Py_LIMITED_API`, we can build a Python-version-agnostic binary called an [abi3 wheel](https://pyo3.rs/latest/building-and-distribution.html#py_limited_apiabi3). `Py_3_7` means that the API is available from Python >= 3.7. There are also `Py_3_8`, `Py_3_9`, and so on. `PyPy` means that the API definition is for PyPy. Those flags are set in [`build.rs`](#6-buildrs-and-pyo3-build-config). ## 2. Bindings to Python objects [`src/types`] contains bindings to [built-in types](https://docs.python.org/3/library/stdtypes.html) of Python, such as `dict` and `list`. For historical reasons, Python's `object` is called `PyAny` in PyO3 and located in [`src/types/any.rs`]. Currently, `PyAny` is a straightforward wrapper of `ffi::PyObject`, defined as: ```rust #[repr(transparent)] pub struct PyAny(UnsafeCell); ``` Concrete Python objects are implemented by wrapping `PyAny`, e.g.,: ```rust #[repr(transparent)] pub struct PyDict(PyAny); ``` These types are not intended to be accessed directly, and instead are used through the `Py` and `Bound` smart pointers. We have some macros in [`src/types/mod.rs`] which make it easier to implement APIs for concrete Python types. ## 3. `PyClass` and related functionalities [`src/pycell.rs`], [`src/pyclass.rs`], and [`src/type_object.rs`] contain types and traits to make `#[pyclass]` work. Also, [`src/pyclass_init.rs`] and [`src/impl_/pyclass.rs`] have related functionalities. To realize object-oriented programming in C, all Python objects have `ob_base: PyObject` as their first field in their structure definition. Thanks to this guarantee, casting `*mut A` to `*mut PyObject` is valid if `A` is a Python object. To ensure this guarantee, we have a wrapper struct `PyCell` in [`src/pycell.rs`] which is roughly: ```rust #[repr(C)] pub struct PyCell { ob_base: crate::ffi::PyObject, inner: T, } ``` Thus, when copying a Rust struct to a Python object, we first allocate `PyCell` on the Python heap and then move `T` into it. Also, `PyCell` provides [RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html)-like methods to ensure Rust's borrow rules. See [the documentation](https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyCell.html) for more. `PyCell` requires that `T` implements `PyClass`. This trait is somewhat complex and derives many traits, but the most important one is `PyTypeInfo` in [`src/type_object.rs`]. `PyTypeInfo` is also implemented for built-in types. In Python, all objects have their types, and types are also objects of `type`. For example, you can see `type({})` shows `dict` and `type(type({}))` shows `type` in Python REPL. `T: PyTypeInfo` implies that `T` has a corresponding type object. ### Protocol methods Python has some built-in special methods called dunder methods, such as `__iter__`. They are called "slots" in the [abstract objects layer](https://docs.python.org/3/c-api/abstract.html) in Python/C API. We provide a way to implement those protocols similarly, by recognizing special names in `#[pymethods]`, with a few new ones for slots that can not be implemented in Python, such as GC support. ## 4. Procedural macros to simplify usage for users. [`pyo3-macros`] provides five proc-macro APIs: `pymodule`, `pyfunction`, `pyclass`, `pymethods`, and `#[derive(FromPyObject)]`. [`pyo3-macros-backend`] has the actual implementations of these APIs. [`src/impl_`] contains `#[doc(hidden)]` functionality used in code generated by these proc-macros, such as parsing function arguments. ## 5. `build.rs` and `pyo3-build-config` PyO3 supports a wide range of OSes, interpreters and use cases. The correct environment must be detected at build time in order to set up relevant conditional compilation correctly. This logic is captured in the [`pyo3-build-config`] crate, which is a `build-dependency` of `pyo3` and `pyo3-macros`, and can also be used by downstream users in the same way. In [`pyo3-build-config`]'s `build.rs` the build environment is detected and inlined into the crate as a "config file". This works in all cases except for cross-compiling, where it is necessary to capture this from the `pyo3` `build.rs` to get some extra environment variables that Cargo doesn't set for build dependencies. The `pyo3` `build.rs` also runs some safety checks such as ensuring the Python version detected is actually supported. Some of the functionality of `pyo3-build-config`: - Find the interpreter for build and detect the Python version. - We have to set some version flags like `#[cfg(Py_3_7)]`. - If the interpreter is PyPy, we set `#[cfg(PyPy)`. - If the `PYO3_CONFIG_FILE` environment variable is set then that file's contents will be used instead of any detected configuration. - If the `PYO3_NO_PYTHON` environment variable is set then the interpreter detection is bypassed entirely and only abi3 extensions can be built. - Check if we are building a Python extension. - If we are building an extension (e.g., Python library installable by `pip`), we don't link `libpython`. Currently we use the `extension-module` feature for this purpose. This may change in the future. See [#1123](https://github.com/PyO3/pyo3/pull/1123). - Cross-compiling configuration - If `TARGET` architecture and `HOST` architecture differ, we can find cross compile information from environment variables (`PYO3_CROSS_LIB_DIR`, `PYO3_CROSS_PYTHON_VERSION` and `PYO3_CROSS_PYTHON_IMPLEMENTATION`) or system files. When cross compiling extension modules it is often possible to make it work without any additional user input. - When an experimental feature `generate-import-lib` is enabled, the `pyo3-ffi` build script can generate `python3.dll` import libraries for Windows targets automatically via an external [`python3-dll-a`] crate. This enables the users to cross compile Python extensions for Windows without having to install any Windows Python libraries. [python/c api]: https://docs.python.org/3/c-api/ [`python3-dll-a`]: https://docs.rs/python3-dll-a/latest/python3_dll_a/ [`pyo3-macros`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros [`pyo3-macros-backend`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros-backend [`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config [`pyo3-ffi`]: https://github.com/PyO3/pyo3/tree/main/pyo3-ffi [`src/class`]: https://github.com/PyO3/pyo3/tree/main/src/class [`src/ffi`]: https://github.com/PyO3/pyo3/tree/main/src/ffi [`src/types`]: https://github.com/PyO3/pyo3/tree/main/src/types [`src/impl_`]: https://github.com/PyO3/pyo3/blob/main/src/impl_ [`src/instance.rs`]: https://github.com/PyO3/pyo3/tree/main/src/instance.rs [`src/pycell.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pycell.rs [`src/pyclass.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass.rs [`src/pyclass_init.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass_init.rs [`src/pyclass_slot.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass_slot.rs [`src/type_object.rs`]: https://github.com/PyO3/pyo3/tree/main/src/type_object.rs [`src/class/methods.rs`]: https://github.com/PyO3/pyo3/tree/main/src/class/methods.rs [`src/class/impl_.rs`]: https://github.com/PyO3/pyo3/tree/main/src/class/impl_.rs [`src/types/any.rs`]: https://github.com/PyO3/pyo3/tree/main/src/types/any.rs [`src/types/mod.rs`]: https://github.com/PyO3/pyo3/tree/main/src/types/mod.rs pyo3/emscripten/0000775000175000017500000000000015105742312013447 5ustar bdrungbdrungpyo3/emscripten/pybuilddir.txt0000644000175000017500000000003315105742312016351 0ustar bdrungbdrungbuild/lib.linux-x86_64-3.11pyo3/emscripten/env.sh0000644000175000017500000000035715105742312014576 0ustar bdrungbdrung#!/bin/bash # Activate emsdk environment. emsdk_env.sh writes a lot to stderr so we suppress # the output. This also prevents it from complaining when emscripten isn't yet # installed. source "$EMSDKDIR/emsdk_env.sh" 2> /dev/null || true pyo3/emscripten/runner.py0000755000175000017500000000023615105742312015334 0ustar bdrungbdrung#!/usr/local/bin/python import pathlib import sys import subprocess p = pathlib.Path(sys.argv[1]) sys.exit(subprocess.call(["node", p.name], cwd=p.parent)) pyo3/emscripten/Makefile0000644000175000017500000000535215105742312015112 0ustar bdrungbdrungCURDIR=$(abspath .) # These three are passed in from nox. BUILDROOT ?= $(CURDIR)/builddir PYMAJORMINORMICRO ?= 3.11.0 EMSCRIPTEN_VERSION=3.1.68 export EMSDKDIR = $(BUILDROOT)/emsdk PLATFORM=wasm32_emscripten SYSCONFIGDATA_NAME=_sysconfigdata__$(PLATFORM) # BASH_ENV tells bash to source emsdk_env.sh on startup. export BASH_ENV := $(CURDIR)/env.sh # Use bash to run each command so that env.sh will be used. SHELL := /bin/bash # Set version variables. version_tuple := $(subst ., ,$(PYMAJORMINORMICRO:v%=%)) PYMAJOR=$(word 1,$(version_tuple)) PYMINOR=$(word 2,$(version_tuple)) PYMICRO=$(word 3,$(version_tuple)) PYVERSION=$(PYMAJORMINORMICRO) PYMAJORMINOR=$(PYMAJOR).$(PYMINOR) PYTHONURL=https://www.python.org/ftp/python/$(PYMAJORMINORMICRO)/Python-$(PYVERSION).tgz PYTHONTARBALL=$(BUILDROOT)/downloads/Python-$(PYVERSION).tgz PYTHONBUILD=$(BUILDROOT)/build/Python-$(PYVERSION) PYTHONLIBDIR=$(BUILDROOT)/install/Python-$(PYVERSION)/lib all: $(PYTHONLIBDIR)/libpython$(PYMAJORMINOR).a $(BUILDROOT)/.exists: mkdir -p $(BUILDROOT) touch $@ # Install emscripten $(EMSDKDIR): $(CURDIR)/emscripten_patches/* $(BUILDROOT)/.exists git clone https://github.com/emscripten-core/emsdk.git --depth 1 --branch $(EMSCRIPTEN_VERSION) $(EMSDKDIR) $(EMSDKDIR)/emsdk install $(EMSCRIPTEN_VERSION) cd $(EMSDKDIR)/upstream/emscripten && cat $(CURDIR)/emscripten_patches/* | patch -p1 $(EMSDKDIR)/emsdk activate $(EMSCRIPTEN_VERSION) $(PYTHONTARBALL): [ -d $(BUILDROOT)/downloads ] || mkdir -p $(BUILDROOT)/downloads wget -q -O $@ $(PYTHONURL) $(PYTHONBUILD)/.patched: $(PYTHONTARBALL) [ -d $(PYTHONBUILD) ] || ( \ mkdir -p $(dir $(PYTHONBUILD));\ tar -C $(dir $(PYTHONBUILD)) -xf $(PYTHONTARBALL) \ ) touch $@ $(PYTHONBUILD)/Makefile: $(PYTHONBUILD)/.patched $(BUILDROOT)/emsdk cd $(PYTHONBUILD) && \ CONFIG_SITE=Tools/wasm/config.site-wasm32-emscripten \ emconfigure ./configure -C \ --host=wasm32-unknown-emscripten \ --build=$(shell $(PYTHONBUILD)/config.guess) \ --with-emscripten-target=browser \ --enable-wasm-dynamic-linking \ --with-build-python=python3.11 $(PYTHONLIBDIR)/libpython$(PYMAJORMINOR).a : $(PYTHONBUILD)/Makefile cd $(PYTHONBUILD) && \ emmake make -j3 libpython$(PYMAJORMINOR).a # Generate sysconfigdata _PYTHON_SYSCONFIGDATA_NAME=$(SYSCONFIGDATA_NAME) _PYTHON_PROJECT_BASE=$(PYTHONBUILD) python3.11 -m sysconfig --generate-posix-vars cp `cat pybuilddir.txt`/$(SYSCONFIGDATA_NAME).py $(PYTHONBUILD)/Lib mkdir -p $(PYTHONLIBDIR) # Copy libexpat.a, libmpdec.a, and libpython3.11.a # In noxfile, we explicitly link libexpat and libmpdec via RUSTFLAGS find $(PYTHONBUILD) -name '*.a' -exec cp {} $(PYTHONLIBDIR) \; # Install Python stdlib cp -r $(PYTHONBUILD)/Lib $(PYTHONLIBDIR)/python$(PYMAJORMINOR) clean: rm -rf $(BUILDROOT) pyo3/emscripten/emscripten_patches/0000775000175000017500000000000015105742312017327 5ustar bdrungbdrungpyo3/emscripten/emscripten_patches/0001-Add-_gxx_personality_v0-stub-to-library.js.patch0000644000175000017500000000202615105742312031065 0ustar bdrungbdrungFrom 4b56f37c3dc9185a235a8314086c4d7a6239b2f8 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 4 Jun 2022 19:19:47 -0700 Subject: [PATCH] Add _gxx_personality_v0 stub to library.js Mitigation for an incompatibility between Rust and Emscripten: https://github.com/rust-lang/rust/issues/85821 https://github.com/emscripten-core/emscripten/issues/17128 --- src/library.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/library.js b/src/library.js index e7bb4c38e..7d01744df 100644 --- a/src/library.js +++ b/src/library.js @@ -403,6 +403,8 @@ mergeInto(LibraryManager.library, { abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); }, + __gxx_personality_v0: function() {}, + // ========================================================================== // time.h // ========================================================================== -- 2.25.1 pyo3/Code-of-Conduct.md0000644000175000017500000000640415105742312014473 0ustar bdrungbdrung# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq pyo3/README.md0000644000175000017500000004370415105742312012563 0ustar bdrungbdrung# PyO3 [![actions status](https://img.shields.io/github/actions/workflow/status/PyO3/pyo3/ci.yml?branch=main&logo=github&style=)](https://github.com/PyO3/pyo3/actions) [![benchmark](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/PyO3/pyo3) [![codecov](https://img.shields.io/codecov/c/gh/PyO3/pyo3?logo=codecov)](https://codecov.io/gh/PyO3/pyo3) [![crates.io](https://img.shields.io/crates/v/pyo3?logo=rust)](https://crates.io/crates/pyo3) [![minimum rustc 1.63](https://img.shields.io/badge/rustc-1.63+-blue?logo=rust)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![discord server](https://img.shields.io/discord/1209263839632424990?logo=discord)](https://discord.gg/33kcChzH7f) [![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green?logo=github)](https://github.com/PyO3/pyo3/blob/main/Contributing.md) [Rust](https://www.rust-lang.org/) bindings for [Python](https://www.python.org/), including tools for creating native Python extension modules. Running and interacting with Python code from a Rust binary is also supported. - User Guide: [stable](https://pyo3.rs) | [main](https://pyo3.rs/main) - API Documentation: [stable](https://docs.rs/pyo3/) | [main](https://pyo3.rs/main/doc) ## Usage Requires Rust 1.63 or greater. PyO3 supports the following Python distributions: - CPython 3.7 or greater - PyPy 7.3 (Python 3.9+) - GraalPy 24.2 or greater (Python 3.11+) You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn. ### Using Rust from Python PyO3 can be used to generate a native Python module. The easiest way to try this out for the first time is to use [`maturin`](https://github.com/PyO3/maturin). `maturin` is a tool for building and publishing Rust-based Python packages with minimal configuration. The following steps install `maturin`, use it to generate and build a new Python package, and then launch Python to import and execute a function from the package. First, follow the commands below to create a new directory containing a new Python `virtualenv`, and install `maturin` into the virtualenv using Python's package manager, `pip`: ```bash # (replace string_sum with the desired package name) $ mkdir string_sum $ cd string_sum $ python -m venv .env $ source .env/bin/activate $ pip install maturin ``` Still inside this `string_sum` directory, now run `maturin init`. This will generate the new package source. When given the choice of bindings to use, select pyo3 bindings: ```bash $ maturin init ✔ 🤷 What kind of bindings to use? · pyo3 ✨ Done! New project created string_sum ``` The most important files generated by this command are `Cargo.toml` and `lib.rs`, which will look roughly like the following: **`Cargo.toml`** ```toml [package] name = "string_sum" version = "0.1.0" edition = "2021" [lib] # The name of the native library. This is the name which will be used in Python to import the # library (i.e. `import string_sum`). If you change this, you must also change the name of the # `#[pymodule]` in `src/lib.rs`. name = "string_sum" # "cdylib" is necessary to produce a shared library for Python to import from. # # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: # crate-type = ["cdylib", "rlib"] crate-type = ["cdylib"] [dependencies] pyo3 = { version = "0.25.1", features = ["extension-module"] } ``` **`src/lib.rs`** ```rust use pyo3::prelude::*; /// Formats the sum of two numbers as string. #[pyfunction] fn sum_as_string(a: usize, b: usize) -> PyResult { Ok((a + b).to_string()) } /// A Python module implemented in Rust. The name of this function must match /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to /// import the module. #[pymodule] fn string_sum(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(sum_as_string, m)?)?; Ok(()) } ``` Finally, run `maturin develop`. This will build the package and install it into the Python virtualenv previously created and activated. The package is then ready to be used from `python`: ```bash $ maturin develop # lots of progress output as maturin runs the compilation... $ python >>> import string_sum >>> string_sum.sum_as_string(5, 20) '25' ``` To make changes to the package, just edit the Rust source code and then re-run `maturin develop` to recompile. To run this all as a single copy-and-paste, use the bash script below (replace `string_sum` in the first command with the desired package name): ```bash mkdir string_sum && cd "$_" python -m venv .env source .env/bin/activate pip install maturin maturin init --bindings pyo3 maturin develop ``` If you want to be able to run `cargo test` or use this project in a Cargo workspace and are running into linker issues, there are some workarounds in [the FAQ](https://pyo3.rs/latest/faq.html#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror). As well as with `maturin`, it is possible to build using [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](https://pyo3.rs/latest/building-and-distribution.html#manual-builds). Both offer more flexibility than `maturin` but require more configuration to get started. ### Using Python from Rust To embed Python into a Rust binary, you need to ensure that your Python installation contains a shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give some example code which runs an embedded Python interpreter. To install the Python shared library on Ubuntu: ```bash sudo apt install python3-dev ``` To install the Python shared library on RPM based distributions (e.g. Fedora, Red Hat, SuSE), install the `python3-devel` package. Start a new project with `cargo new` and add `pyo3` to the `Cargo.toml` like this: ```toml [dependencies.pyo3] version = "0.25.1" features = ["auto-initialize"] ``` Example program displaying the value of `sys.version` and the current user name: ```rust use pyo3::prelude::*; use pyo3::types::IntoPyDict; use pyo3::ffi::c_str; fn main() -> PyResult<()> { Python::with_gil(|py| { let sys = py.import("sys")?; let version: String = sys.getattr("version")?.extract()?; let locals = [("os", py.import("os")?)].into_py_dict(py)?; let code = c_str!("os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"); let user: String = py.eval(code, None, Some(&locals))?.extract()?; println!("Hello {}, I'm Python {}", user, version); Ok(()) }) } ``` The guide has [a section](https://pyo3.rs/latest/python-from-rust.html) with lots of examples about this topic. ## Tools and libraries - [maturin](https://github.com/PyO3/maturin) _Build and publish crates with pyo3, rust-cpython or cffi bindings as well as rust binaries as python packages_ - [setuptools-rust](https://github.com/PyO3/setuptools-rust) _Setuptools plugin for Rust support_. - [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://docs.rs/pyo3/*/pyo3/types/struct.PyDict.html)_ - [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_ - [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_ - [pyo3-log](https://github.com/vorner/pyo3-log) _Bridge from Rust to Python logging_ - [pythonize](https://github.com/davidhewitt/pythonize) _Serde serializer for converting Rust objects to JSON-compatible Python objects_ - [pyo3-async-runtimes](https://github.com/PyO3/pyo3-async-runtimes) _Utilities for interoperability with Python's Asyncio library and Rust's async runtimes._ - [rustimport](https://github.com/mityax/rustimport) _Directly import Rust files or crates from Python, without manual compilation step. Provides pyo3 integration by default and generates pyo3 binding code automatically._ - [pyo3-arrow](https://crates.io/crates/pyo3-arrow) _Lightweight [Apache Arrow](https://arrow.apache.org/) integration for pyo3._ - [pyo3-bytes](https://crates.io/crates/pyo3-bytes) _Integration between [`bytes`](https://crates.io/crates/bytes) and pyo3._ - [pyo3-object_store](https://github.com/developmentseed/obstore/tree/main/pyo3-object_store) _Integration between [`object_store`](https://docs.rs/object_store) and [`pyo3`](https://github.com/PyO3/pyo3)._ ## Examples - [arro3](https://github.com/kylebarron/arro3) _A minimal Python library for Apache Arrow, connecting to the Rust arrow crate._ - [arro3-compute](https://github.com/kylebarron/arro3/tree/main/arro3-compute) _`arro3-compute`_ - [arro3-core](https://github.com/kylebarron/arro3/tree/main/arro3-core) _`arro3-core`_ - [arro3-io](https://github.com/kylebarron/arro3/tree/main/arro3-io) _`arro3-io`_ - [bed-reader](https://github.com/fastlmm/bed-reader) _Read and write the PLINK BED format, simply and efficiently._ - Shows Rayon/ndarray::parallel (including capturing errors, controlling thread num), Python types to Rust generics, Github Actions - [blake3-py](https://github.com/oconnor663/blake3-py) _Python bindings for the [BLAKE3](https://github.com/BLAKE3-team/BLAKE3) cryptographic hash function._ - Parallelized [builds](https://github.com/oconnor663/blake3-py/blob/master/.github/workflows/dists.yml) on GitHub Actions for MacOS, Linux, Windows, including free-threaded 3.13t wheels. - [cellular_raza](https://cellular-raza.com) _A cellular agent-based simulation framework for building complex models from a clean slate._ - [connector-x](https://github.com/sfu-db/connector-x/tree/main/connectorx-python) _Fastest library to load data from DB to DataFrames in Rust and Python._ - [cryptography](https://github.com/pyca/cryptography/tree/main/src/rust) _Python cryptography library with some functionality in Rust._ - [css-inline](https://github.com/Stranger6667/css-inline/tree/master/bindings/python) _CSS inlining for Python implemented in Rust._ - [datafusion-python](https://github.com/apache/arrow-datafusion-python) _A Python library that binds to Apache Arrow in-memory query engine DataFusion._ - [deltalake-python](https://github.com/delta-io/delta-rs/tree/main/python) _Native Delta Lake Python binding based on delta-rs with Pandas integration._ - [fastbloom](https://github.com/yankun1992/fastbloom) _A fast [bloom filter](https://github.com/yankun1992/fastbloom#BloomFilter) | [counting bloom filter](https://github.com/yankun1992/fastbloom#countingbloomfilter) implemented by Rust for Rust and Python!_ - [fastuuid](https://github.com/thedrow/fastuuid/) _Python bindings to Rust's UUID library._ - [feos](https://github.com/feos-org/feos) _Lightning fast thermodynamic modeling in Rust with fully developed Python interface._ - [forust](https://github.com/jinlow/forust) _A lightweight gradient boosted decision tree library written in Rust._ - [geo-index](https://github.com/kylebarron/geo-index) _A Rust crate and [Python library](https://github.com/kylebarron/geo-index/tree/main/python) for packed, immutable, zero-copy spatial indexes._ - [granian](https://github.com/emmett-framework/granian) _A Rust HTTP server for Python applications._ - [haem](https://github.com/BooleanCat/haem) _A Python library for working on Bioinformatics problems._ - [html2text-rs](https://github.com/deedy5/html2text_rs) _Python library for converting HTML to markup or plain text._ - [html-py-ever](https://github.com/PyO3/setuptools-rust/tree/main/examples/html-py-ever) _Using [html5ever](https://github.com/servo/html5ever) through [kuchiki](https://github.com/kuchiki-rs/kuchiki) to speed up html parsing and css-selecting._ - [inline-python](https://github.com/m-ou-se/inline-python) _Inline Python code directly in your Rust code._ - [johnnycanencrypt](https://github.com/kushaldas/johnnycanencrypt) OpenPGP library with Yubikey support. - [jsonschema](https://github.com/Stranger6667/jsonschema/tree/master/crates/jsonschema-py) _A high-performance JSON Schema validator for Python._ - [mocpy](https://github.com/cds-astro/mocpy) _Astronomical Python library offering data structures for describing any arbitrary coverage regions on the unit sphere._ - [obstore](https://github.com/developmentseed/obstore) _The simplest, highest-throughput Python interface to Amazon S3, Google Cloud Storage, Azure Storage, & other S3-compliant APIs, powered by Rust._ - [opendal](https://github.com/apache/opendal/tree/main/bindings/python) _A data access layer that allows users to easily and efficiently retrieve data from various storage services in a unified way._ - [orjson](https://github.com/ijl/orjson) _Fast Python JSON library._ - [ormsgpack](https://github.com/aviramha/ormsgpack) _Fast Python msgpack library._ - [polars](https://github.com/pola-rs/polars) _Fast multi-threaded DataFrame library in Rust | Python | Node.js._ - [pycrdt](https://github.com/jupyter-server/pycrdt) _Python bindings for the Rust CRDT implementation [Yrs](https://github.com/y-crdt/y-crdt)._ - [pydantic-core](https://github.com/pydantic/pydantic-core) _Core validation logic for pydantic written in Rust._ - [primp](https://github.com/deedy5/primp) _The fastest python HTTP client that can impersonate web browsers by mimicking their headers and TLS/JA3/JA4/HTTP2 fingerprints._ - [rateslib](https://github.com/attack68/rateslib) _A fixed income library for Python using Rust extensions._ - [river](https://github.com/online-ml/river) _Online machine learning in python, the computationally heavy statistics algorithms are implemented in Rust._ - [robyn](https://github.com/sparckles/Robyn) A Super Fast Async Python Web Framework with a Rust runtime. - [rust-python-coverage](https://github.com/cjermain/rust-python-coverage) _Example PyO3 project with automated test coverage for Rust and Python._ - [rnet](https://github.com/0x676e67/rnet) Asynchronous Python HTTP Client with Black Magic - [sail](https://github.com/lakehq/sail) _Unifying stream, batch, and AI workloads with Apache Spark compatibility._ - [tiktoken](https://github.com/openai/tiktoken) _A fast BPE tokeniser for use with OpenAI's models._ - [tokenizers](https://github.com/huggingface/tokenizers/tree/main/bindings/python) _Python bindings to the Hugging Face tokenizers (NLP) written in Rust._ - [tzfpy](http://github.com/ringsaturn/tzfpy) _A fast package to convert longitude/latitude to timezone name._ - [utiles](https://github.com/jessekrubin/utiles) _Fast Python web-map tile utilities_ ## Articles and other media - [(Video) PyO3: From Python to Rust and Back Again](https://www.youtube.com/watch?v=UmL_CA-v3O8) - Jul 3, 2024 - [Parsing Python ASTs 20x Faster with Rust](https://www.gauge.sh/blog/parsing-python-asts-20x-faster-with-rust) - Jun 17, 2024 - [(Video) How Python Harnesses Rust through PyO3](https://www.youtube.com/watch?v=UkZ_m3Wj2hA) - May 18, 2024 - [(Video) Combining Rust and Python: The Best of Both Worlds?](https://www.youtube.com/watch?v=lyG6AKzu4ew) - Mar 1, 2024 - [(Video) Extending Python with Rust using PyO3](https://www.youtube.com/watch?v=T45ZEmSR1-s) - Dec 16, 2023 - [A Week of PyO3 + rust-numpy (How to Speed Up Your Data Pipeline X Times)](https://terencezl.github.io/blog/2023/06/06/a-week-of-pyo3-rust-numpy/) - Jun 6, 2023 - [(Podcast) PyO3 with David Hewitt](https://rustacean-station.org/episode/david-hewitt/) - May 19, 2023 - [Making Python 100x faster with less than 100 lines of Rust](https://ohadravid.github.io/posts/2023-03-rusty-python/) - Mar 28, 2023 - [How Pydantic V2 leverages Rust's Superpowers](https://fosdem.org/2023/schedule/event/rust_how_pydantic_v2_leverages_rusts_superpowers/) - Feb 4, 2023 - [How we extended the River stats module with Rust using PyO3](https://boring-guy.sh/posts/river-rust/) - Dec 23, 2022 - [Nine Rules for Writing Python Extensions in Rust](https://towardsdatascience.com/nine-rules-for-writing-python-extensions-in-rust-d35ea3a4ec29?sk=f8d808d5f414154fdb811e4137011437) - Dec 31, 2021 - [Calling Rust from Python using PyO3](https://saidvandeklundert.net/learn/2021-11-18-calling-rust-from-python-using-pyo3/) - Nov 18, 2021 - [davidhewitt's 2021 talk at Rust Manchester meetup](https://www.youtube.com/watch?v=-XyWG_klSAw&t=320s) - Aug 19, 2021 - [Incrementally porting a small Python project to Rust](https://blog.waleedkhan.name/port-python-to-rust/) - Apr 29, 2021 - [Vortexa - Integrating Rust into Python](https://www.vortexa.com/insight/integrating-rust-into-python) - Apr 12, 2021 - [Writing and publishing a Python module in Rust](https://blog.yossarian.net/2020/08/02/Writing-and-publishing-a-python-module-in-rust) - Aug 2, 2020 ## Contributing Everyone is welcomed to contribute to PyO3! There are many ways to support the project, such as: - help PyO3 users with issues on GitHub and [Discord](https://discord.gg/33kcChzH7f) - improve documentation - write features and bugfixes - publish blogs and examples of how to use PyO3 Our [contributing notes](https://github.com/PyO3/pyo3/blob/main/Contributing.md) and [architecture guide](https://github.com/PyO3/pyo3/blob/main/Architecture.md) have more resources if you wish to volunteer time for PyO3 and are searching where to start. If you don't have time to contribute yourself but still wish to support the project's future success, some of our maintainers have GitHub sponsorship pages: - [davidhewitt](https://github.com/sponsors/davidhewitt) - [messense](https://github.com/sponsors/messense) ## License PyO3 is licensed under the [Apache-2.0 license](LICENSE-APACHE) or the [MIT license](LICENSE-MIT), at your option. Python is licensed under the [Python License](https://docs.python.org/3/license.html). Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in PyO3 by you, as defined in the Apache License, shall be dual-licensed as above, without any additional terms or conditions. Deploys by Netlify pyo3/CHANGELOG.md0000644000175000017500000052570315105742312013121 0ustar bdrungbdrung# Changelog All notable changes to this project will be documented in this file. For help with updating to new PyO3 versions, please see the [migration guide](https://pyo3.rs/latest/migration.html). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). To see unreleased changes, please see the [CHANGELOG on the main branch guide](https://pyo3.rs/main/changelog.html). ## [0.25.1] - 2025-06-12 ### Packaging - Add support for Windows on ARM64. [#5145](https://github.com/PyO3/pyo3/pull/5145) - Add `chrono-local` feature for optional conversions for chrono's `Local` timezone & `DateTime` instances. [#5174](https://github.com/PyO3/pyo3/pull/5174) ### Added - Add FFI definition `PyBytes_AS_STRING`. [#5121](https://github.com/PyO3/pyo3/pull/5121) - Add support for module associated consts introspection. [#5150](https://github.com/PyO3/pyo3/pull/5150) ### Changed - Enable "vectorcall" FFI definitions on GraalPy. [#5121](https://github.com/PyO3/pyo3/pull/5121) - Use `Py_Is` function on GraalPy [#5121](https://github.com/PyO3/pyo3/pull/5121) ### Fixed - Report a better compile error for `async` declarations when not using `experimental-async` feature. [#5156](https://github.com/PyO3/pyo3/pull/5156) - Fix implementation of `FromPyObject` for `uuid::Uuid` on big-endian architectures. [#5161](https://github.com/PyO3/pyo3/pull/5161) - Fix segmentation faults on 32-bit x86 with Python 3.14. [#5180](https://github.com/PyO3/pyo3/pull/5180) ## [0.25.0] - 2025-05-14 ### Packaging - Support Python 3.14.0b1. [#4811](https://github.com/PyO3/pyo3/pull/4811) - Bump supported GraalPy version to 24.2. [#5116](https://github.com/PyO3/pyo3/pull/5116) - Add optional `bigdecimal` dependency to add conversions for `bigdecimal::BigDecimal`. [#5011](https://github.com/PyO3/pyo3/pull/5011) - Add optional `time` dependency to add conversions for `time` types. [#5057](https://github.com/PyO3/pyo3/pull/5057) - Remove `cfg-if` dependency. [#5110](https://github.com/PyO3/pyo3/pull/5110) - Add optional `ordered_float` dependency to add conversions for `ordered_float::NotNan` and `ordered_float::OrderedFloat`. [#5114](https://github.com/PyO3/pyo3/pull/5114) ### Added - Add initial type stub generation to the `experimental-inspect` feature. [#3977](https://github.com/PyO3/pyo3/pull/3977) - Add `#[pyclass(generic)]` option to support runtime generic typing. [#4926](https://github.com/PyO3/pyo3/pull/4926) - Implement `OnceExt` & `MutexExt` for `parking_lot` & `lock_api`. Use the new extension traits by enabling the `arc_lock`, `lock_api`, or `parking_lot` cargo features. [#5044](https://github.com/PyO3/pyo3/pull/5044) - Implement `From`/`Into` for `Borrowed` -> `Py`. [#5054](https://github.com/PyO3/pyo3/pull/5054) - Add `PyTzInfo` constructors. [#5055](https://github.com/PyO3/pyo3/pull/5055) - Add FFI definition `PY_INVALID_STACK_EFFECT`. [#5064](https://github.com/PyO3/pyo3/pull/5064) - Implement `AsRef>` for `Py`, `Bound` and `Borrowed`. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Add FFI definition `PyModule_Add` and `compat::PyModule_Add`. [#5085](https://github.com/PyO3/pyo3/pull/5085) - Add FFI definitions `Py_HashBuffer`, `Py_HashPointer`, and `PyObject_GenericHash`. [#5086](https://github.com/PyO3/pyo3/pull/5086) - Support `#[pymodule_export]` on `const` items in declarative modules. [#5096](https://github.com/PyO3/pyo3/pull/5096) - Add `#[pyclass(immutable_type)]` option (on Python 3.14+ with `abi3`, or 3.10+ otherwise) for immutable type objects. [#5101](https://github.com/PyO3/pyo3/pull/5101) - Support `#[pyo3(rename_all)]` support on `#[derive(IntoPyObject)]`. [#5112](https://github.com/PyO3/pyo3/pull/5112) - Add `PyRange` wrapper. [#5117](https://github.com/PyO3/pyo3/pull/5117) ### Changed - Enable use of `datetime` types with `abi3` feature enabled. [#4970](https://github.com/PyO3/pyo3/pull/4970) - Deprecate `timezone_utc` in favor of `PyTzInfo::utc`. [#5055](https://github.com/PyO3/pyo3/pull/5055) - Reduce visibility of some CPython implementation details: [#5064](https://github.com/PyO3/pyo3/pull/5064) - The FFI definition `PyCodeObject` is now an opaque struct on all Python versions. - The FFI definition `PyFutureFeatures` is now only defined up until Python 3.10 (it was present in CPython headers but unused in 3.11 and 3.12). - Change `PyAnyMethods::is` to take `other: &Bound`. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Change `Py::is` to take `other: &Py`. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Change `PyVisit::call` to take `T: Into>>`. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Expose `PyDateTime_DATE_GET_TZINFO` and `PyDateTime_TIME_GET_TZINFO` on PyPy 3.10 and later. [#5079](https://github.com/PyO3/pyo3/pull/5079) - Add `#[track_caller]` to `with_gil` and `with_gil_unchecked`. [#5109](https://github.com/PyO3/pyo3/pull/5109) - Use `std::thread::park()` instead of `libc::pause()` or `sleep(9999999)`. [#5115](https://github.com/PyO3/pyo3/pull/5115) ### Removed - Remove all functionality deprecated in PyO3 0.23. [#4982](https://github.com/PyO3/pyo3/pull/4982) - Remove deprecated `IntoPy` and `ToPyObject` traits. [#5010](https://github.com/PyO3/pyo3/pull/5010) - Remove private types from `pyo3-ffi` (i.e. starting with `_Py`) which are not referenced by public APIs: `_PyLocalMonitors`, `_Py_GlobalMonitors`, `_PyCoCached`, `_PyCoLineInstrumentationData`, `_PyCoMonitoringData`, `_PyCompilerSrcLocation`, `_PyErr_StackItem`. [#5064](https://github.com/PyO3/pyo3/pull/5064) - Remove FFI definition `PyCode_GetNumFree` (PyO3 cannot support it due to knowledge of the code object). [#5064](https://github.com/PyO3/pyo3/pull/5064) - Remove `AsPyPointer` trait. [#5071](https://github.com/PyO3/pyo3/pull/5071) - Remove support for the deprecated string form of `from_py_with`. [#5097](https://github.com/PyO3/pyo3/pull/5097) - Remove FFI definitions of private static variables: `_PyMethodWrapper_Type`, `_PyCoroWrapper_Type`, `_PyImport_FrozenBootstrap`, `_PyImport_FrozenStdlib`, `_PyImport_FrozenTest`, `_PyManagedBuffer_Type`, `_PySet_Dummy`, `_PyWeakref_ProxyType`, and `_PyWeakref_CallableProxyType`. [#5105](https://github.com/PyO3/pyo3/pull/5105) - Remove FFI definitions `PyASCIIObjectState`, `PyUnicode_IS_ASCII`, `PyUnicode_IS_COMPACT`, and `PyUnicode_IS_COMPACT_ASCII` on Python 3.14 and newer. [#5133](https://github.com/PyO3/pyo3/pull/5133) ### Fixed - Correctly pick up the shared state for conda-based Python installation when reading information from sysconfigdata. [#5037](https://github.com/PyO3/pyo3/pull/5037) - Fix compile failure with `#[derive(IntoPyObject, FromPyObject)]` when using `#[pyo3()]` options recognised by only one of the two derives. [#5070](https://github.com/PyO3/pyo3/pull/5070) - Fix various compile errors from missing FFI definitions using certain feature combinations on PyPy and GraalPy. [#5091](https://github.com/PyO3/pyo3/pull/5091) - Fallback on `backports.zoneinfo` for python <3.9 when converting timezones into python. [#5120](https://github.com/PyO3/pyo3/pull/5120) ## [0.24.2] - 2025-04-21 ### Fixed - Fix `unused_imports` lint of `#[pyfunction]` and `#[pymethods]` expanded in `macro_rules` context. [#5030](https://github.com/PyO3/pyo3/pull/5030) - Fix size of `PyCodeObject::_co_instrumentation_version` ffi struct member on Python 3.13 for systems where `uintptr_t` is not 64 bits. [#5048](https://github.com/PyO3/pyo3/pull/5048) - Fix struct-type complex enum variant fields incorrectly exposing raw identifiers as `r#ident` in Python bindings. [#5050](https://github.com/PyO3/pyo3/pull/5050) ## [0.24.1] - 2025-03-31 ### Added - Add `abi3-py313` feature. [#4969](https://github.com/PyO3/pyo3/pull/4969) - Add `PyAnyMethods::getattr_opt`. [#4978](https://github.com/PyO3/pyo3/pull/4978) - Add `PyInt::new` constructor for all supported number types (i32, u32, i64, u64, isize, usize). [#4984](https://github.com/PyO3/pyo3/pull/4984) - Add `pyo3::sync::with_critical_section2`. [#4992](https://github.com/PyO3/pyo3/pull/4992) - Implement `PyCallArgs` for `Borrowed<'_, 'py, PyTuple>`, `&Bound<'py, PyTuple>`, and `&Py`. [#5013](https://github.com/PyO3/pyo3/pull/5013) ### Fixed - Fix `is_type_of` for native types not using same specialized check as `is_type_of_bound`. [#4981](https://github.com/PyO3/pyo3/pull/4981) - Fix `Probe` class naming issue with `#[pymethods]`. [#4988](https://github.com/PyO3/pyo3/pull/4988) - Fix compile failure with required `#[pyfunction]` arguments taking `Option<&str>` and `Option<&T>` (for `#[pyclass]` types). [#5002](https://github.com/PyO3/pyo3/pull/5002) - Fix `PyString::from_object` causing of bounds reads whith `encoding` and `errors` parameters which are not nul-terminated. [#5008](https://github.com/PyO3/pyo3/pull/5008) - Fix compile error when additional options follow after `crate` for `#[pyfunction]`. [#5015](https://github.com/PyO3/pyo3/pull/5015) ## [0.24.0] - 2025-03-09 ### Packaging - Add supported CPython/PyPy versions to cargo package metadata. [#4756](https://github.com/PyO3/pyo3/pull/4756) - Bump `target-lexicon` dependency to 0.13. [#4822](https://github.com/PyO3/pyo3/pull/4822) - Add optional `jiff` dependency to add conversions for `jiff` datetime types. [#4823](https://github.com/PyO3/pyo3/pull/4823) - Add optional `uuid` dependency to add conversions for `uuid::Uuid`. [#4864](https://github.com/PyO3/pyo3/pull/4864) - Bump minimum supported `inventory` version to 0.3.5. [#4954](https://github.com/PyO3/pyo3/pull/4954) ### Added - Add `PyIterator::send` method to allow sending values into a python generator. [#4746](https://github.com/PyO3/pyo3/pull/4746) - Add `PyCallArgs` trait for passing arguments into the Python calling protocol. This enabled using a faster calling convention for certain types, improving performance. [#4768](https://github.com/PyO3/pyo3/pull/4768) - Add `#[pyo3(default = ...']` option for `#[derive(FromPyObject)]` to set a default value for extracted fields of named structs. [#4829](https://github.com/PyO3/pyo3/pull/4829) - Add `#[pyo3(into_py_with = ...)]` option for `#[derive(IntoPyObject, IntoPyObjectRef)]`. [#4850](https://github.com/PyO3/pyo3/pull/4850) - Add FFI definitions `PyThreadState_GetFrame` and `PyFrame_GetBack`. [#4866](https://github.com/PyO3/pyo3/pull/4866) - Optimize `last` for `BoundListIterator`, `BoundTupleIterator` and `BorrowedTupleIterator`. [#4878](https://github.com/PyO3/pyo3/pull/4878) - Optimize `Iterator::count()` for `PyDict`, `PyList`, `PyTuple` & `PySet`. [#4878](https://github.com/PyO3/pyo3/pull/4878) - Optimize `nth`, `nth_back`, `advance_by` and `advance_back_by` for `BoundTupleIterator` [#4897](https://github.com/PyO3/pyo3/pull/4897) - Add support for `types.GenericAlias` as `pyo3::types::PyGenericAlias`. [#4917](https://github.com/PyO3/pyo3/pull/4917) - Add `MutextExt` trait to help avoid deadlocks with the GIL while locking a `std::sync::Mutex`. [#4934](https://github.com/PyO3/pyo3/pull/4934) - Add `#[pyo3(rename_all = "...")]` option for `#[derive(FromPyObject)]`. [#4941](https://github.com/PyO3/pyo3/pull/4941) ### Changed - Optimize `nth`, `nth_back`, `advance_by` and `advance_back_by` for `BoundListIterator`. [#4810](https://github.com/PyO3/pyo3/pull/4810) - Use `DerefToPyAny` in blanket implementations of `From>` and `From>` for `PyObject`. [#4593](https://github.com/PyO3/pyo3/pull/4593) - Map `io::ErrorKind::IsADirectory`/`NotADirectory` to the corresponding Python exception on Rust 1.83+. [#4747](https://github.com/PyO3/pyo3/pull/4747) - `PyAnyMethods::call` and friends now require `PyCallArgs` for their positional arguments. [#4768](https://github.com/PyO3/pyo3/pull/4768) - Expose FFI definitions for `PyObject_Vectorcall(Method)` on the stable abi on 3.12+. [#4853](https://github.com/PyO3/pyo3/pull/4853) - `#[pyo3(from_py_with = ...)]` now take a path rather than a string literal [#4860](https://github.com/PyO3/pyo3/pull/4860) - Format Python traceback in impl Debug for PyErr. [#4900](https://github.com/PyO3/pyo3/pull/4900) - Convert `PathBuf` & `Path` into Python `pathlib.Path` instead of `PyString`. [#4925](https://github.com/PyO3/pyo3/pull/4925) - Relax parsing of exotic Python versions. [#4949](https://github.com/PyO3/pyo3/pull/4949) - PyO3 threads now hang instead of `pthread_exit` trying to acquire the GIL when the interpreter is shutting down. This mimics the [Python 3.14](https://github.com/python/cpython/issues/87135) behavior and avoids undefined behavior and crashes. [#4874](https://github.com/PyO3/pyo3/pull/4874) ### Removed - Remove implementations of `Deref` for `PyAny` and other "native" types. [#4593](https://github.com/PyO3/pyo3/pull/4593) - Remove implicit default of trailing optional arguments (see #2935) [#4729](https://github.com/PyO3/pyo3/pull/4729) - Remove the deprecated implicit eq fallback for simple enums. [#4730](https://github.com/PyO3/pyo3/pull/4730) ### Fixed - Correct FFI definition of `PyIter_Send` to return a `PySendResult`. [#4746](https://github.com/PyO3/pyo3/pull/4746) - Fix a thread safety issue in the runtime borrow checker used by mutable pyclass instances on the free-threaded build. [#4948](https://github.com/PyO3/pyo3/pull/4948) ## [0.23.5] - 2025-02-22 ### Packaging - Add support for PyPy3.11 [#4760](https://github.com/PyO3/pyo3/pull/4760) ### Fixed - Fix thread-unsafe implementation of freelist pyclasses on the free-threaded build. [#4902](https://github.com/PyO3/pyo3/pull/4902) - Re-enable a workaround for situations where CPython incorrectly does not add `__builtins__` to `__globals__` in code executed by `Python::py_run` (was removed in PyO3 0.23.0). [#4921](https://github.com/PyO3/pyo3/pull/4921) ## [0.23.4] - 2025-01-10 ### Added - Add `PyList::locked_for_each`, which uses a critical section to lock the list on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789) - Add `pyo3_build_config::add_python_framework_link_args` build script API to set rpath when using macOS system Python. [#4833](https://github.com/PyO3/pyo3/pull/4833) ### Changed - Use `datetime.fold` to distinguish ambiguous datetimes when converting to and from `chrono::DateTime` (rather than erroring). [#4791](https://github.com/PyO3/pyo3/pull/4791) - Optimize PyList iteration on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789) ### Fixed - Fix unnecessary internal `py.allow_threads` GIL-switch when attempting to access contents of a `PyErr` which originated from Python (could lead to unintended deadlocks). [#4766](https://github.com/PyO3/pyo3/pull/4766) - Fix thread-unsafe access of dict internals in `BoundDictIterator` on the free-threaded build. [#4788](https://github.com/PyO3/pyo3/pull/4788) * Fix unnecessary critical sections in `BoundDictIterator` on the free-threaded build. [#4788](https://github.com/PyO3/pyo3/pull/4788) - Fix time-of-check to time-of-use issues with list iteration on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789) - Fix `chrono::DateTime` to-Python conversion when `Tz` is `chrono_tz::Tz`. [#4790](https://github.com/PyO3/pyo3/pull/4790) - Fix `#[pyclass]` not being able to be named `Probe`. [#4794](https://github.com/PyO3/pyo3/pull/4794) - Fix not treating cross-compilation from x64 to aarch64 on Windows as a cross-compile. [#4800](https://github.com/PyO3/pyo3/pull/4800) - Fix missing struct fields on GraalPy when subclassing builtin classes. [#4802](https://github.com/PyO3/pyo3/pull/4802) - Fix generating import lib for PyPy when `abi3` feature is enabled. [#4806](https://github.com/PyO3/pyo3/pull/4806) - Fix generating import lib for python3.13t when `abi3` feature is enabled. [#4808](https://github.com/PyO3/pyo3/pull/4808) - Fix compile failure for raw identifiers like `r#box` in `derive(FromPyObject)`. [#4814](https://github.com/PyO3/pyo3/pull/4814) - Fix compile failure for `#[pyclass]` enum variants with more than 12 fields. [#4832](https://github.com/PyO3/pyo3/pull/4832) ## [0.23.3] - 2024-12-03 ### Packaging - Bump optional `python3-dll-a` dependency to 0.2.11. [#4749](https://github.com/PyO3/pyo3/pull/4749) ### Fixed - Fix unresolved symbol link failures on Windows when compiling for Python 3.13t with `abi3` features enabled. [#4733](https://github.com/PyO3/pyo3/pull/4733) - Fix unresolved symbol link failures on Windows when compiling for Python 3.13t using the `generate-import-lib` feature. [#4749](https://github.com/PyO3/pyo3/pull/4749) - Fix compile-time regression in PyO3 0.23.0 where changing `PYO3_CONFIG_FILE` would not reconfigure PyO3 for the new interpreter. [#4758](https://github.com/PyO3/pyo3/pull/4758) ## [0.23.2] - 2024-11-25 ### Added - Add `IntoPyObjectExt` trait. [#4708](https://github.com/PyO3/pyo3/pull/4708) ### Fixed - Fix compile failures when building for free-threaded Python when the `abi3` or `abi3-pyxx` features are enabled. [#4719](https://github.com/PyO3/pyo3/pull/4719) - Fix `ambiguous_associated_items` lint error in `#[pyclass]` and `#[derive(IntoPyObject)]` macros. [#4725](https://github.com/PyO3/pyo3/pull/4725) ## [0.23.1] - 2024-11-16 Re-release of 0.23.0 with fixes to docs.rs build. ## [0.23.0] - 2024-11-15 ### Packaging - Drop support for PyPy 3.7 and 3.8. [#4582](https://github.com/PyO3/pyo3/pull/4582) - Extend range of supported versions of `hashbrown` optional dependency to include version 0.15. [#4604](https://github.com/PyO3/pyo3/pull/4604) - Bump minimum version of `eyre` optional dependency to 0.6.8. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Bump minimum version of `hashbrown` optional dependency to 0.14.5. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Bump minimum version of `indexmap` optional dependency to 2.5.0. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Bump minimum version of `num-complex` optional dependency to 0.4.6. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Bump minimum version of `chrono-tz` optional dependency to 0.10. [#4617](https://github.com/PyO3/pyo3/pull/4617) - Support free-threaded Python 3.13t. [#4588](https://github.com/PyO3/pyo3/pull/4588) ### Added - Add `IntoPyObject` (fallible) conversion trait to convert from Rust to Python values. [#4060](https://github.com/PyO3/pyo3/pull/4060) - Add `#[pyclass(str="")]` option to generate `__str__` based on a `Display` implementation or format string. [#4233](https://github.com/PyO3/pyo3/pull/4233) - Implement `PartialEq` for `Bound<'py, PyInt>` with `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128` and `isize`. [#4317](https://github.com/PyO3/pyo3/pull/4317) - Implement `PartialEq` and `PartialEq` for `Bound<'py, PyFloat>`. [#4348](https://github.com/PyO3/pyo3/pull/4348) - Add `as_super` and `into_super` methods for `Bound`. [#4351](https://github.com/PyO3/pyo3/pull/4351) - Add FFI definitions `PyCFunctionFast` and `PyCFunctionFastWithKeywords` [#4415](https://github.com/PyO3/pyo3/pull/4415) - Add FFI definitions for `PyMutex` on Python 3.13 and newer. [#4421](https://github.com/PyO3/pyo3/pull/4421) - Add `PyDict::locked_for_each` to iterate efficiently on freethreaded Python. [#4439](https://github.com/PyO3/pyo3/pull/4439) - Add FFI definitions `PyObject_GetOptionalAttr`, `PyObject_GetOptionalAttrString`, `PyObject_HasAttrWithError`, `PyObject_HasAttrStringWithError`, `Py_CONSTANT_*` constants, `Py_GetConstant`, `Py_GetConstantBorrowed`, and `PyType_GetModuleByDef` on Python 3.13 and newer. [#4447](https://github.com/PyO3/pyo3/pull/4447) - Add FFI definitions for the Python critical section API available on Python 3.13 and newer. [#4477](https://github.com/PyO3/pyo3/pull/4477) - Add derive macro for `IntoPyObject`. [#4495](https://github.com/PyO3/pyo3/pull/4495) - Add `Borrowed::as_ptr`. [#4520](https://github.com/PyO3/pyo3/pull/4520) - Add FFI definition for `PyImport_AddModuleRef`. [#4529](https://github.com/PyO3/pyo3/pull/4529) - Add `PyAnyMethods::try_iter`. [#4553](https://github.com/PyO3/pyo3/pull/4553) - Add `pyo3::sync::with_critical_section`, a wrapper around the Python Critical Section API added in Python 3.13. [#4587](https://github.com/PyO3/pyo3/pull/4587) - Add `#[pymodule(gil_used = false)]` option to declare that a module supports the free-threaded build. [#4588](https://github.com/PyO3/pyo3/pull/4588) - Add `PyModule::gil_used` method to declare that a module supports the free-threaded build. [#4588](https://github.com/PyO3/pyo3/pull/4588) - Add FFI definition `PyDateTime_CAPSULE_NAME`. [#4634](https://github.com/PyO3/pyo3/pull/4634) - Add `PyMappingProxy` type to represent the `mappingproxy` Python class. [#4644](https://github.com/PyO3/pyo3/pull/4644) - Add FFI definitions `PyList_Extend` and `PyList_Clear`. [#4667](https://github.com/PyO3/pyo3/pull/4667) - Add derive macro for `IntoPyObjectRef`. [#4674](https://github.com/PyO3/pyo3/pull/4674) - Add `pyo3::sync::OnceExt` and `pyo3::sync::OnceLockExt` traits. [#4676](https://github.com/PyO3/pyo3/pull/4676) ### Changed - Prefer `IntoPyObject` over `IntoPy>>` for `#[pyfunction]` and `#[pymethods]` return types. [#4060](https://github.com/PyO3/pyo3/pull/4060) - Report multiple errors from `#[pyclass]` and `#[pyo3(..)]` attributes. [#4243](https://github.com/PyO3/pyo3/pull/4243) - Nested declarative `#[pymodule]` are automatically treated as submodules (no `PyInit_` entrypoint is created). [#4308](https://github.com/PyO3/pyo3/pull/4308) - Deprecate `PyAnyMethods::is_ellipsis` (`Py::is_ellipsis` was deprecated in PyO3 0.20). [#4322](https://github.com/PyO3/pyo3/pull/4322) - Deprecate `PyLong` in favor of `PyInt`. [#4347](https://github.com/PyO3/pyo3/pull/4347) - Rename `IntoPyDict::into_py_dict_bound` to `IntoPyDict::into_py_dict`. [#4388](https://github.com/PyO3/pyo3/pull/4388) - `PyModule::from_code` now expects `&CStr` as arguments instead of `&str`. [#4404](https://github.com/PyO3/pyo3/pull/4404) - Use "fastcall" Python calling convention for `#[pyfunction]`s when compiling on abi3 for Python 3.10 and up. [#4415](https://github.com/PyO3/pyo3/pull/4415) - Remove `Copy` and `Clone` from `PyObject` struct FFI definition. [#4434](https://github.com/PyO3/pyo3/pull/4434) - `Python::eval` and `Python::run` now take a `&CStr` instead of `&str`. [#4435](https://github.com/PyO3/pyo3/pull/4435) - Deprecate `IPowModulo`, `PyClassAttributeDef`, `PyGetterDef`, `PyMethodDef`, `PyMethodDefType`, and `PySetterDef` from PyO3's public API. [#4441](https://github.com/PyO3/pyo3/pull/4441) - `IntoPyObject` impls for `Vec`, `&[u8]`, `[u8; N]`, `Cow<[u8]>` and `SmallVec<[u8; N]>` now convert into Python `bytes` rather than a `list` of integers. [#4442](https://github.com/PyO3/pyo3/pull/4442) - Emit a compile-time error when attempting to subclass a class that doesn't allow subclassing. [#4453](https://github.com/PyO3/pyo3/pull/4453) - `IntoPyDict::into_py_dict` is now fallible due to `IntoPyObject` migration. [#4493](https://github.com/PyO3/pyo3/pull/4493) - The `abi3` feature will now override config files provided via `PYO3_BUILD_CONFIG`. [#4497](https://github.com/PyO3/pyo3/pull/4497) - Disable the `GILProtected` struct on free-threaded Python. [#4504](https://github.com/PyO3/pyo3/pull/4504) - Updated FFI definitions for functions and struct fields that have been deprecated or removed from CPython. [#4534](https://github.com/PyO3/pyo3/pull/4534) - Disable `PyListMethods::get_item_unchecked` on free-threaded Python. [#4539](https://github.com/PyO3/pyo3/pull/4539) - Add `GILOnceCell::import`. [#4542](https://github.com/PyO3/pyo3/pull/4542) - Deprecate `PyAnyMethods::iter` in favour of `PyAnyMethods::try_iter`. [#4553](https://github.com/PyO3/pyo3/pull/4553) - The `#[pyclass]` macro now requires a types to be `Sync`. (Except for `#[pyclass(unsendable)]` types). [#4566](https://github.com/PyO3/pyo3/pull/4566) - `PyList::new` and `PyTuple::new` are now fallible due to `IntoPyObject` migration. [#4580](https://github.com/PyO3/pyo3/pull/4580) - `PyErr::matches` is now fallible due to `IntoPyObject` migration. [#4595](https://github.com/PyO3/pyo3/pull/4595) - Deprecate `ToPyObject` in favour of `IntoPyObject` [#4595](https://github.com/PyO3/pyo3/pull/4595) - Deprecate `PyWeakrefMethods::get_option`. [#4597](https://github.com/PyO3/pyo3/pull/4597) - Seal `PyWeakrefMethods` trait. [#4598](https://github.com/PyO3/pyo3/pull/4598) - Remove `PyNativeTypeInitializer` and `PyObjectInit` from the PyO3 public API. [#4611](https://github.com/PyO3/pyo3/pull/4611) - Deprecate `IntoPy` in favor of `IntoPyObject` [#4618](https://github.com/PyO3/pyo3/pull/4618) - Eagerly normalize exceptions in `PyErr::take()` and `PyErr::fetch()` on Python 3.11 and older. [#4655](https://github.com/PyO3/pyo3/pull/4655) - Move `IntoPy::type_output` to `IntoPyObject::type_output`. [#4657](https://github.com/PyO3/pyo3/pull/4657) - Change return type of `PyMapping::keys`, `PyMapping::values` and `PyMapping::items` to `Bound<'py, PyList>` instead of `Bound<'py, PySequence>`. [#4661](https://github.com/PyO3/pyo3/pull/4661) - Complex enums now allow field types that either implement `IntoPyObject` by reference or by value together with `Clone`. This makes `Py` available as field type. [#4694](https://github.com/PyO3/pyo3/pull/4694) ### Removed - Remove all functionality deprecated in PyO3 0.20. [#4322](https://github.com/PyO3/pyo3/pull/4322) - Remove all functionality deprecated in PyO3 0.21. [#4323](https://github.com/PyO3/pyo3/pull/4323) - Deprecate `PyUnicode` in favour of `PyString`. [#4370](https://github.com/PyO3/pyo3/pull/4370) - Remove deprecated `gil-refs` feature. [#4378](https://github.com/PyO3/pyo3/pull/4378) - Remove private FFI definitions `_Py_IMMORTAL_REFCNT`, `_Py_IsImmortal`, `_Py_TPFLAGS_STATIC_BUILTIN`, `_Py_Dealloc`, `_Py_IncRef`, `_Py_DecRef`. [#4447](https://github.com/PyO3/pyo3/pull/4447) - Remove private FFI definitions `_Py_c_sum`, `_Py_c_diff`, `_Py_c_neg`, `_Py_c_prod`, `_Py_c_quot`, `_Py_c_pow`, `_Py_c_abs`. [#4521](https://github.com/PyO3/pyo3/pull/4521) - Remove `_borrowed` methods of `PyWeakRef` and `PyWeakRefProxy`. [#4528](https://github.com/PyO3/pyo3/pull/4528) - Removed private FFI definition `_PyErr_ChainExceptions`. [#4534](https://github.com/PyO3/pyo3/pull/4534) ### Fixed - Fix invalid library search path `lib_dir` when cross-compiling. [#4389](https://github.com/PyO3/pyo3/pull/4389) - Fix FFI definition `Py_Is` for PyPy on 3.10 to call the function defined by PyPy. [#4447](https://github.com/PyO3/pyo3/pull/4447) - Fix compile failure when using `#[cfg]` attributes for simple enum variants. [#4509](https://github.com/PyO3/pyo3/pull/4509) - Fix compiler warning for `non_snake_case` method names inside `#[pymethods]` generated code. [#4567](https://github.com/PyO3/pyo3/pull/4567) - Fix compile error with `#[derive(FromPyObject)]` generic struct with trait bounds. [#4645](https://github.com/PyO3/pyo3/pull/4645) - Fix compile error for `#[classmethod]` and `#[staticmethod]` on magic methods. [#4654](https://github.com/PyO3/pyo3/pull/4654) - Fix compile warning for `unsafe_op_in_unsafe_fn` in generated macro code. [#4674](https://github.com/PyO3/pyo3/pull/4674) - Fix incorrect deprecation warning for `#[pyclass] enum`s with custom `__eq__` implementation. [#4692](https://github.com/PyO3/pyo3/pull/4692) - Fix `non_upper_case_globals` lint firing for generated `__match_args__` on complex enums. [#4705](https://github.com/PyO3/pyo3/pull/4705) ## [0.22.5] - 2024-10-15 ### Fixed - Fix regression in 0.22.4 of naming collision in `__clear__` slot and `clear` method generated code. [#4619](https://github.com/PyO3/pyo3/pull/4619) ## [0.22.4] - 2024-10-12 ### Added - Add FFI definition `PyWeakref_GetRef` and `compat::PyWeakref_GetRef`. [#4528](https://github.com/PyO3/pyo3/pull/4528) ### Changed - Deprecate `_borrowed` methods on `PyWeakRef` and `PyWeakrefProxy` (just use the owning forms). [#4590](https://github.com/PyO3/pyo3/pull/4590) ### Fixed - Revert removal of private FFI function `_PyLong_NumBits` on Python 3.13 and later. [#4450](https://github.com/PyO3/pyo3/pull/4450) - Fix `__traverse__` functions for base classes not being called by subclasses created with `#[pyclass(extends = ...)]`. [#4563](https://github.com/PyO3/pyo3/pull/4563) - Fix regression in 0.22.3 failing compiles under `#![forbid(unsafe_code)]`. [#4574](https://github.com/PyO3/pyo3/pull/4574) - Fix `create_exception` macro triggering lint and compile errors due to interaction with `gil-refs` feature. [#4589](https://github.com/PyO3/pyo3/pull/4589) - Workaround possible use-after-free in `_borrowed` methods on `PyWeakRef` and `PyWeakrefProxy` by leaking their contents. [#4590](https://github.com/PyO3/pyo3/pull/4590) - Fix crash calling `PyType_GetSlot` on static types before Python 3.10. [#4599](https://github.com/PyO3/pyo3/pull/4599) ## [0.22.3] - 2024-09-15 ### Added - Add `pyo3::ffi::compat` namespace with compatibility shims for C API functions added in recent versions of Python. - Add FFI definition `PyDict_GetItemRef` on Python 3.13 and newer, and `compat::PyDict_GetItemRef` for all versions. [#4355](https://github.com/PyO3/pyo3/pull/4355) - Add FFI definition `PyList_GetItemRef` on Python 3.13 and newer, and `pyo3_ffi::compat::PyList_GetItemRef` for all versions. [#4410](https://github.com/PyO3/pyo3/pull/4410) - Add FFI definitions `compat::Py_NewRef` and `compat::Py_XNewRef`. [#4445](https://github.com/PyO3/pyo3/pull/4445) - Add FFI definitions `compat::PyObject_CallNoArgs` and `compat::PyObject_CallMethodNoArgs`. [#4461](https://github.com/PyO3/pyo3/pull/4461) - Add `GilOnceCell>::clone_ref`. [#4511](https://github.com/PyO3/pyo3/pull/4511) ### Changed - Improve error messages for `#[pyfunction]` defined inside `#[pymethods]`. [#4349](https://github.com/PyO3/pyo3/pull/4349) - Improve performance of calls to Python by using the vectorcall calling convention where possible. [#4456](https://github.com/PyO3/pyo3/pull/4456) - Mention the type name in the exception message when trying to instantiate a class with no constructor defined. [#4481](https://github.com/PyO3/pyo3/pull/4481) ### Removed - Remove private FFI definition `_Py_PackageContext`. [#4420](https://github.com/PyO3/pyo3/pull/4420) ### Fixed - Fix compile failure in declarative `#[pymodule]` under presence of `#![no_implicit_prelude]`. [#4328](https://github.com/PyO3/pyo3/pull/4328) - Fix use of borrowed reference in `PyDict::get_item` (unsafe in free-threaded Python). [#4355](https://github.com/PyO3/pyo3/pull/4355) - Fix `#[pyclass(eq)]` macro hygiene issues for structs and enums. [#4359](https://github.com/PyO3/pyo3/pull/4359) - Fix hygiene/span issues of `#[pyfunction]` and `#[pymethods]` generated code which affected expansion in `macro_rules` context. [#4382](https://github.com/PyO3/pyo3/pull/4382) - Fix `unsafe_code` lint error in `#[pyclass]` generated code. [#4396](https://github.com/PyO3/pyo3/pull/4396) - Fix async functions returning a tuple only returning the first element to Python. [#4407](https://github.com/PyO3/pyo3/pull/4407) - Fix use of borrowed reference in `PyList::get_item` (unsafe in free-threaded Python). [#4410](https://github.com/PyO3/pyo3/pull/4410) - Correct FFI definition `PyArg_ParseTupleAndKeywords` to take `*const *const c_char` instead of `*mut *mut c_char` on Python 3.13 and up. [#4420](https://github.com/PyO3/pyo3/pull/4420) - Fix a soundness bug with `PyClassInitializer`: panic if adding subclass to existing instance via `PyClassInitializer::from(Py).add_subclass(SubClass)`. [#4454](https://github.com/PyO3/pyo3/pull/4454) - Fix illegal reference counting op inside implementation of `__traverse__` handlers. [#4479](https://github.com/PyO3/pyo3/pull/4479) ## [0.22.2] - 2024-07-17 ### Packaging - Require opt-in to freethreaded Python using the `UNSAFE_PYO3_BUILD_FREE_THREADED=1` environment variable (it is not yet supported by PyO3). [#4327](https://github.com/PyO3/pyo3/pull/4327) ### Changed - Use FFI function calls for reference counting on all abi3 versions. [#4324](https://github.com/PyO3/pyo3/pull/4324) - `#[pymodule(...)]` now directly accepts all relevant `#[pyo3(...)]` options. [#4330](https://github.com/PyO3/pyo3/pull/4330) ### Fixed - Fix compile failure in declarative `#[pymodule]` under presence of `#![no_implicit_prelude]`. [#4328](https://github.com/PyO3/pyo3/pull/4328) - Fix compile failure due to c-string literals on Rust < 1.79. [#4353](https://github.com/PyO3/pyo3/pull/4353) ## [0.22.1] - 2024-07-06 ### Added - Add `#[pyo3(submodule)]` option for declarative `#[pymodule]`s. [#4301](https://github.com/PyO3/pyo3/pull/4301) - Implement `PartialEq` for `Bound<'py, PyBool>`. [#4305](https://github.com/PyO3/pyo3/pull/4305) ### Fixed - Return `NotImplemented` instead of raising `TypeError` from generated equality method when comparing different types. [#4287](https://github.com/PyO3/pyo3/pull/4287) - Handle full-path `#[pyo3::prelude::pymodule]` and similar for `#[pyclass]` and `#[pyfunction]` in declarative modules. [#4288](https://github.com/PyO3/pyo3/pull/4288) - Fix 128-bit int regression on big-endian platforms with Python <3.13. [#4291](https://github.com/PyO3/pyo3/pull/4291) - Stop generating code that will never be covered with declarative modules. [#4297](https://github.com/PyO3/pyo3/pull/4297) - Fix invalid deprecation warning for trailing optional on `#[setter]` function. [#4304](https://github.com/PyO3/pyo3/pull/4304) ## [0.22.0] - 2024-06-24 ### Packaging - Update `heck` dependency to 0.5. [#3966](https://github.com/PyO3/pyo3/pull/3966) - Extend range of supported versions of `chrono-tz` optional dependency to include version 0.10. [#4061](https://github.com/PyO3/pyo3/pull/4061) - Update MSRV to 1.63. [#4129](https://github.com/PyO3/pyo3/pull/4129) - Add optional `num-rational` feature to add conversions with Python's `fractions.Fraction`. [#4148](https://github.com/PyO3/pyo3/pull/4148) - Support Python 3.13. [#4184](https://github.com/PyO3/pyo3/pull/4184) ### Added - Add `PyWeakref`, `PyWeakrefReference` and `PyWeakrefProxy`. [#3835](https://github.com/PyO3/pyo3/pull/3835) - Support `#[pyclass]` on enums that have tuple variants. [#4072](https://github.com/PyO3/pyo3/pull/4072) - Add support for scientific notation in `Decimal` conversion. [#4079](https://github.com/PyO3/pyo3/pull/4079) - Add `pyo3_disable_reference_pool` conditional compilation flag to avoid the overhead of the global reference pool at the cost of known limitations as explained in the performance section of the guide. [#4095](https://github.com/PyO3/pyo3/pull/4095) - Add `#[pyo3(constructor = (...))]` to customize the generated constructors for complex enum variants. [#4158](https://github.com/PyO3/pyo3/pull/4158) - Add `PyType::module`, which always matches Python `__module__`. [#4196](https://github.com/PyO3/pyo3/pull/4196) - Add `PyType::fully_qualified_name` which matches the "fully qualified name" defined in [PEP 737](https://peps.python.org/pep-0737). [#4196](https://github.com/PyO3/pyo3/pull/4196) - Add `PyTypeMethods::mro` and `PyTypeMethods::bases`. [#4197](https://github.com/PyO3/pyo3/pull/4197) - Add `#[pyclass(ord)]` to implement ordering based on `PartialOrd`. [#4202](https://github.com/PyO3/pyo3/pull/4202) - Implement `ToPyObject` and `IntoPy` for `PyBackedStr` and `PyBackedBytes`. [#4205](https://github.com/PyO3/pyo3/pull/4205) - Add `#[pyclass(hash)]` option to implement `__hash__` in terms of the `Hash` implementation [#4206](https://github.com/PyO3/pyo3/pull/4206) - Add `#[pyclass(eq)]` option to generate `__eq__` based on `PartialEq`, and `#[pyclass(eq_int)]` for simple enums to implement equality based on their discriminants. [#4210](https://github.com/PyO3/pyo3/pull/4210) - Implement `From>` for `PyClassInitializer`. [#4214](https://github.com/PyO3/pyo3/pull/4214) - Add `as_super` methods to `PyRef` and `PyRefMut` for accesing the base class by reference. [#4219](https://github.com/PyO3/pyo3/pull/4219) - Implement `PartialEq` for `Bound<'py, PyString>`. [#4245](https://github.com/PyO3/pyo3/pull/4245) - Implement `PyModuleMethods::filename` on PyPy. [#4249](https://github.com/PyO3/pyo3/pull/4249) - Implement `PartialEq<[u8]>` for `Bound<'py, PyBytes>`. [#4250](https://github.com/PyO3/pyo3/pull/4250) - Add `pyo3_ffi::c_str` macro to create `&'static CStr` on Rust versions which don't have 1.77's `c""` literals. [#4255](https://github.com/PyO3/pyo3/pull/4255) - Support `bool` conversion with `numpy` 2.0's `numpy.bool` type [#4258](https://github.com/PyO3/pyo3/pull/4258) - Add `PyAnyMethods::{bitnot, matmul, floor_div, rem, divmod}`. [#4264](https://github.com/PyO3/pyo3/pull/4264) ### Changed - Change the type of `PySliceIndices::slicelength` and the `length` parameter of `PySlice::indices()`. [#3761](https://github.com/PyO3/pyo3/pull/3761) - Deprecate implicit default for trailing optional arguments [#4078](https://github.com/PyO3/pyo3/pull/4078) - `Clone`ing pointers into the Python heap has been moved behind the `py-clone` feature, as it must panic without the GIL being held as a soundness fix. [#4095](https://github.com/PyO3/pyo3/pull/4095) - Add `#[track_caller]` to all `Py`, `Bound<'py, T>` and `Borrowed<'a, 'py, T>` methods which can panic. [#4098](https://github.com/PyO3/pyo3/pull/4098) - Change `PyAnyMethods::dir` to be fallible and return `PyResult>` (and similar for `PyAny::dir`). [#4100](https://github.com/PyO3/pyo3/pull/4100) - The global reference pool (to track pending reference count decrements) is now initialized lazily to avoid the overhead of taking a mutex upon function entry when the functionality is not actually used. [#4178](https://github.com/PyO3/pyo3/pull/4178) - Emit error messages when using `weakref` or `dict` when compiling for `abi3` for Python older than 3.9. [#4194](https://github.com/PyO3/pyo3/pull/4194) - Change `PyType::name` to always match Python `__name__`. [#4196](https://github.com/PyO3/pyo3/pull/4196) - Remove CPython internal ffi call for complex number including: add, sub, mul, div, neg, abs, pow. Added PyAnyMethods::{abs, pos, neg} [#4201](https://github.com/PyO3/pyo3/pull/4201) - Deprecate implicit integer comparision for simple enums in favor of `#[pyclass(eq_int)]`. [#4210](https://github.com/PyO3/pyo3/pull/4210) - Set the `module=` attribute of declarative modules' child `#[pymodule]`s and `#[pyclass]`es. [#4213](https://github.com/PyO3/pyo3/pull/4213) - Set the `module` option for complex enum variants from the value set on the complex enum `module`. [#4228](https://github.com/PyO3/pyo3/pull/4228) - Respect the Python "limited API" when building for the `abi3` feature on PyPy or GraalPy. [#4237](https://github.com/PyO3/pyo3/pull/4237) - Optimize code generated by `#[pyo3(get)]` on `#[pyclass]` fields. [#4254](https://github.com/PyO3/pyo3/pull/4254) - `PyCFunction::new`, `PyCFunction::new_with_keywords` and `PyCFunction::new_closure` now take `&'static CStr` name and doc arguments (previously was `&'static str`). [#4255](https://github.com/PyO3/pyo3/pull/4255) - The `experimental-declarative-modules` feature is now stabilized and available by default. [#4257](https://github.com/PyO3/pyo3/pull/4257) ### Fixed - Fix panic when `PYO3_CROSS_LIB_DIR` is set to a missing path. [#4043](https://github.com/PyO3/pyo3/pull/4043) - Fix a compile error when exporting an exception created with `create_exception!` living in a different Rust module using the `declarative-module` feature. [#4086](https://github.com/PyO3/pyo3/pull/4086) - Fix FFI definitions of `PY_VECTORCALL_ARGUMENTS_OFFSET` and `PyVectorcall_NARGS` to fix a false-positive assertion. [#4104](https://github.com/PyO3/pyo3/pull/4104) - Disable `PyUnicode_DATA` on PyPy: not exposed by PyPy. [#4116](https://github.com/PyO3/pyo3/pull/4116) - Correctly handle `#[pyo3(from_py_with = ...)]` attribute on dunder (`__magic__`) method arguments instead of silently ignoring it. [#4117](https://github.com/PyO3/pyo3/pull/4117) - Fix a compile error when declaring a standalone function or class method with a Python name that is a Rust keyword. [#4226](https://github.com/PyO3/pyo3/pull/4226) - Fix declarative modules discarding doc comments on the `mod` node. [#4236](https://github.com/PyO3/pyo3/pull/4236) - Fix `__dict__` attribute missing for `#[pyclass(dict)]` instances when building for `abi3` on Python 3.9. [#4251](https://github.com/PyO3/pyo3/pull/4251) ## [0.21.2] - 2024-04-16 ### Changed - Deprecate the `PySet::empty()` gil-ref constructor. [#4082](https://github.com/PyO3/pyo3/pull/4082) ### Fixed - Fix compile error for `async fn` in `#[pymethods]` with a `&self` receiver and more than one additional argument. [#4035](https://github.com/PyO3/pyo3/pull/4035) - Improve error message for wrong receiver type in `__traverse__`. [#4045](https://github.com/PyO3/pyo3/pull/4045) - Fix compile error when exporting a `#[pyclass]` living in a different Rust module using the `experimental-declarative-modules` feature. [#4054](https://github.com/PyO3/pyo3/pull/4054) - Fix `missing_docs` lint triggering on documented `#[pymodule]` functions. [#4067](https://github.com/PyO3/pyo3/pull/4067) - Fix undefined symbol errors for extension modules on AIX (by linking `libpython`). [#4073](https://github.com/PyO3/pyo3/pull/4073) ## [0.21.1] - 2024-04-01 ### Added - Implement `Send` and `Sync` for `PyBackedStr` and `PyBackedBytes`. [#4007](https://github.com/PyO3/pyo3/pull/4007) - Implement `Clone`, `Debug`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` implementation for `PyBackedBytes` and `PyBackedStr`, and `Display` for `PyBackedStr`. [#4020](https://github.com/PyO3/pyo3/pull/4020) - Add `import_exception_bound!` macro to import exception types without generating GIL Ref functionality for them. [#4027](https://github.com/PyO3/pyo3/pull/4027) ### Changed - Emit deprecation warning for uses of GIL Refs as `#[setter]` function arguments. [#3998](https://github.com/PyO3/pyo3/pull/3998) - Add `#[inline]` hints on many `Bound` and `Borrowed` methods. [#4024](https://github.com/PyO3/pyo3/pull/4024) ### Fixed - Handle `#[pyo3(from_py_with = "")]` in `#[setter]` methods [#3995](https://github.com/PyO3/pyo3/pull/3995) - Allow extraction of `&Bound` in `#[setter]` methods. [#3998](https://github.com/PyO3/pyo3/pull/3998) - Fix some uncovered code blocks emitted by `#[pymodule]`, `#[pyfunction]` and `#[pyclass]` macros. [#4009](https://github.com/PyO3/pyo3/pull/4009) - Fix typo in the panic message when a class referenced in `pyo3::import_exception!` does not exist. [#4012](https://github.com/PyO3/pyo3/pull/4012) - Fix compile error when using an async `#[pymethod]` with a receiver and additional arguments. [#4015](https://github.com/PyO3/pyo3/pull/4015) ## [0.21.0] - 2024-03-25 ### Added - Add support for GraalPy (24.0 and up). [#3247](https://github.com/PyO3/pyo3/pull/3247) - Add `PyMemoryView` type. [#3514](https://github.com/PyO3/pyo3/pull/3514) - Allow `async fn` in for `#[pyfunction]` and `#[pymethods]`, with the `experimental-async` feature. [#3540](https://github.com/PyO3/pyo3/pull/3540) [#3588](https://github.com/PyO3/pyo3/pull/3588) [#3599](https://github.com/PyO3/pyo3/pull/3599) [#3931](https://github.com/PyO3/pyo3/pull/3931) - Implement `PyTypeInfo` for `PyEllipsis`, `PyNone` and `PyNotImplemented`. [#3577](https://github.com/PyO3/pyo3/pull/3577) - Support `#[pyclass]` on enums that have non-unit variants. [#3582](https://github.com/PyO3/pyo3/pull/3582) - Support `chrono` feature with `abi3` feature. [#3664](https://github.com/PyO3/pyo3/pull/3664) - `FromPyObject`, `IntoPy` and `ToPyObject` are implemented on `std::duration::Duration` [#3670](https://github.com/PyO3/pyo3/pull/3670) - Add `PyString::to_cow`. Add `Py::to_str`, `Py::to_cow`, and `Py::to_string_lossy`, as ways to access Python string data safely beyond the GIL lifetime. [#3677](https://github.com/PyO3/pyo3/pull/3677) - Add `Bound` and `Borrowed` smart pointers as a new API for accessing Python objects. [#3686](https://github.com/PyO3/pyo3/pull/3686) - Add `PyNativeType::as_borrowed` to convert "GIL refs" to the new `Bound` smart pointer. [#3692](https://github.com/PyO3/pyo3/pull/3692) - Add `FromPyObject::extract_bound` method, to migrate `FromPyObject` implementations to the Bound API. [#3706](https://github.com/PyO3/pyo3/pull/3706) - Add `gil-refs` feature to allow continued use of the deprecated GIL Refs APIs. [#3707](https://github.com/PyO3/pyo3/pull/3707) - Add methods to `PyAnyMethods` for binary operators (`add`, `sub`, etc.) [#3712](https://github.com/PyO3/pyo3/pull/3712) - Add `chrono-tz` feature allowing conversion between `chrono_tz::Tz` and `zoneinfo.ZoneInfo` [#3730](https://github.com/PyO3/pyo3/pull/3730) - Add FFI definition `PyType_GetModuleByDef`. [#3734](https://github.com/PyO3/pyo3/pull/3734) - Conversion between `std::time::SystemTime` and `datetime.datetime` [#3736](https://github.com/PyO3/pyo3/pull/3736) - Add `Py::as_any` and `Py::into_any`. [#3785](https://github.com/PyO3/pyo3/pull/3785) - Add `PyStringMethods::encode_utf8`. [#3801](https://github.com/PyO3/pyo3/pull/3801) - Add `PyBackedStr` and `PyBackedBytes`, as alternatives to `&str` and `&bytes` where a Python object owns the data. [#3802](https://github.com/PyO3/pyo3/pull/3802) [#3991](https://github.com/PyO3/pyo3/pull/3991) - Allow `#[pymodule]` macro on Rust `mod` blocks, with the `experimental-declarative-modules` feature. [#3815](https://github.com/PyO3/pyo3/pull/3815) - Implement `ExactSizeIterator` for `set` and `frozenset` iterators on `abi3` feature. [#3849](https://github.com/PyO3/pyo3/pull/3849) - Add `Py::drop_ref` to explicitly drop a `Py`` and immediately decrease the Python reference count if the GIL is already held. [#3871](https://github.com/PyO3/pyo3/pull/3871) - Allow `#[pymodule]` macro on single argument functions that take `&Bound<'_, PyModule>`. [#3905](https://github.com/PyO3/pyo3/pull/3905) - Implement `FromPyObject` for `Cow`. [#3928](https://github.com/PyO3/pyo3/pull/3928) - Implement `Default` for `GILOnceCell`. [#3971](https://github.com/PyO3/pyo3/pull/3971) - Add `PyDictMethods::into_mapping`, `PyListMethods::into_sequence` and `PyTupleMethods::into_sequence`. [#3982](https://github.com/PyO3/pyo3/pull/3982) ### Changed - `PyDict::from_sequence` now takes a single argument of type `&PyAny` (previously took two arguments `Python` and `PyObject`). [#3532](https://github.com/PyO3/pyo3/pull/3532) - Deprecate `Py::is_ellipsis` and `PyAny::is_ellipsis` in favour of `any.is(py.Ellipsis())`. [#3577](https://github.com/PyO3/pyo3/pull/3577) - Split some `PyTypeInfo` functionality into new traits `HasPyGilRef` and `PyTypeCheck`. [#3600](https://github.com/PyO3/pyo3/pull/3600) - Deprecate `PyTryFrom` and `PyTryInto` traits in favor of `any.downcast()` via the `PyTypeCheck` and `PyTypeInfo` traits. [#3601](https://github.com/PyO3/pyo3/pull/3601) - Allow async methods to accept `&self`/`&mut self` [#3609](https://github.com/PyO3/pyo3/pull/3609) - `FromPyObject` for set types now also accept `frozenset` objects as input. [#3632](https://github.com/PyO3/pyo3/pull/3632) - `FromPyObject` for `bool` now also accepts NumPy's `bool_` as input. [#3638](https://github.com/PyO3/pyo3/pull/3638) - Add `AsRefSource` associated type to `PyNativeType`. [#3653](https://github.com/PyO3/pyo3/pull/3653) - Rename `.is_true` to `.is_truthy` on `PyAny` and `Py` to clarify that the test is not based on identity with or equality to the True singleton. [#3657](https://github.com/PyO3/pyo3/pull/3657) - `PyType::name` is now `PyType::qualname` whereas `PyType::name` efficiently accesses the full name which includes the module name. [#3660](https://github.com/PyO3/pyo3/pull/3660) - The `Iter(A)NextOutput` types are now deprecated and `__(a)next__` can directly return anything which can be converted into Python objects, i.e. awaitables do not need to be wrapped into `IterANextOutput` or `Option` any more. `Option` can still be used as well and returning `None` will trigger the fast path for `__next__`, stopping iteration without having to raise a `StopIteration` exception. [#3661](https://github.com/PyO3/pyo3/pull/3661) - Implement `FromPyObject` on `chrono::DateTime` for all `Tz`, not just `FixedOffset` and `Utc`. [#3663](https://github.com/PyO3/pyo3/pull/3663) - Add lifetime parameter to `PyTzInfoAccess` trait. For the deprecated gil-ref API, the trait is now implemented for `&'py PyTime` and `&'py PyDateTime` instead of `PyTime` and `PyDate`. [#3679](https://github.com/PyO3/pyo3/pull/3679) - Calls to `__traverse__` become no-ops for unsendable pyclasses if on the wrong thread, thereby avoiding hard aborts at the cost of potential leakage. [#3689](https://github.com/PyO3/pyo3/pull/3689) - Include `PyNativeType` in `pyo3::prelude`. [#3692](https://github.com/PyO3/pyo3/pull/3692) - Improve performance of `extract::` (and other integer types) by avoiding call to `__index__()` converting the value to an integer for 3.10+. Gives performance improvement of around 30% for successful extraction. [#3742](https://github.com/PyO3/pyo3/pull/3742) - Relax bound of `FromPyObject` for `Py` to just `T: PyTypeCheck`. [#3776](https://github.com/PyO3/pyo3/pull/3776) - `PySet` and `PyFrozenSet` iterators now always iterate the equivalent of `iter(set)`. (A "fast path" with no noticeable performance benefit was removed.) [#3849](https://github.com/PyO3/pyo3/pull/3849) - Move implementations of `FromPyObject` for `&str`, `Cow`, `&[u8]` and `Cow<[u8]>` onto a temporary trait `FromPyObjectBound` when `gil-refs` feature is deactivated. [#3928](https://github.com/PyO3/pyo3/pull/3928) - Deprecate `GILPool`, `Python::with_pool`, and `Python::new_pool`. [#3947](https://github.com/PyO3/pyo3/pull/3947) ### Removed - Remove all functionality deprecated in PyO3 0.19. [#3603](https://github.com/PyO3/pyo3/pull/3603) ### Fixed - Match PyPy 7.3.14 in removing PyPy-only symbol `Py_MAX_NDIMS` in favour of `PyBUF_MAX_NDIM`. [#3757](https://github.com/PyO3/pyo3/pull/3757) - Fix segmentation fault using `datetime` types when an invalid `datetime` module is on sys.path. [#3818](https://github.com/PyO3/pyo3/pull/3818) - Fix `non_local_definitions` lint warning triggered by many PyO3 macros. [#3901](https://github.com/PyO3/pyo3/pull/3901) - Disable `PyCode` and `PyCode_Type` on PyPy: `PyCode_Type` is not exposed by PyPy. [#3934](https://github.com/PyO3/pyo3/pull/3934) ## [0.21.0-beta.0] - 2024-03-10 Prerelease of PyO3 0.21. See [the GitHub diff](https://github.com/pyo3/pyo3/compare/v0.21.0-beta.0...v0.21.0) for what changed between 0.21.0-beta.0 and the final release. ## [0.20.3] - 2024-02-23 ### Packaging - Add `portable-atomic` dependency. [#3619](https://github.com/PyO3/pyo3/pull/3619) - Check maximum version of Python at build time and for versions not yet supported require opt-in to the `abi3` stable ABI by the environment variable `PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1`. [#3821](https://github.com/PyO3/pyo3/pull/3821) ### Fixed - Use `portable-atomic` to support platforms without 64-bit atomics. [#3619](https://github.com/PyO3/pyo3/pull/3619) - Fix compilation failure with `either` feature enabled without `experimental-inspect` enabled. [#3834](https://github.com/PyO3/pyo3/pull/3834) ## [0.20.2] - 2024-01-04 ### Packaging - Pin `pyo3` and `pyo3-ffi` dependencies on `pyo3-build-config` to require the same patch version, i.e. `pyo3` 0.20.2 requires _exactly_ `pyo3-build-config` 0.20.2. [#3721](https://github.com/PyO3/pyo3/pull/3721) ### Fixed - Fix compile failure when building `pyo3` 0.20.0 with latest `pyo3-build-config` 0.20.X. [#3724](https://github.com/PyO3/pyo3/pull/3724) - Fix docs.rs build. [#3722](https://github.com/PyO3/pyo3/pull/3722) ## [0.20.1] - 2023-12-30 ### Added - Add optional `either` feature to add conversions for `either::Either` sum type. [#3456](https://github.com/PyO3/pyo3/pull/3456) - Add optional `smallvec` feature to add conversions for `smallvec::SmallVec`. [#3507](https://github.com/PyO3/pyo3/pull/3507) - Add `take` and `into_inner` methods to `GILOnceCell` [#3556](https://github.com/PyO3/pyo3/pull/3556) - `#[classmethod]` methods can now also receive `Py` as their first argument. [#3587](https://github.com/PyO3/pyo3/pull/3587) - `#[pyfunction(pass_module)]` can now also receive `Py` as their first argument. [#3587](https://github.com/PyO3/pyo3/pull/3587) - Add `traverse` method to `GILProtected`. [#3616](https://github.com/PyO3/pyo3/pull/3616) - Added `abi3-py312` feature [#3687](https://github.com/PyO3/pyo3/pull/3687) ### Fixed - Fix minimum version specification for optional `chrono` dependency. [#3512](https://github.com/PyO3/pyo3/pull/3512) - Silenced new `clippy::unnecessary_fallible_conversions` warning when using a `Py` `self` receiver. [#3564](https://github.com/PyO3/pyo3/pull/3564) ## [0.20.0] - 2023-10-11 ### Packaging - Dual-license PyO3 under either the Apache 2.0 OR the MIT license. This makes the project GPLv2 compatible. [#3108](https://github.com/PyO3/pyo3/pull/3108) - Update MSRV to Rust 1.56. [#3208](https://github.com/PyO3/pyo3/pull/3208) - Bump `indoc` dependency to 2.0 and `unindent` dependency to 0.2. [#3237](https://github.com/PyO3/pyo3/pull/3237) - Bump `syn` dependency to 2.0. [#3239](https://github.com/PyO3/pyo3/pull/3239) - Drop support for debug builds of Python 3.7. [#3387](https://github.com/PyO3/pyo3/pull/3387) - Bump `chrono` optional dependency to require 0.4.25 or newer. [#3427](https://github.com/PyO3/pyo3/pull/3427) - Support Python 3.12. [#3488](https://github.com/PyO3/pyo3/pull/3488) ### Added - Support `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__` and `__ge__` in `#[pymethods]`. [#3203](https://github.com/PyO3/pyo3/pull/3203) - Add FFI definition `Py_GETENV`. [#3336](https://github.com/PyO3/pyo3/pull/3336) - Add `as_ptr` and `into_ptr` inherent methods for `Py`, `PyAny`, `PyRef`, and `PyRefMut`. [#3359](https://github.com/PyO3/pyo3/pull/3359) - Implement `DoubleEndedIterator` for `PyTupleIterator` and `PyListIterator`. [#3366](https://github.com/PyO3/pyo3/pull/3366) - Add `#[pyclass(rename_all = "...")]` option: this allows renaming all getters and setters of a struct, or all variants of an enum. Available renaming rules are: `"camelCase"`, `"kebab-case"`, `"lowercase"`, `"PascalCase"`, `"SCREAMING-KEBAB-CASE"`, `"SCREAMING_SNAKE_CASE"`, `"snake_case"`, `"UPPERCASE"`. [#3384](https://github.com/PyO3/pyo3/pull/3384) - Add FFI definitions `PyObject_GC_IsTracked` and `PyObject_GC_IsFinalized` on Python 3.9 and up (PyPy 3.10 and up). [#3403](https://github.com/PyO3/pyo3/pull/3403) - Add types for `None`, `Ellipsis`, and `NotImplemented`. [#3408](https://github.com/PyO3/pyo3/pull/3408) - Add FFI definitions for the `Py_mod_multiple_interpreters` constant and its possible values. [#3494](https://github.com/PyO3/pyo3/pull/3494) - Add FFI definitions for `PyInterpreterConfig` struct, its constants and `Py_NewInterpreterFromConfig`. [#3502](https://github.com/PyO3/pyo3/pull/3502) ### Changed - Change `PySet::discard` to return `PyResult` (previously returned nothing). [#3281](https://github.com/PyO3/pyo3/pull/3281) - Optimize implmentation of `IntoPy` for Rust tuples to Python tuples. [#3321](https://github.com/PyO3/pyo3/pull/3321) - Change `PyDict::get_item` to no longer suppress arbitrary exceptions (the return type is now `PyResult>` instead of `Option<&PyAny>`), and deprecate `PyDict::get_item_with_error`. [#3330](https://github.com/PyO3/pyo3/pull/3330) - Deprecate FFI definitions which are deprecated in Python 3.12. [#3336](https://github.com/PyO3/pyo3/pull/3336) - `AsPyPointer` is now an `unsafe trait`. [#3358](https://github.com/PyO3/pyo3/pull/3358) - Accept all `os.PathLike` values in implementation of `FromPyObject` for `PathBuf`. [#3374](https://github.com/PyO3/pyo3/pull/3374) - Add `__builtins__` to globals in `py.run()` and `py.eval()` if they're missing. [#3378](https://github.com/PyO3/pyo3/pull/3378) - Optimize implementation of `FromPyObject` for `BigInt` and `BigUint`. [#3379](https://github.com/PyO3/pyo3/pull/3379) - `PyIterator::from_object` and `PyByteArray::from` now take a single argument of type `&PyAny` (previously took two arguments `Python` and `AsPyPointer`). [#3389](https://github.com/PyO3/pyo3/pull/3389) - Replace `AsPyPointer` with `AsRef` as a bound in the blanket implementation of `From<&T> for PyObject`. [#3391](https://github.com/PyO3/pyo3/pull/3391) - Replace blanket `impl IntoPy for &T where T: AsPyPointer` with implementations of `impl IntoPy` for `&PyAny`, `&T where T: AsRef`, and `&Py`. [#3393](https://github.com/PyO3/pyo3/pull/3393) - Preserve `std::io::Error` kind in implementation of `From` for `PyErr` [#3396](https://github.com/PyO3/pyo3/pull/3396) - Try to select a relevant `ErrorKind` in implementation of `From` for `OSError` subclass. [#3397](https://github.com/PyO3/pyo3/pull/3397) - Retrieve the original `PyErr` in implementation of `From` for `PyErr` if the `std::io::Error` has been built using a Python exception (previously would create a new exception wrapping the `std::io::Error`). [#3402](https://github.com/PyO3/pyo3/pull/3402) - `#[pymodule]` will now return the same module object on repeated import by the same Python interpreter, on Python 3.9 and up. [#3446](https://github.com/PyO3/pyo3/pull/3446) - Truncate leap-seconds and warn when converting `chrono` types to Python `datetime` types (`datetime` cannot represent leap-seconds). [#3458](https://github.com/PyO3/pyo3/pull/3458) - `Err` returned from `#[pyfunction]` will now have a non-None `__context__` if called from inside a `catch` block. [#3455](https://github.com/PyO3/pyo3/pull/3455) - Deprecate undocumented `#[__new__]` form of `#[new]` attribute. [#3505](https://github.com/PyO3/pyo3/pull/3505) ### Removed - Remove all functionality deprecated in PyO3 0.18, including `#[args]` attribute for `#[pymethods]`. [#3232](https://github.com/PyO3/pyo3/pull/3232) - Remove `IntoPyPointer` trait in favour of `into_ptr` inherent methods. [#3385](https://github.com/PyO3/pyo3/pull/3385) ### Fixed - Handle exceptions properly in `PySet::discard`. [#3281](https://github.com/PyO3/pyo3/pull/3281) - The `PyTupleIterator` type returned by `PyTuple::iter` is now public and hence can be named by downstream crates. [#3366](https://github.com/PyO3/pyo3/pull/3366) - Linking of `PyOS_FSPath` on PyPy. [#3374](https://github.com/PyO3/pyo3/pull/3374) - Fix memory leak in `PyTypeBuilder::build`. [#3401](https://github.com/PyO3/pyo3/pull/3401) - Disable removed FFI definitions `_Py_GetAllocatedBlocks`, `_PyObject_GC_Malloc`, and `_PyObject_GC_Calloc` on Python 3.11 and up. [#3403](https://github.com/PyO3/pyo3/pull/3403) - Fix `ResourceWarning` and crashes related to GC when running with debug builds of CPython. [#3404](https://github.com/PyO3/pyo3/pull/3404) - Some-wrapping of `Option` default arguments will no longer re-wrap `Some(T)` or expressions evaluating to `None`. [#3461](https://github.com/PyO3/pyo3/pull/3461) - Fix `IterNextOutput::Return` not returning a value on PyPy. [#3471](https://github.com/PyO3/pyo3/pull/3471) - Emit compile errors instead of ignoring macro invocations inside `#[pymethods]` blocks. [#3491](https://github.com/PyO3/pyo3/pull/3491) - Emit error on invalid arguments to `#[new]`, `#[classmethod]`, `#[staticmethod]`, and `#[classattr]`. [#3484](https://github.com/PyO3/pyo3/pull/3484) - Disable `PyMarshal_WriteObjectToString` from `PyMarshal_ReadObjectFromString` with the `abi3` feature. [#3490](https://github.com/PyO3/pyo3/pull/3490) - Fix FFI definitions for `_PyFrameEvalFunction` on Python 3.11 and up (it now receives a `_PyInterpreterFrame` opaque struct). [#3500](https://github.com/PyO3/pyo3/pull/3500) ## [0.19.2] - 2023-08-01 ### Added - Add FFI definitions `PyState_AddModule`, `PyState_RemoveModule` and `PyState_FindModule` for PyPy 3.9 and up. [#3295](https://github.com/PyO3/pyo3/pull/3295) - Add FFI definitions `_PyObject_CallFunction_SizeT` and `_PyObject_CallMethod_SizeT`. [#3297](https://github.com/PyO3/pyo3/pull/3297) - Add a "performance" section to the guide collecting performance-related tricks and problems. [#3304](https://github.com/PyO3/pyo3/pull/3304) - Add `PyErr::Display` for all Python versions, and FFI symbol `PyErr_DisplayException` for Python 3.12. [#3334](https://github.com/PyO3/pyo3/pull/3334) - Add FFI definition `PyType_GetDict()` for Python 3.12. [#3339](https://github.com/PyO3/pyo3/pull/3339) - Add `PyAny::downcast_exact`. [#3346](https://github.com/PyO3/pyo3/pull/3346) - Add `PySlice::full()` to construct a full slice (`::`). [#3353](https://github.com/PyO3/pyo3/pull/3353) ### Changed - Update `PyErr` for 3.12 betas to avoid deprecated ffi methods. [#3306](https://github.com/PyO3/pyo3/pull/3306) - Update FFI definitions of `object.h` for Python 3.12.0b4. [#3335](https://github.com/PyO3/pyo3/pull/3335) - Update `pyo3::ffi` struct definitions to be compatible with 3.12.0b4. [#3342](https://github.com/PyO3/pyo3/pull/3342) - Optimize conversion of `float` to `f64` (and `PyFloat::value`) on non-abi3 builds. [#3345](https://github.com/PyO3/pyo3/pull/3345) ### Fixed - Fix timezone conversion bug for FixedOffset datetimes that were being incorrectly converted to and from UTC. [#3269](https://github.com/PyO3/pyo3/pull/3269) - Fix `SystemError` raised in `PyUnicodeDecodeError_Create` on PyPy 3.10. [#3297](https://github.com/PyO3/pyo3/pull/3297) - Correct FFI definition `Py_EnterRecursiveCall` to return `c_int` (was incorrectly returning `()`). [#3300](https://github.com/PyO3/pyo3/pull/3300) - Fix case where `PyErr::matches` and `PyErr::is_instance` returned results inconsistent with `PyErr::get_type`. [#3313](https://github.com/PyO3/pyo3/pull/3313) - Fix loss of panic message in `PanicException` when unwinding after the exception was "normalized". [#3326](https://github.com/PyO3/pyo3/pull/3326) - Fix `PyErr::from_value` and `PyErr::into_value` losing traceback on conversion. [#3328](https://github.com/PyO3/pyo3/pull/3328) - Fix reference counting of immortal objects on Python 3.12.0b4. [#3335](https://github.com/PyO3/pyo3/pull/3335) ## [0.19.1] - 2023-07-03 ### Packaging - Extend range of supported versions of `hashbrown` optional dependency to include version 0.14 [#3258](https://github.com/PyO3/pyo3/pull/3258) - Extend range of supported versions of `indexmap` optional dependency to include version 2. [#3277](https://github.com/PyO3/pyo3/pull/3277) - Support PyPy 3.10. [#3289](https://github.com/PyO3/pyo3/pull/3289) ### Added - Add `pyo3::types::PyFrozenSetBuilder` to allow building a `PyFrozenSet` item by item. [#3156](https://github.com/PyO3/pyo3/pull/3156) - Add support for converting to and from Python's `ipaddress.IPv4Address`/`ipaddress.IPv6Address` and `std::net::IpAddr`. [#3197](https://github.com/PyO3/pyo3/pull/3197) - Add support for `num-bigint` feature in combination with `abi3`. [#3198](https://github.com/PyO3/pyo3/pull/3198) - Add `PyErr_GetRaisedException()`, `PyErr_SetRaisedException()` to FFI definitions for Python 3.12 and later. [#3248](https://github.com/PyO3/pyo3/pull/3248) - Add `Python::with_pool` which is a safer but more limited alternative to `Python::new_pool`. [#3263](https://github.com/PyO3/pyo3/pull/3263) - Add `PyDict::get_item_with_error` on PyPy. [#3270](https://github.com/PyO3/pyo3/pull/3270) - Allow `#[new]` methods may to return `Py` in order to return existing instances. [#3287](https://github.com/PyO3/pyo3/pull/3287) ### Fixed - Fix conversion of classes implementing `__complex__` to `Complex` when using `abi3` or PyPy. [#3185](https://github.com/PyO3/pyo3/pull/3185) - Stop suppressing unrelated exceptions in `PyAny::hasattr`. [#3271](https://github.com/PyO3/pyo3/pull/3271) - Fix memory leak when creating `PySet` or `PyFrozenSet` or returning types converted into these internally, e.g. `HashSet` or `BTreeSet`. [#3286](https://github.com/PyO3/pyo3/pull/3286) ## [0.19.0] - 2023-05-31 ### Packaging - Correct dependency on syn to version 1.0.85 instead of the incorrect version 1.0.56. [#3152](https://github.com/PyO3/pyo3/pull/3152) ### Added - Accept `text_signature` option (and automatically generate signature) for `#[new]` in `#[pymethods]`. [#2980](https://github.com/PyO3/pyo3/pull/2980) - Add support for converting to and from Python's `decimal.Decimal` and `rust_decimal::Decimal`. [#3016](https://github.com/PyO3/pyo3/pull/3016) - Add `#[pyo3(from_item_all)]` when deriving `FromPyObject` to specify `get_item` as getter for all fields. [#3120](https://github.com/PyO3/pyo3/pull/3120) - Add `pyo3::exceptions::PyBaseExceptionGroup` for Python 3.11, and corresponding FFI definition `PyExc_BaseExceptionGroup`. [#3141](https://github.com/PyO3/pyo3/pull/3141) - Accept `#[new]` with `#[classmethod]` to create a constructor which receives a (subtype's) class/`PyType` as its first argument. [#3157](https://github.com/PyO3/pyo3/pull/3157) - Add `PyClass::get` and `Py::get` for GIL-indepedent access to classes with `#[pyclass(frozen)]`. [#3158](https://github.com/PyO3/pyo3/pull/3158) - Add `PyAny::is_exact_instance` and `PyAny::is_exact_instance_of`. [#3161](https://github.com/PyO3/pyo3/pull/3161) ### Changed - `PyAny::is_instance_of::(obj)` is now equivalent to `T::is_type_of(obj)`, and now returns `bool` instead of `PyResult`. [#2881](https://github.com/PyO3/pyo3/pull/2881) - Deprecate `text_signature` option on `#[pyclass]` structs. [#2980](https://github.com/PyO3/pyo3/pull/2980) - No longer wrap `anyhow::Error`/`eyre::Report` containing a basic `PyErr` without a chain in a `PyRuntimeError`. [#3004](https://github.com/PyO3/pyo3/pull/3004) - - Change `#[getter]` and `#[setter]` to use a common call "trampoline" to slightly reduce generated code size and compile times. [#3029](https://github.com/PyO3/pyo3/pull/3029) - Improve default values for str, numbers and bool in automatically-generated `text_signature`. [#3050](https://github.com/PyO3/pyo3/pull/3050) - Improve default value for `None` in automatically-generated `text_signature`. [#3066](https://github.com/PyO3/pyo3/pull/3066) - Rename `PySequence::list` and `PySequence::tuple` to `PySequence::to_list` and `PySequence::to_tuple`. (The old names continue to exist as deprecated forms.) [#3111](https://github.com/PyO3/pyo3/pull/3111) - Extend the lifetime of the GIL token returned by `PyRef::py` and `PyRefMut::py` to match the underlying borrow. [#3131](https://github.com/PyO3/pyo3/pull/3131) - Safe access to the GIL, for example via `Python::with_gil`, is now locked inside of implementations of the `__traverse__` slot. [#3168](https://github.com/PyO3/pyo3/pull/3168) ### Removed - Remove all functionality deprecated in PyO3 0.17, most prominently `Python::acquire_gil` is replaced by `Python::with_gil`. [#2981](https://github.com/PyO3/pyo3/pull/2981) ### Fixed - Correct FFI definitions `PyGetSetDef`, `PyMemberDef`, `PyStructSequence_Field` and `PyStructSequence_Desc` to have `*const c_char` members for `name` and `doc` (not `*mut c_char`). [#3036](https://github.com/PyO3/pyo3/pull/3036) - Fix panic on `fmt::Display`, instead return `""` string and report error via `sys.unraisablehook()` [#3062](https://github.com/PyO3/pyo3/pull/3062) - Fix a compile error of "temporary value dropped while borrowed" when `#[pyfunction]`s take references into `#[pyclass]`es [#3142](https://github.com/PyO3/pyo3/pull/3142) - Fix crashes caused by PyO3 applying deferred reference count updates when entering a `__traverse__` implementation. [#3168](https://github.com/PyO3/pyo3/pull/3168) - Forbid running the `Drop` implementations of unsendable classes on other threads. [#3176](https://github.com/PyO3/pyo3/pull/3176) - Fix a compile error when `#[pymethods]` items come from somewhere else (for example, as a macro argument) and a custom receiver like `Py` is used. [#3178](https://github.com/PyO3/pyo3/pull/3178) ## [0.18.3] - 2023-04-13 ### Added - Add `GILProtected` to mediate concurrent access to a value using Python's global interpreter lock (GIL). [#2975](https://github.com/PyO3/pyo3/pull/2975) - Support `PyASCIIObject` / `PyUnicode` and associated methods on big-endian architectures. [#3015](https://github.com/PyO3/pyo3/pull/3015) - Add FFI definition `_PyDict_Contains_KnownHash()` for CPython 3.10 and up. [#3088](https://github.com/PyO3/pyo3/pull/3088) ### Fixed - Fix compile error for `#[pymethods]` and `#[pyfunction]` called "output". [#3022](https://github.com/PyO3/pyo3/pull/3022) - Fix compile error in generated code for magic methods implemented as a `#[staticmethod]`. [#3055](https://github.com/PyO3/pyo3/pull/3055) - Fix `is_instance` for `PyDateTime` (would incorrectly check for a `PyDate`). [#3071](https://github.com/PyO3/pyo3/pull/3071) - Fix upstream deprecation of `PyUnicode_InternImmortal` since Python 3.10. [#3071](https://github.com/PyO3/pyo3/pull/3087) ## [0.18.2] - 2023-03-24 ### Packaging - Disable default features of `chrono` to avoid depending on `time` v0.1.x. [#2939](https://github.com/PyO3/pyo3/pull/2939) ### Added - Implement `IntoPy`, `ToPyObject` and `FromPyObject` for `Cow<[u8]>` to efficiently handle both `bytes` and `bytearray` objects. [#2899](https://github.com/PyO3/pyo3/pull/2899) - Implement `IntoPy`, `ToPyObject` and `FromPyObject` for `Cell`. [#3014](https://github.com/PyO3/pyo3/pull/3014) - Add `PyList::to_tuple()`, as a convenient and efficient conversion from lists to tuples. [#3042](https://github.com/PyO3/pyo3/pull/3042) - Add `PyTuple::to_list()`, as a convenient and efficient conversion from tuples to lists. [#3044](https://github.com/PyO3/pyo3/pull/3044) ### Changed - Optimize `PySequence` conversion for `list` and `tuple` inputs. [#2944](https://github.com/PyO3/pyo3/pull/2944) - Improve exception raised when creating `#[pyclass]` type object fails during module import. [#2947](https://github.com/PyO3/pyo3/pull/2947) - Optimize `PyMapping` conversion for `dict` inputs. [#2954](https://github.com/PyO3/pyo3/pull/2954) - Allow `create_exception!` to take a `dotted.module` to place the exception in a submodule. [#2979](https://github.com/PyO3/pyo3/pull/2979) ### Fixed - Fix a reference counting race condition affecting `PyObject`s cloned in `allow_threads` blocks. [#2952](https://github.com/PyO3/pyo3/pull/2952) - Fix `clippy::redundant_closure` lint on default arguments in `#[pyo3(signature = (...))]` annotations. [#2990](https://github.com/PyO3/pyo3/pull/2990) - Fix `non_snake_case` lint on generated code in `#[pyfunction]` macro. [#2993](https://github.com/PyO3/pyo3/pull/2993) - Fix some FFI definitions for the upcoming PyPy 3.10 release. [#3031](https://github.com/PyO3/pyo3/pull/3031) ## [0.18.1] - 2023-02-07 ### Added - Add `PyErr::write_unraisable()`. [#2889](https://github.com/PyO3/pyo3/pull/2889) - Add `Python::Ellipsis()` and `PyAny::is_ellipsis()` methods. [#2911](https://github.com/PyO3/pyo3/pull/2911) - Add `PyDict::update()` and `PyDict::update_if_missing()` methods. [#2912](https://github.com/PyO3/pyo3/pull/2912) ### Changed - FFI definition `PyIter_Check` on CPython 3.7 is now implemented as `hasattr(type(obj), "__next__")`, which works correctly on all platforms and adds support for `abi3`. [#2914](https://github.com/PyO3/pyo3/pull/2914) - Warn about unknown config keys in `PYO3_CONFIG_FILE` instead of denying. [#2926](https://github.com/PyO3/pyo3/pull/2926) ### Fixed - Send errors returned by `__releasebuffer__` to `sys.unraisablehook` rather than causing `SystemError`. [#2886](https://github.com/PyO3/pyo3/pull/2886) - Fix downcast to `PyIterator` succeeding for Python classes which did not implement `__next__`. [#2914](https://github.com/PyO3/pyo3/pull/2914) - Fix segfault in `__traverse__` when visiting `None` fields of `Option`. [#2921](https://github.com/PyO3/pyo3/pull/2921) - Fix `#[pymethods(crate = "...")]` option being ignored. [#2923](https://github.com/PyO3/pyo3/pull/2923) - Link against `pythonXY_d.dll` for debug Python builds on Windows. [#2937](https://github.com/PyO3/pyo3/pull/2937) ## [0.18.0] - 2023-01-17 ### Packaging - Relax `indexmap` optional depecency to allow `>= 1.6, < 2`. [#2849](https://github.com/PyO3/pyo3/pull/2849) - Relax `hashbrown` optional dependency to allow `>= 0.9, < 0.14`. [#2875](https://github.com/PyO3/pyo3/pull/2875) - Update `memoffset` dependency to 0.8. [#2875](https://github.com/PyO3/pyo3/pull/2875) ### Added - Add `GILOnceCell::get_or_try_init` for fallible `GILOnceCell` initialization. [#2398](https://github.com/PyO3/pyo3/pull/2398) - Add experimental feature `experimental-inspect` with `type_input()` and `type_output()` helpers to get the Python type of any Python-compatible object. [#2490](https://github.com/PyO3/pyo3/pull/2490) [#2882](https://github.com/PyO3/pyo3/pull/2882) - The `#[pyclass]` macro can now take `get_all` and `set_all` to create getters and setters for every field. [#2692](https://github.com/PyO3/pyo3/pull/2692) - Add `#[pyo3(signature = (...))]` option for `#[pyfunction]` and `#[pymethods]`. [#2702](https://github.com/PyO3/pyo3/pull/2702) - `pyo3-build-config`: rebuild when `PYO3_ENVIRONMENT_SIGNATURE` environment variable value changes. [#2727](https://github.com/PyO3/pyo3/pull/2727) - Add conversions between non-zero int types in `std::num` and Python `int`. [#2730](https://github.com/PyO3/pyo3/pull/2730) - Add `Py::downcast()` as a companion to `PyAny::downcast()`, as well as `downcast_unchecked()` for both types. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Add types for all built-in `Warning` classes as well as `PyErr::warn_explicit`. [#2742](https://github.com/PyO3/pyo3/pull/2742) - Add `abi3-py311` feature. [#2776](https://github.com/PyO3/pyo3/pull/2776) - Add FFI definition `_PyErr_ChainExceptions()` for CPython. [#2788](https://github.com/PyO3/pyo3/pull/2788) - Add FFI definitions `PyVectorcall_NARGS` and `PY_VECTORCALL_ARGUMENTS_OFFSET` for PyPy 3.8 and up. [#2811](https://github.com/PyO3/pyo3/pull/2811) - Add `PyList::get_item_unchecked` for PyPy. [#2827](https://github.com/PyO3/pyo3/pull/2827) ### Changed - PyO3's macros now emit a much nicer error message if function return values don't implement the required trait(s). [#2664](https://github.com/PyO3/pyo3/pull/2664) - Use a TypeError, rather than a ValueError, when refusing to treat a str as a Vec. [#2685](https://github.com/PyO3/pyo3/pull/2685) - Change `PyCFunction::new_closure` to take `name` and `doc` arguments. [#2686](https://github.com/PyO3/pyo3/pull/2686) - `PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now take `&PyAny` instead of `&PyType` arguments, so that they work with objects that pretend to be types using `__subclasscheck__` and `__instancecheck__`. [#2695](https://github.com/PyO3/pyo3/pull/2695) - Deprecate `#[args]` attribute and passing "args" specification directly to `#[pyfunction]` in favor of the new `#[pyo3(signature = (...))]` option. [#2702](https://github.com/PyO3/pyo3/pull/2702) - Deprecate required arguments after `Option` arguments to `#[pyfunction]` and `#[pymethods]` without also using `#[pyo3(signature)]` to specify whether the arguments should be required or have defaults. [#2703](https://github.com/PyO3/pyo3/pull/2703) - Change `#[pyfunction]` and `#[pymethods]` to use a common call "trampoline" to slightly reduce generated code size and compile times. [#2705](https://github.com/PyO3/pyo3/pull/2705) - `PyAny::cast_as()` and `Py::cast_as()` are now deprecated in favor of `PyAny::downcast()` and the new `Py::downcast()`. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Relax lifetime bounds on `PyAny::downcast()`. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Automatically generate `__text_signature__` for all Python functions created using `#[pyfunction]` and `#[pymethods]`. [#2784](https://github.com/PyO3/pyo3/pull/2784) - Accept any iterator in `PySet::new` and `PyFrozenSet::new`. [#2795](https://github.com/PyO3/pyo3/pull/2795) - Mixing `#[cfg(...)]` and `#[pyo3(...)]` attributes on `#[pyclass]` struct fields will now work. [#2796](https://github.com/PyO3/pyo3/pull/2796) - Re-enable `PyFunction` on when building for abi3 or PyPy. [#2838](https://github.com/PyO3/pyo3/pull/2838) - Improve `derive(FromPyObject)` to use `intern!` when applicable for `#[pyo3(item)]`. [#2879](https://github.com/PyO3/pyo3/pull/2879) ### Removed - Remove the deprecated `pyproto` feature, `#[pyproto]` macro, and all accompanying APIs. [#2587](https://github.com/PyO3/pyo3/pull/2587) - Remove all functionality deprecated in PyO3 0.16. [#2843](https://github.com/PyO3/pyo3/pull/2843) ### Fixed - Disable `PyModule::filename` on PyPy. [#2715](https://github.com/PyO3/pyo3/pull/2715) - `PyCodeObject` is now once again defined with fields on Python 3.7. [#2726](https://github.com/PyO3/pyo3/pull/2726) - Raise a `TypeError` if `#[new]` pymethods with no arguments receive arguments when called from Python. [#2749](https://github.com/PyO3/pyo3/pull/2749) - Use the `NOARGS` argument calling convention for methods that have a single `py: Python` argument (as a performance optimization). [#2760](https://github.com/PyO3/pyo3/pull/2760) - Fix truncation of `isize` values to `c_long` in `PySlice::new`. [#2769](https://github.com/PyO3/pyo3/pull/2769) - Fix soundness issue with FFI definition `PyUnicodeDecodeError_Create` on PyPy leading to indeterminate behavior (typically a `TypeError`). [#2772](https://github.com/PyO3/pyo3/pull/2772) - Allow functions taking `**kwargs` to accept keyword arguments which share a name with a positional-only argument (as permitted by PEP 570). [#2800](https://github.com/PyO3/pyo3/pull/2800) - Fix unresolved symbol for `PyObject_Vectorcall` on PyPy 3.9 and up. [#2811](https://github.com/PyO3/pyo3/pull/2811) - Fix memory leak in `PyCFunction::new_closure`. [#2842](https://github.com/PyO3/pyo3/pull/2842) ## [0.17.3] - 2022-11-01 ### Packaging - Support Python 3.11. (Previous versions of PyO3 0.17 have been tested against Python 3.11 release candidates and are expected to be compatible, this is the first version tested against Python 3.11.0.) [#2708](https://github.com/PyO3/pyo3/pull/2708) ### Added - Implemented `ExactSizeIterator` for `PyListIterator`, `PyDictIterator`, `PySetIterator` and `PyFrozenSetIterator`. [#2676](https://github.com/PyO3/pyo3/pull/2676) ### Fixed - Fix regression of `impl FromPyObject for [T; N]` no longer accepting types passing `PySequence_Check`, e.g. NumPy arrays, since version 0.17.0. This the same fix that was applied `impl FromPyObject for Vec` in version 0.17.1 extended to fixed-size arrays. [#2675](https://github.com/PyO3/pyo3/pull/2675) - Fix UB in `FunctionDescription::extract_arguments_fastcall` due to creating slices from a null pointer. [#2687](https://github.com/PyO3/pyo3/pull/2687) ## [0.17.2] - 2022-10-04 ### Packaging - Added optional `chrono` feature to convert `chrono` types into types in the `datetime` module. [#2612](https://github.com/PyO3/pyo3/pull/2612) ### Added - Add support for `num-bigint` feature on `PyPy`. [#2626](https://github.com/PyO3/pyo3/pull/2626) ### Fixed - Correctly implement `__richcmp__` for enums, fixing `__ne__` returning always returning `True`. [#2622](https://github.com/PyO3/pyo3/pull/2622) - Fix compile error since 0.17.0 with `Option<&SomePyClass>` argument with a default. [#2630](https://github.com/PyO3/pyo3/pull/2630) - Fix regression of `impl FromPyObject for Vec` no longer accepting types passing `PySequence_Check`, e.g. NumPy arrays, since 0.17.0. [#2631](https://github.com/PyO3/pyo3/pull/2631) ## [0.17.1] - 2022-08-28 ### Fixed - Fix visibility of `PyDictItems`, `PyDictKeys`, and `PyDictValues` types added in PyO3 0.17.0. - Fix compile failure when using `#[pyo3(from_py_with = "...")]` attribute on an argument of type `Option`. [#2592](https://github.com/PyO3/pyo3/pull/2592) - Fix clippy `redundant-closure` lint on `**kwargs` arguments for `#[pyfunction]` and `#[pymethods]`. [#2595](https://github.com/PyO3/pyo3/pull/2595) ## [0.17.0] - 2022-08-23 ### Packaging - Update inventory dependency to `0.3` (the `multiple-pymethods` feature now requires Rust 1.62 for correctness). [#2492](https://github.com/PyO3/pyo3/pull/2492) ### Added - Add `timezone_utc`. [#1588](https://github.com/PyO3/pyo3/pull/1588) - Implement `ToPyObject` for `[T; N]`. [#2313](https://github.com/PyO3/pyo3/pull/2313) - Add `PyDictKeys`, `PyDictValues` and `PyDictItems` Rust types. [#2358](https://github.com/PyO3/pyo3/pull/2358) - Add `append_to_inittab`. [#2377](https://github.com/PyO3/pyo3/pull/2377) - Add FFI definition `PyFrame_GetCode`. [#2406](https://github.com/PyO3/pyo3/pull/2406) - Add `PyCode` and `PyFrame` high level objects. [#2408](https://github.com/PyO3/pyo3/pull/2408) - Add FFI definitions `Py_fstring_input`, `sendfunc`, and `_PyErr_StackItem`. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Add `PyDateTime::new_with_fold`, `PyTime::new_with_fold`, `PyTime::get_fold`, and `PyDateTime::get_fold` for PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Add `#[pyclass(frozen)]`. [#2448](https://github.com/PyO3/pyo3/pull/2448) - Accept `#[pyo3(name)]` on enum variants. [#2457](https://github.com/PyO3/pyo3/pull/2457) - Add `CompareOp::matches` to implement `__richcmp__` as the result of a Rust `std::cmp::Ordering` comparison. [#2460](https://github.com/PyO3/pyo3/pull/2460) - Add `PySuper` type. [#2486](https://github.com/PyO3/pyo3/pull/2486) - Support PyPy on Windows with the `generate-import-lib` feature. [#2506](https://github.com/PyO3/pyo3/pull/2506) - Add FFI definitions `Py_EnterRecursiveCall` and `Py_LeaveRecursiveCall`. [#2511](https://github.com/PyO3/pyo3/pull/2511) - Add `PyDict::get_item_with_error`. [#2536](https://github.com/PyO3/pyo3/pull/2536) - Add `#[pyclass(sequence)]` option. [#2567](https://github.com/PyO3/pyo3/pull/2567) ### Changed - Change datetime constructors taking a `tzinfo` to take `Option<&PyTzInfo>` instead of `Option<&PyObject>`: `PyDateTime::new`, `PyDateTime::new_with_fold`, `PyTime::new`, and `PyTime::new_with_fold`. [#1588](https://github.com/PyO3/pyo3/pull/1588) - Move `PyTypeObject::type_object` method to the `PyTypeInfo` trait, and deprecate the `PyTypeObject` trait. [#2287](https://github.com/PyO3/pyo3/pull/2287) - Methods of `Py` and `PyAny` now accept `impl IntoPy>` rather than just `&str` to allow use of the `intern!` macro. [#2312](https://github.com/PyO3/pyo3/pull/2312) - Change the deprecated `pyproto` feature to be opt-in instead of opt-out. [#2322](https://github.com/PyO3/pyo3/pull/2322) - Emit better error messages when `#[pyfunction]` return types do not implement `IntoPy`. [#2326](https://github.com/PyO3/pyo3/pull/2326) - Require `T: IntoPy` for `impl IntoPy for [T; N]` instead of `T: ToPyObject`. [#2326](https://github.com/PyO3/pyo3/pull/2326) - Deprecate the `ToBorrowedObject` trait. [#2333](https://github.com/PyO3/pyo3/pull/2333) - Iterators over `PySet` and `PyDict` will now panic if the underlying collection is mutated during the iteration. [#2380](https://github.com/PyO3/pyo3/pull/2380) - Iterators over `PySet` and `PyDict` will now panic if the underlying collection is mutated during the iteration. [#2380](https://github.com/PyO3/pyo3/pull/2380) - Allow `#[classattr]` methods to be fallible. [#2385](https://github.com/PyO3/pyo3/pull/2385) - Prevent multiple `#[pymethods]` with the same name for a single `#[pyclass]`. [#2399](https://github.com/PyO3/pyo3/pull/2399) - Fixup `lib_name` when using `PYO3_CONFIG_FILE`. [#2404](https://github.com/PyO3/pyo3/pull/2404) - Add a message to the `ValueError` raised by the `#[derive(FromPyObject)]` implementation for a tuple struct. [#2414](https://github.com/PyO3/pyo3/pull/2414) - Allow `#[classattr]` methods to take `Python` argument. [#2456](https://github.com/PyO3/pyo3/pull/2456) - Rework `PyCapsule` type to resolve soundness issues: [#2485](https://github.com/PyO3/pyo3/pull/2485) - `PyCapsule::new` and `PyCapsule::new_with_destructor` now take `name: Option` instead of `&CStr`. - The destructor `F` in `PyCapsule::new_with_destructor` must now be `Send`. - `PyCapsule::get_context` deprecated in favor of `PyCapsule::context` which doesn't take a `py: Python<'_>` argument. - `PyCapsule::set_context` no longer takes a `py: Python<'_>` argument. - `PyCapsule::name` now returns `PyResult>` instead of `&CStr`. - `FromPyObject::extract` for `Vec` no longer accepts Python `str` inputs. [#2500](https://github.com/PyO3/pyo3/pull/2500) - Ensure each `#[pymodule]` is only initialized once. [#2523](https://github.com/PyO3/pyo3/pull/2523) - `pyo3_build_config::add_extension_module_link_args` now also emits linker arguments for `wasm32-unknown-emscripten`. [#2538](https://github.com/PyO3/pyo3/pull/2538) - Type checks for `PySequence` and `PyMapping` now require inputs to inherit from (or register with) `collections.abc.Sequence` and `collections.abc.Mapping` respectively. [#2477](https://github.com/PyO3/pyo3/pull/2477) - Disable `PyFunction` on when building for abi3 or PyPy. [#2542](https://github.com/PyO3/pyo3/pull/2542) - Deprecate `Python::acquire_gil`. [#2549](https://github.com/PyO3/pyo3/pull/2549) ### Removed - Remove all functionality deprecated in PyO3 0.15. [#2283](https://github.com/PyO3/pyo3/pull/2283) - Make the `Dict`, `WeakRef` and `BaseNativeType` members of the `PyClass` private implementation details. [#2572](https://github.com/PyO3/pyo3/pull/2572) ### Fixed - Enable incorrectly disabled FFI definition `PyThreadState_DeleteCurrent`. [#2357](https://github.com/PyO3/pyo3/pull/2357) - Fix `wrap_pymodule` interactions with name resolution rules: it no longer "sees through" glob imports of `use submodule::*` when `submodule::submodule` is a `#[pymodule]`. [#2363](https://github.com/PyO3/pyo3/pull/2363) - Correct FFI definition `PyEval_EvalCodeEx` to take `*const *mut PyObject` array arguments instead of `*mut *mut PyObject`. [#2368](https://github.com/PyO3/pyo3/pull/2368) - Fix "raw-ident" structs (e.g. `#[pyclass] struct r#RawName`) incorrectly having `r#` at the start of the class name created in Python. [#2395](https://github.com/PyO3/pyo3/pull/2395) - Correct FFI definition `Py_tracefunc` to be `unsafe extern "C" fn` (was previously safe). [#2407](https://github.com/PyO3/pyo3/pull/2407) - Fix compile failure with `#[pyo3(from_py_with = "...")]` annotations on a field in a `#[derive(FromPyObject)]` struct. [#2414](https://github.com/PyO3/pyo3/pull/2414) - Fix FFI definitions `_PyDateTime_BaseTime` and `_PyDateTime_BaseDateTime` lacking leading underscores in their names. [#2421](https://github.com/PyO3/pyo3/pull/2421) - Remove FFI definition `PyArena` on Python 3.10 and up. [#2421](https://github.com/PyO3/pyo3/pull/2421) - Fix FFI definition `PyCompilerFlags` missing member `cf_feature_version` on Python 3.8 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyAsyncMethods` missing member `am_send` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyGenObject` having multiple incorrect members on various Python versions. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PySyntaxErrorObject` missing members `end_lineno` and `end_offset` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyHeapTypeObject` missing member `ht_module` on Python 3.9 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyFrameObject` having multiple incorrect members on various Python versions. [#2424](https://github.com/PyO3/pyo3/pull/2424) [#2434](https://github.com/PyO3/pyo3/pull/2434) - Fix FFI definition `PyTypeObject` missing deprecated field `tp_print` on Python 3.8. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Fix FFI definitions `PyDateTime_CAPI`. `PyDateTime_Date`, `PyASCIIObject`, `PyBaseExceptionObject`, `PyListObject`, and `PyTypeObject` on PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Fix FFI definition `_inittab` field `initfunc` typo'd as `initfun`. [#2431](https://github.com/PyO3/pyo3/pull/2431) - Fix FFI definitions `_PyDateTime_BaseTime` and `_PyDateTime_BaseDateTime` incorrectly having `fold` member. [#2432](https://github.com/PyO3/pyo3/pull/2432) - Fix FFI definitions `PyTypeObject`. `PyHeapTypeObject`, and `PyCFunctionObject` having incorrect members on PyPy 3.9. [#2433](https://github.com/PyO3/pyo3/pull/2433) - Fix FFI definition `PyGetSetDef` to have `*const c_char` for `doc` member (not `*mut c_char`). [#2439](https://github.com/PyO3/pyo3/pull/2439) - Fix `#[pyo3(from_py_with = "...")]` being ignored for 1-element tuple structs and transparent structs. [#2440](https://github.com/PyO3/pyo3/pull/2440) - Use `memoffset` to avoid UB when computing `PyCell` layout. [#2450](https://github.com/PyO3/pyo3/pull/2450) - Fix incorrect enum names being returned by the generated `repr` for enums renamed by `#[pyclass(name = "...")]` [#2457](https://github.com/PyO3/pyo3/pull/2457) - Fix `PyObject_CallNoArgs` incorrectly being available when building for abi3 on Python 3.9. [#2476](https://github.com/PyO3/pyo3/pull/2476) - Fix several clippy warnings generated by `#[pyfunction]` arguments. [#2503](https://github.com/PyO3/pyo3/pull/2503) ## [0.16.6] - 2022-08-23 ### Changed - Fix soundness issues with `PyCapsule` type with select workarounds. Users are encourage to upgrade to PyO3 0.17 at their earliest convenience which contains API breakages which fix the issues in a long-term fashion. [#2522](https://github.com/PyO3/pyo3/pull/2522) - `PyCapsule::new` and `PyCapsule::new_with_destructor` now take ownership of a copy of the `name` to resolve a possible use-after-free. - `PyCapsule::name` now returns an empty `CStr` instead of dereferencing a null pointer if the capsule has no name. - The destructor `F` in `PyCapsule::new_with_destructor` will never be called if the capsule is deleted from a thread other than the one which the capsule was created in (a warning will be emitted). - Panics during drop of panic payload caught by PyO3 will now abort. [#2544](https://github.com/PyO3/pyo3/pull/2544) ## [0.16.5] - 2022-05-15 ### Added - Add an experimental `generate-import-lib` feature to support auto-generating non-abi3 python import libraries for Windows targets. [#2364](https://github.com/PyO3/pyo3/pull/2364) - Add FFI definition `Py_ExitStatusException`. [#2374](https://github.com/PyO3/pyo3/pull/2374) ### Changed - Deprecate experimental `generate-abi3-import-lib` feature in favor of the new `generate-import-lib` feature. [#2364](https://github.com/PyO3/pyo3/pull/2364) ### Fixed - Added missing `warn_default_encoding` field to `PyConfig` on 3.10+. The previously missing field could result in incorrect behavior or crashes. [#2370](https://github.com/PyO3/pyo3/pull/2370) - Fixed order of `pathconfig_warnings` and `program_name` fields of `PyConfig` on 3.10+. Previously, the order of the fields was swapped and this could lead to incorrect behavior or crashes. [#2370](https://github.com/PyO3/pyo3/pull/2370) ## [0.16.4] - 2022-04-14 ### Added - Add `PyTzInfoAccess` trait for safe access to time zone information. [#2263](https://github.com/PyO3/pyo3/pull/2263) - Add an experimental `generate-abi3-import-lib` feature to auto-generate `python3.dll` import libraries for Windows. [#2282](https://github.com/PyO3/pyo3/pull/2282) - Add FFI definitions for `PyDateTime_BaseTime` and `PyDateTime_BaseDateTime`. [#2294](https://github.com/PyO3/pyo3/pull/2294) ### Changed - Improved performance of failing calls to `FromPyObject::extract` which is common when functions accept multiple distinct types. [#2279](https://github.com/PyO3/pyo3/pull/2279) - Default to "m" ABI tag when choosing `libpython` link name for CPython 3.7 on Unix. [#2288](https://github.com/PyO3/pyo3/pull/2288) - Allow to compile "abi3" extensions without a working build host Python interpreter. [#2293](https://github.com/PyO3/pyo3/pull/2293) ### Fixed - Crates depending on PyO3 can collect code coverage via LLVM instrumentation using stable Rust. [#2286](https://github.com/PyO3/pyo3/pull/2286) - Fix segfault when calling FFI methods `PyDateTime_DATE_GET_TZINFO` or `PyDateTime_TIME_GET_TZINFO` on `datetime` or `time` without a tzinfo. [#2289](https://github.com/PyO3/pyo3/pull/2289) - Fix directory names starting with the letter `n` breaking serialization of the interpreter configuration on Windows since PyO3 0.16.3. [#2299](https://github.com/PyO3/pyo3/pull/2299) ## [0.16.3] - 2022-04-05 ### Packaging - Extend `parking_lot` dependency supported versions to include 0.12. [#2239](https://github.com/PyO3/pyo3/pull/2239) ### Added - Add methods to `pyo3_build_config::InterpreterConfig` to run Python scripts using the configured executable. [#2092](https://github.com/PyO3/pyo3/pull/2092) - Add `as_bytes` method to `Py`. [#2235](https://github.com/PyO3/pyo3/pull/2235) - Add FFI definitions for `PyType_FromModuleAndSpec`, `PyType_GetModule`, `PyType_GetModuleState` and `PyModule_AddType`. [#2250](https://github.com/PyO3/pyo3/pull/2250) - Add `pyo3_build_config::cross_compiling_from_to` as a helper to detect when PyO3 is cross-compiling. [#2253](https://github.com/PyO3/pyo3/pull/2253) - Add `#[pyclass(mapping)]` option to leave sequence slots empty in container implementations. [#2265](https://github.com/PyO3/pyo3/pull/2265) - Add `PyString::intern` to enable usage of the Python's built-in string interning. [#2268](https://github.com/PyO3/pyo3/pull/2268) - Add `intern!` macro which can be used to amortize the cost of creating Python strings by storing them inside a `GILOnceCell`. [#2269](https://github.com/PyO3/pyo3/pull/2269) - Add `PYO3_CROSS_PYTHON_IMPLEMENTATION` environment variable for selecting the default cross Python implementation. [#2272](https://github.com/PyO3/pyo3/pull/2272) ### Changed - Allow `#[pyo3(crate = "...", text_signature = "...")]` options to be used directly in `#[pyclass(crate = "...", text_signature = "...")]`. [#2234](https://github.com/PyO3/pyo3/pull/2234) - Make `PYO3_CROSS_LIB_DIR` environment variable optional when cross compiling. [#2241](https://github.com/PyO3/pyo3/pull/2241) - Mark `METH_FASTCALL` calling convention as limited API on Python 3.10. [#2250](https://github.com/PyO3/pyo3/pull/2250) - Deprecate `pyo3_build_config::cross_compiling` in favor of `pyo3_build_config::cross_compiling_from_to`. [#2253](https://github.com/PyO3/pyo3/pull/2253) ### Fixed - Fix `abi3-py310` feature: use Python 3.10 ABI when available instead of silently falling back to the 3.9 ABI. [#2242](https://github.com/PyO3/pyo3/pull/2242) - Use shared linking mode when cross compiling against a [Framework bundle](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html) for macOS. [#2233](https://github.com/PyO3/pyo3/pull/2233) - Fix panic during compilation when `PYO3_CROSS_LIB_DIR` is set for some host/target combinations. [#2232](https://github.com/PyO3/pyo3/pull/2232) - Correct dependency version for `syn` to require minimal patch version 1.0.56. [#2240](https://github.com/PyO3/pyo3/pull/2240) ## [0.16.2] - 2022-03-15 ### Packaging - Warn when modules are imported on PyPy 3.7 versions older than PyPy 7.3.8, as they are known to have binary compatibility issues. [#2217](https://github.com/PyO3/pyo3/pull/2217) - Ensure build script of `pyo3-ffi` runs before that of `pyo3` to fix cross compilation. [#2224](https://github.com/PyO3/pyo3/pull/2224) ## [0.16.1] - 2022-03-05 ### Packaging - Extend `hashbrown` optional dependency supported versions to include 0.12. [#2197](https://github.com/PyO3/pyo3/pull/2197) ### Fixed - Fix incorrect platform detection for Windows in `pyo3-build-config`. [#2198](https://github.com/PyO3/pyo3/pull/2198) - Fix regression from 0.16 preventing cross compiling to aarch64 macOS. [#2201](https://github.com/PyO3/pyo3/pull/2201) ## [0.16.0] - 2022-02-27 ### Packaging - Update MSRV to Rust 1.48. [#2004](https://github.com/PyO3/pyo3/pull/2004) - Update `indoc` optional dependency to 1.0. [#2004](https://github.com/PyO3/pyo3/pull/2004) - Drop support for Python 3.6, remove `abi3-py36` feature. [#2006](https://github.com/PyO3/pyo3/pull/2006) - `pyo3-build-config` no longer enables the `resolve-config` feature by default. [#2008](https://github.com/PyO3/pyo3/pull/2008) - Update `inventory` optional dependency to 0.2. [#2019](https://github.com/PyO3/pyo3/pull/2019) - Drop `paste` dependency. [#2081](https://github.com/PyO3/pyo3/pull/2081) - The bindings found in `pyo3::ffi` are now a re-export of a separate `pyo3-ffi` crate. [#2126](https://github.com/PyO3/pyo3/pull/2126) - Support PyPy 3.9. [#2143](https://github.com/PyO3/pyo3/pull/2143) ### Added - Add `PyCapsule` type exposing the [Capsule API](https://docs.python.org/3/c-api/capsule.html#capsules). [#1980](https://github.com/PyO3/pyo3/pull/1980) - Add `pyo3_build_config::Sysconfigdata` and supporting APIs. [#1996](https://github.com/PyO3/pyo3/pull/1996) - Add `Py::setattr` method. [#2009](https://github.com/PyO3/pyo3/pull/2009) - Add `#[pyo3(crate = "some::path")]` option to all attribute macros (except the deprecated `#[pyproto]`). [#2022](https://github.com/PyO3/pyo3/pull/2022) - Enable `create_exception!` macro to take an optional docstring. [#2027](https://github.com/PyO3/pyo3/pull/2027) - Enable `#[pyclass]` for fieldless (aka C-like) enums. [#2034](https://github.com/PyO3/pyo3/pull/2034) - Add buffer magic methods `__getbuffer__` and `__releasebuffer__` to `#[pymethods]`. [#2067](https://github.com/PyO3/pyo3/pull/2067) - Add support for paths in `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Enable `wrap_pyfunction!` to wrap a `#[pyfunction]` implemented in a different Rust module or crate. [#2091](https://github.com/PyO3/pyo3/pull/2091) - Add `PyAny::contains` method (`in` operator for `PyAny`). [#2115](https://github.com/PyO3/pyo3/pull/2115) - Add `PyMapping::contains` method (`in` operator for `PyMapping`). [#2133](https://github.com/PyO3/pyo3/pull/2133) - Add garbage collection magic magic methods `__traverse__` and `__clear__` to `#[pymethods]`. [#2159](https://github.com/PyO3/pyo3/pull/2159) - Add support for `from_py_with` on struct tuples and enums to override the default from-Python conversion. [#2181](https://github.com/PyO3/pyo3/pull/2181) - Add `eq`, `ne`, `lt`, `le`, `gt`, `ge` methods to `PyAny` that wrap `rich_compare`. [#2175](https://github.com/PyO3/pyo3/pull/2175) - Add `Py::is` and `PyAny::is` methods to check for object identity. [#2183](https://github.com/PyO3/pyo3/pull/2183) - Add support for the `__getattribute__` magic method. [#2187](https://github.com/PyO3/pyo3/pull/2187) ### Changed - `PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now operate run-time type object instead of a type known at compile-time. The old behavior is still available as `PyType::is_subclass_of`, `PyErr::is_instance_of` and `PyAny::is_instance_of`. [#1985](https://github.com/PyO3/pyo3/pull/1985) - Rename some methods on `PyErr` (the old names are just marked deprecated for now): [#2026](https://github.com/PyO3/pyo3/pull/2026) - `pytype` -> `get_type` - `pvalue` -> `value` (and deprecate equivalent `instance`) - `ptraceback` -> `traceback` - `from_instance` -> `from_value` - `into_instance` -> `into_value` - `PyErr::new_type` now takes an optional docstring and now returns `PyResult>` rather than a `ffi::PyTypeObject` pointer. [#2027](https://github.com/PyO3/pyo3/pull/2027) - Deprecate `PyType::is_instance`; it is inconsistent with other `is_instance` methods in PyO3. Instead of `typ.is_instance(obj)`, use `obj.is_instance(typ)`. [#2031](https://github.com/PyO3/pyo3/pull/2031) - `__getitem__`, `__setitem__` and `__delitem__` in `#[pymethods]` now implement both a Python mapping and sequence by default. [#2065](https://github.com/PyO3/pyo3/pull/2065) - Improve performance and error messages for `#[derive(FromPyObject)]` for enums. [#2068](https://github.com/PyO3/pyo3/pull/2068) - Reduce generated LLVM code size (to improve compile times) for: - internal `handle_panic` helper [#2074](https://github.com/PyO3/pyo3/pull/2074) [#2158](https://github.com/PyO3/pyo3/pull/2158) - `#[pyfunction]` and `#[pymethods]` argument extraction [#2075](https://github.com/PyO3/pyo3/pull/2075) [#2085](https://github.com/PyO3/pyo3/pull/2085) - `#[pyclass]` type object creation [#2076](https://github.com/PyO3/pyo3/pull/2076) [#2081](https://github.com/PyO3/pyo3/pull/2081) [#2157](https://github.com/PyO3/pyo3/pull/2157) - Respect Rust privacy rules for items wrapped with `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Add modulo argument to `__ipow__` magic method. [#2083](https://github.com/PyO3/pyo3/pull/2083) - Fix FFI definition for `_PyCFunctionFast`. [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTimeAPI` and `PyDateTime_TimeZone_UTC` are now unsafe functions instead of statics. [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTimeAPI` does not implicitly call `PyDateTime_IMPORT` anymore to reflect the original Python API more closely. Before the first call to `PyDateTime_IMPORT` a null pointer is returned. Therefore before calling any of the following FFI functions `PyDateTime_IMPORT` must be called to avoid undefined behavior: [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTime_TimeZone_UTC` - `PyDate_Check` - `PyDate_CheckExact` - `PyDateTime_Check` - `PyDateTime_CheckExact` - `PyTime_Check` - `PyTime_CheckExact` - `PyDelta_Check` - `PyDelta_CheckExact` - `PyTZInfo_Check` - `PyTZInfo_CheckExact` - `PyDateTime_FromTimestamp` - `PyDate_FromTimestamp` - Deprecate the `gc` option for `pyclass` (e.g. `#[pyclass(gc)]`). Just implement a `__traverse__` `#[pymethod]`. [#2159](https://github.com/PyO3/pyo3/pull/2159) - The `ml_meth` field of `PyMethodDef` is now represented by the `PyMethodDefPointer` union. [2166](https://github.com/PyO3/pyo3/pull/2166) - Deprecate the `#[pyproto]` traits. [#2173](https://github.com/PyO3/pyo3/pull/2173) ### Removed - Remove all functionality deprecated in PyO3 0.14. [#2007](https://github.com/PyO3/pyo3/pull/2007) - Remove `Default` impl for `PyMethodDef`. [#2166](https://github.com/PyO3/pyo3/pull/2166) - Remove `PartialEq` impl for `Py` and `PyAny` (use the new `is` instead). [#2183](https://github.com/PyO3/pyo3/pull/2183) ### Fixed - Fix undefined symbol for `PyObject_HasAttr` on PyPy. [#2025](https://github.com/PyO3/pyo3/pull/2025) - Fix memory leak in `PyErr::into_value`. [#2026](https://github.com/PyO3/pyo3/pull/2026) - Fix clippy warning `needless-option-as-deref` in code generated by `#[pyfunction]` and `#[pymethods]`. [#2040](https://github.com/PyO3/pyo3/pull/2040) - Fix undefined behavior in `PySlice::indices`. [#2061](https://github.com/PyO3/pyo3/pull/2061) - Fix the `wrap_pymodule!` macro using the wrong name for a `#[pymodule]` with a `#[pyo3(name = "..")]` attribute. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Fix magic methods in `#[pymethods]` accepting implementations with the wrong number of arguments. [#2083](https://github.com/PyO3/pyo3/pull/2083) - Fix panic in `#[pyfunction]` generated code when a required argument following an `Option` was not provided. [#2093](https://github.com/PyO3/pyo3/pull/2093) - Fixed undefined behavior caused by incorrect `ExactSizeIterator` implementations. [#2124](https://github.com/PyO3/pyo3/pull/2124) - Fix missing FFI definition `PyCMethod_New` on Python 3.9 and up. [#2143](https://github.com/PyO3/pyo3/pull/2143) - Add missing FFI definitions `_PyLong_NumBits` and `_PyLong_AsByteArray` on PyPy. [#2146](https://github.com/PyO3/pyo3/pull/2146) - Fix memory leak in implementation of `AsPyPointer` for `Option`. [#2160](https://github.com/PyO3/pyo3/pull/2160) - Fix FFI definition of `_PyLong_NumBits` to return `size_t` instead of `c_int`. [#2161](https://github.com/PyO3/pyo3/pull/2161) - Fix `TypeError` thrown when argument parsing failed missing the originating causes. [2177](https://github.com/PyO3/pyo3/pull/2178) ## [0.15.2] - 2022-04-14 ### Packaging - Backport of PyPy 3.9 support from PyO3 0.16. [#2262](https://github.com/PyO3/pyo3/pull/2262) ## [0.15.1] - 2021-11-19 ### Added - Add implementations for `Py::as_ref` and `Py::into_ref` for `Py`, `Py` and `Py`. [#1682](https://github.com/PyO3/pyo3/pull/1682) - Add `PyTraceback` type to represent and format Python tracebacks. [#1977](https://github.com/PyO3/pyo3/pull/1977) ### Changed - `#[classattr]` constants with a known magic method name (which is lowercase) no longer trigger lint warnings expecting constants to be uppercase. [#1969](https://github.com/PyO3/pyo3/pull/1969) ### Fixed - Fix creating `#[classattr]` by functions with the name of a known magic method. [#1969](https://github.com/PyO3/pyo3/pull/1969) - Fix use of `catch_unwind` in `allow_threads` which can cause fatal crashes. [#1989](https://github.com/PyO3/pyo3/pull/1989) - Fix build failure on PyPy when abi3 features are activated. [#1991](https://github.com/PyO3/pyo3/pull/1991) - Fix mingw platform detection. [#1993](https://github.com/PyO3/pyo3/pull/1993) - Fix panic in `__get__` implementation when accessing descriptor on type object. [#1997](https://github.com/PyO3/pyo3/pull/1997) ## [0.15.0] - 2021-11-03 ### Packaging - `pyo3`'s `Cargo.toml` now advertises `links = "python"` to inform Cargo that it links against *libpython*. [#1819](https://github.com/PyO3/pyo3/pull/1819) - Added optional `anyhow` feature to convert `anyhow::Error` into `PyErr`. [#1822](https://github.com/PyO3/pyo3/pull/1822) - Support Python 3.10. [#1889](https://github.com/PyO3/pyo3/pull/1889) - Added optional `eyre` feature to convert `eyre::Report` into `PyErr`. [#1893](https://github.com/PyO3/pyo3/pull/1893) - Support PyPy 3.8. [#1948](https://github.com/PyO3/pyo3/pull/1948) ### Added - Add `PyList::get_item_unchecked` and `PyTuple::get_item_unchecked` to get items without bounds checks. [#1733](https://github.com/PyO3/pyo3/pull/1733) - Support `#[doc = include_str!(...)]` attributes on Rust 1.54 and up. [#1746](https://github.com/PyO3/pyo3/issues/1746) - Add `PyAny::py` as a convenience for `PyNativeType::py`. [#1751](https://github.com/PyO3/pyo3/pull/1751) - Add implementation of `std::ops::Index` for `PyList`, `PyTuple` and `PySequence`. [#1825](https://github.com/PyO3/pyo3/pull/1825) - Add range indexing implementations of `std::ops::Index` for `PyList`, `PyTuple` and `PySequence`. [#1829](https://github.com/PyO3/pyo3/pull/1829) - Add `PyMapping` type to represent the Python mapping protocol. [#1844](https://github.com/PyO3/pyo3/pull/1844) - Add commonly-used sequence methods to `PyList` and `PyTuple`. [#1849](https://github.com/PyO3/pyo3/pull/1849) - Add `as_sequence` methods to `PyList` and `PyTuple`. [#1860](https://github.com/PyO3/pyo3/pull/1860) - Add support for magic methods in `#[pymethods]`, intended as a replacement for `#[pyproto]`. [#1864](https://github.com/PyO3/pyo3/pull/1864) - Add `abi3-py310` feature. [#1889](https://github.com/PyO3/pyo3/pull/1889) - Add `PyCFunction::new_closure` to create a Python function from a Rust closure. [#1901](https://github.com/PyO3/pyo3/pull/1901) - Add support for positional-only arguments in `#[pyfunction]`. [#1925](https://github.com/PyO3/pyo3/pull/1925) - Add `PyErr::take` to attempt to fetch a Python exception if present. [#1957](https://github.com/PyO3/pyo3/pull/1957) ### Changed - `PyList`, `PyTuple` and `PySequence`'s APIs now accepts only `usize` indices instead of `isize`. [#1733](https://github.com/PyO3/pyo3/pull/1733), [#1802](https://github.com/PyO3/pyo3/pull/1802), [#1803](https://github.com/PyO3/pyo3/pull/1803) - `PyList::get_item` and `PyTuple::get_item` now return `PyResult<&PyAny>` instead of panicking. [#1733](https://github.com/PyO3/pyo3/pull/1733) - `PySequence::in_place_repeat` and `PySequence::in_place_concat` now return `PyResult<&PySequence>` instead of `PyResult<()>`, which is needed in case of immutable sequences such as tuples. [#1803](https://github.com/PyO3/pyo3/pull/1803) - `PySequence::get_slice` now returns `PyResult<&PySequence>` instead of `PyResult<&PyAny>`. [#1829](https://github.com/PyO3/pyo3/pull/1829) - Deprecate `PyTuple::split_from`. [#1804](https://github.com/PyO3/pyo3/pull/1804) - Deprecate `PyTuple::slice`, new method `PyTuple::get_slice` added with `usize` indices. [#1828](https://github.com/PyO3/pyo3/pull/1828) - Deprecate FFI definitions `PyParser_SimpleParseStringFlags`, `PyParser_SimpleParseStringFlagsFilename`, `PyParser_SimpleParseFileFlags` when building for Python 3.9. [#1830](https://github.com/PyO3/pyo3/pull/1830) - Mark FFI definitions removed in Python 3.10 `PyParser_ASTFromString`, `PyParser_ASTFromStringObject`, `PyParser_ASTFromFile`, `PyParser_ASTFromFileObject`, `PyParser_SimpleParseStringFlags`, `PyParser_SimpleParseStringFlagsFilename`, `PyParser_SimpleParseFileFlags`, `PyParser_SimpleParseString`, `PyParser_SimpleParseFile`, `Py_SymtableString`, and `Py_SymtableStringObject`. [#1830](https://github.com/PyO3/pyo3/pull/1830) - `#[pymethods]` now handles magic methods similarly to `#[pyproto]`. In the future, `#[pyproto]` may be deprecated. [#1864](https://github.com/PyO3/pyo3/pull/1864) - Deprecate FFI definitions `PySys_AddWarnOption`, `PySys_AddWarnOptionUnicode` and `PySys_HasWarnOptions`. [#1887](https://github.com/PyO3/pyo3/pull/1887) - Deprecate `#[call]` attribute in favor of using `fn __call__`. [#1929](https://github.com/PyO3/pyo3/pull/1929) - Fix missing FFI definition `_PyImport_FindExtensionObject` on Python 3.10. [#1942](https://github.com/PyO3/pyo3/pull/1942) - Change `PyErr::fetch` to panic in debug mode if no exception is present. [#1957](https://github.com/PyO3/pyo3/pull/1957) ### Fixed - Fix building with a conda environment on Windows. [#1873](https://github.com/PyO3/pyo3/pull/1873) - Fix panic on Python 3.6 when calling `Python::with_gil` with Python initialized but threading not initialized. [#1874](https://github.com/PyO3/pyo3/pull/1874) - Fix incorrect linking to version-specific DLL instead of `python3.dll` when cross-compiling to Windows with `abi3`. [#1880](https://github.com/PyO3/pyo3/pull/1880) - Fix FFI definition for `PyTuple_ClearFreeList` incorrectly being present for Python 3.9 and up. [#1887](https://github.com/PyO3/pyo3/pull/1887) - Fix panic in generated `#[derive(FromPyObject)]` for enums. [#1888](https://github.com/PyO3/pyo3/pull/1888) - Fix cross-compiling to Python 3.7 builds with the "m" abi flag. [#1908](https://github.com/PyO3/pyo3/pull/1908) - Fix `__mod__` magic method fallback to `__rmod__`. [#1934](https://github.com/PyO3/pyo3/pull/1934). - Fix missing FFI definition `_PyImport_FindExtensionObject` on Python 3.10. [#1942](https://github.com/PyO3/pyo3/pull/1942) ## [0.14.5] - 2021-09-05 ### Added - Make `pyo3_build_config::InterpreterConfig` and subfields public. [#1848](https://github.com/PyO3/pyo3/pull/1848) - Add `resolve-config` feature to the `pyo3-build-config` to control whether its build script does anything. [#1856](https://github.com/PyO3/pyo3/pull/1856) ### Fixed - Fix 0.14.4 compile regression on `s390x-unknown-linux-gnu` target. [#1850](https://github.com/PyO3/pyo3/pull/1850) ## [0.14.4] - 2021-08-29 ### Changed - Mark `PyString::data` as `unsafe` and disable it and some supporting PyUnicode FFI APIs (which depend on a C bitfield) on big-endian targets. [#1834](https://github.com/PyO3/pyo3/pull/1834) ## [0.14.3] - 2021-08-22 ### Added - Add `PyString::data` to access the raw bytes stored in a Python string. [#1794](https://github.com/PyO3/pyo3/pull/1794) ### Fixed - Raise `AttributeError` to avoid panic when calling `del` on a `#[setter]` defined class property. [#1779](https://github.com/PyO3/pyo3/pull/1779) - Restrict FFI definitions `PyGILState_Check` and `Py_tracefunc` to the unlimited API. [#1787](https://github.com/PyO3/pyo3/pull/1787) - Add missing `_type` field to `PyStatus` struct definition. [#1791](https://github.com/PyO3/pyo3/pull/1791) - Reduce lower bound `num-complex` optional dependency to support interop with `rust-numpy` and `ndarray` when building with the MSRV of 1.41 [#1799](https://github.com/PyO3/pyo3/pull/1799) - Fix memory leak in `Python::run_code`. [#1806](https://github.com/PyO3/pyo3/pull/1806) - Fix memory leak in `PyModule::from_code`. [#1810](https://github.com/PyO3/pyo3/pull/1810) - Remove use of `pyo3::` in `pyo3::types::datetime` which broke builds using `-Z avoid-dev-deps` [#1811](https://github.com/PyO3/pyo3/pull/1811) ## [0.14.2] - 2021-08-09 ### Added - Add `indexmap` feature to add `ToPyObject`, `IntoPy` and `FromPyObject` implementations for `indexmap::IndexMap`. [#1728](https://github.com/PyO3/pyo3/pull/1728) - Add `pyo3_build_config::add_extension_module_link_args` to use in build scripts to set linker arguments (for macOS). [#1755](https://github.com/PyO3/pyo3/pull/1755) - Add `Python::with_gil_unchecked` unsafe variation of `Python::with_gil` to allow obtaining a `Python` in scenarios where `Python::with_gil` would fail. [#1769](https://github.com/PyO3/pyo3/pull/1769) ### Changed - `PyErr::new` no longer acquires the Python GIL internally. [#1724](https://github.com/PyO3/pyo3/pull/1724) - Reverted PyO3 0.14.0's use of `cargo:rustc-cdylib-link-arg` in its build script, as Cargo unintentionally allowed crates to pass linker args to downstream crates in this way. Projects supporting macOS may need to restore `.cargo/config.toml` files. [#1755](https://github.com/PyO3/pyo3/pull/1755) ### Fixed - Fix regression in 0.14.0 rejecting usage of `#[doc(hidden)]` on structs and functions annotated with PyO3 macros. [#1722](https://github.com/PyO3/pyo3/pull/1722) - Fix regression in 0.14.0 leading to incorrect code coverage being computed for `#[pyfunction]`s. [#1726](https://github.com/PyO3/pyo3/pull/1726) - Fix incorrect FFI definition of `Py_Buffer` on PyPy. [#1737](https://github.com/PyO3/pyo3/pull/1737) - Fix incorrect calculation of `dictoffset` on 32-bit Windows. [#1475](https://github.com/PyO3/pyo3/pull/1475) - Fix regression in 0.13.2 leading to linking to incorrect Python library on Windows "gnu" targets. [#1759](https://github.com/PyO3/pyo3/pull/1759) - Fix compiler warning: deny trailing semicolons in expression macro. [#1762](https://github.com/PyO3/pyo3/pull/1762) - Fix incorrect FFI definition of `Py_DecodeLocale`. The 2nd argument is now `*mut Py_ssize_t` instead of `Py_ssize_t`. [#1766](https://github.com/PyO3/pyo3/pull/1766) ## [0.14.1] - 2021-07-04 ### Added - Implement `IntoPy` for `&PathBuf` and `&OsString`. [#1712](https://github.com/PyO3/pyo3/pull/1712) ### Fixed - Fix crashes on PyPy due to incorrect definitions of `PyList_SET_ITEM`. [#1713](https://github.com/PyO3/pyo3/pull/1713) ## [0.14.0] - 2021-07-03 ### Packaging - Update `num-bigint` optional dependency to 0.4. [#1481](https://github.com/PyO3/pyo3/pull/1481) - Update `num-complex` optional dependency to 0.4. [#1482](https://github.com/PyO3/pyo3/pull/1482) - Extend `hashbrown` optional dependency supported versions to include 0.11. [#1496](https://github.com/PyO3/pyo3/pull/1496) - Support PyPy 3.7. [#1538](https://github.com/PyO3/pyo3/pull/1538) ### Added - Extend conversions for `[T; N]` to all `N` using const generics (on Rust 1.51 and up). [#1128](https://github.com/PyO3/pyo3/pull/1128) - Add conversions between `OsStr`/ `OsString` and Python strings. [#1379](https://github.com/PyO3/pyo3/pull/1379) - Add conversions between `Path`/ `PathBuf` and Python strings (and `pathlib.Path` objects). [#1379](https://github.com/PyO3/pyo3/pull/1379) [#1654](https://github.com/PyO3/pyo3/pull/1654) - Add a new set of `#[pyo3(...)]` attributes to control various PyO3 macro functionality: - `#[pyo3(from_py_with = "...")]` function arguments and struct fields to override the default from-Python conversion. [#1411](https://github.com/PyO3/pyo3/pull/1411) - `#[pyo3(name = "...")]` for setting Python names. [#1567](https://github.com/PyO3/pyo3/pull/1567) - `#[pyo3(text_signature = "...")]` for setting text signature. [#1658](https://github.com/PyO3/pyo3/pull/1658) - Add FFI definition `PyCFunction_CheckExact` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425) - Add FFI definition `Py_IS_TYPE`. [#1429](https://github.com/PyO3/pyo3/pull/1429) - Add FFI definition `_Py_InitializeMain`. [#1473](https://github.com/PyO3/pyo3/pull/1473) - Add FFI definitions from `cpython/import.h`.[#1475](https://github.com/PyO3/pyo3/pull/1475) - Add tuple and unit struct support for `#[pyclass]` macro. [#1504](https://github.com/PyO3/pyo3/pull/1504) - Add FFI definition `PyDateTime_TimeZone_UTC`. [#1572](https://github.com/PyO3/pyo3/pull/1572) - Add support for `#[pyclass(extends=Exception)]`. [#1591](https://github.com/PyO3/pyo3/pull/1591) - Add `PyErr::cause` and `PyErr::set_cause`. [#1679](https://github.com/PyO3/pyo3/pull/1679) - Add FFI definitions from `cpython/pystate.h`. [#1687](https://github.com/PyO3/pyo3/pull/1687/) - Add `wrap_pyfunction!` macro to `pyo3::prelude`. [#1695](https://github.com/PyO3/pyo3/pull/1695) ### Changed - Allow only one `#[pymethods]` block per `#[pyclass]` by default, to remove the dependency on `inventory`. Add a `multiple-pymethods` feature to opt-in the original behavior and dependency on `inventory`. [#1457](https://github.com/PyO3/pyo3/pull/1457) - Change `PyTimeAccess::get_fold` to return a `bool` instead of a `u8`. [#1397](https://github.com/PyO3/pyo3/pull/1397) - Deprecate FFI definition `PyCFunction_Call` for Python 3.9 and up. [#1425](https://github.com/PyO3/pyo3/pull/1425) - Deprecate FFI definition `PyModule_GetFilename`. [#1425](https://github.com/PyO3/pyo3/pull/1425) - The `auto-initialize` feature is no longer enabled by default. [#1443](https://github.com/PyO3/pyo3/pull/1443) - Change `PyCFunction::new` and `PyCFunction::new_with_keywords` to take `&'static str` arguments rather than implicitly copying (and leaking) them. [#1450](https://github.com/PyO3/pyo3/pull/1450) - Deprecate `PyModule::call`, `PyModule::call0`, `PyModule::call1` and `PyModule::get`. [#1492](https://github.com/PyO3/pyo3/pull/1492) - Add length information to `PyBufferError`s raised from `PyBuffer::copy_to_slice` and `PyBuffer::copy_from_slice`. [#1534](https://github.com/PyO3/pyo3/pull/1534) - Automatically set `-undefined` and `dynamic_lookup` linker arguments on macOS with the `extension-module` feature. [#1539](https://github.com/PyO3/pyo3/pull/1539) - Deprecate `#[pyproto]` methods which are easier to implement as `#[pymethods]`: [#1560](https://github.com/PyO3/pyo3/pull/1560) - `PyBasicProtocol::__bytes__` and `PyBasicProtocol::__format__` - `PyContextProtocol::__enter__` and `PyContextProtocol::__exit__` - `PyDescrProtocol::__delete__` and `PyDescrProtocol::__set_name__` - `PyMappingProtocol::__reversed__` - `PyNumberProtocol::__complex__` and `PyNumberProtocol::__round__` - `PyAsyncProtocol::__aenter__` and `PyAsyncProtocol::__aexit__` - Deprecate several attributes in favor of the new `#[pyo3(...)]` options: - `#[name = "..."]`, replaced by `#[pyo3(name = "...")]` [#1567](https://github.com/PyO3/pyo3/pull/1567) - `#[pyfn(m, "name")]`, replaced by `#[pyfn(m)] #[pyo3(name = "...")]`. [#1610](https://github.com/PyO3/pyo3/pull/1610) - `#[pymodule(name)]`, replaced by `#[pymodule] #[pyo3(name = "...")]` [#1650](https://github.com/PyO3/pyo3/pull/1650) - `#[text_signature = "..."]`, replaced by `#[pyo3(text_signature = "...")]`. [#1658](https://github.com/PyO3/pyo3/pull/1658) - Reduce LLVM line counts to improve compilation times. [#1604](https://github.com/PyO3/pyo3/pull/1604) - No longer call `PyEval_InitThreads` in `#[pymodule]` init code. [#1630](https://github.com/PyO3/pyo3/pull/1630) - Use `METH_FASTCALL` argument passing convention, when possible, to improve `#[pyfunction]` and method performance. [#1619](https://github.com/PyO3/pyo3/pull/1619), [#1660](https://github.com/PyO3/pyo3/pull/1660) - Filter sysconfigdata candidates by architecture when cross-compiling. [#1626](https://github.com/PyO3/pyo3/pull/1626) ### Removed - Remove deprecated exception names `BaseException` etc. [#1426](https://github.com/PyO3/pyo3/pull/1426) - Remove deprecated methods `Python::is_instance`, `Python::is_subclass`, `Python::release`, `Python::xdecref`, and `Py::from_owned_ptr_or_panic`. [#1426](https://github.com/PyO3/pyo3/pull/1426) - Remove many FFI definitions which never existed in the Python C-API: - (previously deprecated) `PyGetSetDef_INIT`, `PyGetSetDef_DICT`, `PyCoro_Check`, `PyCoroWrapper_Check`, and `PyAsyncGen_Check` [#1426](https://github.com/PyO3/pyo3/pull/1426) - `PyMethodDef_INIT` [#1426](https://github.com/PyO3/pyo3/pull/1426) - `PyTypeObject_INIT` [#1429](https://github.com/PyO3/pyo3/pull/1429) - `PyObject_Check`, `PySuper_Check`, and `FreeFunc` [#1438](https://github.com/PyO3/pyo3/pull/1438) - `PyModuleDef_INIT` [#1630](https://github.com/PyO3/pyo3/pull/1630) - Remove pyclass implementation details from `PyTypeInfo`: - `Type`, `DESCRIPTION`, and `FLAGS` [#1456](https://github.com/PyO3/pyo3/pull/1456) - `BaseType`, `BaseLayout`, `Layout`, `Initializer` [#1596](https://github.com/PyO3/pyo3/pull/1596) - Remove `PYO3_CROSS_INCLUDE_DIR` environment variable and the associated C header parsing functionality. [#1521](https://github.com/PyO3/pyo3/pull/1521) - Remove `raw_pycfunction!` macro. [#1619](https://github.com/PyO3/pyo3/pull/1619) - Remove `PyClassAlloc` trait. [#1657](https://github.com/PyO3/pyo3/pull/1657) - Remove `PyList::get_parked_item`. [#1664](https://github.com/PyO3/pyo3/pull/1664) ### Fixed - Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425) - `PYO3_CROSS_LIB_DIR` environment variable no long required when compiling for x86-64 Python from macOS arm64 and reverse. [#1428](https://github.com/PyO3/pyo3/pull/1428) - Fix FFI definition `_PyEval_RequestCodeExtraIndex`, which took an argument of the wrong type. [#1429](https://github.com/PyO3/pyo3/pull/1429) - Fix FFI definition `PyIndex_Check` missing with the `abi3` feature. [#1436](https://github.com/PyO3/pyo3/pull/1436) - Fix incorrect `TypeError` raised when keyword-only argument passed along with a positional argument in `*args`. [#1440](https://github.com/PyO3/pyo3/pull/1440) - Fix inability to use a named lifetime for `&PyTuple` of `*args` in `#[pyfunction]`. [#1440](https://github.com/PyO3/pyo3/pull/1440) - Fix use of Python argument for `#[pymethods]` inside macro expansions. [#1505](https://github.com/PyO3/pyo3/pull/1505) - No longer include `__doc__` in `__all__` generated for `#[pymodule]`. [#1509](https://github.com/PyO3/pyo3/pull/1509) - Always use cross-compiling configuration if any of the `PYO3_CROSS` family of environment variables are set. [#1514](https://github.com/PyO3/pyo3/pull/1514) - Support `EnvironmentError`, `IOError`, and `WindowsError` on PyPy. [#1533](https://github.com/PyO3/pyo3/pull/1533) - Fix unnecessary rebuilds when cycling between `cargo check` and `cargo clippy` in a Python virtualenv. [#1557](https://github.com/PyO3/pyo3/pull/1557) - Fix segfault when dereferencing `ffi::PyDateTimeAPI` without the GIL. [#1563](https://github.com/PyO3/pyo3/pull/1563) - Fix memory leak in `FromPyObject` implementations for `u128` and `i128`. [#1638](https://github.com/PyO3/pyo3/pull/1638) - Fix `#[pyclass(extends=PyDict)]` leaking the dict contents on drop. [#1657](https://github.com/PyO3/pyo3/pull/1657) - Fix segfault when calling `PyList::get_item` with negative indices. [#1668](https://github.com/PyO3/pyo3/pull/1668) - Fix FFI definitions of `PyEval_SetProfile`/`PyEval_SetTrace` to take `Option` parameters. [#1692](https://github.com/PyO3/pyo3/pull/1692) - Fix `ToPyObject` impl for `HashSet` to accept non-default hashers. [#1702](https://github.com/PyO3/pyo3/pull/1702) ## [0.13.2] - 2021-02-12 ### Packaging - Lower minimum supported Rust version to 1.41. [#1421](https://github.com/PyO3/pyo3/pull/1421) ### Added - Add unsafe API `with_embedded_python_interpreter` to initialize a Python interpreter, execute a closure, and finalize the interpreter. [#1355](https://github.com/PyO3/pyo3/pull/1355) - Add `serde` feature which provides implementations of `Serialize` and `Deserialize` for `Py`. [#1366](https://github.com/PyO3/pyo3/pull/1366) - Add FFI definition `_PyCFunctionFastWithKeywords` on Python 3.7 and up. [#1384](https://github.com/PyO3/pyo3/pull/1384) - Add `PyDateTime::new_with_fold` method. [#1398](https://github.com/PyO3/pyo3/pull/1398) - Add `size_hint` impls for `{PyDict,PyList,PySet,PyTuple}Iterator`s. [#1699](https://github.com/PyO3/pyo3/pull/1699) ### Changed - `prepare_freethreaded_python` will no longer register an `atexit` handler to call `Py_Finalize`. This resolves a number of issues with incompatible C extensions causing crashes at finalization. [#1355](https://github.com/PyO3/pyo3/pull/1355) - Mark `PyLayout::py_init`, `PyClassDict::clear_dict`, and `opt_to_pyobj` safe, as they do not perform any unsafe operations. [#1404](https://github.com/PyO3/pyo3/pull/1404) ### Fixed - Fix support for using `r#raw_idents` as argument names in pyfunctions. [#1383](https://github.com/PyO3/pyo3/pull/1383) - Fix typo in FFI definition for `PyFunction_GetCode` (was incorrectly `PyFunction_Code`). [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix FFI definitions `PyMarshal_WriteObjectToString` and `PyMarshal_ReadObjectFromString` as available in limited API. [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix FFI definitions `PyListObject` and those from `funcobject.h` as requiring non-limited API. [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix unqualified `Result` usage in `pyobject_native_type_base`. [#1402](https://github.com/PyO3/pyo3/pull/1402) - Fix build on systems where the default Python encoding is not UTF-8. [#1405](https://github.com/PyO3/pyo3/pull/1405) - Fix build on mingw / MSYS2. [#1423](https://github.com/PyO3/pyo3/pull/1423) ## [0.13.1] - 2021-01-10 ### Added - Add support for `#[pyclass(dict)]` and `#[pyclass(weakref)]` with the `abi3` feature on Python 3.9 and up. [#1342](https://github.com/PyO3/pyo3/pull/1342) - Add FFI definitions `PyOS_BeforeFork`, `PyOS_AfterFork_Parent`, `PyOS_AfterFork_Child` for Python 3.7 and up. [#1348](https://github.com/PyO3/pyo3/pull/1348) - Add an `auto-initialize` feature to control whether PyO3 should automatically initialize an embedded Python interpreter. For compatibility this feature is enabled by default in PyO3 0.13.1, but is planned to become opt-in from PyO3 0.14.0. [#1347](https://github.com/PyO3/pyo3/pull/1347) - Add support for cross-compiling to Windows without needing `PYO3_CROSS_INCLUDE_DIR`. [#1350](https://github.com/PyO3/pyo3/pull/1350) ### Deprecated - Deprecate FFI definitions `PyEval_CallObjectWithKeywords`, `PyEval_CallObject`, `PyEval_CallFunction`, `PyEval_CallMethod` when building for Python 3.9. [#1338](https://github.com/PyO3/pyo3/pull/1338) - Deprecate FFI definitions `PyGetSetDef_DICT` and `PyGetSetDef_INIT` which have never been in the Python API. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Deprecate FFI definitions `PyGen_NeedsFinalizing`, `PyImport_Cleanup` (removed in 3.9), and `PyOS_InitInterrupts` (3.10). [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definition `PyOS_AfterFork` for Python 3.7 and up. [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definitions `PyCoro_Check`, `PyAsyncGen_Check`, and `PyCoroWrapper_Check`, which have never been in the Python API (for the first two, it is possible to use `PyCoro_CheckExact` and `PyAsyncGen_CheckExact` instead; these are the actual functions provided by the Python API). [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definitions for `PyUnicode_FromUnicode`, `PyUnicode_AsUnicode` and `PyUnicode_AsUnicodeAndSize`, which will be removed from 3.12 and up due to [PEP 623](https://www.python.org/dev/peps/pep-0623/). [#1370](https://github.com/PyO3/pyo3/pull/1370) ### Removed - Remove FFI definition `PyFrame_ClearFreeList` when building for Python 3.9. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Remove FFI definition `_PyDict_Contains` when building for Python 3.10. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Remove FFI definitions `PyGen_NeedsFinalizing` and `PyImport_Cleanup` (for 3.9 and up), and `PyOS_InitInterrupts` (3.10). [#1348](https://github.com/PyO3/pyo3/pull/1348) ### Fixed - Stop including `Py_TRACE_REFS` config setting automatically if `Py_DEBUG` is set on Python 3.8 and up. [#1334](https://github.com/PyO3/pyo3/pull/1334) - Remove `#[deny(warnings)]` attribute (and instead refuse warnings only in CI). [#1340](https://github.com/PyO3/pyo3/pull/1340) - Fix deprecation warning for missing `__module__` with `#[pyclass]`. [#1343](https://github.com/PyO3/pyo3/pull/1343) - Correct return type of `PyFrozenSet::empty` to `&PyFrozenSet` (was incorrectly `&PySet`). [#1351](https://github.com/PyO3/pyo3/pull/1351) - Fix missing `Py_INCREF` on heap type objects on Python versions before 3.8. [#1365](https://github.com/PyO3/pyo3/pull/1365) ## [0.13.0] - 2020-12-22 ### Packaging - Drop support for Python 3.5 (as it is now end-of-life). [#1250](https://github.com/PyO3/pyo3/pull/1250) - Bump minimum supported Rust version to 1.45. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Bump indoc dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Bump paste dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Rename internal crates `pyo3cls` and `pyo3-derive-backend` to `pyo3-macros` and `pyo3-macros-backend` respectively. [#1317](https://github.com/PyO3/pyo3/pull/1317) ### Added - Add support for building for CPython limited API. Opting-in to the limited API enables a single extension wheel built with PyO3 to be installable on multiple Python versions. This required a few minor changes to runtime behavior of of PyO3 `#[pyclass]` types. See the migration guide for full details. [#1152](https://github.com/PyO3/pyo3/pull/1152) - Add feature flags `abi3-py36`, `abi3-py37`, `abi3-py38` etc. to set the minimum Python version when using the limited API. [#1263](https://github.com/PyO3/pyo3/pull/1263) - Add argument names to `TypeError` messages generated by pymethod wrappers. [#1212](https://github.com/PyO3/pyo3/pull/1212) - Add FFI definitions for PEP 587 "Python Initialization Configuration". [#1247](https://github.com/PyO3/pyo3/pull/1247) - Add FFI definitions for `PyEval_SetProfile` and `PyEval_SetTrace`. [#1255](https://github.com/PyO3/pyo3/pull/1255) - Add FFI definitions for context.h functions (`PyContext_New`, etc). [#1259](https://github.com/PyO3/pyo3/pull/1259) - Add `PyAny::is_instance` method. [#1276](https://github.com/PyO3/pyo3/pull/1276) - Add support for conversion between `char` and `PyString`. [#1282](https://github.com/PyO3/pyo3/pull/1282) - Add FFI definitions for `PyBuffer_SizeFromFormat`, `PyObject_LengthHint`, `PyObject_CallNoArgs`, `PyObject_CallOneArg`, `PyObject_CallMethodNoArgs`, `PyObject_CallMethodOneArg`, `PyObject_VectorcallDict`, and `PyObject_VectorcallMethod`. [#1287](https://github.com/PyO3/pyo3/pull/1287) - Add conversions between `u128`/`i128` and `PyLong` for PyPy. [#1310](https://github.com/PyO3/pyo3/pull/1310) - Add `Python::version` and `Python::version_info` to get the running interpreter version. [#1322](https://github.com/PyO3/pyo3/pull/1322) - Add conversions for tuples of length 10, 11, and 12. [#1454](https://github.com/PyO3/pyo3/pull/1454) ### Changed - Change return type of `PyType::name` from `Cow` to `PyResult<&str>`. [#1152](https://github.com/PyO3/pyo3/pull/1152) - `#[pyclass(subclass)]` is now required for subclassing from Rust (was previously just required for subclassing from Python). [#1152](https://github.com/PyO3/pyo3/pull/1152) - Change `PyIterator` to be consistent with other native types: it is now used as `&PyIterator` instead of `PyIterator<'a>`. [#1176](https://github.com/PyO3/pyo3/pull/1176) - Change formatting of `PyDowncastError` messages to be closer to Python's builtin error messages. [#1212](https://github.com/PyO3/pyo3/pull/1212) - Change `Debug` and `Display` impls for `PyException` to be consistent with `PyAny`. [#1275](https://github.com/PyO3/pyo3/pull/1275) - Change `Debug` impl of `PyErr` to output more helpful information (acquiring the GIL if necessary). [#1275](https://github.com/PyO3/pyo3/pull/1275) - Rename `PyTypeInfo::is_instance` and `PyTypeInfo::is_exact_instance` to `PyTypeInfo::is_type_of` and `PyTypeInfo::is_exact_type_of`. [#1278](https://github.com/PyO3/pyo3/pull/1278) - Optimize `PyAny::call0`, `Py::call0` and `PyAny::call_method0` and `Py::call_method0` on Python 3.9 and up. [#1287](https://github.com/PyO3/pyo3/pull/1285) - Require double-quotes for pyclass name argument e.g `#[pyclass(name = "MyClass")]`. [#1303](https://github.com/PyO3/pyo3/pull/1303) ### Deprecated - Deprecate `Python::is_instance`, `Python::is_subclass`, `Python::release`, and `Python::xdecref`. [#1292](https://github.com/PyO3/pyo3/pull/1292) ### Removed - Remove deprecated ffi definitions `PyUnicode_AsUnicodeCopy`, `PyUnicode_GetMax`, `_Py_CheckRecursionLimit`, `PyObject_AsCharBuffer`, `PyObject_AsReadBuffer`, `PyObject_CheckReadBuffer` and `PyObject_AsWriteBuffer`, which will be removed in Python 3.10. [#1217](https://github.com/PyO3/pyo3/pull/1217) - Remove unused `python3` feature. [#1235](https://github.com/PyO3/pyo3/pull/1235) ### Fixed - Fix missing field in `PyCodeObject` struct (`co_posonlyargcount`) - caused invalid access to other fields in Python >3.7. [#1260](https://github.com/PyO3/pyo3/pull/1260) - Fix building for `x86_64-unknown-linux-musl` target from `x86_64-unknown-linux-gnu` host. [#1267](https://github.com/PyO3/pyo3/pull/1267) - Fix `#[text_signature]` interacting badly with rust `r#raw_identifiers`. [#1286](https://github.com/PyO3/pyo3/pull/1286) - Fix FFI definitions for `PyObject_Vectorcall` and `PyVectorcall_Call`. [#1287](https://github.com/PyO3/pyo3/pull/1285) - Fix building with Anaconda python inside a virtualenv. [#1290](https://github.com/PyO3/pyo3/pull/1290) - Fix definition of opaque FFI types. [#1312](https://github.com/PyO3/pyo3/pull/1312) - Fix using custom error type in pyclass `#[new]` methods. [#1319](https://github.com/PyO3/pyo3/pull/1319) ## [0.12.4] - 2020-11-28 ### Fixed - Fix reference count bug in implementation of `From>` for `PyObject`, a regression introduced in PyO3 0.12. [#1297](https://github.com/PyO3/pyo3/pull/1297) ## [0.12.3] - 2020-10-12 ### Fixed - Fix support for Rust versions 1.39 to 1.44, broken by an incorrect internal update to paste 1.0 which was done in PyO3 0.12.2. [#1234](https://github.com/PyO3/pyo3/pull/1234) ## [0.12.2] - 2020-10-12 ### Added - Add support for keyword-only arguments without default values in `#[pyfunction]`. [#1209](https://github.com/PyO3/pyo3/pull/1209) - Add `Python::check_signals` as a safe a wrapper for `PyErr_CheckSignals`. [#1214](https://github.com/PyO3/pyo3/pull/1214) ### Fixed - Fix invalid document for protocol methods. [#1169](https://github.com/PyO3/pyo3/pull/1169) - Hide docs of PyO3 private implementation details in `pyo3::class::methods`. [#1169](https://github.com/PyO3/pyo3/pull/1169) - Fix unnecessary rebuild on PATH changes when the python interpreter is provided by PYO3_PYTHON. [#1231](https://github.com/PyO3/pyo3/pull/1231) ## [0.12.1] - 2020-09-16 ### Fixed - Fix building for a 32-bit Python on 64-bit Windows with a 64-bit Rust toolchain. [#1179](https://github.com/PyO3/pyo3/pull/1179) - Fix building on platforms where `c_char` is `u8`. [#1182](https://github.com/PyO3/pyo3/pull/1182) ## [0.12.0] - 2020-09-12 ### Added - Add FFI definitions `Py_FinalizeEx`, `PyOS_getsig`, and `PyOS_setsig`. [#1021](https://github.com/PyO3/pyo3/pull/1021) - Add `PyString::to_str` for accessing `PyString` as `&str`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Add `Python::with_gil` for executing a closure with the Python GIL. [#1037](https://github.com/PyO3/pyo3/pull/1037) - Add type information to failures in `PyAny::downcast`. [#1050](https://github.com/PyO3/pyo3/pull/1050) - Implement `Debug` for `PyIterator`. [#1051](https://github.com/PyO3/pyo3/pull/1051) - Add `PyBytes::new_with` and `PyByteArray::new_with` for initialising `bytes` and `bytearray` objects using a closure. [#1074](https://github.com/PyO3/pyo3/pull/1074) - Add `#[derive(FromPyObject)]` macro for enums and structs. [#1065](https://github.com/PyO3/pyo3/pull/1065) - Add `Py::as_ref` and `Py::into_ref` for converting `Py` to `&T`. [#1098](https://github.com/PyO3/pyo3/pull/1098) - Add ability to return `Result` types other than `PyResult` from `#[pyfunction]`, `#[pymethod]` and `#[pyproto]` functions. [#1106](https://github.com/PyO3/pyo3/pull/1118). - Implement `ToPyObject`, `IntoPy`, and `FromPyObject` for [hashbrown](https://crates.io/crates/hashbrown)'s `HashMap` and `HashSet` types (requires the `hashbrown` feature). [#1114](https://github.com/PyO3/pyo3/pull/1114) - Add `#[pyfunction(pass_module)]` and `#[pyfn(pass_module)]` to pass the module object as the first function argument. [#1143](https://github.com/PyO3/pyo3/pull/1143) - Add `PyModule::add_function` and `PyModule::add_submodule` as typed alternatives to `PyModule::add_wrapped`. [#1143](https://github.com/PyO3/pyo3/pull/1143) - Add native `PyCFunction` and `PyFunction` types. [#1163](https://github.com/PyO3/pyo3/pull/1163) ### Changed - Rework exception types: [#1024](https://github.com/PyO3/pyo3/pull/1024) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Rename exception types from e.g. `RuntimeError` to `PyRuntimeError`. The old names continue to exist but are deprecated. - Exception objects are now accessible as `&T` or `Py`, just like other Python-native types. - Rename `PyException::py_err` to `PyException::new_err`. - Rename `PyUnicodeDecodeErr::new_err` to `PyUnicodeDecodeErr::new`. - Remove `PyStopIteration::stop_iteration`. - Require `T: Send` for the return value `T` of `Python::allow_threads`. [#1036](https://github.com/PyO3/pyo3/pull/1036) - Rename `PYTHON_SYS_EXECUTABLE` to `PYO3_PYTHON`. The old name will continue to work (undocumented) but will be removed in a future release. [#1039](https://github.com/PyO3/pyo3/pull/1039) - Remove `unsafe` from signature of `PyType::as_type_ptr`. [#1047](https://github.com/PyO3/pyo3/pull/1047) - Change return type of `PyIterator::from_object` to `PyResult` (was `Result`). [#1051](https://github.com/PyO3/pyo3/pull/1051) - `IntoPy` is no longer implied by `FromPy`. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Change `PyObject` to be a type alias for `Py`. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Rework `PyErr` to be compatible with the `std::error::Error` trait: [#1067](https://github.com/PyO3/pyo3/pull/1067) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Implement `Display`, `Error`, `Send` and `Sync` for `PyErr` and `PyErrArguments`. - Add `PyErr::instance` for accessing `PyErr` as `&PyBaseException`. - `PyErr`'s fields are now an implementation detail. The equivalent values can be accessed with `PyErr::ptype`, `PyErr::pvalue` and `PyErr::ptraceback`. - Change receiver of `PyErr::print` and `PyErr::print_and_set_sys_last_vars` to `&self` (was `self`). - Remove `PyErrValue`, `PyErr::from_value`, `PyErr::into_normalized`, and `PyErr::normalize`. - Remove `PyException::into`. - Remove `Into>` for `PyErr` and `PyException`. - Change methods generated by `#[pyproto]` to return `NotImplemented` if Python should try a reversed operation. #[1072](https://github.com/PyO3/pyo3/pull/1072) - Change argument to `PyModule::add` to `impl IntoPy` (was `impl ToPyObject`). #[1124](https://github.com/PyO3/pyo3/pull/1124) ### Removed - Remove many exception and `PyErr` APIs; see the "changed" section above. [#1024](https://github.com/PyO3/pyo3/pull/1024) [#1067](https://github.com/PyO3/pyo3/pull/1067) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Remove `PyString::to_string` (use new `PyString::to_str`). [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `PyString::as_bytes`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `Python::register_any`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `GILGuard::acquire` from the public API. Use `Python::acquire_gil` or `Python::with_gil`. [#1036](https://github.com/PyO3/pyo3/pull/1036) - Remove the `FromPy` trait. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Remove the `AsPyRef` trait. [#1098](https://github.com/PyO3/pyo3/pull/1098) ### Fixed - Correct FFI definitions `Py_SetProgramName` and `Py_SetPythonHome` to take `*const` arguments (was `*mut`). [#1021](https://github.com/PyO3/pyo3/pull/1021) - Fix `FromPyObject` for `num_bigint::BigInt` for Python objects with an `__index__` method. [#1027](https://github.com/PyO3/pyo3/pull/1027) - Correct FFI definition `_PyLong_AsByteArray` to take `*mut c_uchar` argument (was `*const c_uchar`). [#1029](https://github.com/PyO3/pyo3/pull/1029) - Fix segfault with `#[pyclass(dict, unsendable)]`. [#1058](https://github.com/PyO3/pyo3/pull/1058) [#1059](https://github.com/PyO3/pyo3/pull/1059) - Fix using `&Self` as an argument type for functions in a `#[pymethods]` block. [#1071](https://github.com/PyO3/pyo3/pull/1071) - Fix best-effort build against PyPy 3.6. [#1092](https://github.com/PyO3/pyo3/pull/1092) - Fix many cases of lifetime elision in `#[pyproto]` implementations. [#1093](https://github.com/PyO3/pyo3/pull/1093) - Fix detection of Python build configuration when cross-compiling. [#1095](https://github.com/PyO3/pyo3/pull/1095) - Always link against libpython on android with the `extension-module` feature. [#1095](https://github.com/PyO3/pyo3/pull/1095) - Fix the `+` operator not trying `__radd__` when both `__add__` and `__radd__` are defined in `PyNumberProtocol` (and similar for all other reversible operators). [#1107](https://github.com/PyO3/pyo3/pull/1107) - Fix building with Anaconda python. [#1175](https://github.com/PyO3/pyo3/pull/1175) ## [0.11.1] - 2020-06-30 ### Added - `#[pyclass(unsendable)]`. [#1009](https://github.com/PyO3/pyo3/pull/1009) ### Changed - Update `parking_lot` dependency to `0.11`. [#1010](https://github.com/PyO3/pyo3/pull/1010) ## [0.11.0] - 2020-06-28 ### Added - Support stable versions of Rust (>=1.39). [#969](https://github.com/PyO3/pyo3/pull/969) - Add FFI definition `PyObject_AsFileDescriptor`. [#938](https://github.com/PyO3/pyo3/pull/938) - Add `PyByteArray::data`, `PyByteArray::as_bytes`, and `PyByteArray::as_bytes_mut`. [#967](https://github.com/PyO3/pyo3/pull/967) - Add `GILOnceCell` to use in situations where `lazy_static` or `once_cell` can deadlock. [#975](https://github.com/PyO3/pyo3/pull/975) - Add `Py::borrow`, `Py::borrow_mut`, `Py::try_borrow`, and `Py::try_borrow_mut` for accessing `#[pyclass]` values. [#976](https://github.com/PyO3/pyo3/pull/976) - Add `IterNextOutput` and `IterANextOutput` for returning from `__next__` / `__anext__`. [#997](https://github.com/PyO3/pyo3/pull/997) ### Changed - Simplify internals of `#[pyo3(get)]` attribute. (Remove the hidden API `GetPropertyValue`.) [#934](https://github.com/PyO3/pyo3/pull/934) - Call `Py_Finalize` at exit to flush buffers, etc. [#943](https://github.com/PyO3/pyo3/pull/943) - Add type parameter to PyBuffer. #[951](https://github.com/PyO3/pyo3/pull/951) - Require `Send` bound for `#[pyclass]`. [#966](https://github.com/PyO3/pyo3/pull/966) - Add `Python` argument to most methods on `PyObject` and `Py` to ensure GIL safety. [#970](https://github.com/PyO3/pyo3/pull/970) - Change signature of `PyTypeObject::type_object` - now takes `Python` argument and returns `&PyType`. [#970](https://github.com/PyO3/pyo3/pull/970) - Change return type of `PyTuple::slice` and `PyTuple::split_from` from `Py` to `&PyTuple`. [#970](https://github.com/PyO3/pyo3/pull/970) - Change return type of `PyTuple::as_slice` to `&[&PyAny]`. [#971](https://github.com/PyO3/pyo3/pull/971) - Rename `PyTypeInfo::type_object` to `type_object_raw`, and add `Python` argument. [#975](https://github.com/PyO3/pyo3/pull/975) - Update `num-complex` optional dependendency from `0.2` to `0.3`. [#977](https://github.com/PyO3/pyo3/pull/977) - Update `num-bigint` optional dependendency from `0.2` to `0.3`. [#978](https://github.com/PyO3/pyo3/pull/978) - `#[pyproto]` is re-implemented without specialization. [#961](https://github.com/PyO3/pyo3/pull/961) - `PyClassAlloc::alloc` is renamed to `PyClassAlloc::new`. [#990](https://github.com/PyO3/pyo3/pull/990) - `#[pyproto]` methods can now have return value `T` or `PyResult` (previously only `PyResult` was supported). [#996](https://github.com/PyO3/pyo3/pull/996) - `#[pyproto]` methods can now skip annotating the return type if it is `()`. [#998](https://github.com/PyO3/pyo3/pull/998) ### Removed - Remove `ManagedPyRef` (unused, and needs specialization) [#930](https://github.com/PyO3/pyo3/pull/930) ### Fixed - Fix passing explicit `None` to `Option` argument `#[pyfunction]` with a default value. [#936](https://github.com/PyO3/pyo3/pull/936) - Fix `PyClass.__new__`'s not respecting subclasses when inherited by a Python class. [#990](https://github.com/PyO3/pyo3/pull/990) - Fix returning `Option` from `#[pyproto]` methods. [#996](https://github.com/PyO3/pyo3/pull/996) - Fix accepting `PyRef` and `PyRefMut` to `#[getter]` and `#[setter]` methods. [#999](https://github.com/PyO3/pyo3/pull/999) ## [0.10.1] - 2020-05-14 ### Fixed - Fix deadlock in `Python::acquire_gil` after dropping a `PyObject` or `Py`. [#924](https://github.com/PyO3/pyo3/pull/924) ## [0.10.0] - 2020-05-13 ### Added - Add FFI definition `_PyDict_NewPresized`. [#849](https://github.com/PyO3/pyo3/pull/849) - Implement `IntoPy` for `HashSet` and `BTreeSet`. [#864](https://github.com/PyO3/pyo3/pull/864) - Add `PyAny::dir` method. [#886](https://github.com/PyO3/pyo3/pull/886) - Gate macros behind a `macros` feature (enabled by default). [#897](https://github.com/PyO3/pyo3/pull/897) - Add ability to define class attributes using `#[classattr]` on functions in `#[pymethods]`. [#905](https://github.com/PyO3/pyo3/pull/905) - Implement `Clone` for `PyObject` and `Py`. [#908](https://github.com/PyO3/pyo3/pull/908) - Implement `Deref` for all builtin types. (`PyList`, `PyTuple`, `PyDict` etc.) [#911](https://github.com/PyO3/pyo3/pull/911) - Implement `Deref` for `PyCell`. [#911](https://github.com/PyO3/pyo3/pull/911) - Add `#[classattr]` support for associated constants in `#[pymethods]`. [#914](https://github.com/PyO3/pyo3/pull/914) ### Changed - Panics will now be raised as a Python `PanicException`. [#797](https://github.com/PyO3/pyo3/pull/797) - Change `PyObject` and `Py` reference counts to decrement immediately upon drop when the GIL is held. [#851](https://github.com/PyO3/pyo3/pull/851) - Allow `PyIterProtocol` methods to use either `PyRef` or `PyRefMut` as the receiver type. [#856](https://github.com/PyO3/pyo3/pull/856) - Change the implementation of `FromPyObject` for `Py` to apply to a wider range of `T`, including all `T: PyClass`. [#880](https://github.com/PyO3/pyo3/pull/880) - Move all methods from the `ObjectProtocol` trait to the `PyAny` struct. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove need for `#![feature(specialization)]` in crates depending on PyO3. [#917](https://github.com/PyO3/pyo3/pull/917) ### Removed - Remove `PyMethodsProtocol` trait. [#889](https://github.com/PyO3/pyo3/pull/889) - Remove `num-traits` dependency. [#895](https://github.com/PyO3/pyo3/pull/895) - Remove `ObjectProtocol` trait. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove `PyAny::None`. Users should use `Python::None` instead. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove all `*ProtocolImpl` traits. [#917](https://github.com/PyO3/pyo3/pull/917) ### Fixed - Fix support for `__radd__` and other `__r*__` methods as implementations for Python mathematical operators. [#839](https://github.com/PyO3/pyo3/pull/839) - Fix panics during garbage collection when traversing objects that were already mutably borrowed. [#855](https://github.com/PyO3/pyo3/pull/855) - Prevent `&'static` references to Python objects as arguments to `#[pyfunction]` and `#[pymethods]`. [#869](https://github.com/PyO3/pyo3/pull/869) - Fix lifetime safety bug with `AsPyRef::as_ref`. [#876](https://github.com/PyO3/pyo3/pull/876) - Fix `#[pyo3(get)]` attribute on `Py` fields. [#880](https://github.com/PyO3/pyo3/pull/880) - Fix segmentation faults caused by functions such as `PyList::get_item` returning borrowed objects when it was not safe to do so. [#890](https://github.com/PyO3/pyo3/pull/890) - Fix segmentation faults caused by nested `Python::acquire_gil` calls creating dangling references. [#893](https://github.com/PyO3/pyo3/pull/893) - Fix segmentatation faults when a panic occurs during a call to `Python::allow_threads`. [#912](https://github.com/PyO3/pyo3/pull/912) ## [0.9.2] - 2020-04-09 ### Added - `FromPyObject` implementations for `HashSet` and `BTreeSet`. [#842](https://github.com/PyO3/pyo3/pull/842) ### Fixed - Correctly detect 32bit architecture. [#830](https://github.com/PyO3/pyo3/pull/830) ## [0.9.1] - 2020-03-23 ### Fixed - Error messages for `#[pyclass]`. [#826](https://github.com/PyO3/pyo3/pull/826) - `FromPyObject` implementation for `PySequence`. [#827](https://github.com/PyO3/pyo3/pull/827) ## [0.9.0] - 2020-03-19 ### Added - `PyCell`, which has RefCell-like features. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyClass`, `PyLayout`, `PyClassInitializer`. [#683](https://github.com/PyO3/pyo3/pull/683) - Implemented `IntoIterator` for `PySet` and `PyFrozenSet`. [#716](https://github.com/PyO3/pyo3/pull/716) - `FromPyObject` is now automatically implemented for `T: Clone` pyclasses. [#730](https://github.com/PyO3/pyo3/pull/730) - `#[pyo3(get)]` and `#[pyo3(set)]` will now use the Rust doc-comment from the field for the Python property. [#755](https://github.com/PyO3/pyo3/pull/755) - `#[setter]` functions may now take an argument of `Pyo3::Python`. [#760](https://github.com/PyO3/pyo3/pull/760) - `PyTypeInfo::BaseLayout` and `PyClass::BaseNativeType`. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyDowncastImpl`. [#770](https://github.com/PyO3/pyo3/pull/770) - Implement `FromPyObject` and `IntoPy` traits for arrays (up to 32). [#778](https://github.com/PyO3/pyo3/pull/778) - `migration.md` and `types.md` in the guide. [#795](https://github.com/PyO3/pyo3/pull/795), #[802](https://github.com/PyO3/pyo3/pull/802) - `ffi::{_PyBytes_Resize, _PyDict_Next, _PyDict_Contains, _PyDict_GetDictPtr}`. #[820](https://github.com/PyO3/pyo3/pull/820) ### Changed - `#[new]` does not take `PyRawObject` and can return `Self`. [#683](https://github.com/PyO3/pyo3/pull/683) - The blanket implementations for `FromPyObject` for `&T` and `&mut T` are no longer specializable. Implement `PyTryFrom` for your type to control the behavior of `FromPyObject::extract` for your types. [#713](https://github.com/PyO3/pyo3/pull/713) - The implementation for `IntoPy for T` where `U: FromPy` is no longer specializable. Control the behavior of this via the implementation of `FromPy`. [#713](https://github.com/PyO3/pyo3/pull/713) - Use `parking_lot::Mutex` instead of `spin::Mutex`. [#734](https://github.com/PyO3/pyo3/pull/734) - Bumped minimum Rust version to `1.42.0-nightly 2020-01-21`. [#761](https://github.com/PyO3/pyo3/pull/761) - `PyRef` and `PyRefMut` are renewed for `PyCell`. [#770](https://github.com/PyO3/pyo3/pull/770) - Some new FFI functions for Python 3.8. [#784](https://github.com/PyO3/pyo3/pull/784) - `PyAny` is now on the top level module and prelude. [#816](https://github.com/PyO3/pyo3/pull/816) ### Removed - `PyRawObject`. [#683](https://github.com/PyO3/pyo3/pull/683) - `PyNoArgsFunction`. [#741](https://github.com/PyO3/pyo3/pull/741) - `initialize_type`. To set the module name for a `#[pyclass]`, use the `module` argument to the macro. #[751](https://github.com/PyO3/pyo3/pull/751) - `AsPyRef::as_mut/with/with_mut/into_py/into_mut_py`. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyTryFrom::try_from_mut/try_from_mut_exact/try_from_mut_unchecked`. [#770](https://github.com/PyO3/pyo3/pull/770) - `Python::mut_from_owned_ptr/mut_from_borrowed_ptr`. [#770](https://github.com/PyO3/pyo3/pull/770) - `ObjectProtocol::get_base/get_mut_base`. [#770](https://github.com/PyO3/pyo3/pull/770) ### Fixed - Fixed unsoundness of subclassing. [#683](https://github.com/PyO3/pyo3/pull/683). - Clear error indicator when the exception is handled on the Rust side. [#719](https://github.com/PyO3/pyo3/pull/719) - Usage of raw identifiers with `#[pyo3(set)]`. [#745](https://github.com/PyO3/pyo3/pull/745) - Usage of `PyObject` with `#[pyo3(get)]`. [#760](https://github.com/PyO3/pyo3/pull/760) - `#[pymethods]` used in conjunction with `#[cfg]`. #[769](https://github.com/PyO3/pyo3/pull/769) - `"*"` in a `#[pyfunction()]` argument list incorrectly accepting any number of positional arguments (use `args = "*"` when this behavior is desired). #[792](https://github.com/PyO3/pyo3/pull/792) - `PyModule::dict`. #[809](https://github.com/PyO3/pyo3/pull/809) - Fix the case where `DESCRIPTION` is not null-terminated. #[822](https://github.com/PyO3/pyo3/pull/822) ## [0.8.5] - 2020-01-05 ### Added - Implemented `FromPyObject` for `HashMap` and `BTreeMap` - Support for `#[name = "foo"]` attribute for `#[pyfunction]` and in `#[pymethods]`. [#692](https://github.com/PyO3/pyo3/pull/692) ## [0.8.4] - 2019-12-14 ### Added - Support for `#[text_signature]` attribute. [#675](https://github.com/PyO3/pyo3/pull/675) ## [0.8.3] - 2019-11-23 ### Removed - `#[init]` is removed. [#658](https://github.com/PyO3/pyo3/pull/658) ### Fixed - Now all `&Py~` types have `!Send` bound. [#655](https://github.com/PyO3/pyo3/pull/655) - Fix a compile error raised by the stabilization of `!` type. [#672](https://github.com/PyO3/pyo3/issues/672). ## [0.8.2] - 2019-10-27 ### Added - FFI compatibility for PEP 590 Vectorcall. [#641](https://github.com/PyO3/pyo3/pull/641) ### Fixed - Fix PySequenceProtocol::set_item. [#624](https://github.com/PyO3/pyo3/pull/624) - Fix a corner case of BigInt::FromPyObject. [#630](https://github.com/PyO3/pyo3/pull/630) - Fix index errors in parameter conversion. [#631](https://github.com/PyO3/pyo3/pull/631) - Fix handling of invalid utf-8 sequences in `PyString::as_bytes`. [#639](https://github.com/PyO3/pyo3/pull/639) and `PyString::to_string_lossy` [#642](https://github.com/PyO3/pyo3/pull/642). - Remove `__contains__` and `__iter__` from PyMappingProtocol. [#644](https://github.com/PyO3/pyo3/pull/644) - Fix proc-macro definition of PySetAttrProtocol. [#645](https://github.com/PyO3/pyo3/pull/645) ## [0.8.1] - 2019-10-08 ### Added - Conversion between [num-bigint](https://github.com/rust-num/num-bigint) and Python int. [#608](https://github.com/PyO3/pyo3/pull/608) ### Fixed - Make sure the right Python interpreter is used in OSX builds. [#604](https://github.com/PyO3/pyo3/pull/604) - Patch specialization being broken by Rust 1.40. [#614](https://github.com/PyO3/pyo3/issues/614) - Fix a segfault around PyErr. [#597](https://github.com/PyO3/pyo3/pull/597) ## [0.8.0] - 2019-09-16 ### Added - `module` argument to `pyclass` macro. [#499](https://github.com/PyO3/pyo3/pull/499) - `py_run!` macro [#512](https://github.com/PyO3/pyo3/pull/512) - Use existing fields and methods before calling custom **getattr**. [#505](https://github.com/PyO3/pyo3/pull/505) - `PyBytes` can now be indexed just like `Vec` - Implement `IntoPy` for `PyRef` and `PyRefMut`. ### Changed - Implementing the Using the `gc` parameter for `pyclass` (e.g. `#[pyclass(gc)]`) without implementing the `class::PyGCProtocol` trait is now a compile-time error. Failing to implement this trait could lead to segfaults. [#532](https://github.com/PyO3/pyo3/pull/532) - `PyByteArray::data` has been replaced with `PyDataArray::to_vec` because returning a `&[u8]` is unsound. (See [this comment](https://github.com/PyO3/pyo3/issues/373#issuecomment-512332696) for a great write-up for why that was unsound) - Replace `mashup` with `paste`. - `GILPool` gained a `Python` marker to prevent it from being misused to release Python objects without the GIL held. ### Removed - `IntoPyObject` was replaced with `IntoPy` - `#[pyclass(subclass)]` is hidden a `unsound-subclass` feature because it's causing segmentation faults. ### Fixed - More readable error message for generics in pyclass [#503](https://github.com/PyO3/pyo3/pull/503) ## [0.7.0] - 2019-05-26 ### Added - PyPy support by omerbenamram in [#393](https://github.com/PyO3/pyo3/pull/393) - Have `PyModule` generate an index of its members (`__all__` list). - Allow `slf: PyRef` for pyclass(#419) - Allow to use lifetime specifiers in `pymethods` - Add `marshal` module. [#460](https://github.com/PyO3/pyo3/pull/460) ### Changed - `Python::run` returns `PyResult<()>` instead of `PyResult<&PyAny>`. - Methods decorated with `#[getter]` and `#[setter]` can now omit wrapping the result type in `PyResult` if they don't raise exceptions. ### Fixed - `type_object::PyTypeObject` has been marked unsafe because breaking the contract `type_object::PyTypeObject::init_type` can lead to UB. - Fixed automatic derive of `PySequenceProtocol` implementation in [#423](https://github.com/PyO3/pyo3/pull/423). - Capitalization & better wording to README.md. - Docstrings of properties is now properly set using the doc of the `#[getter]` method. - Fixed issues with `pymethods` crashing on doc comments containing double quotes. - `PySet::new` and `PyFrozenSet::new` now return `PyResult<&Py[Frozen]Set>`; exceptions are raised if the items are not hashable. - Fixed building using `venv` on Windows. - `PyTuple::new` now returns `&PyTuple` instead of `Py`. - Fixed several issues with argument parsing; notable, the `*args` and `**kwargs` tuple/dict now doesn't contain arguments that are otherwise assigned to parameters. ## [0.6.0] - 2019-03-28 ### Regressions - Currently, [#341](https://github.com/PyO3/pyo3/issues/341) causes `cargo test` to fail with weird linking errors when the `extension-module` feature is activated. For now you can work around this by making the `extension-module` feature optional and running the tests with `cargo test --no-default-features`: ```toml [dependencies.pyo3] version = "0.6.0" [features] extension-module = ["pyo3/extension-module"] default = ["extension-module"] ``` ### Added - Added a `wrap_pymodule!` macro similar to the existing `wrap_pyfunction!` macro. Only available on python 3 - Added support for cross compiling (e.g. to arm v7) by mtp401 in [#327](https://github.com/PyO3/pyo3/pull/327). See the "Cross Compiling" section in the "Building and Distribution" chapter of the guide for more details. - The `PyRef` and `PyRefMut` types, which allow to differentiate between an instance of a rust struct on the rust heap and an instance that is embedded inside a python object. By kngwyu in [#335](https://github.com/PyO3/pyo3/pull/335) - Added `FromPy` and `IntoPy` which are equivalent to `From` and `Into` except that they require a gil token. - Added `ManagedPyRef`, which should eventually replace `ToBorrowedObject`. ### Changed - Renamed `PyObjectRef` to `PyAny` in #388 - Renamed `add_function` to `add_wrapped` as it now also supports modules. - Renamed `#[pymodinit]` to `#[pymodule]` - `py.init(|| value)` becomes `Py::new(value)` - `py.init_ref(|| value)` becomes `PyRef::new(value)` - `py.init_mut(|| value)` becomes `PyRefMut::new(value)`. - `PyRawObject::init` is now infallible, e.g. it returns `()` instead of `PyResult<()>`. - Renamed `py_exception!` to `create_exception!` and refactored the error macros. - Renamed `wrap_function!` to `wrap_pyfunction!` - Renamed `#[prop(get, set)]` to `#[pyo3(get, set)]` - `#[pyfunction]` now supports the same arguments as `#[pyfn()]` - Some macros now emit proper spanned errors instead of panics. - Migrated to the 2018 edition - `crate::types::exceptions` moved to `crate::exceptions` - Replace `IntoPyTuple` with `IntoPy>`. - `IntoPyPointer` and `ToPyPointer` moved into the crate root. - `class::CompareOp` moved into `class::basic::CompareOp` - PyTypeObject is now a direct subtrait PyTypeCreate, removing the old cyclical implementation in [#350](https://github.com/PyO3/pyo3/pull/350) - Add `PyList::{sort, reverse}` by chr1sj0nes in [#357](https://github.com/PyO3/pyo3/pull/357) and [#358](https://github.com/PyO3/pyo3/pull/358) - Renamed the `typeob` module to `type_object` ### Removed - `PyToken` was removed due to unsoundness (See [#94](https://github.com/PyO3/pyo3/issues/94)). - Removed the unnecessary type parameter from `PyObjectAlloc` - `NoArgs`. Just use an empty tuple - `PyObjectWithGIL`. `PyNativeType` is sufficient now that PyToken is removed. ### Fixed - A soudness hole where every instances of a `#[pyclass]` struct was considered to be part of a python object, even though you can create instances that are not part of the python heap. This was fixed through `PyRef` and `PyRefMut`. - Fix kwargs support in [#328](https://github.com/PyO3/pyo3/pull/328). - Add full support for `__dict__` in [#403](https://github.com/PyO3/pyo3/pull/403). ## [0.5.3] - 2019-01-04 ### Fixed - Fix memory leak in ArrayList by kngwyu [#316](https://github.com/PyO3/pyo3/pull/316) ## [0.5.2] - 2018-11-25 ### Fixed - Fix undeterministic segfaults when creating many objects by kngwyu in [#281](https://github.com/PyO3/pyo3/pull/281) ## [0.5.1] - 2018-11-24 Yanked ## [0.5.0] - 2018-11-11 ### Added - `#[pyclass]` objects can now be returned from rust functions - `PyComplex` by kngwyu in [#226](https://github.com/PyO3/pyo3/pull/226) - `PyDict::from_sequence`, equivalent to `dict([(key, val), ...])` - Bindings for the `datetime` standard library types: `PyDate`, `PyTime`, `PyDateTime`, `PyTzInfo`, `PyDelta` with associated `ffi` types, by pganssle [#200](https://github.com/PyO3/pyo3/pull/200). - `PyString`, `PyUnicode`, and `PyBytes` now have an `as_bytes` method that returns `&[u8]`. - `PyObjectProtocol::get_type_ptr` by ijl in [#242](https://github.com/PyO3/pyo3/pull/242) ### Changed - Removes the types from the root module and the prelude. They now live in `pyo3::types` instead. - All exceptions are constructed with `py_err` instead of `new`, as they return `PyErr` and not `Self`. - `as_mut` and friends take and `&mut self` instead of `&self` - `ObjectProtocol::call` now takes an `Option<&PyDict>` for the kwargs instead of an `IntoPyDictPointer`. - `IntoPyDictPointer` was replace by `IntoPyDict` which doesn't convert `PyDict` itself anymore and returns a `PyDict` instead of `*mut PyObject`. - `PyTuple::new` now takes an `IntoIterator` instead of a slice - Updated to syn 0.15 - Splitted `PyTypeObject` into `PyTypeObject` without the create method and `PyTypeCreate` with requires `PyObjectAlloc + PyTypeInfo + Sized`. - Ran `cargo edition --fix` which prefixed path with `crate::` for rust 2018 - Renamed `async` to `pyasync` as async will be a keyword in the 2018 edition. - Starting to use `NonNull<*mut PyObject>` for Py and PyObject by ijl [#260](https://github.com/PyO3/pyo3/pull/260) ### Removed - Removed most entries from the prelude. The new prelude is small and clear. - Slowly removing specialization uses - `PyString`, `PyUnicode`, and `PyBytes` no longer have a `data` method (replaced by `as_bytes`) and `PyStringData` has been removed. - The pyobject_extract macro ### Fixed - Added an explanation that the GIL can temporarily be released even while holding a GILGuard. - Lots of clippy errors - Fix segfault on calling an unknown method on a PyObject - Work around a [bug](https://github.com/rust-lang/rust/issues/55380) in the rust compiler by kngwyu [#252](https://github.com/PyO3/pyo3/pull/252) - Fixed a segfault with subclassing pyo3 create classes and using `__class__` by kngwyu [#263](https://github.com/PyO3/pyo3/pull/263) ## [0.4.1] - 2018-08-20 ### Changed - PyTryFrom's error is always to `PyDowncastError` ### Fixed - Fixed compilation on nightly since `use_extern_macros` was stabilized ### Removed - The pyobject_downcast macro ## [0.4.0] - 2018-07-30 ### Changed - Merged both examples into one - Rustfmt all the things :heavy_check_mark: - Switched to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Removed - Conversions from tuples to PyDict due to [rust-lang/rust#52050](https://github.com/rust-lang/rust/issues/52050) ## [0.3.2] - 2018-07-22 ### Changed - Replaced `concat_idents` with mashup ## [0.3.1] - 2018-07-18 ### Fixed - Fixed scoping bug in pyobject_native_type that would break rust-numpy ## [0.3.0] - 2018-07-18 ### Added - A few internal macros became part of the public api ([#155](https://github.com/PyO3/pyo3/pull/155), [#186](https://github.com/PyO3/pyo3/pull/186)) - Always clone in getters. This allows using the get-annotation on all Clone-Types ### Changed - Upgraded to syn 0.14 which means much better error messages :tada: - 128 bit integer support by [kngwyu](https://github.com/kngwyu) ([#137](https://github.com/PyO3/pyo3/pull/173)) - `proc_macro` has been stabilized on nightly ([rust-lang/rust#52081](https://github.com/rust-lang/rust/pull/52081)). This means that we can remove the `proc_macro` feature, but now we need the `use_extern_macros` from the 2018 edition instead. - All proc macro are now prefixed with `py` and live in the prelude. This means you can use `#[pyclass]`, `#[pymethods]`, `#[pyproto]`, `#[pyfunction]` and `#[pymodinit]` directly, at least after a `use pyo3::prelude::*`. They were also moved into a module called `proc_macro`. You shouldn't use `#[pyo3::proc_macro::pyclass]` or other longer paths in attributes because `proc_macro_path_invoc` isn't going to be stabilized soon. - Renamed the `base` option in the `pyclass` macro to `extends`. - `#[pymodinit]` uses the function name as module name, unless the name is overrriden with `#[pymodinit(name)]` - The guide is now properly versioned. ## [0.2.7] - 2018-05-18 ### Fixed - Fix nightly breakage with proc_macro_path ## [0.2.6] - 2018-04-03 ### Fixed - Fix compatibility with TryFrom trait #137 ## [0.2.5] - 2018-02-21 ### Added - CPython 3.7 support ### Fixed - Embedded CPython 3.7b1 crashes on initialization #110 - Generated extension functions are weakly typed #108 - call_method\* crashes when the method does not exist #113 - Allow importing exceptions from nested modules #116 ## [0.2.4] - 2018-01-19 ### Added - Allow to get mutable ref from PyObject #106 - Drop `RefFromPyObject` trait - Add Python::register_any method ### Fixed - Fix impl `FromPyObject` for `Py` - Mark method that work with raw pointers as unsafe #95 ## [0.2.3] - 11-27-2017 ### Changed - Rustup to 1.23.0-nightly 2017-11-07 ### Fixed - Proper `c_char` usage #93 ### Removed - Remove use of now unneeded 'AsciiExt' trait ## [0.2.2] - 09-26-2017 ### Changed - Rustup to 1.22.0-nightly 2017-09-30 ## [0.2.1] - 09-26-2017 ### Fixed - Fix rustc const_fn nightly breakage ## [0.2.0] - 08-12-2017 ### Added - Added inheritance support #15 - Added weakref support #56 - Added subclass support #64 - Added `self.__dict__` supoort #68 - Added `pyo3::prelude` module #70 - Better `Iterator` support for PyTuple, PyList, PyDict #75 - Introduce IntoPyDictPointer similar to IntoPyTuple #69 ### Changed - Allow to add gc support without implementing PyGCProtocol #57 - Refactor `PyErr` implementation. Drop `py` parameter from constructor. ## [0.1.0] - 07-23-2017 ### Added - Initial release [Unreleased]: https://github.com/pyo3/pyo3/compare/v0.25.1...HEAD [0.25.0]: https://github.com/pyo3/pyo3/compare/v0.25.0...v0.25.1 [0.25.0]: https://github.com/pyo3/pyo3/compare/v0.24.2...v0.25.0 [0.24.2]: https://github.com/pyo3/pyo3/compare/v0.24.1...v0.24.2 [0.24.1]: https://github.com/pyo3/pyo3/compare/v0.24.0...v0.24.1 [0.24.0]: https://github.com/pyo3/pyo3/compare/v0.23.5...v0.24.0 [0.23.5]: https://github.com/pyo3/pyo3/compare/v0.23.4...v0.23.5 [0.23.4]: https://github.com/pyo3/pyo3/compare/v0.23.3...v0.23.4 [0.23.3]: https://github.com/pyo3/pyo3/compare/v0.23.2...v0.23.3 [0.23.2]: https://github.com/pyo3/pyo3/compare/v0.23.1...v0.23.2 [0.23.1]: https://github.com/pyo3/pyo3/compare/v0.23.0...v0.23.1 [0.23.0]: https://github.com/pyo3/pyo3/compare/v0.22.5...v0.23.0 [0.22.5]: https://github.com/pyo3/pyo3/compare/v0.22.4...v0.22.5 [0.22.4]: https://github.com/pyo3/pyo3/compare/v0.22.3...v0.22.4 [0.22.3]: https://github.com/pyo3/pyo3/compare/v0.22.2...v0.22.3 [0.22.2]: https://github.com/pyo3/pyo3/compare/v0.22.1...v0.22.2 [0.22.1]: https://github.com/pyo3/pyo3/compare/v0.22.0...v0.22.1 [0.22.0]: https://github.com/pyo3/pyo3/compare/v0.21.2...v0.22.0 [0.21.2]: https://github.com/pyo3/pyo3/compare/v0.21.1...v0.21.2 [0.21.1]: https://github.com/pyo3/pyo3/compare/v0.21.0...v0.21.1 [0.21.0]: https://github.com/pyo3/pyo3/compare/v0.20.3...v0.21.0 [0.21.0-beta.0]: https://github.com/pyo3/pyo3/compare/v0.20.3...v0.21.0-beta.0 [0.20.3]: https://github.com/pyo3/pyo3/compare/v0.20.2...v0.20.3 [0.20.2]: https://github.com/pyo3/pyo3/compare/v0.20.1...v0.20.2 [0.20.1]: https://github.com/pyo3/pyo3/compare/v0.20.0...v0.20.1 [0.20.0]: https://github.com/pyo3/pyo3/compare/v0.19.2...v0.20.0 [0.19.2]: https://github.com/pyo3/pyo3/compare/v0.19.1...v0.19.2 [0.19.1]: https://github.com/pyo3/pyo3/compare/v0.19.0...v0.19.1 [0.19.0]: https://github.com/pyo3/pyo3/compare/v0.18.3...v0.19.0 [0.18.3]: https://github.com/pyo3/pyo3/compare/v0.18.2...v0.18.3 [0.18.2]: https://github.com/pyo3/pyo3/compare/v0.18.1...v0.18.2 [0.18.1]: https://github.com/pyo3/pyo3/compare/v0.18.0...v0.18.1 [0.18.0]: https://github.com/pyo3/pyo3/compare/v0.17.3...v0.18.0 [0.17.3]: https://github.com/pyo3/pyo3/compare/v0.17.2...v0.17.3 [0.17.2]: https://github.com/pyo3/pyo3/compare/v0.17.1...v0.17.2 [0.17.1]: https://github.com/pyo3/pyo3/compare/v0.17.0...v0.17.1 [0.17.0]: https://github.com/pyo3/pyo3/compare/v0.16.6...v0.17.0 [0.16.6]: https://github.com/pyo3/pyo3/compare/v0.16.5...v0.16.6 [0.16.5]: https://github.com/pyo3/pyo3/compare/v0.16.4...v0.16.5 [0.16.4]: https://github.com/pyo3/pyo3/compare/v0.16.3...v0.16.4 [0.16.3]: https://github.com/pyo3/pyo3/compare/v0.16.2...v0.16.3 [0.16.2]: https://github.com/pyo3/pyo3/compare/v0.16.1...v0.16.2 [0.16.1]: https://github.com/pyo3/pyo3/compare/v0.16.0...v0.16.1 [0.16.0]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.16.0 [0.15.2]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.15.2 [0.15.1]: https://github.com/pyo3/pyo3/compare/v0.15.0...v0.15.1 [0.15.0]: https://github.com/pyo3/pyo3/compare/v0.14.5...v0.15.0 [0.14.5]: https://github.com/pyo3/pyo3/compare/v0.14.4...v0.14.5 [0.14.4]: https://github.com/pyo3/pyo3/compare/v0.14.3...v0.14.4 [0.14.3]: https://github.com/pyo3/pyo3/compare/v0.14.2...v0.14.3 [0.14.2]: https://github.com/pyo3/pyo3/compare/v0.14.1...v0.14.2 [0.14.1]: https://github.com/pyo3/pyo3/compare/v0.14.0...v0.14.1 [0.14.0]: https://github.com/pyo3/pyo3/compare/v0.13.2...v0.14.0 [0.13.2]: https://github.com/pyo3/pyo3/compare/v0.13.1...v0.13.2 [0.13.1]: https://github.com/pyo3/pyo3/compare/v0.13.0...v0.13.1 [0.13.0]: https://github.com/pyo3/pyo3/compare/v0.12.4...v0.13.0 [0.12.4]: https://github.com/pyo3/pyo3/compare/v0.12.3...v0.12.4 [0.12.3]: https://github.com/pyo3/pyo3/compare/v0.12.2...v0.12.3 [0.12.2]: https://github.com/pyo3/pyo3/compare/v0.12.1...v0.12.2 [0.12.1]: https://github.com/pyo3/pyo3/compare/v0.12.0...v0.12.1 [0.12.0]: https://github.com/pyo3/pyo3/compare/v0.11.1...v0.12.0 [0.11.1]: https://github.com/pyo3/pyo3/compare/v0.11.0...v0.11.1 [0.11.0]: https://github.com/pyo3/pyo3/compare/v0.10.1...v0.11.0 [0.10.1]: https://github.com/pyo3/pyo3/compare/v0.10.0...v0.10.1 [0.10.0]: https://github.com/pyo3/pyo3/compare/v0.9.2...v0.10.0 [0.9.2]: https://github.com/pyo3/pyo3/compare/v0.9.1...v0.9.2 [0.9.1]: https://github.com/pyo3/pyo3/compare/v0.9.0...v0.9.1 [0.9.0]: https://github.com/pyo3/pyo3/compare/v0.8.5...v0.9.0 [0.8.5]: https://github.com/pyo3/pyo3/compare/v0.8.4...v0.8.5 [0.8.4]: https://github.com/pyo3/pyo3/compare/v0.8.3...v0.8.4 [0.8.3]: https://github.com/pyo3/pyo3/compare/v0.8.2...v0.8.3 [0.8.2]: https://github.com/pyo3/pyo3/compare/v0.8.1...v0.8.2 [0.8.1]: https://github.com/pyo3/pyo3/compare/v0.8.0...v0.8.1 [0.8.0]: https://github.com/pyo3/pyo3/compare/v0.7.0...v0.8.0 [0.7.0]: https://github.com/pyo3/pyo3/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/pyo3/pyo3/compare/v0.5.3...v0.6.0 [0.5.3]: https://github.com/pyo3/pyo3/compare/v0.5.2...v0.5.3 [0.5.2]: https://github.com/pyo3/pyo3/compare/v0.5.1...v0.5.2 [0.5.1]: https://github.com/pyo3/pyo3/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/pyo3/pyo3/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/pyo3/pyo3/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/pyo3/pyo3/compare/v0.3.2...v0.4.0 [0.3.2]: https://github.com/pyo3/pyo3/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/pyo3/pyo3/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/pyo3/pyo3/compare/v0.2.7...v0.3.0 [0.2.7]: https://github.com/pyo3/pyo3/compare/v0.2.6...v0.2.7 [0.2.6]: https://github.com/pyo3/pyo3/compare/v0.2.5...v0.2.6 [0.2.5]: https://github.com/pyo3/pyo3/compare/v0.2.4...v0.2.5 [0.2.4]: https://github.com/pyo3/pyo3/compare/v0.2.3...v0.2.4 [0.2.3]: https://github.com/pyo3/pyo3/compare/v0.2.2...v0.2.3 [0.2.2]: https://github.com/pyo3/pyo3/compare/v0.2.1...v0.2.2 [0.2.1]: https://github.com/pyo3/pyo3/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/pyo3/pyo3/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/PyO3/pyo3/tree/0.1.0 pyo3/src/0000775000175000017500000000000015105742312012065 5ustar bdrungbdrungpyo3/src/internal/0000775000175000017500000000000015105742312013701 5ustar bdrungbdrungpyo3/src/internal/get_slot.rs0000644000175000017500000002443315105742312016073 0ustar bdrungbdrunguse crate::{ ffi, types::{PyType, PyTypeMethods}, Borrowed, Bound, }; use std::os::raw::c_int; impl Bound<'_, PyType> { #[inline] pub(crate) fn get_slot(&self, slot: Slot) -> as GetSlotImpl>::Type where Slot: GetSlotImpl, { // SAFETY: `self` is a valid type object. unsafe { slot.get_slot( self.as_type_ptr(), #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] is_runtime_3_10(self.py()), ) } } } impl Borrowed<'_, '_, PyType> { #[inline] pub(crate) fn get_slot(self, slot: Slot) -> as GetSlotImpl>::Type where Slot: GetSlotImpl, { // SAFETY: `self` is a valid type object. unsafe { slot.get_slot( self.as_type_ptr(), #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] is_runtime_3_10(self.py()), ) } } } /// Gets a slot from a raw FFI pointer. /// /// Safety: /// - `ty` must be a valid non-null pointer to a `PyTypeObject`. /// - The Python runtime must be initialized pub(crate) unsafe fn get_slot( ty: *mut ffi::PyTypeObject, slot: Slot, ) -> as GetSlotImpl>::Type where Slot: GetSlotImpl, { unsafe { slot.get_slot( ty, // SAFETY: the Python runtime is initialized #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] is_runtime_3_10(crate::Python::assume_gil_acquired()), ) } } pub(crate) trait GetSlotImpl { type Type; /// Gets the requested slot from a type object. /// /// Safety: /// - `ty` must be a valid non-null pointer to a `PyTypeObject`. /// - `is_runtime_3_10` must be `false` if the runtime is not Python 3.10 or later. unsafe fn get_slot( self, ty: *mut ffi::PyTypeObject, #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] is_runtime_3_10: bool, ) -> Self::Type; } #[derive(Copy, Clone)] pub(crate) struct Slot; macro_rules! impl_slots { ($($name:ident: ($slot:ident, $field:ident) -> $tp:ty),+ $(,)?) => { $( pub (crate) const $name: Slot<{ ffi::$slot }> = Slot; impl GetSlotImpl for Slot<{ ffi::$slot }> { type Type = $tp; #[inline] unsafe fn get_slot( self, ty: *mut ffi::PyTypeObject, #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] is_runtime_3_10: bool ) -> Self::Type { #[cfg(not(Py_LIMITED_API))] { unsafe {(*ty).$field } } #[cfg(Py_LIMITED_API)] { #[cfg(not(Py_3_10))] { // Calling PyType_GetSlot on static types is not valid before Python 3.10 // ... so the workaround is to first do a runtime check for these versions // (3.7, 3.8, 3.9) and then look in the type object anyway. This is only ok // because we know that the interpreter is not going to change the size // of the type objects for these historical versions. if !is_runtime_3_10 && unsafe {ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE)} == 0 { return unsafe {(*ty.cast::()).$field}; } } // SAFETY: slot type is set carefully to be valid unsafe {std::mem::transmute(ffi::PyType_GetSlot(ty, ffi::$slot))} } } } )* }; } // Slots are implemented on-demand as needed.) impl_slots! { TP_ALLOC: (Py_tp_alloc, tp_alloc) -> Option, TP_BASE: (Py_tp_base, tp_base) -> *mut ffi::PyTypeObject, TP_CLEAR: (Py_tp_clear, tp_clear) -> Option, TP_DESCR_GET: (Py_tp_descr_get, tp_descr_get) -> Option, TP_FREE: (Py_tp_free, tp_free) -> Option, TP_TRAVERSE: (Py_tp_traverse, tp_traverse) -> Option, } #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] fn is_runtime_3_10(py: crate::Python<'_>) -> bool { use crate::sync::GILOnceCell; static IS_RUNTIME_3_10: GILOnceCell = GILOnceCell::new(); *IS_RUNTIME_3_10.get_or_init(py, || py.version_info() >= (3, 10)) } #[repr(C)] #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] pub struct PyNumberMethods39Snapshot { pub nb_add: Option, pub nb_subtract: Option, pub nb_multiply: Option, pub nb_remainder: Option, pub nb_divmod: Option, pub nb_power: Option, pub nb_negative: Option, pub nb_positive: Option, pub nb_absolute: Option, pub nb_bool: Option, pub nb_invert: Option, pub nb_lshift: Option, pub nb_rshift: Option, pub nb_and: Option, pub nb_xor: Option, pub nb_or: Option, pub nb_int: Option, pub nb_reserved: *mut std::os::raw::c_void, pub nb_float: Option, pub nb_inplace_add: Option, pub nb_inplace_subtract: Option, pub nb_inplace_multiply: Option, pub nb_inplace_remainder: Option, pub nb_inplace_power: Option, pub nb_inplace_lshift: Option, pub nb_inplace_rshift: Option, pub nb_inplace_and: Option, pub nb_inplace_xor: Option, pub nb_inplace_or: Option, pub nb_floor_divide: Option, pub nb_true_divide: Option, pub nb_inplace_floor_divide: Option, pub nb_inplace_true_divide: Option, pub nb_index: Option, pub nb_matrix_multiply: Option, pub nb_inplace_matrix_multiply: Option, } #[repr(C)] #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] pub struct PySequenceMethods39Snapshot { pub sq_length: Option, pub sq_concat: Option, pub sq_repeat: Option, pub sq_item: Option, pub was_sq_slice: *mut std::os::raw::c_void, pub sq_ass_item: Option, pub was_sq_ass_slice: *mut std::os::raw::c_void, pub sq_contains: Option, pub sq_inplace_concat: Option, pub sq_inplace_repeat: Option, } #[repr(C)] #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] pub struct PyMappingMethods39Snapshot { pub mp_length: Option, pub mp_subscript: Option, pub mp_ass_subscript: Option, } #[repr(C)] #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] pub struct PyAsyncMethods39Snapshot { pub am_await: Option, pub am_aiter: Option, pub am_anext: Option, } #[repr(C)] #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] pub struct PyBufferProcs39Snapshot { // not available in limited api, but structure needs to have the right size pub bf_getbuffer: *mut std::os::raw::c_void, pub bf_releasebuffer: *mut std::os::raw::c_void, } /// Snapshot of the structure of PyTypeObject for Python 3.7 through 3.9. /// /// This is used as a fallback for static types in abi3 when the Python version is less than 3.10; /// this is a bit of a hack but there's no better option and the structure of the type object is /// not going to change for those historical versions. #[repr(C)] #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] struct PyTypeObject39Snapshot { pub ob_base: ffi::PyVarObject, pub tp_name: *const std::os::raw::c_char, pub tp_basicsize: ffi::Py_ssize_t, pub tp_itemsize: ffi::Py_ssize_t, pub tp_dealloc: Option, #[cfg(not(Py_3_8))] pub tp_print: *mut std::os::raw::c_void, // stubbed out, not available in limited API #[cfg(Py_3_8)] pub tp_vectorcall_offset: ffi::Py_ssize_t, pub tp_getattr: Option, pub tp_setattr: Option, pub tp_as_async: *mut PyAsyncMethods39Snapshot, pub tp_repr: Option, pub tp_as_number: *mut PyNumberMethods39Snapshot, pub tp_as_sequence: *mut PySequenceMethods39Snapshot, pub tp_as_mapping: *mut PyMappingMethods39Snapshot, pub tp_hash: Option, pub tp_call: Option, pub tp_str: Option, pub tp_getattro: Option, pub tp_setattro: Option, pub tp_as_buffer: *mut PyBufferProcs39Snapshot, pub tp_flags: std::os::raw::c_ulong, pub tp_doc: *const std::os::raw::c_char, pub tp_traverse: Option, pub tp_clear: Option, pub tp_richcompare: Option, pub tp_weaklistoffset: ffi::Py_ssize_t, pub tp_iter: Option, pub tp_iternext: Option, pub tp_methods: *mut ffi::PyMethodDef, pub tp_members: *mut ffi::PyMemberDef, pub tp_getset: *mut ffi::PyGetSetDef, pub tp_base: *mut ffi::PyTypeObject, pub tp_dict: *mut ffi::PyObject, pub tp_descr_get: Option, pub tp_descr_set: Option, pub tp_dictoffset: ffi::Py_ssize_t, pub tp_init: Option, pub tp_alloc: Option, pub tp_new: Option, pub tp_free: Option, pub tp_is_gc: Option, pub tp_bases: *mut ffi::PyObject, pub tp_mro: *mut ffi::PyObject, pub tp_cache: *mut ffi::PyObject, pub tp_subclasses: *mut ffi::PyObject, pub tp_weaklist: *mut ffi::PyObject, pub tp_del: Option, pub tp_version_tag: std::os::raw::c_uint, pub tp_finalize: Option, #[cfg(Py_3_8)] pub tp_vectorcall: Option, } pyo3/src/sealed.rs0000644000175000017500000000435115105742312013671 0ustar bdrungbdrunguse crate::types::{ PyBool, PyByteArray, PyBytes, PyCapsule, PyComplex, PyDict, PyFloat, PyFrozenSet, PyList, PyMapping, PyMappingProxy, PyModule, PyRange, PySequence, PySet, PySlice, PyString, PyTraceback, PyTuple, PyType, PyWeakref, PyWeakrefProxy, PyWeakrefReference, }; use crate::{ffi, Bound, PyAny, PyResult}; use crate::pyclass_init::PyClassInitializer; use crate::impl_::{ pyclass_init::PyNativeTypeInitializer, pymethods::PyMethodDef, pymodule::{AddClassToModule, AddTypeToModule, ModuleDef}, }; pub trait Sealed {} // for FfiPtrExt impl Sealed for *mut ffi::PyObject {} // for PyResultExt impl Sealed for PyResult> {} // for Py(...)Methods impl Sealed for Bound<'_, PyAny> {} impl Sealed for Bound<'_, PyBool> {} impl Sealed for Bound<'_, PyByteArray> {} impl Sealed for Bound<'_, PyBytes> {} impl Sealed for Bound<'_, PyCapsule> {} impl Sealed for Bound<'_, PyComplex> {} impl Sealed for Bound<'_, PyDict> {} impl Sealed for Bound<'_, PyFloat> {} impl Sealed for Bound<'_, PyFrozenSet> {} impl Sealed for Bound<'_, PyList> {} impl Sealed for Bound<'_, PyMapping> {} impl Sealed for Bound<'_, PyMappingProxy> {} impl Sealed for Bound<'_, PyModule> {} impl Sealed for Bound<'_, PyRange> {} impl Sealed for Bound<'_, PySequence> {} impl Sealed for Bound<'_, PySet> {} impl Sealed for Bound<'_, PySlice> {} impl Sealed for Bound<'_, PyString> {} impl Sealed for Bound<'_, PyTraceback> {} impl Sealed for Bound<'_, PyTuple> {} impl Sealed for Bound<'_, PyType> {} impl Sealed for Bound<'_, PyWeakref> {} impl Sealed for Bound<'_, PyWeakrefProxy> {} impl Sealed for Bound<'_, PyWeakrefReference> {} impl Sealed for AddTypeToModule {} impl Sealed for AddClassToModule {} impl Sealed for PyMethodDef {} impl Sealed for ModuleDef {} impl Sealed for PyNativeTypeInitializer {} impl Sealed for PyClassInitializer {} impl Sealed for std::sync::Once {} impl Sealed for std::sync::Mutex {} #[cfg(feature = "lock_api")] impl Sealed for lock_api::Mutex {} #[cfg(feature = "parking_lot")] impl Sealed for parking_lot::Once {} #[cfg(feature = "arc_lock")] impl Sealed for std::sync::Arc> {} pyo3/src/type_object.rs0000644000175000017500000000710415105742312014742 0ustar bdrungbdrung//! Python type object information use crate::ffi_ptr_ext::FfiPtrExt; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyType}; use crate::{ffi, Bound, Python}; use std::ptr; /// `T: PyLayout` represents that `T` is a concrete representation of `U` in the Python heap. /// E.g., `PyClassObject` is a concrete representation of all `pyclass`es, and `ffi::PyObject` /// is of `PyAny`. /// /// This trait is intended to be used internally. /// /// # Safety /// /// This trait must only be implemented for types which represent valid layouts of Python objects. pub unsafe trait PyLayout {} /// `T: PySizedLayout` represents that `T` is not a instance of /// [`PyVarObject`](https://docs.python.org/3/c-api/structures.html#c.PyVarObject). /// /// In addition, that `T` is a concrete representation of `U`. pub trait PySizedLayout: PyLayout + Sized {} /// Python type information. /// All Python native types (e.g., `PyDict`) and `#[pyclass]` structs implement this trait. /// /// This trait is marked unsafe because: /// - specifying the incorrect layout can lead to memory errors /// - the return value of type_object must always point to the same PyTypeObject instance /// /// It is safely implemented by the `pyclass` macro. /// /// # Safety /// /// Implementations must provide an implementation for `type_object_raw` which infallibly produces a /// non-null pointer to the corresponding Python type object. pub unsafe trait PyTypeInfo: Sized { /// Class name. const NAME: &'static str; /// Module name, if any. const MODULE: Option<&'static str>; /// Returns the PyTypeObject instance for this type. fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject; /// Returns the safe abstraction over the type object. #[inline] fn type_object(py: Python<'_>) -> Bound<'_, PyType> { // Making the borrowed object `Bound` is necessary for soundness reasons. It's an extreme // edge case, but arbitrary Python code _could_ change the __class__ of an object and cause // the type object to be freed. // // By making `Bound` we assume ownership which is then safe against races. unsafe { Self::type_object_raw(py) .cast::() .assume_borrowed_unchecked(py) .to_owned() .downcast_into_unchecked() } } /// Checks if `object` is an instance of this type or a subclass of this type. #[inline] fn is_type_of(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 } } /// Checks if `object` is an instance of this type. #[inline] fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool { unsafe { ptr::eq( ffi::Py_TYPE(object.as_ptr()), Self::type_object_raw(object.py()), ) } } } /// Implemented by types which can be used as a concrete Python type inside `Py` smart pointers. pub trait PyTypeCheck { /// Name of self. This is used in error messages, for example. const NAME: &'static str; /// Checks if `object` is an instance of `Self`, which may include a subtype. /// /// This should be equivalent to the Python expression `isinstance(object, Self)`. fn type_check(object: &Bound<'_, PyAny>) -> bool; } impl PyTypeCheck for T where T: PyTypeInfo, { const NAME: &'static str = ::NAME; #[inline] fn type_check(object: &Bound<'_, PyAny>) -> bool { T::is_type_of(object) } } pyo3/src/buffer.rs0000644000175000017500000010416215105742312013706 0ustar bdrungbdrung#![cfg(any(not(Py_LIMITED_API), Py_3_11))] // Copyright (c) 2017 Daniel Grunwald // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. //! `PyBuffer` implementation use crate::Bound; use crate::{err, exceptions::PyBufferError, ffi, FromPyObject, PyAny, PyResult, Python}; use std::marker::PhantomData; use std::os::raw; use std::pin::Pin; use std::{cell, mem, ptr, slice}; use std::{ffi::CStr, fmt::Debug}; /// Allows access to the underlying buffer used by a python object such as `bytes`, `bytearray` or `array.array`. // use Pin because Python expects that the Py_buffer struct has a stable memory address #[repr(transparent)] pub struct PyBuffer(Pin>, PhantomData); // PyBuffer is thread-safe: the shape of the buffer is immutable while a Py_buffer exists. // Accessing the buffer contents is protected using the GIL. unsafe impl Send for PyBuffer {} unsafe impl Sync for PyBuffer {} impl Debug for PyBuffer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("PyBuffer") .field("buf", &self.0.buf) .field("obj", &self.0.obj) .field("len", &self.0.len) .field("itemsize", &self.0.itemsize) .field("readonly", &self.0.readonly) .field("ndim", &self.0.ndim) .field("format", &self.0.format) .field("shape", &self.0.shape) .field("strides", &self.0.strides) .field("suboffsets", &self.0.suboffsets) .field("internal", &self.0.internal) .finish() } } /// Represents the type of a Python buffer element. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ElementType { /// A signed integer type. SignedInteger { /// The width of the signed integer in bytes. bytes: usize, }, /// An unsigned integer type. UnsignedInteger { /// The width of the unsigned integer in bytes. bytes: usize, }, /// A boolean type. Bool, /// A float type. Float { /// The width of the float in bytes. bytes: usize, }, /// An unknown type. This may occur when parsing has failed. Unknown, } impl ElementType { /// Determines the `ElementType` from a Python `struct` module format string. /// /// See for more information /// about struct format strings. pub fn from_format(format: &CStr) -> ElementType { match format.to_bytes() { [size] | [b'@', size] => native_element_type_from_type_char(*size), [b'=' | b'<' | b'>' | b'!', size] => standard_element_type_from_type_char(*size), _ => ElementType::Unknown, } } } fn native_element_type_from_type_char(type_char: u8) -> ElementType { use self::ElementType::*; match type_char { b'c' => UnsignedInteger { bytes: mem::size_of::(), }, b'b' => SignedInteger { bytes: mem::size_of::(), }, b'B' => UnsignedInteger { bytes: mem::size_of::(), }, b'?' => Bool, b'h' => SignedInteger { bytes: mem::size_of::(), }, b'H' => UnsignedInteger { bytes: mem::size_of::(), }, b'i' => SignedInteger { bytes: mem::size_of::(), }, b'I' => UnsignedInteger { bytes: mem::size_of::(), }, b'l' => SignedInteger { bytes: mem::size_of::(), }, b'L' => UnsignedInteger { bytes: mem::size_of::(), }, b'q' => SignedInteger { bytes: mem::size_of::(), }, b'Q' => UnsignedInteger { bytes: mem::size_of::(), }, b'n' => SignedInteger { bytes: mem::size_of::(), }, b'N' => UnsignedInteger { bytes: mem::size_of::(), }, b'e' => Float { bytes: 2 }, b'f' => Float { bytes: 4 }, b'd' => Float { bytes: 8 }, _ => Unknown, } } fn standard_element_type_from_type_char(type_char: u8) -> ElementType { use self::ElementType::*; match type_char { b'c' | b'B' => UnsignedInteger { bytes: 1 }, b'b' => SignedInteger { bytes: 1 }, b'?' => Bool, b'h' => SignedInteger { bytes: 2 }, b'H' => UnsignedInteger { bytes: 2 }, b'i' | b'l' => SignedInteger { bytes: 4 }, b'I' | b'L' => UnsignedInteger { bytes: 4 }, b'q' => SignedInteger { bytes: 8 }, b'Q' => UnsignedInteger { bytes: 8 }, b'e' => Float { bytes: 2 }, b'f' => Float { bytes: 4 }, b'd' => Float { bytes: 8 }, _ => Unknown, } } #[cfg(target_endian = "little")] fn is_matching_endian(c: u8) -> bool { c == b'@' || c == b'=' || c == b'>' } #[cfg(target_endian = "big")] fn is_matching_endian(c: u8) -> bool { c == b'@' || c == b'=' || c == b'>' || c == b'!' } /// Trait implemented for possible element types of `PyBuffer`. /// /// # Safety /// /// This trait must only be implemented for types which represent valid elements of Python buffers. pub unsafe trait Element: Copy { /// Gets whether the element specified in the format string is potentially compatible. /// Alignment and size are checked separately from this function. fn is_compatible_format(format: &CStr) -> bool; } impl FromPyObject<'_> for PyBuffer { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult> { Self::get(obj) } } impl PyBuffer { /// Gets the underlying buffer from the specified python object. pub fn get(obj: &Bound<'_, PyAny>) -> PyResult> { // TODO: use nightly API Box::new_uninit() once our MSRV is 1.82 let mut buf = Box::new(mem::MaybeUninit::uninit()); let buf: Box = { err::error_on_minusone(obj.py(), unsafe { ffi::PyObject_GetBuffer(obj.as_ptr(), buf.as_mut_ptr(), ffi::PyBUF_FULL_RO) })?; // Safety: buf is initialized by PyObject_GetBuffer. // TODO: use nightly API Box::assume_init() once our MSRV is 1.82 unsafe { mem::transmute(buf) } }; // Create PyBuffer immediately so that if validation checks fail, the PyBuffer::drop code // will call PyBuffer_Release (thus avoiding any leaks). let buf = PyBuffer(Pin::from(buf), PhantomData); if buf.0.shape.is_null() { Err(PyBufferError::new_err("shape is null")) } else if buf.0.strides.is_null() { Err(PyBufferError::new_err("strides is null")) } else if mem::size_of::() != buf.item_size() || !T::is_compatible_format(buf.format()) { Err(PyBufferError::new_err(format!( "buffer contents are not compatible with {}", std::any::type_name::() ))) } else if buf.0.buf.align_offset(mem::align_of::()) != 0 { Err(PyBufferError::new_err(format!( "buffer contents are insufficiently aligned for {}", std::any::type_name::() ))) } else { Ok(buf) } } /// Gets the pointer to the start of the buffer memory. /// /// Warning: the buffer memory might be mutated by other Python functions, /// and thus may only be accessed while the GIL is held. #[inline] pub fn buf_ptr(&self) -> *mut raw::c_void { self.0.buf } /// Gets a pointer to the specified item. /// /// If `indices.len() < self.dimensions()`, returns the start address of the sub-array at the specified dimension. pub fn get_ptr(&self, indices: &[usize]) -> *mut raw::c_void { let shape = &self.shape()[..indices.len()]; for i in 0..indices.len() { assert!(indices[i] < shape[i]); } unsafe { ffi::PyBuffer_GetPointer( #[cfg(Py_3_11)] &*self.0, #[cfg(not(Py_3_11))] { &*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer }, #[cfg(Py_3_11)] { indices.as_ptr().cast() }, #[cfg(not(Py_3_11))] { indices.as_ptr() as *mut ffi::Py_ssize_t }, ) } } /// Gets whether the underlying buffer is read-only. #[inline] pub fn readonly(&self) -> bool { self.0.readonly != 0 } /// Gets the size of a single element, in bytes. /// Important exception: when requesting an unformatted buffer, item_size still has the value #[inline] pub fn item_size(&self) -> usize { self.0.itemsize as usize } /// Gets the total number of items. #[inline] pub fn item_count(&self) -> usize { (self.0.len as usize) / (self.0.itemsize as usize) } /// `item_size() * item_count()`. /// For contiguous arrays, this is the length of the underlying memory block. /// For non-contiguous arrays, it is the length that the logical structure would have if it were copied to a contiguous representation. #[inline] pub fn len_bytes(&self) -> usize { self.0.len as usize } /// Gets the number of dimensions. /// /// May be 0 to indicate a single scalar value. #[inline] pub fn dimensions(&self) -> usize { self.0.ndim as usize } /// Returns an array of length `dimensions`. `shape()[i]` is the length of the array in dimension number `i`. /// /// May return None for single-dimensional arrays or scalar values (`dimensions() <= 1`); /// You can call `item_count()` to get the length of the single dimension. /// /// Despite Python using an array of signed integers, the values are guaranteed to be non-negative. /// However, dimensions of length 0 are possible and might need special attention. #[inline] pub fn shape(&self) -> &[usize] { unsafe { slice::from_raw_parts(self.0.shape.cast(), self.0.ndim as usize) } } /// Returns an array that holds, for each dimension, the number of bytes to skip to get to the next element in the dimension. /// /// Stride values can be any integer. For regular arrays, strides are usually positive, /// but a consumer MUST be able to handle the case `strides[n] <= 0`. #[inline] pub fn strides(&self) -> &[isize] { unsafe { slice::from_raw_parts(self.0.strides, self.0.ndim as usize) } } /// An array of length ndim. /// If `suboffsets[n] >= 0`, the values stored along the nth dimension are pointers and the suboffset value dictates how many bytes to add to each pointer after de-referencing. /// A suboffset value that is negative indicates that no de-referencing should occur (striding in a contiguous memory block). /// /// If all suboffsets are negative (i.e. no de-referencing is needed), then this field must be NULL (the default value). #[inline] pub fn suboffsets(&self) -> Option<&[isize]> { unsafe { if self.0.suboffsets.is_null() { None } else { Some(slice::from_raw_parts( self.0.suboffsets, self.0.ndim as usize, )) } } } /// A NUL terminated string in struct module style syntax describing the contents of a single item. #[inline] pub fn format(&self) -> &CStr { if self.0.format.is_null() { ffi::c_str!("B") } else { unsafe { CStr::from_ptr(self.0.format) } } } /// Gets whether the buffer is contiguous in C-style order (last index varies fastest when visiting items in order of memory address). #[inline] pub fn is_c_contiguous(&self) -> bool { unsafe { ffi::PyBuffer_IsContiguous(&*self.0, b'C' as std::os::raw::c_char) != 0 } } /// Gets whether the buffer is contiguous in Fortran-style order (first index varies fastest when visiting items in order of memory address). #[inline] pub fn is_fortran_contiguous(&self) -> bool { unsafe { ffi::PyBuffer_IsContiguous(&*self.0, b'F' as std::os::raw::c_char) != 0 } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is C-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [ReadOnlyCell]> { if self.is_c_contiguous() { unsafe { Some(slice::from_raw_parts( self.0.buf as *mut ReadOnlyCell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer is not read-only /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is C-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_mut_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [cell::Cell]> { if !self.readonly() && self.is_c_contiguous() { unsafe { Some(slice::from_raw_parts( self.0.buf as *mut cell::Cell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is Fortran-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_fortran_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [ReadOnlyCell]> { if mem::size_of::() == self.item_size() && self.is_fortran_contiguous() { unsafe { Some(slice::from_raw_parts( self.0.buf as *mut ReadOnlyCell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer is not read-only /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is Fortran-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_fortran_mut_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [cell::Cell]> { if !self.readonly() && self.is_fortran_contiguous() { unsafe { Some(slice::from_raw_parts( self.0.buf as *mut cell::Cell, self.item_count(), )) } } else { None } } /// Copies the buffer elements to the specified slice. /// If the buffer is multi-dimensional, the elements are written in C-style order. /// /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// you can use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_to_slice(&self, py: Python<'_>, target: &mut [T]) -> PyResult<()> { self._copy_to_slice(py, target, b'C') } /// Copies the buffer elements to the specified slice. /// If the buffer is multi-dimensional, the elements are written in Fortran-style order. /// /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// you can use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_to_fortran_slice(&self, py: Python<'_>, target: &mut [T]) -> PyResult<()> { self._copy_to_slice(py, target, b'F') } fn _copy_to_slice(&self, py: Python<'_>, target: &mut [T], fort: u8) -> PyResult<()> { if mem::size_of_val(target) != self.len_bytes() { return Err(PyBufferError::new_err(format!( "slice to copy to (of length {}) does not match buffer length of {}", target.len(), self.item_count() ))); } err::error_on_minusone(py, unsafe { ffi::PyBuffer_ToContiguous( target.as_mut_ptr().cast(), #[cfg(Py_3_11)] &*self.0, #[cfg(not(Py_3_11))] { &*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer }, self.0.len, fort as std::os::raw::c_char, ) }) } /// Copies the buffer elements to a newly allocated vector. /// If the buffer is multi-dimensional, the elements are written in C-style order. /// /// Fails if the buffer format is not compatible with type `T`. pub fn to_vec(&self, py: Python<'_>) -> PyResult> { self._to_vec(py, b'C') } /// Copies the buffer elements to a newly allocated vector. /// If the buffer is multi-dimensional, the elements are written in Fortran-style order. /// /// Fails if the buffer format is not compatible with type `T`. pub fn to_fortran_vec(&self, py: Python<'_>) -> PyResult> { self._to_vec(py, b'F') } fn _to_vec(&self, py: Python<'_>, fort: u8) -> PyResult> { let item_count = self.item_count(); let mut vec: Vec = Vec::with_capacity(item_count); // Copy the buffer into the uninitialized space in the vector. // Due to T:Copy, we don't need to be concerned with Drop impls. err::error_on_minusone(py, unsafe { ffi::PyBuffer_ToContiguous( vec.as_ptr() as *mut raw::c_void, #[cfg(Py_3_11)] &*self.0, #[cfg(not(Py_3_11))] { &*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer }, self.0.len, fort as std::os::raw::c_char, ) })?; // set vector length to mark the now-initialized space as usable unsafe { vec.set_len(item_count) }; Ok(vec) } /// Copies the specified slice into the buffer. /// If the buffer is multi-dimensional, the elements in the slice are expected to be in C-style order. /// /// * Fails if the buffer is read-only. /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_from_slice(&self, py: Python<'_>, source: &[T]) -> PyResult<()> { self._copy_from_slice(py, source, b'C') } /// Copies the specified slice into the buffer. /// If the buffer is multi-dimensional, the elements in the slice are expected to be in Fortran-style order. /// /// * Fails if the buffer is read-only. /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_from_fortran_slice(&self, py: Python<'_>, source: &[T]) -> PyResult<()> { self._copy_from_slice(py, source, b'F') } fn _copy_from_slice(&self, py: Python<'_>, source: &[T], fort: u8) -> PyResult<()> { if self.readonly() { return Err(PyBufferError::new_err("cannot write to read-only buffer")); } else if mem::size_of_val(source) != self.len_bytes() { return Err(PyBufferError::new_err(format!( "slice to copy from (of length {}) does not match buffer length of {}", source.len(), self.item_count() ))); } err::error_on_minusone(py, unsafe { ffi::PyBuffer_FromContiguous( #[cfg(Py_3_11)] &*self.0, #[cfg(not(Py_3_11))] { &*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer }, #[cfg(Py_3_11)] { source.as_ptr().cast() }, #[cfg(not(Py_3_11))] { source.as_ptr() as *mut raw::c_void }, self.0.len, fort as std::os::raw::c_char, ) }) } /// Releases the buffer object, freeing the reference to the Python object /// which owns the buffer. /// /// This will automatically be called on drop. pub fn release(self, _py: Python<'_>) { // First move self into a ManuallyDrop, so that PyBuffer::drop will // never be called. (It would acquire the GIL and call PyBuffer_Release // again.) let mut mdself = mem::ManuallyDrop::new(self); unsafe { // Next, make the actual PyBuffer_Release call. ffi::PyBuffer_Release(&mut *mdself.0); // Finally, drop the contained Pin> in place, to free the // Box memory. let inner: *mut Pin> = &mut mdself.0; ptr::drop_in_place(inner); } } } impl Drop for PyBuffer { fn drop(&mut self) { Python::with_gil(|_| unsafe { ffi::PyBuffer_Release(&mut *self.0) }); } } /// Like [std::cell::Cell], but only provides read-only access to the data. /// /// `&ReadOnlyCell` is basically a safe version of `*const T`: /// The data cannot be modified through the reference, but other references may /// be modifying the data. #[repr(transparent)] pub struct ReadOnlyCell(cell::UnsafeCell); impl ReadOnlyCell { /// Returns a copy of the current value. #[inline] pub fn get(&self) -> T { unsafe { *self.0.get() } } /// Returns a pointer to the current value. #[inline] pub fn as_ptr(&self) -> *const T { self.0.get() } } macro_rules! impl_element( ($t:ty, $f:ident) => { unsafe impl Element for $t { fn is_compatible_format(format: &CStr) -> bool { let slice = format.to_bytes(); if slice.len() > 1 && !is_matching_endian(slice[0]) { return false; } ElementType::from_format(format) == ElementType::$f { bytes: mem::size_of::<$t>() } } } } ); impl_element!(u8, UnsignedInteger); impl_element!(u16, UnsignedInteger); impl_element!(u32, UnsignedInteger); impl_element!(u64, UnsignedInteger); impl_element!(usize, UnsignedInteger); impl_element!(i8, SignedInteger); impl_element!(i16, SignedInteger); impl_element!(i32, SignedInteger); impl_element!(i64, SignedInteger); impl_element!(isize, SignedInteger); impl_element!(f32, Float); impl_element!(f64, Float); #[cfg(test)] mod tests { use super::PyBuffer; use crate::ffi; use crate::types::any::PyAnyMethods; use crate::Python; #[test] fn test_debug() { Python::with_gil(|py| { let bytes = py.eval(ffi::c_str!("b'abcde'"), None, None).unwrap(); let buffer: PyBuffer = PyBuffer::get(&bytes).unwrap(); let expected = format!( concat!( "PyBuffer {{ buf: {:?}, obj: {:?}, ", "len: 5, itemsize: 1, readonly: 1, ", "ndim: 1, format: {:?}, shape: {:?}, ", "strides: {:?}, suboffsets: {:?}, internal: {:?} }}", ), buffer.0.buf, buffer.0.obj, buffer.0.format, buffer.0.shape, buffer.0.strides, buffer.0.suboffsets, buffer.0.internal ); let debug_repr = format!("{buffer:?}"); assert_eq!(debug_repr, expected); }); } #[test] fn test_element_type_from_format() { use super::ElementType; use super::ElementType::*; use std::mem::size_of; use std::os::raw; for (cstr, expected) in [ // @ prefix goes to native_element_type_from_type_char ( ffi::c_str!("@b"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@c"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@b"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@B"), UnsignedInteger { bytes: size_of::(), }, ), (ffi::c_str!("@?"), Bool), ( ffi::c_str!("@h"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@H"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@i"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@I"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@l"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@L"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@q"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@Q"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@n"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@N"), UnsignedInteger { bytes: size_of::(), }, ), (ffi::c_str!("@e"), Float { bytes: 2 }), (ffi::c_str!("@f"), Float { bytes: 4 }), (ffi::c_str!("@d"), Float { bytes: 8 }), (ffi::c_str!("@z"), Unknown), // = prefix goes to standard_element_type_from_type_char (ffi::c_str!("=b"), SignedInteger { bytes: 1 }), (ffi::c_str!("=c"), UnsignedInteger { bytes: 1 }), (ffi::c_str!("=B"), UnsignedInteger { bytes: 1 }), (ffi::c_str!("=?"), Bool), (ffi::c_str!("=h"), SignedInteger { bytes: 2 }), (ffi::c_str!("=H"), UnsignedInteger { bytes: 2 }), (ffi::c_str!("=l"), SignedInteger { bytes: 4 }), (ffi::c_str!("=l"), SignedInteger { bytes: 4 }), (ffi::c_str!("=I"), UnsignedInteger { bytes: 4 }), (ffi::c_str!("=L"), UnsignedInteger { bytes: 4 }), (ffi::c_str!("=q"), SignedInteger { bytes: 8 }), (ffi::c_str!("=Q"), UnsignedInteger { bytes: 8 }), (ffi::c_str!("=e"), Float { bytes: 2 }), (ffi::c_str!("=f"), Float { bytes: 4 }), (ffi::c_str!("=d"), Float { bytes: 8 }), (ffi::c_str!("=z"), Unknown), (ffi::c_str!("=0"), Unknown), // unknown prefix -> Unknown (ffi::c_str!(":b"), Unknown), ] { assert_eq!( ElementType::from_format(cstr), expected, "element from format &Cstr: {cstr:?}", ); } } #[test] fn test_compatible_size() { // for the cast in PyBuffer::shape() assert_eq!( std::mem::size_of::(), std::mem::size_of::() ); } #[test] fn test_bytes_buffer() { Python::with_gil(|py| { let bytes = py.eval(ffi::c_str!("b'abcde'"), None, None).unwrap(); let buffer = PyBuffer::get(&bytes).unwrap(); assert_eq!(buffer.dimensions(), 1); assert_eq!(buffer.item_count(), 5); assert_eq!(buffer.format().to_str().unwrap(), "B"); assert_eq!(buffer.shape(), [5]); // single-dimensional buffer is always contiguous assert!(buffer.is_c_contiguous()); assert!(buffer.is_fortran_contiguous()); let slice = buffer.as_slice(py).unwrap(); assert_eq!(slice.len(), 5); assert_eq!(slice[0].get(), b'a'); assert_eq!(slice[2].get(), b'c'); assert_eq!(unsafe { *(buffer.get_ptr(&[1]) as *mut u8) }, b'b'); assert!(buffer.as_mut_slice(py).is_none()); assert!(buffer.copy_to_slice(py, &mut [0u8]).is_err()); let mut arr = [0; 5]; buffer.copy_to_slice(py, &mut arr).unwrap(); assert_eq!(arr, b"abcde" as &[u8]); assert!(buffer.copy_from_slice(py, &[0u8; 5]).is_err()); assert_eq!(buffer.to_vec(py).unwrap(), b"abcde"); }); } #[test] fn test_array_buffer() { Python::with_gil(|py| { let array = py .import("array") .unwrap() .call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None) .unwrap(); let buffer = PyBuffer::get(&array).unwrap(); assert_eq!(buffer.dimensions(), 1); assert_eq!(buffer.item_count(), 4); assert_eq!(buffer.format().to_str().unwrap(), "f"); assert_eq!(buffer.shape(), [4]); // array creates a 1D contiguious buffer, so it's both C and F contiguous. This would // be more interesting if we can come up with a 2D buffer but I think it would need a // third-party lib or a custom class. // C-contiguous fns let slice = buffer.as_slice(py).unwrap(); assert_eq!(slice.len(), 4); assert_eq!(slice[0].get(), 1.0); assert_eq!(slice[3].get(), 2.5); let mut_slice = buffer.as_mut_slice(py).unwrap(); assert_eq!(mut_slice.len(), 4); assert_eq!(mut_slice[0].get(), 1.0); mut_slice[3].set(2.75); assert_eq!(slice[3].get(), 2.75); buffer .copy_from_slice(py, &[10.0f32, 11.0, 12.0, 13.0]) .unwrap(); assert_eq!(slice[2].get(), 12.0); assert_eq!(buffer.to_vec(py).unwrap(), [10.0, 11.0, 12.0, 13.0]); // F-contiguous fns let buffer = PyBuffer::get(&array).unwrap(); let slice = buffer.as_fortran_slice(py).unwrap(); assert_eq!(slice.len(), 4); assert_eq!(slice[1].get(), 11.0); let mut_slice = buffer.as_fortran_mut_slice(py).unwrap(); assert_eq!(mut_slice.len(), 4); assert_eq!(mut_slice[2].get(), 12.0); mut_slice[3].set(2.75); assert_eq!(slice[3].get(), 2.75); buffer .copy_from_fortran_slice(py, &[10.0f32, 11.0, 12.0, 13.0]) .unwrap(); assert_eq!(slice[2].get(), 12.0); assert_eq!(buffer.to_fortran_vec(py).unwrap(), [10.0, 11.0, 12.0, 13.0]); }); } } pyo3/src/call.rs0000644000175000017500000002306315105742312013350 0ustar bdrungbdrung//! Defines how Python calls are dispatched, see [`PyCallArgs`].for more information. use crate::ffi_ptr_ext::FfiPtrExt as _; use crate::types::{PyAnyMethods as _, PyDict, PyString, PyTuple}; use crate::{ffi, Borrowed, Bound, IntoPyObjectExt as _, Py, PyAny, PyResult}; pub(crate) mod private { use super::*; pub trait Sealed {} impl Sealed for () {} impl Sealed for Bound<'_, PyTuple> {} impl Sealed for &'_ Bound<'_, PyTuple> {} impl Sealed for Py {} impl Sealed for &'_ Py {} impl Sealed for Borrowed<'_, '_, PyTuple> {} pub struct Token; } /// This trait marks types that can be used as arguments to Python function /// calls. /// /// This trait is currently implemented for Rust tuple (up to a size of 12), /// [`Bound<'py, PyTuple>`] and [`Py`]. Custom types that are /// convertable to `PyTuple` via `IntoPyObject` need to do so before passing it /// to `call`. /// /// This trait is not intended to used by downstream crates directly. As such it /// has no publicly available methods and cannot be implemented ouside of /// `pyo3`. The corresponding public API is available through [`call`] /// ([`call0`], [`call1`] and friends) on [`PyAnyMethods`]. /// /// # What is `PyCallArgs` used for? /// `PyCallArgs` is used internally in `pyo3` to dispatch the Python calls in /// the most optimal way for the current build configuration. Certain types, /// such as Rust tuples, do allow the usage of a faster calling convention of /// the Python interpreter (if available). More types that may take advantage /// from this may be added in the future. /// /// [`call0`]: crate::types::PyAnyMethods::call0 /// [`call1`]: crate::types::PyAnyMethods::call1 /// [`call`]: crate::types::PyAnyMethods::call /// [`PyAnyMethods`]: crate::types::PyAnyMethods #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "`{Self}` cannot used as a Python `call` argument", note = "`PyCallArgs` is implemented for Rust tuples, `Bound<'py, PyTuple>` and `Py`", note = "if your type is convertable to `PyTuple` via `IntoPyObject`, call `.into_pyobject(py)` manually", note = "if you meant to pass the type as a single argument, wrap it in a 1-tuple, `(,)`" ) )] pub trait PyCallArgs<'py>: Sized + private::Sealed { #[doc(hidden)] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult>; #[doc(hidden)] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult>; #[doc(hidden)] fn call_method_positional( self, object: Borrowed<'_, 'py, PyAny>, method_name: Borrowed<'_, 'py, PyString>, _: private::Token, ) -> PyResult> { object .getattr(method_name) .and_then(|method| method.call1(self)) } } impl<'py> PyCallArgs<'py> for () { fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { let args = self.into_pyobject_or_pyerr(function.py())?; args.call(function, kwargs, token) } fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { let args = self.into_pyobject_or_pyerr(function.py())?; args.call_positional(function, token) } } impl<'py> PyCallArgs<'py> for Bound<'py, PyTuple> { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { self.as_borrowed().call(function, kwargs, token) } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { self.as_borrowed().call_positional(function, token) } } impl<'py> PyCallArgs<'py> for &'_ Bound<'py, PyTuple> { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { self.as_borrowed().call(function, kwargs, token) } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { self.as_borrowed().call_positional(function, token) } } impl<'py> PyCallArgs<'py> for Py { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { self.bind_borrowed(function.py()) .call(function, kwargs, token) } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { self.bind_borrowed(function.py()) .call_positional(function, token) } } impl<'py> PyCallArgs<'py> for &'_ Py { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, token: private::Token, ) -> PyResult> { self.bind_borrowed(function.py()) .call(function, kwargs, token) } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: private::Token, ) -> PyResult> { self.bind_borrowed(function.py()) .call_positional(function, token) } } impl<'py> PyCallArgs<'py> for Borrowed<'_, 'py, PyTuple> { #[inline] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, PyDict>, _: private::Token, ) -> PyResult> { unsafe { ffi::PyObject_Call(function.as_ptr(), self.as_ptr(), kwargs.as_ptr()) .assume_owned_or_err(function.py()) } } #[inline] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, _: private::Token, ) -> PyResult> { unsafe { ffi::PyObject_Call(function.as_ptr(), self.as_ptr(), std::ptr::null_mut()) .assume_owned_or_err(function.py()) } } } #[cfg(test)] #[cfg(feature = "macros")] mod tests { use crate::{ pyfunction, types::{PyDict, PyTuple}, Py, }; #[pyfunction(signature = (*args, **kwargs), crate = "crate")] fn args_kwargs( args: Py, kwargs: Option>, ) -> (Py, Option>) { (args, kwargs) } #[test] fn test_call() { use crate::{ types::{IntoPyDict, PyAnyMethods, PyDict, PyTuple}, wrap_pyfunction, Py, Python, }; Python::with_gil(|py| { let f = wrap_pyfunction!(args_kwargs, py).unwrap(); let args = PyTuple::new(py, [1, 2, 3]).unwrap(); let kwargs = &[("foo", 1), ("bar", 2)].into_py_dict(py).unwrap(); macro_rules! check_call { ($args:expr, $kwargs:expr) => { let (a, k): (Py, Py) = f .call(args.clone(), Some(kwargs)) .unwrap() .extract() .unwrap(); assert!(a.is(&args)); assert!(k.is(kwargs)); }; } // Bound<'py, PyTuple> check_call!(args.clone(), kwargs); // &Bound<'py, PyTuple> check_call!(&args, kwargs); // Py check_call!(args.clone().unbind(), kwargs); // &Py check_call!(&args.as_unbound(), kwargs); // Borrowed<'_, '_, PyTuple> check_call!(args.as_borrowed(), kwargs); }) } #[test] fn test_call_positional() { use crate::{ types::{PyAnyMethods, PyNone, PyTuple}, wrap_pyfunction, Py, Python, }; Python::with_gil(|py| { let f = wrap_pyfunction!(args_kwargs, py).unwrap(); let args = PyTuple::new(py, [1, 2, 3]).unwrap(); macro_rules! check_call { ($args:expr, $kwargs:expr) => { let (a, k): (Py, Py) = f.call1(args.clone()).unwrap().extract().unwrap(); assert!(a.is(&args)); assert!(k.is_none(py)); }; } // Bound<'py, PyTuple> check_call!(args.clone(), kwargs); // &Bound<'py, PyTuple> check_call!(&args, kwargs); // Py check_call!(args.clone().unbind(), kwargs); // &Py check_call!(args.as_unbound(), kwargs); // Borrowed<'_, '_, PyTuple> check_call!(args.as_borrowed(), kwargs); }) } } pyo3/src/pyclass.rs0000644000175000017500000000743415105742312014117 0ustar bdrungbdrung//! `PyClass` and related traits. use crate::{ffi, impl_::pyclass::PyClassImpl, PyTypeInfo}; use std::{cmp::Ordering, os::raw::c_int}; mod create_type_object; mod gc; pub(crate) use self::create_type_object::{create_type_object, PyClassTypeObject}; pub use self::gc::{PyTraverseError, PyVisit}; /// Types that can be used as Python classes. /// /// The `#[pyclass]` attribute implements this trait for your Rust struct - /// you shouldn't implement this trait directly. pub trait PyClass: PyTypeInfo + PyClassImpl { /// Whether the pyclass is frozen. /// /// This can be enabled via `#[pyclass(frozen)]`. type Frozen: Frozen; } /// Operators for the `__richcmp__` method #[derive(Debug, Clone, Copy)] pub enum CompareOp { /// The *less than* operator. Lt = ffi::Py_LT as isize, /// The *less than or equal to* operator. Le = ffi::Py_LE as isize, /// The equality operator. Eq = ffi::Py_EQ as isize, /// The *not equal to* operator. Ne = ffi::Py_NE as isize, /// The *greater than* operator. Gt = ffi::Py_GT as isize, /// The *greater than or equal to* operator. Ge = ffi::Py_GE as isize, } impl CompareOp { /// Conversion from the C enum. pub fn from_raw(op: c_int) -> Option { match op { ffi::Py_LT => Some(CompareOp::Lt), ffi::Py_LE => Some(CompareOp::Le), ffi::Py_EQ => Some(CompareOp::Eq), ffi::Py_NE => Some(CompareOp::Ne), ffi::Py_GT => Some(CompareOp::Gt), ffi::Py_GE => Some(CompareOp::Ge), _ => None, } } /// Returns if a Rust [`std::cmp::Ordering`] matches this ordering query. /// /// Usage example: /// /// ```rust,no_run /// # use pyo3::prelude::*; /// # use pyo3::class::basic::CompareOp; /// /// #[pyclass] /// struct Size { /// size: usize, /// } /// /// #[pymethods] /// impl Size { /// fn __richcmp__(&self, other: &Size, op: CompareOp) -> bool { /// op.matches(self.size.cmp(&other.size)) /// } /// } /// ``` pub fn matches(&self, result: Ordering) -> bool { match self { CompareOp::Eq => result == Ordering::Equal, CompareOp::Ne => result != Ordering::Equal, CompareOp::Lt => result == Ordering::Less, CompareOp::Le => result != Ordering::Greater, CompareOp::Gt => result == Ordering::Greater, CompareOp::Ge => result != Ordering::Less, } } } /// A workaround for [associated const equality](https://github.com/rust-lang/rust/issues/92827). /// /// This serves to have True / False values in the [`PyClass`] trait's `Frozen` type. #[doc(hidden)] pub mod boolean_struct { pub(crate) mod private { use super::*; /// A way to "seal" the boolean traits. pub trait Boolean { const VALUE: bool; } impl Boolean for True { const VALUE: bool = true; } impl Boolean for False { const VALUE: bool = false; } } pub struct True(()); pub struct False(()); } /// A trait which is used to describe whether a `#[pyclass]` is frozen. #[doc(hidden)] pub trait Frozen: boolean_struct::private::Boolean {} impl Frozen for boolean_struct::True {} impl Frozen for boolean_struct::False {} mod tests { #[test] fn test_compare_op_matches() { use super::CompareOp; use std::cmp::Ordering; assert!(CompareOp::Eq.matches(Ordering::Equal)); assert!(CompareOp::Ne.matches(Ordering::Less)); assert!(CompareOp::Ge.matches(Ordering::Greater)); assert!(CompareOp::Gt.matches(Ordering::Greater)); assert!(CompareOp::Le.matches(Ordering::Equal)); assert!(CompareOp::Lt.matches(Ordering::Less)); } } pyo3/src/impl_/0000775000175000017500000000000015105742312013165 5ustar bdrungbdrungpyo3/src/impl_/concat.rs0000644000175000017500000000154215105742312015002 0ustar bdrungbdrung/// `concat!` but working with constants #[macro_export] #[doc(hidden)] macro_rules! const_concat { ($e:expr) => {{ $e }}; ($l:expr, $($r:expr),+ $(,)?) => {{ const L: &'static str = $l; const R: &'static str = $crate::impl_::concat::const_concat!($($r),*); const LEN: usize = L.len() + R.len(); const fn combine(l: &'static [u8], r: &'static [u8]) -> [u8; LEN] { let mut out = [0u8; LEN]; let mut i = 0; while i < l.len() { out[i] = l[i]; i += 1; } while i < LEN { out[i] = r[i - l.len()]; i += 1; } out } #[allow(unsafe_code)] unsafe { ::std::str::from_utf8_unchecked(&combine(L.as_bytes(), R.as_bytes())) } }} } pub use const_concat; pyo3/src/impl_/pyclass.rs0000644000175000017500000013410215105742312015210 0ustar bdrungbdrunguse crate::{ exceptions::{PyAttributeError, PyNotImplementedError, PyRuntimeError, PyValueError}, ffi, impl_::{ freelist::PyObjectFreeList, pycell::{GetBorrowChecker, PyClassMutability, PyClassObjectLayout}, pyclass_init::PyObjectInit, pymethods::{PyGetterDef, PyMethodDefType}, }, pycell::PyBorrowError, types::{any::PyAnyMethods, PyBool}, Borrowed, BoundObject, IntoPyObject, IntoPyObjectExt, Py, PyAny, PyClass, PyErr, PyRef, PyResult, PyTypeInfo, Python, }; use std::{ borrow::Cow, ffi::{CStr, CString}, marker::PhantomData, os::raw::{c_int, c_void}, ptr, ptr::NonNull, sync::Mutex, thread, }; mod assertions; mod lazy_type_object; mod probes; pub use assertions::*; pub use lazy_type_object::LazyTypeObject; pub use probes::*; /// Gets the offset of the dictionary from the start of the object in bytes. #[inline] pub fn dict_offset() -> ffi::Py_ssize_t { PyClassObject::::dict_offset() } /// Gets the offset of the weakref list from the start of the object in bytes. #[inline] pub fn weaklist_offset() -> ffi::Py_ssize_t { PyClassObject::::weaklist_offset() } mod sealed { pub trait Sealed {} impl Sealed for super::PyClassDummySlot {} impl Sealed for super::PyClassDictSlot {} impl Sealed for super::PyClassWeakRefSlot {} impl Sealed for super::ThreadCheckerImpl {} impl Sealed for super::SendablePyClass {} } /// Represents the `__dict__` field for `#[pyclass]`. pub trait PyClassDict: sealed::Sealed { /// Initial form of a [PyObject](crate::ffi::PyObject) `__dict__` reference. const INIT: Self; /// Empties the dictionary of its key-value pairs. #[inline] fn clear_dict(&mut self, _py: Python<'_>) {} } /// Represents the `__weakref__` field for `#[pyclass]`. pub trait PyClassWeakRef: sealed::Sealed { /// Initializes a `weakref` instance. const INIT: Self; /// Clears the weak references to the given object. /// /// # Safety /// - `_obj` must be a pointer to the pyclass instance which contains `self`. /// - The GIL must be held. #[inline] unsafe fn clear_weakrefs(&mut self, _obj: *mut ffi::PyObject, _py: Python<'_>) {} } /// Zero-sized dummy field. pub struct PyClassDummySlot; impl PyClassDict for PyClassDummySlot { const INIT: Self = PyClassDummySlot; } impl PyClassWeakRef for PyClassDummySlot { const INIT: Self = PyClassDummySlot; } /// Actual dict field, which holds the pointer to `__dict__`. /// /// `#[pyclass(dict)]` automatically adds this. #[repr(transparent)] #[allow(dead_code)] // These are constructed in INIT and used by the macro code pub struct PyClassDictSlot(*mut ffi::PyObject); impl PyClassDict for PyClassDictSlot { const INIT: Self = Self(std::ptr::null_mut()); #[inline] fn clear_dict(&mut self, _py: Python<'_>) { if !self.0.is_null() { unsafe { ffi::PyDict_Clear(self.0) } } } } /// Actual weakref field, which holds the pointer to `__weakref__`. /// /// `#[pyclass(weakref)]` automatically adds this. #[repr(transparent)] #[allow(dead_code)] // These are constructed in INIT and used by the macro code pub struct PyClassWeakRefSlot(*mut ffi::PyObject); impl PyClassWeakRef for PyClassWeakRefSlot { const INIT: Self = Self(std::ptr::null_mut()); #[inline] unsafe fn clear_weakrefs(&mut self, obj: *mut ffi::PyObject, _py: Python<'_>) { if !self.0.is_null() { unsafe { ffi::PyObject_ClearWeakRefs(obj) } } } } /// This type is used as a "dummy" type on which dtolnay specializations are /// applied to apply implementations from `#[pymethods]` pub struct PyClassImplCollector(PhantomData); impl PyClassImplCollector { pub fn new() -> Self { Self(PhantomData) } } impl Default for PyClassImplCollector { fn default() -> Self { Self::new() } } impl Clone for PyClassImplCollector { fn clone(&self) -> Self { *self } } impl Copy for PyClassImplCollector {} pub enum MaybeRuntimePyMethodDef { /// Used in cases where const functionality is not sufficient to define the method /// purely at compile time. Runtime(fn() -> PyMethodDefType), Static(PyMethodDefType), } pub struct PyClassItems { pub methods: &'static [MaybeRuntimePyMethodDef], pub slots: &'static [ffi::PyType_Slot], } // Allow PyClassItems in statics unsafe impl Sync for PyClassItems {} /// Implements the underlying functionality of `#[pyclass]`, assembled by various proc macros. /// /// Users are discouraged from implementing this trait manually; it is a PyO3 implementation detail /// and may be changed at any time. pub trait PyClassImpl: Sized + 'static { /// #[pyclass(subclass)] const IS_BASETYPE: bool = false; /// #[pyclass(extends=...)] const IS_SUBCLASS: bool = false; /// #[pyclass(mapping)] const IS_MAPPING: bool = false; /// #[pyclass(sequence)] const IS_SEQUENCE: bool = false; /// #[pyclass(immutable_type)] const IS_IMMUTABLE_TYPE: bool = false; /// Base class type BaseType: PyTypeInfo + PyClassBaseType; /// Immutable or mutable type PyClassMutability: PyClassMutability + GetBorrowChecker; /// Specify this class has `#[pyclass(dict)]` or not. type Dict: PyClassDict; /// Specify this class has `#[pyclass(weakref)]` or not. type WeakRef: PyClassWeakRef; /// The closest native ancestor. This is `PyAny` by default, and when you declare /// `#[pyclass(extends=PyDict)]`, it's `PyDict`. type BaseNativeType: PyTypeInfo; /// This handles following two situations: /// 1. In case `T` is `Send`, stub `ThreadChecker` is used and does nothing. /// This implementation is used by default. Compile fails if `T: !Send`. /// 2. In case `T` is `!Send`, `ThreadChecker` panics when `T` is accessed by another thread. /// This implementation is used when `#[pyclass(unsendable)]` is given. /// Panicking makes it safe to expose `T: !Send` to the Python interpreter, where all objects /// can be accessed by multiple threads by `threading` module. type ThreadChecker: PyClassThreadChecker; #[cfg(feature = "multiple-pymethods")] type Inventory: PyClassInventory; /// Rendered class doc fn doc(py: Python<'_>) -> PyResult<&'static CStr>; fn items_iter() -> PyClassItemsIter; #[inline] fn dict_offset() -> Option { None } #[inline] fn weaklist_offset() -> Option { None } fn lazy_type_object() -> &'static LazyTypeObject; } /// Runtime helper to build a class docstring from the `doc` and `text_signature`. /// /// This is done at runtime because the class text signature is collected via dtolnay /// specialization in to the `#[pyclass]` macro from the `#[pymethods]` macro. pub fn build_pyclass_doc( class_name: &'static str, doc: &'static CStr, text_signature: Option<&'static str>, ) -> PyResult> { if let Some(text_signature) = text_signature { let doc = CString::new(format!( "{}{}\n--\n\n{}", class_name, text_signature, doc.to_str().unwrap(), )) .map_err(|_| PyValueError::new_err("class doc cannot contain nul bytes"))?; Ok(Cow::Owned(doc)) } else { Ok(Cow::Borrowed(doc)) } } /// Iterator used to process all class items during type instantiation. pub struct PyClassItemsIter { /// Iteration state idx: usize, /// Items from the `#[pyclass]` macro pyclass_items: &'static PyClassItems, /// Items from the `#[pymethods]` macro #[cfg(not(feature = "multiple-pymethods"))] pymethods_items: &'static PyClassItems, /// Items from the `#[pymethods]` macro with inventory #[cfg(feature = "multiple-pymethods")] pymethods_items: Box>, } impl PyClassItemsIter { pub fn new( pyclass_items: &'static PyClassItems, #[cfg(not(feature = "multiple-pymethods"))] pymethods_items: &'static PyClassItems, #[cfg(feature = "multiple-pymethods")] pymethods_items: Box< dyn Iterator, >, ) -> Self { Self { idx: 0, pyclass_items, pymethods_items, } } } impl Iterator for PyClassItemsIter { type Item = &'static PyClassItems; #[cfg(not(feature = "multiple-pymethods"))] fn next(&mut self) -> Option { match self.idx { 0 => { self.idx += 1; Some(self.pyclass_items) } 1 => { self.idx += 1; Some(self.pymethods_items) } // Termination clause _ => None, } } #[cfg(feature = "multiple-pymethods")] fn next(&mut self) -> Option { match self.idx { 0 => { self.idx += 1; Some(self.pyclass_items) } // Termination clause _ => self.pymethods_items.next(), } } } // Traits describing known special methods. macro_rules! slot_fragment_trait { ($trait_name:ident, $($default_method:tt)*) => { #[allow(non_camel_case_types)] pub trait $trait_name: Sized { $($default_method)* } impl $trait_name for &'_ PyClassImplCollector {} } } slot_fragment_trait! { PyClass__getattribute__SlotFragment, /// # Safety: _slf and _attr must be valid non-null Python objects #[inline] unsafe fn __getattribute__( self, py: Python<'_>, slf: *mut ffi::PyObject, attr: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { let res = unsafe { ffi::PyObject_GenericGetAttr(slf, attr) }; if res.is_null() { Err(PyErr::fetch(py)) } else { Ok(res) } } } slot_fragment_trait! { PyClass__getattr__SlotFragment, /// # Safety: _slf and _attr must be valid non-null Python objects #[inline] unsafe fn __getattr__( self, py: Python<'_>, _slf: *mut ffi::PyObject, attr: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Err(PyErr::new::( (unsafe {Py::::from_borrowed_ptr(py, attr)},) )) } } #[doc(hidden)] #[macro_export] macro_rules! generate_pyclass_getattro_slot { ($cls:ty) => {{ unsafe extern "C" fn __wrap( _slf: *mut $crate::ffi::PyObject, attr: *mut $crate::ffi::PyObject, ) -> *mut $crate::ffi::PyObject { unsafe { $crate::impl_::trampoline::getattrofunc(_slf, attr, |py, _slf, attr| { use ::std::result::Result::*; use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); // Strategy: // - Try __getattribute__ first. Its default is PyObject_GenericGetAttr. // - If it returns a result, use it. // - If it fails with AttributeError, try __getattr__. // - If it fails otherwise, reraise. match collector.__getattribute__(py, _slf, attr) { Ok(obj) => Ok(obj), Err(e) if e.is_instance_of::<$crate::exceptions::PyAttributeError>(py) => { collector.__getattr__(py, _slf, attr) } Err(e) => Err(e), } }) } } $crate::ffi::PyType_Slot { slot: $crate::ffi::Py_tp_getattro, pfunc: __wrap as $crate::ffi::getattrofunc as _, } }}; } pub use generate_pyclass_getattro_slot; /// Macro which expands to three items /// - Trait for a __setitem__ dunder /// - Trait for the corresponding __delitem__ dunder /// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders macro_rules! define_pyclass_setattr_slot { ( $set_trait:ident, $del_trait:ident, $set:ident, $del:ident, $set_error:expr, $del_error:expr, $generate_macro:ident, $slot:ident, $func_ty:ident, ) => { slot_fragment_trait! { $set_trait, /// # Safety: _slf and _attr must be valid non-null Python objects #[inline] unsafe fn $set( self, _py: Python<'_>, _slf: *mut ffi::PyObject, _attr: *mut ffi::PyObject, _value: NonNull, ) -> PyResult<()> { $set_error } } slot_fragment_trait! { $del_trait, /// # Safety: _slf and _attr must be valid non-null Python objects #[inline] unsafe fn $del( self, _py: Python<'_>, _slf: *mut ffi::PyObject, _attr: *mut ffi::PyObject, ) -> PyResult<()> { $del_error } } #[doc(hidden)] #[macro_export] macro_rules! $generate_macro { ($cls:ty) => {{ unsafe extern "C" fn __wrap( _slf: *mut $crate::ffi::PyObject, attr: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject, ) -> ::std::os::raw::c_int { unsafe { $crate::impl_::trampoline::setattrofunc( _slf, attr, value, |py, _slf, attr, value| { use ::std::option::Option::*; use $crate::impl_::callback::IntoPyCallbackOutput; use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); if let Some(value) = ::std::ptr::NonNull::new(value) { collector.$set(py, _slf, attr, value).convert(py) } else { collector.$del(py, _slf, attr).convert(py) } }, ) } } $crate::ffi::PyType_Slot { slot: $crate::ffi::$slot, pfunc: __wrap as $crate::ffi::$func_ty as _, } }}; } pub use $generate_macro; }; } define_pyclass_setattr_slot! { PyClass__setattr__SlotFragment, PyClass__delattr__SlotFragment, __setattr__, __delattr__, Err(PyAttributeError::new_err("can't set attribute")), Err(PyAttributeError::new_err("can't delete attribute")), generate_pyclass_setattr_slot, Py_tp_setattro, setattrofunc, } define_pyclass_setattr_slot! { PyClass__set__SlotFragment, PyClass__delete__SlotFragment, __set__, __delete__, Err(PyNotImplementedError::new_err("can't set descriptor")), Err(PyNotImplementedError::new_err("can't delete descriptor")), generate_pyclass_setdescr_slot, Py_tp_descr_set, descrsetfunc, } define_pyclass_setattr_slot! { PyClass__setitem__SlotFragment, PyClass__delitem__SlotFragment, __setitem__, __delitem__, Err(PyNotImplementedError::new_err("can't set item")), Err(PyNotImplementedError::new_err("can't delete item")), generate_pyclass_setitem_slot, Py_mp_ass_subscript, objobjargproc, } /// Macro which expands to three items /// - Trait for a lhs dunder e.g. __add__ /// - Trait for the corresponding rhs e.g. __radd__ /// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders macro_rules! define_pyclass_binary_operator_slot { ( $lhs_trait:ident, $rhs_trait:ident, $lhs:ident, $rhs:ident, $generate_macro:ident, $slot:ident, $func_ty:ident, ) => { slot_fragment_trait! { $lhs_trait, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn $lhs( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { $rhs_trait, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn $rhs( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } #[doc(hidden)] #[macro_export] macro_rules! $generate_macro { ($cls:ty) => {{ unsafe extern "C" fn __wrap( _slf: *mut $crate::ffi::PyObject, _other: *mut $crate::ffi::PyObject, ) -> *mut $crate::ffi::PyObject { unsafe { $crate::impl_::trampoline::binaryfunc(_slf, _other, |py, _slf, _other| { use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); let lhs_result = collector.$lhs(py, _slf, _other)?; if lhs_result == $crate::ffi::Py_NotImplemented() { $crate::ffi::Py_DECREF(lhs_result); collector.$rhs(py, _other, _slf) } else { ::std::result::Result::Ok(lhs_result) } }) } } $crate::ffi::PyType_Slot { slot: $crate::ffi::$slot, pfunc: __wrap as $crate::ffi::$func_ty as _, } }}; } pub use $generate_macro; }; } define_pyclass_binary_operator_slot! { PyClass__add__SlotFragment, PyClass__radd__SlotFragment, __add__, __radd__, generate_pyclass_add_slot, Py_nb_add, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__sub__SlotFragment, PyClass__rsub__SlotFragment, __sub__, __rsub__, generate_pyclass_sub_slot, Py_nb_subtract, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__mul__SlotFragment, PyClass__rmul__SlotFragment, __mul__, __rmul__, generate_pyclass_mul_slot, Py_nb_multiply, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__mod__SlotFragment, PyClass__rmod__SlotFragment, __mod__, __rmod__, generate_pyclass_mod_slot, Py_nb_remainder, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__divmod__SlotFragment, PyClass__rdivmod__SlotFragment, __divmod__, __rdivmod__, generate_pyclass_divmod_slot, Py_nb_divmod, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__lshift__SlotFragment, PyClass__rlshift__SlotFragment, __lshift__, __rlshift__, generate_pyclass_lshift_slot, Py_nb_lshift, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__rshift__SlotFragment, PyClass__rrshift__SlotFragment, __rshift__, __rrshift__, generate_pyclass_rshift_slot, Py_nb_rshift, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__and__SlotFragment, PyClass__rand__SlotFragment, __and__, __rand__, generate_pyclass_and_slot, Py_nb_and, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__or__SlotFragment, PyClass__ror__SlotFragment, __or__, __ror__, generate_pyclass_or_slot, Py_nb_or, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__xor__SlotFragment, PyClass__rxor__SlotFragment, __xor__, __rxor__, generate_pyclass_xor_slot, Py_nb_xor, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__matmul__SlotFragment, PyClass__rmatmul__SlotFragment, __matmul__, __rmatmul__, generate_pyclass_matmul_slot, Py_nb_matrix_multiply, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__truediv__SlotFragment, PyClass__rtruediv__SlotFragment, __truediv__, __rtruediv__, generate_pyclass_truediv_slot, Py_nb_true_divide, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__floordiv__SlotFragment, PyClass__rfloordiv__SlotFragment, __floordiv__, __rfloordiv__, generate_pyclass_floordiv_slot, Py_nb_floor_divide, binaryfunc, } slot_fragment_trait! { PyClass__pow__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __pow__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, _mod: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__rpow__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __rpow__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, _mod: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } #[doc(hidden)] #[macro_export] macro_rules! generate_pyclass_pow_slot { ($cls:ty) => {{ unsafe extern "C" fn __wrap( _slf: *mut $crate::ffi::PyObject, _other: *mut $crate::ffi::PyObject, _mod: *mut $crate::ffi::PyObject, ) -> *mut $crate::ffi::PyObject { unsafe { $crate::impl_::trampoline::ternaryfunc( _slf, _other, _mod, |py, _slf, _other, _mod| { use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); let lhs_result = collector.__pow__(py, _slf, _other, _mod)?; if lhs_result == $crate::ffi::Py_NotImplemented() { $crate::ffi::Py_DECREF(lhs_result); collector.__rpow__(py, _other, _slf, _mod) } else { ::std::result::Result::Ok(lhs_result) } }, ) } } $crate::ffi::PyType_Slot { slot: $crate::ffi::Py_nb_power, pfunc: __wrap as $crate::ffi::ternaryfunc as _, } }}; } pub use generate_pyclass_pow_slot; slot_fragment_trait! { PyClass__lt__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __lt__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__le__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __le__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__eq__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __eq__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__ne__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __ne__( self, py: Python<'_>, slf: *mut ffi::PyObject, other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { // By default `__ne__` will try `__eq__` and invert the result let slf = unsafe { Borrowed::from_ptr(py, slf)}; let other = unsafe { Borrowed::from_ptr(py, other)}; slf.eq(other).map(|is_eq| PyBool::new(py, !is_eq).to_owned().into_ptr()) } } slot_fragment_trait! { PyClass__gt__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __gt__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__ge__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __ge__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } #[doc(hidden)] #[macro_export] macro_rules! generate_pyclass_richcompare_slot { ($cls:ty) => {{ #[allow(unknown_lints, non_local_definitions)] impl $cls { #[allow(non_snake_case)] unsafe extern "C" fn __pymethod___richcmp____( slf: *mut $crate::ffi::PyObject, other: *mut $crate::ffi::PyObject, op: ::std::os::raw::c_int, ) -> *mut $crate::ffi::PyObject { unsafe { $crate::impl_::trampoline::richcmpfunc(slf, other, op, |py, slf, other, op| { use $crate::class::basic::CompareOp; use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); match CompareOp::from_raw(op).expect("invalid compareop") { CompareOp::Lt => collector.__lt__(py, slf, other), CompareOp::Le => collector.__le__(py, slf, other), CompareOp::Eq => collector.__eq__(py, slf, other), CompareOp::Ne => collector.__ne__(py, slf, other), CompareOp::Gt => collector.__gt__(py, slf, other), CompareOp::Ge => collector.__ge__(py, slf, other), } }) } } } $crate::ffi::PyType_Slot { slot: $crate::ffi::Py_tp_richcompare, pfunc: <$cls>::__pymethod___richcmp____ as $crate::ffi::richcmpfunc as _, } }}; } pub use generate_pyclass_richcompare_slot; use super::{pycell::PyClassObject, pymethods::BoundRef}; /// Implements a freelist. /// /// Do not implement this trait manually. Instead, use `#[pyclass(freelist = N)]` /// on a Rust struct to implement it. pub trait PyClassWithFreeList: PyClass { fn get_free_list(py: Python<'_>) -> &'static Mutex; } /// Implementation of tp_alloc for `freelist` classes. /// /// # Safety /// - `subtype` must be a valid pointer to the type object of T or a subclass. /// - The GIL must be held. pub unsafe extern "C" fn alloc_with_freelist( subtype: *mut ffi::PyTypeObject, nitems: ffi::Py_ssize_t, ) -> *mut ffi::PyObject { let py = unsafe { Python::assume_gil_acquired() }; #[cfg(not(Py_3_8))] unsafe { bpo_35810_workaround(py, subtype) }; let self_type = T::type_object_raw(py); // If this type is a variable type or the subtype is not equal to this type, we cannot use the // freelist if nitems == 0 && ptr::eq(subtype, self_type) { let mut free_list = T::get_free_list(py).lock().unwrap(); if let Some(obj) = free_list.pop() { drop(free_list); unsafe { ffi::PyObject_Init(obj, subtype) }; unsafe { ffi::PyObject_Init(obj, subtype) }; return obj as _; } } unsafe { ffi::PyType_GenericAlloc(subtype, nitems) } } /// Implementation of tp_free for `freelist` classes. /// /// # Safety /// - `obj` must be a valid pointer to an instance of T (not a subclass). /// - The GIL must be held. pub unsafe extern "C" fn free_with_freelist(obj: *mut c_void) { let obj = obj as *mut ffi::PyObject; unsafe { debug_assert_eq!( T::type_object_raw(Python::assume_gil_acquired()), ffi::Py_TYPE(obj) ); let mut free_list = T::get_free_list(Python::assume_gil_acquired()) .lock() .unwrap(); if let Some(obj) = free_list.insert(obj) { drop(free_list); let ty = ffi::Py_TYPE(obj); // Deduce appropriate inverse of PyType_GenericAlloc let free = if ffi::PyType_IS_GC(ty) != 0 { ffi::PyObject_GC_Del } else { ffi::PyObject_Free }; free(obj as *mut c_void); #[cfg(Py_3_8)] if ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE) != 0 { ffi::Py_DECREF(ty as *mut ffi::PyObject); } } } } /// Workaround for Python issue 35810; no longer necessary in Python 3.8 #[inline] #[cfg(not(Py_3_8))] unsafe fn bpo_35810_workaround(py: Python<'_>, ty: *mut ffi::PyTypeObject) { #[cfg(Py_LIMITED_API)] { // Must check version at runtime for abi3 wheels - they could run against a higher version // than the build config suggests. use crate::sync::GILOnceCell; static IS_PYTHON_3_8: GILOnceCell = GILOnceCell::new(); if *IS_PYTHON_3_8.get_or_init(py, || py.version_info() >= (3, 8)) { // No fix needed - the wheel is running on a sufficiently new interpreter. return; } } #[cfg(not(Py_LIMITED_API))] { // suppress unused variable warning let _ = py; } unsafe { ffi::Py_INCREF(ty as *mut ffi::PyObject) }; } /// Method storage for `#[pyclass]`. /// /// Implementation detail. Only to be used through our proc macro code. /// Allows arbitrary `#[pymethod]` blocks to submit their methods, /// which are eventually collected by `#[pyclass]`. #[cfg(feature = "multiple-pymethods")] pub trait PyClassInventory: inventory::Collect { /// Returns the items for a single `#[pymethods] impl` block fn items(&'static self) -> &'static PyClassItems; } // Items from #[pymethods] if not using inventory. #[cfg(not(feature = "multiple-pymethods"))] pub trait PyMethods { fn py_methods(self) -> &'static PyClassItems; } #[cfg(not(feature = "multiple-pymethods"))] impl PyMethods for &'_ PyClassImplCollector { fn py_methods(self) -> &'static PyClassItems { &PyClassItems { methods: &[], slots: &[], } } } // Text signature for __new__ pub trait PyClassNewTextSignature { fn new_text_signature(self) -> Option<&'static str>; } impl PyClassNewTextSignature for &'_ PyClassImplCollector { #[inline] fn new_text_signature(self) -> Option<&'static str> { None } } // Thread checkers #[doc(hidden)] pub trait PyClassThreadChecker: Sized + sealed::Sealed { fn ensure(&self); fn check(&self) -> bool; fn can_drop(&self, py: Python<'_>) -> bool; fn new() -> Self; } /// Default thread checker for `#[pyclass]`. /// /// Keeping the T: Send bound here slightly improves the compile /// error message to hint to users to figure out what's wrong /// when `#[pyclass]` types do not implement `Send`. #[doc(hidden)] pub struct SendablePyClass(PhantomData); impl PyClassThreadChecker for SendablePyClass { fn ensure(&self) {} fn check(&self) -> bool { true } fn can_drop(&self, _py: Python<'_>) -> bool { true } #[inline] fn new() -> Self { SendablePyClass(PhantomData) } } /// Thread checker for `#[pyclass(unsendable)]` types. /// Panics when the value is accessed by another thread. #[doc(hidden)] pub struct ThreadCheckerImpl(thread::ThreadId); impl ThreadCheckerImpl { fn ensure(&self, type_name: &'static str) { assert_eq!( thread::current().id(), self.0, "{type_name} is unsendable, but sent to another thread" ); } fn check(&self) -> bool { thread::current().id() == self.0 } fn can_drop(&self, py: Python<'_>, type_name: &'static str) -> bool { if thread::current().id() != self.0 { PyRuntimeError::new_err(format!( "{type_name} is unsendable, but is being dropped on another thread" )) .write_unraisable(py, None); return false; } true } } impl PyClassThreadChecker for ThreadCheckerImpl { fn ensure(&self) { self.ensure(std::any::type_name::()); } fn check(&self) -> bool { self.check() } fn can_drop(&self, py: Python<'_>) -> bool { self.can_drop(py, std::any::type_name::()) } fn new() -> Self { ThreadCheckerImpl(thread::current().id()) } } /// Trait denoting that this class is suitable to be used as a base type for PyClass. #[cfg_attr( all(diagnostic_namespace, Py_LIMITED_API), diagnostic::on_unimplemented( message = "pyclass `{Self}` cannot be subclassed", label = "required for `#[pyclass(extends={Self})]`", note = "`{Self}` must have `#[pyclass(subclass)]` to be eligible for subclassing", note = "with the `abi3` feature enabled, PyO3 does not support subclassing native types", ) )] #[cfg_attr( all(diagnostic_namespace, not(Py_LIMITED_API)), diagnostic::on_unimplemented( message = "pyclass `{Self}` cannot be subclassed", label = "required for `#[pyclass(extends={Self})]`", note = "`{Self}` must have `#[pyclass(subclass)]` to be eligible for subclassing", ) )] pub trait PyClassBaseType: Sized { type LayoutAsBase: PyClassObjectLayout; type BaseNativeType; type Initializer: PyObjectInit; type PyClassMutability: PyClassMutability; } /// Implementation of tp_dealloc for pyclasses without gc pub(crate) unsafe extern "C" fn tp_dealloc(obj: *mut ffi::PyObject) { unsafe { crate::impl_::trampoline::dealloc(obj, PyClassObject::::tp_dealloc) } } /// Implementation of tp_dealloc for pyclasses with gc pub(crate) unsafe extern "C" fn tp_dealloc_with_gc(obj: *mut ffi::PyObject) { #[cfg(not(PyPy))] unsafe { ffi::PyObject_GC_UnTrack(obj.cast()); } unsafe { crate::impl_::trampoline::dealloc(obj, PyClassObject::::tp_dealloc) } } pub(crate) unsafe extern "C" fn get_sequence_item_from_mapping( obj: *mut ffi::PyObject, index: ffi::Py_ssize_t, ) -> *mut ffi::PyObject { let index = unsafe { ffi::PyLong_FromSsize_t(index) }; if index.is_null() { return std::ptr::null_mut(); } let result = unsafe { ffi::PyObject_GetItem(obj, index) }; unsafe { ffi::Py_DECREF(index) }; result } pub(crate) unsafe extern "C" fn assign_sequence_item_from_mapping( obj: *mut ffi::PyObject, index: ffi::Py_ssize_t, value: *mut ffi::PyObject, ) -> c_int { unsafe { let index = ffi::PyLong_FromSsize_t(index); if index.is_null() { return -1; } let result = if value.is_null() { ffi::PyObject_DelItem(obj, index) } else { ffi::PyObject_SetItem(obj, index, value) }; ffi::Py_DECREF(index); result } } /// Helper trait to locate field within a `#[pyclass]` for a `#[pyo3(get)]`. /// /// Below MSRV 1.77 we can't use `std::mem::offset_of!`, and the replacement in /// `memoffset::offset_of` doesn't work in const contexts for types containing `UnsafeCell`. /// /// # Safety /// /// The trait is unsafe to implement because producing an incorrect offset will lead to UB. pub unsafe trait OffsetCalculator { /// Offset to the field within a `PyClassObject`, in bytes. fn offset() -> usize; } // Used in generated implementations of OffsetCalculator pub fn class_offset() -> usize { offset_of!(PyClassObject, contents) } // Used in generated implementations of OffsetCalculator pub use memoffset::offset_of; /// Type which uses specialization on impl blocks to determine how to read a field from a Rust pyclass /// as part of a `#[pyo3(get)]` annotation. pub struct PyClassGetterGenerator< // structural information about the field: class type, field type, where the field is within the // class struct ClassT: PyClass, FieldT, Offset: OffsetCalculator, // on Rust 1.77+ this could be a const OFFSET: usize // additional metadata about the field which is used to switch between different implementations // at compile time const IS_PY_T: bool, const IMPLEMENTS_INTOPYOBJECT_REF: bool, const IMPLEMENTS_INTOPYOBJECT: bool, >(PhantomData<(ClassT, FieldT, Offset)>); impl< ClassT: PyClass, FieldT, Offset: OffsetCalculator, const IS_PY_T: bool, const IMPLEMENTS_INTOPYOBJECT_REF: bool, const IMPLEMENTS_INTOPYOBJECT: bool, > PyClassGetterGenerator< ClassT, FieldT, Offset, IS_PY_T, IMPLEMENTS_INTOPYOBJECT_REF, IMPLEMENTS_INTOPYOBJECT, > { /// Safety: constructing this type requires that there exists a value of type FieldT /// at the calculated offset within the type ClassT. pub const unsafe fn new() -> Self { Self(PhantomData) } } impl< ClassT: PyClass, U, Offset: OffsetCalculator>, const IMPLEMENTS_INTOPYOBJECT_REF: bool, const IMPLEMENTS_INTOPYOBJECT: bool, > PyClassGetterGenerator< ClassT, Py, Offset, true, IMPLEMENTS_INTOPYOBJECT_REF, IMPLEMENTS_INTOPYOBJECT, > { /// `Py` fields have a potential optimization to use Python's "struct members" to read /// the field directly from the struct, rather than using a getter function. /// /// This is the most efficient operation the Python interpreter could possibly do to /// read a field, but it's only possible for us to allow this for frozen classes. pub fn generate(&self, name: &'static CStr, doc: &'static CStr) -> PyMethodDefType { use crate::pyclass::boolean_struct::private::Boolean; if ClassT::Frozen::VALUE { PyMethodDefType::StructMember(ffi::PyMemberDef { name: name.as_ptr(), type_code: ffi::Py_T_OBJECT_EX, offset: Offset::offset() as ffi::Py_ssize_t, flags: ffi::Py_READONLY, doc: doc.as_ptr(), }) } else { PyMethodDefType::Getter(PyGetterDef { name, meth: pyo3_get_value_into_pyobject_ref::, Offset>, doc, }) } } } /// Field is not `Py`; try to use `IntoPyObject` for `&T` (prefered over `ToPyObject`) to avoid /// potentially expensive clones of containers like `Vec` impl PyClassGetterGenerator where ClassT: PyClass, for<'a, 'py> &'a FieldT: IntoPyObject<'py>, Offset: OffsetCalculator, { pub const fn generate(&self, name: &'static CStr, doc: &'static CStr) -> PyMethodDefType { PyMethodDefType::Getter(PyGetterDef { name, meth: pyo3_get_value_into_pyobject_ref::, doc, }) } } #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "`{Self}` cannot be converted to a Python object", label = "required by `#[pyo3(get)]` to create a readable property from a field of type `{Self}`", note = "implement `IntoPyObject` for `&{Self}` or `IntoPyObject + Clone` for `{Self}` to define the conversion" ) )] pub trait PyO3GetField<'py>: IntoPyObject<'py> + Clone {} impl<'py, T> PyO3GetField<'py> for T where T: IntoPyObject<'py> + Clone {} /// Base case attempts to use IntoPyObject + Clone impl< ClassT: PyClass, FieldT, Offset: OffsetCalculator, const IMPLEMENTS_INTOPYOBJECT: bool, > PyClassGetterGenerator { pub const fn generate(&self, name: &'static CStr, doc: &'static CStr) -> PyMethodDefType // The bound goes here rather than on the block so that this impl is always available // if no specialization is used instead where for<'py> FieldT: PyO3GetField<'py>, { PyMethodDefType::Getter(PyGetterDef { name, meth: pyo3_get_value_into_pyobject::, doc, }) } } /// ensures `obj` is not mutably aliased #[inline] unsafe fn ensure_no_mutable_alias<'py, ClassT: PyClass>( py: Python<'py>, obj: &*mut ffi::PyObject, ) -> Result, PyBorrowError> { unsafe { BoundRef::ref_from_ptr(py, obj) .downcast_unchecked::() .try_borrow() } } /// calculates the field pointer from an PyObject pointer #[inline] fn field_from_object(obj: *mut ffi::PyObject) -> *mut FieldT where ClassT: PyClass, Offset: OffsetCalculator, { unsafe { obj.cast::().add(Offset::offset()).cast::() } } fn pyo3_get_value_into_pyobject_ref( py: Python<'_>, obj: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> where ClassT: PyClass, for<'a, 'py> &'a FieldT: IntoPyObject<'py>, Offset: OffsetCalculator, { let _holder = unsafe { ensure_no_mutable_alias::(py, &obj)? }; let value = field_from_object::(obj); // SAFETY: Offset is known to describe the location of the value, and // _holder is preventing mutable aliasing Ok((unsafe { &*value }) .into_pyobject(py) .map_err(Into::into)? .into_ptr()) } fn pyo3_get_value_into_pyobject( py: Python<'_>, obj: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> where ClassT: PyClass, for<'py> FieldT: IntoPyObject<'py> + Clone, Offset: OffsetCalculator, { let _holder = unsafe { ensure_no_mutable_alias::(py, &obj)? }; let value = field_from_object::(obj); // SAFETY: Offset is known to describe the location of the value, and // _holder is preventing mutable aliasing Ok((unsafe { &*value }) .clone() .into_pyobject(py) .map_err(Into::into)? .into_ptr()) } pub struct ConvertField< const IMPLEMENTS_INTOPYOBJECT_REF: bool, const IMPLEMENTS_INTOPYOBJECT: bool, >; impl ConvertField { #[inline] pub fn convert_field<'a, 'py, T>(obj: &'a T, py: Python<'py>) -> PyResult> where &'a T: IntoPyObject<'py>, { obj.into_py_any(py) } } impl ConvertField { #[inline] pub fn convert_field<'py, T>(obj: &T, py: Python<'py>) -> PyResult> where T: PyO3GetField<'py>, { obj.clone().into_py_any(py) } } #[cfg(test)] #[cfg(feature = "macros")] mod tests { use super::*; #[test] fn get_py_for_frozen_class() { #[crate::pyclass(crate = "crate", frozen)] struct FrozenClass { #[pyo3(get)] value: Py, } let mut methods = Vec::new(); let mut slots = Vec::new(); for items in FrozenClass::items_iter() { methods.extend(items.methods.iter().map(|m| match m { MaybeRuntimePyMethodDef::Static(m) => m.clone(), MaybeRuntimePyMethodDef::Runtime(r) => r(), })); slots.extend_from_slice(items.slots); } assert_eq!(methods.len(), 1); assert!(slots.is_empty()); match methods.first() { Some(PyMethodDefType::StructMember(member)) => { assert_eq!(unsafe { CStr::from_ptr(member.name) }, ffi::c_str!("value")); assert_eq!(member.type_code, ffi::Py_T_OBJECT_EX); assert_eq!( member.offset, (memoffset::offset_of!(PyClassObject, contents) + memoffset::offset_of!(FrozenClass, value)) as ffi::Py_ssize_t ); assert_eq!(member.flags, ffi::Py_READONLY); } _ => panic!("Expected a StructMember"), } } #[test] fn get_py_for_non_frozen_class() { #[crate::pyclass(crate = "crate")] struct FrozenClass { #[pyo3(get)] value: Py, } let mut methods = Vec::new(); let mut slots = Vec::new(); for items in FrozenClass::items_iter() { methods.extend(items.methods.iter().map(|m| match m { MaybeRuntimePyMethodDef::Static(m) => m.clone(), MaybeRuntimePyMethodDef::Runtime(r) => r(), })); slots.extend_from_slice(items.slots); } assert_eq!(methods.len(), 1); assert!(slots.is_empty()); match methods.first() { Some(PyMethodDefType::Getter(getter)) => { assert_eq!(getter.name, ffi::c_str!("value")); assert_eq!(getter.doc, ffi::c_str!("")); // tests for the function pointer are in test_getter_setter.py } _ => panic!("Expected a StructMember"), } } } pyo3/src/impl_/coroutine.rs0000644000175000017500000000526615105742312015551 0ustar bdrungbdrunguse std::{ future::Future, ops::{Deref, DerefMut}, }; use crate::{ coroutine::{cancel::ThrowCallback, Coroutine}, instance::Bound, pycell::impl_::PyClassBorrowChecker, pyclass::boolean_struct::False, types::{PyAnyMethods, PyString}, IntoPyObject, Py, PyAny, PyClass, PyErr, PyResult, Python, }; pub fn new_coroutine<'py, F, T, E>( name: &Bound<'py, PyString>, qualname_prefix: Option<&'static str>, throw_callback: Option, future: F, ) -> Coroutine where F: Future> + Send + 'static, T: IntoPyObject<'py>, E: Into, { Coroutine::new(Some(name.clone()), qualname_prefix, throw_callback, future) } fn get_ptr(obj: &Py) -> *mut T { obj.get_class_object().get_ptr() } pub struct RefGuard(Py); impl RefGuard { pub fn new(obj: &Bound<'_, PyAny>) -> PyResult { let bound = obj.downcast::()?; bound.get_class_object().borrow_checker().try_borrow()?; Ok(RefGuard(bound.clone().unbind())) } } impl Deref for RefGuard { type Target = T; fn deref(&self) -> &Self::Target { // SAFETY: `RefGuard` has been built from `PyRef` and provides the same guarantees unsafe { &*get_ptr(&self.0) } } } impl Drop for RefGuard { fn drop(&mut self) { Python::with_gil(|py| { self.0 .bind(py) .get_class_object() .borrow_checker() .release_borrow() }) } } pub struct RefMutGuard>(Py); impl> RefMutGuard { pub fn new(obj: &Bound<'_, PyAny>) -> PyResult { let bound = obj.downcast::()?; bound.get_class_object().borrow_checker().try_borrow_mut()?; Ok(RefMutGuard(bound.clone().unbind())) } } impl> Deref for RefMutGuard { type Target = T; fn deref(&self) -> &Self::Target { // SAFETY: `RefMutGuard` has been built from `PyRefMut` and provides the same guarantees unsafe { &*get_ptr(&self.0) } } } impl> DerefMut for RefMutGuard { fn deref_mut(&mut self) -> &mut Self::Target { // SAFETY: `RefMutGuard` has been built from `PyRefMut` and provides the same guarantees unsafe { &mut *get_ptr(&self.0) } } } impl> Drop for RefMutGuard { fn drop(&mut self) { Python::with_gil(|py| { self.0 .bind(py) .get_class_object() .borrow_checker() .release_borrow_mut() }) } } pyo3/src/impl_/extract_argument.rs0000644000175000017500000007637715105742312017131 0ustar bdrungbdrunguse crate::{ conversion::FromPyObjectBound, exceptions::PyTypeError, ffi, pyclass::boolean_struct::False, types::{any::PyAnyMethods, dict::PyDictMethods, tuple::PyTupleMethods, PyDict, PyTuple}, Borrowed, Bound, PyAny, PyClass, PyErr, PyRef, PyRefMut, PyResult, PyTypeCheck, Python, }; /// Helper type used to keep implementation more concise. /// /// (Function argument extraction borrows input arguments.) type PyArg<'py> = Borrowed<'py, 'py, PyAny>; /// A trait which is used to help PyO3 macros extract function arguments. /// /// `#[pyclass]` structs need to extract as `PyRef` and `PyRefMut` /// wrappers rather than extracting `&T` and `&mut T` directly. The `Holder` type is used /// to hold these temporary wrappers - the way the macro is constructed, these wrappers /// will be dropped as soon as the pyfunction call ends. /// /// There exists a trivial blanket implementation for `T: FromPyObject` with `Holder = ()`. pub trait PyFunctionArgument<'a, 'py, const IS_OPTION: bool>: Sized + 'a { type Holder: FunctionArgumentHolder; fn extract(obj: &'a Bound<'py, PyAny>, holder: &'a mut Self::Holder) -> PyResult; } impl<'a, 'py, T> PyFunctionArgument<'a, 'py, false> for T where T: FromPyObjectBound<'a, 'py> + 'a, { type Holder = (); #[inline] fn extract(obj: &'a Bound<'py, PyAny>, _: &'a mut ()) -> PyResult { obj.extract() } } impl<'a, 'py, T: 'py> PyFunctionArgument<'a, 'py, false> for &'a Bound<'py, T> where T: PyTypeCheck, { type Holder = (); #[inline] fn extract(obj: &'a Bound<'py, PyAny>, _: &'a mut ()) -> PyResult { obj.downcast().map_err(Into::into) } } impl<'a, 'py, T> PyFunctionArgument<'a, 'py, true> for Option where T: PyFunctionArgument<'a, 'py, false>, // inner `Option`s will use `FromPyObject` { type Holder = T::Holder; #[inline] fn extract(obj: &'a Bound<'py, PyAny>, holder: &'a mut T::Holder) -> PyResult { if obj.is_none() { Ok(None) } else { Ok(Some(T::extract(obj, holder)?)) } } } #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] impl<'a> PyFunctionArgument<'a, '_, false> for &'a str { type Holder = Option>; #[inline] fn extract( obj: &'a Bound<'_, PyAny>, holder: &'a mut Option>, ) -> PyResult { Ok(holder.insert(obj.extract()?)) } } /// Trait for types which can be a function argument holder - they should /// to be able to const-initialize to an empty value. pub trait FunctionArgumentHolder: Sized { const INIT: Self; } impl FunctionArgumentHolder for () { const INIT: Self = (); } impl FunctionArgumentHolder for Option { const INIT: Self = None; } #[inline] pub fn extract_pyclass_ref<'a, 'py: 'a, T: PyClass>( obj: &'a Bound<'py, PyAny>, holder: &'a mut Option>, ) -> PyResult<&'a T> { Ok(&*holder.insert(obj.extract()?)) } #[inline] pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass>( obj: &'a Bound<'py, PyAny>, holder: &'a mut Option>, ) -> PyResult<&'a mut T> { Ok(&mut *holder.insert(obj.extract()?)) } /// The standard implementation of how PyO3 extracts a `#[pyfunction]` or `#[pymethod]` function argument. #[doc(hidden)] pub fn extract_argument<'a, 'py, T, const IS_OPTION: bool>( obj: &'a Bound<'py, PyAny>, holder: &'a mut T::Holder, arg_name: &str, ) -> PyResult where T: PyFunctionArgument<'a, 'py, IS_OPTION>, { match PyFunctionArgument::extract(obj, holder) { Ok(value) => Ok(value), Err(e) => Err(argument_extraction_error(obj.py(), arg_name, e)), } } /// Alternative to [`extract_argument`] used for `Option` arguments. This is necessary because Option<&T> /// does not implement `PyFunctionArgument` for `T: PyClass`. #[doc(hidden)] pub fn extract_optional_argument<'a, 'py, T, const IS_OPTION: bool>( obj: Option<&'a Bound<'py, PyAny>>, holder: &'a mut T::Holder, arg_name: &str, default: fn() -> Option, ) -> PyResult> where T: PyFunctionArgument<'a, 'py, IS_OPTION>, { match obj { Some(obj) => { if obj.is_none() { // Explicit `None` will result in None being used as the function argument Ok(None) } else { extract_argument(obj, holder, arg_name).map(Some) } } _ => Ok(default()), } } /// Alternative to [`extract_argument`] used when the argument has a default value provided by an annotation. #[doc(hidden)] pub fn extract_argument_with_default<'a, 'py, T, const IS_OPTION: bool>( obj: Option<&'a Bound<'py, PyAny>>, holder: &'a mut T::Holder, arg_name: &str, default: fn() -> T, ) -> PyResult where T: PyFunctionArgument<'a, 'py, IS_OPTION>, { match obj { Some(obj) => extract_argument(obj, holder, arg_name), None => Ok(default()), } } /// Alternative to [`extract_argument`] used when the argument has a `#[pyo3(from_py_with)]` annotation. #[doc(hidden)] pub fn from_py_with<'a, 'py, T>( obj: &'a Bound<'py, PyAny>, arg_name: &str, extractor: fn(&'a Bound<'py, PyAny>) -> PyResult, ) -> PyResult { match extractor(obj) { Ok(value) => Ok(value), Err(e) => Err(argument_extraction_error(obj.py(), arg_name, e)), } } /// Alternative to [`extract_argument`] used when the argument has a `#[pyo3(from_py_with)]` annotation and also a default value. #[doc(hidden)] pub fn from_py_with_with_default<'a, 'py, T>( obj: Option<&'a Bound<'py, PyAny>>, arg_name: &str, extractor: fn(&'a Bound<'py, PyAny>) -> PyResult, default: fn() -> T, ) -> PyResult { match obj { Some(obj) => from_py_with(obj, arg_name, extractor), None => Ok(default()), } } /// Adds the argument name to the error message of an error which occurred during argument extraction. /// /// Only modifies TypeError. (Cannot guarantee all exceptions have constructors from /// single string.) #[doc(hidden)] #[cold] pub fn argument_extraction_error(py: Python<'_>, arg_name: &str, error: PyErr) -> PyErr { if error.get_type(py).is(py.get_type::()) { let remapped_error = PyTypeError::new_err(format!("argument '{}': {}", arg_name, error.value(py))); remapped_error.set_cause(py, error.cause(py)); remapped_error } else { error } } /// Unwraps the Option<&PyAny> produced by the FunctionDescription `extract_arguments_` methods. /// They check if required methods are all provided. /// /// # Safety /// `argument` must not be `None` #[doc(hidden)] #[inline] pub unsafe fn unwrap_required_argument<'a, 'py>( argument: Option<&'a Bound<'py, PyAny>>, ) -> &'a Bound<'py, PyAny> { match argument { Some(value) => value, #[cfg(debug_assertions)] None => unreachable!("required method argument was not extracted"), #[cfg(not(debug_assertions))] None => std::hint::unreachable_unchecked(), } } pub struct KeywordOnlyParameterDescription { pub name: &'static str, pub required: bool, } /// Function argument specification for a `#[pyfunction]` or `#[pymethod]`. pub struct FunctionDescription { pub cls_name: Option<&'static str>, pub func_name: &'static str, pub positional_parameter_names: &'static [&'static str], pub positional_only_parameters: usize, pub required_positional_parameters: usize, pub keyword_only_parameters: &'static [KeywordOnlyParameterDescription], } impl FunctionDescription { fn full_name(&self) -> String { if let Some(cls_name) = self.cls_name { format!("{}.{}()", cls_name, self.func_name) } else { format!("{}()", self.func_name) } } /// Equivalent of `extract_arguments_tuple_dict` which uses the Python C-API "fastcall" convention. /// /// # Safety /// - `args` must be a pointer to a C-style array of valid `ffi::PyObject` pointers, or NULL. /// - `kwnames` must be a pointer to a PyTuple, or NULL. /// - `nargs + kwnames.len()` is the total length of the `args` array. #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] pub unsafe fn extract_arguments_fastcall<'py, V, K>( &self, py: Python<'py>, args: *const *mut ffi::PyObject, nargs: ffi::Py_ssize_t, kwnames: *mut ffi::PyObject, output: &mut [Option>], ) -> PyResult<(V::Varargs, K::Varkeywords)> where V: VarargsHandler<'py>, K: VarkeywordsHandler<'py>, { let num_positional_parameters = self.positional_parameter_names.len(); debug_assert!(nargs >= 0); debug_assert!(self.positional_only_parameters <= num_positional_parameters); debug_assert!(self.required_positional_parameters <= num_positional_parameters); debug_assert_eq!( output.len(), num_positional_parameters + self.keyword_only_parameters.len() ); // Handle positional arguments // Safety: // - Option has the same memory layout as `*mut ffi::PyObject` // - we both have the GIL and can borrow these input references for the `'py` lifetime. let args: *const Option> = args.cast(); let positional_args_provided = nargs as usize; let remaining_positional_args = if args.is_null() { debug_assert_eq!(positional_args_provided, 0); &[] } else { // Can consume at most the number of positional parameters in the function definition, // the rest are varargs. let positional_args_to_consume = num_positional_parameters.min(positional_args_provided); let (positional_parameters, remaining) = unsafe { std::slice::from_raw_parts(args, positional_args_provided) .split_at(positional_args_to_consume) }; output[..positional_args_to_consume].copy_from_slice(positional_parameters); remaining }; let varargs = V::handle_varargs_fastcall(py, remaining_positional_args, self)?; // Handle keyword arguments let mut varkeywords = K::Varkeywords::default(); // Safety: kwnames is known to be a pointer to a tuple, or null // - we both have the GIL and can borrow this input reference for the `'py` lifetime. let kwnames: Option> = unsafe { Borrowed::from_ptr_or_opt(py, kwnames).map(|kwnames| kwnames.downcast_unchecked()) }; if let Some(kwnames) = kwnames { let kwargs = unsafe { ::std::slice::from_raw_parts( // Safety: PyArg has the same memory layout as `*mut ffi::PyObject` args.offset(nargs).cast::>(), kwnames.len(), ) }; self.handle_kwargs::( kwnames.iter_borrowed().zip(kwargs.iter().copied()), &mut varkeywords, num_positional_parameters, output, )? } // Once all inputs have been processed, check that all required arguments have been provided. self.ensure_no_missing_required_positional_arguments(output, positional_args_provided)?; self.ensure_no_missing_required_keyword_arguments(output)?; Ok((varargs, varkeywords)) } /// Extracts the `args` and `kwargs` provided into `output`, according to this function /// definition. /// /// `output` must have the same length as this function has positional and keyword-only /// parameters (as per the `positional_parameter_names` and `keyword_only_parameters` /// respectively). /// /// Unexpected, duplicate or invalid arguments will cause this function to return `TypeError`. /// /// # Safety /// - `args` must be a pointer to a PyTuple. /// - `kwargs` must be a pointer to a PyDict, or NULL. pub unsafe fn extract_arguments_tuple_dict<'py, V, K>( &self, py: Python<'py>, args: *mut ffi::PyObject, kwargs: *mut ffi::PyObject, output: &mut [Option>], ) -> PyResult<(V::Varargs, K::Varkeywords)> where V: VarargsHandler<'py>, K: VarkeywordsHandler<'py>, { // Safety: // - `args` is known to be a tuple // - `kwargs` is known to be a dict or null // - we both have the GIL and can borrow these input references for the `'py` lifetime. let args: Borrowed<'py, 'py, PyTuple> = unsafe { Borrowed::from_ptr(py, args).downcast_unchecked::() }; let kwargs: Option> = unsafe { Borrowed::from_ptr_or_opt(py, kwargs).map(|kwargs| kwargs.downcast_unchecked()) }; let num_positional_parameters = self.positional_parameter_names.len(); debug_assert!(self.positional_only_parameters <= num_positional_parameters); debug_assert!(self.required_positional_parameters <= num_positional_parameters); debug_assert_eq!( output.len(), num_positional_parameters + self.keyword_only_parameters.len() ); // Copy positional arguments into output for (i, arg) in args .iter_borrowed() .take(num_positional_parameters) .enumerate() { output[i] = Some(arg); } // If any arguments remain, push them to varargs (if possible) or error let varargs = V::handle_varargs_tuple(&args, self)?; // Handle keyword arguments let mut varkeywords = K::Varkeywords::default(); if let Some(kwargs) = kwargs { self.handle_kwargs::( unsafe { kwargs.iter_borrowed() }, &mut varkeywords, num_positional_parameters, output, )? } // Once all inputs have been processed, check that all required arguments have been provided. self.ensure_no_missing_required_positional_arguments(output, args.len())?; self.ensure_no_missing_required_keyword_arguments(output)?; Ok((varargs, varkeywords)) } #[inline] fn handle_kwargs<'py, K, I>( &self, kwargs: I, varkeywords: &mut K::Varkeywords, num_positional_parameters: usize, output: &mut [Option>], ) -> PyResult<()> where K: VarkeywordsHandler<'py>, I: IntoIterator, PyArg<'py>)>, { debug_assert_eq!( num_positional_parameters, self.positional_parameter_names.len() ); debug_assert_eq!( output.len(), num_positional_parameters + self.keyword_only_parameters.len() ); let mut positional_only_keyword_arguments = Vec::new(); for (kwarg_name_py, value) in kwargs { // Safety: All keyword arguments should be UTF-8 strings, but if it's not, `.to_str()` // will return an error anyway. #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] let kwarg_name = unsafe { kwarg_name_py.downcast_unchecked::() }.to_str(); #[cfg(all(not(Py_3_10), Py_LIMITED_API))] let kwarg_name = kwarg_name_py.extract::(); if let Ok(kwarg_name_owned) = kwarg_name { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] let kwarg_name = kwarg_name_owned; #[cfg(all(not(Py_3_10), Py_LIMITED_API))] let kwarg_name: &str = &kwarg_name_owned; // Try to place parameter in keyword only parameters if let Some(i) = self.find_keyword_parameter_in_keyword_only(kwarg_name) { if output[i + num_positional_parameters] .replace(value) .is_some() { return Err(self.multiple_values_for_argument(kwarg_name)); } continue; } // Repeat for positional parameters if let Some(i) = self.find_keyword_parameter_in_positional(kwarg_name) { if i < self.positional_only_parameters { // If accepting **kwargs, then it's allowed for the name of the // kwarg to conflict with a postional-only argument - the value // will go into **kwargs anyway. if K::handle_varkeyword(varkeywords, kwarg_name_py, value, self).is_err() { positional_only_keyword_arguments.push(kwarg_name_owned); } } else if output[i].replace(value).is_some() { return Err(self.multiple_values_for_argument(kwarg_name)); } continue; } }; K::handle_varkeyword(varkeywords, kwarg_name_py, value, self)? } if !positional_only_keyword_arguments.is_empty() { #[cfg(all(not(Py_3_10), Py_LIMITED_API))] let positional_only_keyword_arguments: Vec<_> = positional_only_keyword_arguments .iter() .map(std::ops::Deref::deref) .collect(); return Err(self.positional_only_keyword_arguments(&positional_only_keyword_arguments)); } Ok(()) } #[inline] fn find_keyword_parameter_in_positional(&self, kwarg_name: &str) -> Option { self.positional_parameter_names .iter() .position(|¶m_name| param_name == kwarg_name) } #[inline] fn find_keyword_parameter_in_keyword_only(&self, kwarg_name: &str) -> Option { // Compare the keyword name against each parameter in turn. This is exactly the same method // which CPython uses to map keyword names. Although it's O(num_parameters), the number of // parameters is expected to be small so it's not worth constructing a mapping. self.keyword_only_parameters .iter() .position(|param_desc| param_desc.name == kwarg_name) } #[inline] fn ensure_no_missing_required_positional_arguments( &self, output: &[Option>], positional_args_provided: usize, ) -> PyResult<()> { if positional_args_provided < self.required_positional_parameters { for out in &output[positional_args_provided..self.required_positional_parameters] { if out.is_none() { return Err(self.missing_required_positional_arguments(output)); } } } Ok(()) } #[inline] fn ensure_no_missing_required_keyword_arguments( &self, output: &[Option>], ) -> PyResult<()> { let keyword_output = &output[self.positional_parameter_names.len()..]; for (param, out) in self.keyword_only_parameters.iter().zip(keyword_output) { if param.required && out.is_none() { return Err(self.missing_required_keyword_arguments(keyword_output)); } } Ok(()) } #[cold] fn too_many_positional_arguments(&self, args_provided: usize) -> PyErr { let was = if args_provided == 1 { "was" } else { "were" }; let msg = if self.required_positional_parameters != self.positional_parameter_names.len() { format!( "{} takes from {} to {} positional arguments but {} {} given", self.full_name(), self.required_positional_parameters, self.positional_parameter_names.len(), args_provided, was ) } else { format!( "{} takes {} positional arguments but {} {} given", self.full_name(), self.positional_parameter_names.len(), args_provided, was ) }; PyTypeError::new_err(msg) } #[cold] fn multiple_values_for_argument(&self, argument: &str) -> PyErr { PyTypeError::new_err(format!( "{} got multiple values for argument '{}'", self.full_name(), argument )) } #[cold] fn unexpected_keyword_argument(&self, argument: PyArg<'_>) -> PyErr { PyTypeError::new_err(format!( "{} got an unexpected keyword argument '{}'", self.full_name(), argument.as_any() )) } #[cold] fn positional_only_keyword_arguments(&self, parameter_names: &[&str]) -> PyErr { let mut msg = format!( "{} got some positional-only arguments passed as keyword arguments: ", self.full_name() ); push_parameter_list(&mut msg, parameter_names); PyTypeError::new_err(msg) } #[cold] fn missing_required_arguments(&self, argument_type: &str, parameter_names: &[&str]) -> PyErr { let arguments = if parameter_names.len() == 1 { "argument" } else { "arguments" }; let mut msg = format!( "{} missing {} required {} {}: ", self.full_name(), parameter_names.len(), argument_type, arguments, ); push_parameter_list(&mut msg, parameter_names); PyTypeError::new_err(msg) } #[cold] fn missing_required_keyword_arguments(&self, keyword_outputs: &[Option>]) -> PyErr { debug_assert_eq!(self.keyword_only_parameters.len(), keyword_outputs.len()); let missing_keyword_only_arguments: Vec<_> = self .keyword_only_parameters .iter() .zip(keyword_outputs) .filter_map(|(keyword_desc, out)| { if keyword_desc.required && out.is_none() { Some(keyword_desc.name) } else { None } }) .collect(); debug_assert!(!missing_keyword_only_arguments.is_empty()); self.missing_required_arguments("keyword", &missing_keyword_only_arguments) } #[cold] fn missing_required_positional_arguments(&self, output: &[Option>]) -> PyErr { let missing_positional_arguments: Vec<_> = self .positional_parameter_names .iter() .take(self.required_positional_parameters) .zip(output) .filter_map(|(param, out)| if out.is_none() { Some(*param) } else { None }) .collect(); debug_assert!(!missing_positional_arguments.is_empty()); self.missing_required_arguments("positional", &missing_positional_arguments) } } /// A trait used to control whether to accept varargs in FunctionDescription::extract_argument_(method) functions. pub trait VarargsHandler<'py> { type Varargs; /// Called by `FunctionDescription::extract_arguments_fastcall` with any additional arguments. fn handle_varargs_fastcall( py: Python<'py>, varargs: &[Option>], function_description: &FunctionDescription, ) -> PyResult; /// Called by `FunctionDescription::extract_arguments_tuple_dict` with the original tuple. /// /// Additional arguments are those in the tuple slice starting from `function_description.positional_parameter_names.len()`. fn handle_varargs_tuple( args: &Bound<'py, PyTuple>, function_description: &FunctionDescription, ) -> PyResult; } /// Marker struct which indicates varargs are not allowed. pub struct NoVarargs; impl<'py> VarargsHandler<'py> for NoVarargs { type Varargs = (); #[inline] fn handle_varargs_fastcall( _py: Python<'py>, varargs: &[Option>], function_description: &FunctionDescription, ) -> PyResult { let extra_arguments = varargs.len(); if extra_arguments > 0 { return Err(function_description.too_many_positional_arguments( function_description.positional_parameter_names.len() + extra_arguments, )); } Ok(()) } #[inline] fn handle_varargs_tuple( args: &Bound<'py, PyTuple>, function_description: &FunctionDescription, ) -> PyResult { let positional_parameter_count = function_description.positional_parameter_names.len(); let provided_args_count = args.len(); if provided_args_count <= positional_parameter_count { Ok(()) } else { Err(function_description.too_many_positional_arguments(provided_args_count)) } } } /// Marker struct which indicates varargs should be collected into a `PyTuple`. pub struct TupleVarargs; impl<'py> VarargsHandler<'py> for TupleVarargs { type Varargs = Bound<'py, PyTuple>; #[inline] fn handle_varargs_fastcall( py: Python<'py>, varargs: &[Option>], _function_description: &FunctionDescription, ) -> PyResult { PyTuple::new(py, varargs) } #[inline] fn handle_varargs_tuple( args: &Bound<'py, PyTuple>, function_description: &FunctionDescription, ) -> PyResult { let positional_parameters = function_description.positional_parameter_names.len(); Ok(args.get_slice(positional_parameters, args.len())) } } /// A trait used to control whether to accept varkeywords in FunctionDescription::extract_argument_(method) functions. pub trait VarkeywordsHandler<'py> { type Varkeywords: Default; fn handle_varkeyword( varkeywords: &mut Self::Varkeywords, name: PyArg<'py>, value: PyArg<'py>, function_description: &FunctionDescription, ) -> PyResult<()>; } /// Marker struct which indicates unknown keywords are not permitted. pub struct NoVarkeywords; impl<'py> VarkeywordsHandler<'py> for NoVarkeywords { type Varkeywords = (); #[inline] fn handle_varkeyword( _varkeywords: &mut Self::Varkeywords, name: PyArg<'py>, _value: PyArg<'py>, function_description: &FunctionDescription, ) -> PyResult<()> { Err(function_description.unexpected_keyword_argument(name)) } } /// Marker struct which indicates unknown keywords should be collected into a `PyDict`. pub struct DictVarkeywords; impl<'py> VarkeywordsHandler<'py> for DictVarkeywords { type Varkeywords = Option>; #[inline] fn handle_varkeyword( varkeywords: &mut Self::Varkeywords, name: PyArg<'py>, value: PyArg<'py>, _function_description: &FunctionDescription, ) -> PyResult<()> { varkeywords .get_or_insert_with(|| PyDict::new(name.py())) .set_item(name, value) } } fn push_parameter_list(msg: &mut String, parameter_names: &[&str]) { let len = parameter_names.len(); for (i, parameter) in parameter_names.iter().enumerate() { if i != 0 { if len > 2 { msg.push(','); } if i == len - 1 { msg.push_str(" and ") } else { msg.push(' ') } } msg.push('\''); msg.push_str(parameter); msg.push('\''); } } #[cfg(test)] mod tests { use crate::types::{IntoPyDict, PyTuple}; use crate::Python; use super::{push_parameter_list, FunctionDescription, NoVarargs, NoVarkeywords}; #[test] fn unexpected_keyword_argument() { let function_description = FunctionDescription { cls_name: None, func_name: "example", positional_parameter_names: &[], positional_only_parameters: 0, required_positional_parameters: 0, keyword_only_parameters: &[], }; Python::with_gil(|py| { let args = PyTuple::empty(py); let kwargs = [("foo", 0u8)].into_py_dict(py).unwrap(); let err = unsafe { function_description .extract_arguments_tuple_dict::( py, args.as_ptr(), kwargs.as_ptr(), &mut [], ) .unwrap_err() }; assert_eq!( err.to_string(), "TypeError: example() got an unexpected keyword argument 'foo'" ); }) } #[test] fn keyword_not_string() { let function_description = FunctionDescription { cls_name: None, func_name: "example", positional_parameter_names: &[], positional_only_parameters: 0, required_positional_parameters: 0, keyword_only_parameters: &[], }; Python::with_gil(|py| { let args = PyTuple::empty(py); let kwargs = [(1u8, 1u8)].into_py_dict(py).unwrap(); let err = unsafe { function_description .extract_arguments_tuple_dict::( py, args.as_ptr(), kwargs.as_ptr(), &mut [], ) .unwrap_err() }; assert_eq!( err.to_string(), "TypeError: example() got an unexpected keyword argument '1'" ); }) } #[test] fn missing_required_arguments() { let function_description = FunctionDescription { cls_name: None, func_name: "example", positional_parameter_names: &["foo", "bar"], positional_only_parameters: 0, required_positional_parameters: 2, keyword_only_parameters: &[], }; Python::with_gil(|py| { let args = PyTuple::empty(py); let mut output = [None, None]; let err = unsafe { function_description.extract_arguments_tuple_dict::( py, args.as_ptr(), std::ptr::null_mut(), &mut output, ) } .unwrap_err(); assert_eq!( err.to_string(), "TypeError: example() missing 2 required positional arguments: 'foo' and 'bar'" ); }) } #[test] fn push_parameter_list_empty() { let mut s = String::new(); push_parameter_list(&mut s, &[]); assert_eq!(&s, ""); } #[test] fn push_parameter_list_one() { let mut s = String::new(); push_parameter_list(&mut s, &["a"]); assert_eq!(&s, "'a'"); } #[test] fn push_parameter_list_two() { let mut s = String::new(); push_parameter_list(&mut s, &["a", "b"]); assert_eq!(&s, "'a' and 'b'"); } #[test] fn push_parameter_list_three() { let mut s = String::new(); push_parameter_list(&mut s, &["a", "b", "c"]); assert_eq!(&s, "'a', 'b', and 'c'"); } #[test] fn push_parameter_list_four() { let mut s = String::new(); push_parameter_list(&mut s, &["a", "b", "c", "d"]); assert_eq!(&s, "'a', 'b', 'c', and 'd'"); } } pyo3/src/impl_/wrap.rs0000644000175000017500000000760015105742312014505 0ustar bdrungbdrunguse std::{convert::Infallible, marker::PhantomData, ops::Deref}; use crate::{ffi, types::PyNone, Bound, IntoPyObject, IntoPyObjectExt, PyObject, PyResult, Python}; /// Used to wrap values in `Option` for default arguments. pub trait SomeWrap { fn wrap(self) -> Option; } impl SomeWrap for T { fn wrap(self) -> Option { Some(self) } } impl SomeWrap for Option { fn wrap(self) -> Self { self } } // Hierarchy of conversions used in the `IntoPy` implementation pub struct Converter(EmptyTupleConverter); pub struct EmptyTupleConverter(IntoPyObjectConverter); pub struct IntoPyObjectConverter(IntoPyConverter); pub struct IntoPyConverter(UnknownReturnResultType); pub struct UnknownReturnResultType(UnknownReturnType); pub struct UnknownReturnType(PhantomData); pub fn converter(_: &T) -> Converter { Converter(EmptyTupleConverter(IntoPyObjectConverter(IntoPyConverter( UnknownReturnResultType(UnknownReturnType(PhantomData)), )))) } impl Deref for Converter { type Target = EmptyTupleConverter; fn deref(&self) -> &Self::Target { &self.0 } } impl Deref for EmptyTupleConverter { type Target = IntoPyObjectConverter; fn deref(&self) -> &Self::Target { &self.0 } } impl Deref for IntoPyObjectConverter { type Target = IntoPyConverter; fn deref(&self) -> &Self::Target { &self.0 } } impl Deref for IntoPyConverter { type Target = UnknownReturnResultType; fn deref(&self) -> &Self::Target { &self.0 } } impl Deref for UnknownReturnResultType { type Target = UnknownReturnType; fn deref(&self) -> &Self::Target { &self.0 } } impl EmptyTupleConverter> { #[inline] pub fn map_into_ptr(&self, py: Python<'_>, obj: PyResult<()>) -> PyResult<*mut ffi::PyObject> { obj.map(|_| PyNone::get(py).to_owned().into_ptr()) } } impl<'py, T: IntoPyObject<'py>> IntoPyObjectConverter { #[inline] pub fn wrap(&self, obj: T) -> Result { Ok(obj) } } impl<'py, T: IntoPyObject<'py>, E> IntoPyObjectConverter> { #[inline] pub fn wrap(&self, obj: Result) -> Result { obj } #[inline] pub fn map_into_pyobject(&self, py: Python<'py>, obj: PyResult) -> PyResult where T: IntoPyObject<'py>, { obj.and_then(|obj| obj.into_py_any(py)) } #[inline] pub fn map_into_ptr(&self, py: Python<'py>, obj: PyResult) -> PyResult<*mut ffi::PyObject> where T: IntoPyObject<'py>, { obj.and_then(|obj| obj.into_bound_py_any(py)) .map(Bound::into_ptr) } } impl UnknownReturnResultType> { #[inline] pub fn wrap<'py>(&self, _: Result) -> Result where T: IntoPyObject<'py>, { unreachable!("should be handled by IntoPyObjectConverter") } } impl UnknownReturnType { #[inline] pub fn wrap<'py>(&self, _: T) -> T where T: IntoPyObject<'py>, { unreachable!("should be handled by IntoPyObjectConverter") } #[inline] pub fn map_into_pyobject<'py>(&self, _: Python<'py>, _: PyResult) -> PyResult where T: IntoPyObject<'py>, { unreachable!("should be handled by IntoPyObjectConverter") } #[inline] pub fn map_into_ptr<'py>(&self, _: Python<'py>, _: PyResult) -> PyResult<*mut ffi::PyObject> where T: IntoPyObject<'py>, { unreachable!("should be handled by IntoPyObjectConverter") } } #[cfg(test)] mod tests { use super::*; #[test] fn wrap_option() { let a: Option = SomeWrap::wrap(42); assert_eq!(a, Some(42)); let b: Option = SomeWrap::wrap(None); assert_eq!(b, None); } } pyo3/src/impl_/not_send.rs0000644000175000017500000000037515105742312015347 0ustar bdrungbdrunguse std::marker::PhantomData; use crate::Python; /// A marker type that makes the type !Send. /// Workaround for lack of !Send on stable (). pub(crate) struct NotSend(PhantomData<*mut Python<'static>>); pyo3/src/impl_/trampoline.rs0000644000175000017500000001645715105742312015720 0ustar bdrungbdrung//! Trampolines for various pyfunction and pymethod implementations. //! //! They exist to monomorphise std::panic::catch_unwind once into PyO3, rather than inline in every //! function, thus saving a huge amount of compile-time complexity. use std::{ any::Any, os::raw::c_int, panic::{self, UnwindSafe}, }; use crate::gil::GILGuard; use crate::{ ffi, ffi_ptr_ext::FfiPtrExt, impl_::callback::PyCallbackOutput, impl_::panic::PanicTrap, impl_::pymethods::IPowModulo, panic::PanicException, types::PyModule, Py, PyResult, Python, }; #[inline] pub unsafe fn module_init( f: for<'py> unsafe fn(Python<'py>) -> PyResult>, ) -> *mut ffi::PyObject { unsafe { trampoline(|py| f(py).map(|module| module.into_ptr())) } } #[inline] #[allow(clippy::used_underscore_binding)] pub unsafe fn noargs( slf: *mut ffi::PyObject, _args: *mut ffi::PyObject, f: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> PyResult<*mut ffi::PyObject>, ) -> *mut ffi::PyObject { #[cfg(not(GraalPy))] // this is not specified and GraalPy does not pass null here debug_assert!(_args.is_null()); unsafe { trampoline(|py| f(py, slf)) } } macro_rules! trampoline { (pub fn $name:ident($($arg_names:ident: $arg_types:ty),* $(,)?) -> $ret:ty;) => { #[inline] pub unsafe fn $name( $($arg_names: $arg_types,)* f: for<'py> unsafe fn (Python<'py>, $($arg_types),*) -> PyResult<$ret>, ) -> $ret { unsafe {trampoline(|py| f(py, $($arg_names,)*))} } } } macro_rules! trampolines { ($(pub fn $name:ident($($arg_names:ident: $arg_types:ty),* $(,)?) -> $ret:ty);* ;) => { $(trampoline!(pub fn $name($($arg_names: $arg_types),*) -> $ret;));*; } } trampolines!( pub fn fastcall_with_keywords( slf: *mut ffi::PyObject, args: *const *mut ffi::PyObject, nargs: ffi::Py_ssize_t, kwnames: *mut ffi::PyObject, ) -> *mut ffi::PyObject; pub fn cfunction_with_keywords( slf: *mut ffi::PyObject, args: *mut ffi::PyObject, kwargs: *mut ffi::PyObject, ) -> *mut ffi::PyObject; ); // Trampolines used by slot methods trampolines!( pub fn getattrofunc(slf: *mut ffi::PyObject, attr: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn setattrofunc( slf: *mut ffi::PyObject, attr: *mut ffi::PyObject, value: *mut ffi::PyObject, ) -> c_int; pub fn binaryfunc(slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn descrgetfunc( slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject, arg2: *mut ffi::PyObject, ) -> *mut ffi::PyObject; pub fn getiterfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn hashfunc(slf: *mut ffi::PyObject) -> ffi::Py_hash_t; pub fn inquiry(slf: *mut ffi::PyObject) -> c_int; pub fn iternextfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn lenfunc(slf: *mut ffi::PyObject) -> ffi::Py_ssize_t; pub fn newfunc( subtype: *mut ffi::PyTypeObject, args: *mut ffi::PyObject, kwargs: *mut ffi::PyObject, ) -> *mut ffi::PyObject; pub fn objobjproc(slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject) -> c_int; pub fn reprfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn richcmpfunc( slf: *mut ffi::PyObject, other: *mut ffi::PyObject, op: c_int, ) -> *mut ffi::PyObject; pub fn ssizeargfunc(arg1: *mut ffi::PyObject, arg2: ffi::Py_ssize_t) -> *mut ffi::PyObject; pub fn ternaryfunc( slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject, arg2: *mut ffi::PyObject, ) -> *mut ffi::PyObject; pub fn unaryfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject; ); #[cfg(any(not(Py_LIMITED_API), Py_3_11))] trampoline! { pub fn getbufferproc(slf: *mut ffi::PyObject, buf: *mut ffi::Py_buffer, flags: c_int) -> c_int; } #[cfg(any(not(Py_LIMITED_API), Py_3_11))] #[inline] pub unsafe fn releasebufferproc( slf: *mut ffi::PyObject, buf: *mut ffi::Py_buffer, f: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject, *mut ffi::Py_buffer) -> PyResult<()>, ) { unsafe { trampoline_unraisable(|py| f(py, slf, buf), slf) } } #[inline] pub(crate) unsafe fn dealloc( slf: *mut ffi::PyObject, f: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> (), ) { // After calling tp_dealloc the object is no longer valid, // so pass null_mut() to the context. // // (Note that we don't allow the implementation `f` to fail.) unsafe { trampoline_unraisable( |py| { f(py, slf); Ok(()) }, std::ptr::null_mut(), ) } } // Ipowfunc is a unique case where PyO3 has its own type // to workaround a problem on 3.7 (see IPowModulo type definition). // Once 3.7 support dropped can just remove this. trampoline!( pub fn ipowfunc( arg1: *mut ffi::PyObject, arg2: *mut ffi::PyObject, arg3: IPowModulo, ) -> *mut ffi::PyObject; ); /// Implementation of trampoline functions, which sets up a GILPool and calls F. /// /// Panics during execution are trapped so that they don't propagate through any /// outer FFI boundary. /// /// The GIL must already be held when this is called. #[inline] pub(crate) unsafe fn trampoline(body: F) -> R where F: for<'py> FnOnce(Python<'py>) -> PyResult + UnwindSafe, R: PyCallbackOutput, { let trap = PanicTrap::new("uncaught panic at ffi boundary"); // SAFETY: This function requires the GIL to already be held. let guard = unsafe { GILGuard::assume() }; let py = guard.python(); let out = panic_result_into_callback_output( py, panic::catch_unwind(move || -> PyResult<_> { body(py) }), ); trap.disarm(); out } /// Converts the output of std::panic::catch_unwind into a Python function output, either by raising a Python /// exception or by unwrapping the contained success output. #[inline] fn panic_result_into_callback_output( py: Python<'_>, panic_result: Result, Box>, ) -> R where R: PyCallbackOutput, { let py_err = match panic_result { Ok(Ok(value)) => return value, Ok(Err(py_err)) => py_err, Err(payload) => PanicException::from_panic_payload(payload), }; py_err.restore(py); R::ERR_VALUE } /// Implementation of trampoline for functions which can't return an error. /// /// Panics during execution are trapped so that they don't propagate through any /// outer FFI boundary. /// /// Exceptions produced are sent to `sys.unraisablehook`. /// /// # Safety /// /// - ctx must be either a valid ffi::PyObject or NULL /// - The GIL must already be held when this is called. #[inline] unsafe fn trampoline_unraisable(body: F, ctx: *mut ffi::PyObject) where F: for<'py> FnOnce(Python<'py>) -> PyResult<()> + UnwindSafe, { let trap = PanicTrap::new("uncaught panic at ffi boundary"); // SAFETY: The GIL is already held. let guard = unsafe { GILGuard::assume() }; let py = guard.python(); if let Err(py_err) = panic::catch_unwind(move || body(py)) .unwrap_or_else(|payload| Err(PanicException::from_panic_payload(payload))) { py_err.write_unraisable(py, unsafe { ctx.assume_borrowed_or_opt(py) }.as_deref()); } trap.disarm(); } pyo3/src/impl_/exceptions.rs0000644000175000017500000000141615105742312015714 0ustar bdrungbdrunguse crate::{sync::GILOnceCell, types::PyType, Bound, Py, Python}; pub struct ImportedExceptionTypeObject { imported_value: GILOnceCell>, module: &'static str, name: &'static str, } impl ImportedExceptionTypeObject { pub const fn new(module: &'static str, name: &'static str) -> Self { Self { imported_value: GILOnceCell::new(), module, name, } } pub fn get<'py>(&self, py: Python<'py>) -> &Bound<'py, PyType> { self.imported_value .import(py, self.module, self.name) .unwrap_or_else(|e| { panic!( "failed to import exception {}.{}: {}", self.module, self.name, e ) }) } } pyo3/src/impl_/pymodule.rs0000644000175000017500000002443015105742312015372 0ustar bdrungbdrung//! Implementation details of `#[pymodule]` which need to be accessible from proc-macro generated code. use std::{cell::UnsafeCell, ffi::CStr, marker::PhantomData}; #[cfg(all( not(any(PyPy, GraalPy)), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))), not(target_has_atomic = "64"), ))] use portable_atomic::AtomicI64; #[cfg(all( not(any(PyPy, GraalPy)), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))), target_has_atomic = "64", ))] use std::sync::atomic::AtomicI64; use std::sync::atomic::{AtomicBool, Ordering}; #[cfg(not(any(PyPy, GraalPy)))] use crate::exceptions::PyImportError; #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))] use crate::PyErr; use crate::{ ffi, impl_::pymethods::PyMethodDef, sync::GILOnceCell, types::{PyCFunction, PyModule, PyModuleMethods}, Bound, Py, PyClass, PyResult, PyTypeInfo, Python, }; /// `Sync` wrapper of `ffi::PyModuleDef`. pub struct ModuleDef { // wrapped in UnsafeCell so that Rust compiler treats this as interior mutability ffi_def: UnsafeCell, initializer: ModuleInitializer, /// Interpreter ID where module was initialized (not applicable on PyPy). #[cfg(all( not(any(PyPy, GraalPy)), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))) ))] interpreter: AtomicI64, /// Initialized module object, cached to avoid reinitialization. module: GILOnceCell>, /// Whether or not the module supports running without the GIL gil_used: AtomicBool, } /// Wrapper to enable initializer to be used in const fns. pub struct ModuleInitializer(pub for<'py> fn(&Bound<'py, PyModule>) -> PyResult<()>); unsafe impl Sync for ModuleDef {} impl ModuleDef { /// Make new module definition with given module name. pub const unsafe fn new( name: &'static CStr, doc: &'static CStr, initializer: ModuleInitializer, ) -> Self { #[allow(clippy::declare_interior_mutable_const)] const INIT: ffi::PyModuleDef = ffi::PyModuleDef { m_base: ffi::PyModuleDef_HEAD_INIT, m_name: std::ptr::null(), m_doc: std::ptr::null(), m_size: 0, m_methods: std::ptr::null_mut(), m_slots: std::ptr::null_mut(), m_traverse: None, m_clear: None, m_free: None, }; let ffi_def = UnsafeCell::new(ffi::PyModuleDef { m_name: name.as_ptr(), m_doc: doc.as_ptr(), ..INIT }); ModuleDef { ffi_def, initializer, // -1 is never expected to be a valid interpreter ID #[cfg(all( not(any(PyPy, GraalPy)), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))) ))] interpreter: AtomicI64::new(-1), module: GILOnceCell::new(), gil_used: AtomicBool::new(true), } } /// Builds a module using user given initializer. Used for [`#[pymodule]`][crate::pymodule]. #[cfg_attr(any(Py_LIMITED_API, not(Py_GIL_DISABLED)), allow(unused_variables))] pub fn make_module(&'static self, py: Python<'_>, gil_used: bool) -> PyResult> { // Check the interpreter ID has not changed, since we currently have no way to guarantee // that static data is not reused across interpreters. // // PyPy does not have subinterpreters, so no need to check interpreter ID. #[cfg(not(any(PyPy, GraalPy)))] { // PyInterpreterState_Get is only available on 3.9 and later, but is missing // from python3.dll for Windows stable API on 3.9 #[cfg(all(Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10)))))] { let current_interpreter = unsafe { ffi::PyInterpreterState_GetID(ffi::PyInterpreterState_Get()) }; crate::err::error_on_minusone(py, current_interpreter)?; if let Err(initialized_interpreter) = self.interpreter.compare_exchange( -1, current_interpreter, Ordering::SeqCst, Ordering::SeqCst, ) { if initialized_interpreter != current_interpreter { return Err(PyImportError::new_err( "PyO3 modules do not yet support subinterpreters, see https://github.com/PyO3/pyo3/issues/576", )); } } } #[cfg(not(all(Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))))))] { // CPython before 3.9 does not have APIs to check the interpreter ID, so best that can be // done to guard against subinterpreters is fail if the module is initialized twice if self.module.get(py).is_some() { return Err(PyImportError::new_err( "PyO3 modules compiled for CPython 3.8 or older may only be initialized once per interpreter process" )); } } } self.module .get_or_try_init(py, || { let module = unsafe { Py::::from_owned_ptr_or_err( py, ffi::PyModule_Create(self.ffi_def.get()), )? }; #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))] { let gil_used_ptr = { if gil_used { ffi::Py_MOD_GIL_USED } else { ffi::Py_MOD_GIL_NOT_USED } }; if unsafe { ffi::PyUnstable_Module_SetGIL(module.as_ptr(), gil_used_ptr) } < 0 { return Err(PyErr::fetch(py)); } } self.initializer.0(module.bind(py))?; Ok(module) }) .map(|py_module| py_module.clone_ref(py)) } } /// Trait to add an element (class, function...) to a module. /// /// Currently only implemented for classes. pub trait PyAddToModule: crate::sealed::Sealed { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()>; } /// For adding native types (non-pyclass) to a module. pub struct AddTypeToModule(PhantomData); impl AddTypeToModule { #[allow(clippy::new_without_default)] pub const fn new() -> Self { AddTypeToModule(PhantomData) } } impl PyAddToModule for AddTypeToModule { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add(T::NAME, T::type_object(module.py())) } } /// For adding a class to a module. pub struct AddClassToModule(PhantomData); impl AddClassToModule { #[allow(clippy::new_without_default)] pub const fn new() -> Self { AddClassToModule(PhantomData) } } impl PyAddToModule for AddClassToModule { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_class::() } } /// For adding a function to a module. impl PyAddToModule for PyMethodDef { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(PyCFunction::internal_new(module.py(), self, Some(module))?) } } /// For adding a module to a module. impl PyAddToModule for ModuleDef { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_submodule( self.make_module(module.py(), self.gil_used.load(Ordering::Relaxed))? .bind(module.py()), ) } } #[cfg(test)] mod tests { use std::{ borrow::Cow, ffi::CStr, sync::atomic::{AtomicBool, Ordering}, }; use crate::{ ffi, types::{any::PyAnyMethods, module::PyModuleMethods, PyModule}, Bound, PyResult, Python, }; use super::{ModuleDef, ModuleInitializer}; #[test] fn module_init() { static MODULE_DEF: ModuleDef = unsafe { ModuleDef::new( ffi::c_str!("test_module"), ffi::c_str!("some doc"), ModuleInitializer(|m| { m.add("SOME_CONSTANT", 42)?; Ok(()) }), ) }; Python::with_gil(|py| { let module = MODULE_DEF.make_module(py, false).unwrap().into_bound(py); assert_eq!( module .getattr("__name__") .unwrap() .extract::>() .unwrap(), "test_module", ); assert_eq!( module .getattr("__doc__") .unwrap() .extract::>() .unwrap(), "some doc", ); assert_eq!( module .getattr("SOME_CONSTANT") .unwrap() .extract::() .unwrap(), 42, ); }) } #[test] fn module_def_new() { // To get coverage for ModuleDef::new() need to create a non-static ModuleDef, however init // etc require static ModuleDef, so this test needs to be separated out. static NAME: &CStr = ffi::c_str!("test_module"); static DOC: &CStr = ffi::c_str!("some doc"); static INIT_CALLED: AtomicBool = AtomicBool::new(false); #[allow(clippy::unnecessary_wraps)] fn init(_: &Bound<'_, PyModule>) -> PyResult<()> { INIT_CALLED.store(true, Ordering::SeqCst); Ok(()) } unsafe { let module_def: ModuleDef = ModuleDef::new(NAME, DOC, ModuleInitializer(init)); assert_eq!((*module_def.ffi_def.get()).m_name, NAME.as_ptr() as _); assert_eq!((*module_def.ffi_def.get()).m_doc, DOC.as_ptr() as _); Python::with_gil(|py| { module_def.initializer.0(&py.import("builtins").unwrap()).unwrap(); assert!(INIT_CALLED.load(Ordering::SeqCst)); }) } } } pyo3/src/impl_/panic.rs0000644000175000017500000000112515105742312014622 0ustar bdrungbdrung/// Type which will panic if dropped. /// /// If this is dropped during a panic, this will cause an abort. /// /// Use this to avoid letting unwinds cross through the FFI boundary, which is UB. pub struct PanicTrap { msg: &'static str, } impl PanicTrap { #[inline] pub const fn new(msg: &'static str) -> Self { Self { msg } } #[inline] pub const fn disarm(self) { std::mem::forget(self) } } impl Drop for PanicTrap { fn drop(&mut self) { // Panic here will abort the process, assuming in an unwind. panic!("{}", self.msg) } } pyo3/src/impl_/pyfunction.rs0000644000175000017500000000327015105742312015731 0ustar bdrungbdrunguse crate::{ types::{PyCFunction, PyModule}, Borrowed, Bound, PyResult, Python, }; pub use crate::impl_::pymethods::PyMethodDef; /// Trait to enable the use of `wrap_pyfunction` with both `Python` and `PyModule`, /// and also to infer the return type of either `&'py PyCFunction` or `Bound<'py, PyCFunction>`. pub trait WrapPyFunctionArg<'py, T> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult; } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Bound<'py, PyModule> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.py(), method_def, Some(&self)) } } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Bound<'py, PyModule> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.py(), method_def, Some(self)) } } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Borrowed<'_, 'py, PyModule> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.py(), method_def, Some(&self)) } } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Borrowed<'_, 'py, PyModule> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.py(), method_def, Some(self)) } } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Python<'py> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self, method_def, None) } } pyo3/src/impl_/pymethods.rs0000644000175000017500000005410415105742312015551 0ustar bdrungbdrunguse crate::exceptions::PyStopAsyncIteration; use crate::gil::LockGIL; use crate::impl_::callback::IntoPyCallbackOutput; use crate::impl_::panic::PanicTrap; use crate::impl_::pycell::{PyClassObject, PyClassObjectLayout}; use crate::internal::get_slot::{get_slot, TP_BASE, TP_CLEAR, TP_TRAVERSE}; use crate::pycell::impl_::PyClassBorrowChecker as _; use crate::pycell::{PyBorrowError, PyBorrowMutError}; use crate::pyclass::boolean_struct::False; use crate::types::any::PyAnyMethods; use crate::types::PyType; use crate::{ ffi, Bound, DowncastError, Py, PyAny, PyClass, PyClassInitializer, PyErr, PyObject, PyRef, PyRefMut, PyResult, PyTraverseError, PyTypeCheck, PyVisit, Python, }; use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; use std::os::raw::{c_int, c_void}; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::ptr::null_mut; use super::trampoline; use crate::internal_tricks::{clear_eq, traverse_eq}; /// Python 3.8 and up - __ipow__ has modulo argument correctly populated. #[cfg(Py_3_8)] #[repr(transparent)] pub struct IPowModulo(*mut ffi::PyObject); /// Python 3.7 and older - __ipow__ does not have modulo argument correctly populated. #[cfg(not(Py_3_8))] #[repr(transparent)] pub struct IPowModulo(#[allow(dead_code)] std::mem::MaybeUninit<*mut ffi::PyObject>); /// Helper to use as pymethod ffi definition #[allow(non_camel_case_types)] pub type ipowfunc = unsafe extern "C" fn( arg1: *mut ffi::PyObject, arg2: *mut ffi::PyObject, arg3: IPowModulo, ) -> *mut ffi::PyObject; impl IPowModulo { #[cfg(Py_3_8)] #[inline] pub fn as_ptr(self) -> *mut ffi::PyObject { self.0 } #[cfg(not(Py_3_8))] #[inline] pub fn as_ptr(self) -> *mut ffi::PyObject { // Safety: returning a borrowed pointer to Python `None` singleton unsafe { ffi::Py_None() } } } /// `PyMethodDefType` represents different types of Python callable objects. /// It is used by the `#[pymethods]` attribute. #[cfg_attr(test, derive(Clone))] pub enum PyMethodDefType { /// Represents class method Class(PyMethodDef), /// Represents static method Static(PyMethodDef), /// Represents normal method Method(PyMethodDef), /// Represents class attribute, used by `#[attribute]` ClassAttribute(PyClassAttributeDef), /// Represents getter descriptor, used by `#[getter]` Getter(PyGetterDef), /// Represents setter descriptor, used by `#[setter]` Setter(PySetterDef), /// Represents a struct member StructMember(ffi::PyMemberDef), } #[derive(Copy, Clone, Debug)] pub enum PyMethodType { PyCFunction(ffi::PyCFunction), PyCFunctionWithKeywords(ffi::PyCFunctionWithKeywords), #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] PyCFunctionFastWithKeywords(ffi::PyCFunctionFastWithKeywords), } pub type PyClassAttributeFactory = for<'p> fn(Python<'p>) -> PyResult; // TODO: it would be nice to use CStr in these types, but then the constructors can't be const fn // until `CStr::from_bytes_with_nul_unchecked` is const fn. #[derive(Clone, Debug)] pub struct PyMethodDef { pub(crate) ml_name: &'static CStr, pub(crate) ml_meth: PyMethodType, pub(crate) ml_flags: c_int, pub(crate) ml_doc: &'static CStr, } #[derive(Copy, Clone)] pub struct PyClassAttributeDef { pub(crate) name: &'static CStr, pub(crate) meth: PyClassAttributeFactory, } #[derive(Clone)] pub struct PyGetterDef { pub(crate) name: &'static CStr, pub(crate) meth: Getter, pub(crate) doc: &'static CStr, } #[derive(Clone)] pub struct PySetterDef { pub(crate) name: &'static CStr, pub(crate) meth: Setter, pub(crate) doc: &'static CStr, } unsafe impl Sync for PyMethodDef {} unsafe impl Sync for PyGetterDef {} unsafe impl Sync for PySetterDef {} impl PyMethodDef { /// Define a function with no `*args` and `**kwargs`. pub const fn noargs( ml_name: &'static CStr, cfunction: ffi::PyCFunction, ml_doc: &'static CStr, ) -> Self { Self { ml_name, ml_meth: PyMethodType::PyCFunction(cfunction), ml_flags: ffi::METH_NOARGS, ml_doc, } } /// Define a function that can take `*args` and `**kwargs`. pub const fn cfunction_with_keywords( ml_name: &'static CStr, cfunction: ffi::PyCFunctionWithKeywords, ml_doc: &'static CStr, ) -> Self { Self { ml_name, ml_meth: PyMethodType::PyCFunctionWithKeywords(cfunction), ml_flags: ffi::METH_VARARGS | ffi::METH_KEYWORDS, ml_doc, } } /// Define a function that can take `*args` and `**kwargs`. #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] pub const fn fastcall_cfunction_with_keywords( ml_name: &'static CStr, cfunction: ffi::PyCFunctionFastWithKeywords, ml_doc: &'static CStr, ) -> Self { Self { ml_name, ml_meth: PyMethodType::PyCFunctionFastWithKeywords(cfunction), ml_flags: ffi::METH_FASTCALL | ffi::METH_KEYWORDS, ml_doc, } } pub const fn flags(mut self, flags: c_int) -> Self { self.ml_flags |= flags; self } /// Convert `PyMethodDef` to Python method definition struct `ffi::PyMethodDef` pub(crate) fn as_method_def(&self) -> ffi::PyMethodDef { let meth = match self.ml_meth { PyMethodType::PyCFunction(meth) => ffi::PyMethodDefPointer { PyCFunction: meth }, PyMethodType::PyCFunctionWithKeywords(meth) => ffi::PyMethodDefPointer { PyCFunctionWithKeywords: meth, }, #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] PyMethodType::PyCFunctionFastWithKeywords(meth) => ffi::PyMethodDefPointer { PyCFunctionFastWithKeywords: meth, }, }; ffi::PyMethodDef { ml_name: self.ml_name.as_ptr(), ml_meth: meth, ml_flags: self.ml_flags, ml_doc: self.ml_doc.as_ptr(), } } } impl PyClassAttributeDef { /// Define a class attribute. pub const fn new(name: &'static CStr, meth: PyClassAttributeFactory) -> Self { Self { name, meth } } } // Manual implementation because `Python<'_>` does not implement `Debug` and // trait bounds on `fn` compiler-generated derive impls are too restrictive. impl fmt::Debug for PyClassAttributeDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PyClassAttributeDef") .field("name", &self.name) .finish() } } /// Class getter / setters pub(crate) type Getter = for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> PyResult<*mut ffi::PyObject>; pub(crate) type Setter = for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject, *mut ffi::PyObject) -> PyResult; impl PyGetterDef { /// Define a getter. pub const fn new(name: &'static CStr, getter: Getter, doc: &'static CStr) -> Self { Self { name, meth: getter, doc, } } } impl PySetterDef { /// Define a setter. pub const fn new(name: &'static CStr, setter: Setter, doc: &'static CStr) -> Self { Self { name, meth: setter, doc, } } } /// Calls an implementation of __traverse__ for tp_traverse /// /// NB cannot accept `'static` visitor, this is a sanity check below: /// /// ```rust,compile_fail /// use pyo3::prelude::*; /// use pyo3::pyclass::{PyTraverseError, PyVisit}; /// /// #[pyclass] /// struct Foo; /// /// #[pymethods] /// impl Foo { /// fn __traverse__(&self, _visit: PyVisit<'static>) -> Result<(), PyTraverseError> { /// Ok(()) /// } /// } /// ``` /// /// Elided lifetime should compile ok: /// /// ```rust,no_run /// use pyo3::prelude::*; /// use pyo3::pyclass::{PyTraverseError, PyVisit}; /// /// #[pyclass] /// struct Foo; /// /// #[pymethods] /// impl Foo { /// fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { /// Ok(()) /// } /// } /// ``` #[doc(hidden)] pub unsafe fn _call_traverse( slf: *mut ffi::PyObject, impl_: fn(&T, PyVisit<'_>) -> Result<(), PyTraverseError>, visit: ffi::visitproc, arg: *mut c_void, current_traverse: ffi::traverseproc, ) -> c_int where T: PyClass, { // It is important the implementation of `__traverse__` cannot safely access the GIL, // c.f. https://github.com/PyO3/pyo3/issues/3165, and hence we do not expose our GIL // token to the user code and lock safe methods for acquiring the GIL. // (This includes enforcing the `&self` method receiver as e.g. `PyRef` could // reconstruct a GIL token via `PyRef::py`.) // Since we do not create a `GILPool` at all, it is important that our usage of the GIL // token does not produce any owned objects thereby calling into `register_owned`. let trap = PanicTrap::new("uncaught panic inside __traverse__ handler"); let lock = LockGIL::during_traverse(); let super_retval = unsafe { call_super_traverse(slf, visit, arg, current_traverse) }; if super_retval != 0 { return super_retval; } // SAFETY: `slf` is a valid Python object pointer to a class object of type T, and // traversal is running so no mutations can occur. let class_object: &PyClassObject = unsafe { &*slf.cast() }; let retval = // `#[pyclass(unsendable)]` types can only be deallocated by their own thread, so // do not traverse them if not on their owning thread :( if class_object.check_threadsafe().is_ok() // ... and we cannot traverse a type which might be being mutated by a Rust thread && class_object.borrow_checker().try_borrow().is_ok() { struct TraverseGuard<'a, T: PyClass>(&'a PyClassObject); impl Drop for TraverseGuard<'_, T> { fn drop(&mut self) { self.0.borrow_checker().release_borrow() } } // `.try_borrow()` above created a borrow, we need to release it when we're done // traversing the object. This allows us to read `instance` safely. let _guard = TraverseGuard(class_object); let instance = unsafe {&*class_object.contents.value.get()}; let visit = PyVisit { visit, arg, _guard: PhantomData }; match catch_unwind(AssertUnwindSafe(move || impl_(instance, visit))) { Ok(Ok(())) => 0, Ok(Err(traverse_error)) => traverse_error.into_inner(), Err(_err) => -1, } } else { 0 }; // Drop lock before trap just in case dropping lock panics drop(lock); trap.disarm(); retval } /// Call super-type traverse method, if necessary. /// /// Adapted from /// /// TODO: There are possible optimizations over looking up the base type in this way /// - if the base type is known in this module, can potentially look it up directly in module state /// (when we have it) /// - if the base type is a Python builtin, can jut call the C function directly /// - if the base type is a PyO3 type defined in the same module, can potentially do similar to /// tp_alloc where we solve this at compile time unsafe fn call_super_traverse( obj: *mut ffi::PyObject, visit: ffi::visitproc, arg: *mut c_void, current_traverse: ffi::traverseproc, ) -> c_int { // SAFETY: in this function here it's ok to work with raw type objects `ffi::Py_TYPE` // because the GC is running and so // - (a) we cannot do refcounting and // - (b) the type of the object cannot change. let mut ty = unsafe { ffi::Py_TYPE(obj) }; let mut traverse: Option; // First find the current type by the current_traverse function loop { traverse = unsafe { get_slot(ty, TP_TRAVERSE) }; if traverse_eq(traverse, current_traverse) { break; } ty = unsafe { get_slot(ty, TP_BASE) }; if ty.is_null() { // FIXME: return an error if current type not in the MRO? Should be impossible. return 0; } } // Get first base which has a different traverse function while traverse_eq(traverse, current_traverse) { ty = unsafe { get_slot(ty, TP_BASE) }; if ty.is_null() { break; } traverse = unsafe { get_slot(ty, TP_TRAVERSE) }; } // If we found a type with a different traverse function, call it if let Some(traverse) = traverse { return unsafe { traverse(obj, visit, arg) }; } // FIXME same question as cython: what if the current type is not in the MRO? 0 } /// Calls an implementation of __clear__ for tp_clear pub unsafe fn _call_clear( slf: *mut ffi::PyObject, impl_: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> PyResult<()>, current_clear: ffi::inquiry, ) -> c_int { unsafe { trampoline::trampoline(move |py| { let super_retval = call_super_clear(py, slf, current_clear); if super_retval != 0 { return Err(PyErr::fetch(py)); } impl_(py, slf)?; Ok(0) }) } } /// Call super-type traverse method, if necessary. /// /// Adapted from /// /// TODO: There are possible optimizations over looking up the base type in this way /// - if the base type is known in this module, can potentially look it up directly in module state /// (when we have it) /// - if the base type is a Python builtin, can jut call the C function directly /// - if the base type is a PyO3 type defined in the same module, can potentially do similar to /// tp_alloc where we solve this at compile time unsafe fn call_super_clear( py: Python<'_>, obj: *mut ffi::PyObject, current_clear: ffi::inquiry, ) -> c_int { let mut ty = unsafe { PyType::from_borrowed_type_ptr(py, ffi::Py_TYPE(obj)) }; let mut clear: Option; // First find the current type by the current_clear function loop { clear = ty.get_slot(TP_CLEAR); if clear_eq(clear, current_clear) { break; } let base = ty.get_slot(TP_BASE); if base.is_null() { // FIXME: return an error if current type not in the MRO? Should be impossible. return 0; } ty = unsafe { PyType::from_borrowed_type_ptr(py, base) }; } // Get first base which has a different clear function while clear_eq(clear, current_clear) { let base = ty.get_slot(TP_BASE); if base.is_null() { break; } ty = unsafe { PyType::from_borrowed_type_ptr(py, base) }; clear = ty.get_slot(TP_CLEAR); } // If we found a type with a different clear function, call it if let Some(clear) = clear { return unsafe { clear(obj) }; } // FIXME same question as cython: what if the current type is not in the MRO? 0 } // Autoref-based specialization for handling `__next__` returning `Option` pub struct IterBaseTag; impl IterBaseTag { #[inline] pub fn convert<'py, Value, Target>(self, py: Python<'py>, value: Value) -> PyResult where Value: IntoPyCallbackOutput<'py, Target>, { value.convert(py) } } pub trait IterBaseKind { #[inline] fn iter_tag(&self) -> IterBaseTag { IterBaseTag } } impl IterBaseKind for &Value {} pub struct IterOptionTag; impl IterOptionTag { #[inline] pub fn convert<'py, Value>( self, py: Python<'py>, value: Option, ) -> PyResult<*mut ffi::PyObject> where Value: IntoPyCallbackOutput<'py, *mut ffi::PyObject>, { match value { Some(value) => value.convert(py), None => Ok(null_mut()), } } } pub trait IterOptionKind { #[inline] fn iter_tag(&self) -> IterOptionTag { IterOptionTag } } impl IterOptionKind for Option {} pub struct IterResultOptionTag; impl IterResultOptionTag { #[inline] pub fn convert<'py, Value, Error>( self, py: Python<'py>, value: Result, Error>, ) -> PyResult<*mut ffi::PyObject> where Value: IntoPyCallbackOutput<'py, *mut ffi::PyObject>, Error: Into, { match value { Ok(Some(value)) => value.convert(py), Ok(None) => Ok(null_mut()), Err(err) => Err(err.into()), } } } pub trait IterResultOptionKind { #[inline] fn iter_tag(&self) -> IterResultOptionTag { IterResultOptionTag } } impl IterResultOptionKind for Result, Error> {} // Autoref-based specialization for handling `__anext__` returning `Option` pub struct AsyncIterBaseTag; impl AsyncIterBaseTag { #[inline] pub fn convert<'py, Value, Target>(self, py: Python<'py>, value: Value) -> PyResult where Value: IntoPyCallbackOutput<'py, Target>, { value.convert(py) } } pub trait AsyncIterBaseKind { #[inline] fn async_iter_tag(&self) -> AsyncIterBaseTag { AsyncIterBaseTag } } impl AsyncIterBaseKind for &Value {} pub struct AsyncIterOptionTag; impl AsyncIterOptionTag { #[inline] pub fn convert<'py, Value>( self, py: Python<'py>, value: Option, ) -> PyResult<*mut ffi::PyObject> where Value: IntoPyCallbackOutput<'py, *mut ffi::PyObject>, { match value { Some(value) => value.convert(py), None => Err(PyStopAsyncIteration::new_err(())), } } } pub trait AsyncIterOptionKind { #[inline] fn async_iter_tag(&self) -> AsyncIterOptionTag { AsyncIterOptionTag } } impl AsyncIterOptionKind for Option {} pub struct AsyncIterResultOptionTag; impl AsyncIterResultOptionTag { #[inline] pub fn convert<'py, Value, Error>( self, py: Python<'py>, value: Result, Error>, ) -> PyResult<*mut ffi::PyObject> where Value: IntoPyCallbackOutput<'py, *mut ffi::PyObject>, Error: Into, { match value { Ok(Some(value)) => value.convert(py), Ok(None) => Err(PyStopAsyncIteration::new_err(())), Err(err) => Err(err.into()), } } } pub trait AsyncIterResultOptionKind { #[inline] fn async_iter_tag(&self) -> AsyncIterResultOptionTag { AsyncIterResultOptionTag } } impl AsyncIterResultOptionKind for Result, Error> {} /// Used in `#[classmethod]` to pass the class object to the method /// and also in `#[pyfunction(pass_module)]`. /// /// This is a wrapper to avoid implementing `From` for GIL Refs. /// /// Once the GIL Ref API is fully removed, it should be possible to simplify /// this to just `&'a Bound<'py, T>` and `From` implementations. pub struct BoundRef<'a, 'py, T>(pub &'a Bound<'py, T>); impl<'a, 'py> BoundRef<'a, 'py, PyAny> { pub unsafe fn ref_from_ptr(py: Python<'py>, ptr: &'a *mut ffi::PyObject) -> Self { unsafe { BoundRef(Bound::ref_from_ptr(py, ptr)) } } pub unsafe fn ref_from_ptr_or_opt( py: Python<'py>, ptr: &'a *mut ffi::PyObject, ) -> Option { unsafe { Bound::ref_from_ptr_or_opt(py, ptr).as_ref().map(BoundRef) } } pub fn downcast(self) -> Result, DowncastError<'a, 'py>> { self.0.downcast::().map(BoundRef) } pub unsafe fn downcast_unchecked(self) -> BoundRef<'a, 'py, T> { unsafe { BoundRef(self.0.downcast_unchecked::()) } } } impl<'a, 'py, T: PyClass> TryFrom> for PyRef<'py, T> { type Error = PyBorrowError; #[inline] fn try_from(value: BoundRef<'a, 'py, T>) -> Result { value.0.try_borrow() } } impl<'a, 'py, T: PyClass> TryFrom> for PyRefMut<'py, T> { type Error = PyBorrowMutError; #[inline] fn try_from(value: BoundRef<'a, 'py, T>) -> Result { value.0.try_borrow_mut() } } impl<'a, 'py, T> From> for Bound<'py, T> { #[inline] fn from(bound: BoundRef<'a, 'py, T>) -> Self { bound.0.clone() } } impl<'a, 'py, T> From> for &'a Bound<'py, T> { #[inline] fn from(bound: BoundRef<'a, 'py, T>) -> Self { bound.0 } } impl From> for Py { #[inline] fn from(bound: BoundRef<'_, '_, T>) -> Self { bound.0.clone().unbind() } } impl<'py, T> std::ops::Deref for BoundRef<'_, 'py, T> { type Target = Bound<'py, T>; #[inline] fn deref(&self) -> &Self::Target { self.0 } } pub unsafe fn tp_new_impl( py: Python<'_>, initializer: PyClassInitializer, target_type: *mut ffi::PyTypeObject, ) -> PyResult<*mut ffi::PyObject> { unsafe { initializer .create_class_object_of_type(py, target_type) .map(Bound::into_ptr) } } #[cfg(test)] mod tests { #[test] #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] fn test_fastcall_function_with_keywords() { use super::PyMethodDef; use crate::types::{PyAnyMethods, PyCFunction}; use crate::{ffi, Python}; Python::with_gil(|py| { unsafe extern "C" fn accepts_no_arguments( _slf: *mut ffi::PyObject, _args: *const *mut ffi::PyObject, nargs: ffi::Py_ssize_t, kwargs: *mut ffi::PyObject, ) -> *mut ffi::PyObject { assert_eq!(nargs, 0); assert!(kwargs.is_null()); unsafe { Python::assume_gil_acquired().None().into_ptr() } } let f = PyCFunction::internal_new( py, &PyMethodDef::fastcall_cfunction_with_keywords( ffi::c_str!("test"), accepts_no_arguments, ffi::c_str!("doc"), ), None, ) .unwrap(); f.call0().unwrap(); }); } } pyo3/src/impl_/pyclass/0000775000175000017500000000000015105742312014643 5ustar bdrungbdrungpyo3/src/impl_/pyclass/lazy_type_object.rs0000644000175000017500000002170115105742312020556 0ustar bdrungbdrunguse std::{ ffi::CStr, marker::PhantomData, thread::{self, ThreadId}, }; #[cfg(Py_3_14)] use crate::err::error_on_minusone; #[cfg(Py_3_14)] use crate::types::PyTypeMethods; use crate::{ exceptions::PyRuntimeError, ffi, impl_::pyclass::MaybeRuntimePyMethodDef, impl_::pymethods::PyMethodDefType, pyclass::{create_type_object, PyClassTypeObject}, sync::GILOnceCell, types::PyType, Bound, PyClass, PyErr, PyObject, PyResult, Python, }; use std::sync::Mutex; use super::PyClassItemsIter; /// Lazy type object for PyClass. #[doc(hidden)] pub struct LazyTypeObject(LazyTypeObjectInner, PhantomData); // Non-generic inner of LazyTypeObject to keep code size down struct LazyTypeObjectInner { value: GILOnceCell, // Threads which have begun initialization of the `tp_dict`. Used for // reentrant initialization detection. initializing_threads: Mutex>, tp_dict_filled: GILOnceCell<()>, } impl LazyTypeObject { /// Creates an uninitialized `LazyTypeObject`. #[allow(clippy::new_without_default)] pub const fn new() -> Self { LazyTypeObject( LazyTypeObjectInner { value: GILOnceCell::new(), initializing_threads: Mutex::new(Vec::new()), tp_dict_filled: GILOnceCell::new(), }, PhantomData, ) } } impl LazyTypeObject { /// Gets the type object contained by this `LazyTypeObject`, initializing it if needed. pub fn get_or_init<'py>(&self, py: Python<'py>) -> &Bound<'py, PyType> { self.get_or_try_init(py).unwrap_or_else(|err| { err.print(py); panic!("failed to create type object for {}", T::NAME) }) } /// Fallible version of the above. pub(crate) fn get_or_try_init<'py>(&self, py: Python<'py>) -> PyResult<&Bound<'py, PyType>> { self.0 .get_or_try_init(py, create_type_object::, T::NAME, T::items_iter()) } } impl LazyTypeObjectInner { // Uses dynamically dispatched fn(Python<'py>) -> PyResult // so that this code is only instantiated once, instead of for every T // like the generic LazyTypeObject methods above. fn get_or_try_init<'py>( &self, py: Python<'py>, init: fn(Python<'py>) -> PyResult, name: &str, items_iter: PyClassItemsIter, ) -> PyResult<&Bound<'py, PyType>> { (|| -> PyResult<_> { let PyClassTypeObject { type_object, is_immutable_type, .. } = self.value.get_or_try_init(py, || init(py))?; let type_object = type_object.bind(py); self.ensure_init(type_object, *is_immutable_type, name, items_iter)?; Ok(type_object) })() .map_err(|err| { wrap_in_runtime_error( py, err, format!("An error occurred while initializing class {name}"), ) }) } fn ensure_init( &self, type_object: &Bound<'_, PyType>, #[allow(unused_variables)] is_immutable_type: bool, name: &str, items_iter: PyClassItemsIter, ) -> PyResult<()> { let py = type_object.py(); // We might want to fill the `tp_dict` with python instances of `T` // itself. In order to do so, we must first initialize the type object // with an empty `tp_dict`: now we can create instances of `T`. // // Then we fill the `tp_dict`. Multiple threads may try to fill it at // the same time, but only one of them will succeed. // // More importantly, if a thread is performing initialization of the // `tp_dict`, it can still request the type object through `get_or_init`, // but the `tp_dict` may appear empty of course. if self.tp_dict_filled.get(py).is_some() { // `tp_dict` is already filled: ok. return Ok(()); } let thread_id = thread::current().id(); { let mut threads = self.initializing_threads.lock().unwrap(); if threads.contains(&thread_id) { // Reentrant call: just return the type object, even if the // `tp_dict` is not filled yet. return Ok(()); } threads.push(thread_id); } struct InitializationGuard<'a> { initializing_threads: &'a Mutex>, thread_id: ThreadId, } impl Drop for InitializationGuard<'_> { fn drop(&mut self) { let mut threads = self.initializing_threads.lock().unwrap(); threads.retain(|id| *id != self.thread_id); } } let guard = InitializationGuard { initializing_threads: &self.initializing_threads, thread_id, }; // Pre-compute the class attribute objects: this can temporarily // release the GIL since we're calling into arbitrary user code. It // means that another thread can continue the initialization in the // meantime: at worst, we'll just make a useless computation. let mut items = vec![]; for class_items in items_iter { for def in class_items.methods { let built_method; let method = match def { MaybeRuntimePyMethodDef::Runtime(builder) => { built_method = builder(); &built_method } MaybeRuntimePyMethodDef::Static(method) => method, }; if let PyMethodDefType::ClassAttribute(attr) = method { match (attr.meth)(py) { Ok(val) => items.push((attr.name, val)), Err(err) => { return Err(wrap_in_runtime_error( py, err, format!( "An error occurred while initializing `{}.{}`", name, attr.name.to_str().unwrap() ), )) } } } } } // Now we hold the GIL and we can assume it won't be released until we // return from the function. let result = self.tp_dict_filled.get_or_try_init(py, move || { let result = initialize_tp_dict(py, type_object.as_ptr(), items); #[cfg(Py_3_14)] if is_immutable_type { // freeze immutable types after __dict__ is initialized let res = unsafe { ffi::PyType_Freeze(type_object.as_type_ptr()) }; error_on_minusone(py, res)?; } #[cfg(all(Py_3_10, not(Py_LIMITED_API), not(Py_3_14)))] if is_immutable_type { use crate::types::PyTypeMethods as _; #[cfg(not(Py_GIL_DISABLED))] unsafe { (*type_object.as_type_ptr()).tp_flags |= ffi::Py_TPFLAGS_IMMUTABLETYPE }; #[cfg(Py_GIL_DISABLED)] unsafe { (*type_object.as_type_ptr()).tp_flags.fetch_or( ffi::Py_TPFLAGS_IMMUTABLETYPE, std::sync::atomic::Ordering::Relaxed, ) }; unsafe { ffi::PyType_Modified(type_object.as_type_ptr()) }; } // Initialization successfully complete, can clear the thread list. // (No further calls to get_or_init() will try to init, on any thread.) let mut threads = { drop(guard); self.initializing_threads.lock().unwrap() }; threads.clear(); result }); if let Err(err) = result { return Err(wrap_in_runtime_error( py, err.clone_ref(py), format!("An error occurred while initializing `{name}.__dict__`"), )); } Ok(()) } } fn initialize_tp_dict( py: Python<'_>, type_object: *mut ffi::PyObject, items: Vec<(&'static CStr, PyObject)>, ) -> PyResult<()> { // We hold the GIL: the dictionary update can be considered atomic from // the POV of other threads. for (key, val) in items { crate::err::error_on_minusone(py, unsafe { ffi::PyObject_SetAttrString(type_object, key.as_ptr(), val.into_ptr()) })?; } Ok(()) } // This is necessary for making static `LazyTypeObject`s unsafe impl Sync for LazyTypeObject {} #[cold] fn wrap_in_runtime_error(py: Python<'_>, err: PyErr, message: String) -> PyErr { let runtime_err = PyRuntimeError::new_err(message); runtime_err.set_cause(py, Some(err)); runtime_err } pyo3/src/impl_/pyclass/assertions.rs0000644000175000017500000000222515105742312017402 0ustar bdrungbdrung/// Helper function that can be used at compile time to emit a diagnostic if /// the type does not implement `Sync` when it should. /// /// The mere act of invoking this function will cause the diagnostic to be /// emitted if `T` does not implement `Sync` when it should. /// /// The additional `const IS_SYNC: bool` parameter is used to allow the custom /// diagnostic to be emitted; if `PyClassSync` #[allow(unused)] pub const fn assert_pyclass_sync() where T: PyClassSync + Sync, { } #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "the trait `Sync` is not implemented for `{Self}`", label = "required by `#[pyclass]`", note = "replace thread-unsafe fields with thread-safe alternatives", note = "see for more information", ) )] pub trait PyClassSync {} impl PyClassSync for T where T: Sync {} mod tests { #[cfg(feature = "macros")] #[test] fn test_assert_pyclass_sync() { use super::assert_pyclass_sync; #[crate::pyclass(crate = "crate")] struct MyClass {} assert_pyclass_sync::(); } } pyo3/src/impl_/pyclass/probes.rs0000644000175000017500000000251515105742312016504 0ustar bdrungbdrunguse std::marker::PhantomData; use crate::{conversion::IntoPyObject, Py}; /// Trait used to combine with zero-sized types to calculate at compile time /// some property of a type. /// /// The trick uses the fact that an associated constant has higher priority /// than a trait constant, so we can use the trait to define the false case. /// /// The true case is defined in the zero-sized type's impl block, which is /// gated on some property like trait bound or only being implemented /// for fixed concrete types. pub trait Probe { const VALUE: bool = false; } macro_rules! probe { ($name:ident) => { pub struct $name(PhantomData); impl Probe for $name {} }; } probe!(IsPyT); impl IsPyT> { pub const VALUE: bool = true; } probe!(IsIntoPyObjectRef); // Possible clippy beta regression, // see https://github.com/rust-lang/rust-clippy/issues/13578 #[allow(clippy::extra_unused_lifetimes)] impl<'a, 'py, T: 'a> IsIntoPyObjectRef where &'a T: IntoPyObject<'py>, { pub const VALUE: bool = true; } probe!(IsIntoPyObject); impl<'py, T> IsIntoPyObject where T: IntoPyObject<'py>, { pub const VALUE: bool = true; } probe!(IsSync); impl IsSync { pub const VALUE: bool = true; } probe!(IsOption); impl IsOption> { pub const VALUE: bool = true; } pyo3/src/impl_/pycell.rs0000644000175000017500000000026615105742312015025 0ustar bdrungbdrung//! Externally-accessible implementation of pycell pub use crate::pycell::impl_::{ GetBorrowChecker, PyClassMutability, PyClassObject, PyClassObjectBase, PyClassObjectLayout, }; pyo3/src/impl_/callback.rs0000644000175000017500000001046315105742312015271 0ustar bdrungbdrung//! Utilities for a Python callable object that invokes a Rust function. use crate::err::{PyErr, PyResult}; use crate::exceptions::PyOverflowError; use crate::ffi::{self, Py_hash_t}; use crate::{BoundObject, IntoPyObject, PyObject, Python}; use std::os::raw::c_int; /// A type which can be the return type of a python C-API callback pub trait PyCallbackOutput: Copy { /// The error value to return to python if the callback raised an exception const ERR_VALUE: Self; } impl PyCallbackOutput for *mut ffi::PyObject { const ERR_VALUE: Self = std::ptr::null_mut(); } impl PyCallbackOutput for std::os::raw::c_int { const ERR_VALUE: Self = -1; } impl PyCallbackOutput for ffi::Py_ssize_t { const ERR_VALUE: Self = -1; } /// Convert the result of callback function into the appropriate return value. pub trait IntoPyCallbackOutput<'py, Target> { fn convert(self, py: Python<'py>) -> PyResult; } impl<'py, T, E, U> IntoPyCallbackOutput<'py, U> for Result where T: IntoPyCallbackOutput<'py, U>, E: Into, { #[inline] fn convert(self, py: Python<'py>) -> PyResult { match self { Ok(v) => v.convert(py), Err(e) => Err(e.into()), } } } impl<'py, T> IntoPyCallbackOutput<'py, *mut ffi::PyObject> for T where T: IntoPyObject<'py>, { #[inline] fn convert(self, py: Python<'py>) -> PyResult<*mut ffi::PyObject> { self.into_pyobject(py) .map(BoundObject::into_ptr) .map_err(Into::into) } } impl IntoPyCallbackOutput<'_, Self> for *mut ffi::PyObject { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(self) } } impl IntoPyCallbackOutput<'_, std::os::raw::c_int> for () { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(0) } } impl IntoPyCallbackOutput<'_, std::os::raw::c_int> for bool { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(self as c_int) } } impl IntoPyCallbackOutput<'_, ()> for () { #[inline] fn convert(self, _: Python<'_>) -> PyResult<()> { Ok(()) } } impl IntoPyCallbackOutput<'_, ffi::Py_ssize_t> for usize { #[inline] fn convert(self, _py: Python<'_>) -> PyResult { self.try_into().map_err(|_err| PyOverflowError::new_err(())) } } // Converters needed for `#[pyproto]` implementations impl IntoPyCallbackOutput<'_, bool> for bool { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(self) } } impl IntoPyCallbackOutput<'_, usize> for usize { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(self) } } impl<'py, T> IntoPyCallbackOutput<'py, PyObject> for T where T: IntoPyObject<'py>, { #[inline] fn convert(self, py: Python<'py>) -> PyResult { self.into_pyobject(py) .map(BoundObject::into_any) .map(BoundObject::unbind) .map_err(Into::into) } } pub trait WrappingCastTo { fn wrapping_cast(self) -> T; } macro_rules! wrapping_cast { ($from:ty, $to:ty) => { impl WrappingCastTo<$to> for $from { #[inline] fn wrapping_cast(self) -> $to { self as $to } } }; } wrapping_cast!(u8, Py_hash_t); wrapping_cast!(u16, Py_hash_t); wrapping_cast!(u32, Py_hash_t); wrapping_cast!(usize, Py_hash_t); wrapping_cast!(u64, Py_hash_t); wrapping_cast!(i8, Py_hash_t); wrapping_cast!(i16, Py_hash_t); wrapping_cast!(i32, Py_hash_t); wrapping_cast!(isize, Py_hash_t); wrapping_cast!(i64, Py_hash_t); pub struct HashCallbackOutput(Py_hash_t); impl IntoPyCallbackOutput<'_, Py_hash_t> for HashCallbackOutput { #[inline] fn convert(self, _py: Python<'_>) -> PyResult { let hash = self.0; if hash == -1 { Ok(-2) } else { Ok(hash) } } } impl IntoPyCallbackOutput<'_, HashCallbackOutput> for T where T: WrappingCastTo, { #[inline] fn convert(self, _py: Python<'_>) -> PyResult { Ok(HashCallbackOutput(self.wrapping_cast())) } } #[doc(hidden)] #[inline] pub fn convert<'py, T, U>(py: Python<'py>, value: T) -> PyResult where T: IntoPyCallbackOutput<'py, U>, { value.convert(py) } pyo3/src/impl_/frompyobject.rs0000644000175000017500000000700315105742312016234 0ustar bdrungbdrunguse crate::types::any::PyAnyMethods; use crate::Bound; use crate::{exceptions::PyTypeError, FromPyObject, PyAny, PyErr, PyResult, Python}; #[cold] pub fn failed_to_extract_enum( py: Python<'_>, type_name: &str, variant_names: &[&str], error_names: &[&str], errors: &[PyErr], ) -> PyErr { // TODO maybe use ExceptionGroup on Python 3.11+ ? let mut err_msg = format!( "failed to extract enum {} ('{}')", type_name, error_names.join(" | ") ); for ((variant_name, error_name), error) in variant_names.iter().zip(error_names).zip(errors) { use std::fmt::Write; write!( &mut err_msg, "\n- variant {variant_name} ({error_name}): {error_msg}", variant_name = variant_name, error_name = error_name, error_msg = extract_traceback(py, error.clone_ref(py)), ) .unwrap(); } PyTypeError::new_err(err_msg) } /// Flattens a chain of errors into a single string. fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String { use std::fmt::Write; let mut error_msg = error.to_string(); while let Some(cause) = error.cause(py) { write!(&mut error_msg, ", caused by {cause}").unwrap(); error = cause } error_msg } pub fn extract_struct_field<'py, T>( obj: &Bound<'py, PyAny>, struct_name: &str, field_name: &str, ) -> PyResult where T: FromPyObject<'py>, { match obj.extract() { Ok(value) => Ok(value), Err(err) => Err(failed_to_extract_struct_field( obj.py(), err, struct_name, field_name, )), } } pub fn extract_struct_field_with<'a, 'py, T>( extractor: fn(&'a Bound<'py, PyAny>) -> PyResult, obj: &'a Bound<'py, PyAny>, struct_name: &str, field_name: &str, ) -> PyResult { match extractor(obj) { Ok(value) => Ok(value), Err(err) => Err(failed_to_extract_struct_field( obj.py(), err, struct_name, field_name, )), } } #[cold] fn failed_to_extract_struct_field( py: Python<'_>, inner_err: PyErr, struct_name: &str, field_name: &str, ) -> PyErr { let new_err = PyTypeError::new_err(format!( "failed to extract field {struct_name}.{field_name}" )); new_err.set_cause(py, ::std::option::Option::Some(inner_err)); new_err } pub fn extract_tuple_struct_field<'py, T>( obj: &Bound<'py, PyAny>, struct_name: &str, index: usize, ) -> PyResult where T: FromPyObject<'py>, { match obj.extract() { Ok(value) => Ok(value), Err(err) => Err(failed_to_extract_tuple_struct_field( obj.py(), err, struct_name, index, )), } } pub fn extract_tuple_struct_field_with<'a, 'py, T>( extractor: fn(&'a Bound<'py, PyAny>) -> PyResult, obj: &'a Bound<'py, PyAny>, struct_name: &str, index: usize, ) -> PyResult { match extractor(obj) { Ok(value) => Ok(value), Err(err) => Err(failed_to_extract_tuple_struct_field( obj.py(), err, struct_name, index, )), } } #[cold] fn failed_to_extract_tuple_struct_field( py: Python<'_>, inner_err: PyErr, struct_name: &str, index: usize, ) -> PyErr { let new_err = PyTypeError::new_err(format!("failed to extract field {struct_name}.{index}")); new_err.set_cause(py, ::std::option::Option::Some(inner_err)); new_err } pyo3/src/impl_/pyclass_init.rs0000644000175000017500000000627215105742312016241 0ustar bdrungbdrung//! Contains initialization utilities for `#[pyclass]`. use crate::ffi_ptr_ext::FfiPtrExt; use crate::internal::get_slot::TP_ALLOC; use crate::types::PyType; use crate::{ffi, Borrowed, PyErr, PyResult, Python}; use crate::{ffi::PyTypeObject, sealed::Sealed, type_object::PyTypeInfo}; use std::marker::PhantomData; use std::ptr; /// Initializer for Python types. /// /// This trait is intended to use internally for distinguishing `#[pyclass]` and /// Python native types. pub trait PyObjectInit: Sized + Sealed { /// # Safety /// - `subtype` must be a valid pointer to a type object of T or a subclass. unsafe fn into_new_object( self, py: Python<'_>, subtype: *mut PyTypeObject, ) -> PyResult<*mut ffi::PyObject>; #[doc(hidden)] fn can_be_subclassed(&self) -> bool; } /// Initializer for Python native types, like `PyDict`. pub struct PyNativeTypeInitializer(pub PhantomData); impl PyObjectInit for PyNativeTypeInitializer { unsafe fn into_new_object( self, py: Python<'_>, subtype: *mut PyTypeObject, ) -> PyResult<*mut ffi::PyObject> { unsafe fn inner( py: Python<'_>, type_object: *mut PyTypeObject, subtype: *mut PyTypeObject, ) -> PyResult<*mut ffi::PyObject> { // HACK (due to FIXME below): PyBaseObject_Type's tp_new isn't happy with NULL arguments let is_base_object = ptr::eq(type_object, ptr::addr_of!(ffi::PyBaseObject_Type)); let subtype_borrowed: Borrowed<'_, '_, PyType> = unsafe { subtype .cast::() .assume_borrowed_unchecked(py) .downcast_unchecked() }; if is_base_object { let alloc = subtype_borrowed .get_slot(TP_ALLOC) .unwrap_or(ffi::PyType_GenericAlloc); let obj = unsafe { alloc(subtype, 0) }; return if obj.is_null() { Err(PyErr::fetch(py)) } else { Ok(obj) }; } #[cfg(Py_LIMITED_API)] unreachable!("subclassing native types is not possible with the `abi3` feature"); #[cfg(not(Py_LIMITED_API))] { match unsafe { (*type_object).tp_new } { // FIXME: Call __new__ with actual arguments Some(newfunc) => { let obj = unsafe { newfunc(subtype, std::ptr::null_mut(), std::ptr::null_mut()) }; if obj.is_null() { Err(PyErr::fetch(py)) } else { Ok(obj) } } None => Err(crate::exceptions::PyTypeError::new_err( "base type without tp_new", )), } } } let type_object = T::type_object_raw(py); unsafe { inner(py, type_object, subtype) } } #[inline] fn can_be_subclassed(&self) -> bool { true } } pyo3/src/impl_/freelist.rs0000644000175000017500000000420315105742312015345 0ustar bdrungbdrung//! Support for [free allocation lists][1]. //! //! This can improve performance for types that are often created and deleted in quick succession. //! //! Rather than implementing this manually, //! implement it by annotating a struct with `#[pyclass(freelist = N)]`, //! where `N` is the size of the freelist. //! //! [1]: https://en.wikipedia.org/wiki/Free_list use crate::ffi; use std::mem; /// Represents a slot of a [`PyObjectFreeList`]. enum PyObjectSlot { /// A free slot. Empty, /// An allocated slot. Filled(*mut ffi::PyObject), } // safety: access is guarded by a per-pyclass mutex unsafe impl Send for PyObjectSlot {} /// A free allocation list for PyObject ffi pointers. /// /// See [the parent module](crate::impl_::freelist) for more details. pub struct PyObjectFreeList { entries: Box<[PyObjectSlot]>, split: usize, capacity: usize, } impl PyObjectFreeList { /// Creates a new `PyObjectFreeList` instance with specified capacity. pub fn with_capacity(capacity: usize) -> PyObjectFreeList { let entries = (0..capacity) .map(|_| PyObjectSlot::Empty) .collect::>(); PyObjectFreeList { entries, split: 0, capacity, } } /// Pops the first non empty item. pub fn pop(&mut self) -> Option<*mut ffi::PyObject> { let idx = self.split; if idx == 0 { None } else { match mem::replace(&mut self.entries[idx - 1], PyObjectSlot::Empty) { PyObjectSlot::Filled(v) => { self.split = idx - 1; Some(v) } _ => panic!("PyObjectFreeList is corrupt"), } } } /// Inserts a value into the list. Returns `Some(val)` if the `PyObjectFreeList` is full. pub fn insert(&mut self, val: *mut ffi::PyObject) -> Option<*mut ffi::PyObject> { let next = self.split + 1; if next < self.capacity { self.entries[self.split] = PyObjectSlot::Filled(val); self.split = next; None } else { Some(val) } } } pyo3/src/instance.rs0000644000175000017500000022535015105742312014244 0ustar bdrungbdrunguse crate::conversion::IntoPyObject; use crate::err::{self, PyErr, PyResult}; use crate::impl_::pycell::PyClassObject; use crate::internal_tricks::ptr_from_ref; use crate::pycell::{PyBorrowError, PyBorrowMutError}; use crate::pyclass::boolean_struct::{False, True}; use crate::types::{any::PyAnyMethods, string::PyStringMethods, typeobject::PyTypeMethods}; use crate::types::{DerefToPyAny, PyDict, PyString, PyTuple}; use crate::{ ffi, DowncastError, FromPyObject, PyAny, PyClass, PyClassInitializer, PyRef, PyRefMut, PyTypeInfo, Python, }; use crate::{gil, PyTypeCheck}; use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::ops::Deref; use std::ptr; use std::ptr::NonNull; /// Owned or borrowed gil-bound Python smart pointer /// /// This is implemented for [`Bound`] and [`Borrowed`]. pub trait BoundObject<'py, T>: bound_object_sealed::Sealed { /// Type erased version of `Self` type Any: BoundObject<'py, PyAny>; /// Borrow this smart pointer. fn as_borrowed(&self) -> Borrowed<'_, 'py, T>; /// Turns this smart pointer into an owned [`Bound<'py, T>`] fn into_bound(self) -> Bound<'py, T>; /// Upcast the target type of this smart pointer fn into_any(self) -> Self::Any; /// Turn this smart pointer into a strong reference pointer fn into_ptr(self) -> *mut ffi::PyObject; /// Turn this smart pointer into a borrowed reference pointer fn as_ptr(&self) -> *mut ffi::PyObject; /// Turn this smart pointer into an owned [`Py`] fn unbind(self) -> Py; } mod bound_object_sealed { /// # Safety /// /// Type must be layout-compatible with `*mut ffi::PyObject`. pub unsafe trait Sealed {} // SAFETY: `Bound` is layout-compatible with `*mut ffi::PyObject`. unsafe impl Sealed for super::Bound<'_, T> {} // SAFETY: `Borrowed` is layout-compatible with `*mut ffi::PyObject`. unsafe impl Sealed for super::Borrowed<'_, '_, T> {} } /// A GIL-attached equivalent to [`Py`]. /// /// This type can be thought of as equivalent to the tuple `(Py, Python<'py>)`. By having the `'py` /// lifetime of the [`Python<'py>`] token, this ties the lifetime of the [`Bound<'py, T>`] smart pointer /// to the lifetime of the GIL and allows PyO3 to call Python APIs at maximum efficiency. /// /// To access the object in situations where the GIL is not held, convert it to [`Py`] /// using [`.unbind()`][Bound::unbind]. This includes situations where the GIL is temporarily /// released, such as [`Python::allow_threads`](crate::Python::allow_threads)'s closure. /// /// See #[doc = concat!("[the guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/types.html#boundpy-t)")] /// for more detail. #[repr(transparent)] pub struct Bound<'py, T>(Python<'py>, ManuallyDrop>); impl<'py, T> Bound<'py, T> where T: PyClass, { /// Creates a new instance `Bound` of a `#[pyclass]` on the Python heap. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Foo {/* fields omitted */} /// /// # fn main() -> PyResult<()> { /// let foo: Py = Python::with_gil(|py| -> PyResult<_> { /// let foo: Bound<'_, Foo> = Bound::new(py, Foo {})?; /// Ok(foo.into()) /// })?; /// # Python::with_gil(move |_py| drop(foo)); /// # Ok(()) /// # } /// ``` pub fn new( py: Python<'py>, value: impl Into>, ) -> PyResult> { value.into().create_class_object(py) } } impl<'py> Bound<'py, PyAny> { /// Constructs a new `Bound<'py, PyAny>` from a pointer. Panics if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership #[inline] #[track_caller] pub unsafe fn from_owned_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { Self( py, ManuallyDrop::new(unsafe { Py::from_owned_ptr(py, ptr) }), ) } /// Constructs a new `Bound<'py, PyAny>` from a pointer. Returns `None` if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership #[inline] pub unsafe fn from_owned_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option { unsafe { Py::from_owned_ptr_or_opt(py, ptr) }.map(|obj| Self(py, ManuallyDrop::new(obj))) } /// Constructs a new `Bound<'py, PyAny>` from a pointer. Returns an `Err` by calling `PyErr::fetch` /// if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership #[inline] pub unsafe fn from_owned_ptr_or_err( py: Python<'py>, ptr: *mut ffi::PyObject, ) -> PyResult { unsafe { Py::from_owned_ptr_or_err(py, ptr) }.map(|obj| Self(py, ManuallyDrop::new(obj))) } /// Constructs a new `Bound<'py, PyAny>` from a pointer without checking for null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object /// - `ptr` must be a strong/owned reference pub(crate) unsafe fn from_owned_ptr_unchecked( py: Python<'py>, ptr: *mut ffi::PyObject, ) -> Self { Self( py, ManuallyDrop::new(unsafe { Py::from_owned_ptr_unchecked(ptr) }), ) } /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. /// Panics if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object #[inline] #[track_caller] pub unsafe fn from_borrowed_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { unsafe { Self(py, ManuallyDrop::new(Py::from_borrowed_ptr(py, ptr))) } } /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. /// Returns `None` if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null #[inline] pub unsafe fn from_borrowed_ptr_or_opt( py: Python<'py>, ptr: *mut ffi::PyObject, ) -> Option { unsafe { Py::from_borrowed_ptr_or_opt(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj))) } } /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. /// Returns an `Err` by calling `PyErr::fetch` if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null #[inline] pub unsafe fn from_borrowed_ptr_or_err( py: Python<'py>, ptr: *mut ffi::PyObject, ) -> PyResult { unsafe { Py::from_borrowed_ptr_or_err(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj))) } } /// This slightly strange method is used to obtain `&Bound` from a pointer in macro code /// where we need to constrain the lifetime `'a` safely. /// /// Note that `'py` is required to outlive `'a` implicitly by the nature of the fact that /// `&'a Bound<'py>` means that `Bound<'py>` exists for at least the lifetime `'a`. /// /// # Safety /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a`. The `ptr` can /// be either a borrowed reference or an owned reference, it does not matter, as this is /// just `&Bound` there will never be any ownership transfer. #[inline] pub(crate) unsafe fn ref_from_ptr<'a>( _py: Python<'py>, ptr: &'a *mut ffi::PyObject, ) -> &'a Self { unsafe { &*ptr_from_ref(ptr).cast::>() } } /// Variant of the above which returns `None` for null pointers. /// /// # Safety /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a, or null. #[inline] pub(crate) unsafe fn ref_from_ptr_or_opt<'a>( _py: Python<'py>, ptr: &'a *mut ffi::PyObject, ) -> &'a Option { unsafe { &*ptr_from_ref(ptr).cast::>>() } } } impl<'py, T> Bound<'py, T> where T: PyClass, { /// Immutably borrows the value `T`. /// /// This borrow lasts while the returned [`PyRef`] exists. /// Multiple immutable borrows can be taken out at the same time. /// /// For frozen classes, the simpler [`get`][Self::get] is available. /// /// # Examples /// /// ```rust /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct Foo { /// inner: u8, /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let foo: Bound<'_, Foo> = Bound::new(py, Foo { inner: 73 })?; /// let inner: &u8 = &foo.borrow().inner; /// /// assert_eq!(*inner, 73); /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Panics /// /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use /// [`try_borrow`](#method.try_borrow). #[inline] #[track_caller] pub fn borrow(&self) -> PyRef<'py, T> { PyRef::borrow(self) } /// Mutably borrows the value `T`. /// /// This borrow lasts while the returned [`PyRefMut`] exists. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct Foo { /// inner: u8, /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let foo: Bound<'_, Foo> = Bound::new(py, Foo { inner: 73 })?; /// foo.borrow_mut().inner = 35; /// /// assert_eq!(foo.borrow().inner, 35); /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Panics /// Panics if the value is currently borrowed. For a non-panicking variant, use /// [`try_borrow_mut`](#method.try_borrow_mut). #[inline] #[track_caller] pub fn borrow_mut(&self) -> PyRefMut<'py, T> where T: PyClass, { PyRefMut::borrow(self) } /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed. /// /// The borrow lasts while the returned [`PyRef`] exists. /// /// This is the non-panicking variant of [`borrow`](#method.borrow). /// /// For frozen classes, the simpler [`get`][Self::get] is available. #[inline] pub fn try_borrow(&self) -> Result, PyBorrowError> { PyRef::try_borrow(self) } /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed. /// /// The borrow lasts while the returned [`PyRefMut`] exists. /// /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). #[inline] pub fn try_borrow_mut(&self) -> Result, PyBorrowMutError> where T: PyClass, { PyRefMut::try_borrow(self) } /// Provide an immutable borrow of the value `T` without acquiring the GIL. /// /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`]. /// /// # Examples /// /// ``` /// use std::sync::atomic::{AtomicUsize, Ordering}; /// # use pyo3::prelude::*; /// /// #[pyclass(frozen)] /// struct FrozenCounter { /// value: AtomicUsize, /// } /// /// Python::with_gil(|py| { /// let counter = FrozenCounter { value: AtomicUsize::new(0) }; /// /// let py_counter = Bound::new(py, counter).unwrap(); /// /// py_counter.get().value.fetch_add(1, Ordering::Relaxed); /// }); /// ``` #[inline] pub fn get(&self) -> &T where T: PyClass + Sync, { self.1.get() } /// Upcast this `Bound` to its base type by reference. /// /// If this type defined an explicit base class in its `pyclass` declaration /// (e.g. `#[pyclass(extends = BaseType)]`), the returned type will be /// `&Bound`. If an explicit base class was _not_ declared, the /// return value will be `&Bound` (making this method equivalent /// to [`as_any`]). /// /// This method is particularly useful for calling methods defined in an /// extension trait that has been implemented for `Bound`. /// /// See also the [`into_super`] method to upcast by value, and the /// [`PyRef::as_super`]/[`PyRefMut::as_super`] methods for upcasting a pyclass /// that has already been [`borrow`]ed. /// /// # Example: Calling a method defined on the `Bound` base type /// /// ```rust /// # fn main() { /// use pyo3::prelude::*; /// /// #[pyclass(subclass)] /// struct BaseClass; /// /// trait MyClassMethods<'py> { /// fn pyrepr(&self) -> PyResult; /// } /// impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> { /// fn pyrepr(&self) -> PyResult { /// self.call_method0("__repr__")?.extract() /// } /// } /// /// #[pyclass(extends = BaseClass)] /// struct SubClass; /// /// Python::with_gil(|py| { /// let obj = Bound::new(py, (SubClass, BaseClass)).unwrap(); /// assert!(obj.as_super().pyrepr().is_ok()); /// }) /// # } /// ``` /// /// [`as_any`]: Bound::as_any /// [`into_super`]: Bound::into_super /// [`borrow`]: Bound::borrow #[inline] pub fn as_super(&self) -> &Bound<'py, T::BaseType> { // a pyclass can always be safely "downcast" to its base type unsafe { self.as_any().downcast_unchecked() } } /// Upcast this `Bound` to its base type by value. /// /// If this type defined an explicit base class in its `pyclass` declaration /// (e.g. `#[pyclass(extends = BaseType)]`), the returned type will be /// `Bound`. If an explicit base class was _not_ declared, the /// return value will be `Bound` (making this method equivalent /// to [`into_any`]). /// /// This method is particularly useful for calling methods defined in an /// extension trait that has been implemented for `Bound`. /// /// See also the [`as_super`] method to upcast by reference, and the /// [`PyRef::into_super`]/[`PyRefMut::into_super`] methods for upcasting a pyclass /// that has already been [`borrow`]ed. /// /// # Example: Calling a method defined on the `Bound` base type /// /// ```rust /// # fn main() { /// use pyo3::prelude::*; /// /// #[pyclass(subclass)] /// struct BaseClass; /// /// trait MyClassMethods<'py> { /// fn pyrepr(self) -> PyResult; /// } /// impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> { /// fn pyrepr(self) -> PyResult { /// self.call_method0("__repr__")?.extract() /// } /// } /// /// #[pyclass(extends = BaseClass)] /// struct SubClass; /// /// Python::with_gil(|py| { /// let obj = Bound::new(py, (SubClass, BaseClass)).unwrap(); /// assert!(obj.into_super().pyrepr().is_ok()); /// }) /// # } /// ``` /// /// [`into_any`]: Bound::into_any /// [`as_super`]: Bound::as_super /// [`borrow`]: Bound::borrow #[inline] pub fn into_super(self) -> Bound<'py, T::BaseType> { // a pyclass can always be safely "downcast" to its base type unsafe { self.into_any().downcast_into_unchecked() } } #[inline] pub(crate) fn get_class_object(&self) -> &PyClassObject { self.1.get_class_object() } } impl std::fmt::Debug for Bound<'_, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let any = self.as_any(); python_format(any, any.repr(), f) } } impl std::fmt::Display for Bound<'_, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let any = self.as_any(); python_format(any, any.str(), f) } } fn python_format( any: &Bound<'_, PyAny>, format_result: PyResult>, f: &mut std::fmt::Formatter<'_>, ) -> Result<(), std::fmt::Error> { match format_result { Result::Ok(s) => return f.write_str(&s.to_string_lossy()), Result::Err(err) => err.write_unraisable(any.py(), Some(any)), } match any.get_type().name() { Result::Ok(name) => std::write!(f, ""), Result::Err(_err) => f.write_str(""), } } // The trait bound is needed to avoid running into the auto-deref recursion // limit (error[E0055]), because `Bound` would deref into itself. See: // https://github.com/rust-lang/rust/issues/19509 impl<'py, T> Deref for Bound<'py, T> where T: DerefToPyAny, { type Target = Bound<'py, PyAny>; #[inline] fn deref(&self) -> &Bound<'py, PyAny> { self.as_any() } } impl<'py, T> AsRef> for Bound<'py, T> { #[inline] fn as_ref(&self) -> &Bound<'py, PyAny> { self.as_any() } } impl AsRef> for Bound<'_, T> { #[inline] fn as_ref(&self) -> &Py { self.as_any().as_unbound() } } impl Clone for Bound<'_, T> { #[inline] fn clone(&self) -> Self { Self(self.0, ManuallyDrop::new(self.1.clone_ref(self.0))) } } impl Drop for Bound<'_, T> { #[inline] fn drop(&mut self) { unsafe { ffi::Py_DECREF(self.as_ptr()) } } } impl<'py, T> Bound<'py, T> { /// Returns the GIL token associated with this object. #[inline] pub fn py(&self) -> Python<'py> { self.0 } /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { self.1.as_ptr() } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(self) -> *mut ffi::PyObject { ManuallyDrop::new(self).as_ptr() } /// Helper to cast to `Bound<'py, PyAny>`. #[inline] pub fn as_any(&self) -> &Bound<'py, PyAny> { // Safety: all Bound have the same memory layout, and all Bound are valid // Bound, so pointer casting is valid. unsafe { &*ptr_from_ref(self).cast::>() } } /// Helper to cast to `Bound<'py, PyAny>`, transferring ownership. #[inline] pub fn into_any(self) -> Bound<'py, PyAny> { // Safety: all Bound are valid Bound Bound(self.0, ManuallyDrop::new(self.unbind().into_any())) } /// Casts this `Bound` to a `Borrowed` smart pointer. #[inline] pub fn as_borrowed<'a>(&'a self) -> Borrowed<'a, 'py, T> { Borrowed( unsafe { NonNull::new_unchecked(self.as_ptr()) }, PhantomData, self.py(), ) } /// Removes the connection for this `Bound` from the GIL, allowing /// it to cross thread boundaries. #[inline] pub fn unbind(self) -> Py { // Safety: the type T is known to be correct and the ownership of the // pointer is transferred to the new Py instance. let non_null = (ManuallyDrop::new(self).1).0; unsafe { Py::from_non_null(non_null) } } /// Removes the connection for this `Bound` from the GIL, allowing /// it to cross thread boundaries, without transferring ownership. #[inline] pub fn as_unbound(&self) -> &Py { &self.1 } } impl<'py, T> BoundObject<'py, T> for Bound<'py, T> { type Any = Bound<'py, PyAny>; fn as_borrowed(&self) -> Borrowed<'_, 'py, T> { Bound::as_borrowed(self) } fn into_bound(self) -> Bound<'py, T> { self } fn into_any(self) -> Self::Any { self.into_any() } fn into_ptr(self) -> *mut ffi::PyObject { self.into_ptr() } fn as_ptr(&self) -> *mut ffi::PyObject { self.as_ptr() } fn unbind(self) -> Py { self.unbind() } } /// A borrowed equivalent to `Bound`. /// /// The advantage of this over `&Bound` is that it avoids the need to have a pointer-to-pointer, as Bound /// is already a pointer to an `ffi::PyObject``. /// /// Similarly, this type is `Copy` and `Clone`, like a shared reference (`&T`). #[repr(transparent)] pub struct Borrowed<'a, 'py, T>(NonNull, PhantomData<&'a Py>, Python<'py>); impl<'a, 'py, T> Borrowed<'a, 'py, T> { /// Creates a new owned [`Bound`] from this borrowed reference by /// increasing the reference count. /// /// # Example /// ``` /// use pyo3::{prelude::*, types::PyTuple}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let tuple = PyTuple::new(py, [1, 2, 3])?; /// /// // borrows from `tuple`, so can only be /// // used while `tuple` stays alive /// let borrowed = tuple.get_borrowed_item(0)?; /// /// // creates a new owned reference, which /// // can be used indendently of `tuple` /// let bound = borrowed.to_owned(); /// drop(tuple); /// /// assert_eq!(bound.extract::().unwrap(), 1); /// Ok(()) /// }) /// # } pub fn to_owned(self) -> Bound<'py, T> { (*self).clone() } /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(self) -> *mut ffi::PyObject { self.0.as_ptr() } pub(crate) fn to_any(self) -> Borrowed<'a, 'py, PyAny> { Borrowed(self.0, PhantomData, self.2) } } impl<'a, 'py> Borrowed<'a, 'py, PyAny> { /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Panics if `ptr` is null. /// /// Prefer to use [`Bound::from_borrowed_ptr`], as that avoids the major safety risk /// of needing to precisely define the lifetime `'a` for which the borrow is valid. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it is the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. #[inline] #[track_caller] pub unsafe fn from_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { Self( NonNull::new(ptr).unwrap_or_else(|| crate::err::panic_after_error(py)), PhantomData, py, ) } /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Returns `None` if `ptr` is null. /// /// Prefer to use [`Bound::from_borrowed_ptr_or_opt`], as that avoids the major safety risk /// of needing to precisely define the lifetime `'a` for which the borrow is valid. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it is the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. #[inline] pub unsafe fn from_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option { NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData, py)) } /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Returns an `Err` by calling `PyErr::fetch` /// if `ptr` is null. /// /// Prefer to use [`Bound::from_borrowed_ptr_or_err`], as that avoids the major safety risk /// of needing to precisely define the lifetime `'a` for which the borrow is valid. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it is the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. #[inline] pub unsafe fn from_ptr_or_err(py: Python<'py>, ptr: *mut ffi::PyObject) -> PyResult { NonNull::new(ptr).map_or_else( || Err(PyErr::fetch(py)), |ptr| Ok(Self(ptr, PhantomData, py)), ) } /// # Safety /// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it's the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. #[inline] pub(crate) unsafe fn from_ptr_unchecked(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { Self(unsafe { NonNull::new_unchecked(ptr) }, PhantomData, py) } #[inline] pub(crate) fn downcast(self) -> Result, DowncastError<'a, 'py>> where T: PyTypeCheck, { if T::type_check(&self) { // Safety: type_check is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_unchecked() }) } else { Err(DowncastError::new_from_borrowed(self, T::NAME)) } } /// Converts this `PyAny` to a concrete Python type without checking validity. /// /// # Safety /// Callers must ensure that the type is valid or risk type confusion. #[inline] pub(crate) unsafe fn downcast_unchecked(self) -> Borrowed<'a, 'py, T> { Borrowed(self.0, PhantomData, self.2) } } impl<'a, 'py, T> From<&'a Bound<'py, T>> for Borrowed<'a, 'py, T> { /// Create borrow on a Bound #[inline] fn from(instance: &'a Bound<'py, T>) -> Self { instance.as_borrowed() } } impl AsRef> for Borrowed<'_, '_, T> { #[inline] fn as_ref(&self) -> &Py { self.as_any().as_unbound() } } impl std::fmt::Debug for Borrowed<'_, '_, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Bound::fmt(self, f) } } impl<'py, T> Deref for Borrowed<'_, 'py, T> { type Target = Bound<'py, T>; #[inline] fn deref(&self) -> &Bound<'py, T> { // safety: Bound has the same layout as NonNull unsafe { &*ptr_from_ref(&self.0).cast() } } } impl Clone for Borrowed<'_, '_, T> { #[inline] fn clone(&self) -> Self { *self } } impl Copy for Borrowed<'_, '_, T> {} impl<'a, 'py, T> BoundObject<'py, T> for Borrowed<'a, 'py, T> { type Any = Borrowed<'a, 'py, PyAny>; fn as_borrowed(&self) -> Borrowed<'a, 'py, T> { *self } fn into_bound(self) -> Bound<'py, T> { (*self).to_owned() } fn into_any(self) -> Self::Any { self.to_any() } fn into_ptr(self) -> *mut ffi::PyObject { (*self).to_owned().into_ptr() } fn as_ptr(&self) -> *mut ffi::PyObject { (*self).as_ptr() } fn unbind(self) -> Py { (*self).to_owned().unbind() } } /// A GIL-independent reference to an object allocated on the Python heap. /// /// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it. /// Instead, call one of its methods to access the inner object: /// - [`Py::bind`] or [`Py::into_bound`], to borrow a GIL-bound reference to the contained object. /// - [`Py::borrow`], [`Py::try_borrow`], [`Py::borrow_mut`], or [`Py::try_borrow_mut`], /// /// to get a (mutable) reference to a contained pyclass, using a scheme similar to std's [`RefCell`]. /// See the #[doc = concat!("[guide entry](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#bound-and-interior-mutability)")] /// for more information. /// - You can call methods directly on `Py` with [`Py::call`], [`Py::call_method`] and friends. /// /// These require passing in the [`Python<'py>`](crate::Python) token but are otherwise similar to the corresponding /// methods on [`PyAny`]. /// /// # Example: Storing Python objects in `#[pyclass]` structs /// /// Usually `Bound<'py, T>` is recommended for interacting with Python objects as its lifetime `'py` /// is an association to the GIL and that enables many operations to be done as efficiently as possible. /// /// However, `#[pyclass]` structs cannot carry a lifetime, so `Py` is the only way to store /// a Python object in a `#[pyclass]` struct. /// /// For example, this won't compile: /// /// ```compile_fail /// # use pyo3::prelude::*; /// # use pyo3::types::PyDict; /// # /// #[pyclass] /// struct Foo<'py> { /// inner: Bound<'py, PyDict>, /// } /// /// impl Foo { /// fn new() -> Foo { /// let foo = Python::with_gil(|py| { /// // `py` will only last for this scope. /// /// // `Bound<'py, PyDict>` inherits the GIL lifetime from `py` and /// // so won't be able to outlive this closure. /// let dict: Bound<'_, PyDict> = PyDict::new(py); /// /// // because `Foo` contains `dict` its lifetime /// // is now also tied to `py`. /// Foo { inner: dict } /// }); /// // Foo is no longer valid. /// // Returning it from this function is a 💥 compiler error 💥 /// foo /// } /// } /// ``` /// /// [`Py`]`` can be used to get around this by converting `dict` into a GIL-independent reference: /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// #[pyclass] /// struct Foo { /// inner: Py, /// } /// /// #[pymethods] /// impl Foo { /// #[new] /// fn __new__() -> Foo { /// Python::with_gil(|py| { /// let dict: Py = PyDict::new(py).unbind(); /// Foo { inner: dict } /// }) /// } /// } /// # /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| { /// # let m = pyo3::types::PyModule::new(py, "test")?; /// # m.add_class::()?; /// # /// # let foo: Bound<'_, Foo> = m.getattr("Foo")?.call0()?.downcast_into()?; /// # let dict = &foo.borrow().inner; /// # let dict: &Bound<'_, PyDict> = dict.bind(py); /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// This can also be done with other pyclasses: /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Bar {/* ... */} /// /// #[pyclass] /// struct Foo { /// inner: Py, /// } /// /// #[pymethods] /// impl Foo { /// #[new] /// fn __new__() -> PyResult { /// Python::with_gil(|py| { /// let bar: Py = Py::new(py, Bar {})?; /// Ok(Foo { inner: bar }) /// }) /// } /// } /// # /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| { /// # let m = pyo3::types::PyModule::new(py, "test")?; /// # m.add_class::()?; /// # /// # let foo: Bound<'_, Foo> = m.getattr("Foo")?.call0()?.downcast_into()?; /// # let bar = &foo.borrow().inner; /// # let bar: &Bar = &*bar.borrow(py); /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// # Example: Shared ownership of Python objects /// /// `Py` can be used to share ownership of a Python object, similar to std's [`Rc`]``. /// As with [`Rc`]``, cloning it increases its reference count rather than duplicating /// the underlying object. /// /// This can be done using either [`Py::clone_ref`] or [`Py`]``'s [`Clone`] trait implementation. /// [`Py::clone_ref`] will be faster if you happen to be already holding the GIL. /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// # fn main() { /// Python::with_gil(|py| { /// let first: Py = PyDict::new(py).unbind(); /// /// // All of these are valid syntax /// let second = Py::clone_ref(&first, py); /// let third = first.clone_ref(py); /// #[cfg(feature = "py-clone")] /// let fourth = Py::clone(&first); /// #[cfg(feature = "py-clone")] /// let fifth = first.clone(); /// /// // Disposing of our original `Py` just decrements the reference count. /// drop(first); /// /// // They all point to the same object /// assert!(second.is(&third)); /// #[cfg(feature = "py-clone")] /// assert!(fourth.is(&fifth)); /// #[cfg(feature = "py-clone")] /// assert!(second.is(&fourth)); /// }); /// # } /// ``` /// /// # Preventing reference cycles /// /// It is easy to accidentally create reference cycles using [`Py`]``. /// The Python interpreter can break these reference cycles within pyclasses if they /// [integrate with the garbage collector][gc]. If your pyclass contains other Python /// objects you should implement it to avoid leaking memory. /// /// # A note on Python reference counts /// /// Dropping a [`Py`]`` will eventually decrease Python's reference count /// of the pointed-to variable, allowing Python's garbage collector to free /// the associated memory, but this may not happen immediately. This is /// because a [`Py`]`` can be dropped at any time, but the Python reference /// count can only be modified when the GIL is held. /// /// If a [`Py`]`` is dropped while its thread happens to be holding the /// GIL then the Python reference count will be decreased immediately. /// Otherwise, the reference count will be decreased the next time the GIL is /// reacquired. /// /// If you happen to be already holding the GIL, [`Py::drop_ref`] will decrease /// the Python reference count immediately and will execute slightly faster than /// relying on implicit [`Drop`]s. /// /// # A note on `Send` and `Sync` /// /// Accessing this object is thread-safe, since any access to its API requires a [`Python<'py>`](crate::Python) token. /// As you can only get this by acquiring the GIL, `Py<...>` implements [`Send`] and [`Sync`]. /// /// [`Rc`]: std::rc::Rc /// [`RefCell`]: std::cell::RefCell /// [gc]: https://pyo3.rs/main/class/protocols.html#garbage-collector-integration #[repr(transparent)] pub struct Py(NonNull, PhantomData); // The inner value is only accessed through ways that require proving the gil is held #[cfg(feature = "nightly")] unsafe impl crate::marker::Ungil for Py {} unsafe impl Send for Py {} unsafe impl Sync for Py {} impl Py where T: PyClass, { /// Creates a new instance `Py` of a `#[pyclass]` on the Python heap. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Foo {/* fields omitted */} /// /// # fn main() -> PyResult<()> { /// let foo = Python::with_gil(|py| -> PyResult<_> { /// let foo: Py = Py::new(py, Foo {})?; /// Ok(foo) /// })?; /// # Python::with_gil(move |_py| drop(foo)); /// # Ok(()) /// # } /// ``` pub fn new(py: Python<'_>, value: impl Into>) -> PyResult> { Bound::new(py, value).map(Bound::unbind) } } impl Py { /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { self.0.as_ptr() } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(self) -> *mut ffi::PyObject { ManuallyDrop::new(self).0.as_ptr() } /// Helper to cast to `Py`. #[inline] pub fn as_any(&self) -> &Py { // Safety: all Py have the same memory layout, and all Py are valid // Py, so pointer casting is valid. unsafe { &*ptr_from_ref(self).cast::>() } } /// Helper to cast to `Py`, transferring ownership. #[inline] pub fn into_any(self) -> Py { // Safety: all Py are valid Py unsafe { Py::from_non_null(ManuallyDrop::new(self).0) } } } impl Py where T: PyClass, { /// Immutably borrows the value `T`. /// /// This borrow lasts while the returned [`PyRef`] exists. /// Multiple immutable borrows can be taken out at the same time. /// /// For frozen classes, the simpler [`get`][Self::get] is available. /// /// Equivalent to `self.bind(py).borrow()` - see [`Bound::borrow`]. /// /// # Examples /// /// ```rust /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct Foo { /// inner: u8, /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let foo: Py = Py::new(py, Foo { inner: 73 })?; /// let inner: &u8 = &foo.borrow(py).inner; /// /// assert_eq!(*inner, 73); /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Panics /// /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use /// [`try_borrow`](#method.try_borrow). #[inline] #[track_caller] pub fn borrow<'py>(&'py self, py: Python<'py>) -> PyRef<'py, T> { self.bind(py).borrow() } /// Mutably borrows the value `T`. /// /// This borrow lasts while the returned [`PyRefMut`] exists. /// /// Equivalent to `self.bind(py).borrow_mut()` - see [`Bound::borrow_mut`]. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct Foo { /// inner: u8, /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let foo: Py = Py::new(py, Foo { inner: 73 })?; /// foo.borrow_mut(py).inner = 35; /// /// assert_eq!(foo.borrow(py).inner, 35); /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Panics /// Panics if the value is currently borrowed. For a non-panicking variant, use /// [`try_borrow_mut`](#method.try_borrow_mut). #[inline] #[track_caller] pub fn borrow_mut<'py>(&'py self, py: Python<'py>) -> PyRefMut<'py, T> where T: PyClass, { self.bind(py).borrow_mut() } /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed. /// /// The borrow lasts while the returned [`PyRef`] exists. /// /// This is the non-panicking variant of [`borrow`](#method.borrow). /// /// For frozen classes, the simpler [`get`][Self::get] is available. /// /// Equivalent to `self.bind(py).try_borrow()` - see [`Bound::try_borrow`]. #[inline] pub fn try_borrow<'py>(&'py self, py: Python<'py>) -> Result, PyBorrowError> { self.bind(py).try_borrow() } /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed. /// /// The borrow lasts while the returned [`PyRefMut`] exists. /// /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). /// /// Equivalent to `self.bind(py).try_borrow_mut()` - see [`Bound::try_borrow_mut`]. #[inline] pub fn try_borrow_mut<'py>( &'py self, py: Python<'py>, ) -> Result, PyBorrowMutError> where T: PyClass, { self.bind(py).try_borrow_mut() } /// Provide an immutable borrow of the value `T` without acquiring the GIL. /// /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`]. /// /// # Examples /// /// ``` /// use std::sync::atomic::{AtomicUsize, Ordering}; /// # use pyo3::prelude::*; /// /// #[pyclass(frozen)] /// struct FrozenCounter { /// value: AtomicUsize, /// } /// /// let cell = Python::with_gil(|py| { /// let counter = FrozenCounter { value: AtomicUsize::new(0) }; /// /// Py::new(py, counter).unwrap() /// }); /// /// cell.get().value.fetch_add(1, Ordering::Relaxed); /// # Python::with_gil(move |_py| drop(cell)); /// ``` #[inline] pub fn get(&self) -> &T where T: PyClass + Sync, { // Safety: The class itself is frozen and `Sync` unsafe { &*self.get_class_object().get_ptr() } } /// Get a view on the underlying `PyClass` contents. #[inline] pub(crate) fn get_class_object(&self) -> &PyClassObject { let class_object = self.as_ptr().cast::>(); // Safety: Bound is known to contain an object which is laid out in memory as a // PyClassObject. unsafe { &*class_object } } } impl Py { /// Attaches this `Py` to the given Python context, allowing access to further Python APIs. #[inline] pub fn bind<'py>(&self, _py: Python<'py>) -> &Bound<'py, T> { // Safety: `Bound` has the same layout as `Py` unsafe { &*ptr_from_ref(self).cast() } } /// Same as `bind` but takes ownership of `self`. #[inline] pub fn into_bound(self, py: Python<'_>) -> Bound<'_, T> { Bound(py, ManuallyDrop::new(self)) } /// Same as `bind` but produces a `Borrowed` instead of a `Bound`. #[inline] pub fn bind_borrowed<'a, 'py>(&'a self, py: Python<'py>) -> Borrowed<'a, 'py, T> { Borrowed(self.0, PhantomData, py) } /// Returns whether `self` and `other` point to the same object. To compare /// the equality of two objects (the `==` operator), use [`eq`](PyAnyMethods::eq). /// /// This is equivalent to the Python expression `self is other`. #[inline] pub fn is>>(&self, o: U) -> bool { ptr::eq(self.as_ptr(), o.as_ref().as_ptr()) } /// Gets the reference count of the `ffi::PyObject` pointer. #[inline] pub fn get_refcnt(&self, _py: Python<'_>) -> isize { unsafe { ffi::Py_REFCNT(self.0.as_ptr()) } } /// Makes a clone of `self`. /// /// This creates another pointer to the same object, increasing its reference count. /// /// You should prefer using this method over [`Clone`] if you happen to be holding the GIL already. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// # fn main() { /// Python::with_gil(|py| { /// let first: Py = PyDict::new(py).unbind(); /// let second = Py::clone_ref(&first, py); /// /// // Both point to the same object /// assert!(first.is(&second)); /// }); /// # } /// ``` #[inline] pub fn clone_ref(&self, _py: Python<'_>) -> Py { unsafe { ffi::Py_INCREF(self.as_ptr()); Self::from_non_null(self.0) } } /// Drops `self` and immediately decreases its reference count. /// /// This method is a micro-optimisation over [`Drop`] if you happen to be holding the GIL /// already. /// /// Note that if you are using [`Bound`], you do not need to use [`Self::drop_ref`] since /// [`Bound`] guarantees that the GIL is held. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// # fn main() { /// Python::with_gil(|py| { /// let object: Py = PyDict::new(py).unbind(); /// /// // some usage of object /// /// object.drop_ref(py); /// }); /// # } /// ``` #[inline] pub fn drop_ref(self, py: Python<'_>) { let _ = self.into_bound(py); } /// Returns whether the object is considered to be None. /// /// This is equivalent to the Python expression `self is None`. pub fn is_none(&self, _py: Python<'_>) -> bool { unsafe { ptr::eq(ffi::Py_None(), self.as_ptr()) } } /// Returns whether the object is considered to be true. /// /// This applies truth value testing equivalent to the Python expression `bool(self)`. pub fn is_truthy(&self, py: Python<'_>) -> PyResult { let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; err::error_on_minusone(py, v)?; Ok(v != 0) } /// Extracts some type from the Python object. /// /// This is a wrapper function around `FromPyObject::extract()`. pub fn extract<'a, 'py, D>(&'a self, py: Python<'py>) -> PyResult where D: crate::conversion::FromPyObjectBound<'a, 'py>, // TODO it might be possible to relax this bound in future, to allow // e.g. `.extract::<&str>(py)` where `py` is short-lived. 'py: 'a, { self.bind(py).as_any().extract() } /// Retrieves an attribute value. /// /// This is equivalent to the Python expression `self.attr_name`. /// /// If calling this method becomes performance-critical, the [`intern!`](crate::intern) macro /// can be used to intern `attr_name`, thereby avoiding repeated temporary allocations of /// Python strings. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn version(sys: Py, py: Python<'_>) -> PyResult { /// sys.getattr(py, intern!(py, "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import("sys").unwrap().unbind(); /// # version(sys, py).unwrap(); /// # }); /// ``` pub fn getattr<'py, N>(&self, py: Python<'py>, attr_name: N) -> PyResult where N: IntoPyObject<'py, Target = PyString>, { self.bind(py).as_any().getattr(attr_name).map(Bound::unbind) } /// Sets an attribute value. /// /// This is equivalent to the Python expression `self.attr_name = value`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) /// macro can be used to intern `attr_name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{intern, pyfunction, types::PyModule, IntoPyObjectExt, PyObject, Python, PyResult}; /// # /// #[pyfunction] /// fn set_answer(ob: PyObject, py: Python<'_>) -> PyResult<()> { /// ob.setattr(py, intern!(py, "answer"), 42) /// } /// # /// # Python::with_gil(|py| { /// # let ob = PyModule::new(py, "empty").unwrap().into_py_any(py).unwrap(); /// # set_answer(ob, py).unwrap(); /// # }); /// ``` pub fn setattr<'py, N, V>(&self, py: Python<'py>, attr_name: N, value: V) -> PyResult<()> where N: IntoPyObject<'py, Target = PyString>, V: IntoPyObject<'py>, { self.bind(py).as_any().setattr(attr_name, value) } /// Calls the object. /// /// This is equivalent to the Python expression `self(*args, **kwargs)`. pub fn call<'py, A>( &self, py: Python<'py>, args: A, kwargs: Option<&Bound<'py, PyDict>>, ) -> PyResult where A: IntoPyObject<'py, Target = PyTuple>, { self.bind(py) .as_any() .call( // FIXME(icxolu): remove explicit args conversion args.into_pyobject(py).map_err(Into::into)?.into_bound(), kwargs, ) .map(Bound::unbind) } /// Calls the object with only positional arguments. /// /// This is equivalent to the Python expression `self(*args)`. pub fn call1<'py, N>(&self, py: Python<'py>, args: N) -> PyResult where N: IntoPyObject<'py, Target = PyTuple>, { self.bind(py) .as_any() // FIXME(icxolu): remove explicit args conversion .call1(args.into_pyobject(py).map_err(Into::into)?.into_bound()) .map(Bound::unbind) } /// Calls the object without arguments. /// /// This is equivalent to the Python expression `self()`. pub fn call0(&self, py: Python<'_>) -> PyResult { self.bind(py).as_any().call0().map(Bound::unbind) } /// Calls a method on the object. /// /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) /// macro can be used to intern `name`. pub fn call_method<'py, N, A>( &self, py: Python<'py>, name: N, args: A, kwargs: Option<&Bound<'py, PyDict>>, ) -> PyResult where N: IntoPyObject<'py, Target = PyString>, A: IntoPyObject<'py, Target = PyTuple>, { self.bind(py) .as_any() .call_method( name, // FIXME(icxolu): remove explicit args conversion args.into_pyobject(py).map_err(Into::into)?.into_bound(), kwargs, ) .map(Bound::unbind) } /// Calls a method on the object with only positional arguments. /// /// This is equivalent to the Python expression `self.name(*args)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) /// macro can be used to intern `name`. pub fn call_method1<'py, N, A>(&self, py: Python<'py>, name: N, args: A) -> PyResult where N: IntoPyObject<'py, Target = PyString>, A: IntoPyObject<'py, Target = PyTuple>, { self.bind(py) .as_any() .call_method1( name, // FIXME(icxolu): remove explicit args conversion args.into_pyobject(py).map_err(Into::into)?.into_bound(), ) .map(Bound::unbind) } /// Calls a method on the object with no arguments. /// /// This is equivalent to the Python expression `self.name()`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) /// macro can be used to intern `name`. pub fn call_method0<'py, N>(&self, py: Python<'py>, name: N) -> PyResult where N: IntoPyObject<'py, Target = PyString>, { self.bind(py).as_any().call_method0(name).map(Bound::unbind) } /// Create a `Py` instance by taking ownership of the given FFI pointer. /// /// # Safety /// `ptr` must be a pointer to a Python object of type T. /// /// Callers must own the object referred to by `ptr`, as this function /// implicitly takes ownership of that object. /// /// # Panics /// Panics if `ptr` is null. #[inline] #[track_caller] pub unsafe fn from_owned_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py { match NonNull::new(ptr) { Some(nonnull_ptr) => Py(nonnull_ptr, PhantomData), None => crate::err::panic_after_error(py), } } /// Create a `Py` instance by taking ownership of the given FFI pointer. /// /// If `ptr` is null then the current Python exception is fetched as a [`PyErr`]. /// /// # Safety /// If non-null, `ptr` must be a pointer to a Python object of type T. #[inline] pub unsafe fn from_owned_ptr_or_err( py: Python<'_>, ptr: *mut ffi::PyObject, ) -> PyResult> { match NonNull::new(ptr) { Some(nonnull_ptr) => Ok(Py(nonnull_ptr, PhantomData)), None => Err(PyErr::fetch(py)), } } /// Create a `Py` instance by taking ownership of the given FFI pointer. /// /// If `ptr` is null then `None` is returned. /// /// # Safety /// If non-null, `ptr` must be a pointer to a Python object of type T. #[inline] pub unsafe fn from_owned_ptr_or_opt(_py: Python<'_>, ptr: *mut ffi::PyObject) -> Option { NonNull::new(ptr).map(|nonnull_ptr| Py(nonnull_ptr, PhantomData)) } /// Constructs a new `Py` instance by taking ownership of the given FFI pointer. /// /// # Safety /// /// - `ptr` must be a non-null pointer to a Python object or type `T`. pub(crate) unsafe fn from_owned_ptr_unchecked(ptr: *mut ffi::PyObject) -> Self { Py(unsafe { NonNull::new_unchecked(ptr) }, PhantomData) } /// Create a `Py` instance by creating a new reference from the given FFI pointer. /// /// # Safety /// `ptr` must be a pointer to a Python object of type T. /// /// # Panics /// Panics if `ptr` is null. #[inline] #[track_caller] pub unsafe fn from_borrowed_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py { match unsafe { Self::from_borrowed_ptr_or_opt(py, ptr) } { Some(slf) => slf, None => crate::err::panic_after_error(py), } } /// Create a `Py` instance by creating a new reference from the given FFI pointer. /// /// If `ptr` is null then the current Python exception is fetched as a `PyErr`. /// /// # Safety /// `ptr` must be a pointer to a Python object of type T. #[inline] pub unsafe fn from_borrowed_ptr_or_err( py: Python<'_>, ptr: *mut ffi::PyObject, ) -> PyResult { unsafe { Self::from_borrowed_ptr_or_opt(py, ptr).ok_or_else(|| PyErr::fetch(py)) } } /// Create a `Py` instance by creating a new reference from the given FFI pointer. /// /// If `ptr` is null then `None` is returned. /// /// # Safety /// `ptr` must be a pointer to a Python object of type T. #[inline] pub unsafe fn from_borrowed_ptr_or_opt( _py: Python<'_>, ptr: *mut ffi::PyObject, ) -> Option { unsafe { NonNull::new(ptr).map(|nonnull_ptr| { ffi::Py_INCREF(ptr); Py(nonnull_ptr, PhantomData) }) } } /// For internal conversions. /// /// # Safety /// `ptr` must point to a Python object of type T. unsafe fn from_non_null(ptr: NonNull) -> Self { Self(ptr, PhantomData) } } impl AsRef> for Py { #[inline] fn as_ref(&self) -> &Py { self.as_any() } } impl std::convert::From> for PyObject where T: DerefToPyAny, { #[inline] fn from(other: Py) -> Self { other.into_any() } } impl std::convert::From> for PyObject where T: DerefToPyAny, { #[inline] fn from(other: Bound<'_, T>) -> Self { other.into_any().unbind() } } impl std::convert::From> for Py { #[inline] fn from(other: Bound<'_, T>) -> Self { other.unbind() } } impl std::convert::From> for Py { fn from(value: Borrowed<'_, '_, T>) -> Self { value.unbind() } } impl<'a, T> std::convert::From> for Py where T: PyClass, { fn from(pyref: PyRef<'a, T>) -> Self { unsafe { Py::from_borrowed_ptr(pyref.py(), pyref.as_ptr()) } } } impl<'a, T> std::convert::From> for Py where T: PyClass, { fn from(pyref: PyRefMut<'a, T>) -> Self { unsafe { Py::from_borrowed_ptr(pyref.py(), pyref.as_ptr()) } } } /// If the GIL is held this increments `self`'s reference count. /// Otherwise, it will panic. /// /// Only available if the `py-clone` feature is enabled. #[cfg(feature = "py-clone")] impl Clone for Py { #[track_caller] fn clone(&self) -> Self { unsafe { gil::register_incref(self.0); } Self(self.0, PhantomData) } } /// Dropping a `Py` instance decrements the reference count /// on the object by one if the GIL is held. /// /// Otherwise and by default, this registers the underlying pointer to have its reference count /// decremented the next time PyO3 acquires the GIL. /// /// However, if the `pyo3_disable_reference_pool` conditional compilation flag /// is enabled, it will abort the process. impl Drop for Py { #[track_caller] fn drop(&mut self) { unsafe { gil::register_decref(self.0); } } } impl FromPyObject<'_> for Py where T: PyTypeCheck, { /// Extracts `Self` from the source `PyObject`. fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { ob.extract::>().map(Bound::unbind) } } impl<'py, T> FromPyObject<'py> for Bound<'py, T> where T: PyTypeCheck, { /// Extracts `Self` from the source `PyObject`. fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { ob.downcast().cloned().map_err(Into::into) } } impl std::fmt::Display for Py where T: PyTypeInfo, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Python::with_gil(|py| std::fmt::Display::fmt(self.bind(py), f)) } } impl std::fmt::Debug for Py { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Py").field(&self.0.as_ptr()).finish() } } /// A commonly-used alias for `Py`. /// /// This is an owned reference a Python object without any type information. This value can also be /// safely sent between threads. /// /// See the documentation for [`Py`](struct.Py.html). pub type PyObject = Py; impl PyObject { /// Downcast this `PyObject` to a concrete Python type or pyclass. /// /// Note that you can often avoid downcasting yourself by just specifying /// the desired type in function or method signatures. /// However, manual downcasting is sometimes necessary. /// /// For extracting a Rust-only type, see [`Py::extract`](struct.Py.html#method.extract). /// /// # Example: Downcasting to a specific Python object /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { /// let any: PyObject = PyDict::new(py).into(); /// /// assert!(any.downcast_bound::(py).is_ok()); /// assert!(any.downcast_bound::(py).is_err()); /// }); /// ``` /// /// # Example: Getting a reference to a pyclass /// /// This is useful if you want to mutate a `PyObject` that /// might actually be a pyclass. /// /// ```rust /// # fn main() -> Result<(), pyo3::PyErr> { /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Class { /// i: i32, /// } /// /// Python::with_gil(|py| { /// let class: PyObject = Py::new(py, Class { i: 0 })?.into_any(); /// /// let class_bound = class.downcast_bound::(py)?; /// /// class_bound.borrow_mut().i += 1; /// /// // Alternatively you can get a `PyRefMut` directly /// let class_ref: PyRefMut<'_, Class> = class.extract(py)?; /// assert_eq!(class_ref.i, 1); /// Ok(()) /// }) /// # } /// ``` #[inline] pub fn downcast_bound<'py, T>( &self, py: Python<'py>, ) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeCheck, { self.bind(py).downcast() } /// Casts the PyObject to a concrete Python object type without checking validity. /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. #[inline] pub unsafe fn downcast_bound_unchecked<'py, T>(&self, py: Python<'py>) -> &Bound<'py, T> { unsafe { self.bind(py).downcast_unchecked() } } } #[cfg(test)] mod tests { use super::{Bound, IntoPyObject, Py, PyObject}; use crate::tests::common::generate_unique_module_name; use crate::types::{dict::IntoPyDict, PyAnyMethods, PyCapsule, PyDict, PyString}; use crate::{ffi, Borrowed, PyAny, PyResult, Python}; use pyo3_ffi::c_str; use std::ffi::CStr; #[test] fn test_call() { Python::with_gil(|py| { let obj = py.get_type::().into_pyobject(py).unwrap(); let assert_repr = |obj: Bound<'_, PyAny>, expected: &str| { assert_eq!(obj.repr().unwrap(), expected); }; assert_repr(obj.call0().unwrap(), "{}"); assert_repr(obj.call1(()).unwrap(), "{}"); assert_repr(obj.call((), None).unwrap(), "{}"); assert_repr(obj.call1(((('x', 1),),)).unwrap(), "{'x': 1}"); assert_repr( obj.call((), Some(&[('x', 1)].into_py_dict(py).unwrap())) .unwrap(), "{'x': 1}", ); }) } #[test] fn test_call_tuple_ref() { let assert_repr = |obj: &Bound<'_, PyAny>, expected: &str| { use crate::prelude::PyStringMethods; assert_eq!( obj.repr() .unwrap() .to_cow() .unwrap() .trim_matches(|c| c == '{' || c == '}'), expected.trim_matches(|c| c == ',' || c == ' ') ); }; macro_rules! tuple { ($py:ident, $($key: literal => $value: literal),+) => { let ty_obj = $py.get_type::().into_pyobject($py).unwrap(); assert!(ty_obj.call1(&(($(($key),)+),)).is_err()); let obj = ty_obj.call1(&(($(($key, i32::from($value)),)+),)).unwrap(); assert_repr(&obj, concat!($("'", $key, "'", ": ", stringify!($value), ", ",)+)); assert!(obj.call_method1("update", &(($(($key),)+),)).is_err()); obj.call_method1("update", &(($((i32::from($value), $key),)+),)).unwrap(); assert_repr(&obj, concat!( concat!($("'", $key, "'", ": ", stringify!($value), ", ",)+), concat!($(stringify!($value), ": ", "'", $key, "'", ", ",)+) )); }; } Python::with_gil(|py| { tuple!(py, "a" => 1); tuple!(py, "a" => 1, "b" => 2); tuple!(py, "a" => 1, "b" => 2, "c" => 3); tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4); tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5); tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6); tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7); tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8); tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "i" => 9); tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "i" => 9, "j" => 10, "k" => 11); tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "i" => 9, "j" => 10, "k" => 11, "l" => 12); }) } #[test] fn test_call_for_non_existing_method() { Python::with_gil(|py| { let obj: PyObject = PyDict::new(py).into(); assert!(obj.call_method0(py, "asdf").is_err()); assert!(obj .call_method(py, "nonexistent_method", (1,), None) .is_err()); assert!(obj.call_method0(py, "nonexistent_method").is_err()); assert!(obj.call_method1(py, "nonexistent_method", (1,)).is_err()); }); } #[test] fn py_from_dict() { let dict: Py = Python::with_gil(|py| { let native = PyDict::new(py); Py::from(native) }); Python::with_gil(move |py| { assert_eq!(dict.get_refcnt(py), 1); }); } #[test] fn pyobject_from_py() { Python::with_gil(|py| { let dict: Py = PyDict::new(py).unbind(); let cnt = dict.get_refcnt(py); let p: PyObject = dict.into(); assert_eq!(p.get_refcnt(py), cnt); }); } #[test] fn attr() -> PyResult<()> { use crate::types::PyModule; Python::with_gil(|py| { const CODE: &CStr = c_str!( r#" class A: pass a = A() "# ); let module = PyModule::from_code(py, CODE, c_str!(""), &generate_unique_module_name(""))?; let instance: Py = module.getattr("a")?.into(); instance.getattr(py, "foo").unwrap_err(); instance.setattr(py, "foo", "bar")?; assert!(instance .getattr(py, "foo")? .bind(py) .eq(PyString::new(py, "bar"))?); instance.getattr(py, "foo")?; Ok(()) }) } #[test] fn pystring_attr() -> PyResult<()> { use crate::types::PyModule; Python::with_gil(|py| { const CODE: &CStr = c_str!( r#" class A: pass a = A() "# ); let module = PyModule::from_code(py, CODE, c_str!(""), &generate_unique_module_name(""))?; let instance: Py = module.getattr("a")?.into(); let foo = crate::intern!(py, "foo"); let bar = crate::intern!(py, "bar"); instance.getattr(py, foo).unwrap_err(); instance.setattr(py, foo, bar)?; assert!(instance.getattr(py, foo)?.bind(py).eq(bar)?); Ok(()) }) } #[test] fn invalid_attr() -> PyResult<()> { Python::with_gil(|py| { let instance: Py = py.eval(ffi::c_str!("object()"), None, None)?.into(); instance.getattr(py, "foo").unwrap_err(); // Cannot assign arbitrary attributes to `object` instance.setattr(py, "foo", "bar").unwrap_err(); Ok(()) }) } #[test] fn test_py2_from_py_object() { Python::with_gil(|py| { let instance = py.eval(ffi::c_str!("object()"), None, None).unwrap(); let ptr = instance.as_ptr(); let instance: Bound<'_, PyAny> = instance.extract().unwrap(); assert_eq!(instance.as_ptr(), ptr); }) } #[test] fn test_py2_into_py_object() { Python::with_gil(|py| { let instance = py.eval(ffi::c_str!("object()"), None, None).unwrap(); let ptr = instance.as_ptr(); let instance: PyObject = instance.clone().unbind(); assert_eq!(instance.as_ptr(), ptr); }) } #[test] fn test_debug_fmt() { Python::with_gil(|py| { let obj = "hello world".into_pyobject(py).unwrap(); assert_eq!(format!("{obj:?}"), "'hello world'"); }); } #[test] fn test_display_fmt() { Python::with_gil(|py| { let obj = "hello world".into_pyobject(py).unwrap(); assert_eq!(format!("{obj}"), "hello world"); }); } #[test] fn test_bound_as_any() { Python::with_gil(|py| { let obj = PyString::new(py, "hello world"); let any = obj.as_any(); assert_eq!(any.as_ptr(), obj.as_ptr()); }); } #[test] fn test_bound_into_any() { Python::with_gil(|py| { let obj = PyString::new(py, "hello world"); let any = obj.clone().into_any(); assert_eq!(any.as_ptr(), obj.as_ptr()); }); } #[test] fn test_bound_py_conversions() { Python::with_gil(|py| { let obj: Bound<'_, PyString> = PyString::new(py, "hello world"); let obj_unbound: &Py = obj.as_unbound(); let _: &Bound<'_, PyString> = obj_unbound.bind(py); let obj_unbound: Py = obj.unbind(); let obj: Bound<'_, PyString> = obj_unbound.into_bound(py); assert_eq!(obj, "hello world"); }); } #[test] fn test_borrowed_identity() { Python::with_gil(|py| { let yes = true.into_pyobject(py).unwrap(); let no = false.into_pyobject(py).unwrap(); assert!(yes.is(yes)); assert!(!yes.is(no)); }); } #[test] fn bound_from_borrowed_ptr_constructors() { // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { fn check_drop<'py>( py: Python<'py>, method: impl FnOnce(*mut ffi::PyObject) -> Bound<'py, PyAny>, ) { let mut dropped = false; let capsule = PyCapsule::new_with_destructor( py, (&mut dropped) as *mut _ as usize, None, |ptr, _| unsafe { std::ptr::write(ptr as *mut bool, true) }, ) .unwrap(); let bound = method(capsule.as_ptr()); assert!(!dropped); // creating the bound should have increased the refcount drop(capsule); assert!(!dropped); // dropping the bound should now also decrease the refcount and free the object drop(bound); assert!(dropped); } check_drop(py, |ptr| unsafe { Bound::from_borrowed_ptr(py, ptr) }); check_drop(py, |ptr| unsafe { Bound::from_borrowed_ptr_or_opt(py, ptr).unwrap() }); check_drop(py, |ptr| unsafe { Bound::from_borrowed_ptr_or_err(py, ptr).unwrap() }); }) } #[test] fn borrowed_ptr_constructors() { // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { fn check_drop<'py>( py: Python<'py>, method: impl FnOnce(&*mut ffi::PyObject) -> Borrowed<'_, 'py, PyAny>, ) { let mut dropped = false; let capsule = PyCapsule::new_with_destructor( py, (&mut dropped) as *mut _ as usize, None, |ptr, _| unsafe { std::ptr::write(ptr as *mut bool, true) }, ) .unwrap(); let ptr = &capsule.as_ptr(); let _borrowed = method(ptr); assert!(!dropped); // creating the borrow should not have increased the refcount drop(capsule); assert!(dropped); } check_drop(py, |&ptr| unsafe { Borrowed::from_ptr(py, ptr) }); check_drop(py, |&ptr| unsafe { Borrowed::from_ptr_or_opt(py, ptr).unwrap() }); check_drop(py, |&ptr| unsafe { Borrowed::from_ptr_or_err(py, ptr).unwrap() }); }) } #[test] fn explicit_drop_ref() { Python::with_gil(|py| { let object: Py = PyDict::new(py).unbind(); let object2 = object.clone_ref(py); assert_eq!(object.as_ptr(), object2.as_ptr()); assert_eq!(object.get_refcnt(py), 2); object.drop_ref(py); assert_eq!(object2.get_refcnt(py), 1); object2.drop_ref(py); }); } #[cfg(feature = "macros")] mod using_macros { use super::*; #[crate::pyclass(crate = "crate")] struct SomeClass(i32); #[test] fn py_borrow_methods() { // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { let instance = Py::new(py, SomeClass(0)).unwrap(); assert_eq!(instance.borrow(py).0, 0); assert_eq!(instance.try_borrow(py).unwrap().0, 0); assert_eq!(instance.borrow_mut(py).0, 0); assert_eq!(instance.try_borrow_mut(py).unwrap().0, 0); instance.borrow_mut(py).0 = 123; assert_eq!(instance.borrow(py).0, 123); assert_eq!(instance.try_borrow(py).unwrap().0, 123); assert_eq!(instance.borrow_mut(py).0, 123); assert_eq!(instance.try_borrow_mut(py).unwrap().0, 123); }) } #[test] fn bound_borrow_methods() { // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { let instance = Bound::new(py, SomeClass(0)).unwrap(); assert_eq!(instance.borrow().0, 0); assert_eq!(instance.try_borrow().unwrap().0, 0); assert_eq!(instance.borrow_mut().0, 0); assert_eq!(instance.try_borrow_mut().unwrap().0, 0); instance.borrow_mut().0 = 123; assert_eq!(instance.borrow().0, 123); assert_eq!(instance.try_borrow().unwrap().0, 123); assert_eq!(instance.borrow_mut().0, 123); assert_eq!(instance.try_borrow_mut().unwrap().0, 123); }) } #[crate::pyclass(frozen, crate = "crate")] struct FrozenClass(i32); #[test] fn test_frozen_get() { Python::with_gil(|py| { for i in 0..10 { let instance = Py::new(py, FrozenClass(i)).unwrap(); assert_eq!(instance.get().0, i); assert_eq!(instance.bind(py).get().0, i); } }) } #[crate::pyclass(crate = "crate", subclass)] struct BaseClass; trait MyClassMethods<'py>: Sized { fn pyrepr_by_ref(&self) -> PyResult; fn pyrepr_by_val(self) -> PyResult { self.pyrepr_by_ref() } } impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> { fn pyrepr_by_ref(&self) -> PyResult { self.call_method0("__repr__")?.extract() } } #[crate::pyclass(crate = "crate", extends = BaseClass)] struct SubClass; #[test] fn test_as_super() { Python::with_gil(|py| { let obj = Bound::new(py, (SubClass, BaseClass)).unwrap(); let _: &Bound<'_, BaseClass> = obj.as_super(); let _: &Bound<'_, PyAny> = obj.as_super().as_super(); assert!(obj.as_super().pyrepr_by_ref().is_ok()); }) } #[test] fn test_into_super() { Python::with_gil(|py| { let obj = Bound::new(py, (SubClass, BaseClass)).unwrap(); let _: Bound<'_, BaseClass> = obj.clone().into_super(); let _: Bound<'_, PyAny> = obj.clone().into_super().into_super(); assert!(obj.into_super().pyrepr_by_val().is_ok()); }) } } } pyo3/src/coroutine.rs0000644000175000017500000001371615105742312014450 0ustar bdrungbdrung//! Python coroutine implementation, used notably when wrapping `async fn` //! with `#[pyfunction]`/`#[pymethods]`. use std::{ future::Future, panic, pin::Pin, sync::Arc, task::{Context, Poll, Waker}, }; use pyo3_macros::{pyclass, pymethods}; use crate::{ coroutine::{cancel::ThrowCallback, waker::AsyncioWaker}, exceptions::{PyAttributeError, PyRuntimeError, PyStopIteration}, panic::PanicException, types::{string::PyStringMethods, PyIterator, PyString}, Bound, IntoPyObject, IntoPyObjectExt, Py, PyAny, PyErr, PyObject, PyResult, Python, }; pub(crate) mod cancel; mod waker; pub use cancel::CancelHandle; const COROUTINE_REUSED_ERROR: &str = "cannot reuse already awaited coroutine"; /// Python coroutine wrapping a [`Future`]. #[pyclass(crate = "crate")] pub struct Coroutine { name: Option>, qualname_prefix: Option<&'static str>, throw_callback: Option, future: Option> + Send>>>, waker: Option>, } // Safety: `Coroutine` is allowed to be `Sync` even though the future is not, // because the future is polled with `&mut self` receiver unsafe impl Sync for Coroutine {} impl Coroutine { /// Wrap a future into a Python coroutine. /// /// Coroutine `send` polls the wrapped future, ignoring the value passed /// (should always be `None` anyway). /// /// `Coroutine `throw` drop the wrapped future and reraise the exception passed pub(crate) fn new<'py, F, T, E>( name: Option>, qualname_prefix: Option<&'static str>, throw_callback: Option, future: F, ) -> Self where F: Future> + Send + 'static, T: IntoPyObject<'py>, E: Into, { let wrap = async move { let obj = future.await.map_err(Into::into)?; // SAFETY: GIL is acquired when future is polled (see `Coroutine::poll`) obj.into_py_any(unsafe { Python::assume_gil_acquired() }) }; Self { name: name.map(Bound::unbind), qualname_prefix, throw_callback, future: Some(Box::pin(wrap)), waker: None, } } fn poll(&mut self, py: Python<'_>, throw: Option) -> PyResult { // raise if the coroutine has already been run to completion let future_rs = match self.future { Some(ref mut fut) => fut, None => return Err(PyRuntimeError::new_err(COROUTINE_REUSED_ERROR)), }; // reraise thrown exception it match (throw, &self.throw_callback) { (Some(exc), Some(cb)) => cb.throw(exc), (Some(exc), None) => { self.close(); return Err(PyErr::from_value(exc.into_bound(py))); } (None, _) => {} } // create a new waker, or try to reset it in place if let Some(waker) = self.waker.as_mut().and_then(Arc::get_mut) { waker.reset(); } else { self.waker = Some(Arc::new(AsyncioWaker::new())); } let waker = Waker::from(self.waker.clone().unwrap()); // poll the Rust future and forward its results if ready // polling is UnwindSafe because the future is dropped in case of panic let poll = || future_rs.as_mut().poll(&mut Context::from_waker(&waker)); match panic::catch_unwind(panic::AssertUnwindSafe(poll)) { Ok(Poll::Ready(res)) => { self.close(); return Err(PyStopIteration::new_err((res?,))); } Err(err) => { self.close(); return Err(PanicException::from_panic_payload(err)); } _ => {} } // otherwise, initialize the waker `asyncio.Future` if let Some(future) = self.waker.as_ref().unwrap().initialize_future(py)? { // `asyncio.Future` must be awaited; fortunately, it implements `__iter__ = __await__` // and will yield itself if its result has not been set in polling above if let Some(future) = PyIterator::from_object(future).unwrap().next() { // future has not been leaked into Python for now, and Rust code can only call // `set_result(None)` in `Wake` implementation, so it's safe to unwrap return Ok(future.unwrap().into()); } } // if waker has been waken during future polling, this is roughly equivalent to // `await asyncio.sleep(0)`, so just yield `None`. Ok(py.None()) } } #[pymethods(crate = "crate")] impl Coroutine { #[getter] fn __name__(&self, py: Python<'_>) -> PyResult> { match &self.name { Some(name) => Ok(name.clone_ref(py)), None => Err(PyAttributeError::new_err("__name__")), } } #[getter] fn __qualname__<'py>(&self, py: Python<'py>) -> PyResult> { match (&self.name, &self.qualname_prefix) { (Some(name), Some(prefix)) => Ok(PyString::new( py, &format!("{}.{}", prefix, name.bind(py).to_cow()?), )), (Some(name), None) => Ok(name.bind(py).clone()), (None, _) => Err(PyAttributeError::new_err("__qualname__")), } } fn send(&mut self, py: Python<'_>, _value: &Bound<'_, PyAny>) -> PyResult { self.poll(py, None) } fn throw(&mut self, py: Python<'_>, exc: PyObject) -> PyResult { self.poll(py, Some(exc)) } fn close(&mut self) { // the Rust future is dropped, and the field set to `None` // to indicate the coroutine has been run to completion drop(self.future.take()); } fn __await__(self_: Py) -> Py { self_ } fn __next__(&mut self, py: Python<'_>) -> PyResult { self.poll(py, None) } } pyo3/src/lib.rs0000644000175000017500000005665115105742312013214 0ustar bdrungbdrung#![warn(missing_docs)] #![cfg_attr( feature = "nightly", feature(auto_traits, negative_impls, try_trait_v2, iter_advance_by) )] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(not(cargo_toml_lints), warn(unsafe_op_in_unsafe_fn))] // necessary for MSRV 1.63 to build // Deny some lints in doctests. // Use `#[allow(...)]` locally to override. #![doc(test(attr( deny( rust_2018_idioms, unused_lifetimes, rust_2021_prelude_collisions, warnings ), allow( unused_variables, unused_assignments, unused_extern_crates, // FIXME https://github.com/rust-lang/rust/issues/121621#issuecomment-1965156376 unknown_lints, non_local_definitions, ) )))] //! Rust bindings to the Python interpreter. //! //! PyO3 can be used to write native Python modules or run Python code and modules from Rust. //! //! See [the guide] for a detailed introduction. //! //! # PyO3's object types //! //! PyO3 has several core types that you should familiarize yourself with: //! //! ## The `Python<'py>` object, and the `'py` lifetime //! //! Holding the [global interpreter lock] (GIL) is modeled with the [`Python<'py>`](Python) token. Many //! Python APIs require that the GIL is held, and PyO3 uses this token as proof that these APIs //! can be called safely. It can be explicitly acquired and is also implicitly acquired by PyO3 //! as it wraps Rust functions and structs into Python functions and objects. //! //! The [`Python<'py>`](Python) token's lifetime `'py` is common to many PyO3 APIs: //! - Types that also have the `'py` lifetime, such as the [`Bound<'py, T>`](Bound) smart pointer, are //! bound to the Python GIL and rely on this to offer their functionality. These types often //! have a [`.py()`](Bound::py) method to get the associated [`Python<'py>`](Python) token. //! - Functions which depend on the `'py` lifetime, such as [`PyList::new`](types::PyList::new), //! require a [`Python<'py>`](Python) token as an input. Sometimes the token is passed implicitly by //! taking a [`Bound<'py, T>`](Bound) or other type which is bound to the `'py` lifetime. //! - Traits which depend on the `'py` lifetime, such as [`FromPyObject<'py>`](FromPyObject), usually have //! inputs or outputs which depend on the lifetime. Adding the lifetime to the trait allows //! these inputs and outputs to express their binding to the GIL in the Rust type system. //! //! ## Python object smart pointers //! //! PyO3 has two core smart pointers to refer to Python objects, [`Py`](Py) and its GIL-bound //! form [`Bound<'py, T>`](Bound) which carries the `'py` lifetime. (There is also //! [`Borrowed<'a, 'py, T>`](instance::Borrowed), but it is used much more rarely). //! //! The type parameter `T` in these smart pointers can be filled by: //! - [`PyAny`], e.g. `Py` or `Bound<'py, PyAny>`, where the Python object type is not //! known. `Py` is so common it has a type alias [`PyObject`]. //! - Concrete Python types like [`PyList`](types::PyList) or [`PyTuple`](types::PyTuple). //! - Rust types which are exposed to Python using the [`#[pyclass]`](macro@pyclass) macro. //! //! See the [guide][types] for an explanation of the different Python object types. //! //! ## PyErr //! //! The vast majority of operations in this library will return [`PyResult<...>`](PyResult). //! This is an alias for the type `Result<..., PyErr>`. //! //! A `PyErr` represents a Python exception. A `PyErr` returned to Python code will be raised as a //! Python exception. Errors from `PyO3` itself are also exposed as Python exceptions. //! //! # Feature flags //! //! PyO3 uses [feature flags] to enable you to opt-in to additional functionality. For a detailed //! description, see the [Features chapter of the guide]. //! //! ## Default feature flags //! //! The following features are turned on by default: //! - `macros`: Enables various macros, including all the attribute macros. //! //! ## Optional feature flags //! //! The following features customize PyO3's behavior: //! //! - `abi3`: Restricts PyO3's API to a subset of the full Python API which is guaranteed by //! [PEP 384] to be forward-compatible with future Python versions. //! - `auto-initialize`: Changes [`Python::with_gil`] to automatically initialize the Python //! interpreter if needed. //! - `extension-module`: This will tell the linker to keep the Python symbols unresolved, so that //! your module can also be used with statically linked Python interpreters. Use this feature when //! building an extension module. //! - `multiple-pymethods`: Enables the use of multiple [`#[pymethods]`](macro@crate::pymethods) //! blocks per [`#[pyclass]`](macro@crate::pyclass). This adds a dependency on the [inventory] //! crate, which is not supported on all platforms. //! //! The following features enable interactions with other crates in the Rust ecosystem: //! - [`anyhow`]: Enables a conversion from [anyhow]’s [`Error`][anyhow_error] type to [`PyErr`]. //! - [`chrono`]: Enables a conversion from [chrono]'s structures to the equivalent Python ones. //! - [`chrono-tz`]: Enables a conversion from [chrono-tz]'s `Tz` enum. Requires Python 3.9+. //! - [`either`]: Enables conversions between Python objects and [either]'s [`Either`] type. //! - [`eyre`]: Enables a conversion from [eyre]’s [`Report`] type to [`PyErr`]. //! - [`hashbrown`]: Enables conversions between Python objects and [hashbrown]'s [`HashMap`] and //! [`HashSet`] types. //! - [`indexmap`][indexmap_feature]: Enables conversions between Python dictionary and [indexmap]'s [`IndexMap`]. //! - [`num-bigint`]: Enables conversions between Python objects and [num-bigint]'s [`BigInt`] and //! [`BigUint`] types. //! - [`num-complex`]: Enables conversions between Python objects and [num-complex]'s [`Complex`] //! type. //! - [`num-rational`]: Enables conversions between Python's fractions.Fraction and [num-rational]'s types //! - [`ordered-float`]: Enables conversions between Python's float and [ordered-float]'s types //! - [`rust_decimal`]: Enables conversions between Python's decimal.Decimal and [rust_decimal]'s //! [`Decimal`] type. //! - [`serde`]: Allows implementing [serde]'s [`Serialize`] and [`Deserialize`] traits for //! [`Py`]`` for all `T` that implement [`Serialize`] and [`Deserialize`]. //! - [`smallvec`][smallvec]: Enables conversions between Python list and [smallvec]'s [`SmallVec`]. //! //! ## Unstable features //! //! - `nightly`: Uses `#![feature(auto_traits, negative_impls)]` to define [`Ungil`] as an auto trait. // //! ## `rustc` environment flags //! - `Py_3_7`, `Py_3_8`, `Py_3_9`, `Py_3_10`, `Py_3_11`, `Py_3_12`, `Py_3_13`: Marks code that is //! only enabled when compiling for a given minimum Python version. //! - `Py_LIMITED_API`: Marks code enabled when the `abi3` feature flag is enabled. //! - `Py_GIL_DISABLED`: Marks code that runs only in the free-threaded build of CPython. //! - `PyPy` - Marks code enabled when compiling for PyPy. //! - `GraalPy` - Marks code enabled when compiling for GraalPy. //! //! Additionally, you can query for the values `Py_DEBUG`, `Py_REF_DEBUG`, //! `Py_TRACE_REFS`, and `COUNT_ALLOCS` from `py_sys_config` to query for the //! corresponding C build-time defines. For example, to conditionally define //! debug code using `Py_DEBUG`, you could do: //! //! ```rust,ignore //! #[cfg(py_sys_config = "Py_DEBUG")] //! println!("only runs if python was compiled with Py_DEBUG") //! ``` //! To use these attributes, add [`pyo3-build-config`] as a build dependency in //! your `Cargo.toml` and call `pyo3_build_config::use_pyo3_cfgs()` in a //! `build.rs` file. //! //! # Minimum supported Rust and Python versions //! //! Requires Rust 1.63 or greater. //! //! PyO3 supports the following Python distributions: //! - CPython 3.7 or greater //! - PyPy 7.3 (Python 3.9+) //! - GraalPy 24.0 or greater (Python 3.10+) //! //! # Example: Building a native Python module //! //! PyO3 can be used to generate a native Python module. The easiest way to try this out for the //! first time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based //! Python packages with minimal configuration. The following steps set up some files for an example //! Python module, install `maturin`, and then show how to build and import the Python module. //! //! First, create a new folder (let's call it `string_sum`) containing the following two files: //! //! **`Cargo.toml`** //! //! ```toml //! [package] //! name = "string-sum" //! version = "0.1.0" //! edition = "2021" //! //! [lib] //! name = "string_sum" //! # "cdylib" is necessary to produce a shared library for Python to import from. //! # //! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able //! # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: //! # crate-type = ["cdylib", "rlib"] //! crate-type = ["cdylib"] //! //! [dependencies.pyo3] #![doc = concat!("version = \"", env!("CARGO_PKG_VERSION"), "\"")] //! features = ["extension-module"] //! ``` //! //! **`src/lib.rs`** //! ```rust,no_run //! use pyo3::prelude::*; //! //! /// Formats the sum of two numbers as string. //! #[pyfunction] //! fn sum_as_string(a: usize, b: usize) -> PyResult { //! Ok((a + b).to_string()) //! } //! //! /// A Python module implemented in Rust. //! #[pymodule] //! fn string_sum(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(sum_as_string, m)?)?; //! //! Ok(()) //! } //! ``` //! //! With those two files in place, now `maturin` needs to be installed. This can be done using //! Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin` //! into it: //! ```bash //! $ cd string_sum //! $ python -m venv .env //! $ source .env/bin/activate //! $ pip install maturin //! ``` //! //! Now build and execute the module: //! ```bash //! $ maturin develop //! # lots of progress output as maturin runs the compilation... //! $ python //! >>> import string_sum //! >>> string_sum.sum_as_string(5, 20) //! '25' //! ``` //! //! As well as with `maturin`, it is possible to build using [setuptools-rust] or //! [manually][manual_builds]. Both offer more flexibility than `maturin` but require further //! configuration. //! //! # Example: Using Python from Rust //! //! To embed Python into a Rust binary, you need to ensure that your Python installation contains a //! shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give //! some example code which runs an embedded Python interpreter. //! //! To install the Python shared library on Ubuntu: //! ```bash //! sudo apt install python3-dev //! ``` //! //! Start a new project with `cargo new` and add `pyo3` to the `Cargo.toml` like this: //! ```toml //! [dependencies.pyo3] #![doc = concat!("version = \"", env!("CARGO_PKG_VERSION"), "\"")] //! # this is necessary to automatically initialize the Python interpreter //! features = ["auto-initialize"] //! ``` //! //! Example program displaying the value of `sys.version` and the current user name: //! ```rust //! use pyo3::prelude::*; //! use pyo3::types::IntoPyDict; //! use pyo3::ffi::c_str; //! //! fn main() -> PyResult<()> { //! Python::with_gil(|py| { //! let sys = py.import("sys")?; //! let version: String = sys.getattr("version")?.extract()?; //! //! let locals = [("os", py.import("os")?)].into_py_dict(py)?; //! let code = c_str!("os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"); //! let user: String = py.eval(code, None, Some(&locals))?.extract()?; //! //! println!("Hello {}, I'm Python {}", user, version); //! Ok(()) //! }) //! } //! ``` //! //! The guide has [a section][calling_rust] with lots of examples about this topic. //! //! # Other Examples //! //! The PyO3 [README](https://github.com/PyO3/pyo3#readme) contains quick-start examples for both //! using [Rust from Python] and [Python from Rust]. //! //! The PyO3 repository's [examples subdirectory] //! contains some basic packages to demonstrate usage of PyO3. //! //! There are many projects using PyO3 - see a list of some at //! . //! //! [anyhow]: https://docs.rs/anyhow/ "A trait object based error system for easy idiomatic error handling in Rust applications." //! [anyhow_error]: https://docs.rs/anyhow/latest/anyhow/struct.Error.html "Anyhows `Error` type, a wrapper around a dynamic error type" //! [`anyhow`]: ./anyhow/index.html "Documentation about the `anyhow` feature." //! [inventory]: https://docs.rs/inventory //! [`HashMap`]: https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html //! [`HashSet`]: https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html //! [`SmallVec`]: https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html //! [`Uuid`]: https://docs.rs/uuid/latest/uuid/struct.Uuid.html //! [`IndexMap`]: https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html //! [`BigInt`]: https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html //! [`BigUint`]: https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html //! [`Complex`]: https://docs.rs/num-complex/latest/num_complex/struct.Complex.html //! [`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html //! [`Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html //! [chrono]: https://docs.rs/chrono/ "Date and Time for Rust." //! [chrono-tz]: https://docs.rs/chrono-tz/ "TimeZone implementations for chrono from the IANA database." //! [`chrono`]: ./chrono/index.html "Documentation about the `chrono` feature." //! [`chrono-tz`]: ./chrono-tz/index.html "Documentation about the `chrono-tz` feature." //! [either]: https://docs.rs/either/ "A type that represents one of two alternatives." //! [`either`]: ./either/index.html "Documentation about the `either` feature." //! [`Either`]: https://docs.rs/either/latest/either/enum.Either.html //! [eyre]: https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications." //! [`Report`]: https://docs.rs/eyre/latest/eyre/struct.Report.html //! [`eyre`]: ./eyre/index.html "Documentation about the `eyre` feature." //! [`hashbrown`]: ./hashbrown/index.html "Documentation about the `hashbrown` feature." //! [indexmap_feature]: ./indexmap/index.html "Documentation about the `indexmap` feature." //! [`maturin`]: https://github.com/PyO3/maturin "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" //! [`num-bigint`]: ./num_bigint/index.html "Documentation about the `num-bigint` feature." //! [`num-complex`]: ./num_complex/index.html "Documentation about the `num-complex` feature." //! [`num-rational`]: ./num_rational/index.html "Documentation about the `num-rational` feature." //! [`ordered-float`]: ./ordered_float/index.html "Documentation about the `ordered-float` feature." //! [`pyo3-build-config`]: https://docs.rs/pyo3-build-config //! [rust_decimal]: https://docs.rs/rust_decimal //! [`rust_decimal`]: ./rust_decimal/index.html "Documenation about the `rust_decimal` feature." //! [`Decimal`]: https://docs.rs/rust_decimal/latest/rust_decimal/struct.Decimal.html //! [`serde`]: <./serde/index.html> "Documentation about the `serde` feature." #![doc = concat!("[calling_rust]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/python-from-rust.html \"Calling Python from Rust - PyO3 user guide\"")] //! [examples subdirectory]: https://github.com/PyO3/pyo3/tree/main/examples //! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html "Features - The Cargo Book" //! [global interpreter lock]: https://docs.python.org/3/glossary.html#term-global-interpreter-lock //! [hashbrown]: https://docs.rs/hashbrown //! [smallvec]: https://docs.rs/smallvec //! [uuid]: https://docs.rs/uuid //! [indexmap]: https://docs.rs/indexmap #![doc = concat!("[manual_builds]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution.html#manual-builds \"Manual builds - Building and Distribution - PyO3 user guide\"")] //! [num-bigint]: https://docs.rs/num-bigint //! [num-complex]: https://docs.rs/num-complex //! [num-rational]: https://docs.rs/num-rational //! [ordered-float]: https://docs.rs/ordered-float //! [serde]: https://docs.rs/serde //! [setuptools-rust]: https://github.com/PyO3/setuptools-rust "Setuptools plugin for Rust extensions" //! [the guide]: https://pyo3.rs "PyO3 user guide" #![doc = concat!("[types]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/types.html \"GIL lifetimes, mutability and Python object types\"")] //! [PEP 384]: https://www.python.org/dev/peps/pep-0384 "PEP 384 -- Defining a Stable ABI" //! [Python from Rust]: https://github.com/PyO3/pyo3#using-python-from-rust //! [Rust from Python]: https://github.com/PyO3/pyo3#using-rust-from-python #![doc = concat!("[Features chapter of the guide]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/features.html#features-reference \"Features Reference - PyO3 user guide\"")] //! [`Ungil`]: crate::marker::Ungil pub use crate::class::*; pub use crate::conversion::{FromPyObject, IntoPyObject, IntoPyObjectExt}; pub use crate::err::{DowncastError, DowncastIntoError, PyErr, PyErrArguments, PyResult, ToPyErr}; #[cfg(not(any(PyPy, GraalPy)))] pub use crate::gil::{prepare_freethreaded_python, with_embedded_python_interpreter}; pub use crate::instance::{Borrowed, Bound, BoundObject, Py, PyObject}; pub use crate::marker::Python; pub use crate::pycell::{PyRef, PyRefMut}; pub use crate::pyclass::PyClass; pub use crate::pyclass_init::PyClassInitializer; pub use crate::type_object::{PyTypeCheck, PyTypeInfo}; pub use crate::types::PyAny; pub use crate::version::PythonVersionInfo; pub(crate) mod ffi_ptr_ext; pub(crate) mod py_result_ext; pub(crate) mod sealed; /// Old module which contained some implementation details of the `#[pyproto]` module. /// /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead /// of `use pyo3::class::basic::CompareOp`. /// /// For compatibility reasons this has not yet been removed, however will be done so /// once is resolved. pub mod class { pub use self::gc::{PyTraverseError, PyVisit}; /// Old module which contained some implementation details of the `#[pyproto]` module. /// /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead /// of `use pyo3::class::basic::CompareOp`. /// /// For compatibility reasons this has not yet been removed, however will be done so /// once is resolved. pub mod basic { pub use crate::pyclass::CompareOp; } /// Old module which contained some implementation details of the `#[pyproto]` module. /// /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::PyTraverseError` instead /// of `use pyo3::class::gc::PyTraverseError`. /// /// For compatibility reasons this has not yet been removed, however will be done so /// once is resolved. pub mod gc { pub use crate::pyclass::{PyTraverseError, PyVisit}; } } #[cfg(feature = "macros")] #[doc(hidden)] pub use { indoc, // Re-exported for py_run unindent, // Re-exported for py_run }; #[cfg(all(feature = "macros", feature = "multiple-pymethods"))] #[doc(hidden)] pub use inventory; // Re-exported for `#[pyclass]` and `#[pymethods]` with `multiple-pymethods`. /// Tests and helpers which reside inside PyO3's main library. Declared first so that macros /// are available in unit tests. #[cfg(test)] #[macro_use] mod tests; #[macro_use] mod internal_tricks; mod internal; pub mod buffer; pub mod call; pub mod conversion; mod conversions; #[cfg(feature = "experimental-async")] pub mod coroutine; mod err; pub mod exceptions; pub mod ffi; mod gil; #[doc(hidden)] pub mod impl_; mod instance; pub mod marker; pub mod marshal; #[macro_use] pub mod sync; pub mod panic; pub mod pybacked; pub mod pycell; pub mod pyclass; pub mod pyclass_init; pub mod type_object; pub mod types; mod version; #[allow(unused_imports)] // with no features enabled this module has no public exports pub use crate::conversions::*; #[cfg(feature = "macros")] pub use pyo3_macros::{ pyfunction, pymethods, pymodule, FromPyObject, IntoPyObject, IntoPyObjectRef, }; /// A proc macro used to expose Rust structs and fieldless enums as Python objects. /// #[doc = include_str!("../guide/pyclass-parameters.md")] /// /// For more on creating Python classes, /// see the [class section of the guide][1]. /// #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html")] #[cfg(feature = "macros")] pub use pyo3_macros::pyclass; #[cfg(feature = "macros")] #[macro_use] mod macros; #[cfg(feature = "experimental-inspect")] pub mod inspect; // Putting the declaration of prelude at the end seems to help encourage rustc and rustdoc to prefer using // other paths to the same items. (e.g. `pyo3::types::PyAnyMethods` instead of `pyo3::prelude::PyAnyMethods`). pub mod prelude; /// Test readme and user guide #[cfg(doctest)] pub mod doc_test { macro_rules! doctests { ($($path:expr => $mod:ident),* $(,)?) => { $( #[doc = include_str!(concat!("../", $path))] mod $mod{} )* }; } doctests! { "README.md" => readme_md, "guide/src/advanced.md" => guide_advanced_md, "guide/src/async-await.md" => guide_async_await_md, "guide/src/building-and-distribution.md" => guide_building_and_distribution_md, "guide/src/building-and-distribution/multiple-python-versions.md" => guide_bnd_multiple_python_versions_md, "guide/src/class.md" => guide_class_md, "guide/src/class/call.md" => guide_class_call, "guide/src/class/object.md" => guide_class_object, "guide/src/class/numeric.md" => guide_class_numeric, "guide/src/class/protocols.md" => guide_class_protocols_md, "guide/src/class/thread-safety.md" => guide_class_thread_safety_md, "guide/src/conversions.md" => guide_conversions_md, "guide/src/conversions/tables.md" => guide_conversions_tables_md, "guide/src/conversions/traits.md" => guide_conversions_traits_md, "guide/src/debugging.md" => guide_debugging_md, // deliberate choice not to test guide/ecosystem because those pages depend on external // crates such as pyo3_asyncio. "guide/src/exception.md" => guide_exception_md, "guide/src/faq.md" => guide_faq_md, "guide/src/features.md" => guide_features_md, "guide/src/free-threading.md" => guide_free_threading_md, "guide/src/function.md" => guide_function_md, "guide/src/function/error-handling.md" => guide_function_error_handling_md, "guide/src/function/signature.md" => guide_function_signature_md, "guide/src/migration.md" => guide_migration_md, "guide/src/module.md" => guide_module_md, "guide/src/parallelism.md" => guide_parallelism_md, "guide/src/performance.md" => guide_performance_md, "guide/src/python-from-rust.md" => guide_python_from_rust_md, "guide/src/python-from-rust/calling-existing-code.md" => guide_pfr_calling_existing_code_md, "guide/src/python-from-rust/function-calls.md" => guide_pfr_function_calls_md, "guide/src/python-typing-hints.md" => guide_python_typing_hints_md, "guide/src/rust-from-python.md" => guide_rust_from_python_md, "guide/src/trait-bounds.md" => guide_trait_bounds_md, "guide/src/types.md" => guide_types_md, } } pyo3/src/internal.rs0000644000175000017500000000016115105742312014243 0ustar bdrungbdrung//! Holding place for code which is not intended to be reachable from outside of PyO3. pub(crate) mod get_slot; pyo3/src/pybacked.rs0000644000175000017500000004104415105742312014216 0ustar bdrungbdrung//! Contains types for working with Python objects that own the underlying data. use std::{convert::Infallible, ops::Deref, ptr::NonNull, sync::Arc}; use crate::{ types::{ any::PyAnyMethods, bytearray::PyByteArrayMethods, bytes::PyBytesMethods, string::PyStringMethods, PyByteArray, PyBytes, PyString, }, Bound, DowncastError, FromPyObject, IntoPyObject, Py, PyAny, PyErr, PyResult, Python, }; /// A wrapper around `str` where the storage is owned by a Python `bytes` or `str` object. /// /// This type gives access to the underlying data via a `Deref` implementation. #[cfg_attr(feature = "py-clone", derive(Clone))] pub struct PyBackedStr { #[allow(dead_code)] // only held so that the storage is not dropped storage: Py, data: NonNull, } impl Deref for PyBackedStr { type Target = str; fn deref(&self) -> &str { // Safety: `data` is known to be immutable and owned by self unsafe { self.data.as_ref() } } } impl AsRef for PyBackedStr { fn as_ref(&self) -> &str { self } } impl AsRef<[u8]> for PyBackedStr { fn as_ref(&self) -> &[u8] { self.as_bytes() } } // Safety: the underlying Python str (or bytes) is immutable and // safe to share between threads unsafe impl Send for PyBackedStr {} unsafe impl Sync for PyBackedStr {} impl std::fmt::Display for PyBackedStr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.deref().fmt(f) } } impl_traits!(PyBackedStr, str); impl TryFrom> for PyBackedStr { type Error = PyErr; fn try_from(py_string: Bound<'_, PyString>) -> Result { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] { let s = py_string.to_str()?; let data = NonNull::from(s); Ok(Self { storage: py_string.into_any().unbind(), data, }) } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] { let bytes = py_string.encode_utf8()?; let s = unsafe { std::str::from_utf8_unchecked(bytes.as_bytes()) }; let data = NonNull::from(s); Ok(Self { storage: bytes.into_any().unbind(), data, }) } } } impl FromPyObject<'_> for PyBackedStr { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let py_string = obj.downcast::()?.to_owned(); Self::try_from(py_string) } } impl<'py> IntoPyObject<'py> for PyBackedStr { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.storage.into_bound(py)) } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyString::new(py, &self).into_any()) } } impl<'py> IntoPyObject<'py> for &PyBackedStr { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.storage.bind(py).to_owned()) } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyString::new(py, self).into_any()) } } /// A wrapper around `[u8]` where the storage is either owned by a Python `bytes` object, or a Rust `Box<[u8]>`. /// /// This type gives access to the underlying data via a `Deref` implementation. #[cfg_attr(feature = "py-clone", derive(Clone))] pub struct PyBackedBytes { #[allow(dead_code)] // only held so that the storage is not dropped storage: PyBackedBytesStorage, data: NonNull<[u8]>, } #[allow(dead_code)] #[cfg_attr(feature = "py-clone", derive(Clone))] enum PyBackedBytesStorage { Python(Py), Rust(Arc<[u8]>), } impl Deref for PyBackedBytes { type Target = [u8]; fn deref(&self) -> &[u8] { // Safety: `data` is known to be immutable and owned by self unsafe { self.data.as_ref() } } } impl AsRef<[u8]> for PyBackedBytes { fn as_ref(&self) -> &[u8] { self } } // Safety: the underlying Python bytes or Rust bytes is immutable and // safe to share between threads unsafe impl Send for PyBackedBytes {} unsafe impl Sync for PyBackedBytes {} impl PartialEq<[u8; N]> for PyBackedBytes { fn eq(&self, other: &[u8; N]) -> bool { self.deref() == other } } impl PartialEq for [u8; N] { fn eq(&self, other: &PyBackedBytes) -> bool { self == other.deref() } } impl PartialEq<&[u8; N]> for PyBackedBytes { fn eq(&self, other: &&[u8; N]) -> bool { self.deref() == *other } } impl PartialEq for &[u8; N] { fn eq(&self, other: &PyBackedBytes) -> bool { self == &other.deref() } } impl_traits!(PyBackedBytes, [u8]); impl From> for PyBackedBytes { fn from(py_bytes: Bound<'_, PyBytes>) -> Self { let b = py_bytes.as_bytes(); let data = NonNull::from(b); Self { storage: PyBackedBytesStorage::Python(py_bytes.to_owned().unbind()), data, } } } impl From> for PyBackedBytes { fn from(py_bytearray: Bound<'_, PyByteArray>) -> Self { let s = Arc::<[u8]>::from(py_bytearray.to_vec()); let data = NonNull::from(s.as_ref()); Self { storage: PyBackedBytesStorage::Rust(s), data, } } } impl FromPyObject<'_> for PyBackedBytes { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { if let Ok(bytes) = obj.downcast::() { Ok(Self::from(bytes.to_owned())) } else if let Ok(bytearray) = obj.downcast::() { Ok(Self::from(bytearray.to_owned())) } else { Err(DowncastError::new(obj, "`bytes` or `bytearray`").into()) } } } impl<'py> IntoPyObject<'py> for PyBackedBytes { type Target = PyBytes; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { match self.storage { PyBackedBytesStorage::Python(bytes) => Ok(bytes.into_bound(py)), PyBackedBytesStorage::Rust(bytes) => Ok(PyBytes::new(py, &bytes)), } } } impl<'py> IntoPyObject<'py> for &PyBackedBytes { type Target = PyBytes; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { match &self.storage { PyBackedBytesStorage::Python(bytes) => Ok(bytes.bind(py).clone()), PyBackedBytesStorage::Rust(bytes) => Ok(PyBytes::new(py, bytes)), } } } macro_rules! impl_traits { ($slf:ty, $equiv:ty) => { impl std::fmt::Debug for $slf { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.deref().fmt(f) } } impl PartialEq for $slf { fn eq(&self, other: &Self) -> bool { self.deref() == other.deref() } } impl PartialEq<$equiv> for $slf { fn eq(&self, other: &$equiv) -> bool { self.deref() == other } } impl PartialEq<&$equiv> for $slf { fn eq(&self, other: &&$equiv) -> bool { self.deref() == *other } } impl PartialEq<$slf> for $equiv { fn eq(&self, other: &$slf) -> bool { self == other.deref() } } impl PartialEq<$slf> for &$equiv { fn eq(&self, other: &$slf) -> bool { self == &other.deref() } } impl Eq for $slf {} impl PartialOrd for $slf { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl PartialOrd<$equiv> for $slf { fn partial_cmp(&self, other: &$equiv) -> Option { self.deref().partial_cmp(other) } } impl PartialOrd<$slf> for $equiv { fn partial_cmp(&self, other: &$slf) -> Option { self.partial_cmp(other.deref()) } } impl Ord for $slf { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.deref().cmp(other.deref()) } } impl std::hash::Hash for $slf { fn hash(&self, state: &mut H) { self.deref().hash(state) } } }; } use impl_traits; #[cfg(test)] mod test { use super::*; use crate::{IntoPyObject, Python}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; #[test] fn py_backed_str_empty() { Python::with_gil(|py| { let s = PyString::new(py, ""); let py_backed_str = s.extract::().unwrap(); assert_eq!(&*py_backed_str, ""); }); } #[test] fn py_backed_str() { Python::with_gil(|py| { let s = PyString::new(py, "hello"); let py_backed_str = s.extract::().unwrap(); assert_eq!(&*py_backed_str, "hello"); }); } #[test] fn py_backed_str_try_from() { Python::with_gil(|py| { let s = PyString::new(py, "hello"); let py_backed_str = PyBackedStr::try_from(s).unwrap(); assert_eq!(&*py_backed_str, "hello"); }); } #[test] fn py_backed_str_into_pyobject() { Python::with_gil(|py| { let orig_str = PyString::new(py, "hello"); let py_backed_str = orig_str.extract::().unwrap(); let new_str = py_backed_str.into_pyobject(py).unwrap(); assert_eq!(new_str.extract::().unwrap(), "hello"); #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] assert!(new_str.is(&orig_str)); }); } #[test] fn py_backed_bytes_empty() { Python::with_gil(|py| { let b = PyBytes::new(py, b""); let py_backed_bytes = b.extract::().unwrap(); assert_eq!(&*py_backed_bytes, b""); }); } #[test] fn py_backed_bytes() { Python::with_gil(|py| { let b = PyBytes::new(py, b"abcde"); let py_backed_bytes = b.extract::().unwrap(); assert_eq!(&*py_backed_bytes, b"abcde"); }); } #[test] fn py_backed_bytes_from_bytes() { Python::with_gil(|py| { let b = PyBytes::new(py, b"abcde"); let py_backed_bytes = PyBackedBytes::from(b); assert_eq!(&*py_backed_bytes, b"abcde"); }); } #[test] fn py_backed_bytes_from_bytearray() { Python::with_gil(|py| { let b = PyByteArray::new(py, b"abcde"); let py_backed_bytes = PyBackedBytes::from(b); assert_eq!(&*py_backed_bytes, b"abcde"); }); } #[test] fn py_backed_bytes_into_pyobject() { Python::with_gil(|py| { let orig_bytes = PyBytes::new(py, b"abcde"); let py_backed_bytes = PyBackedBytes::from(orig_bytes.clone()); assert!((&py_backed_bytes) .into_pyobject(py) .unwrap() .is(&orig_bytes)); }); } #[test] fn rust_backed_bytes_into_pyobject() { Python::with_gil(|py| { let orig_bytes = PyByteArray::new(py, b"abcde"); let rust_backed_bytes = PyBackedBytes::from(orig_bytes); assert!(matches!( rust_backed_bytes.storage, PyBackedBytesStorage::Rust(_) )); let to_object = (&rust_backed_bytes).into_pyobject(py).unwrap(); assert!(&to_object.is_exact_instance_of::()); assert_eq!(&to_object.extract::().unwrap(), b"abcde"); }); } #[test] fn test_backed_types_send_sync() { fn is_send() {} fn is_sync() {} is_send::(); is_sync::(); is_send::(); is_sync::(); } #[cfg(feature = "py-clone")] #[test] fn test_backed_str_clone() { Python::with_gil(|py| { let s1: PyBackedStr = PyString::new(py, "hello").try_into().unwrap(); let s2 = s1.clone(); assert_eq!(s1, s2); drop(s1); assert_eq!(s2, "hello"); }); } #[test] fn test_backed_str_eq() { Python::with_gil(|py| { let s1: PyBackedStr = PyString::new(py, "hello").try_into().unwrap(); let s2: PyBackedStr = PyString::new(py, "hello").try_into().unwrap(); assert_eq!(s1, "hello"); assert_eq!(s1, s2); let s3: PyBackedStr = PyString::new(py, "abcde").try_into().unwrap(); assert_eq!("abcde", s3); assert_ne!(s1, s3); }); } #[test] fn test_backed_str_hash() { Python::with_gil(|py| { let h = { let mut hasher = DefaultHasher::new(); "abcde".hash(&mut hasher); hasher.finish() }; let s1: PyBackedStr = PyString::new(py, "abcde").try_into().unwrap(); let h1 = { let mut hasher = DefaultHasher::new(); s1.hash(&mut hasher); hasher.finish() }; assert_eq!(h, h1); }); } #[test] fn test_backed_str_ord() { Python::with_gil(|py| { let mut a = vec!["a", "c", "d", "b", "f", "g", "e"]; let mut b = a .iter() .map(|s| PyString::new(py, s).try_into().unwrap()) .collect::>(); a.sort(); b.sort(); assert_eq!(a, b); }) } #[cfg(feature = "py-clone")] #[test] fn test_backed_bytes_from_bytes_clone() { Python::with_gil(|py| { let b1: PyBackedBytes = PyBytes::new(py, b"abcde").into(); let b2 = b1.clone(); assert_eq!(b1, b2); drop(b1); assert_eq!(b2, b"abcde"); }); } #[cfg(feature = "py-clone")] #[test] fn test_backed_bytes_from_bytearray_clone() { Python::with_gil(|py| { let b1: PyBackedBytes = PyByteArray::new(py, b"abcde").into(); let b2 = b1.clone(); assert_eq!(b1, b2); drop(b1); assert_eq!(b2, b"abcde"); }); } #[test] fn test_backed_bytes_eq() { Python::with_gil(|py| { let b1: PyBackedBytes = PyBytes::new(py, b"abcde").into(); let b2: PyBackedBytes = PyByteArray::new(py, b"abcde").into(); assert_eq!(b1, b"abcde"); assert_eq!(b1, b2); let b3: PyBackedBytes = PyBytes::new(py, b"hello").into(); assert_eq!(b"hello", b3); assert_ne!(b1, b3); }); } #[test] fn test_backed_bytes_hash() { Python::with_gil(|py| { let h = { let mut hasher = DefaultHasher::new(); b"abcde".hash(&mut hasher); hasher.finish() }; let b1: PyBackedBytes = PyBytes::new(py, b"abcde").into(); let h1 = { let mut hasher = DefaultHasher::new(); b1.hash(&mut hasher); hasher.finish() }; let b2: PyBackedBytes = PyByteArray::new(py, b"abcde").into(); let h2 = { let mut hasher = DefaultHasher::new(); b2.hash(&mut hasher); hasher.finish() }; assert_eq!(h, h1); assert_eq!(h, h2); }); } #[test] fn test_backed_bytes_ord() { Python::with_gil(|py| { let mut a = vec![b"a", b"c", b"d", b"b", b"f", b"g", b"e"]; let mut b = a .iter() .map(|&b| PyBytes::new(py, b).into()) .collect::>(); a.sort(); b.sort(); assert_eq!(a, b); }) } } pyo3/src/conversion.rs0000644000175000017500000003715215105742312014626 0ustar bdrungbdrung//! Defines conversions between Rust and Python types. use crate::err::PyResult; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::pyclass::boolean_struct::False; use crate::types::any::PyAnyMethods; use crate::types::PyTuple; use crate::{Borrowed, Bound, BoundObject, Py, PyAny, PyClass, PyErr, PyRef, PyRefMut, Python}; use std::convert::Infallible; /// Defines a conversion from a Rust type to a Python object, which may fail. /// /// This trait has `#[derive(IntoPyObject)]` to automatically implement it for simple types and /// `#[derive(IntoPyObjectRef)]` to implement the same for references. /// /// It functions similarly to std's [`TryInto`] trait, but requires a [GIL token](Python) /// as an argument. /// /// The [`into_pyobject`][IntoPyObject::into_pyobject] method is designed for maximum flexibility and efficiency; it /// - allows for a concrete Python type to be returned (the [`Target`][IntoPyObject::Target] associated type) /// - allows for the smart pointer containing the Python object to be either `Bound<'py, Self::Target>` or `Borrowed<'a, 'py, Self::Target>` /// to avoid unnecessary reference counting overhead /// - allows for a custom error type to be returned in the event of a conversion error to avoid /// unnecessarily creating a Python exception /// /// # See also /// /// - The [`IntoPyObjectExt`] trait, which provides convenience methods for common usages of /// `IntoPyObject` which erase type information and convert errors to `PyErr`. #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "`{Self}` cannot be converted to a Python object", note = "`IntoPyObject` is automatically implemented by the `#[pyclass]` macro", note = "if you do not wish to have a corresponding Python type, implement it manually", note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`" ) )] pub trait IntoPyObject<'py>: Sized { /// The Python output type type Target; /// The smart pointer type to use. /// /// This will usually be [`Bound<'py, Target>`], but in special cases [`Borrowed<'a, 'py, Target>`] can be /// used to minimize reference counting overhead. type Output: BoundObject<'py, Self::Target>; /// The type returned in the event of a conversion error. type Error: Into; /// Performs the conversion. fn into_pyobject(self, py: Python<'py>) -> Result; /// Extracts the type hint information for this type when it appears as a return value. /// /// For example, `Vec` would return `List[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of [`FromPyObject::type_input`]. /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::Any } /// Converts sequence of Self into a Python object. Used to specialize `Vec`, `[u8; N]` /// and `SmallVec<[u8; N]>` as a sequence of bytes into a `bytes` object. #[doc(hidden)] fn owned_sequence_into_pyobject( iter: I, py: Python<'py>, _: private::Token, ) -> Result, PyErr> where I: IntoIterator + AsRef<[Self]>, I::IntoIter: ExactSizeIterator, { let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py)); let list = crate::types::list::try_new_from_iter(py, &mut iter); list.map(Bound::into_any) } /// Converts sequence of Self into a Python object. Used to specialize `&[u8]` and `Cow<[u8]>` /// as a sequence of bytes into a `bytes` object. #[doc(hidden)] fn borrowed_sequence_into_pyobject( iter: I, py: Python<'py>, _: private::Token, ) -> Result, PyErr> where Self: private::Reference, I: IntoIterator + AsRef<[::BaseType]>, I::IntoIter: ExactSizeIterator, { let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py)); let list = crate::types::list::try_new_from_iter(py, &mut iter); list.map(Bound::into_any) } } pub(crate) mod private { pub struct Token; pub trait Reference { type BaseType; } impl Reference for &'_ T { type BaseType = T; } } impl<'py, T> IntoPyObject<'py> for Bound<'py, T> { type Target = T; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self) } } impl<'a, 'py, T> IntoPyObject<'py> for &'a Bound<'py, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self.as_borrowed()) } } impl<'a, 'py, T> IntoPyObject<'py> for Borrowed<'a, 'py, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self) } } impl<'a, 'py, T> IntoPyObject<'py> for &Borrowed<'a, 'py, T> { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(*self) } } impl<'py, T> IntoPyObject<'py> for Py { type Target = T; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.into_bound(py)) } } impl<'a, 'py, T> IntoPyObject<'py> for &'a Py { type Target = T; type Output = Borrowed<'a, 'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.bind_borrowed(py)) } } impl<'a, 'py, T> IntoPyObject<'py> for &&'a T where &'a T: IntoPyObject<'py>, { type Target = <&'a T as IntoPyObject<'py>>::Target; type Output = <&'a T as IntoPyObject<'py>>::Output; type Error = <&'a T as IntoPyObject<'py>>::Error; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } mod into_pyobject_ext { pub trait Sealed {} impl<'py, T> Sealed for T where T: super::IntoPyObject<'py> {} } /// Convenience methods for common usages of [`IntoPyObject`]. Every type that implements /// [`IntoPyObject`] also implements this trait. /// /// These methods: /// - Drop type information from the output, returning a `PyAny` object. /// - Always convert the `Error` type to `PyErr`, which may incur a performance penalty but it /// more convenient in contexts where the `?` operator would produce a `PyErr` anyway. pub trait IntoPyObjectExt<'py>: IntoPyObject<'py> + into_pyobject_ext::Sealed { /// Converts `self` into an owned Python object, dropping type information. #[inline] fn into_bound_py_any(self, py: Python<'py>) -> PyResult> { match self.into_pyobject(py) { Ok(obj) => Ok(obj.into_any().into_bound()), Err(err) => Err(err.into()), } } /// Converts `self` into an owned Python object, dropping type information and unbinding it /// from the `'py` lifetime. #[inline] fn into_py_any(self, py: Python<'py>) -> PyResult> { match self.into_pyobject(py) { Ok(obj) => Ok(obj.into_any().unbind()), Err(err) => Err(err.into()), } } /// Converts `self` into a Python object. /// /// This is equivalent to calling [`into_pyobject`][IntoPyObject::into_pyobject] followed /// with `.map_err(Into::into)` to convert the error type to [`PyErr`]. This is helpful /// for generic code which wants to make use of the `?` operator. #[inline] fn into_pyobject_or_pyerr(self, py: Python<'py>) -> PyResult { match self.into_pyobject(py) { Ok(obj) => Ok(obj), Err(err) => Err(err.into()), } } } impl<'py, T> IntoPyObjectExt<'py> for T where T: IntoPyObject<'py> {} /// Extract a type from a Python object. /// /// /// Normal usage is through the `extract` methods on [`Bound`] and [`Py`], which forward to this trait. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyString; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// // Calling `.extract()` on a `Bound` smart pointer /// let obj: Bound<'_, PyString> = PyString::new(py, "blah"); /// let s: String = obj.extract()?; /// # assert_eq!(s, "blah"); /// /// // Calling `.extract(py)` on a `Py` smart pointer /// let obj: Py = obj.unbind(); /// let s: String = obj.extract(py)?; /// # assert_eq!(s, "blah"); /// # Ok(()) /// }) /// # } /// ``` /// // /// FIXME: until `FromPyObject` can pick up a second lifetime, the below commentary is no longer // /// true. Update and restore this documentation at that time. // /// // /// Note: depending on the implementation, the lifetime of the extracted result may // /// depend on the lifetime of the `obj` or the `prepared` variable. // /// // /// For example, when extracting `&str` from a Python byte string, the resulting string slice will // /// point to the existing string data (lifetime: `'py`). // /// On the other hand, when extracting `&str` from a Python Unicode string, the preparation step // /// will convert the string to UTF-8, and the resulting string slice will have lifetime `'prepared`. // /// Since which case applies depends on the runtime type of the Python object, // /// both the `obj` and `prepared` variables must outlive the resulting string slice. /// /// During the migration of PyO3 from the "GIL Refs" API to the `Bound` smart pointer, this trait /// has two methods `extract` and `extract_bound` which are defaulted to call each other. To avoid /// infinite recursion, implementors must implement at least one of these methods. The recommendation /// is to implement `extract_bound` and leave `extract` as the default implementation. pub trait FromPyObject<'py>: Sized { /// Extracts `Self` from the bound smart pointer `obj`. /// /// Implementors are encouraged to implement this method and leave `extract` defaulted, as /// this will be most compatible with PyO3's future API. fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult; /// Extracts the type hint information for this type when it appears as an argument. /// /// For example, `Vec` would return `Sequence[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of /// [`IntoPyObject::type_output`]. It may be different for some types, such as `Dict`, /// to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Any } } mod from_py_object_bound_sealed { /// Private seal for the `FromPyObjectBound` trait. /// /// This prevents downstream types from implementing the trait before /// PyO3 is ready to declare the trait as public API. pub trait Sealed {} // This generic implementation is why the seal is separate from // `crate::sealed::Sealed`. impl<'py, T> Sealed for T where T: super::FromPyObject<'py> {} impl Sealed for &'_ str {} impl Sealed for std::borrow::Cow<'_, str> {} impl Sealed for &'_ [u8] {} impl Sealed for std::borrow::Cow<'_, [u8]> {} } /// Expected form of [`FromPyObject`] to be used in a future PyO3 release. /// /// The difference between this and `FromPyObject` is that this trait takes an /// additional lifetime `'a`, which is the lifetime of the input `Bound`. /// /// This allows implementations for `&'a str` and `&'a [u8]`, which could not /// be expressed by the existing `FromPyObject` trait once the GIL Refs API was /// removed. /// /// # Usage /// /// Users are prevented from implementing this trait, instead they should implement /// the normal `FromPyObject` trait. This trait has a blanket implementation /// for `T: FromPyObject`. /// /// The only case where this trait may have a use case to be implemented is when the /// lifetime of the extracted value is tied to the lifetime `'a` of the input `Bound` /// instead of the GIL lifetime `py`, as is the case for the `&'a str` implementation. /// /// Please contact the PyO3 maintainers if you believe you have a use case for implementing /// this trait before PyO3 is ready to change the main `FromPyObject` trait to take an /// additional lifetime. /// /// Similarly, users should typically not call these trait methods and should instead /// use this via the `extract` method on `Bound` and `Py`. pub trait FromPyObjectBound<'a, 'py>: Sized + from_py_object_bound_sealed::Sealed { /// Extracts `Self` from the bound smart pointer `obj`. /// /// Users are advised against calling this method directly: instead, use this via /// [`Bound<'_, PyAny>::extract`] or [`Py::extract`]. fn from_py_object_bound(ob: Borrowed<'a, 'py, PyAny>) -> PyResult; /// Extracts the type hint information for this type when it appears as an argument. /// /// For example, `Vec` would return `Sequence[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of /// [`IntoPyObject::type_output`]. It may be different for some types, such as `Dict`, /// to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Any } } impl<'py, T> FromPyObjectBound<'_, 'py> for T where T: FromPyObject<'py>, { fn from_py_object_bound(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { Self::extract_bound(&ob) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } impl FromPyObject<'_> for T where T: PyClass + Clone, { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let bound = obj.downcast::()?; Ok(bound.try_borrow()?.clone()) } } impl<'py, T> FromPyObject<'py> for PyRef<'py, T> where T: PyClass, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { obj.downcast::()?.try_borrow().map_err(Into::into) } } impl<'py, T> FromPyObject<'py> for PyRefMut<'py, T> where T: PyClass, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { obj.downcast::()?.try_borrow_mut().map_err(Into::into) } } impl<'py> IntoPyObject<'py> for () { type Target = PyTuple; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyTuple::empty(py)) } } /// ```rust,compile_fail /// use pyo3::prelude::*; /// /// #[pyclass] /// struct TestClass { /// num: u32, /// } /// /// let t = TestClass { num: 10 }; /// /// Python::with_gil(|py| { /// let pyvalue = Py::new(py, t).unwrap().to_object(py); /// let t: TestClass = pyvalue.extract(py).unwrap(); /// }) /// ``` mod test_no_clone {} pyo3/src/exceptions.rs0000644000175000017500000010501215105742312014611 0ustar bdrungbdrung//! Exception and warning types defined by Python. //! //! The structs in this module represent Python's built-in exceptions and //! warnings, while the modules comprise structs representing errors defined in //! Python code. //! //! The latter are created with the //! [`import_exception`](crate::import_exception) macro, which you can use //! yourself to import Python classes that are ultimately derived from //! `BaseException`. use crate::{ffi, Bound, PyResult, Python}; use std::ffi::CStr; use std::ops; /// The boilerplate to convert between a Rust type and a Python exception. #[doc(hidden)] #[macro_export] macro_rules! impl_exception_boilerplate { ($name: ident) => { $crate::impl_exception_boilerplate_bound!($name); impl $crate::ToPyErr for $name {} }; } #[doc(hidden)] #[macro_export] macro_rules! impl_exception_boilerplate_bound { ($name: ident) => { impl $name { /// Creates a new [`PyErr`] of this type. /// /// [`PyErr`]: https://docs.rs/pyo3/latest/pyo3/struct.PyErr.html "PyErr in pyo3" #[inline] #[allow(dead_code)] pub fn new_err(args: A) -> $crate::PyErr where A: $crate::PyErrArguments + ::std::marker::Send + ::std::marker::Sync + 'static, { $crate::PyErr::new::<$name, A>(args) } } }; } /// Defines a Rust type for an exception defined in Python code. /// /// # Syntax /// /// ```import_exception!(module, MyError)``` /// /// * `module` is the name of the containing module. /// * `MyError` is the name of the new exception type. /// /// # Examples /// ``` /// use pyo3::import_exception; /// use pyo3::types::IntoPyDict; /// use pyo3::Python; /// /// import_exception!(socket, gaierror); /// /// # fn main() -> pyo3::PyResult<()> { /// Python::with_gil(|py| { /// let ctx = [("gaierror", py.get_type::())].into_py_dict(py)?; /// pyo3::py_run!(py, *ctx, "import socket; assert gaierror is socket.gaierror"); /// # Ok(()) /// }) /// # } /// /// ``` #[macro_export] macro_rules! import_exception { ($module: expr, $name: ident) => { /// A Rust type representing an exception defined in Python code. /// /// This type was created by the [`pyo3::import_exception!`] macro - see its documentation /// for more information. /// /// [`pyo3::import_exception!`]: https://docs.rs/pyo3/latest/pyo3/macro.import_exception.html "import_exception in pyo3" #[repr(transparent)] #[allow(non_camel_case_types)] // E.g. `socket.herror` pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::pyobject_native_type_core!( $name, $name::type_object_raw, #module=::std::option::Option::Some(stringify!($module)) ); impl $name { fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { use $crate::types::PyTypeMethods; static TYPE_OBJECT: $crate::impl_::exceptions::ImportedExceptionTypeObject = $crate::impl_::exceptions::ImportedExceptionTypeObject::new(stringify!($module), stringify!($name)); TYPE_OBJECT.get(py).as_type_ptr() } } }; } /// Variant of [`import_exception`](crate::import_exception) that does not emit code needed to /// use the imported exception type as a GIL Ref. /// /// This is useful only during migration as a way to avoid generating needless code. #[macro_export] macro_rules! import_exception_bound { ($module: expr, $name: ident) => { /// A Rust type representing an exception defined in Python code. /// /// This type was created by the [`pyo3::import_exception_bound!`] macro - see its documentation /// for more information. /// /// [`pyo3::import_exception_bound!`]: https://docs.rs/pyo3/latest/pyo3/macro.import_exception.html "import_exception in pyo3" #[repr(transparent)] #[allow(non_camel_case_types)] // E.g. `socket.herror` pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate_bound!($name); $crate::pyobject_native_type_info!( $name, $name::type_object_raw, ::std::option::Option::Some(stringify!($module)) ); impl $crate::types::DerefToPyAny for $name {} impl $name { fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { use $crate::types::PyTypeMethods; static TYPE_OBJECT: $crate::impl_::exceptions::ImportedExceptionTypeObject = $crate::impl_::exceptions::ImportedExceptionTypeObject::new( stringify!($module), stringify!($name), ); TYPE_OBJECT.get(py).as_type_ptr() } } }; } /// Defines a new exception type. /// /// # Syntax /// /// * `module` is the name of the containing module. /// * `name` is the name of the new exception type. /// * `base` is the base class of `MyError`, usually [`PyException`]. /// * `doc` (optional) is the docstring visible to users (with `.__doc__` and `help()`) and /// /// accompanies your error type in your crate's documentation. /// /// # Examples /// /// ``` /// use pyo3::prelude::*; /// use pyo3::create_exception; /// use pyo3::exceptions::PyException; /// /// create_exception!(my_module, MyError, PyException, "Some description."); /// /// #[pyfunction] /// fn raise_myerror() -> PyResult<()> { /// let err = MyError::new_err("Some error happened."); /// Err(err) /// } /// /// #[pymodule] /// fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { /// m.add("MyError", m.py().get_type::())?; /// m.add_function(wrap_pyfunction!(raise_myerror, m)?)?; /// Ok(()) /// } /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = wrap_pyfunction!(raise_myerror, py)?; /// # let locals = pyo3::types::PyDict::new(py); /// # locals.set_item("MyError", py.get_type::())?; /// # locals.set_item("raise_myerror", fun)?; /// # /// # py.run(pyo3::ffi::c_str!( /// # "try: /// # raise_myerror() /// # except MyError as e: /// # assert e.__doc__ == 'Some description.' /// # assert str(e) == 'Some error happened.'"), /// # None, /// # Some(&locals), /// # )?; /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// Python code can handle this exception like any other exception: /// /// ```python /// from my_module import MyError, raise_myerror /// /// try: /// raise_myerror() /// except MyError as e: /// assert e.__doc__ == 'Some description.' /// assert str(e) == 'Some error happened.' /// ``` /// #[macro_export] macro_rules! create_exception { ($module: expr, $name: ident, $base: ty) => { #[repr(transparent)] #[allow(non_camel_case_types)] // E.g. `socket.herror` pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::create_exception_type_object!($module, $name, $base, None); }; ($module: expr, $name: ident, $base: ty, $doc: expr) => { #[repr(transparent)] #[allow(non_camel_case_types)] // E.g. `socket.herror` #[doc = $doc] pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::create_exception_type_object!($module, $name, $base, Some($doc)); }; } /// `impl PyTypeInfo for $name` where `$name` is an /// exception newly defined in Rust code. #[doc(hidden)] #[macro_export] macro_rules! create_exception_type_object { ($module: expr, $name: ident, $base: ty, None) => { $crate::create_exception_type_object!($module, $name, $base, ::std::option::Option::None); }; ($module: expr, $name: ident, $base: ty, Some($doc: expr)) => { $crate::create_exception_type_object!($module, $name, $base, ::std::option::Option::Some($crate::ffi::c_str!($doc))); }; ($module: expr, $name: ident, $base: ty, $doc: expr) => { $crate::pyobject_native_type_core!( $name, $name::type_object_raw, #module=::std::option::Option::Some(stringify!($module)) ); impl $name { fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { use $crate::sync::GILOnceCell; static TYPE_OBJECT: GILOnceCell<$crate::Py<$crate::types::PyType>> = GILOnceCell::new(); TYPE_OBJECT .get_or_init(py, || $crate::PyErr::new_type( py, $crate::ffi::c_str!(concat!(stringify!($module), ".", stringify!($name))), $doc, ::std::option::Option::Some(&py.get_type::<$base>()), ::std::option::Option::None, ).expect("Failed to initialize new exception type.") ).as_ptr() as *mut $crate::ffi::PyTypeObject } } }; } macro_rules! impl_native_exception ( ($name:ident, $exc_name:ident, $doc:expr, $layout:path $(, #checkfunction=$checkfunction:path)?) => ( #[doc = $doc] #[repr(transparent)] #[allow(clippy::upper_case_acronyms)] pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::pyobject_native_type!($name, $layout, |_py| unsafe { $crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject } $(, #checkfunction=$checkfunction)?); $crate::pyobject_subclassable_native_type!($name, $layout); ); ($name:ident, $exc_name:ident, $doc:expr) => ( impl_native_exception!($name, $exc_name, $doc, $crate::ffi::PyBaseExceptionObject); ) ); #[cfg(windows)] macro_rules! impl_windows_native_exception ( ($name:ident, $exc_name:ident, $doc:expr, $layout:path) => ( #[cfg(windows)] #[doc = $doc] #[repr(transparent)] #[allow(clippy::upper_case_acronyms)] pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::pyobject_native_type!($name, $layout, |_py| unsafe { $crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject }); ); ($name:ident, $exc_name:ident, $doc:expr) => ( impl_windows_native_exception!($name, $exc_name, $doc, $crate::ffi::PyBaseExceptionObject); ) ); macro_rules! native_doc( ($name: literal, $alt: literal) => ( concat!( "Represents Python's [`", $name, "`](https://docs.python.org/3/library/exceptions.html#", $name, ") exception. ", $alt ) ); ($name: literal) => ( concat!( " Represents Python's [`", $name, "`](https://docs.python.org/3/library/exceptions.html#", $name, ") exception. # Example: Raising ", $name, " from Rust This exception can be sent to Python code by converting it into a [`PyErr`](crate::PyErr), where Python code can then catch it. ``` use pyo3::prelude::*; use pyo3::exceptions::Py", $name, "; #[pyfunction] fn always_throws() -> PyResult<()> { let message = \"I'm ", $name ,", and I was raised from Rust.\"; Err(Py", $name, "::new_err(message)) } # # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction!(always_throws, py).unwrap(); # let err = fun.call0().expect_err(\"called a function that should always return an error but the return value was Ok\"); # assert!(err.is_instance_of::(py)) # }); ``` Python code: ```python from my_module import always_throws try: always_throws() except ", $name, " as e: print(f\"Caught an exception: {e}\") ``` # Example: Catching ", $name, " in Rust ``` use pyo3::prelude::*; use pyo3::exceptions::Py", $name, "; use pyo3::ffi::c_str; Python::with_gil(|py| { let result: PyResult<()> = py.run(c_str!(\"raise ", $name, "\"), None, None); let error_type = match result { Ok(_) => \"Not an error\", Err(error) if error.is_instance_of::(py) => \"" , $name, "\", Err(_) => \"Some other error\", }; assert_eq!(error_type, \"", $name, "\"); }); ``` " ) ); ); impl_native_exception!( PyBaseException, PyExc_BaseException, native_doc!("BaseException"), ffi::PyBaseExceptionObject, #checkfunction=ffi::PyExceptionInstance_Check ); impl_native_exception!(PyException, PyExc_Exception, native_doc!("Exception")); impl_native_exception!( PyStopAsyncIteration, PyExc_StopAsyncIteration, native_doc!("StopAsyncIteration") ); impl_native_exception!( PyStopIteration, PyExc_StopIteration, native_doc!("StopIteration"), ffi::PyStopIterationObject ); impl_native_exception!( PyGeneratorExit, PyExc_GeneratorExit, native_doc!("GeneratorExit") ); impl_native_exception!( PyArithmeticError, PyExc_ArithmeticError, native_doc!("ArithmeticError") ); impl_native_exception!(PyLookupError, PyExc_LookupError, native_doc!("LookupError")); impl_native_exception!( PyAssertionError, PyExc_AssertionError, native_doc!("AssertionError") ); impl_native_exception!( PyAttributeError, PyExc_AttributeError, native_doc!("AttributeError") ); impl_native_exception!(PyBufferError, PyExc_BufferError, native_doc!("BufferError")); impl_native_exception!(PyEOFError, PyExc_EOFError, native_doc!("EOFError")); impl_native_exception!( PyFloatingPointError, PyExc_FloatingPointError, native_doc!("FloatingPointError") ); #[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PyOSError, PyExc_OSError, native_doc!("OSError"), ffi::PyOSErrorObject ); #[cfg(any(PyPy, GraalPy))] impl_native_exception!(PyOSError, PyExc_OSError, native_doc!("OSError")); impl_native_exception!(PyImportError, PyExc_ImportError, native_doc!("ImportError")); impl_native_exception!( PyModuleNotFoundError, PyExc_ModuleNotFoundError, native_doc!("ModuleNotFoundError") ); impl_native_exception!(PyIndexError, PyExc_IndexError, native_doc!("IndexError")); impl_native_exception!(PyKeyError, PyExc_KeyError, native_doc!("KeyError")); impl_native_exception!( PyKeyboardInterrupt, PyExc_KeyboardInterrupt, native_doc!("KeyboardInterrupt") ); impl_native_exception!(PyMemoryError, PyExc_MemoryError, native_doc!("MemoryError")); impl_native_exception!(PyNameError, PyExc_NameError, native_doc!("NameError")); impl_native_exception!( PyOverflowError, PyExc_OverflowError, native_doc!("OverflowError") ); impl_native_exception!( PyRuntimeError, PyExc_RuntimeError, native_doc!("RuntimeError") ); impl_native_exception!( PyRecursionError, PyExc_RecursionError, native_doc!("RecursionError") ); impl_native_exception!( PyNotImplementedError, PyExc_NotImplementedError, native_doc!("NotImplementedError") ); #[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PySyntaxError, PyExc_SyntaxError, native_doc!("SyntaxError"), ffi::PySyntaxErrorObject ); #[cfg(any(PyPy, GraalPy))] impl_native_exception!(PySyntaxError, PyExc_SyntaxError, native_doc!("SyntaxError")); impl_native_exception!( PyReferenceError, PyExc_ReferenceError, native_doc!("ReferenceError") ); impl_native_exception!(PySystemError, PyExc_SystemError, native_doc!("SystemError")); #[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PySystemExit, PyExc_SystemExit, native_doc!("SystemExit"), ffi::PySystemExitObject ); #[cfg(any(PyPy, GraalPy))] impl_native_exception!(PySystemExit, PyExc_SystemExit, native_doc!("SystemExit")); impl_native_exception!(PyTypeError, PyExc_TypeError, native_doc!("TypeError")); impl_native_exception!( PyUnboundLocalError, PyExc_UnboundLocalError, native_doc!("UnboundLocalError") ); #[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PyUnicodeError, PyExc_UnicodeError, native_doc!("UnicodeError"), ffi::PyUnicodeErrorObject ); #[cfg(any(PyPy, GraalPy))] impl_native_exception!( PyUnicodeError, PyExc_UnicodeError, native_doc!("UnicodeError") ); // these four errors need arguments, so they're too annoying to write tests for using macros... impl_native_exception!( PyUnicodeDecodeError, PyExc_UnicodeDecodeError, native_doc!("UnicodeDecodeError", "") ); impl_native_exception!( PyUnicodeEncodeError, PyExc_UnicodeEncodeError, native_doc!("UnicodeEncodeError", "") ); impl_native_exception!( PyUnicodeTranslateError, PyExc_UnicodeTranslateError, native_doc!("UnicodeTranslateError", "") ); #[cfg(Py_3_11)] impl_native_exception!( PyBaseExceptionGroup, PyExc_BaseExceptionGroup, native_doc!("BaseExceptionGroup", "") ); impl_native_exception!(PyValueError, PyExc_ValueError, native_doc!("ValueError")); impl_native_exception!( PyZeroDivisionError, PyExc_ZeroDivisionError, native_doc!("ZeroDivisionError") ); impl_native_exception!( PyBlockingIOError, PyExc_BlockingIOError, native_doc!("BlockingIOError") ); impl_native_exception!( PyBrokenPipeError, PyExc_BrokenPipeError, native_doc!("BrokenPipeError") ); impl_native_exception!( PyChildProcessError, PyExc_ChildProcessError, native_doc!("ChildProcessError") ); impl_native_exception!( PyConnectionError, PyExc_ConnectionError, native_doc!("ConnectionError") ); impl_native_exception!( PyConnectionAbortedError, PyExc_ConnectionAbortedError, native_doc!("ConnectionAbortedError") ); impl_native_exception!( PyConnectionRefusedError, PyExc_ConnectionRefusedError, native_doc!("ConnectionRefusedError") ); impl_native_exception!( PyConnectionResetError, PyExc_ConnectionResetError, native_doc!("ConnectionResetError") ); impl_native_exception!( PyFileExistsError, PyExc_FileExistsError, native_doc!("FileExistsError") ); impl_native_exception!( PyFileNotFoundError, PyExc_FileNotFoundError, native_doc!("FileNotFoundError") ); impl_native_exception!( PyInterruptedError, PyExc_InterruptedError, native_doc!("InterruptedError") ); impl_native_exception!( PyIsADirectoryError, PyExc_IsADirectoryError, native_doc!("IsADirectoryError") ); impl_native_exception!( PyNotADirectoryError, PyExc_NotADirectoryError, native_doc!("NotADirectoryError") ); impl_native_exception!( PyPermissionError, PyExc_PermissionError, native_doc!("PermissionError") ); impl_native_exception!( PyProcessLookupError, PyExc_ProcessLookupError, native_doc!("ProcessLookupError") ); impl_native_exception!( PyTimeoutError, PyExc_TimeoutError, native_doc!("TimeoutError") ); impl_native_exception!( PyEnvironmentError, PyExc_EnvironmentError, native_doc!("EnvironmentError") ); impl_native_exception!(PyIOError, PyExc_IOError, native_doc!("IOError")); #[cfg(windows)] impl_windows_native_exception!( PyWindowsError, PyExc_WindowsError, native_doc!("WindowsError") ); impl PyUnicodeDecodeError { /// Creates a Python `UnicodeDecodeError`. pub fn new<'py>( py: Python<'py>, encoding: &CStr, input: &[u8], range: ops::Range, reason: &CStr, ) -> PyResult> { use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; unsafe { ffi::PyUnicodeDecodeError_Create( encoding.as_ptr(), input.as_ptr().cast(), input.len() as ffi::Py_ssize_t, range.start as ffi::Py_ssize_t, range.end as ffi::Py_ssize_t, reason.as_ptr(), ) .assume_owned_or_err(py) } .downcast_into() } /// Creates a Python `UnicodeDecodeError` from a Rust UTF-8 decoding error. /// /// # Examples /// /// ``` /// #![cfg_attr(invalid_from_utf8_lint, allow(invalid_from_utf8))] /// use pyo3::prelude::*; /// use pyo3::exceptions::PyUnicodeDecodeError; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let invalid_utf8 = b"fo\xd8o"; /// let err = std::str::from_utf8(invalid_utf8).expect_err("should be invalid utf8"); /// let decode_err = PyUnicodeDecodeError::new_utf8(py, invalid_utf8, err)?; /// assert_eq!( /// decode_err.to_string(), /// "'utf-8' codec can't decode byte 0xd8 in position 2: invalid utf-8" /// ); /// Ok(()) /// }) /// # } pub fn new_utf8<'py>( py: Python<'py>, input: &[u8], err: std::str::Utf8Error, ) -> PyResult> { let pos = err.valid_up_to(); PyUnicodeDecodeError::new( py, ffi::c_str!("utf-8"), input, pos..(pos + 1), ffi::c_str!("invalid utf-8"), ) } } impl_native_exception!(PyWarning, PyExc_Warning, native_doc!("Warning")); impl_native_exception!(PyUserWarning, PyExc_UserWarning, native_doc!("UserWarning")); impl_native_exception!( PyDeprecationWarning, PyExc_DeprecationWarning, native_doc!("DeprecationWarning") ); impl_native_exception!( PyPendingDeprecationWarning, PyExc_PendingDeprecationWarning, native_doc!("PendingDeprecationWarning") ); impl_native_exception!( PySyntaxWarning, PyExc_SyntaxWarning, native_doc!("SyntaxWarning") ); impl_native_exception!( PyRuntimeWarning, PyExc_RuntimeWarning, native_doc!("RuntimeWarning") ); impl_native_exception!( PyFutureWarning, PyExc_FutureWarning, native_doc!("FutureWarning") ); impl_native_exception!( PyImportWarning, PyExc_ImportWarning, native_doc!("ImportWarning") ); impl_native_exception!( PyUnicodeWarning, PyExc_UnicodeWarning, native_doc!("UnicodeWarning") ); impl_native_exception!( PyBytesWarning, PyExc_BytesWarning, native_doc!("BytesWarning") ); impl_native_exception!( PyResourceWarning, PyExc_ResourceWarning, native_doc!("ResourceWarning") ); #[cfg(Py_3_10)] impl_native_exception!( PyEncodingWarning, PyExc_EncodingWarning, native_doc!("EncodingWarning") ); #[cfg(test)] macro_rules! test_exception { ($exc_ty:ident $(, |$py:tt| $constructor:expr )?) => { #[allow(non_snake_case)] #[test] fn $exc_ty () { use super::$exc_ty; $crate::Python::with_gil(|py| { use $crate::types::PyAnyMethods; let err: $crate::PyErr = { None $( .or(Some({ let $py = py; $constructor })) )? .unwrap_or($exc_ty::new_err("a test exception")) }; assert!(err.is_instance_of::<$exc_ty>(py)); let value = err.value(py).as_any().downcast::<$exc_ty>().unwrap(); assert!($crate::PyErr::from(value.clone()).is_instance_of::<$exc_ty>(py)); }) } }; } /// Exceptions defined in Python's [`asyncio`](https://docs.python.org/3/library/asyncio.html) /// module. pub mod asyncio { import_exception!(asyncio, CancelledError); import_exception!(asyncio, InvalidStateError); import_exception!(asyncio, TimeoutError); import_exception!(asyncio, IncompleteReadError); import_exception!(asyncio, LimitOverrunError); import_exception!(asyncio, QueueEmpty); import_exception!(asyncio, QueueFull); #[cfg(test)] mod tests { test_exception!(CancelledError); test_exception!(InvalidStateError); test_exception!(TimeoutError); test_exception!(IncompleteReadError, |_| IncompleteReadError::new_err(( "partial", "expected" ))); test_exception!(LimitOverrunError, |_| LimitOverrunError::new_err(( "message", "consumed" ))); test_exception!(QueueEmpty); test_exception!(QueueFull); } } /// Exceptions defined in Python's [`socket`](https://docs.python.org/3/library/socket.html) /// module. pub mod socket { import_exception!(socket, herror); import_exception!(socket, gaierror); import_exception!(socket, timeout); #[cfg(test)] mod tests { test_exception!(herror); test_exception!(gaierror); test_exception!(timeout); } } #[cfg(test)] mod tests { use super::*; use crate::types::any::PyAnyMethods; use crate::types::{IntoPyDict, PyDict}; use crate::PyErr; import_exception_bound!(socket, gaierror); import_exception_bound!(email.errors, MessageError); #[test] fn test_check_exception() { Python::with_gil(|py| { let err: PyErr = gaierror::new_err(()); let socket = py .import("socket") .map_err(|e| e.display(py)) .expect("could not import socket"); let d = PyDict::new(py); d.set_item("socket", socket) .map_err(|e| e.display(py)) .expect("could not setitem"); d.set_item("exc", err) .map_err(|e| e.display(py)) .expect("could not setitem"); py.run( ffi::c_str!("assert isinstance(exc, socket.gaierror)"), None, Some(&d), ) .map_err(|e| e.display(py)) .expect("assertion failed"); }); } #[test] fn test_check_exception_nested() { Python::with_gil(|py| { let err: PyErr = MessageError::new_err(()); let email = py .import("email") .map_err(|e| e.display(py)) .expect("could not import email"); let d = PyDict::new(py); d.set_item("email", email) .map_err(|e| e.display(py)) .expect("could not setitem"); d.set_item("exc", err) .map_err(|e| e.display(py)) .expect("could not setitem"); py.run( ffi::c_str!("assert isinstance(exc, email.errors.MessageError)"), None, Some(&d), ) .map_err(|e| e.display(py)) .expect("assertion failed"); }); } #[test] fn custom_exception() { create_exception!(mymodule, CustomError, PyException); Python::with_gil(|py| { let error_type = py.get_type::(); let ctx = [("CustomError", error_type)].into_py_dict(py).unwrap(); let type_description: String = py .eval(ffi::c_str!("str(CustomError)"), None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); py.run( ffi::c_str!("assert CustomError('oops').args == ('oops',)"), None, Some(&ctx), ) .unwrap(); py.run( ffi::c_str!("assert CustomError.__doc__ is None"), None, Some(&ctx), ) .unwrap(); }); } #[test] fn custom_exception_dotted_module() { create_exception!(mymodule.exceptions, CustomError, PyException); Python::with_gil(|py| { let error_type = py.get_type::(); let ctx = [("CustomError", error_type)].into_py_dict(py).unwrap(); let type_description: String = py .eval(ffi::c_str!("str(CustomError)"), None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!( type_description, "" ); }); } #[test] fn custom_exception_doc() { create_exception!(mymodule, CustomError, PyException, "Some docs"); Python::with_gil(|py| { let error_type = py.get_type::(); let ctx = [("CustomError", error_type)].into_py_dict(py).unwrap(); let type_description: String = py .eval(ffi::c_str!("str(CustomError)"), None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); py.run( ffi::c_str!("assert CustomError('oops').args == ('oops',)"), None, Some(&ctx), ) .unwrap(); py.run( ffi::c_str!("assert CustomError.__doc__ == 'Some docs'"), None, Some(&ctx), ) .unwrap(); }); } #[test] fn custom_exception_doc_expr() { create_exception!( mymodule, CustomError, PyException, concat!("Some", " more ", stringify!(docs)) ); Python::with_gil(|py| { let error_type = py.get_type::(); let ctx = [("CustomError", error_type)].into_py_dict(py).unwrap(); let type_description: String = py .eval(ffi::c_str!("str(CustomError)"), None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); py.run( ffi::c_str!("assert CustomError('oops').args == ('oops',)"), None, Some(&ctx), ) .unwrap(); py.run( ffi::c_str!("assert CustomError.__doc__ == 'Some more docs'"), None, Some(&ctx), ) .unwrap(); }); } #[test] fn native_exception_debug() { Python::with_gil(|py| { let exc = py .run(ffi::c_str!("raise Exception('banana')"), None, None) .expect_err("raising should have given us an error") .into_value(py) .into_bound(py); assert_eq!( format!("{exc:?}"), exc.repr().unwrap().extract::().unwrap() ); }); } #[test] fn native_exception_display() { Python::with_gil(|py| { let exc = py .run(ffi::c_str!("raise Exception('banana')"), None, None) .expect_err("raising should have given us an error") .into_value(py) .into_bound(py); assert_eq!( exc.to_string(), exc.str().unwrap().extract::().unwrap() ); }); } #[test] fn unicode_decode_error() { let invalid_utf8 = b"fo\xd8o"; #[cfg_attr(invalid_from_utf8_lint, allow(invalid_from_utf8))] let err = std::str::from_utf8(invalid_utf8).expect_err("should be invalid utf8"); Python::with_gil(|py| { let decode_err = PyUnicodeDecodeError::new_utf8(py, invalid_utf8, err).unwrap(); assert_eq!( format!("{decode_err:?}"), "UnicodeDecodeError('utf-8', b'fo\\xd8o', 2, 3, 'invalid utf-8')" ); // Restoring should preserve the same error let e: PyErr = decode_err.into(); e.restore(py); assert_eq!( PyErr::fetch(py).to_string(), "UnicodeDecodeError: \'utf-8\' codec can\'t decode byte 0xd8 in position 2: invalid utf-8" ); }); } #[cfg(Py_3_11)] test_exception!(PyBaseExceptionGroup, |_| PyBaseExceptionGroup::new_err(( "msg", vec![PyValueError::new_err("err")] ))); test_exception!(PyBaseException); test_exception!(PyException); test_exception!(PyStopAsyncIteration); test_exception!(PyStopIteration); test_exception!(PyGeneratorExit); test_exception!(PyArithmeticError); test_exception!(PyLookupError); test_exception!(PyAssertionError); test_exception!(PyAttributeError); test_exception!(PyBufferError); test_exception!(PyEOFError); test_exception!(PyFloatingPointError); test_exception!(PyOSError); test_exception!(PyImportError); test_exception!(PyModuleNotFoundError); test_exception!(PyIndexError); test_exception!(PyKeyError); test_exception!(PyKeyboardInterrupt); test_exception!(PyMemoryError); test_exception!(PyNameError); test_exception!(PyOverflowError); test_exception!(PyRuntimeError); test_exception!(PyRecursionError); test_exception!(PyNotImplementedError); test_exception!(PySyntaxError); test_exception!(PyReferenceError); test_exception!(PySystemError); test_exception!(PySystemExit); test_exception!(PyTypeError); test_exception!(PyUnboundLocalError); test_exception!(PyUnicodeError); test_exception!(PyUnicodeDecodeError, |py| { let invalid_utf8 = b"fo\xd8o"; #[cfg_attr(invalid_from_utf8_lint, allow(invalid_from_utf8))] let err = std::str::from_utf8(invalid_utf8).expect_err("should be invalid utf8"); PyErr::from_value( PyUnicodeDecodeError::new_utf8(py, invalid_utf8, err) .unwrap() .into_any(), ) }); test_exception!(PyUnicodeEncodeError, |py| py .eval(ffi::c_str!("chr(40960).encode('ascii')"), None, None) .unwrap_err()); test_exception!(PyUnicodeTranslateError, |_| { PyUnicodeTranslateError::new_err(("\u{3042}", 0, 1, "ouch")) }); test_exception!(PyValueError); test_exception!(PyZeroDivisionError); test_exception!(PyBlockingIOError); test_exception!(PyBrokenPipeError); test_exception!(PyChildProcessError); test_exception!(PyConnectionError); test_exception!(PyConnectionAbortedError); test_exception!(PyConnectionRefusedError); test_exception!(PyConnectionResetError); test_exception!(PyFileExistsError); test_exception!(PyFileNotFoundError); test_exception!(PyInterruptedError); test_exception!(PyIsADirectoryError); test_exception!(PyNotADirectoryError); test_exception!(PyPermissionError); test_exception!(PyProcessLookupError); test_exception!(PyTimeoutError); test_exception!(PyEnvironmentError); test_exception!(PyIOError); #[cfg(windows)] test_exception!(PyWindowsError); test_exception!(PyWarning); test_exception!(PyUserWarning); test_exception!(PyDeprecationWarning); test_exception!(PyPendingDeprecationWarning); test_exception!(PySyntaxWarning); test_exception!(PyRuntimeWarning); test_exception!(PyFutureWarning); test_exception!(PyImportWarning); test_exception!(PyUnicodeWarning); test_exception!(PyBytesWarning); #[cfg(Py_3_10)] test_exception!(PyEncodingWarning); } pyo3/src/version.rs0000644000175000017500000001204415105742312014117 0ustar bdrungbdrung/// Represents the major, minor, and patch (if any) versions of this interpreter. /// /// This struct is usually created with [`Python::version`]. /// /// # Examples /// /// ```rust /// # use pyo3::Python; /// Python::with_gil(|py| { /// // PyO3 supports Python 3.7 and up. /// assert!(py.version_info() >= (3, 7)); /// assert!(py.version_info() >= (3, 7, 0)); /// }); /// ``` /// /// [`Python::version`]: crate::marker::Python::version #[derive(Debug)] pub struct PythonVersionInfo<'a> { /// Python major version (e.g. `3`). pub major: u8, /// Python minor version (e.g. `11`). pub minor: u8, /// Python patch version (e.g. `0`). pub patch: u8, /// Python version suffix, if applicable (e.g. `a0`). pub suffix: Option<&'a str>, } impl<'a> PythonVersionInfo<'a> { /// Parses a hard-coded Python interpreter version string (e.g. 3.9.0a4+). pub(crate) fn from_str(version_number_str: &'a str) -> Result, &'a str> { fn split_and_parse_number(version_part: &str) -> (u8, Option<&str>) { match version_part.find(|c: char| !c.is_ascii_digit()) { None => (version_part.parse().unwrap(), None), Some(version_part_suffix_start) => { let (version_part, version_part_suffix) = version_part.split_at(version_part_suffix_start); (version_part.parse().unwrap(), Some(version_part_suffix)) } } } let mut parts = version_number_str.splitn(3, '.'); let major_str = parts.next().ok_or("Python major version missing")?; let minor_str = parts.next().ok_or("Python minor version missing")?; let patch_str = parts.next(); let major = major_str .parse() .map_err(|_| "Python major version not an integer")?; let (minor, suffix) = split_and_parse_number(minor_str); if suffix.is_some() { assert!(patch_str.is_none()); return Ok(PythonVersionInfo { major, minor, patch: 0, suffix, }); } let (patch, suffix) = patch_str.map(split_and_parse_number).unwrap_or_default(); Ok(PythonVersionInfo { major, minor, patch, suffix, }) } } impl PartialEq<(u8, u8)> for PythonVersionInfo<'_> { fn eq(&self, other: &(u8, u8)) -> bool { self.major == other.0 && self.minor == other.1 } } impl PartialEq<(u8, u8, u8)> for PythonVersionInfo<'_> { fn eq(&self, other: &(u8, u8, u8)) -> bool { self.major == other.0 && self.minor == other.1 && self.patch == other.2 } } impl PartialOrd<(u8, u8)> for PythonVersionInfo<'_> { fn partial_cmp(&self, other: &(u8, u8)) -> Option { (self.major, self.minor).partial_cmp(other) } } impl PartialOrd<(u8, u8, u8)> for PythonVersionInfo<'_> { fn partial_cmp(&self, other: &(u8, u8, u8)) -> Option { (self.major, self.minor, self.patch).partial_cmp(other) } } #[cfg(test)] mod test { use super::*; use crate::Python; #[test] fn test_python_version_info() { Python::with_gil(|py| { let version = py.version_info(); #[cfg(Py_3_7)] assert!(version >= (3, 7)); #[cfg(Py_3_7)] assert!(version >= (3, 7, 0)); #[cfg(Py_3_8)] assert!(version >= (3, 8)); #[cfg(Py_3_8)] assert!(version >= (3, 8, 0)); #[cfg(Py_3_9)] assert!(version >= (3, 9)); #[cfg(Py_3_9)] assert!(version >= (3, 9, 0)); #[cfg(Py_3_10)] assert!(version >= (3, 10)); #[cfg(Py_3_10)] assert!(version >= (3, 10, 0)); #[cfg(Py_3_11)] assert!(version >= (3, 11)); #[cfg(Py_3_11)] assert!(version >= (3, 11, 0)); }); } #[test] fn test_python_version_info_parse() { assert!(PythonVersionInfo::from_str("3.5.0a1").unwrap() >= (3, 5, 0)); assert!(PythonVersionInfo::from_str("3.5+").unwrap() >= (3, 5, 0)); assert!(PythonVersionInfo::from_str("3.5+").unwrap() == (3, 5, 0)); assert!(PythonVersionInfo::from_str("3.5+").unwrap() != (3, 5, 1)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() < (3, 5, 3)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() == (3, 5, 2)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() == (3, 5)); assert!(PythonVersionInfo::from_str("3.5+").unwrap() == (3, 5)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() < (3, 6)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() > (3, 4)); assert!(PythonVersionInfo::from_str("3.11.3+chromium.29").unwrap() >= (3, 11, 3)); assert_eq!( PythonVersionInfo::from_str("3.11.3+chromium.29") .unwrap() .suffix, Some("+chromium.29") ); } } pyo3/src/panic.rs0000644000175000017500000000174715105742312013534 0ustar bdrungbdrung//! Helper to convert Rust panics to Python exceptions. use crate::exceptions::PyBaseException; use crate::PyErr; use std::any::Any; pyo3_exception!( " The exception raised when Rust code called from Python panics. Like SystemExit, this exception is derived from BaseException so that it will typically propagate all the way through the stack and cause the Python interpreter to exit. ", PanicException, PyBaseException ); impl PanicException { /// Creates a new PanicException from a panic payload. /// /// Attempts to format the error in the same way panic does. #[cold] pub(crate) fn from_panic_payload(payload: Box) -> PyErr { if let Some(string) = payload.downcast_ref::() { Self::new_err((string.clone(),)) } else if let Some(s) = payload.downcast_ref::<&str>() { Self::new_err((s.to_string(),)) } else { Self::new_err(("panic from Rust code",)) } } } pyo3/src/err/0000775000175000017500000000000015105742312012655 5ustar bdrungbdrungpyo3/src/err/mod.rs0000644000175000017500000011277515105742312014015 0ustar bdrungbdrunguse crate::instance::Bound; use crate::panic::PanicException; use crate::type_object::PyTypeInfo; use crate::types::any::PyAnyMethods; use crate::types::{ string::PyStringMethods, traceback::PyTracebackMethods, typeobject::PyTypeMethods, PyTraceback, PyType, }; use crate::{ exceptions::{self, PyBaseException}, ffi, }; use crate::{Borrowed, BoundObject, Py, PyAny, PyObject, Python}; use std::borrow::Cow; use std::ffi::CStr; mod err_state; mod impls; use crate::conversion::IntoPyObject; use err_state::{PyErrState, PyErrStateLazyFnOutput, PyErrStateNormalized}; use std::convert::Infallible; use std::ptr; /// Represents a Python exception. /// /// To avoid needing access to [`Python`] in `Into` conversions to create `PyErr` (thus improving /// compatibility with `?` and other Rust errors) this type supports creating exceptions instances /// in a lazy fashion, where the full Python object for the exception is created only when needed. /// /// Accessing the contained exception in any way, such as with [`value`](PyErr::value), /// [`get_type`](PyErr::get_type), or [`is_instance`](PyErr::is_instance) /// will create the full exception object if it was not already created. pub struct PyErr { state: PyErrState, } // The inner value is only accessed through ways that require proving the gil is held #[cfg(feature = "nightly")] unsafe impl crate::marker::Ungil for PyErr {} /// Represents the result of a Python call. pub type PyResult = Result; /// Error that indicates a failure to convert a PyAny to a more specific Python type. #[derive(Debug)] pub struct DowncastError<'a, 'py> { from: Borrowed<'a, 'py, PyAny>, to: Cow<'static, str>, } impl<'a, 'py> DowncastError<'a, 'py> { /// Create a new `PyDowncastError` representing a failure to convert the object /// `from` into the type named in `to`. pub fn new(from: &'a Bound<'py, PyAny>, to: impl Into>) -> Self { DowncastError { from: from.as_borrowed(), to: to.into(), } } pub(crate) fn new_from_borrowed( from: Borrowed<'a, 'py, PyAny>, to: impl Into>, ) -> Self { DowncastError { from, to: to.into(), } } } /// Error that indicates a failure to convert a PyAny to a more specific Python type. #[derive(Debug)] pub struct DowncastIntoError<'py> { from: Bound<'py, PyAny>, to: Cow<'static, str>, } impl<'py> DowncastIntoError<'py> { /// Create a new `DowncastIntoError` representing a failure to convert the object /// `from` into the type named in `to`. pub fn new(from: Bound<'py, PyAny>, to: impl Into>) -> Self { DowncastIntoError { from, to: to.into(), } } /// Consumes this `DowncastIntoError` and returns the original object, allowing continued /// use of it after a failed conversion. /// /// See [`downcast_into`][PyAnyMethods::downcast_into] for an example. pub fn into_inner(self) -> Bound<'py, PyAny> { self.from } } /// Helper conversion trait that allows to use custom arguments for lazy exception construction. pub trait PyErrArguments: Send + Sync { /// Arguments for exception fn arguments(self, py: Python<'_>) -> PyObject; } impl PyErrArguments for T where T: for<'py> IntoPyObject<'py> + Send + Sync, { fn arguments(self, py: Python<'_>) -> PyObject { // FIXME: `arguments` should become fallible match self.into_pyobject(py) { Ok(obj) => obj.into_any().unbind(), Err(e) => panic!("Converting PyErr arguments failed: {}", e.into()), } } } impl PyErr { /// Creates a new PyErr of type `T`. /// /// `args` can be: /// * a tuple: the exception instance will be created using the equivalent to the Python /// expression `T(*tuple)` /// * any other value: the exception instance will be created using the equivalent to the Python /// expression `T(value)` /// /// This exception instance will be initialized lazily. This avoids the need for the Python GIL /// to be held, but requires `args` to be `Send` and `Sync`. If `args` is not `Send` or `Sync`, /// consider using [`PyErr::from_value`] instead. /// /// If `T` does not inherit from `BaseException`, then a `TypeError` will be returned. /// /// If calling T's constructor with `args` raises an exception, that exception will be returned. /// /// # Examples /// /// ``` /// use pyo3::prelude::*; /// use pyo3::exceptions::PyTypeError; /// /// #[pyfunction] /// fn always_throws() -> PyResult<()> { /// Err(PyErr::new::("Error message")) /// } /// # /// # Python::with_gil(|py| { /// # let fun = pyo3::wrap_pyfunction!(always_throws, py).unwrap(); /// # let err = fun.call0().expect_err("called a function that should always return an error but the return value was Ok"); /// # assert!(err.is_instance_of::(py)) /// # }); /// ``` /// /// In most cases, you can use a concrete exception's constructor instead: /// /// ``` /// use pyo3::prelude::*; /// use pyo3::exceptions::PyTypeError; /// /// #[pyfunction] /// fn always_throws() -> PyResult<()> { /// Err(PyTypeError::new_err("Error message")) /// } /// # /// # Python::with_gil(|py| { /// # let fun = pyo3::wrap_pyfunction!(always_throws, py).unwrap(); /// # let err = fun.call0().expect_err("called a function that should always return an error but the return value was Ok"); /// # assert!(err.is_instance_of::(py)) /// # }); /// ``` #[inline] pub fn new(args: A) -> PyErr where T: PyTypeInfo, A: PyErrArguments + Send + Sync + 'static, { PyErr::from_state(PyErrState::lazy(Box::new(move |py| { PyErrStateLazyFnOutput { ptype: T::type_object(py).into(), pvalue: args.arguments(py), } }))) } /// Constructs a new PyErr from the given Python type and arguments. /// /// `ty` is the exception type; usually one of the standard exceptions /// like `exceptions::PyRuntimeError`. /// /// `args` is either a tuple or a single value, with the same meaning as in [`PyErr::new`]. /// /// If `ty` does not inherit from `BaseException`, then a `TypeError` will be returned. /// /// If calling `ty` with `args` raises an exception, that exception will be returned. pub fn from_type(ty: Bound<'_, PyType>, args: A) -> PyErr where A: PyErrArguments + Send + Sync + 'static, { PyErr::from_state(PyErrState::lazy_arguments(ty.unbind().into_any(), args)) } /// Creates a new PyErr. /// /// If `obj` is a Python exception object, the PyErr will contain that object. /// /// If `obj` is a Python exception type object, this is equivalent to `PyErr::from_type(obj, ())`. /// /// Otherwise, a `TypeError` is created. /// /// # Examples /// ```rust /// use pyo3::prelude::*; /// use pyo3::PyTypeInfo; /// use pyo3::exceptions::PyTypeError; /// use pyo3::types::PyString; /// /// Python::with_gil(|py| { /// // Case #1: Exception object /// let err = PyErr::from_value(PyTypeError::new_err("some type error") /// .value(py).clone().into_any()); /// assert_eq!(err.to_string(), "TypeError: some type error"); /// /// // Case #2: Exception type /// let err = PyErr::from_value(PyTypeError::type_object(py).into_any()); /// assert_eq!(err.to_string(), "TypeError: "); /// /// // Case #3: Invalid exception value /// let err = PyErr::from_value(PyString::new(py, "foo").into_any()); /// assert_eq!( /// err.to_string(), /// "TypeError: exceptions must derive from BaseException" /// ); /// }); /// ``` pub fn from_value(obj: Bound<'_, PyAny>) -> PyErr { let state = match obj.downcast_into::() { Ok(obj) => PyErrState::normalized(PyErrStateNormalized::new(obj)), Err(err) => { // Assume obj is Type[Exception]; let later normalization handle if this // is not the case let obj = err.into_inner(); let py = obj.py(); PyErrState::lazy_arguments(obj.unbind(), py.None()) } }; PyErr::from_state(state) } /// Returns the type of this exception. /// /// # Examples /// ```rust /// use pyo3::{prelude::*, exceptions::PyTypeError, types::PyType}; /// /// Python::with_gil(|py| { /// let err: PyErr = PyTypeError::new_err(("some type error",)); /// assert!(err.get_type(py).is(&PyType::new::(py))); /// }); /// ``` pub fn get_type<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> { self.normalized(py).ptype(py) } /// Returns the value of this exception. /// /// # Examples /// /// ```rust /// use pyo3::{exceptions::PyTypeError, PyErr, Python}; /// /// Python::with_gil(|py| { /// let err: PyErr = PyTypeError::new_err(("some type error",)); /// assert!(err.is_instance_of::(py)); /// assert_eq!(err.value(py).to_string(), "some type error"); /// }); /// ``` pub fn value<'py>(&self, py: Python<'py>) -> &Bound<'py, PyBaseException> { self.normalized(py).pvalue.bind(py) } /// Consumes self to take ownership of the exception value contained in this error. pub fn into_value(self, py: Python<'_>) -> Py { // NB technically this causes one reference count increase and decrease in quick succession // on pvalue, but it's probably not worth optimizing this right now for the additional code // complexity. let normalized = self.normalized(py); let exc = normalized.pvalue.clone_ref(py); if let Some(tb) = normalized.ptraceback(py) { unsafe { ffi::PyException_SetTraceback(exc.as_ptr(), tb.as_ptr()); } } exc } /// Returns the traceback of this exception object. /// /// # Examples /// ```rust /// use pyo3::{exceptions::PyTypeError, Python}; /// /// Python::with_gil(|py| { /// let err = PyTypeError::new_err(("some type error",)); /// assert!(err.traceback(py).is_none()); /// }); /// ``` pub fn traceback<'py>(&self, py: Python<'py>) -> Option> { self.normalized(py).ptraceback(py) } /// Gets whether an error is present in the Python interpreter's global state. #[inline] pub fn occurred(_: Python<'_>) -> bool { unsafe { !ffi::PyErr_Occurred().is_null() } } /// Takes the current error from the Python interpreter's global state and clears the global /// state. If no error is set, returns `None`. /// /// If the error is a `PanicException` (which would have originated from a panic in a pyo3 /// callback) then this function will resume the panic. /// /// Use this function when it is not known if an error should be present. If the error is /// expected to have been set, for example from [`PyErr::occurred`] or by an error return value /// from a C FFI function, use [`PyErr::fetch`]. pub fn take(py: Python<'_>) -> Option { let state = PyErrStateNormalized::take(py)?; let pvalue = state.pvalue.bind(py); if ptr::eq( pvalue.get_type().as_ptr(), PanicException::type_object_raw(py).cast(), ) { let msg: String = pvalue .str() .map(|py_str| py_str.to_string_lossy().into()) .unwrap_or_else(|_| String::from("Unwrapped panic from Python code")); Self::print_panic_and_unwind(py, PyErrState::normalized(state), msg) } Some(PyErr::from_state(PyErrState::normalized(state))) } fn print_panic_and_unwind(py: Python<'_>, state: PyErrState, msg: String) -> ! { eprintln!("--- PyO3 is resuming a panic after fetching a PanicException from Python. ---"); eprintln!("Python stack trace below:"); state.restore(py); unsafe { ffi::PyErr_PrintEx(0); } std::panic::resume_unwind(Box::new(msg)) } /// Equivalent to [PyErr::take], but when no error is set: /// - Panics in debug mode. /// - Returns a `SystemError` in release mode. /// /// This behavior is consistent with Python's internal handling of what happens when a C return /// value indicates an error occurred but the global error state is empty. (A lack of exception /// should be treated as a bug in the code which returned an error code but did not set an /// exception.) /// /// Use this function when the error is expected to have been set, for example from /// [PyErr::occurred] or by an error return value from a C FFI function. #[cfg_attr(debug_assertions, track_caller)] #[inline] pub fn fetch(py: Python<'_>) -> PyErr { const FAILED_TO_FETCH: &str = "attempted to fetch exception but none was set"; match PyErr::take(py) { Some(err) => err, #[cfg(debug_assertions)] None => panic!("{}", FAILED_TO_FETCH), #[cfg(not(debug_assertions))] None => exceptions::PySystemError::new_err(FAILED_TO_FETCH), } } /// Creates a new exception type with the given name and docstring. /// /// - `base` can be an existing exception type to subclass, or a tuple of classes. /// - `dict` specifies an optional dictionary of class variables and methods. /// - `doc` will be the docstring seen by python users. /// /// /// # Errors /// /// This function returns an error if `name` is not of the form `.`. pub fn new_type<'py>( py: Python<'py>, name: &CStr, doc: Option<&CStr>, base: Option<&Bound<'py, PyType>>, dict: Option, ) -> PyResult> { let base: *mut ffi::PyObject = match base { None => std::ptr::null_mut(), Some(obj) => obj.as_ptr(), }; let dict: *mut ffi::PyObject = match dict { None => std::ptr::null_mut(), Some(obj) => obj.as_ptr(), }; let doc_ptr = match doc.as_ref() { Some(c) => c.as_ptr(), None => std::ptr::null(), }; let ptr = unsafe { ffi::PyErr_NewExceptionWithDoc(name.as_ptr(), doc_ptr, base, dict) }; unsafe { Py::from_owned_ptr_or_err(py, ptr) } } /// Prints a standard traceback to `sys.stderr`. pub fn display(&self, py: Python<'_>) { #[cfg(Py_3_12)] unsafe { ffi::PyErr_DisplayException(self.value(py).as_ptr()) } #[cfg(not(Py_3_12))] unsafe { // keep the bound `traceback` alive for entire duration of // PyErr_Display. if we inline this, the `Bound` will be dropped // after the argument got evaluated, leading to call with a dangling // pointer. let traceback = self.traceback(py); let type_bound = self.get_type(py); ffi::PyErr_Display( type_bound.as_ptr(), self.value(py).as_ptr(), traceback .as_ref() .map_or(std::ptr::null_mut(), |traceback| traceback.as_ptr()), ) } } /// Calls `sys.excepthook` and then prints a standard traceback to `sys.stderr`. pub fn print(&self, py: Python<'_>) { self.clone_ref(py).restore(py); unsafe { ffi::PyErr_PrintEx(0) } } /// Calls `sys.excepthook` and then prints a standard traceback to `sys.stderr`. /// /// Additionally sets `sys.last_{type,value,traceback,exc}` attributes to this exception. pub fn print_and_set_sys_last_vars(&self, py: Python<'_>) { self.clone_ref(py).restore(py); unsafe { ffi::PyErr_PrintEx(1) } } /// Returns true if the current exception matches the exception in `exc`. /// /// If `exc` is a class object, this also returns `true` when `self` is an instance of a subclass. /// If `exc` is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match. pub fn matches<'py, T>(&self, py: Python<'py>, exc: T) -> Result where T: IntoPyObject<'py>, { Ok(self.is_instance(py, &exc.into_pyobject(py)?.into_any().as_borrowed())) } /// Returns true if the current exception is instance of `T`. #[inline] pub fn is_instance(&self, py: Python<'_>, ty: &Bound<'_, PyAny>) -> bool { let type_bound = self.get_type(py); (unsafe { ffi::PyErr_GivenExceptionMatches(type_bound.as_ptr(), ty.as_ptr()) }) != 0 } /// Returns true if the current exception is instance of `T`. #[inline] pub fn is_instance_of(&self, py: Python<'_>) -> bool where T: PyTypeInfo, { self.is_instance(py, &T::type_object(py)) } /// Writes the error back to the Python interpreter's global state. /// This is the opposite of `PyErr::fetch()`. #[inline] pub fn restore(self, py: Python<'_>) { self.state.restore(py) } /// Reports the error as unraisable. /// /// This calls `sys.unraisablehook()` using the current exception and obj argument. /// /// This method is useful to report errors in situations where there is no good mechanism /// to report back to the Python land. In Python this is used to indicate errors in /// background threads or destructors which are protected. In Rust code this is commonly /// useful when you are calling into a Python callback which might fail, but there is no /// obvious way to handle this error other than logging it. /// /// Calling this method has the benefit that the error goes back into a standardized callback /// in Python which for instance allows unittests to ensure that no unraisable error /// actually happend by hooking `sys.unraisablehook`. /// /// Example: /// ```rust /// # use pyo3::prelude::*; /// # use pyo3::exceptions::PyRuntimeError; /// # fn failing_function() -> PyResult<()> { Err(PyRuntimeError::new_err("foo")) } /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// match failing_function() { /// Err(pyerr) => pyerr.write_unraisable(py, None), /// Ok(..) => { /* do something here */ } /// } /// Ok(()) /// }) /// # } #[inline] pub fn write_unraisable(self, py: Python<'_>, obj: Option<&Bound<'_, PyAny>>) { self.restore(py); unsafe { ffi::PyErr_WriteUnraisable(obj.map_or(std::ptr::null_mut(), Bound::as_ptr)) } } /// Issues a warning message. /// /// May return an `Err(PyErr)` if warnings-as-errors is enabled. /// /// Equivalent to `warnings.warn()` in Python. /// /// The `category` should be one of the `Warning` classes available in /// [`pyo3::exceptions`](crate::exceptions), or a subclass. The Python /// object can be retrieved using [`Python::get_type()`]. /// /// Example: /// ```rust /// # use pyo3::prelude::*; /// # use pyo3::ffi::c_str; /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let user_warning = py.get_type::(); /// PyErr::warn(py, &user_warning, c_str!("I am warning you"), 0)?; /// Ok(()) /// }) /// # } /// ``` pub fn warn<'py>( py: Python<'py>, category: &Bound<'py, PyAny>, message: &CStr, stacklevel: i32, ) -> PyResult<()> { error_on_minusone(py, unsafe { ffi::PyErr_WarnEx( category.as_ptr(), message.as_ptr(), stacklevel as ffi::Py_ssize_t, ) }) } /// Issues a warning message, with more control over the warning attributes. /// /// May return a `PyErr` if warnings-as-errors is enabled. /// /// Equivalent to `warnings.warn_explicit()` in Python. /// /// The `category` should be one of the `Warning` classes available in /// [`pyo3::exceptions`](crate::exceptions), or a subclass. pub fn warn_explicit<'py>( py: Python<'py>, category: &Bound<'py, PyAny>, message: &CStr, filename: &CStr, lineno: i32, module: Option<&CStr>, registry: Option<&Bound<'py, PyAny>>, ) -> PyResult<()> { let module_ptr = match module { None => std::ptr::null_mut(), Some(s) => s.as_ptr(), }; let registry: *mut ffi::PyObject = match registry { None => std::ptr::null_mut(), Some(obj) => obj.as_ptr(), }; error_on_minusone(py, unsafe { ffi::PyErr_WarnExplicit( category.as_ptr(), message.as_ptr(), filename.as_ptr(), lineno, module_ptr, registry, ) }) } /// Clone the PyErr. This requires the GIL, which is why PyErr does not implement Clone. /// /// # Examples /// ```rust /// use pyo3::{exceptions::PyTypeError, PyErr, Python, prelude::PyAnyMethods}; /// Python::with_gil(|py| { /// let err: PyErr = PyTypeError::new_err(("some type error",)); /// let err_clone = err.clone_ref(py); /// assert!(err.get_type(py).is(&err_clone.get_type(py))); /// assert!(err.value(py).is(err_clone.value(py))); /// match err.traceback(py) { /// None => assert!(err_clone.traceback(py).is_none()), /// Some(tb) => assert!(err_clone.traceback(py).unwrap().is(&tb)), /// } /// }); /// ``` #[inline] pub fn clone_ref(&self, py: Python<'_>) -> PyErr { PyErr::from_state(PyErrState::normalized(self.normalized(py).clone_ref(py))) } /// Return the cause (either an exception instance, or None, set by `raise ... from ...`) /// associated with the exception, as accessible from Python through `__cause__`. pub fn cause(&self, py: Python<'_>) -> Option { use crate::ffi_ptr_ext::FfiPtrExt; let obj = unsafe { ffi::PyException_GetCause(self.value(py).as_ptr()).assume_owned_or_opt(py) }; // PyException_GetCause is documented as potentially returning PyNone, but only GraalPy seems to actually do that #[cfg(GraalPy)] if let Some(cause) = &obj { if cause.is_none() { return None; } } obj.map(Self::from_value) } /// Set the cause associated with the exception, pass `None` to clear it. pub fn set_cause(&self, py: Python<'_>, cause: Option) { let value = self.value(py); let cause = cause.map(|err| err.into_value(py)); unsafe { // PyException_SetCause _steals_ a reference to cause, so must use .into_ptr() ffi::PyException_SetCause( value.as_ptr(), cause.map_or(std::ptr::null_mut(), Py::into_ptr), ); } } #[inline] fn from_state(state: PyErrState) -> PyErr { PyErr { state } } #[inline] fn normalized(&self, py: Python<'_>) -> &PyErrStateNormalized { self.state.as_normalized(py) } } impl std::fmt::Debug for PyErr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { Python::with_gil(|py| { f.debug_struct("PyErr") .field("type", &self.get_type(py)) .field("value", self.value(py)) .field( "traceback", &self.traceback(py).map(|tb| match tb.format() { Ok(s) => s, Err(err) => { err.write_unraisable(py, Some(&tb)); // It would be nice to format what we can of the // error, but we can't guarantee that the error // won't have another unformattable traceback inside // it and we want to avoid an infinite recursion. format!("") } }), ) .finish() }) } } impl std::fmt::Display for PyErr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Python::with_gil(|py| { let value = self.value(py); let type_name = value.get_type().qualname().map_err(|_| std::fmt::Error)?; write!(f, "{type_name}")?; if let Ok(s) = value.str() { write!(f, ": {}", &s.to_string_lossy()) } else { write!(f, ": ") } }) } } impl std::error::Error for PyErr {} impl<'py> IntoPyObject<'py> for PyErr { type Target = PyBaseException; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(self.into_value(py).into_bound(py)) } } impl<'py> IntoPyObject<'py> for &PyErr { type Target = PyBaseException; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.clone_ref(py).into_pyobject(py) } } struct PyDowncastErrorArguments { from: Py, to: Cow<'static, str>, } impl PyErrArguments for PyDowncastErrorArguments { fn arguments(self, py: Python<'_>) -> PyObject { const FAILED_TO_EXTRACT: Cow<'_, str> = Cow::Borrowed(""); let from = self.from.bind(py).qualname(); let from = match &from { Ok(qn) => qn.to_cow().unwrap_or(FAILED_TO_EXTRACT), Err(_) => FAILED_TO_EXTRACT, }; format!("'{}' object cannot be converted to '{}'", from, self.to) .into_pyobject(py) .unwrap() .into_any() .unbind() } } /// Python exceptions that can be converted to [`PyErr`]. /// /// This is used to implement [`From> for PyErr`]. /// /// Users should not need to implement this trait directly. It is implemented automatically in the /// [`crate::import_exception!`] and [`crate::create_exception!`] macros. pub trait ToPyErr {} impl<'py, T> std::convert::From> for PyErr where T: ToPyErr, { #[inline] fn from(err: Bound<'py, T>) -> PyErr { PyErr::from_value(err.into_any()) } } /// Convert `DowncastError` to Python `TypeError`. impl std::convert::From> for PyErr { fn from(err: DowncastError<'_, '_>) -> PyErr { let args = PyDowncastErrorArguments { from: err.from.get_type().into(), to: err.to, }; exceptions::PyTypeError::new_err(args) } } impl std::error::Error for DowncastError<'_, '_> {} impl std::fmt::Display for DowncastError<'_, '_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { display_downcast_error(f, &self.from, &self.to) } } /// Convert `DowncastIntoError` to Python `TypeError`. impl std::convert::From> for PyErr { fn from(err: DowncastIntoError<'_>) -> PyErr { let args = PyDowncastErrorArguments { from: err.from.get_type().into(), to: err.to, }; exceptions::PyTypeError::new_err(args) } } impl std::error::Error for DowncastIntoError<'_> {} impl std::fmt::Display for DowncastIntoError<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { display_downcast_error(f, &self.from, &self.to) } } fn display_downcast_error( f: &mut std::fmt::Formatter<'_>, from: &Bound<'_, PyAny>, to: &str, ) -> std::fmt::Result { write!( f, "'{}' object cannot be converted to '{}'", from.get_type().qualname().map_err(|_| std::fmt::Error)?, to ) } #[track_caller] pub fn panic_after_error(_py: Python<'_>) -> ! { unsafe { ffi::PyErr_Print(); } panic!("Python API call failed"); } /// Returns Ok if the error code is not -1. #[inline] pub(crate) fn error_on_minusone(py: Python<'_>, result: T) -> PyResult<()> { if result != T::MINUS_ONE { Ok(()) } else { Err(PyErr::fetch(py)) } } pub(crate) trait SignedInteger: Eq { const MINUS_ONE: Self; } macro_rules! impl_signed_integer { ($t:ty) => { impl SignedInteger for $t { const MINUS_ONE: Self = -1; } }; } impl_signed_integer!(i8); impl_signed_integer!(i16); impl_signed_integer!(i32); impl_signed_integer!(i64); impl_signed_integer!(i128); impl_signed_integer!(isize); #[cfg(test)] mod tests { use super::PyErrState; use crate::exceptions::{self, PyTypeError, PyValueError}; use crate::{ffi, PyErr, PyTypeInfo, Python}; #[test] fn no_error() { assert!(Python::with_gil(PyErr::take).is_none()); } #[test] fn set_valueerror() { Python::with_gil(|py| { let err: PyErr = exceptions::PyValueError::new_err("some exception message"); assert!(err.is_instance_of::(py)); err.restore(py); assert!(PyErr::occurred(py)); let err = PyErr::fetch(py); assert!(err.is_instance_of::(py)); assert_eq!(err.to_string(), "ValueError: some exception message"); }) } #[test] fn invalid_error_type() { Python::with_gil(|py| { let err: PyErr = PyErr::new::(()); assert!(err.is_instance_of::(py)); err.restore(py); let err = PyErr::fetch(py); assert!(err.is_instance_of::(py)); assert_eq!( err.to_string(), "TypeError: exceptions must derive from BaseException" ); }) } #[test] fn set_typeerror() { Python::with_gil(|py| { let err: PyErr = exceptions::PyTypeError::new_err(()); err.restore(py); assert!(PyErr::occurred(py)); drop(PyErr::fetch(py)); }); } #[test] #[should_panic(expected = "new panic")] fn fetching_panic_exception_resumes_unwind() { use crate::panic::PanicException; Python::with_gil(|py| { let err: PyErr = PanicException::new_err("new panic"); err.restore(py); assert!(PyErr::occurred(py)); // should resume unwind let _ = PyErr::fetch(py); }); } #[test] #[should_panic(expected = "new panic")] #[cfg(not(Py_3_12))] fn fetching_normalized_panic_exception_resumes_unwind() { use crate::panic::PanicException; Python::with_gil(|py| { let err: PyErr = PanicException::new_err("new panic"); // Restoring an error doesn't normalize it before Python 3.12, // so we have to explicitly test this case. let _ = err.normalized(py); err.restore(py); assert!(PyErr::occurred(py)); // should resume unwind let _ = PyErr::fetch(py); }); } #[test] fn err_debug() { // Debug representation should be like the following (without the newlines): // PyErr { // type: , // value: Exception('banana'), // traceback: Some(\"Traceback (most recent call last):\\n File \\\"\\\", line 1, in \\n\") // } Python::with_gil(|py| { let err = py .run(ffi::c_str!("raise Exception('banana')"), None, None) .expect_err("raising should have given us an error"); let debug_str = format!("{err:?}"); assert!(debug_str.starts_with("PyErr { ")); assert!(debug_str.ends_with(" }")); // Strip "PyErr { " and " }". Split into 3 substrings to separate type, // value, and traceback while not splitting the string within traceback. let mut fields = debug_str["PyErr { ".len()..debug_str.len() - 2].splitn(3, ", "); assert_eq!(fields.next().unwrap(), "type: "); assert_eq!(fields.next().unwrap(), "value: Exception('banana')"); assert_eq!( fields.next().unwrap(), "traceback: Some(\"Traceback (most recent call last):\\n File \\\"\\\", line 1, in \\n\")" ); assert!(fields.next().is_none()); }); } #[test] fn err_display() { Python::with_gil(|py| { let err = py .run(ffi::c_str!("raise Exception('banana')"), None, None) .expect_err("raising should have given us an error"); assert_eq!(err.to_string(), "Exception: banana"); }); } #[test] fn test_pyerr_send_sync() { fn is_send() {} fn is_sync() {} is_send::(); is_sync::(); is_send::(); is_sync::(); } #[test] fn test_pyerr_matches() { Python::with_gil(|py| { let err = PyErr::new::("foo"); assert!(err.matches(py, PyValueError::type_object(py)).unwrap()); assert!(err .matches( py, (PyValueError::type_object(py), PyTypeError::type_object(py)) ) .unwrap()); assert!(!err.matches(py, PyTypeError::type_object(py)).unwrap()); // String is not a valid exception class, so we should get a TypeError let err: PyErr = PyErr::from_type(crate::types::PyString::type_object(py), "foo"); assert!(err.matches(py, PyTypeError::type_object(py)).unwrap()); }) } #[test] fn test_pyerr_cause() { Python::with_gil(|py| { let err = py .run(ffi::c_str!("raise Exception('banana')"), None, None) .expect_err("raising should have given us an error"); assert!(err.cause(py).is_none()); let err = py .run( ffi::c_str!("raise Exception('banana') from Exception('apple')"), None, None, ) .expect_err("raising should have given us an error"); let cause = err .cause(py) .expect("raising from should have given us a cause"); assert_eq!(cause.to_string(), "Exception: apple"); err.set_cause(py, None); assert!(err.cause(py).is_none()); let new_cause = exceptions::PyValueError::new_err("orange"); err.set_cause(py, Some(new_cause)); let cause = err .cause(py) .expect("set_cause should have given us a cause"); assert_eq!(cause.to_string(), "ValueError: orange"); }); } #[test] fn warnings() { use crate::types::any::PyAnyMethods; // Note: although the warning filter is interpreter global, keeping the // GIL locked should prevent effects to be visible to other testing // threads. Python::with_gil(|py| { let cls = py.get_type::(); // Reset warning filter to default state let warnings = py.import("warnings").unwrap(); warnings.call_method0("resetwarnings").unwrap(); // First, test the warning is emitted #[cfg(not(Py_GIL_DISABLED))] assert_warnings!( py, { PyErr::warn(py, &cls, ffi::c_str!("I am warning you"), 0).unwrap() }, [(exceptions::PyUserWarning, "I am warning you")] ); // Test with raising warnings .call_method1("simplefilter", ("error", &cls)) .unwrap(); PyErr::warn(py, &cls, ffi::c_str!("I am warning you"), 0).unwrap_err(); // Test with error for an explicit module warnings.call_method0("resetwarnings").unwrap(); warnings .call_method1("filterwarnings", ("error", "", &cls, "pyo3test")) .unwrap(); // This has the wrong module and will not raise, just be emitted #[cfg(not(Py_GIL_DISABLED))] assert_warnings!( py, { PyErr::warn(py, &cls, ffi::c_str!("I am warning you"), 0).unwrap() }, [(exceptions::PyUserWarning, "I am warning you")] ); let err = PyErr::warn_explicit( py, &cls, ffi::c_str!("I am warning you"), ffi::c_str!("pyo3test.py"), 427, None, None, ) .unwrap_err(); assert!(err .value(py) .getattr("args") .unwrap() .get_item(0) .unwrap() .eq("I am warning you") .unwrap()); // Finally, reset filter again warnings.call_method0("resetwarnings").unwrap(); }); } } pyo3/src/err/err_state.rs0000644000175000017500000003576415105742312015230 0ustar bdrungbdrunguse std::{ cell::UnsafeCell, sync::{Mutex, Once}, thread::ThreadId, }; use crate::{ exceptions::{PyBaseException, PyTypeError}, ffi, ffi_ptr_ext::FfiPtrExt, types::{PyAnyMethods, PyTraceback, PyType}, Bound, Py, PyAny, PyErrArguments, PyObject, PyTypeInfo, Python, }; pub(crate) struct PyErrState { // Safety: can only hand out references when in the "normalized" state. Will never change // after normalization. normalized: Once, // Guard against re-entrancy when normalizing the exception state. normalizing_thread: Mutex>, inner: UnsafeCell>, } // Safety: The inner value is protected by locking to ensure that only the normalized state is // handed out as a reference. unsafe impl Send for PyErrState {} unsafe impl Sync for PyErrState {} #[cfg(feature = "nightly")] unsafe impl crate::marker::Ungil for PyErrState {} impl PyErrState { pub(crate) fn lazy(f: Box) -> Self { Self::from_inner(PyErrStateInner::Lazy(f)) } pub(crate) fn lazy_arguments(ptype: Py, args: impl PyErrArguments + 'static) -> Self { Self::from_inner(PyErrStateInner::Lazy(Box::new(move |py| { PyErrStateLazyFnOutput { ptype, pvalue: args.arguments(py), } }))) } pub(crate) fn normalized(normalized: PyErrStateNormalized) -> Self { let state = Self::from_inner(PyErrStateInner::Normalized(normalized)); // This state is already normalized, by completing the Once immediately we avoid // reaching the `py.allow_threads` in `make_normalized` which is less efficient // and introduces a GIL switch which could deadlock. // See https://github.com/PyO3/pyo3/issues/4764 state.normalized.call_once(|| {}); state } pub(crate) fn restore(self, py: Python<'_>) { self.inner .into_inner() .expect("PyErr state should never be invalid outside of normalization") .restore(py) } fn from_inner(inner: PyErrStateInner) -> Self { Self { normalized: Once::new(), normalizing_thread: Mutex::new(None), inner: UnsafeCell::new(Some(inner)), } } #[inline] pub(crate) fn as_normalized(&self, py: Python<'_>) -> &PyErrStateNormalized { if self.normalized.is_completed() { match unsafe { // Safety: self.inner will never be written again once normalized. &*self.inner.get() } { Some(PyErrStateInner::Normalized(n)) => return n, _ => unreachable!(), } } self.make_normalized(py) } #[cold] fn make_normalized(&self, py: Python<'_>) -> &PyErrStateNormalized { // This process is safe because: // - Access is guaranteed not to be concurrent thanks to `Python` GIL token // - Write happens only once, and then never will change again. // Guard against re-entrant normalization, because `Once` does not provide // re-entrancy guarantees. if let Some(thread) = self.normalizing_thread.lock().unwrap().as_ref() { assert!( !(*thread == std::thread::current().id()), "Re-entrant normalization of PyErrState detected" ); } // avoid deadlock of `.call_once` with the GIL py.allow_threads(|| { self.normalized.call_once(|| { self.normalizing_thread .lock() .unwrap() .replace(std::thread::current().id()); // Safety: no other thread can access the inner value while we are normalizing it. let state = unsafe { (*self.inner.get()) .take() .expect("Cannot normalize a PyErr while already normalizing it.") }; let normalized_state = Python::with_gil(|py| PyErrStateInner::Normalized(state.normalize(py))); // Safety: no other thread can access the inner value while we are normalizing it. unsafe { *self.inner.get() = Some(normalized_state); } }) }); match unsafe { // Safety: self.inner will never be written again once normalized. &*self.inner.get() } { Some(PyErrStateInner::Normalized(n)) => n, _ => unreachable!(), } } } pub(crate) struct PyErrStateNormalized { #[cfg(not(Py_3_12))] ptype: Py, pub pvalue: Py, #[cfg(not(Py_3_12))] ptraceback: Option>, } impl PyErrStateNormalized { pub(crate) fn new(pvalue: Bound<'_, PyBaseException>) -> Self { Self { #[cfg(not(Py_3_12))] ptype: pvalue.get_type().into(), #[cfg(not(Py_3_12))] ptraceback: unsafe { Py::from_owned_ptr_or_opt( pvalue.py(), ffi::PyException_GetTraceback(pvalue.as_ptr()), ) }, pvalue: pvalue.into(), } } #[cfg(not(Py_3_12))] pub(crate) fn ptype<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> { self.ptype.bind(py).clone() } #[cfg(Py_3_12)] pub(crate) fn ptype<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> { self.pvalue.bind(py).get_type() } #[cfg(not(Py_3_12))] pub(crate) fn ptraceback<'py>(&self, py: Python<'py>) -> Option> { self.ptraceback .as_ref() .map(|traceback| traceback.bind(py).clone()) } #[cfg(Py_3_12)] pub(crate) fn ptraceback<'py>(&self, py: Python<'py>) -> Option> { unsafe { ffi::PyException_GetTraceback(self.pvalue.as_ptr()) .assume_owned_or_opt(py) .map(|b| b.downcast_into_unchecked()) } } pub(crate) fn take(py: Python<'_>) -> Option { #[cfg(Py_3_12)] { // Safety: PyErr_GetRaisedException can be called when attached to Python and // returns either NULL or an owned reference. unsafe { ffi::PyErr_GetRaisedException().assume_owned_or_opt(py) }.map(|pvalue| { PyErrStateNormalized { // Safety: PyErr_GetRaisedException returns a valid exception type. pvalue: unsafe { pvalue.downcast_into_unchecked() }.unbind(), } }) } #[cfg(not(Py_3_12))] { let (ptype, pvalue, ptraceback) = unsafe { let mut ptype: *mut ffi::PyObject = std::ptr::null_mut(); let mut pvalue: *mut ffi::PyObject = std::ptr::null_mut(); let mut ptraceback: *mut ffi::PyObject = std::ptr::null_mut(); ffi::PyErr_Fetch(&mut ptype, &mut pvalue, &mut ptraceback); // Ensure that the exception coming from the interpreter is normalized. if !ptype.is_null() { ffi::PyErr_NormalizeException(&mut ptype, &mut pvalue, &mut ptraceback); } // Safety: PyErr_NormalizeException will have produced up to three owned // references of the correct types. ( ptype .assume_owned_or_opt(py) .map(|b| b.downcast_into_unchecked()), pvalue .assume_owned_or_opt(py) .map(|b| b.downcast_into_unchecked()), ptraceback .assume_owned_or_opt(py) .map(|b| b.downcast_into_unchecked()), ) }; ptype.map(|ptype| PyErrStateNormalized { ptype: ptype.unbind(), pvalue: pvalue.expect("normalized exception value missing").unbind(), ptraceback: ptraceback.map(Bound::unbind), }) } } #[cfg(not(Py_3_12))] unsafe fn from_normalized_ffi_tuple( py: Python<'_>, ptype: *mut ffi::PyObject, pvalue: *mut ffi::PyObject, ptraceback: *mut ffi::PyObject, ) -> Self { PyErrStateNormalized { ptype: unsafe { Py::from_owned_ptr_or_opt(py, ptype).expect("Exception type missing") }, pvalue: unsafe { Py::from_owned_ptr_or_opt(py, pvalue).expect("Exception value missing") }, ptraceback: unsafe { Py::from_owned_ptr_or_opt(py, ptraceback) }, } } pub fn clone_ref(&self, py: Python<'_>) -> Self { Self { #[cfg(not(Py_3_12))] ptype: self.ptype.clone_ref(py), pvalue: self.pvalue.clone_ref(py), #[cfg(not(Py_3_12))] ptraceback: self .ptraceback .as_ref() .map(|ptraceback| ptraceback.clone_ref(py)), } } } pub(crate) struct PyErrStateLazyFnOutput { pub(crate) ptype: PyObject, pub(crate) pvalue: PyObject, } pub(crate) type PyErrStateLazyFn = dyn for<'py> FnOnce(Python<'py>) -> PyErrStateLazyFnOutput + Send + Sync; enum PyErrStateInner { Lazy(Box), Normalized(PyErrStateNormalized), } impl PyErrStateInner { fn normalize(self, py: Python<'_>) -> PyErrStateNormalized { match self { #[cfg(not(Py_3_12))] PyErrStateInner::Lazy(lazy) => { let (ptype, pvalue, ptraceback) = lazy_into_normalized_ffi_tuple(py, lazy); unsafe { PyErrStateNormalized::from_normalized_ffi_tuple(py, ptype, pvalue, ptraceback) } } #[cfg(Py_3_12)] PyErrStateInner::Lazy(lazy) => { // To keep the implementation simple, just write the exception into the interpreter, // which will cause it to be normalized raise_lazy(py, lazy); PyErrStateNormalized::take(py) .expect("exception missing after writing to the interpreter") } PyErrStateInner::Normalized(normalized) => normalized, } } #[cfg(not(Py_3_12))] fn restore(self, py: Python<'_>) { let (ptype, pvalue, ptraceback) = match self { PyErrStateInner::Lazy(lazy) => lazy_into_normalized_ffi_tuple(py, lazy), PyErrStateInner::Normalized(PyErrStateNormalized { ptype, pvalue, ptraceback, }) => ( ptype.into_ptr(), pvalue.into_ptr(), ptraceback.map_or(std::ptr::null_mut(), Py::into_ptr), ), }; unsafe { ffi::PyErr_Restore(ptype, pvalue, ptraceback) } } #[cfg(Py_3_12)] fn restore(self, py: Python<'_>) { match self { PyErrStateInner::Lazy(lazy) => raise_lazy(py, lazy), PyErrStateInner::Normalized(PyErrStateNormalized { pvalue }) => unsafe { ffi::PyErr_SetRaisedException(pvalue.into_ptr()) }, } } } #[cfg(not(Py_3_12))] fn lazy_into_normalized_ffi_tuple( py: Python<'_>, lazy: Box, ) -> (*mut ffi::PyObject, *mut ffi::PyObject, *mut ffi::PyObject) { // To be consistent with 3.12 logic, go via raise_lazy, but also then normalize // the resulting exception raise_lazy(py, lazy); let mut ptype = std::ptr::null_mut(); let mut pvalue = std::ptr::null_mut(); let mut ptraceback = std::ptr::null_mut(); unsafe { ffi::PyErr_Fetch(&mut ptype, &mut pvalue, &mut ptraceback); ffi::PyErr_NormalizeException(&mut ptype, &mut pvalue, &mut ptraceback); } (ptype, pvalue, ptraceback) } /// Raises a "lazy" exception state into the Python interpreter. /// /// In principle this could be split in two; first a function to create an exception /// in a normalized state, and then a call to `PyErr_SetRaisedException` to raise it. /// /// This would require either moving some logic from C to Rust, or requesting a new /// API in CPython. fn raise_lazy(py: Python<'_>, lazy: Box) { let PyErrStateLazyFnOutput { ptype, pvalue } = lazy(py); unsafe { if ffi::PyExceptionClass_Check(ptype.as_ptr()) == 0 { ffi::PyErr_SetString( PyTypeError::type_object_raw(py).cast(), ffi::c_str!("exceptions must derive from BaseException").as_ptr(), ) } else { ffi::PyErr_SetObject(ptype.as_ptr(), pvalue.as_ptr()) } } } #[cfg(test)] mod tests { use crate::{ exceptions::PyValueError, sync::GILOnceCell, PyErr, PyErrArguments, PyObject, Python, }; #[test] #[should_panic(expected = "Re-entrant normalization of PyErrState detected")] fn test_reentrant_normalization() { static ERR: GILOnceCell = GILOnceCell::new(); struct RecursiveArgs; impl PyErrArguments for RecursiveArgs { fn arguments(self, py: Python<'_>) -> PyObject { // .value(py) triggers normalization ERR.get(py) .expect("is set just below") .value(py) .clone() .into() } } Python::with_gil(|py| { ERR.set(py, PyValueError::new_err(RecursiveArgs)).unwrap(); ERR.get(py).expect("is set just above").value(py); }) } #[test] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled fn test_no_deadlock_thread_switch() { static ERR: GILOnceCell = GILOnceCell::new(); struct GILSwitchArgs; impl PyErrArguments for GILSwitchArgs { fn arguments(self, py: Python<'_>) -> PyObject { // releasing the GIL potentially allows for other threads to deadlock // with the normalization going on here py.allow_threads(|| { std::thread::sleep(std::time::Duration::from_millis(10)); }); py.None() } } Python::with_gil(|py| ERR.set(py, PyValueError::new_err(GILSwitchArgs)).unwrap()); // Let many threads attempt to read the normalized value at the same time let handles = (0..10) .map(|_| { std::thread::spawn(|| { Python::with_gil(|py| { ERR.get(py).expect("is set just above").value(py); }); }) }) .collect::>(); for handle in handles { handle.join().unwrap(); } // We should never have deadlocked, and should be able to run // this assertion Python::with_gil(|py| { assert!(ERR .get(py) .expect("is set above") .is_instance_of::(py)) }); } } pyo3/src/err/impls.rs0000644000175000017500000001723615105742312014356 0ustar bdrungbdrunguse crate::IntoPyObject; use crate::{err::PyErrArguments, exceptions, PyErr, PyObject, Python}; use std::io; /// Convert `PyErr` to `io::Error` impl From for io::Error { fn from(err: PyErr) -> Self { let kind = Python::with_gil(|py| { if err.is_instance_of::(py) { io::ErrorKind::BrokenPipe } else if err.is_instance_of::(py) { io::ErrorKind::ConnectionRefused } else if err.is_instance_of::(py) { io::ErrorKind::ConnectionAborted } else if err.is_instance_of::(py) { io::ErrorKind::ConnectionReset } else if err.is_instance_of::(py) { io::ErrorKind::Interrupted } else if err.is_instance_of::(py) { io::ErrorKind::NotFound } else if err.is_instance_of::(py) { io::ErrorKind::PermissionDenied } else if err.is_instance_of::(py) { io::ErrorKind::AlreadyExists } else if err.is_instance_of::(py) { io::ErrorKind::WouldBlock } else if err.is_instance_of::(py) { io::ErrorKind::TimedOut } else { #[cfg(io_error_more)] if err.is_instance_of::(py) { io::ErrorKind::IsADirectory } else if err.is_instance_of::(py) { io::ErrorKind::NotADirectory } else { io::ErrorKind::Other } #[cfg(not(io_error_more))] io::ErrorKind::Other } }); io::Error::new(kind, err) } } /// Create `PyErr` from `io::Error` /// (`OSError` except if the `io::Error` is wrapping a Python exception, /// in this case the exception is returned) impl From for PyErr { fn from(err: io::Error) -> PyErr { // If the error wraps a Python error we return it if err.get_ref().map_or(false, |e| e.is::()) { return *err.into_inner().unwrap().downcast().unwrap(); } match err.kind() { io::ErrorKind::BrokenPipe => exceptions::PyBrokenPipeError::new_err(err), io::ErrorKind::ConnectionRefused => exceptions::PyConnectionRefusedError::new_err(err), io::ErrorKind::ConnectionAborted => exceptions::PyConnectionAbortedError::new_err(err), io::ErrorKind::ConnectionReset => exceptions::PyConnectionResetError::new_err(err), io::ErrorKind::Interrupted => exceptions::PyInterruptedError::new_err(err), io::ErrorKind::NotFound => exceptions::PyFileNotFoundError::new_err(err), io::ErrorKind::PermissionDenied => exceptions::PyPermissionError::new_err(err), io::ErrorKind::AlreadyExists => exceptions::PyFileExistsError::new_err(err), io::ErrorKind::WouldBlock => exceptions::PyBlockingIOError::new_err(err), io::ErrorKind::TimedOut => exceptions::PyTimeoutError::new_err(err), #[cfg(io_error_more)] io::ErrorKind::IsADirectory => exceptions::PyIsADirectoryError::new_err(err), #[cfg(io_error_more)] io::ErrorKind::NotADirectory => exceptions::PyNotADirectoryError::new_err(err), _ => exceptions::PyOSError::new_err(err), } } } impl PyErrArguments for io::Error { fn arguments(self, py: Python<'_>) -> PyObject { //FIXME(icxolu) remove unwrap self.to_string() .into_pyobject(py) .unwrap() .into_any() .unbind() } } impl From> for PyErr { fn from(err: io::IntoInnerError) -> PyErr { err.into_error().into() } } impl PyErrArguments for io::IntoInnerError { fn arguments(self, py: Python<'_>) -> PyObject { self.into_error().arguments(py) } } impl From for PyErr { fn from(_: std::convert::Infallible) -> PyErr { unreachable!() } } macro_rules! impl_to_pyerr { ($err: ty, $pyexc: ty) => { impl PyErrArguments for $err { fn arguments(self, py: Python<'_>) -> PyObject { // FIXME(icxolu) remove unwrap self.to_string() .into_pyobject(py) .unwrap() .into_any() .unbind() } } impl std::convert::From<$err> for PyErr { fn from(err: $err) -> PyErr { <$pyexc>::new_err(err) } } }; } impl_to_pyerr!(std::array::TryFromSliceError, exceptions::PyValueError); impl_to_pyerr!(std::num::ParseIntError, exceptions::PyValueError); impl_to_pyerr!(std::num::ParseFloatError, exceptions::PyValueError); impl_to_pyerr!(std::num::TryFromIntError, exceptions::PyValueError); impl_to_pyerr!(std::str::ParseBoolError, exceptions::PyValueError); impl_to_pyerr!(std::ffi::IntoStringError, exceptions::PyUnicodeDecodeError); impl_to_pyerr!(std::ffi::NulError, exceptions::PyValueError); impl_to_pyerr!(std::str::Utf8Error, exceptions::PyUnicodeDecodeError); impl_to_pyerr!(std::string::FromUtf8Error, exceptions::PyUnicodeDecodeError); impl_to_pyerr!( std::string::FromUtf16Error, exceptions::PyUnicodeDecodeError ); impl_to_pyerr!( std::char::DecodeUtf16Error, exceptions::PyUnicodeDecodeError ); impl_to_pyerr!(std::net::AddrParseError, exceptions::PyValueError); #[cfg(test)] mod tests { use crate::{PyErr, Python}; use std::io; #[test] fn io_errors() { use crate::types::any::PyAnyMethods; let check_err = |kind, expected_ty| { Python::with_gil(|py| { let rust_err = io::Error::new(kind, "some error msg"); let py_err: PyErr = rust_err.into(); let py_err_msg = format!("{expected_ty}: some error msg"); assert_eq!(py_err.to_string(), py_err_msg); let py_error_clone = py_err.clone_ref(py); let rust_err_from_py_err: io::Error = py_err.into(); assert_eq!(rust_err_from_py_err.to_string(), py_err_msg); assert_eq!(rust_err_from_py_err.kind(), kind); let py_err_recovered_from_rust_err: PyErr = rust_err_from_py_err.into(); assert!(py_err_recovered_from_rust_err .value(py) .is(py_error_clone.value(py))); // It should be the same exception }) }; check_err(io::ErrorKind::BrokenPipe, "BrokenPipeError"); check_err(io::ErrorKind::ConnectionRefused, "ConnectionRefusedError"); check_err(io::ErrorKind::ConnectionAborted, "ConnectionAbortedError"); check_err(io::ErrorKind::ConnectionReset, "ConnectionResetError"); check_err(io::ErrorKind::Interrupted, "InterruptedError"); check_err(io::ErrorKind::NotFound, "FileNotFoundError"); check_err(io::ErrorKind::PermissionDenied, "PermissionError"); check_err(io::ErrorKind::AlreadyExists, "FileExistsError"); check_err(io::ErrorKind::WouldBlock, "BlockingIOError"); check_err(io::ErrorKind::TimedOut, "TimeoutError"); #[cfg(io_error_more)] check_err(io::ErrorKind::IsADirectory, "IsADirectoryError"); #[cfg(io_error_more)] check_err(io::ErrorKind::NotADirectory, "NotADirectoryError"); } } pyo3/src/tests/0000775000175000017500000000000015105742312013227 5ustar bdrungbdrungpyo3/src/tests/mod.rs0000644000175000017500000000043215105742312014351 0ustar bdrungbdrung#[macro_use] pub(crate) mod common { #[cfg(not(Py_GIL_DISABLED))] use crate as pyo3; include!("./common.rs"); } /// Test macro hygiene - this is in the crate since we won't have /// `pyo3` available in the crate root. #[cfg(all(test, feature = "macros"))] mod hygiene; pyo3/src/tests/hygiene/0000775000175000017500000000000015105742312014657 5ustar bdrungbdrungpyo3/src/tests/hygiene/mod.rs0000644000175000017500000000067215105742312016007 0ustar bdrungbdrung#![no_implicit_prelude] #![allow(dead_code, unused_variables, clippy::unnecessary_wraps)] // The modules in this test are used to check PyO3 macro expansion is hygienic. By locating the test // inside the crate the global `::pyo3` namespace is not available, so in combination with // #[pyo3(crate = "crate")] this validates that all macro expansion respects the setting. mod misc; mod pyclass; mod pyfunction; mod pymethods; mod pymodule; pyo3/src/tests/hygiene/pyclass.rs0000644000175000017500000000536015105742312016705 0ustar bdrungbdrung#[crate::pyclass] #[pyo3(crate = "crate")] #[derive(::std::clone::Clone)] pub struct Foo; #[crate::pyclass] #[pyo3(crate = "crate")] pub struct Foo2; #[cfg_attr(any(Py_3_9, not(Py_LIMITED_API)), crate::pyclass( name = "ActuallyBar", freelist = 8, unsendable, subclass, extends = crate::types::PyAny, module = "Spam", weakref, dict ))] #[cfg_attr(not(any(Py_3_9, not(Py_LIMITED_API))), crate::pyclass( name = "ActuallyBar", freelist = 8, unsendable, subclass, extends = crate::types::PyAny, module = "Spam" ))] #[pyo3(crate = "crate")] pub struct Bar { #[pyo3(get, set)] a: u8, #[pyo3(get, set)] b: Foo, #[pyo3(set)] c: ::std::option::Option>, } #[crate::pyclass(eq, eq_int)] #[pyo3(crate = "crate")] #[derive(PartialEq)] pub enum Enum { Var0, } #[crate::pyclass] #[pyo3(crate = "crate")] pub struct Foo3 { #[pyo3(get, set)] #[cfg(any())] field: i32, #[pyo3(get, set)] #[cfg(not(any()))] field: u32, } #[crate::pyclass] #[pyo3(crate = "crate")] pub struct Foo4 { #[pyo3(get, set)] #[cfg(any())] #[cfg(not(any()))] field: i32, #[pyo3(get, set)] #[cfg(not(any()))] field: u32, } #[crate::pyclass(eq, ord)] #[pyo3(crate = "crate")] #[derive(PartialEq, PartialOrd)] pub struct PointEqOrd { x: u32, y: u32, z: u32, } #[crate::pyclass(eq, ord)] #[pyo3(crate = "crate")] #[derive(PartialEq, PartialOrd)] pub enum ComplexEnumEqOrd { Variant1 { a: u32, b: u32 }, Variant2 { c: u32 }, } #[crate::pyclass(eq, ord)] #[pyo3(crate = "crate")] #[derive(PartialEq, PartialOrd)] pub enum TupleEnumEqOrd { Variant1(u32, u32), Variant2(u32), } #[crate::pyclass(crate = "crate")] pub enum ComplexEnumManyVariantFields { ManyStructFields { field_1: u16, field_2: u32, field_3: u32, field_4: i32, field_5: u32, field_6: u32, field_7: u8, field_8: u32, field_9: i32, field_10: u32, field_11: u32, field_12: u32, field_13: u32, field_14: i16, field_15: u32, }, ManyTupleFields( u16, u32, u32, i32, u32, u32, u8, u32, i32, u32, u32, u32, u32, i16, u32, ), } #[crate::pyclass(str = "{x}, {y}, {z}")] #[pyo3(crate = "crate")] pub struct PointFmt { x: u32, y: u32, z: u32, } #[crate::pyclass(str)] #[pyo3(crate = "crate")] pub struct Point { x: i32, y: i32, z: i32, } impl ::std::fmt::Display for Point { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::std::write!(f, "({}, {}, {})", self.x, self.y, self.z) } } pyo3/src/tests/hygiene/misc.rs0000644000175000017500000000452615105742312016165 0ustar bdrungbdrung#[derive(crate::FromPyObject)] #[pyo3(crate = "crate")] struct Derive1(i32); // newtype case #[derive(crate::FromPyObject)] #[pyo3(crate = "crate")] struct Derive2(i32, i32); // tuple case #[derive(crate::FromPyObject)] #[pyo3(crate = "crate")] struct Derive3 { f: i32, #[pyo3(item(42))] g: i32, #[pyo3(default)] h: i32, } // struct case #[derive(crate::FromPyObject)] #[pyo3(crate = "crate")] enum Derive4 { A(i32), B { f: i32 }, } // enum case crate::create_exception!(mymodule, CustomError, crate::exceptions::PyException); crate::import_exception!(socket, gaierror); fn intern(py: crate::Python<'_>) { let _foo = crate::intern!(py, "foo"); let _bar = crate::intern!(py, stringify!(bar)); } #[cfg(not(any(PyPy, GraalPy)))] fn append_to_inittab() { #[crate::pymodule] #[pyo3(crate = "crate")] mod module_for_inittab {} crate::append_to_inittab!(module_for_inittab); } macro_rules! macro_rules_hygiene { ($name_a:ident, $name_b:ident) => { #[crate::pyclass(crate = "crate")] struct $name_a {} #[crate::pymethods(crate = "crate")] impl $name_a { fn finalize(&mut self) -> $name_b { $name_b {} } } #[crate::pyclass(crate = "crate")] struct $name_b {} }; } macro_rules_hygiene!(MyClass1, MyClass2); #[derive(crate::IntoPyObject, crate::IntoPyObjectRef)] #[pyo3(crate = "crate")] struct IntoPyObject1(i32); // transparent newtype case #[derive(crate::IntoPyObject, crate::IntoPyObjectRef)] #[pyo3(crate = "crate", transparent)] struct IntoPyObject2<'a> { inner: &'a str, // transparent newtype case } #[derive(crate::IntoPyObject, crate::IntoPyObjectRef)] #[pyo3(crate = "crate")] struct IntoPyObject3<'py>(i32, crate::Bound<'py, crate::PyAny>); // tuple case #[derive(crate::IntoPyObject, crate::IntoPyObjectRef)] #[pyo3(crate = "crate")] struct IntoPyObject4<'a, 'py> { callable: &'a crate::Bound<'py, crate::PyAny>, // struct case num: usize, } #[derive(crate::IntoPyObject, crate::IntoPyObjectRef)] #[pyo3(crate = "crate")] enum IntoPyObject5<'a, 'py> { TransparentTuple(i32), #[pyo3(transparent)] TransparentStruct { f: crate::Py, }, Tuple(crate::Bound<'py, crate::types::PyString>, usize), Struct { f: i32, g: &'a str, }, } // enum case pyo3/src/tests/hygiene/pymodule.rs0000644000175000017500000000175015105742312017064 0ustar bdrungbdrung#[crate::pyfunction] #[pyo3(crate = "crate")] fn do_something(x: i32) -> crate::PyResult { ::std::result::Result::Ok(x) } #[crate::pymodule] #[pyo3(crate = "crate")] fn foo( _py: crate::Python<'_>, _m: &crate::Bound<'_, crate::types::PyModule>, ) -> crate::PyResult<()> { ::std::result::Result::Ok(()) } #[crate::pymodule] #[pyo3(crate = "crate")] fn my_module(m: &crate::Bound<'_, crate::types::PyModule>) -> crate::PyResult<()> { as crate::types::PyModuleMethods>::add_function( m, crate::wrap_pyfunction!(do_something, m)?, )?; as crate::types::PyModuleMethods>::add_wrapped( m, crate::wrap_pymodule!(foo), )?; ::std::result::Result::Ok(()) } #[crate::pymodule(submodule)] #[pyo3(crate = "crate")] mod my_module_declarative { #[pymodule_export] use super::{do_something, foo}; #[pymodule_export] const BAR: u32 = 42; } pyo3/src/tests/hygiene/pyfunction.rs0000644000175000017500000000074415105742312017426 0ustar bdrungbdrung#[crate::pyfunction] #[pyo3(crate = "crate")] fn do_something(x: i32) -> crate::PyResult { ::std::result::Result::Ok(x) } #[crate::pyfunction] #[pyo3(crate = "crate", name = "check5012")] fn check_5012(x: i32) -> crate::PyResult { ::std::result::Result::Ok(x) } #[test] fn invoke_wrap_pyfunction() { crate::Python::with_gil(|py| { let func = crate::wrap_pyfunction!(do_something, py).unwrap(); crate::py_run!(py, func, r#"func(5)"#); }); } pyo3/src/tests/hygiene/pymethods.rs0000644000175000017500000002420715105742312017244 0ustar bdrungbdrung#[crate::pyclass] #[pyo3(crate = "crate")] pub struct Dummy; #[crate::pyclass] #[pyo3(crate = "crate")] pub struct DummyIter; #[crate::pymethods] #[pyo3(crate = "crate")] impl Dummy { ////////////////////// // Basic customization ////////////////////// fn __repr__(&self) -> &'static str { "Dummy" } fn __str__(&self) -> &'static str { "Dummy" } fn __bytes__<'py>(&self, py: crate::Python<'py>) -> crate::Bound<'py, crate::types::PyBytes> { crate::types::PyBytes::new(py, &[0]) } fn __format__(&self, format_spec: ::std::string::String) -> ::std::string::String { ::std::unimplemented!() } fn __lt__(&self, other: &Self) -> bool { false } fn __le__(&self, other: &Self) -> bool { false } fn __eq__(&self, other: &Self) -> bool { false } fn __ne__(&self, other: &Self) -> bool { false } fn __gt__(&self, other: &Self) -> bool { false } fn __ge__(&self, other: &Self) -> bool { false } fn __hash__(&self) -> u64 { 42 } fn __bool__(&self) -> bool { true } ////////////////////// // Customizing attribute access ////////////////////// fn __getattr__(&self, name: ::std::string::String) -> &crate::Bound<'_, crate::PyAny> { ::std::unimplemented!() } fn __getattribute__(&self, name: ::std::string::String) -> &crate::Bound<'_, crate::PyAny> { ::std::unimplemented!() } fn __setattr__(&mut self, name: ::std::string::String, value: ::std::string::String) {} fn __delattr__(&mut self, name: ::std::string::String) {} fn __dir__<'py>( &self, py: crate::Python<'py>, ) -> crate::PyResult> { crate::types::PyList::new(py, ::std::vec![0_u8]) } ////////////////////// // Implementing Descriptors ////////////////////// fn __get__( &self, instance: &crate::Bound<'_, crate::PyAny>, owner: &crate::Bound<'_, crate::PyAny>, ) -> crate::PyResult<&crate::Bound<'_, crate::PyAny>> { ::std::unimplemented!() } fn __set__( &self, instance: &crate::Bound<'_, crate::PyAny>, owner: &crate::Bound<'_, crate::PyAny>, ) { } fn __delete__(&self, instance: &crate::Bound<'_, crate::PyAny>) {} fn __set_name__( &self, owner: &crate::Bound<'_, crate::PyAny>, name: &crate::Bound<'_, crate::PyAny>, ) { } ////////////////////// // Implementing Descriptors ////////////////////// fn __len__(&self) -> usize { 0 } fn __getitem__(&self, key: u32) -> crate::PyResult { ::std::result::Result::Err(crate::exceptions::PyKeyError::new_err("boo")) } fn __setitem__(&self, key: u32, value: u32) {} fn __delitem__(&self, key: u32) {} fn __iter__(_: crate::pycell::PyRef<'_, Self>, py: crate::Python<'_>) -> crate::Py { crate::Py::new(py, DummyIter {}).unwrap() } fn __next__(&mut self) -> ::std::option::Option<()> { ::std::option::Option::None } fn __reversed__( slf: crate::pycell::PyRef<'_, Self>, py: crate::Python<'_>, ) -> crate::Py { crate::Py::new(py, DummyIter {}).unwrap() } fn __contains__(&self, item: u32) -> bool { false } ////////////////////// // Emulating numeric types ////////////////////// fn __add__(&self, other: &Self) -> Dummy { Dummy {} } fn __sub__(&self, other: &Self) -> Dummy { Dummy {} } fn __mul__(&self, other: &Self) -> Dummy { Dummy {} } fn __truediv__(&self, _other: &Self) -> crate::PyResult<()> { ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo")) } fn __floordiv__(&self, _other: &Self) -> crate::PyResult<()> { ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo")) } fn __mod__(&self, _other: &Self) -> u32 { 0 } fn __divmod__(&self, _other: &Self) -> (u32, u32) { (0, 0) } fn __pow__(&self, _other: &Self, modulo: ::std::option::Option) -> Dummy { Dummy {} } fn __lshift__(&self, other: &Self) -> Dummy { Dummy {} } fn __rshift__(&self, other: &Self) -> Dummy { Dummy {} } fn __and__(&self, other: &Self) -> Dummy { Dummy {} } fn __xor__(&self, other: &Self) -> Dummy { Dummy {} } fn __or__(&self, other: &Self) -> Dummy { Dummy {} } fn __radd__(&self, other: &Self) -> Dummy { Dummy {} } fn __rrsub__(&self, other: &Self) -> Dummy { Dummy {} } fn __rmul__(&self, other: &Self) -> Dummy { Dummy {} } fn __rtruediv__(&self, _other: &Self) -> crate::PyResult<()> { ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo")) } fn __rfloordiv__(&self, _other: &Self) -> crate::PyResult<()> { ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo")) } fn __rmod__(&self, _other: &Self) -> u32 { 0 } fn __rdivmod__(&self, _other: &Self) -> (u32, u32) { (0, 0) } fn __rpow__(&self, _other: &Self, modulo: ::std::option::Option) -> Dummy { Dummy {} } fn __rlshift__(&self, other: &Self) -> Dummy { Dummy {} } fn __rrshift__(&self, other: &Self) -> Dummy { Dummy {} } fn __rand__(&self, other: &Self) -> Dummy { Dummy {} } fn __rxor__(&self, other: &Self) -> Dummy { Dummy {} } fn __ror__(&self, other: &Self) -> Dummy { Dummy {} } fn __iadd__(&mut self, other: &Self) {} fn __irsub__(&mut self, other: &Self) {} fn __imul__(&mut self, other: &Self) {} fn __itruediv__(&mut self, _other: &Self) {} fn __ifloordiv__(&mut self, _other: &Self) {} fn __imod__(&mut self, _other: &Self) {} fn __ipow__(&mut self, _other: &Self, modulo: ::std::option::Option) {} fn __ilshift__(&mut self, other: &Self) {} fn __irshift__(&mut self, other: &Self) {} fn __iand__(&mut self, other: &Self) {} fn __ixor__(&mut self, other: &Self) {} fn __ior__(&mut self, other: &Self) {} fn __neg__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } fn __pos__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } fn __abs__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } fn __invert__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } fn __complex__<'py>( &self, py: crate::Python<'py>, ) -> crate::Bound<'py, crate::types::PyComplex> { crate::types::PyComplex::from_doubles(py, 0.0, 0.0) } fn __int__(&self) -> u32 { 0 } fn __float__(&self) -> f64 { 0.0 } fn __index__(&self) -> u32 { 0 } #[pyo3(signature=(ndigits=::std::option::Option::None))] fn __round__(&self, ndigits: ::std::option::Option) -> u32 { 0 } fn __trunc__(&self) -> u32 { 0 } fn __floor__(&self) -> u32 { 0 } fn __ceil__(&self) -> u32 { 0 } ////////////////////// // With Statement Context Managers ////////////////////// fn __enter__(&mut self) {} fn __exit__( &mut self, exc_type: &crate::Bound<'_, crate::PyAny>, exc_value: &crate::Bound<'_, crate::PyAny>, traceback: &crate::Bound<'_, crate::PyAny>, ) { } ////////////////////// // Awaitable Objects ////////////////////// fn __await__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } ////////////////////// // Asynchronous Iterators ////////////////////// fn __aiter__( slf: crate::pycell::PyRef<'_, Self>, py: crate::Python<'_>, ) -> crate::Py { crate::Py::new(py, DummyIter {}).unwrap() } fn __anext__(&mut self) -> ::std::option::Option<()> { ::std::option::Option::None } ////////////////////// // Asynchronous Context Managers ////////////////////// fn __aenter__(&mut self) {} fn __aexit__( &mut self, exc_type: &crate::Bound<'_, crate::PyAny>, exc_value: &crate::Bound<'_, crate::PyAny>, traceback: &crate::Bound<'_, crate::PyAny>, ) { } // Things with attributes #[pyo3(signature = (_y, *, _z=2))] fn test(&self, _y: &Dummy, _z: i32) {} #[staticmethod] fn staticmethod() {} #[classmethod] fn clsmethod(_: &crate::Bound<'_, crate::types::PyType>) {} #[pyo3(signature = (*_args, **_kwds))] fn __call__( &self, _args: &crate::Bound<'_, crate::types::PyTuple>, _kwds: ::std::option::Option<&crate::Bound<'_, crate::types::PyDict>>, ) -> crate::PyResult { ::std::unimplemented!() } #[new] fn new(a: u8) -> Self { Dummy {} } #[getter] fn get(&self) -> i32 { 0 } #[setter] fn set(&mut self, _v: i32) {} #[classattr] fn class_attr() -> i32 { 0 } // Dunder methods invented for protocols // PyGcProtocol // Buffer protocol? } #[crate::pyclass(crate = "crate")] struct Clear; #[crate::pymethods(crate = "crate")] impl Clear { pub fn __traverse__( &self, visit: crate::PyVisit<'_>, ) -> ::std::result::Result<(), crate::PyTraverseError> { ::std::result::Result::Ok(()) } pub fn __clear__(&self) {} #[pyo3(signature=(*, reuse=false))] pub fn clear(&self, reuse: bool) {} } // Ensure that crate argument is also accepted inline #[crate::pyclass(crate = "crate")] struct Dummy2; #[crate::pymethods(crate = "crate")] impl Dummy2 { #[classmethod] fn __len__(cls: &crate::Bound<'_, crate::types::PyType>) -> crate::PyResult { ::std::result::Result::Ok(0) } #[staticmethod] fn __repr__() -> &'static str { "Dummy" } } pyo3/src/tests/common.rs0000644000175000017500000001472115105742312015070 0ustar bdrungbdrung// the inner mod enables the #![allow(dead_code)] to // be applied - `test_utils.rs` uses `include!` to pull in this file /// Common macros and helpers for tests #[allow(dead_code)] // many tests do not use the complete set of functionality offered here #[allow(missing_docs)] // only used in tests #[macro_use] mod inner { #[allow(unused_imports)] // pulls in `use crate as pyo3` in `test_utils.rs` use super::*; #[cfg(not(Py_GIL_DISABLED))] use pyo3::prelude::*; #[cfg(not(Py_GIL_DISABLED))] use pyo3::types::{IntoPyDict, PyList}; use uuid::Uuid; #[macro_export] macro_rules! py_assert { ($py:expr, $($val:ident)+, $assertion:literal) => { pyo3::py_run!($py, $($val)+, concat!("assert ", $assertion)) }; ($py:expr, *$dict:expr, $assertion:literal) => { pyo3::py_run!($py, *$dict, concat!("assert ", $assertion)) }; } #[macro_export] macro_rules! assert_py_eq { ($val:expr, $expected:expr) => { assert!($val.eq($expected).unwrap()); }; } #[macro_export] macro_rules! py_expect_exception { // Case1: idents & no err_msg ($py:expr, $($val:ident)+, $code:expr, $err:ident) => {{ use pyo3::types::IntoPyDict; use pyo3::BoundObject; let d = [$((stringify!($val), (&$val).into_pyobject($py).unwrap().into_any().into_bound()),)+].into_py_dict($py).unwrap(); py_expect_exception!($py, *d, $code, $err) }}; // Case2: dict & no err_msg ($py:expr, *$dict:expr, $code:expr, $err:ident) => {{ let res = $py.run(&std::ffi::CString::new($code).unwrap(), None, Some(&$dict.as_borrowed())); let err = res.expect_err(&format!("Did not raise {}", stringify!($err))); if !err.matches($py, $py.get_type::()).unwrap() { panic!("Expected {} but got {:?}", stringify!($err), err) } err }}; // Case3: idents & err_msg ($py:expr, $($val:ident)+, $code:expr, $err:ident, $err_msg:literal) => {{ let err = py_expect_exception!($py, $($val)+, $code, $err); // Suppose that the error message looks like 'TypeError: ~' assert_eq!(format!("Py{}", err), concat!(stringify!($err), ": ", $err_msg)); err }}; // Case4: dict & err_msg ($py:expr, *$dict:expr, $code:expr, $err:ident, $err_msg:literal) => {{ let err = py_expect_exception!($py, *$dict, $code, $err); assert_eq!(format!("Py{}", err), concat!(stringify!($err), ": ", $err_msg)); err }}; } // sys.unraisablehook not available until Python 3.8 #[cfg(all(feature = "macros", Py_3_8, not(Py_GIL_DISABLED)))] #[pyclass(crate = "pyo3")] pub struct UnraisableCapture { pub capture: Option<(PyErr, PyObject)>, old_hook: Option, } #[cfg(all(feature = "macros", Py_3_8, not(Py_GIL_DISABLED)))] #[pymethods(crate = "pyo3")] impl UnraisableCapture { pub fn hook(&mut self, unraisable: Bound<'_, PyAny>) { let err = PyErr::from_value(unraisable.getattr("exc_value").unwrap()); let instance = unraisable.getattr("object").unwrap(); self.capture = Some((err, instance.into())); } } #[cfg(all(feature = "macros", Py_3_8, not(Py_GIL_DISABLED)))] impl UnraisableCapture { pub fn install(py: Python<'_>) -> Py { let sys = py.import("sys").unwrap(); let old_hook = sys.getattr("unraisablehook").unwrap().into(); let capture = Py::new( py, UnraisableCapture { capture: None, old_hook: Some(old_hook), }, ) .unwrap(); sys.setattr("unraisablehook", capture.getattr(py, "hook").unwrap()) .unwrap(); capture } pub fn uninstall(&mut self, py: Python<'_>) { let old_hook = self.old_hook.take().unwrap(); let sys = py.import("sys").unwrap(); sys.setattr("unraisablehook", old_hook).unwrap(); } } #[cfg(not(Py_GIL_DISABLED))] pub struct CatchWarnings<'py> { catch_warnings: Bound<'py, PyAny>, } #[cfg(not(Py_GIL_DISABLED))] impl<'py> CatchWarnings<'py> { pub fn enter( py: Python<'py>, f: impl FnOnce(&Bound<'py, PyList>) -> PyResult, ) -> PyResult { let warnings = py.import("warnings")?; let kwargs = [("record", true)].into_py_dict(py)?; let catch_warnings = warnings .getattr("catch_warnings")? .call((), Some(&kwargs))?; let list = catch_warnings.call_method0("__enter__")?.downcast_into()?; let _guard = Self { catch_warnings }; f(&list) } } #[cfg(not(Py_GIL_DISABLED))] impl Drop for CatchWarnings<'_> { fn drop(&mut self) { let py = self.catch_warnings.py(); self.catch_warnings .call_method1("__exit__", (py.None(), py.None(), py.None())) .unwrap(); } } #[cfg(not(Py_GIL_DISABLED))] #[macro_export] macro_rules! assert_warnings { ($py:expr, $body:expr, [$(($category:ty, $message:literal)),+] $(,)? ) => {{ $crate::tests::common::CatchWarnings::enter($py, |w| { use $crate::types::{PyListMethods, PyStringMethods}; $body; let expected_warnings = [$((<$category as $crate::type_object::PyTypeInfo>::type_object($py), $message)),+]; assert_eq!(w.len(), expected_warnings.len()); for (warning, (category, message)) in w.iter().zip(expected_warnings) { assert!(warning.getattr("category").unwrap().is(&category)); assert_eq!( warning.getattr("message").unwrap().str().unwrap().to_string_lossy(), message ); } Ok(()) }) .unwrap(); }}; } pub fn generate_unique_module_name(base: &str) -> std::ffi::CString { let uuid = Uuid::new_v4().simple().to_string(); std::ffi::CString::new(format!("{base}_{uuid}")).unwrap() } } #[allow(unused_imports)] // some tests use just the macros and none of the other functionality pub use inner::*; pyo3/src/ffi/0000775000175000017500000000000015105742312012631 5ustar bdrungbdrungpyo3/src/ffi/mod.rs0000644000175000017500000000231515105742312013755 0ustar bdrungbdrung//! Raw FFI declarations for Python's C API. //! //! This module provides low level bindings to the Python interpreter. //! It is meant for advanced users only - regular PyO3 users shouldn't //! need to interact with this module at all. //! //! The contents of this module are not documented here, as it would entail //! basically copying the documentation from CPython. Consult the [Python/C API Reference //! Manual][capi] for up-to-date documentation. //! //! # Safety //! //! The functions in this module lack individual safety documentation, but //! generally the following apply: //! - Pointer arguments have to point to a valid Python object of the correct type, //! although null pointers are sometimes valid input. //! - The vast majority can only be used safely while the GIL is held. //! - Some functions have additional safety requirements, consult the //! [Python/C API Reference Manual][capi] for more information. //! //! [capi]: https://docs.python.org/3/c-api/index.html #[cfg(test)] mod tests; // reexport raw bindings exposed in pyo3_ffi pub use pyo3_ffi::*; /// Helper to enable #\[pymethods\] to see the workaround for __ipow__ on Python 3.7 #[doc(hidden)] pub use crate::impl_::pymethods::ipowfunc; pyo3/src/ffi/tests.rs0000644000175000017500000002414015105742312014340 0ustar bdrungbdrunguse crate::ffi::{self, *}; use crate::types::any::PyAnyMethods; use crate::Python; #[cfg(all(not(Py_LIMITED_API), any(not(any(PyPy, GraalPy)), feature = "macros")))] use crate::types::PyString; #[cfg(not(Py_LIMITED_API))] use crate::{types::PyDict, Bound, PyAny}; #[cfg(not(any(Py_3_12, Py_LIMITED_API, GraalPy)))] use libc::wchar_t; #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons #[test] fn test_datetime_fromtimestamp() { use crate::IntoPyObject; Python::with_gil(|py| { let args = (100,).into_pyobject(py).unwrap(); let dt = unsafe { PyDateTime_IMPORT(); Bound::from_owned_ptr(py, PyDateTime_FromTimestamp(args.as_ptr())) }; let locals = PyDict::new(py); locals.set_item("dt", dt).unwrap(); py.run( ffi::c_str!("import datetime; assert dt == datetime.datetime.fromtimestamp(100)"), None, Some(&locals), ) .unwrap(); }) } #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons #[test] fn test_date_fromtimestamp() { use crate::IntoPyObject; Python::with_gil(|py| { let args = (100,).into_pyobject(py).unwrap(); let dt = unsafe { PyDateTime_IMPORT(); Bound::from_owned_ptr(py, PyDate_FromTimestamp(args.as_ptr())) }; let locals = PyDict::new(py); locals.set_item("dt", dt).unwrap(); py.run( ffi::c_str!("import datetime; assert dt == datetime.date.fromtimestamp(100)"), None, Some(&locals), ) .unwrap(); }) } #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons #[test] fn test_utc_timezone() { Python::with_gil(|py| { let utc_timezone: Bound<'_, PyAny> = unsafe { PyDateTime_IMPORT(); Bound::from_borrowed_ptr(py, PyDateTime_TimeZone_UTC()) }; let locals = PyDict::new(py); locals.set_item("utc_timezone", utc_timezone).unwrap(); py.run( ffi::c_str!("import datetime; assert utc_timezone is datetime.timezone.utc"), None, Some(&locals), ) .unwrap(); }) } #[test] #[cfg(not(Py_LIMITED_API))] #[cfg(feature = "macros")] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_timezone_from_offset() { use crate::{ffi_ptr_ext::FfiPtrExt, types::PyDelta}; Python::with_gil(|py| { let delta = PyDelta::new(py, 0, 100, 0, false).unwrap(); let tz = unsafe { PyTimeZone_FromOffset(delta.as_ptr()).assume_owned(py) }; crate::py_run!( py, tz, "import datetime; assert tz == datetime.timezone(datetime.timedelta(seconds=100))" ); }) } #[test] #[cfg(not(Py_LIMITED_API))] #[cfg(feature = "macros")] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_timezone_from_offset_and_name() { use crate::{ffi_ptr_ext::FfiPtrExt, types::PyDelta}; Python::with_gil(|py| { let delta = PyDelta::new(py, 0, 100, 0, false).unwrap(); let tzname = PyString::new(py, "testtz"); let tz = unsafe { PyTimeZone_FromOffsetAndName(delta.as_ptr(), tzname.as_ptr()).assume_owned(py) }; crate::py_run!( py, tz, "import datetime; assert tz == datetime.timezone(datetime.timedelta(seconds=100), 'testtz')" ); }) } #[test] #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn ascii_object_bitfield() { let ob_base: PyObject = unsafe { std::mem::zeroed() }; #[cfg_attr(Py_3_14, allow(unused_mut, unused_variables))] let mut o = PyASCIIObject { ob_base, length: 0, #[cfg(any(Py_3_11, not(PyPy)))] hash: 0, state: 0u32, #[cfg(not(Py_3_12))] wstr: std::ptr::null_mut() as *mut wchar_t, }; #[cfg(not(Py_3_14))] unsafe { assert_eq!(o.interned(), 0); assert_eq!(o.kind(), 0); assert_eq!(o.compact(), 0); assert_eq!(o.ascii(), 0); #[cfg(not(Py_3_12))] assert_eq!(o.ready(), 0); let interned_count = if cfg!(Py_3_12) { 2 } else { 4 }; for i in 0..interned_count { o.set_interned(i); assert_eq!(o.interned(), i); } for i in 0..8 { o.set_kind(i); assert_eq!(o.kind(), i); } o.set_compact(1); assert_eq!(o.compact(), 1); o.set_ascii(1); assert_eq!(o.ascii(), 1); #[cfg(not(Py_3_12))] o.set_ready(1); #[cfg(not(Py_3_12))] assert_eq!(o.ready(), 1); #[cfg(Py_3_12)] o.set_statically_allocated(1); #[cfg(Py_3_12)] assert_eq!(o.statically_allocated(), 1); } } #[test] #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn ascii() { Python::with_gil(|py| { // This test relies on implementation details of PyString. let s = PyString::new(py, "hello, world"); let ptr = s.as_ptr(); unsafe { #[cfg(not(Py_3_14))] { let ascii_ptr = ptr as *mut PyASCIIObject; let ascii = ascii_ptr.as_ref().unwrap(); assert_eq!(ascii.interned(), 0); assert_eq!(ascii.kind(), PyUnicode_1BYTE_KIND); assert_eq!(ascii.compact(), 1); assert_eq!(ascii.ascii(), 1); #[cfg(not(Py_3_12))] assert_eq!(ascii.ready(), 1); assert_eq!(PyUnicode_IS_ASCII(ptr), 1); assert_eq!(PyUnicode_IS_COMPACT(ptr), 1); assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 1); } assert!(!PyUnicode_1BYTE_DATA(ptr).is_null()); // 2 and 4 byte macros return nonsense for this string instance. assert_eq!(PyUnicode_KIND(ptr), PyUnicode_1BYTE_KIND); #[cfg(not(Py_3_14))] assert!(!_PyUnicode_COMPACT_DATA(ptr).is_null()); // _PyUnicode_NONCOMPACT_DATA isn't valid for compact strings. assert!(!PyUnicode_DATA(ptr).is_null()); assert_eq!(PyUnicode_GET_LENGTH(ptr), s.len().unwrap() as Py_ssize_t); assert_eq!(PyUnicode_IS_READY(ptr), 1); // This has potential to mutate object. But it should be a no-op since // we're already ready. assert_eq!(PyUnicode_READY(ptr), 0); } }) } #[test] #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn ucs4() { Python::with_gil(|py| { let s = "哈哈🐈"; let py_string = PyString::new(py, s); let ptr = py_string.as_ptr(); unsafe { #[cfg(not(Py_3_14))] { let ascii_ptr = ptr as *mut PyASCIIObject; let ascii = ascii_ptr.as_ref().unwrap(); assert_eq!(ascii.interned(), 0); assert_eq!(ascii.kind(), PyUnicode_4BYTE_KIND); assert_eq!(ascii.compact(), 1); assert_eq!(ascii.ascii(), 0); #[cfg(not(Py_3_12))] assert_eq!(ascii.ready(), 1); assert_eq!(PyUnicode_IS_ASCII(ptr), 0); assert_eq!(PyUnicode_IS_COMPACT(ptr), 1); assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 0); } assert!(!PyUnicode_4BYTE_DATA(ptr).is_null()); assert_eq!(PyUnicode_KIND(ptr), PyUnicode_4BYTE_KIND); #[cfg(not(Py_3_14))] assert!(!_PyUnicode_COMPACT_DATA(ptr).is_null()); // _PyUnicode_NONCOMPACT_DATA isn't valid for compact strings. assert!(!PyUnicode_DATA(ptr).is_null()); assert_eq!( PyUnicode_GET_LENGTH(ptr), py_string.len().unwrap() as Py_ssize_t ); assert_eq!(PyUnicode_IS_READY(ptr), 1); // This has potential to mutate object. But it should be a no-op since // we're already ready. assert_eq!(PyUnicode_READY(ptr), 0); } }) } #[test] #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons #[cfg(not(all(PyPy, not(Py_3_10))))] fn test_get_tzinfo() { use crate::types::PyTzInfo; crate::Python::with_gil(|py| { use crate::types::{PyDateTime, PyTime}; let utc: &Bound<'_, _> = &PyTzInfo::utc(py).unwrap(); let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(utc)).unwrap(); assert!( unsafe { Bound::from_borrowed_ptr(py, PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) } .is(utc) ); let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap(); assert!( unsafe { Bound::from_borrowed_ptr(py, PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) } .is_none() ); let t = PyTime::new(py, 0, 0, 0, 0, Some(utc)).unwrap(); assert!( unsafe { Bound::from_borrowed_ptr(py, PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }.is(utc) ); let t = PyTime::new(py, 0, 0, 0, 0, None).unwrap(); assert!( unsafe { Bound::from_borrowed_ptr(py, PyDateTime_TIME_GET_TZINFO(t.as_ptr())) } .is_none() ); }) } #[test] fn test_inc_dec_ref() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("object()"), None, None).unwrap(); let ref_count = obj.get_refcnt(); let ptr = obj.as_ptr(); unsafe { Py_INCREF(ptr) }; assert_eq!(obj.get_refcnt(), ref_count + 1); unsafe { Py_DECREF(ptr) }; assert_eq!(obj.get_refcnt(), ref_count); }) } #[test] #[cfg(Py_3_12)] fn test_inc_dec_ref_immortal() { Python::with_gil(|py| { let obj = py.None(); let ref_count = obj.get_refcnt(py); let ptr = obj.as_ptr(); unsafe { Py_INCREF(ptr) }; assert_eq!(obj.get_refcnt(py), ref_count); unsafe { Py_DECREF(ptr) }; assert_eq!(obj.get_refcnt(py), ref_count); }) } pyo3/src/pyclass/0000775000175000017500000000000015105742312013543 5ustar bdrungbdrungpyo3/src/pyclass/create_type_object.rs0000644000175000017500000006263615105742312017756 0ustar bdrungbdrunguse crate::{ exceptions::PyTypeError, ffi, impl_::{ pycell::PyClassObject, pyclass::{ assign_sequence_item_from_mapping, get_sequence_item_from_mapping, tp_dealloc, tp_dealloc_with_gc, MaybeRuntimePyMethodDef, PyClassItemsIter, }, pymethods::{Getter, PyGetterDef, PyMethodDefType, PySetterDef, Setter, _call_clear}, trampoline::trampoline, }, internal_tricks::ptr_from_ref, types::{typeobject::PyTypeMethods, PyType}, Py, PyClass, PyResult, PyTypeInfo, Python, }; use std::{ collections::HashMap, ffi::{CStr, CString}, os::raw::{c_char, c_int, c_ulong, c_void}, ptr, }; pub(crate) struct PyClassTypeObject { pub type_object: Py, pub is_immutable_type: bool, #[allow(dead_code)] // This is purely a cache that must live as long as the type object getset_destructors: Vec, } pub(crate) fn create_type_object(py: Python<'_>) -> PyResult where T: PyClass, { // Written this way to monomorphize the majority of the logic. #[allow(clippy::too_many_arguments)] unsafe fn inner( py: Python<'_>, base: *mut ffi::PyTypeObject, dealloc: unsafe extern "C" fn(*mut ffi::PyObject), dealloc_with_gc: unsafe extern "C" fn(*mut ffi::PyObject), is_mapping: bool, is_sequence: bool, is_immutable_type: bool, doc: &'static CStr, dict_offset: Option, weaklist_offset: Option, is_basetype: bool, items_iter: PyClassItemsIter, name: &'static str, module: Option<&'static str>, size_of: usize, ) -> PyResult { unsafe { PyTypeBuilder { slots: Vec::new(), method_defs: Vec::new(), member_defs: Vec::new(), getset_builders: HashMap::new(), cleanup: Vec::new(), tp_base: base, tp_dealloc: dealloc, tp_dealloc_with_gc: dealloc_with_gc, is_mapping, is_sequence, is_immutable_type, has_new: false, has_dealloc: false, has_getitem: false, has_setitem: false, has_traverse: false, has_clear: false, dict_offset: None, class_flags: 0, #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))] buffer_procs: Default::default(), } .type_doc(doc) .offsets(dict_offset, weaklist_offset) .set_is_basetype(is_basetype) .class_items(items_iter) .build(py, name, module, size_of) } } unsafe { inner( py, T::BaseType::type_object_raw(py), tp_dealloc::, tp_dealloc_with_gc::, T::IS_MAPPING, T::IS_SEQUENCE, T::IS_IMMUTABLE_TYPE, T::doc(py)?, T::dict_offset(), T::weaklist_offset(), T::IS_BASETYPE, T::items_iter(), T::NAME, T::MODULE, std::mem::size_of::>(), ) } } type PyTypeBuilderCleanup = Box; struct PyTypeBuilder { slots: Vec, method_defs: Vec, member_defs: Vec, getset_builders: HashMap<&'static CStr, GetSetDefBuilder>, /// Used to patch the type objects for the things there's no /// PyType_FromSpec API for... there's no reason this should work, /// except for that it does and we have tests. cleanup: Vec, tp_base: *mut ffi::PyTypeObject, tp_dealloc: ffi::destructor, tp_dealloc_with_gc: ffi::destructor, is_mapping: bool, is_sequence: bool, is_immutable_type: bool, has_new: bool, has_dealloc: bool, has_getitem: bool, has_setitem: bool, has_traverse: bool, has_clear: bool, dict_offset: Option, class_flags: c_ulong, // Before Python 3.9, need to patch in buffer methods manually (they don't work in slots) #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))] buffer_procs: ffi::PyBufferProcs, } impl PyTypeBuilder { /// # Safety /// The given pointer must be of the correct type for the given slot unsafe fn push_slot(&mut self, slot: c_int, pfunc: *mut T) { match slot { ffi::Py_tp_new => self.has_new = true, ffi::Py_tp_dealloc => self.has_dealloc = true, ffi::Py_mp_subscript => self.has_getitem = true, ffi::Py_mp_ass_subscript => self.has_setitem = true, ffi::Py_tp_traverse => { self.has_traverse = true; self.class_flags |= ffi::Py_TPFLAGS_HAVE_GC; } ffi::Py_tp_clear => self.has_clear = true, #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))] ffi::Py_bf_getbuffer => { // Safety: slot.pfunc is a valid function pointer self.buffer_procs.bf_getbuffer = Some(unsafe { std::mem::transmute::<*mut T, ffi::getbufferproc>(pfunc) }); } #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))] ffi::Py_bf_releasebuffer => { // Safety: slot.pfunc is a valid function pointer self.buffer_procs.bf_releasebuffer = Some(unsafe { std::mem::transmute::<*mut T, ffi::releasebufferproc>(pfunc) }); } _ => {} } self.slots.push(ffi::PyType_Slot { slot, pfunc: pfunc as _, }); } /// # Safety /// It is the caller's responsibility that `data` is of the correct type for the given slot. unsafe fn push_raw_vec_slot(&mut self, slot: c_int, mut data: Vec) { if !data.is_empty() { // Python expects a zeroed entry to mark the end of the defs unsafe { data.push(std::mem::zeroed()); self.push_slot(slot, Box::into_raw(data.into_boxed_slice()) as *mut c_void); } } } fn pymethod_def(&mut self, def: &PyMethodDefType) { match def { PyMethodDefType::Getter(getter) => self .getset_builders .entry(getter.name) .or_default() .add_getter(getter), PyMethodDefType::Setter(setter) => self .getset_builders .entry(setter.name) .or_default() .add_setter(setter), PyMethodDefType::Method(def) | PyMethodDefType::Class(def) | PyMethodDefType::Static(def) => self.method_defs.push(def.as_method_def()), // These class attributes are added after the type gets created by LazyStaticType PyMethodDefType::ClassAttribute(_) => {} PyMethodDefType::StructMember(def) => self.member_defs.push(*def), } } fn finalize_methods_and_properties(&mut self) -> Vec { let method_defs: Vec = std::mem::take(&mut self.method_defs); // Safety: Py_tp_methods expects a raw vec of PyMethodDef unsafe { self.push_raw_vec_slot(ffi::Py_tp_methods, method_defs) }; let member_defs = std::mem::take(&mut self.member_defs); // Safety: Py_tp_members expects a raw vec of PyMemberDef unsafe { self.push_raw_vec_slot(ffi::Py_tp_members, member_defs) }; let mut getset_destructors = Vec::with_capacity(self.getset_builders.len()); #[allow(unused_mut)] let mut property_defs: Vec<_> = self .getset_builders .iter() .map(|(name, builder)| { let (def, destructor) = builder.as_get_set_def(name); getset_destructors.push(destructor); def }) .collect(); // PyPy automatically adds __dict__ getter / setter. #[cfg(not(PyPy))] // Supported on unlimited API for all versions, and on 3.9+ for limited API #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] if let Some(dict_offset) = self.dict_offset { let get_dict; let closure; // PyObject_GenericGetDict not in the limited API until Python 3.10. #[cfg(any(not(Py_LIMITED_API), Py_3_10))] { let _ = dict_offset; get_dict = ffi::PyObject_GenericGetDict; closure = ptr::null_mut(); } // ... so we write a basic implementation ourselves #[cfg(not(any(not(Py_LIMITED_API), Py_3_10)))] { extern "C" fn get_dict_impl( object: *mut ffi::PyObject, closure: *mut c_void, ) -> *mut ffi::PyObject { unsafe { trampoline(|_| { let dict_offset = closure as ffi::Py_ssize_t; // we don't support negative dict_offset here; PyO3 doesn't set it negative assert!(dict_offset > 0); // TODO: use `.byte_offset` on MSRV 1.75 let dict_ptr = object .cast::() .offset(dict_offset) .cast::<*mut ffi::PyObject>(); if (*dict_ptr).is_null() { std::ptr::write(dict_ptr, ffi::PyDict_New()); } Ok(ffi::compat::Py_XNewRef(*dict_ptr)) }) } } get_dict = get_dict_impl; closure = dict_offset as _; } property_defs.push(ffi::PyGetSetDef { name: ffi::c_str!("__dict__").as_ptr(), get: Some(get_dict), set: Some(ffi::PyObject_GenericSetDict), doc: ptr::null(), closure, }); } // Safety: Py_tp_getset expects a raw vec of PyGetSetDef unsafe { self.push_raw_vec_slot(ffi::Py_tp_getset, property_defs) }; // If mapping methods implemented, define sequence methods get implemented too. // CPython does the same for Python `class` statements. // NB we don't implement sq_length to avoid annoying CPython behaviour of automatically adding // the length to negative indices. // Don't add these methods for "pure" mappings. if !self.is_mapping && self.has_getitem { // Safety: This is the correct slot type for Py_sq_item unsafe { self.push_slot( ffi::Py_sq_item, get_sequence_item_from_mapping as *mut c_void, ) } } if !self.is_mapping && self.has_setitem { // Safety: This is the correct slot type for Py_sq_ass_item unsafe { self.push_slot( ffi::Py_sq_ass_item, assign_sequence_item_from_mapping as *mut c_void, ) } } getset_destructors } fn set_is_basetype(mut self, is_basetype: bool) -> Self { if is_basetype { self.class_flags |= ffi::Py_TPFLAGS_BASETYPE; } self } /// # Safety /// All slots in the PyClassItemsIter should be correct unsafe fn class_items(mut self, iter: PyClassItemsIter) -> Self { for items in iter { for slot in items.slots { unsafe { self.push_slot(slot.slot, slot.pfunc) }; } for method in items.methods { let built_method; let method = match method { MaybeRuntimePyMethodDef::Runtime(builder) => { built_method = builder(); &built_method } MaybeRuntimePyMethodDef::Static(method) => method, }; self.pymethod_def(method); } } self } fn type_doc(mut self, type_doc: &'static CStr) -> Self { let slice = type_doc.to_bytes(); if !slice.is_empty() { unsafe { self.push_slot(ffi::Py_tp_doc, type_doc.as_ptr() as *mut c_char) } // Running this causes PyPy to segfault. #[cfg(all(not(PyPy), not(Py_LIMITED_API), not(Py_3_10)))] { // Until CPython 3.10, tp_doc was treated specially for // heap-types, and it removed the text_signature value from it. // We go in after the fact and replace tp_doc with something // that _does_ include the text_signature value! self.cleanup .push(Box::new(move |_self, type_object| unsafe { ffi::PyObject_Free((*type_object).tp_doc as _); let data = ffi::PyMem_Malloc(slice.len()); data.copy_from(slice.as_ptr() as _, slice.len()); (*type_object).tp_doc = data as _; })) } } self } fn offsets( mut self, dict_offset: Option, #[allow(unused_variables)] weaklist_offset: Option, ) -> Self { self.dict_offset = dict_offset; #[cfg(Py_3_9)] { #[inline(always)] fn offset_def(name: &'static CStr, offset: ffi::Py_ssize_t) -> ffi::PyMemberDef { ffi::PyMemberDef { name: name.as_ptr().cast(), type_code: ffi::Py_T_PYSSIZET, offset, flags: ffi::Py_READONLY, doc: std::ptr::null_mut(), } } // __dict__ support if let Some(dict_offset) = dict_offset { self.member_defs .push(offset_def(ffi::c_str!("__dictoffset__"), dict_offset)); } // weakref support if let Some(weaklist_offset) = weaklist_offset { self.member_defs.push(offset_def( ffi::c_str!("__weaklistoffset__"), weaklist_offset, )); } } // Setting buffer protocols, tp_dictoffset and tp_weaklistoffset via slots doesn't work until // Python 3.9, so on older versions we must manually fixup the type object. #[cfg(all(not(Py_LIMITED_API), not(Py_3_9)))] { self.cleanup .push(Box::new(move |builder, type_object| unsafe { (*(*type_object).tp_as_buffer).bf_getbuffer = builder.buffer_procs.bf_getbuffer; (*(*type_object).tp_as_buffer).bf_releasebuffer = builder.buffer_procs.bf_releasebuffer; if let Some(dict_offset) = dict_offset { (*type_object).tp_dictoffset = dict_offset; } if let Some(weaklist_offset) = weaklist_offset { (*type_object).tp_weaklistoffset = weaklist_offset; } })); } self } fn build( mut self, py: Python<'_>, name: &'static str, module_name: Option<&'static str>, basicsize: usize, ) -> PyResult { // `c_ulong` and `c_uint` have the same size // on some platforms (like windows) #![allow(clippy::useless_conversion)] let getset_destructors = self.finalize_methods_and_properties(); unsafe { self.push_slot(ffi::Py_tp_base, self.tp_base) } if !self.has_new { // Safety: This is the correct slot type for Py_tp_new unsafe { self.push_slot(ffi::Py_tp_new, no_constructor_defined as *mut c_void) } } let base_is_gc = unsafe { ffi::PyType_IS_GC(self.tp_base) == 1 }; let tp_dealloc = if self.has_traverse || base_is_gc { self.tp_dealloc_with_gc } else { self.tp_dealloc }; unsafe { self.push_slot(ffi::Py_tp_dealloc, tp_dealloc as *mut c_void) } if self.has_clear && !self.has_traverse { return Err(PyTypeError::new_err(format!( "`#[pyclass]` {name} implements __clear__ without __traverse__" ))); } // If this type is a GC type, and the base also is, we may need to add // `tp_traverse` / `tp_clear` implementations to call the base, if this type didn't // define `__traverse__` or `__clear__`. // // This is because when Py_TPFLAGS_HAVE_GC is set, then `tp_traverse` and // `tp_clear` are not inherited. if ((self.class_flags & ffi::Py_TPFLAGS_HAVE_GC) != 0) && base_is_gc { // If this assertion breaks, need to consider doing the same for __traverse__. assert!(self.has_traverse); // Py_TPFLAGS_HAVE_GC is set when a `__traverse__` method is found if !self.has_clear { // Safety: This is the correct slot type for Py_tp_clear unsafe { self.push_slot(ffi::Py_tp_clear, call_super_clear as *mut c_void) } } } // For sequences, implement sq_length instead of mp_length if self.is_sequence { for slot in &mut self.slots { if slot.slot == ffi::Py_mp_length { slot.slot = ffi::Py_sq_length; } } } // Add empty sentinel at the end // Safety: python expects this empty slot unsafe { self.push_slot(0, ptr::null_mut::()) } let class_name = py_class_qualified_name(module_name, name)?; let mut spec = ffi::PyType_Spec { name: class_name.as_ptr() as _, basicsize: basicsize as c_int, itemsize: 0, flags: (ffi::Py_TPFLAGS_DEFAULT | self.class_flags) .try_into() .unwrap(), slots: self.slots.as_mut_ptr(), }; // Safety: We've correctly setup the PyType_Spec at this point let type_object: Py = unsafe { Py::from_owned_ptr_or_err(py, ffi::PyType_FromSpec(&mut spec))? }; #[cfg(not(Py_3_11))] bpo_45315_workaround(py, class_name); for cleanup in std::mem::take(&mut self.cleanup) { cleanup(&self, type_object.bind(py).as_type_ptr()); } Ok(PyClassTypeObject { type_object, is_immutable_type: self.is_immutable_type, getset_destructors, }) } } fn py_class_qualified_name(module_name: Option<&str>, class_name: &str) -> PyResult { Ok(CString::new(format!( "{}.{}", module_name.unwrap_or("builtins"), class_name ))?) } /// Workaround for Python issue 45315; no longer necessary in Python 3.11 #[inline] #[cfg(not(Py_3_11))] fn bpo_45315_workaround(py: Python<'_>, class_name: CString) { #[cfg(Py_LIMITED_API)] { // Must check version at runtime for abi3 wheels - they could run against a higher version // than the build config suggests. use crate::sync::GILOnceCell; static IS_PYTHON_3_11: GILOnceCell = GILOnceCell::new(); if *IS_PYTHON_3_11.get_or_init(py, || py.version_info() >= (3, 11)) { // No fix needed - the wheel is running on a sufficiently new interpreter. return; } } #[cfg(not(Py_LIMITED_API))] { // suppress unused variable warning let _ = py; } std::mem::forget(class_name); } /// Default new implementation unsafe extern "C" fn no_constructor_defined( subtype: *mut ffi::PyTypeObject, _args: *mut ffi::PyObject, _kwds: *mut ffi::PyObject, ) -> *mut ffi::PyObject { unsafe { trampoline(|py| { let tpobj = PyType::from_borrowed_type_ptr(py, subtype); let name = tpobj .name() .map_or_else(|_| "".into(), |name| name.to_string()); Err(crate::exceptions::PyTypeError::new_err(format!( "No constructor defined for {name}" ))) }) } } unsafe extern "C" fn call_super_clear(slf: *mut ffi::PyObject) -> c_int { unsafe { _call_clear(slf, |_, _| Ok(()), call_super_clear) } } #[derive(Default)] struct GetSetDefBuilder { doc: Option<&'static CStr>, getter: Option, setter: Option, } impl GetSetDefBuilder { fn add_getter(&mut self, getter: &PyGetterDef) { // TODO: be smarter about merging getter and setter docs if self.doc.is_none() { self.doc = Some(getter.doc); } // TODO: return an error if getter already defined? self.getter = Some(getter.meth) } fn add_setter(&mut self, setter: &PySetterDef) { // TODO: be smarter about merging getter and setter docs if self.doc.is_none() { self.doc = Some(setter.doc); } // TODO: return an error if setter already defined? self.setter = Some(setter.meth) } fn as_get_set_def(&self, name: &'static CStr) -> (ffi::PyGetSetDef, GetSetDefDestructor) { let getset_type = match (self.getter, self.setter) { (Some(getter), None) => GetSetDefType::Getter(getter), (None, Some(setter)) => GetSetDefType::Setter(setter), (Some(getter), Some(setter)) => { GetSetDefType::GetterAndSetter(Box::new(GetterAndSetter { getter, setter })) } (None, None) => { unreachable!("GetSetDefBuilder expected to always have either getter or setter") } }; let getset_def = getset_type.create_py_get_set_def(name, self.doc); let destructor = GetSetDefDestructor { closure: getset_type, }; (getset_def, destructor) } } #[allow(dead_code)] // a stack of fields which are purely to cache until dropped struct GetSetDefDestructor { closure: GetSetDefType, } /// Possible forms of property - either a getter, setter, or both enum GetSetDefType { Getter(Getter), Setter(Setter), // The box is here so that the `GetterAndSetter` has a stable // memory address even if the `GetSetDefType` enum is moved GetterAndSetter(Box), } pub(crate) struct GetterAndSetter { getter: Getter, setter: Setter, } impl GetSetDefType { /// Fills a PyGetSetDef structure /// It is only valid for as long as this GetSetDefType remains alive, /// as well as name and doc members pub(crate) fn create_py_get_set_def( &self, name: &CStr, doc: Option<&CStr>, ) -> ffi::PyGetSetDef { let (get, set, closure): (Option, Option, *mut c_void) = match self { &Self::Getter(closure) => { unsafe extern "C" fn getter( slf: *mut ffi::PyObject, closure: *mut c_void, ) -> *mut ffi::PyObject { // Safety: PyO3 sets the closure when constructing the ffi getter so this cast should always be valid let getter: Getter = unsafe { std::mem::transmute(closure) }; unsafe { trampoline(|py| getter(py, slf)) } } (Some(getter), None, closure as Getter as _) } &Self::Setter(closure) => { unsafe extern "C" fn setter( slf: *mut ffi::PyObject, value: *mut ffi::PyObject, closure: *mut c_void, ) -> c_int { // Safety: PyO3 sets the closure when constructing the ffi setter so this cast should always be valid let setter: Setter = unsafe { std::mem::transmute(closure) }; unsafe { trampoline(|py| setter(py, slf, value)) } } (None, Some(setter), closure as Setter as _) } Self::GetterAndSetter(closure) => { unsafe extern "C" fn getset_getter( slf: *mut ffi::PyObject, closure: *mut c_void, ) -> *mut ffi::PyObject { let getset: &GetterAndSetter = unsafe { &*closure.cast() }; unsafe { trampoline(|py| (getset.getter)(py, slf)) } } unsafe extern "C" fn getset_setter( slf: *mut ffi::PyObject, value: *mut ffi::PyObject, closure: *mut c_void, ) -> c_int { let getset: &GetterAndSetter = unsafe { &*closure.cast() }; unsafe { trampoline(|py| (getset.setter)(py, slf, value)) } } ( Some(getset_getter), Some(getset_setter), ptr_from_ref::(closure) as *mut _, ) } }; ffi::PyGetSetDef { name: name.as_ptr(), doc: doc.map_or(ptr::null(), CStr::as_ptr), get, set, closure, } } } pyo3/src/pyclass/gc.rs0000644000175000017500000000375615105742312014513 0ustar bdrungbdrunguse std::{ marker::PhantomData, os::raw::{c_int, c_void}, }; use crate::{ffi, Py}; /// Error returned by a `__traverse__` visitor implementation. #[repr(transparent)] pub struct PyTraverseError(NonZeroCInt); impl PyTraverseError { /// Returns the error code. pub(crate) fn into_inner(self) -> c_int { self.0.into() } } /// Object visitor for GC. #[derive(Clone)] pub struct PyVisit<'a> { pub(crate) visit: ffi::visitproc, pub(crate) arg: *mut c_void, /// Prevents the `PyVisit` from outliving the `__traverse__` call. pub(crate) _guard: PhantomData<&'a ()>, } impl PyVisit<'_> { /// Visit `obj`. /// /// Note: `obj` accepts a variety of types, including /// - `&Py` /// - `&Option>` /// - `Option<&Py>` pub fn call<'a, T, U: 'a>(&self, obj: T) -> Result<(), PyTraverseError> where T: Into>>, { let ptr = obj.into().map_or_else(std::ptr::null_mut, Py::as_ptr); if !ptr.is_null() { match NonZeroCInt::new(unsafe { (self.visit)(ptr, self.arg) }) { None => Ok(()), Some(r) => Err(PyTraverseError(r)), } } else { Ok(()) } } } /// Workaround for `NonZero` not being available until MSRV 1.79 mod get_nonzero_c_int { pub struct GetNonZeroCInt(); pub trait NonZeroCIntType { type Type; } impl NonZeroCIntType for GetNonZeroCInt<16> { type Type = std::num::NonZeroI16; } impl NonZeroCIntType for GetNonZeroCInt<32> { type Type = std::num::NonZeroI32; } pub type Type = () * 8 }> as NonZeroCIntType>::Type; } use get_nonzero_c_int::Type as NonZeroCInt; #[cfg(test)] mod tests { use super::PyVisit; use static_assertions::assert_not_impl_any; #[test] fn py_visit_not_send_sync() { assert_not_impl_any!(PyVisit<'_>: Send, Sync); } } pyo3/src/sync.rs0000644000175000017500000012111315105742312013404 0ustar bdrungbdrung//! Synchronization mechanisms based on the Python GIL. //! //! With the acceptance of [PEP 703] (aka a "freethreaded Python") for Python 3.13, these //! are likely to undergo significant developments in the future. //! //! [PEP 703]: https://peps.python.org/pep-703/ use crate::{ gil::SuspendGIL, sealed::Sealed, types::{any::PyAnyMethods, PyAny, PyString}, Bound, Py, PyResult, PyTypeCheck, Python, }; use std::{ cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit, sync::{Once, OnceState}, }; #[cfg(not(Py_GIL_DISABLED))] use crate::PyVisit; /// Value with concurrent access protected by the GIL. /// /// This is a synchronization primitive based on Python's global interpreter lock (GIL). /// It ensures that only one thread at a time can access the inner value via shared references. /// It can be combined with interior mutability to obtain mutable references. /// /// This type is not defined for extensions built against the free-threaded CPython ABI. /// /// # Example /// /// Combining `GILProtected` with `RefCell` enables mutable access to static data: /// /// ``` /// # use pyo3::prelude::*; /// use pyo3::sync::GILProtected; /// use std::cell::RefCell; /// /// static NUMBERS: GILProtected>> = GILProtected::new(RefCell::new(Vec::new())); /// /// Python::with_gil(|py| { /// NUMBERS.get(py).borrow_mut().push(42); /// }); /// ``` #[cfg(not(Py_GIL_DISABLED))] pub struct GILProtected { value: T, } #[cfg(not(Py_GIL_DISABLED))] impl GILProtected { /// Place the given value under the protection of the GIL. pub const fn new(value: T) -> Self { Self { value } } /// Gain access to the inner value by giving proof of having acquired the GIL. pub fn get<'py>(&'py self, _py: Python<'py>) -> &'py T { &self.value } /// Gain access to the inner value by giving proof that garbage collection is happening. pub fn traverse<'py>(&'py self, _visit: PyVisit<'py>) -> &'py T { &self.value } } #[cfg(not(Py_GIL_DISABLED))] unsafe impl Sync for GILProtected where T: Send {} /// A write-once primitive similar to [`std::sync::OnceLock`]. /// /// Unlike `OnceLock` which blocks threads to achieve thread safety, `GilOnceCell` /// allows calls to [`get_or_init`][GILOnceCell::get_or_init] and /// [`get_or_try_init`][GILOnceCell::get_or_try_init] to race to create an initialized value. /// (It is still guaranteed that only one thread will ever write to the cell.) /// /// On Python versions that run with the Global Interpreter Lock (GIL), this helps to avoid /// deadlocks between initialization and the GIL. For an example of such a deadlock, see #[doc = concat!( "[the FAQ section](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/faq.html#im-experiencing-deadlocks-using-pyo3-with-stdsynconcelock-stdsynclazylock-lazy_static-and-once_cell)" )] /// of the guide. /// /// Note that because the GIL blocks concurrent execution, in practice the means that /// [`get_or_init`][GILOnceCell::get_or_init] and /// [`get_or_try_init`][GILOnceCell::get_or_try_init] may race if the initialization /// function leads to the GIL being released and a thread context switch. This can /// happen when importing or calling any Python code, as long as it releases the /// GIL at some point. On free-threaded Python without any GIL, the race is /// more likely since there is no GIL to prevent races. In the future, PyO3 may change /// the semantics of GILOnceCell to behave more like the GIL build in the future. /// /// # Re-entrant initialization /// /// [`get_or_init`][GILOnceCell::get_or_init] and /// [`get_or_try_init`][GILOnceCell::get_or_try_init] do not protect against infinite recursion /// from reentrant initialization. /// /// # Examples /// /// The following example shows how to use `GILOnceCell` to share a reference to a Python list /// between threads: /// /// ``` /// use pyo3::sync::GILOnceCell; /// use pyo3::prelude::*; /// use pyo3::types::PyList; /// /// static LIST_CELL: GILOnceCell> = GILOnceCell::new(); /// /// pub fn get_shared_list(py: Python<'_>) -> &Bound<'_, PyList> { /// LIST_CELL /// .get_or_init(py, || PyList::empty(py).unbind()) /// .bind(py) /// } /// # Python::with_gil(|py| assert_eq!(get_shared_list(py).len(), 0)); /// ``` pub struct GILOnceCell { once: Once, data: UnsafeCell>, /// (Copied from std::sync::OnceLock) /// /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl. /// /// ```compile_error,E0597 /// use pyo3::Python; /// use pyo3::sync::GILOnceCell; /// /// struct A<'a>(#[allow(dead_code)] &'a str); /// /// impl<'a> Drop for A<'a> { /// fn drop(&mut self) {} /// } /// /// let cell = GILOnceCell::new(); /// { /// let s = String::new(); /// let _ = Python::with_gil(|py| cell.set(py,A(&s))); /// } /// ``` _marker: PhantomData, } impl Default for GILOnceCell { fn default() -> Self { Self::new() } } // T: Send is needed for Sync because the thread which drops the GILOnceCell can be different // to the thread which fills it. (e.g. think scoped thread which fills the cell and then exits, // leaving the cell to be dropped by the main thread). unsafe impl Sync for GILOnceCell {} unsafe impl Send for GILOnceCell {} impl GILOnceCell { /// Create a `GILOnceCell` which does not yet contain a value. pub const fn new() -> Self { Self { once: Once::new(), data: UnsafeCell::new(MaybeUninit::uninit()), _marker: PhantomData, } } /// Get a reference to the contained value, or `None` if the cell has not yet been written. #[inline] pub fn get(&self, _py: Python<'_>) -> Option<&T> { if self.once.is_completed() { // SAFETY: the cell has been written. Some(unsafe { (*self.data.get()).assume_init_ref() }) } else { None } } /// Get a reference to the contained value, initializing it if needed using the provided /// closure. /// /// See the type-level documentation for detail on re-entrancy and concurrent initialization. #[inline] pub fn get_or_init(&self, py: Python<'_>, f: F) -> &T where F: FnOnce() -> T, { if let Some(value) = self.get(py) { return value; } // .unwrap() will never panic because the result is always Ok self.init(py, || Ok::(f())) .unwrap() } /// Like `get_or_init`, but accepts a fallible initialization function. If it fails, the cell /// is left uninitialized. /// /// See the type-level documentation for detail on re-entrancy and concurrent initialization. #[inline] pub fn get_or_try_init(&self, py: Python<'_>, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { if let Some(value) = self.get(py) { return Ok(value); } self.init(py, f) } #[cold] fn init(&self, py: Python<'_>, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { // Note that f() could temporarily release the GIL, so it's possible that another thread // writes to this GILOnceCell before f() finishes. That's fine; we'll just have to discard // the value computed here and accept a bit of wasted computation. // TODO: on the freethreaded build, consider wrapping this pair of operations in a // critical section (requires a critical section API which can use a PyMutex without // an object.) let value = f()?; let _ = self.set(py, value); Ok(self.get(py).unwrap()) } /// Get the contents of the cell mutably. This is only possible if the reference to the cell is /// unique. pub fn get_mut(&mut self) -> Option<&mut T> { if self.once.is_completed() { // SAFETY: the cell has been written. Some(unsafe { (*self.data.get()).assume_init_mut() }) } else { None } } /// Set the value in the cell. /// /// If the cell has already been written, `Err(value)` will be returned containing the new /// value which was not written. pub fn set(&self, _py: Python<'_>, value: T) -> Result<(), T> { let mut value = Some(value); // NB this can block, but since this is only writing a single value and // does not call arbitrary python code, we don't need to worry about // deadlocks with the GIL. self.once.call_once_force(|_| { // SAFETY: no other threads can be writing this value, because we are // inside the `call_once_force` closure. unsafe { // `.take().unwrap()` will never panic (*self.data.get()).write(value.take().unwrap()); } }); match value { // Some other thread wrote to the cell first Some(value) => Err(value), None => Ok(()), } } /// Takes the value out of the cell, moving it back to an uninitialized state. /// /// Has no effect and returns None if the cell has not yet been written. pub fn take(&mut self) -> Option { if self.once.is_completed() { // Reset the cell to its default state so that it won't try to // drop the value again. self.once = Once::new(); // SAFETY: the cell has been written. `self.once` has been reset, // so when `self` is dropped the value won't be read again. Some(unsafe { self.data.get_mut().assume_init_read() }) } else { None } } /// Consumes the cell, returning the wrapped value. /// /// Returns None if the cell has not yet been written. pub fn into_inner(mut self) -> Option { self.take() } } impl GILOnceCell> { /// Creates a new cell that contains a new Python reference to the same contained object. /// /// Returns an uninitialized cell if `self` has not yet been initialized. pub fn clone_ref(&self, py: Python<'_>) -> Self { let cloned = Self { once: Once::new(), data: UnsafeCell::new(MaybeUninit::uninit()), _marker: PhantomData, }; if let Some(value) = self.get(py) { let _ = cloned.set(py, value.clone_ref(py)); } cloned } } impl GILOnceCell> where T: PyTypeCheck, { /// Get a reference to the contained Python type, initializing the cell if needed. /// /// This is a shorthand method for `get_or_init` which imports the type from Python on init. /// /// # Example: Using `GILOnceCell` to store a class in a static variable. /// /// `GILOnceCell` can be used to avoid importing a class multiple times: /// ``` /// # use pyo3::prelude::*; /// # use pyo3::sync::GILOnceCell; /// # use pyo3::types::{PyDict, PyType}; /// # use pyo3::intern; /// # /// #[pyfunction] /// fn create_ordered_dict<'py>(py: Python<'py>, dict: Bound<'py, PyDict>) -> PyResult> { /// // Even if this function is called multiple times, /// // the `OrderedDict` class will be imported only once. /// static ORDERED_DICT: GILOnceCell> = GILOnceCell::new(); /// ORDERED_DICT /// .import(py, "collections", "OrderedDict")? /// .call1((dict,)) /// } /// /// # Python::with_gil(|py| { /// # let dict = PyDict::new(py); /// # dict.set_item(intern!(py, "foo"), 42).unwrap(); /// # let fun = wrap_pyfunction!(create_ordered_dict, py).unwrap(); /// # let ordered_dict = fun.call1((&dict,)).unwrap(); /// # assert!(dict.eq(ordered_dict).unwrap()); /// # }); /// ``` pub fn import<'py>( &self, py: Python<'py>, module_name: &str, attr_name: &str, ) -> PyResult<&Bound<'py, T>> { self.get_or_try_init(py, || { let type_object = py .import(module_name)? .getattr(attr_name)? .downcast_into()?; Ok(type_object.unbind()) }) .map(|ty| ty.bind(py)) } } impl Drop for GILOnceCell { fn drop(&mut self) { if self.once.is_completed() { // SAFETY: the cell has been written. unsafe { MaybeUninit::assume_init_drop(self.data.get_mut()) } } } } /// Interns `text` as a Python string and stores a reference to it in static storage. /// /// A reference to the same Python string is returned on each invocation. /// /// # Example: Using `intern!` to avoid needlessly recreating the same Python string /// /// ``` /// use pyo3::intern; /// # use pyo3::{prelude::*, types::PyDict}; /// /// #[pyfunction] /// fn create_dict(py: Python<'_>) -> PyResult> { /// let dict = PyDict::new(py); /// // 👇 A new `PyString` is created /// // for every call of this function. /// dict.set_item("foo", 42)?; /// Ok(dict) /// } /// /// #[pyfunction] /// fn create_dict_faster(py: Python<'_>) -> PyResult> { /// let dict = PyDict::new(py); /// // 👇 A `PyString` is created once and reused /// // for the lifetime of the program. /// dict.set_item(intern!(py, "foo"), 42)?; /// Ok(dict) /// } /// # /// # Python::with_gil(|py| { /// # let fun_slow = wrap_pyfunction!(create_dict, py).unwrap(); /// # let dict = fun_slow.call0().unwrap(); /// # assert!(dict.contains("foo").unwrap()); /// # let fun = wrap_pyfunction!(create_dict_faster, py).unwrap(); /// # let dict = fun.call0().unwrap(); /// # assert!(dict.contains("foo").unwrap()); /// # }); /// ``` #[macro_export] macro_rules! intern { ($py: expr, $text: expr) => {{ static INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text); INTERNED.get($py) }}; } /// Implementation detail for `intern!` macro. #[doc(hidden)] pub struct Interned(&'static str, GILOnceCell>); impl Interned { /// Creates an empty holder for an interned `str`. pub const fn new(value: &'static str) -> Self { Interned(value, GILOnceCell::new()) } /// Gets or creates the interned `str` value. #[inline] pub fn get<'py>(&self, py: Python<'py>) -> &Bound<'py, PyString> { self.1 .get_or_init(py, || PyString::intern(py, self.0).into()) .bind(py) } } /// Executes a closure with a Python critical section held on an object. /// /// Acquires the per-object lock for the object `op` that is held /// until the closure `f` is finished. /// /// This is structurally equivalent to the use of the paired /// Py_BEGIN_CRITICAL_SECTION and Py_END_CRITICAL_SECTION C-API macros. /// /// A no-op on GIL-enabled builds, where the critical section API is exposed as /// a no-op by the Python C API. /// /// Provides weaker locking guarantees than traditional locks, but can in some /// cases be used to provide guarantees similar to the GIL without the risk of /// deadlocks associated with traditional locks. /// /// Many CPython C API functions do not acquire the per-object lock on objects /// passed to Python. You should not expect critical sections applied to /// built-in types to prevent concurrent modification. This API is most useful /// for user-defined types with full control over how the internal state for the /// type is managed. #[cfg_attr(not(Py_GIL_DISABLED), allow(unused_variables))] pub fn with_critical_section(object: &Bound<'_, PyAny>, f: F) -> R where F: FnOnce() -> R, { #[cfg(Py_GIL_DISABLED)] { struct Guard(crate::ffi::PyCriticalSection); impl Drop for Guard { fn drop(&mut self) { unsafe { crate::ffi::PyCriticalSection_End(&mut self.0); } } } let mut guard = Guard(unsafe { std::mem::zeroed() }); unsafe { crate::ffi::PyCriticalSection_Begin(&mut guard.0, object.as_ptr()) }; f() } #[cfg(not(Py_GIL_DISABLED))] { f() } } /// Executes a closure with a Python critical section held on two objects. /// /// Acquires the per-object lock for the objects `a` and `b` that are held /// until the closure `f` is finished. /// /// This is structurally equivalent to the use of the paired /// Py_BEGIN_CRITICAL_SECTION2 and Py_END_CRITICAL_SECTION2 C-API macros. /// /// A no-op on GIL-enabled builds, where the critical section API is exposed as /// a no-op by the Python C API. /// /// Provides weaker locking guarantees than traditional locks, but can in some /// cases be used to provide guarantees similar to the GIL without the risk of /// deadlocks associated with traditional locks. /// /// Many CPython C API functions do not acquire the per-object lock on objects /// passed to Python. You should not expect critical sections applied to /// built-in types to prevent concurrent modification. This API is most useful /// for user-defined types with full control over how the internal state for the /// type is managed. #[cfg_attr(not(Py_GIL_DISABLED), allow(unused_variables))] pub fn with_critical_section2(a: &Bound<'_, PyAny>, b: &Bound<'_, PyAny>, f: F) -> R where F: FnOnce() -> R, { #[cfg(Py_GIL_DISABLED)] { struct Guard(crate::ffi::PyCriticalSection2); impl Drop for Guard { fn drop(&mut self) { unsafe { crate::ffi::PyCriticalSection2_End(&mut self.0); } } } let mut guard = Guard(unsafe { std::mem::zeroed() }); unsafe { crate::ffi::PyCriticalSection2_Begin(&mut guard.0, a.as_ptr(), b.as_ptr()) }; f() } #[cfg(not(Py_GIL_DISABLED))] { f() } } #[cfg(rustc_has_once_lock)] mod once_lock_ext_sealed { pub trait Sealed {} impl Sealed for std::sync::OnceLock {} } /// Helper trait for `Once` to help avoid deadlocking when using a `Once` when attached to a /// Python thread. pub trait OnceExt: Sealed { ///The state of `Once` type OnceState; /// Similar to [`call_once`][Once::call_once], but releases the Python GIL temporarily /// if blocking on another thread currently calling this `Once`. fn call_once_py_attached(&self, py: Python<'_>, f: impl FnOnce()); /// Similar to [`call_once_force`][Once::call_once_force], but releases the Python GIL /// temporarily if blocking on another thread currently calling this `Once`. fn call_once_force_py_attached(&self, py: Python<'_>, f: impl FnOnce(&Self::OnceState)); } /// Extension trait for [`std::sync::OnceLock`] which helps avoid deadlocks between the Python /// interpreter and initialization with the `OnceLock`. #[cfg(rustc_has_once_lock)] pub trait OnceLockExt: once_lock_ext_sealed::Sealed { /// Initializes this `OnceLock` with the given closure if it has not been initialized yet. /// /// If this function would block, this function detaches from the Python interpreter and /// reattaches before calling `f`. This avoids deadlocks between the Python interpreter and /// the `OnceLock` in cases where `f` can call arbitrary Python code, as calling arbitrary /// Python code can lead to `f` itself blocking on the Python interpreter. /// /// By detaching from the Python interpreter before blocking, this ensures that if `f` blocks /// then the Python interpreter cannot be blocked by `f` itself. fn get_or_init_py_attached(&self, py: Python<'_>, f: F) -> &T where F: FnOnce() -> T; } /// Extension trait for [`std::sync::Mutex`] which helps avoid deadlocks between /// the Python interpreter and acquiring the `Mutex`. pub trait MutexExt<'a, T, R>: Sealed where Self: 'a, { /// Lock this `Mutex` in a manner that cannot deadlock with the Python interpreter. /// /// Before attempting to lock the mutex, this function detaches from the /// Python runtime. When the lock is acquired, it re-attaches to the Python /// runtime before returning the `LockResult`. This avoids deadlocks between /// the GIL and other global synchronization events triggered by the Python /// interpreter. fn lock_py_attached(&'a self, py: Python<'_>) -> R; } impl OnceExt for Once { type OnceState = OnceState; fn call_once_py_attached(&self, py: Python<'_>, f: impl FnOnce()) { if self.is_completed() { return; } init_once_py_attached(self, py, f) } fn call_once_force_py_attached(&self, py: Python<'_>, f: impl FnOnce(&OnceState)) { if self.is_completed() { return; } init_once_force_py_attached(self, py, f); } } #[cfg(feature = "parking_lot")] impl OnceExt for parking_lot::Once { type OnceState = parking_lot::OnceState; fn call_once_py_attached(&self, _py: Python<'_>, f: impl FnOnce()) { if self.state().done() { return; } let ts_guard = unsafe { SuspendGIL::new() }; self.call_once(move || { drop(ts_guard); f(); }); } fn call_once_force_py_attached( &self, _py: Python<'_>, f: impl FnOnce(&parking_lot::OnceState), ) { if self.state().done() { return; } let ts_guard = unsafe { SuspendGIL::new() }; self.call_once_force(move |state| { drop(ts_guard); f(&state); }); } } #[cfg(rustc_has_once_lock)] impl OnceLockExt for std::sync::OnceLock { fn get_or_init_py_attached(&self, py: Python<'_>, f: F) -> &T where F: FnOnce() -> T, { // this trait is guarded by a rustc version config // so clippy's MSRV check is wrong #[allow(clippy::incompatible_msrv)] // Use self.get() first to create a fast path when initialized self.get() .unwrap_or_else(|| init_once_lock_py_attached(self, py, f)) } } impl<'a, T> MutexExt<'a, T, std::sync::LockResult>> for std::sync::Mutex { fn lock_py_attached( &'a self, _py: Python<'_>, ) -> std::sync::LockResult> { // If try_lock is successful or returns a poisoned mutex, return them so // the caller can deal with them. Otherwise we need to use blocking // lock, which requires detaching from the Python runtime to avoid // possible deadlocks. match self.try_lock() { Ok(inner) => return Ok(inner), Err(std::sync::TryLockError::Poisoned(inner)) => { return std::sync::LockResult::Err(inner) } Err(std::sync::TryLockError::WouldBlock) => {} } // SAFETY: detach from the runtime right before a possibly blocking call // then reattach when the blocking call completes and before calling // into the C API. let ts_guard = unsafe { SuspendGIL::new() }; let res = self.lock(); drop(ts_guard); res } } #[cfg(feature = "lock_api")] impl<'a, R: lock_api::RawMutex, T> MutexExt<'a, T, lock_api::MutexGuard<'a, R, T>> for lock_api::Mutex { fn lock_py_attached(&'a self, _py: Python<'_>) -> lock_api::MutexGuard<'a, R, T> { if let Some(guard) = self.try_lock() { return guard; } let ts_guard = unsafe { SuspendGIL::new() }; let res = self.lock(); drop(ts_guard); res } } #[cfg(feature = "arc_lock")] impl<'a, R, T> MutexExt<'a, T, lock_api::ArcMutexGuard> for std::sync::Arc> where R: lock_api::RawMutex, Self: 'a, { fn lock_py_attached(&self, _py: Python<'_>) -> lock_api::ArcMutexGuard { if let Some(guard) = self.try_lock_arc() { return guard; } let ts_guard = unsafe { SuspendGIL::new() }; let res = self.lock_arc(); drop(ts_guard); res } } #[cold] fn init_once_py_attached(once: &Once, _py: Python<'_>, f: F) where F: FnOnce() -> T, { // SAFETY: detach from the runtime right before a possibly blocking call // then reattach when the blocking call completes and before calling // into the C API. let ts_guard = unsafe { SuspendGIL::new() }; once.call_once(move || { drop(ts_guard); f(); }); } #[cold] fn init_once_force_py_attached(once: &Once, _py: Python<'_>, f: F) where F: FnOnce(&OnceState) -> T, { // SAFETY: detach from the runtime right before a possibly blocking call // then reattach when the blocking call completes and before calling // into the C API. let ts_guard = unsafe { SuspendGIL::new() }; once.call_once_force(move |state| { drop(ts_guard); f(state); }); } #[cfg(rustc_has_once_lock)] #[cold] fn init_once_lock_py_attached<'a, F, T>( lock: &'a std::sync::OnceLock, _py: Python<'_>, f: F, ) -> &'a T where F: FnOnce() -> T, { // SAFETY: detach from the runtime right before a possibly blocking call // then reattach when the blocking call completes and before calling // into the C API. let ts_guard = unsafe { SuspendGIL::new() }; // this trait is guarded by a rustc version config // so clippy's MSRV check is wrong #[allow(clippy::incompatible_msrv)] // By having detached here, we guarantee that `.get_or_init` cannot deadlock with // the Python interpreter let value = lock.get_or_init(move || { drop(ts_guard); f() }); value } #[cfg(test)] mod tests { use super::*; use crate::types::{PyDict, PyDictMethods}; #[cfg(not(target_arch = "wasm32"))] use std::sync::Mutex; #[cfg(not(target_arch = "wasm32"))] #[cfg(feature = "macros")] use std::sync::{ atomic::{AtomicBool, Ordering}, Barrier, }; #[cfg(not(target_arch = "wasm32"))] #[cfg(feature = "macros")] #[crate::pyclass(crate = "crate")] struct BoolWrapper(AtomicBool); #[cfg(not(target_arch = "wasm32"))] #[cfg(feature = "macros")] #[crate::pyclass(crate = "crate")] struct VecWrapper(Vec); #[test] fn test_intern() { Python::with_gil(|py| { let foo1 = "foo"; let foo2 = intern!(py, "foo"); let foo3 = intern!(py, stringify!(foo)); let dict = PyDict::new(py); dict.set_item(foo1, 42_usize).unwrap(); assert!(dict.contains(foo2).unwrap()); assert_eq!( dict.get_item(foo3) .unwrap() .unwrap() .extract::() .unwrap(), 42 ); }); } #[test] fn test_once_cell() { Python::with_gil(|py| { let mut cell = GILOnceCell::new(); assert!(cell.get(py).is_none()); assert_eq!(cell.get_or_try_init(py, || Err(5)), Err(5)); assert!(cell.get(py).is_none()); assert_eq!(cell.get_or_try_init(py, || Ok::<_, ()>(2)), Ok(&2)); assert_eq!(cell.get(py), Some(&2)); assert_eq!(cell.get_or_try_init(py, || Err(5)), Ok(&2)); assert_eq!(cell.take(), Some(2)); assert_eq!(cell.into_inner(), None); let cell_py = GILOnceCell::new(); assert!(cell_py.clone_ref(py).get(py).is_none()); cell_py.get_or_init(py, || py.None()); assert!(cell_py.clone_ref(py).get(py).unwrap().is_none(py)); }) } #[test] fn test_once_cell_drop() { #[derive(Debug)] struct RecordDrop<'a>(&'a mut bool); impl Drop for RecordDrop<'_> { fn drop(&mut self) { *self.0 = true; } } Python::with_gil(|py| { let mut dropped = false; let cell = GILOnceCell::new(); cell.set(py, RecordDrop(&mut dropped)).unwrap(); let drop_container = cell.get(py).unwrap(); assert!(!*drop_container.0); drop(cell); assert!(dropped); }); } #[cfg(feature = "macros")] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled #[test] fn test_critical_section() { let barrier = Barrier::new(2); let bool_wrapper = Python::with_gil(|py| -> Py { Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap() }); std::thread::scope(|s| { s.spawn(|| { Python::with_gil(|py| { let b = bool_wrapper.bind(py); with_critical_section(b, || { barrier.wait(); std::thread::sleep(std::time::Duration::from_millis(10)); b.borrow().0.store(true, Ordering::Release); }) }); }); s.spawn(|| { barrier.wait(); Python::with_gil(|py| { let b = bool_wrapper.bind(py); // this blocks until the other thread's critical section finishes with_critical_section(b, || { assert!(b.borrow().0.load(Ordering::Acquire)); }); }); }); }); } #[cfg(feature = "macros")] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled #[test] fn test_critical_section2() { let barrier = Barrier::new(3); let (bool_wrapper1, bool_wrapper2) = Python::with_gil(|py| { ( Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap(), Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap(), ) }); std::thread::scope(|s| { s.spawn(|| { Python::with_gil(|py| { let b1 = bool_wrapper1.bind(py); let b2 = bool_wrapper2.bind(py); with_critical_section2(b1, b2, || { barrier.wait(); std::thread::sleep(std::time::Duration::from_millis(10)); b1.borrow().0.store(true, Ordering::Release); b2.borrow().0.store(true, Ordering::Release); }) }); }); s.spawn(|| { barrier.wait(); Python::with_gil(|py| { let b1 = bool_wrapper1.bind(py); // this blocks until the other thread's critical section finishes with_critical_section(b1, || { assert!(b1.borrow().0.load(Ordering::Acquire)); }); }); }); s.spawn(|| { barrier.wait(); Python::with_gil(|py| { let b2 = bool_wrapper2.bind(py); // this blocks until the other thread's critical section finishes with_critical_section(b2, || { assert!(b2.borrow().0.load(Ordering::Acquire)); }); }); }); }); } #[cfg(feature = "macros")] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled #[test] fn test_critical_section2_same_object_no_deadlock() { let barrier = Barrier::new(2); let bool_wrapper = Python::with_gil(|py| -> Py { Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap() }); std::thread::scope(|s| { s.spawn(|| { Python::with_gil(|py| { let b = bool_wrapper.bind(py); with_critical_section2(b, b, || { barrier.wait(); std::thread::sleep(std::time::Duration::from_millis(10)); b.borrow().0.store(true, Ordering::Release); }) }); }); s.spawn(|| { barrier.wait(); Python::with_gil(|py| { let b = bool_wrapper.bind(py); // this blocks until the other thread's critical section finishes with_critical_section(b, || { assert!(b.borrow().0.load(Ordering::Acquire)); }); }); }); }); } #[cfg(feature = "macros")] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled #[test] fn test_critical_section2_two_containers() { let (vec1, vec2) = Python::with_gil(|py| { ( Py::new(py, VecWrapper(vec![1, 2, 3])).unwrap(), Py::new(py, VecWrapper(vec![4, 5])).unwrap(), ) }); std::thread::scope(|s| { s.spawn(|| { Python::with_gil(|py| { let v1 = vec1.bind(py); let v2 = vec2.bind(py); with_critical_section2(v1, v2, || { // v2.extend(v1) v2.borrow_mut().0.extend(v1.borrow().0.iter()); }) }); }); s.spawn(|| { Python::with_gil(|py| { let v1 = vec1.bind(py); let v2 = vec2.bind(py); with_critical_section2(v1, v2, || { // v1.extend(v2) v1.borrow_mut().0.extend(v2.borrow().0.iter()); }) }); }); }); Python::with_gil(|py| { let v1 = vec1.bind(py); let v2 = vec2.bind(py); // execution order is not guaranteed, so we need to check both // NB: extend should be atomic, items must not be interleaved // v1.extend(v2) // v2.extend(v1) let expected1_vec1 = vec![1, 2, 3, 4, 5]; let expected1_vec2 = vec![4, 5, 1, 2, 3, 4, 5]; // v2.extend(v1) // v1.extend(v2) let expected2_vec1 = vec![1, 2, 3, 4, 5, 1, 2, 3]; let expected2_vec2 = vec![4, 5, 1, 2, 3]; assert!( (v1.borrow().0.eq(&expected1_vec1) && v2.borrow().0.eq(&expected1_vec2)) || (v1.borrow().0.eq(&expected2_vec1) && v2.borrow().0.eq(&expected2_vec2)) ); }); } #[test] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled fn test_once_ext() { macro_rules! test_once { ($once:expr, $is_poisoned:expr) => {{ // adapted from the example in the docs for Once::try_once_force let init = $once; std::thread::scope(|s| { // poison the once let handle = s.spawn(|| { Python::with_gil(|py| { init.call_once_py_attached(py, || panic!()); }) }); assert!(handle.join().is_err()); // poisoning propagates let handle = s.spawn(|| { Python::with_gil(|py| { init.call_once_py_attached(py, || {}); }); }); assert!(handle.join().is_err()); // call_once_force will still run and reset the poisoned state Python::with_gil(|py| { init.call_once_force_py_attached(py, |state| { assert!($is_poisoned(state.clone())); }); // once any success happens, we stop propagating the poison init.call_once_py_attached(py, || {}); }); // calling call_once_force should return immediately without calling the closure Python::with_gil(|py| init.call_once_force_py_attached(py, |_| panic!())); }); }}; } test_once!(Once::new(), OnceState::is_poisoned); #[cfg(feature = "parking_lot")] test_once!(parking_lot::Once::new(), parking_lot::OnceState::poisoned); } #[cfg(rustc_has_once_lock)] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled #[test] fn test_once_lock_ext() { let cell = std::sync::OnceLock::new(); std::thread::scope(|s| { assert!(cell.get().is_none()); s.spawn(|| { Python::with_gil(|py| { assert_eq!(*cell.get_or_init_py_attached(py, || 12345), 12345); }); }); }); assert_eq!(cell.get(), Some(&12345)); } #[cfg(feature = "macros")] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled #[test] fn test_mutex_ext() { let barrier = Barrier::new(2); let mutex = Python::with_gil(|py| -> Mutex> { Mutex::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap()) }); std::thread::scope(|s| { s.spawn(|| { Python::with_gil(|py| { let b = mutex.lock_py_attached(py).unwrap(); barrier.wait(); // sleep to ensure the other thread actually blocks std::thread::sleep(std::time::Duration::from_millis(10)); (*b).bind(py).borrow().0.store(true, Ordering::Release); drop(b); }); }); s.spawn(|| { barrier.wait(); Python::with_gil(|py| { // blocks until the other thread releases the lock let b = mutex.lock_py_attached(py).unwrap(); assert!((*b).bind(py).borrow().0.load(Ordering::Acquire)); }); }); }); } #[cfg(feature = "macros")] #[cfg(all( any(feature = "parking_lot", feature = "lock_api"), not(target_arch = "wasm32") // We are building wasm Python with pthreads disabled ))] #[test] fn test_parking_lot_mutex_ext() { macro_rules! test_mutex { ($guard:ty ,$mutex:stmt) => {{ let barrier = Barrier::new(2); let mutex = Python::with_gil({ $mutex }); std::thread::scope(|s| { s.spawn(|| { Python::with_gil(|py| { let b: $guard = mutex.lock_py_attached(py); barrier.wait(); // sleep to ensure the other thread actually blocks std::thread::sleep(std::time::Duration::from_millis(10)); (*b).bind(py).borrow().0.store(true, Ordering::Release); drop(b); }); }); s.spawn(|| { barrier.wait(); Python::with_gil(|py| { // blocks until the other thread releases the lock let b: $guard = mutex.lock_py_attached(py); assert!((*b).bind(py).borrow().0.load(Ordering::Acquire)); }); }); }); }}; } test_mutex!(parking_lot::MutexGuard<'_, _>, |py| { parking_lot::Mutex::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap()) }); #[cfg(feature = "arc_lock")] test_mutex!(parking_lot::ArcMutexGuard<_, _>, |py| { let mutex = parking_lot::Mutex::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap()); std::sync::Arc::new(mutex) }); } #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled #[test] fn test_mutex_ext_poison() { let mutex = Mutex::new(42); std::thread::scope(|s| { let lock_result = s.spawn(|| { Python::with_gil(|py| { let _unused = mutex.lock_py_attached(py); panic!(); }); }); assert!(lock_result.join().is_err()); assert!(mutex.is_poisoned()); }); let guard = Python::with_gil(|py| { // recover from the poisoning match mutex.lock_py_attached(py) { Ok(guard) => guard, Err(poisoned) => poisoned.into_inner(), } }); assert!(*guard == 42); } } pyo3/src/inspect/0000775000175000017500000000000015105742312013532 5ustar bdrungbdrungpyo3/src/inspect/mod.rs0000644000175000017500000000021015105742312014646 0ustar bdrungbdrung//! Runtime inspection of objects exposed to Python. //! //! Tracking issue: . pub mod types; pyo3/src/inspect/types.rs0000644000175000017500000003660615105742312015255 0ustar bdrungbdrung//! Data types used to describe runtime Python types. use std::borrow::Cow; use std::fmt::{Display, Formatter}; /// Designation of a Python type. /// /// This enum is used to handle advanced types, such as types with generics. /// Its [`Display`] implementation can be used to convert to the type hint notation (e.g. `List[int]`). #[derive(Debug, Clone, Eq, PartialEq)] pub enum TypeInfo { /// The type `typing.Any`, which represents any possible value (unknown type). Any, /// The type `typing.None`. None, /// The type `typing.NoReturn`, which represents functions that never return (they can still panic / throw, similar to `never` in Rust). NoReturn, /// The type `typing.Callable`. /// /// The first argument represents the parameters of the callable: /// - `Some` of a vector of types to represent the signature, /// - `None` if the signature is unknown (allows any number of arguments with type `Any`). /// /// The second argument represents the return type. Callable(Option>, Box), /// The type `typing.tuple`. /// /// The argument represents the contents of the tuple: /// - `Some` of a vector of types to represent the accepted types, /// - `Some` of an empty vector for the empty tuple, /// - `None` if the number and type of accepted values is unknown. /// /// If the number of accepted values is unknown, but their type is, use [`Self::UnsizedTypedTuple`]. Tuple(Option>), /// The type `typing.Tuple`. /// /// Use this variant to represent a tuple of unknown size but of known types. /// /// If the type is unknown, or if the number of elements is known, use [`Self::Tuple`]. UnsizedTypedTuple(Box), /// A Python class. Class { /// The module this class comes from. module: ModuleName, /// The name of this class, as it appears in a type hint. name: Cow<'static, str>, /// The generics accepted by this class (empty vector if this class is not generic). type_vars: Vec, }, } /// Declares which module a type is a part of. #[derive(Debug, Clone, Eq, PartialEq)] pub enum ModuleName { /// The type is built-in: it doesn't need to be imported. Builtin, /// The type is in the current module: it doesn't need to be imported in this module, but needs to be imported in others. CurrentModule, /// The type is in the specified module. Module(Cow<'static, str>), } impl TypeInfo { /// Returns the module in which a type is declared. /// /// Returns `None` if the type is declared in the current module. pub fn module_name(&self) -> Option<&str> { match self { TypeInfo::Any | TypeInfo::None | TypeInfo::NoReturn | TypeInfo::Callable(_, _) | TypeInfo::Tuple(_) | TypeInfo::UnsizedTypedTuple(_) => Some("typing"), TypeInfo::Class { module, .. } => match module { ModuleName::Builtin => Some("builtins"), ModuleName::CurrentModule => None, ModuleName::Module(name) => Some(name), }, } } /// Returns the name of a type. /// /// The name of a type is the part of the hint that is not generic (e.g. `List` instead of `List[int]`). pub fn name(&self) -> Cow<'_, str> { Cow::from(match self { TypeInfo::Any => "Any", TypeInfo::None => "None", TypeInfo::NoReturn => "NoReturn", TypeInfo::Callable(_, _) => "Callable", TypeInfo::Tuple(_) => "Tuple", TypeInfo::UnsizedTypedTuple(_) => "Tuple", TypeInfo::Class { name, .. } => name, }) } } // Utilities for easily instantiating TypeInfo structures for built-in/common types. impl TypeInfo { /// The Python `Optional` type. pub fn optional_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Optional"), type_vars: vec![t], } } /// The Python `Union` type. pub fn union_of(types: &[TypeInfo]) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Union"), type_vars: types.to_vec(), } } /// The Python `List` type. pub fn list_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("List"), type_vars: vec![t], } } /// The Python `Sequence` type. pub fn sequence_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Sequence"), type_vars: vec![t], } } /// The Python `Set` type. pub fn set_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Set"), type_vars: vec![t], } } /// The Python `FrozenSet` type. pub fn frozen_set_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("FrozenSet"), type_vars: vec![t], } } /// The Python `Iterable` type. pub fn iterable_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Iterable"), type_vars: vec![t], } } /// The Python `Iterator` type. pub fn iterator_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Iterator"), type_vars: vec![t], } } /// The Python `Dict` type. pub fn dict_of(k: TypeInfo, v: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Dict"), type_vars: vec![k, v], } } /// The Python `Mapping` type. pub fn mapping_of(k: TypeInfo, v: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Mapping"), type_vars: vec![k, v], } } /// Convenience factory for non-generic builtins (e.g. `int`). pub fn builtin(name: &'static str) -> TypeInfo { TypeInfo::Class { module: ModuleName::Builtin, name: Cow::from(name), type_vars: vec![], } } } impl Display for TypeInfo { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { TypeInfo::Any | TypeInfo::None | TypeInfo::NoReturn => write!(f, "{}", self.name()), TypeInfo::Callable(input, output) => { write!(f, "Callable[")?; if let Some(input) = input { write!(f, "[")?; let mut comma = false; for arg in input { if comma { write!(f, ", ")?; } write!(f, "{arg}")?; comma = true; } write!(f, "]")?; } else { write!(f, "...")?; } write!(f, ", {output}]") } TypeInfo::Tuple(types) => { write!(f, "Tuple[")?; if let Some(types) = types { if types.is_empty() { write!(f, "()")?; } else { let mut comma = false; for t in types { if comma { write!(f, ", ")?; } write!(f, "{t}")?; comma = true; } } } else { write!(f, "...")?; } write!(f, "]") } TypeInfo::UnsizedTypedTuple(t) => write!(f, "Tuple[{t}, ...]"), TypeInfo::Class { name, type_vars, .. } => { write!(f, "{name}")?; if !type_vars.is_empty() { write!(f, "[")?; let mut comma = false; for var in type_vars { if comma { write!(f, ", ")?; } write!(f, "{var}")?; comma = true; } write!(f, "]") } else { Ok(()) } } } } } #[cfg(test)] mod test { use std::borrow::Cow; use crate::inspect::types::{ModuleName, TypeInfo}; #[track_caller] pub fn assert_display(t: &TypeInfo, expected: &str) { assert_eq!(format!("{t}"), expected) } #[test] fn basic() { assert_display(&TypeInfo::Any, "Any"); assert_display(&TypeInfo::None, "None"); assert_display(&TypeInfo::NoReturn, "NoReturn"); assert_display(&TypeInfo::builtin("int"), "int"); } #[test] fn callable() { let any_to_int = TypeInfo::Callable(None, Box::new(TypeInfo::builtin("int"))); assert_display(&any_to_int, "Callable[..., int]"); let sum = TypeInfo::Callable( Some(vec![TypeInfo::builtin("int"), TypeInfo::builtin("int")]), Box::new(TypeInfo::builtin("int")), ); assert_display(&sum, "Callable[[int, int], int]"); } #[test] fn tuple() { let any = TypeInfo::Tuple(None); assert_display(&any, "Tuple[...]"); let triple = TypeInfo::Tuple(Some(vec![ TypeInfo::builtin("int"), TypeInfo::builtin("str"), TypeInfo::builtin("bool"), ])); assert_display(&triple, "Tuple[int, str, bool]"); let empty = TypeInfo::Tuple(Some(vec![])); assert_display(&empty, "Tuple[()]"); let typed = TypeInfo::UnsizedTypedTuple(Box::new(TypeInfo::builtin("bool"))); assert_display(&typed, "Tuple[bool, ...]"); } #[test] fn class() { let class1 = TypeInfo::Class { module: ModuleName::CurrentModule, name: Cow::from("MyClass"), type_vars: vec![], }; assert_display(&class1, "MyClass"); let class2 = TypeInfo::Class { module: ModuleName::CurrentModule, name: Cow::from("MyClass"), type_vars: vec![TypeInfo::builtin("int"), TypeInfo::builtin("bool")], }; assert_display(&class2, "MyClass[int, bool]"); } #[test] fn collections() { let int = TypeInfo::builtin("int"); let bool = TypeInfo::builtin("bool"); let str = TypeInfo::builtin("str"); let list = TypeInfo::list_of(int.clone()); assert_display(&list, "List[int]"); let sequence = TypeInfo::sequence_of(bool.clone()); assert_display(&sequence, "Sequence[bool]"); let optional = TypeInfo::optional_of(str.clone()); assert_display(&optional, "Optional[str]"); let iterable = TypeInfo::iterable_of(int.clone()); assert_display(&iterable, "Iterable[int]"); let iterator = TypeInfo::iterator_of(bool); assert_display(&iterator, "Iterator[bool]"); let dict = TypeInfo::dict_of(int.clone(), str.clone()); assert_display(&dict, "Dict[int, str]"); let mapping = TypeInfo::mapping_of(int, str.clone()); assert_display(&mapping, "Mapping[int, str]"); let set = TypeInfo::set_of(str.clone()); assert_display(&set, "Set[str]"); let frozen_set = TypeInfo::frozen_set_of(str); assert_display(&frozen_set, "FrozenSet[str]"); } #[test] fn complicated() { let int = TypeInfo::builtin("int"); assert_display(&int, "int"); let bool = TypeInfo::builtin("bool"); assert_display(&bool, "bool"); let str = TypeInfo::builtin("str"); assert_display(&str, "str"); let any = TypeInfo::Any; assert_display(&any, "Any"); let params = TypeInfo::union_of(&[int.clone(), str]); assert_display(¶ms, "Union[int, str]"); let func = TypeInfo::Callable(Some(vec![params, any]), Box::new(bool)); assert_display(&func, "Callable[[Union[int, str], Any], bool]"); let dict = TypeInfo::mapping_of(int, func); assert_display( &dict, "Mapping[int, Callable[[Union[int, str], Any], bool]]", ); } } #[cfg(test)] mod conversion { use std::collections::{HashMap, HashSet}; use crate::inspect::types::test::assert_display; use crate::{FromPyObject, IntoPyObject}; #[test] fn unsigned_int() { assert_display(&usize::type_output(), "int"); assert_display(&usize::type_input(), "int"); assert_display(&u8::type_output(), "int"); assert_display(&u8::type_input(), "int"); assert_display(&u16::type_output(), "int"); assert_display(&u16::type_input(), "int"); assert_display(&u32::type_output(), "int"); assert_display(&u32::type_input(), "int"); assert_display(&u64::type_output(), "int"); assert_display(&u64::type_input(), "int"); } #[test] fn signed_int() { assert_display(&isize::type_output(), "int"); assert_display(&isize::type_input(), "int"); assert_display(&i8::type_output(), "int"); assert_display(&i8::type_input(), "int"); assert_display(&i16::type_output(), "int"); assert_display(&i16::type_input(), "int"); assert_display(&i32::type_output(), "int"); assert_display(&i32::type_input(), "int"); assert_display(&i64::type_output(), "int"); assert_display(&i64::type_input(), "int"); } #[test] fn float() { assert_display(&f32::type_output(), "float"); assert_display(&f32::type_input(), "float"); assert_display(&f64::type_output(), "float"); assert_display(&f64::type_input(), "float"); } #[test] fn bool() { assert_display(&bool::type_output(), "bool"); assert_display(&bool::type_input(), "bool"); } #[test] fn text() { assert_display(&String::type_output(), "str"); assert_display(&String::type_input(), "str"); assert_display(&<&[u8]>::type_output(), "Union[bytes, List[int]]"); assert_display(&<&[String]>::type_output(), "Union[bytes, List[str]]"); assert_display( &<&[u8] as crate::conversion::FromPyObjectBound>::type_input(), "bytes", ); } #[test] fn collections() { assert_display(&>::type_output(), "List[int]"); assert_display(&>::type_input(), "Sequence[int]"); assert_display(&>::type_output(), "Set[int]"); assert_display(&>::type_input(), "Set[int]"); assert_display(&>::type_output(), "Dict[int, float]"); assert_display(&>::type_input(), "Mapping[int, float]"); assert_display(&<(usize, f32)>::type_input(), "Tuple[int, float]"); } } pyo3/src/pycell.rs0000644000175000017500000006222115105742312013724 0ustar bdrungbdrung//! PyO3's interior mutability primitive. //! //! Rust has strict aliasing rules - you can either have any number of immutable (shared) references or one mutable //! reference. Python's ownership model is the complete opposite of that - any Python object //! can be referenced any number of times, and mutation is allowed from any reference. //! //! PyO3 deals with these differences by employing the [Interior Mutability] //! pattern. This requires that PyO3 enforces the borrowing rules and it has two mechanisms for //! doing so: //! - Statically it can enforce thread-safe access with the [`Python<'py>`](crate::Python) token. //! All Rust code holding that token, or anything derived from it, can assume that they have //! safe access to the Python interpreter's state. For this reason all the native Python objects //! can be mutated through shared references. //! - However, methods and functions in Rust usually *do* need `&mut` references. While PyO3 can //! use the [`Python<'py>`](crate::Python) token to guarantee thread-safe access to them, it cannot //! statically guarantee uniqueness of `&mut` references. As such those references have to be tracked //! dynamically at runtime, using `PyCell` and the other types defined in this module. This works //! similar to std's [`RefCell`](std::cell::RefCell) type. //! //! # When *not* to use PyCell //! //! Usually you can use `&mut` references as method and function receivers and arguments, and you //! won't need to use `PyCell` directly: //! //! ```rust,no_run //! use pyo3::prelude::*; //! //! #[pyclass] //! struct Number { //! inner: u32, //! } //! //! #[pymethods] //! impl Number { //! fn increment(&mut self) { //! self.inner += 1; //! } //! } //! ``` //! //! The [`#[pymethods]`](crate::pymethods) proc macro will generate this wrapper function (and more), //! using `PyCell` under the hood: //! //! ```rust,ignore //! # use pyo3::prelude::*; //! # #[pyclass] //! # struct Number { //! # inner: u32, //! # } //! # //! # #[pymethods] //! # impl Number { //! # fn increment(&mut self) { //! # self.inner += 1; //! # } //! # } //! # //! // The function which is exported to Python looks roughly like the following //! unsafe extern "C" fn __pymethod_increment__( //! _slf: *mut pyo3::ffi::PyObject, //! _args: *mut pyo3::ffi::PyObject, //! ) -> *mut pyo3::ffi::PyObject { //! use :: pyo3 as _pyo3; //! _pyo3::impl_::trampoline::noargs(_slf, _args, |py, _slf| { //! # #[allow(deprecated)] //! let _cell = py //! .from_borrowed_ptr::<_pyo3::PyAny>(_slf) //! .downcast::<_pyo3::PyCell>()?; //! let mut _ref = _cell.try_borrow_mut()?; //! let _slf: &mut Number = &mut *_ref; //! _pyo3::impl_::callback::convert(py, Number::increment(_slf)) //! }) //! } //! ``` //! //! # When to use PyCell //! ## Using pyclasses from Rust //! //! However, we *do* need `PyCell` if we want to call its methods from Rust: //! ```rust //! # use pyo3::prelude::*; //! # //! # #[pyclass] //! # struct Number { //! # inner: u32, //! # } //! # //! # #[pymethods] //! # impl Number { //! # fn increment(&mut self) { //! # self.inner += 1; //! # } //! # } //! # fn main() -> PyResult<()> { //! Python::with_gil(|py| { //! let n = Py::new(py, Number { inner: 0 })?; //! //! // We borrow the guard and then dereference //! // it to get a mutable reference to Number //! let mut guard: PyRefMut<'_, Number> = n.bind(py).borrow_mut(); //! let n_mutable: &mut Number = &mut *guard; //! //! n_mutable.increment(); //! //! // To avoid panics we must dispose of the //! // `PyRefMut` before borrowing again. //! drop(guard); //! //! let n_immutable: &Number = &n.bind(py).borrow(); //! assert_eq!(n_immutable.inner, 1); //! //! Ok(()) //! }) //! # } //! ``` //! ## Dealing with possibly overlapping mutable references //! //! It is also necessary to use `PyCell` if you can receive mutable arguments that may overlap. //! Suppose the following function that swaps the values of two `Number`s: //! ``` //! # use pyo3::prelude::*; //! # #[pyclass] //! # pub struct Number { //! # inner: u32, //! # } //! #[pyfunction] //! fn swap_numbers(a: &mut Number, b: &mut Number) { //! std::mem::swap(&mut a.inner, &mut b.inner); //! } //! # fn main() { //! # Python::with_gil(|py| { //! # let n = Py::new(py, Number{inner: 35}).unwrap(); //! # let n2 = n.clone_ref(py); //! # assert!(n.is(&n2)); //! # let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap(); //! # fun.call1((n, n2)).expect_err("Managed to create overlapping mutable references. Note: this is undefined behaviour."); //! # }); //! # } //! ``` //! When users pass in the same `Number` as both arguments, one of the mutable borrows will //! fail and raise a `RuntimeError`: //! ```text //! >>> a = Number() //! >>> swap_numbers(a, a) //! Traceback (most recent call last): //! File "", line 1, in //! RuntimeError: Already borrowed //! ``` //! //! It is better to write that function like this: //! ```rust,ignore //! # #![allow(deprecated)] //! # use pyo3::prelude::*; //! # #[pyclass] //! # pub struct Number { //! # inner: u32, //! # } //! #[pyfunction] //! fn swap_numbers(a: &PyCell, b: &PyCell) { //! // Check that the pointers are unequal //! if !a.is(b) { //! std::mem::swap(&mut a.borrow_mut().inner, &mut b.borrow_mut().inner); //! } else { //! // Do nothing - they are the same object, so don't need swapping. //! } //! } //! # fn main() { //! # // With duplicate numbers //! # Python::with_gil(|py| { //! # let n = Py::new(py, Number{inner: 35}).unwrap(); //! # let n2 = n.clone_ref(py); //! # assert!(n.is(&n2)); //! # let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap(); //! # fun.call1((n, n2)).unwrap(); //! # }); //! # //! # // With two different numbers //! # Python::with_gil(|py| { //! # let n = Py::new(py, Number{inner: 35}).unwrap(); //! # let n2 = Py::new(py, Number{inner: 42}).unwrap(); //! # assert!(!n.is(&n2)); //! # let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap(); //! # fun.call1((&n, &n2)).unwrap(); //! # let n: u32 = n.borrow(py).inner; //! # let n2: u32 = n2.borrow(py).inner; //! # assert_eq!(n, 42); //! # assert_eq!(n2, 35); //! # }); //! # } //! ``` //! See the [guide] for more information. //! //! [guide]: https://pyo3.rs/latest/class.html#pycell-and-interior-mutability "PyCell and interior mutability" //! [Interior Mutability]: https://doc.rust-lang.org/book/ch15-05-interior-mutability.html "RefCell and the Interior Mutability Pattern - The Rust Programming Language" use crate::conversion::IntoPyObject; use crate::exceptions::PyRuntimeError; use crate::ffi_ptr_ext::FfiPtrExt; use crate::internal_tricks::{ptr_from_mut, ptr_from_ref}; use crate::pyclass::{boolean_struct::False, PyClass}; use crate::types::any::PyAnyMethods; use crate::{ffi, Borrowed, Bound, PyErr, Python}; use std::convert::Infallible; use std::fmt; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; pub(crate) mod impl_; use impl_::{PyClassBorrowChecker, PyClassObjectLayout}; /// A wrapper type for an immutably borrowed value from a [`Bound<'py, T>`]. /// /// See the [`Bound`] documentation for more information. /// /// # Examples /// /// You can use [`PyRef`] as an alternative to a `&self` receiver when /// - you need to access the pointer of the [`Bound`], or /// - you want to get a super class. /// ``` /// # use pyo3::prelude::*; /// #[pyclass(subclass)] /// struct Parent { /// basename: &'static str, /// } /// /// #[pyclass(extends=Parent)] /// struct Child { /// name: &'static str, /// } /// /// #[pymethods] /// impl Child { /// #[new] /// fn new() -> (Self, Parent) { /// (Child { name: "Caterpillar" }, Parent { basename: "Butterfly" }) /// } /// /// fn format(slf: PyRef<'_, Self>) -> String { /// // We can get *mut ffi::PyObject from PyRef /// let refcnt = unsafe { pyo3::ffi::Py_REFCNT(slf.as_ptr()) }; /// // We can get &Self::BaseType by as_ref /// let basename = slf.as_ref().basename; /// format!("{}(base: {}, cnt: {})", slf.name, basename, refcnt) /// } /// } /// # Python::with_gil(|py| { /// # let sub = Py::new(py, Child::new()).unwrap(); /// # pyo3::py_run!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 4)', sub.format()"); /// # }); /// ``` /// /// See the [module-level documentation](self) for more information. #[repr(transparent)] pub struct PyRef<'p, T: PyClass> { // TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to // store `Borrowed` here instead, avoiding reference counting overhead. inner: Bound<'p, T>, } impl<'p, T: PyClass> PyRef<'p, T> { /// Returns a `Python` token that is bound to the lifetime of the `PyRef`. pub fn py(&self) -> Python<'p> { self.inner.py() } } impl AsRef for PyRef<'_, T> where T: PyClass, U: PyClass, { fn as_ref(&self) -> &T::BaseType { self.as_super() } } impl<'py, T: PyClass> PyRef<'py, T> { /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { self.inner.as_ptr() } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(self) -> *mut ffi::PyObject { self.inner.clone().into_ptr() } #[track_caller] pub(crate) fn borrow(obj: &Bound<'py, T>) -> Self { Self::try_borrow(obj).expect("Already mutably borrowed") } pub(crate) fn try_borrow(obj: &Bound<'py, T>) -> Result { let cell = obj.get_class_object(); cell.ensure_threadsafe(); cell.borrow_checker() .try_borrow() .map(|_| Self { inner: obj.clone() }) } } impl<'p, T, U> PyRef<'p, T> where T: PyClass, U: PyClass, { /// Gets a `PyRef`. /// /// While `as_ref()` returns a reference of type `&T::BaseType`, this cannot be /// used to get the base of `T::BaseType`. /// /// But with the help of this method, you can get hold of instances of the /// super-superclass when needed. /// /// # Examples /// ``` /// # use pyo3::prelude::*; /// #[pyclass(subclass)] /// struct Base1 { /// name1: &'static str, /// } /// /// #[pyclass(extends=Base1, subclass)] /// struct Base2 { /// name2: &'static str, /// } /// /// #[pyclass(extends=Base2)] /// struct Sub { /// name3: &'static str, /// } /// /// #[pymethods] /// impl Sub { /// #[new] /// fn new() -> PyClassInitializer { /// PyClassInitializer::from(Base1 { name1: "base1" }) /// .add_subclass(Base2 { name2: "base2" }) /// .add_subclass(Self { name3: "sub" }) /// } /// fn name(slf: PyRef<'_, Self>) -> String { /// let subname = slf.name3; /// let super_ = slf.into_super(); /// format!("{} {} {}", super_.as_ref().name1, super_.name2, subname) /// } /// } /// # Python::with_gil(|py| { /// # let sub = Py::new(py, Sub::new()).unwrap(); /// # pyo3::py_run!(py, sub, "assert sub.name() == 'base1 base2 sub'") /// # }); /// ``` pub fn into_super(self) -> PyRef<'p, U> { let py = self.py(); PyRef { inner: unsafe { ManuallyDrop::new(self) .as_ptr() .assume_owned_unchecked(py) .downcast_into_unchecked() }, } } /// Borrows a shared reference to `PyRef`. /// /// With the help of this method, you can access attributes and call methods /// on the superclass without consuming the `PyRef`. This method can also /// be chained to access the super-superclass (and so on). /// /// # Examples /// ``` /// # use pyo3::prelude::*; /// #[pyclass(subclass)] /// struct Base { /// base_name: &'static str, /// } /// #[pymethods] /// impl Base { /// fn base_name_len(&self) -> usize { /// self.base_name.len() /// } /// } /// /// #[pyclass(extends=Base)] /// struct Sub { /// sub_name: &'static str, /// } /// /// #[pymethods] /// impl Sub { /// #[new] /// fn new() -> (Self, Base) { /// (Self { sub_name: "sub_name" }, Base { base_name: "base_name" }) /// } /// fn sub_name_len(&self) -> usize { /// self.sub_name.len() /// } /// fn format_name_lengths(slf: PyRef<'_, Self>) -> String { /// format!("{} {}", slf.as_super().base_name_len(), slf.sub_name_len()) /// } /// } /// # Python::with_gil(|py| { /// # let sub = Py::new(py, Sub::new()).unwrap(); /// # pyo3::py_run!(py, sub, "assert sub.format_name_lengths() == '9 8'") /// # }); /// ``` pub fn as_super(&self) -> &PyRef<'p, U> { let ptr = ptr_from_ref::>(&self.inner) // `Bound` has the same layout as `Bound` .cast::>() // `Bound` has the same layout as `PyRef` .cast::>(); unsafe { &*ptr } } } impl Deref for PyRef<'_, T> { type Target = T; #[inline] fn deref(&self) -> &T { unsafe { &*self.inner.get_class_object().get_ptr() } } } impl Drop for PyRef<'_, T> { fn drop(&mut self) { self.inner .get_class_object() .borrow_checker() .release_borrow() } } impl<'py, T: PyClass> IntoPyObject<'py> for PyRef<'py, T> { type Target = T; type Output = Bound<'py, T>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self.inner.clone()) } } impl<'a, 'py, T: PyClass> IntoPyObject<'py> for &'a PyRef<'py, T> { type Target = T; type Output = Borrowed<'a, 'py, T>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self.inner.as_borrowed()) } } impl fmt::Debug for PyRef<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } /// A wrapper type for a mutably borrowed value from a [`Bound<'py, T>`]. /// /// See the [module-level documentation](self) for more information. #[repr(transparent)] pub struct PyRefMut<'p, T: PyClass> { // TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to // store `Borrowed` here instead, avoiding reference counting overhead. inner: Bound<'p, T>, } impl<'p, T: PyClass> PyRefMut<'p, T> { /// Returns a `Python` token that is bound to the lifetime of the `PyRefMut`. pub fn py(&self) -> Python<'p> { self.inner.py() } } impl AsRef for PyRefMut<'_, T> where T: PyClass, U: PyClass, { fn as_ref(&self) -> &T::BaseType { PyRefMut::downgrade(self).as_super() } } impl AsMut for PyRefMut<'_, T> where T: PyClass, U: PyClass, { fn as_mut(&mut self) -> &mut T::BaseType { self.as_super() } } impl<'py, T: PyClass> PyRefMut<'py, T> { /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { self.inner.as_ptr() } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(self) -> *mut ffi::PyObject { self.inner.clone().into_ptr() } #[inline] #[track_caller] pub(crate) fn borrow(obj: &Bound<'py, T>) -> Self { Self::try_borrow(obj).expect("Already borrowed") } pub(crate) fn try_borrow(obj: &Bound<'py, T>) -> Result { let cell = obj.get_class_object(); cell.ensure_threadsafe(); cell.borrow_checker() .try_borrow_mut() .map(|_| Self { inner: obj.clone() }) } pub(crate) fn downgrade(slf: &Self) -> &PyRef<'py, T> { // `PyRefMut` and `PyRef` have the same layout unsafe { &*ptr_from_ref(slf).cast() } } } impl<'p, T, U> PyRefMut<'p, T> where T: PyClass, U: PyClass, { /// Gets a `PyRef`. /// /// See [`PyRef::into_super`] for more. pub fn into_super(self) -> PyRefMut<'p, U> { let py = self.py(); PyRefMut { inner: unsafe { ManuallyDrop::new(self) .as_ptr() .assume_owned_unchecked(py) .downcast_into_unchecked() }, } } /// Borrows a mutable reference to `PyRefMut`. /// /// With the help of this method, you can mutate attributes and call mutating /// methods on the superclass without consuming the `PyRefMut`. This method /// can also be chained to access the super-superclass (and so on). /// /// See [`PyRef::as_super`] for more. pub fn as_super(&mut self) -> &mut PyRefMut<'p, U> { let ptr = ptr_from_mut::>(&mut self.inner) // `Bound` has the same layout as `Bound` .cast::>() // `Bound` has the same layout as `PyRefMut`, // and the mutable borrow on `self` prevents aliasing .cast::>(); unsafe { &mut *ptr } } } impl> Deref for PyRefMut<'_, T> { type Target = T; #[inline] fn deref(&self) -> &T { unsafe { &*self.inner.get_class_object().get_ptr() } } } impl> DerefMut for PyRefMut<'_, T> { #[inline] fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.inner.get_class_object().get_ptr() } } } impl> Drop for PyRefMut<'_, T> { fn drop(&mut self) { self.inner .get_class_object() .borrow_checker() .release_borrow_mut() } } impl<'py, T: PyClass> IntoPyObject<'py> for PyRefMut<'py, T> { type Target = T; type Output = Bound<'py, T>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self.inner.clone()) } } impl<'a, 'py, T: PyClass> IntoPyObject<'py> for &'a PyRefMut<'py, T> { type Target = T; type Output = Borrowed<'a, 'py, T>; type Error = Infallible; fn into_pyobject(self, _py: Python<'py>) -> Result { Ok(self.inner.as_borrowed()) } } impl + fmt::Debug> fmt::Debug for PyRefMut<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(self.deref(), f) } } /// An error type returned by [`Bound::try_borrow`]. /// /// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`. pub struct PyBorrowError { _private: (), } impl fmt::Debug for PyBorrowError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PyBorrowError").finish() } } impl fmt::Display for PyBorrowError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt("Already mutably borrowed", f) } } impl From for PyErr { fn from(other: PyBorrowError) -> Self { PyRuntimeError::new_err(other.to_string()) } } /// An error type returned by [`Bound::try_borrow_mut`]. /// /// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`. pub struct PyBorrowMutError { _private: (), } impl fmt::Debug for PyBorrowMutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PyBorrowMutError").finish() } } impl fmt::Display for PyBorrowMutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt("Already borrowed", f) } } impl From for PyErr { fn from(other: PyBorrowMutError) -> Self { PyRuntimeError::new_err(other.to_string()) } } #[cfg(test)] #[cfg(feature = "macros")] mod tests { use super::*; #[crate::pyclass] #[pyo3(crate = "crate")] #[derive(Copy, Clone, PartialEq, Eq, Debug)] struct SomeClass(i32); #[test] fn test_as_ptr() { Python::with_gil(|py| { let cell = Bound::new(py, SomeClass(0)).unwrap(); let ptr = cell.as_ptr(); assert_eq!(cell.borrow().as_ptr(), ptr); assert_eq!(cell.borrow_mut().as_ptr(), ptr); }) } #[test] fn test_into_ptr() { Python::with_gil(|py| { let cell = Bound::new(py, SomeClass(0)).unwrap(); let ptr = cell.as_ptr(); assert_eq!(cell.borrow().into_ptr(), ptr); unsafe { ffi::Py_DECREF(ptr) }; assert_eq!(cell.borrow_mut().into_ptr(), ptr); unsafe { ffi::Py_DECREF(ptr) }; }) } #[crate::pyclass] #[pyo3(crate = "crate", subclass)] struct BaseClass { val1: usize, } #[crate::pyclass] #[pyo3(crate = "crate", extends=BaseClass, subclass)] struct SubClass { val2: usize, } #[crate::pyclass] #[pyo3(crate = "crate", extends=SubClass)] struct SubSubClass { val3: usize, } #[crate::pymethods] #[pyo3(crate = "crate")] impl SubSubClass { #[new] fn new(py: Python<'_>) -> crate::Py { let init = crate::PyClassInitializer::from(BaseClass { val1: 10 }) .add_subclass(SubClass { val2: 15 }) .add_subclass(SubSubClass { val3: 20 }); crate::Py::new(py, init).expect("allocation error") } fn get_values(self_: PyRef<'_, Self>) -> (usize, usize, usize) { let val1 = self_.as_super().as_super().val1; let val2 = self_.as_super().val2; (val1, val2, self_.val3) } fn double_values(mut self_: PyRefMut<'_, Self>) { self_.as_super().as_super().val1 *= 2; self_.as_super().val2 *= 2; self_.val3 *= 2; } } #[test] fn test_pyref_as_super() { Python::with_gil(|py| { let obj = SubSubClass::new(py).into_bound(py); let pyref = obj.borrow(); assert_eq!(pyref.as_super().as_super().val1, 10); assert_eq!(pyref.as_super().val2, 15); assert_eq!(pyref.as_ref().val2, 15); // `as_ref` also works assert_eq!(pyref.val3, 20); assert_eq!(SubSubClass::get_values(pyref), (10, 15, 20)); }); } #[test] fn test_pyrefmut_as_super() { Python::with_gil(|py| { let obj = SubSubClass::new(py).into_bound(py); assert_eq!(SubSubClass::get_values(obj.borrow()), (10, 15, 20)); { let mut pyrefmut = obj.borrow_mut(); assert_eq!(pyrefmut.as_super().as_ref().val1, 10); pyrefmut.as_super().as_super().val1 -= 5; pyrefmut.as_super().val2 -= 3; pyrefmut.as_mut().val2 -= 2; // `as_mut` also works pyrefmut.val3 -= 5; } assert_eq!(SubSubClass::get_values(obj.borrow()), (5, 10, 15)); SubSubClass::double_values(obj.borrow_mut()); assert_eq!(SubSubClass::get_values(obj.borrow()), (10, 20, 30)); }); } #[test] fn test_pyrefs_in_python() { Python::with_gil(|py| { let obj = SubSubClass::new(py); crate::py_run!(py, obj, "assert obj.get_values() == (10, 15, 20)"); crate::py_run!(py, obj, "assert obj.double_values() is None"); crate::py_run!(py, obj, "assert obj.get_values() == (20, 30, 40)"); }); } } pyo3/src/marker.rs0000644000175000017500000010731415105742312013720 0ustar bdrungbdrung//! Fundamental properties of objects tied to the Python interpreter. //! //! The Python interpreter is not thread-safe. To protect the Python interpreter in multithreaded //! scenarios there is a global lock, the *global interpreter lock* (hereafter referred to as *GIL*) //! that must be held to safely interact with Python objects. This is why in PyO3 when you acquire //! the GIL you get a [`Python`] marker token that carries the *lifetime* of holding the GIL and all //! borrowed references to Python objects carry this lifetime as well. This will statically ensure //! that you can never use Python objects after dropping the lock - if you mess this up it will be //! caught at compile time and your program will fail to compile. //! //! It also supports this pattern that many extension modules employ: //! - Drop the GIL, so that other Python threads can acquire it and make progress themselves //! - Do something independently of the Python interpreter, like IO, a long running calculation or //! awaiting a future //! - Once that is done, reacquire the GIL //! //! That API is provided by [`Python::allow_threads`] and enforced via the [`Ungil`] bound on the //! closure and the return type. This is done by relying on the [`Send`] auto trait. `Ungil` is //! defined as the following: //! //! ```rust,no_run //! # #![allow(dead_code)] //! pub unsafe trait Ungil {} //! //! unsafe impl Ungil for T {} //! ``` //! //! We piggy-back off the `Send` auto trait because it is not possible to implement custom auto //! traits on stable Rust. This is the solution which enables it for as many types as possible while //! making the API usable. //! //! In practice this API works quite well, but it comes with some drawbacks: //! //! ## Drawbacks //! //! There is no reason to prevent `!Send` types like [`Rc`] from crossing the closure. After all, //! [`Python::allow_threads`] just lets other Python threads run - it does not itself launch a new //! thread. //! //! ```rust, compile_fail //! # #[cfg(feature = "nightly")] //! # compile_error!("this actually works on nightly") //! use pyo3::prelude::*; //! use std::rc::Rc; //! //! fn main() { //! Python::with_gil(|py| { //! let rc = Rc::new(5); //! //! py.allow_threads(|| { //! // This would actually be fine... //! println!("{:?}", *rc); //! }); //! }); //! } //! ``` //! //! Because we are using `Send` for something it's not quite meant for, other code that //! (correctly) upholds the invariants of [`Send`] can cause problems. //! //! [`SendWrapper`] is one of those. Per its documentation: //! //! > A wrapper which allows you to move around non-Send-types between threads, as long as you //! > access the contained value only from within the original thread and make sure that it is //! > dropped from within the original thread. //! //! This will "work" to smuggle Python references across the closure, because we're not actually //! doing anything with threads: //! //! ```rust, no_run //! use pyo3::prelude::*; //! use pyo3::types::PyString; //! use send_wrapper::SendWrapper; //! //! Python::with_gil(|py| { //! let string = PyString::new(py, "foo"); //! //! let wrapped = SendWrapper::new(string); //! //! py.allow_threads(|| { //! # #[cfg(not(feature = "nightly"))] //! # { //! // 💥 Unsound! 💥 //! let smuggled: &Bound<'_, PyString> = &*wrapped; //! println!("{:?}", smuggled); //! # } //! }); //! }); //! ``` //! //! For now the answer to that is "don't do that". //! //! # A proper implementation using an auto trait //! //! However on nightly Rust and when PyO3's `nightly` feature is //! enabled, `Ungil` is defined as the following: //! //! ```rust,no_run //! # #[cfg(any())] //! # { //! #![feature(auto_traits, negative_impls)] //! //! pub unsafe auto trait Ungil {} //! //! // It is unimplemented for the `Python` struct and Python objects. //! impl !Ungil for Python<'_> {} //! impl !Ungil for ffi::PyObject {} //! //! // `Py` wraps it in a safe api, so this is OK //! unsafe impl Ungil for Py {} //! # } //! ``` //! //! With this feature enabled, the above two examples will start working and not working, respectively. //! //! [`SendWrapper`]: https://docs.rs/send_wrapper/latest/send_wrapper/struct.SendWrapper.html //! [`Rc`]: std::rc::Rc //! [`Py`]: crate::Py use crate::conversion::IntoPyObject; use crate::err::PyErr; use crate::err::{self, PyResult}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::gil::{GILGuard, SuspendGIL}; use crate::impl_::not_send::NotSend; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::types::{ PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType, }; use crate::version::PythonVersionInfo; use crate::{ffi, Bound, PyObject, PyTypeInfo}; use std::ffi::CStr; use std::marker::PhantomData; use std::os::raw::c_int; /// Types that are safe to access while the GIL is not held. /// /// # Safety /// /// The type must not carry borrowed Python references or, if it does, not allow access to them if /// the GIL is not held. /// /// See the [module-level documentation](self) for more information. /// /// # Examples /// /// This tracking is currently imprecise as it relies on the [`Send`] auto trait on stable Rust. /// For example, an `Rc` smart pointer should be usable without the GIL, but we currently prevent that: /// /// ```compile_fail /// # use pyo3::prelude::*; /// use std::rc::Rc; /// /// Python::with_gil(|py| { /// let rc = Rc::new(42); /// /// py.allow_threads(|| { /// println!("{:?}", rc); /// }); /// }); /// ``` /// /// This also implies that the interplay between `with_gil` and `allow_threads` is unsound, for example /// one can circumvent this protection using the [`send_wrapper`](https://docs.rs/send_wrapper/) crate: /// /// ```no_run /// # use pyo3::prelude::*; /// # use pyo3::types::PyString; /// use send_wrapper::SendWrapper; /// /// Python::with_gil(|py| { /// let string = PyString::new(py, "foo"); /// /// let wrapped = SendWrapper::new(string); /// /// py.allow_threads(|| { /// let sneaky: &Bound<'_, PyString> = &*wrapped; /// /// println!("{:?}", sneaky); /// }); /// }); /// ``` /// /// Fixing this loophole on stable Rust has significant ergonomic issues, but it is fixed when using /// nightly Rust and the `nightly` feature, c.f. [#2141](https://github.com/PyO3/pyo3/issues/2141). #[cfg_attr(docsrs, doc(cfg(all())))] // Hide the cfg flag #[cfg(not(feature = "nightly"))] pub unsafe trait Ungil {} #[cfg_attr(docsrs, doc(cfg(all())))] // Hide the cfg flag #[cfg(not(feature = "nightly"))] unsafe impl Ungil for T {} #[cfg(feature = "nightly")] mod nightly { macro_rules! define { ($($tt:tt)*) => { $($tt)* } } define! { /// Types that are safe to access while the GIL is not held. /// /// # Safety /// /// The type must not carry borrowed Python references or, if it does, not allow access to them if /// the GIL is not held. /// /// See the [module-level documentation](self) for more information. /// /// # Examples /// /// Types which are `Ungil` cannot be used in contexts where the GIL was released, e.g. /// /// ```compile_fail /// # use pyo3::prelude::*; /// # use pyo3::types::PyString; /// Python::with_gil(|py| { /// let string = PyString::new(py, "foo"); /// /// py.allow_threads(|| { /// println!("{:?}", string); /// }); /// }); /// ``` /// /// This applies to the GIL token `Python` itself as well, e.g. /// /// ```compile_fail /// # use pyo3::prelude::*; /// Python::with_gil(|py| { /// py.allow_threads(|| { /// drop(py); /// }); /// }); /// ``` /// /// On nightly Rust, this is not based on the [`Send`] auto trait and hence we are able /// to prevent incorrectly circumventing it using e.g. the [`send_wrapper`](https://docs.rs/send_wrapper/) crate: /// /// ```compile_fail /// # use pyo3::prelude::*; /// # use pyo3::types::PyString; /// use send_wrapper::SendWrapper; /// /// Python::with_gil(|py| { /// let string = PyString::new(py, "foo"); /// /// let wrapped = SendWrapper::new(string); /// /// py.allow_threads(|| { /// let sneaky: &PyString = *wrapped; /// /// println!("{:?}", sneaky); /// }); /// }); /// ``` /// /// This also enables using non-[`Send`] types in `allow_threads`, /// at least if they are not also bound to the GIL: /// /// ```rust /// # use pyo3::prelude::*; /// use std::rc::Rc; /// /// Python::with_gil(|py| { /// let rc = Rc::new(42); /// /// py.allow_threads(|| { /// println!("{:?}", rc); /// }); /// }); /// ``` pub unsafe auto trait Ungil {} } impl !Ungil for crate::Python<'_> {} // This means that PyString, PyList, etc all inherit !Ungil from this. impl !Ungil for crate::PyAny {} impl !Ungil for crate::PyRef<'_, T> {} impl !Ungil for crate::PyRefMut<'_, T> {} // FFI pointees impl !Ungil for crate::ffi::PyObject {} impl !Ungil for crate::ffi::PyLongObject {} impl !Ungil for crate::ffi::PyThreadState {} impl !Ungil for crate::ffi::PyInterpreterState {} impl !Ungil for crate::ffi::PyWeakReference {} impl !Ungil for crate::ffi::PyFrameObject {} impl !Ungil for crate::ffi::PyCodeObject {} #[cfg(not(Py_LIMITED_API))] impl !Ungil for crate::ffi::PyDictKeysObject {} #[cfg(not(any(Py_LIMITED_API, Py_3_10)))] impl !Ungil for crate::ffi::PyArena {} } #[cfg(feature = "nightly")] pub use nightly::Ungil; /// A marker token that represents holding the GIL. /// /// It serves three main purposes: /// - It provides a global API for the Python interpreter, such as [`Python::eval`]. /// - It can be passed to functions that require a proof of holding the GIL, such as /// [`Py::clone_ref`](crate::Py::clone_ref). /// - Its lifetime represents the scope of holding the GIL which can be used to create Rust /// references that are bound to it, such as [`Bound<'py, PyAny>`]. /// /// Note that there are some caveats to using it that you might need to be aware of. See the /// [Deadlocks](#deadlocks) and [Releasing and freeing memory](#releasing-and-freeing-memory) /// paragraphs for more information about that. /// /// # Obtaining a Python token /// /// The following are the recommended ways to obtain a [`Python<'py>`] token, in order of preference: /// - If you already have something with a lifetime bound to the GIL, such as [`Bound<'py, PyAny>`], you can /// use its `.py()` method to get a token. /// - In a function or method annotated with [`#[pyfunction]`](crate::pyfunction) or [`#[pymethods]`](crate::pymethods) you can declare it /// as a parameter, and PyO3 will pass in the token when Python code calls it. /// - When you need to acquire the GIL yourself, such as when calling Python code from Rust, you /// should call [`Python::with_gil`] to do that and pass your code as a closure to it. /// /// The first two options are zero-cost; [`Python::with_gil`] requires runtime checking and may need to block /// to acquire the GIL. /// /// # Deadlocks /// /// Note that the GIL can be temporarily released by the Python interpreter during a function call /// (e.g. importing a module). In general, you don't need to worry about this because the GIL is /// reacquired before returning to the Rust code: /// /// ```text /// `Python` exists |=====================================| /// GIL actually held |==========| |================| /// Rust code running |=======| |==| |======| /// ``` /// /// This behaviour can cause deadlocks when trying to lock a Rust mutex while holding the GIL: /// /// * Thread 1 acquires the GIL /// * Thread 1 locks a mutex /// * Thread 1 makes a call into the Python interpreter which releases the GIL /// * Thread 2 acquires the GIL /// * Thread 2 tries to locks the mutex, blocks /// * Thread 1's Python interpreter call blocks trying to reacquire the GIL held by thread 2 /// /// To avoid deadlocking, you should release the GIL before trying to lock a mutex or `await`ing in /// asynchronous code, e.g. with [`Python::allow_threads`]. /// /// # Releasing and freeing memory /// /// The [`Python<'py>`] type can be used to create references to variables owned by the Python /// interpreter, using functions such as [`Python::eval`] and [`PyModule::import`]. #[derive(Copy, Clone)] pub struct Python<'py>(PhantomData<(&'py GILGuard, NotSend)>); impl Python<'_> { /// Acquires the global interpreter lock, allowing access to the Python interpreter. The /// provided closure `F` will be executed with the acquired `Python` marker token. /// /// If implementing [`#[pymethods]`](crate::pymethods) or [`#[pyfunction]`](crate::pyfunction), /// declare `py: Python` as an argument. PyO3 will pass in the token to grant access to the GIL /// context in which the function is running, avoiding the need to call `with_gil`. /// /// If the [`auto-initialize`] feature is enabled and the Python runtime is not already /// initialized, this function will initialize it. See #[cfg_attr( not(any(PyPy, GraalPy)), doc = "[`prepare_freethreaded_python`](crate::prepare_freethreaded_python)" )] #[cfg_attr(PyPy, doc = "`prepare_freethreaded_python`")] /// for details. /// /// If the current thread does not yet have a Python "thread state" associated with it, /// a new one will be automatically created before `F` is executed and destroyed after `F` /// completes. /// /// # Panics /// /// - If the [`auto-initialize`] feature is not enabled and the Python interpreter is not /// initialized. /// /// # Examples /// /// ``` /// use pyo3::prelude::*; /// use pyo3::ffi::c_str; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let x: i32 = py.eval(c_str!("5"), None, None)?.extract()?; /// assert_eq!(x, 5); /// Ok(()) /// }) /// # } /// ``` /// /// [`auto-initialize`]: https://pyo3.rs/main/features.html#auto-initialize #[inline] #[track_caller] pub fn with_gil(f: F) -> R where F: for<'py> FnOnce(Python<'py>) -> R, { let guard = GILGuard::acquire(); // SAFETY: Either the GIL was already acquired or we just created a new `GILGuard`. f(guard.python()) } /// Like [`Python::with_gil`] except Python interpreter state checking is skipped. /// /// Normally when the GIL is acquired, we check that the Python interpreter is an /// appropriate state (e.g. it is fully initialized). This function skips those /// checks. /// /// # Safety /// /// If [`Python::with_gil`] would succeed, it is safe to call this function. /// /// In most cases, you should use [`Python::with_gil`]. /// /// A justified scenario for calling this function is during multi-phase interpreter /// initialization when [`Python::with_gil`] would fail before // this link is only valid on 3.8+not pypy and up. #[cfg_attr( all(Py_3_8, not(PyPy)), doc = "[`_Py_InitializeMain`](crate::ffi::_Py_InitializeMain)" )] #[cfg_attr(any(not(Py_3_8), PyPy), doc = "`_Py_InitializeMain`")] /// is called because the interpreter is only partially initialized. /// /// Behavior in other scenarios is not documented. #[inline] #[track_caller] pub unsafe fn with_gil_unchecked(f: F) -> R where F: for<'py> FnOnce(Python<'py>) -> R, { let guard = unsafe { GILGuard::acquire_unchecked() }; f(guard.python()) } } impl<'py> Python<'py> { /// Temporarily releases the GIL, thus allowing other Python threads to run. The GIL will be /// reacquired when `F`'s scope ends. /// /// If you don't need to touch the Python /// interpreter for some time and have other Python threads around, this will let you run /// Rust-only code while letting those other Python threads make progress. /// /// Only types that implement [`Ungil`] can cross the closure. See the /// [module level documentation](self) for more information. /// /// If you need to pass Python objects into the closure you can use [`Py`]``to create a /// reference independent of the GIL lifetime. However, you cannot do much with those without a /// [`Python`] token, for which you'd need to reacquire the GIL. /// /// # Example: Releasing the GIL while running a computation in Rust-only code /// /// ``` /// use pyo3::prelude::*; /// /// #[pyfunction] /// fn sum_numbers(py: Python<'_>, numbers: Vec) -> PyResult { /// // We release the GIL here so any other Python threads get a chance to run. /// py.allow_threads(move || { /// // An example of an "expensive" Rust calculation /// let sum = numbers.iter().sum(); /// /// Ok(sum) /// }) /// } /// # /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = pyo3::wrap_pyfunction!(sum_numbers, py)?; /// # let res = fun.call1((vec![1_u32, 2, 3],))?; /// # assert_eq!(res.extract::()?, 6_u32); /// # Ok(()) /// # }) /// # } /// ``` /// /// Please see the [Parallelism] chapter of the guide for a thorough discussion of using /// [`Python::allow_threads`] in this manner. /// /// # Example: Passing borrowed Python references into the closure is not allowed /// /// ```compile_fail /// use pyo3::prelude::*; /// use pyo3::types::PyString; /// /// fn parallel_print(py: Python<'_>) { /// let s = PyString::new(py, "This object cannot be accessed without holding the GIL >_<"); /// py.allow_threads(move || { /// println!("{:?}", s); // This causes a compile error. /// }); /// } /// ``` /// /// [`Py`]: crate::Py /// [`PyString`]: crate::types::PyString /// [auto-traits]: https://doc.rust-lang.org/nightly/unstable-book/language-features/auto-traits.html /// [Parallelism]: https://pyo3.rs/main/parallelism.html pub fn allow_threads(self, f: F) -> T where F: Ungil + FnOnce() -> T, T: Ungil, { // Use a guard pattern to handle reacquiring the GIL, // so that the GIL will be reacquired even if `f` panics. // The `Send` bound on the closure prevents the user from // transferring the `Python` token into the closure. let _guard = unsafe { SuspendGIL::new() }; f() } /// Evaluates a Python expression in the given context and returns the result. /// /// If `globals` is `None`, it defaults to Python module `__main__`. /// If `locals` is `None`, it defaults to the value of `globals`. /// /// If `globals` doesn't contain `__builtins__`, default `__builtins__` /// will be added automatically. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # use pyo3::ffi::c_str; /// # Python::with_gil(|py| { /// let result = py.eval(c_str!("[i * 10 for i in range(5)]"), None, None).unwrap(); /// let res: Vec = result.extract().unwrap(); /// assert_eq!(res, vec![0, 10, 20, 30, 40]) /// # }); /// ``` pub fn eval( self, code: &CStr, globals: Option<&Bound<'py, PyDict>>, locals: Option<&Bound<'py, PyDict>>, ) -> PyResult> { self.run_code(code, ffi::Py_eval_input, globals, locals) } /// Executes one or more Python statements in the given context. /// /// If `globals` is `None`, it defaults to Python module `__main__`. /// If `locals` is `None`, it defaults to the value of `globals`. /// /// If `globals` doesn't contain `__builtins__`, default `__builtins__` /// will be added automatically. /// /// # Examples /// ``` /// use pyo3::{ /// prelude::*, /// types::{PyBytes, PyDict}, /// ffi::c_str, /// }; /// Python::with_gil(|py| { /// let locals = PyDict::new(py); /// py.run(c_str!( /// r#" /// import base64 /// s = 'Hello Rust!' /// ret = base64.b64encode(s.encode('utf-8')) /// "#), /// None, /// Some(&locals), /// ) /// .unwrap(); /// let ret = locals.get_item("ret").unwrap().unwrap(); /// let b64 = ret.downcast::().unwrap(); /// assert_eq!(b64.as_bytes(), b"SGVsbG8gUnVzdCE="); /// }); /// ``` /// /// You can use [`py_run!`](macro.py_run.html) for a handy alternative of `run` /// if you don't need `globals` and unwrapping is OK. pub fn run( self, code: &CStr, globals: Option<&Bound<'py, PyDict>>, locals: Option<&Bound<'py, PyDict>>, ) -> PyResult<()> { let res = self.run_code(code, ffi::Py_file_input, globals, locals); res.map(|obj| { debug_assert!(obj.is_none()); }) } /// Runs code in the given context. /// /// `start` indicates the type of input expected: one of `Py_single_input`, /// `Py_file_input`, or `Py_eval_input`. /// /// If `globals` is `None`, it defaults to Python module `__main__`. /// If `locals` is `None`, it defaults to the value of `globals`. fn run_code( self, code: &CStr, start: c_int, globals: Option<&Bound<'py, PyDict>>, locals: Option<&Bound<'py, PyDict>>, ) -> PyResult> { let mptr = unsafe { ffi::compat::PyImport_AddModuleRef(ffi::c_str!("__main__").as_ptr()) .assume_owned_or_err(self)? }; let attr = mptr.getattr(crate::intern!(self, "__dict__"))?; let globals = match globals { Some(globals) => globals, None => attr.downcast::()?, }; let locals = locals.unwrap_or(globals); // If `globals` don't provide `__builtins__`, most of the code will fail if Python // version is <3.10. That's probably not what user intended, so insert `__builtins__` // for them. // // See also: // - https://github.com/python/cpython/pull/24564 (the same fix in CPython 3.10) // - https://github.com/PyO3/pyo3/issues/3370 let builtins_s = crate::intern!(self, "__builtins__"); let has_builtins = globals.contains(builtins_s)?; if !has_builtins { crate::sync::with_critical_section(globals, || { // check if another thread set __builtins__ while this thread was blocked on the critical section let has_builtins = globals.contains(builtins_s)?; if !has_builtins { // Inherit current builtins. let builtins = unsafe { ffi::PyEval_GetBuiltins() }; // `PyDict_SetItem` doesn't take ownership of `builtins`, but `PyEval_GetBuiltins` // seems to return a borrowed reference, so no leak here. if unsafe { ffi::PyDict_SetItem(globals.as_ptr(), builtins_s.as_ptr(), builtins) } == -1 { return Err(PyErr::fetch(self)); } } Ok(()) })?; } let code_obj = unsafe { ffi::Py_CompileString(code.as_ptr(), ffi::c_str!("").as_ptr(), start) .assume_owned_or_err(self)? }; unsafe { ffi::PyEval_EvalCode(code_obj.as_ptr(), globals.as_ptr(), locals.as_ptr()) .assume_owned_or_err(self) .downcast_into_unchecked() } } /// Gets the Python type object for type `T`. #[inline] pub fn get_type(self) -> Bound<'py, PyType> where T: PyTypeInfo, { T::type_object(self) } /// Imports the Python module with the specified name. pub fn import(self, name: N) -> PyResult> where N: IntoPyObject<'py, Target = PyString>, { PyModule::import(self, name) } /// Gets the Python builtin value `None`. #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn None(self) -> PyObject { PyNone::get(self).to_owned().into_any().unbind() } /// Gets the Python builtin value `Ellipsis`, or `...`. #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn Ellipsis(self) -> PyObject { PyEllipsis::get(self).to_owned().into_any().unbind() } /// Gets the Python builtin value `NotImplemented`. #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn NotImplemented(self) -> PyObject { PyNotImplemented::get(self).to_owned().into_any().unbind() } /// Gets the running Python interpreter version as a string. /// /// # Examples /// ```rust /// # use pyo3::Python; /// Python::with_gil(|py| { /// // The full string could be, for example: /// // "3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)]" /// assert!(py.version().starts_with("3.")); /// }); /// ``` pub fn version(self) -> &'py str { unsafe { CStr::from_ptr(ffi::Py_GetVersion()) .to_str() .expect("Python version string not UTF-8") } } /// Gets the running Python interpreter version as a struct similar to /// `sys.version_info`. /// /// # Examples /// ```rust /// # use pyo3::Python; /// Python::with_gil(|py| { /// // PyO3 supports Python 3.7 and up. /// assert!(py.version_info() >= (3, 7)); /// assert!(py.version_info() >= (3, 7, 0)); /// }); /// ``` pub fn version_info(self) -> PythonVersionInfo<'py> { let version_str = self.version(); // Portion of the version string returned by Py_GetVersion up to the first space is the // version number. let version_number_str = version_str.split(' ').next().unwrap_or(version_str); PythonVersionInfo::from_str(version_number_str).unwrap() } /// Lets the Python interpreter check and handle any pending signals. This will invoke the /// corresponding signal handlers registered in Python (if any). /// /// Returns `Err(`[`PyErr`]`)` if any signal handler raises an exception. /// /// These signals include `SIGINT` (normally raised by CTRL + C), which by default raises /// `KeyboardInterrupt`. For this reason it is good practice to call this function regularly /// as part of long-running Rust functions so that users can cancel it. /// /// # Example /// /// ```rust,no_run /// # #![allow(dead_code)] // this example is quite impractical to test /// use pyo3::prelude::*; /// /// # fn main() { /// #[pyfunction] /// fn loop_forever(py: Python<'_>) -> PyResult<()> { /// loop { /// // As this loop is infinite it should check for signals every once in a while. /// // Using `?` causes any `PyErr` (potentially containing `KeyboardInterrupt`) /// // to break out of the loop. /// py.check_signals()?; /// /// // do work here /// # break Ok(()) // don't actually loop forever /// } /// } /// # } /// ``` /// /// # Note /// /// This function calls [`PyErr_CheckSignals()`][1] which in turn may call signal handlers. /// As Python's [`signal`][2] API allows users to define custom signal handlers, calling this /// function allows arbitrary Python code inside signal handlers to run. /// /// If the function is called from a non-main thread, or under a non-main Python interpreter, /// it does nothing yet still returns `Ok(())`. /// /// [1]: https://docs.python.org/3/c-api/exceptions.html?highlight=pyerr_checksignals#c.PyErr_CheckSignals /// [2]: https://docs.python.org/3/library/signal.html pub fn check_signals(self) -> PyResult<()> { err::error_on_minusone(self, unsafe { ffi::PyErr_CheckSignals() }) } } impl<'unbound> Python<'unbound> { /// Unsafely creates a Python token with an unbounded lifetime. /// /// Many of PyO3 APIs use `Python<'_>` as proof that the GIL is held, but this function can be /// used to call them unsafely. /// /// # Safety /// /// - This token and any borrowed Python references derived from it can only be safely used /// whilst the currently executing thread is actually holding the GIL. /// - This function creates a token with an *unbounded* lifetime. Safe code can assume that /// holding a `Python<'py>` token means the GIL is and stays acquired for the lifetime `'py`. /// If you let it or borrowed Python references escape to safe code you are /// responsible for bounding the lifetime `'unbound` appropriately. For more on unbounded /// lifetimes, see the [nomicon]. /// /// [nomicon]: https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html #[inline] pub unsafe fn assume_gil_acquired() -> Python<'unbound> { Python(PhantomData) } } #[cfg(test)] mod tests { use super::*; use crate::types::{IntoPyDict, PyList}; #[test] fn test_eval() { Python::with_gil(|py| { // Make sure builtin names are accessible let v: i32 = py .eval(ffi::c_str!("min(1, 2)"), None, None) .map_err(|e| e.display(py)) .unwrap() .extract() .unwrap(); assert_eq!(v, 1); let d = [("foo", 13)].into_py_dict(py).unwrap(); // Inject our own global namespace let v: i32 = py .eval(ffi::c_str!("foo + 29"), Some(&d), None) .unwrap() .extract() .unwrap(); assert_eq!(v, 42); // Inject our own local namespace let v: i32 = py .eval(ffi::c_str!("foo + 29"), None, Some(&d)) .unwrap() .extract() .unwrap(); assert_eq!(v, 42); // Make sure builtin names are still accessible when using a local namespace let v: i32 = py .eval(ffi::c_str!("min(foo, 2)"), None, Some(&d)) .unwrap() .extract() .unwrap(); assert_eq!(v, 2); }); } #[test] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled fn test_allow_threads_releases_and_acquires_gil() { Python::with_gil(|py| { let b = std::sync::Arc::new(std::sync::Barrier::new(2)); let b2 = b.clone(); std::thread::spawn(move || Python::with_gil(|_| b2.wait())); py.allow_threads(|| { // If allow_threads does not release the GIL, this will deadlock because // the thread spawned above will never be able to acquire the GIL. b.wait(); }); unsafe { // If the GIL is not reacquired at the end of allow_threads, this call // will crash the Python interpreter. let tstate = ffi::PyEval_SaveThread(); ffi::PyEval_RestoreThread(tstate); } }); } #[test] fn test_allow_threads_panics_safely() { Python::with_gil(|py| { let result = std::panic::catch_unwind(|| unsafe { let py = Python::assume_gil_acquired(); py.allow_threads(|| { panic!("There was a panic!"); }); }); // Check panic was caught assert!(result.is_err()); // If allow_threads is implemented correctly, this thread still owns the GIL here // so the following Python calls should not cause crashes. let list = PyList::new(py, [1, 2, 3, 4]).unwrap(); assert_eq!(list.extract::>().unwrap(), vec![1, 2, 3, 4]); }); } #[cfg(not(pyo3_disable_reference_pool))] #[test] fn test_allow_threads_pass_stuff_in() { let list = Python::with_gil(|py| PyList::new(py, vec!["foo", "bar"]).unwrap().unbind()); let mut v = vec![1, 2, 3]; let a = std::sync::Arc::new(String::from("foo")); Python::with_gil(|py| { py.allow_threads(|| { drop((list, &mut v, a)); }); }); } #[test] #[cfg(not(Py_LIMITED_API))] fn test_acquire_gil() { const GIL_NOT_HELD: c_int = 0; const GIL_HELD: c_int = 1; // Before starting the interpreter the state of calling `PyGILState_Check` // seems to be undefined, so let's ensure that Python is up. #[cfg(not(any(PyPy, GraalPy)))] crate::prepare_freethreaded_python(); let state = unsafe { crate::ffi::PyGILState_Check() }; assert_eq!(state, GIL_NOT_HELD); Python::with_gil(|_| { let state = unsafe { crate::ffi::PyGILState_Check() }; assert_eq!(state, GIL_HELD); }); let state = unsafe { crate::ffi::PyGILState_Check() }; assert_eq!(state, GIL_NOT_HELD); } #[test] fn test_ellipsis() { Python::with_gil(|py| { assert_eq!(py.Ellipsis().to_string(), "Ellipsis"); let v = py .eval(ffi::c_str!("..."), None, None) .map_err(|e| e.display(py)) .unwrap(); assert!(v.eq(py.Ellipsis()).unwrap()); }); } #[test] fn test_py_run_inserts_globals() { use crate::types::dict::PyDictMethods; Python::with_gil(|py| { let namespace = PyDict::new(py); py.run( ffi::c_str!("class Foo: pass\na = int(3)"), Some(&namespace), Some(&namespace), ) .unwrap(); assert!(matches!(namespace.get_item("Foo"), Ok(Some(..)))); assert!(matches!(namespace.get_item("a"), Ok(Some(..)))); // 3.9 and older did not automatically insert __builtins__ if it wasn't inserted "by hand" #[cfg(not(Py_3_10))] assert!(matches!(namespace.get_item("__builtins__"), Ok(Some(..)))); }) } #[cfg(feature = "macros")] #[test] fn test_py_run_inserts_globals_2() { use std::ffi::CString; #[crate::pyclass(crate = "crate")] #[derive(Clone)] struct CodeRunner { code: CString, } impl CodeRunner { fn reproducer(&mut self, py: Python<'_>) -> PyResult<()> { let variables = PyDict::new(py); variables.set_item("cls", crate::Py::new(py, self.clone())?)?; py.run(self.code.as_c_str(), Some(&variables), None)?; Ok(()) } } #[crate::pymethods(crate = "crate")] impl CodeRunner { fn func(&mut self, py: Python<'_>) -> PyResult<()> { py.import("math")?; Ok(()) } } let mut runner = CodeRunner { code: CString::new( r#" cls.func() "# .to_string(), ) .unwrap(), }; Python::with_gil(|py| { runner.reproducer(py).unwrap(); }); } } pyo3/src/gil.rs0000644000175000017500000005466315105742312013222 0ustar bdrungbdrung//! Interaction with Python's global interpreter lock #[cfg(pyo3_disable_reference_pool)] use crate::impl_::panic::PanicTrap; use crate::{ffi, Python}; #[cfg(not(pyo3_disable_reference_pool))] use once_cell::sync::Lazy; use std::cell::Cell; use std::{mem, ptr::NonNull, sync}; static START: sync::Once = sync::Once::new(); std::thread_local! { /// This is an internal counter in pyo3 monitoring whether this thread has the GIL. /// /// It will be incremented whenever a GILGuard or GILPool is created, and decremented whenever /// they are dropped. /// /// As a result, if this thread has the GIL, GIL_COUNT is greater than zero. /// /// Additionally, we sometimes need to prevent safe access to the GIL, /// e.g. when implementing `__traverse__`, which is represented by a negative value. static GIL_COUNT: Cell = const { Cell::new(0) }; } const GIL_LOCKED_DURING_TRAVERSE: isize = -1; /// Checks whether the GIL is acquired. /// /// Note: This uses pyo3's internal count rather than PyGILState_Check for two reasons: /// 1) for performance /// 2) PyGILState_Check always returns 1 if the sub-interpreter APIs have ever been called, /// which could lead to incorrect conclusions that the GIL is held. #[inline(always)] fn gil_is_acquired() -> bool { GIL_COUNT.try_with(|c| c.get() > 0).unwrap_or(false) } /// Prepares the use of Python in a free-threaded context. /// /// If the Python interpreter is not already initialized, this function will initialize it with /// signal handling disabled (Python will not raise the `KeyboardInterrupt` exception). Python /// signal handling depends on the notion of a 'main thread', which must be the thread that /// initializes the Python interpreter. /// /// If the Python interpreter is already initialized, this function has no effect. /// /// This function is unavailable under PyPy because PyPy cannot be embedded in Rust (or any other /// software). Support for this is tracked on the /// [PyPy issue tracker](https://github.com/pypy/pypy/issues/3836). /// /// # Examples /// ```rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// pyo3::prepare_freethreaded_python(); /// Python::with_gil(|py| py.run(pyo3::ffi::c_str!("print('Hello World')"), None, None)) /// # } /// ``` #[cfg(not(any(PyPy, GraalPy)))] pub fn prepare_freethreaded_python() { // Protect against race conditions when Python is not yet initialized and multiple threads // concurrently call 'prepare_freethreaded_python()'. Note that we do not protect against // concurrent initialization of the Python runtime by other users of the Python C API. START.call_once_force(|_| unsafe { // Use call_once_force because if initialization panics, it's okay to try again. if ffi::Py_IsInitialized() == 0 { ffi::Py_InitializeEx(0); // Release the GIL. ffi::PyEval_SaveThread(); } }); } /// Executes the provided closure with an embedded Python interpreter. /// /// This function initializes the Python interpreter, executes the provided closure, and then /// finalizes the Python interpreter. /// /// After execution all Python resources are cleaned up, and no further Python APIs can be called. /// Because many Python modules implemented in C do not support multiple Python interpreters in a /// single process, it is not safe to call this function more than once. (Many such modules will not /// initialize correctly on the second run.) /// /// # Panics /// - If the Python interpreter is already initialized before calling this function. /// /// # Safety /// - This function should only ever be called once per process (usually as part of the `main` /// function). It is also not thread-safe. /// - No Python APIs can be used after this function has finished executing. /// - The return value of the closure must not contain any Python value, _including_ `PyResult`. /// /// # Examples /// /// ```rust /// unsafe { /// pyo3::with_embedded_python_interpreter(|py| { /// if let Err(e) = py.run(pyo3::ffi::c_str!("print('Hello World')"), None, None) { /// // We must make sure to not return a `PyErr`! /// e.print(py); /// } /// }); /// } /// ``` #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn with_embedded_python_interpreter(f: F) -> R where F: for<'p> FnOnce(Python<'p>) -> R, { assert_eq!( unsafe { ffi::Py_IsInitialized() }, 0, "called `with_embedded_python_interpreter` but a Python interpreter is already running." ); unsafe { ffi::Py_InitializeEx(0) }; let result = { let guard = unsafe { GILGuard::assume() }; let py = guard.python(); // Import the threading module - this ensures that it will associate this thread as the "main" // thread, which is important to avoid an `AssertionError` at finalization. py.import("threading").unwrap(); // Execute the closure. f(py) }; // Finalize the Python interpreter. unsafe { ffi::Py_Finalize() }; result } /// RAII type that represents the Global Interpreter Lock acquisition. pub(crate) enum GILGuard { /// Indicates the GIL was already held with this GILGuard was acquired. Assumed, /// Indicates that we actually acquired the GIL when this GILGuard was acquired Ensured { gstate: ffi::PyGILState_STATE }, } impl GILGuard { /// PyO3 internal API for acquiring the GIL. The public API is Python::with_gil. /// /// If the GIL was already acquired via PyO3, this returns /// `GILGuard::Assumed`. Otherwise, the GIL will be acquired and /// `GILGuard::Ensured` will be returned. pub(crate) fn acquire() -> Self { if gil_is_acquired() { // SAFETY: We just checked that the GIL is already acquired. return unsafe { Self::assume() }; } // Maybe auto-initialize the GIL: // - If auto-initialize feature set and supported, try to initialize the interpreter. // - If the auto-initialize feature is set but unsupported, emit hard errors only when the // extension-module feature is not activated - extension modules don't care about // auto-initialize so this avoids breaking existing builds. // - Otherwise, just check the GIL is initialized. #[cfg(all(feature = "auto-initialize", not(any(PyPy, GraalPy))))] { prepare_freethreaded_python(); } #[cfg(not(all(feature = "auto-initialize", not(any(PyPy, GraalPy)))))] { // This is a "hack" to make running `cargo test` for PyO3 convenient (i.e. no need // to specify `--features auto-initialize` manually. Tests within the crate itself // all depend on the auto-initialize feature for conciseness but Cargo does not // provide a mechanism to specify required features for tests. #[cfg(not(any(PyPy, GraalPy)))] if option_env!("CARGO_PRIMARY_PACKAGE").is_some() { prepare_freethreaded_python(); } START.call_once_force(|_| unsafe { // Use call_once_force because if there is a panic because the interpreter is // not initialized, it's fine for the user to initialize the interpreter and // retry. assert_ne!( ffi::Py_IsInitialized(), 0, "The Python interpreter is not initialized and the `auto-initialize` \ feature is not enabled.\n\n\ Consider calling `pyo3::prepare_freethreaded_python()` before attempting \ to use Python APIs." ); }); } // SAFETY: We have ensured the Python interpreter is initialized. unsafe { Self::acquire_unchecked() } } /// Acquires the `GILGuard` without performing any state checking. /// /// This can be called in "unsafe" contexts where the normal interpreter state /// checking performed by `GILGuard::acquire` may fail. This includes calling /// as part of multi-phase interpreter initialization. pub(crate) unsafe fn acquire_unchecked() -> Self { if gil_is_acquired() { return unsafe { Self::assume() }; } let gstate = unsafe { ffi::PyGILState_Ensure() }; // acquire GIL increment_gil_count(); #[cfg(not(pyo3_disable_reference_pool))] if let Some(pool) = Lazy::get(&POOL) { pool.update_counts(unsafe { Python::assume_gil_acquired() }); } GILGuard::Ensured { gstate } } /// Acquires the `GILGuard` while assuming that the GIL is already held. pub(crate) unsafe fn assume() -> Self { increment_gil_count(); let guard = GILGuard::Assumed; #[cfg(not(pyo3_disable_reference_pool))] if let Some(pool) = Lazy::get(&POOL) { pool.update_counts(guard.python()); } guard } /// Gets the Python token associated with this [`GILGuard`]. #[inline] pub fn python(&self) -> Python<'_> { unsafe { Python::assume_gil_acquired() } } } /// The Drop implementation for `GILGuard` will release the GIL. impl Drop for GILGuard { fn drop(&mut self) { match self { GILGuard::Assumed => {} GILGuard::Ensured { gstate } => unsafe { // Drop the objects in the pool before attempting to release the thread state ffi::PyGILState_Release(*gstate); }, } decrement_gil_count(); } } // Vector of PyObject type PyObjVec = Vec>; #[cfg(not(pyo3_disable_reference_pool))] /// Thread-safe storage for objects which were dec_ref while the GIL was not held. struct ReferencePool { pending_decrefs: sync::Mutex, } #[cfg(not(pyo3_disable_reference_pool))] impl ReferencePool { const fn new() -> Self { Self { pending_decrefs: sync::Mutex::new(Vec::new()), } } fn register_decref(&self, obj: NonNull) { self.pending_decrefs.lock().unwrap().push(obj); } fn update_counts(&self, _py: Python<'_>) { let mut pending_decrefs = self.pending_decrefs.lock().unwrap(); if pending_decrefs.is_empty() { return; } let decrefs = mem::take(&mut *pending_decrefs); drop(pending_decrefs); for ptr in decrefs { unsafe { ffi::Py_DECREF(ptr.as_ptr()) }; } } } #[cfg(not(pyo3_disable_reference_pool))] unsafe impl Send for ReferencePool {} #[cfg(not(pyo3_disable_reference_pool))] unsafe impl Sync for ReferencePool {} #[cfg(not(pyo3_disable_reference_pool))] static POOL: Lazy = Lazy::new(ReferencePool::new); /// A guard which can be used to temporarily release the GIL and restore on `Drop`. pub(crate) struct SuspendGIL { count: isize, tstate: *mut ffi::PyThreadState, } impl SuspendGIL { pub(crate) unsafe fn new() -> Self { let count = GIL_COUNT.with(|c| c.replace(0)); let tstate = unsafe { ffi::PyEval_SaveThread() }; Self { count, tstate } } } impl Drop for SuspendGIL { fn drop(&mut self) { GIL_COUNT.with(|c| c.set(self.count)); unsafe { ffi::PyEval_RestoreThread(self.tstate); // Update counts of PyObjects / Py that were cloned or dropped while the GIL was released. #[cfg(not(pyo3_disable_reference_pool))] if let Some(pool) = Lazy::get(&POOL) { pool.update_counts(Python::assume_gil_acquired()); } } } } /// Used to lock safe access to the GIL pub(crate) struct LockGIL { count: isize, } impl LockGIL { /// Lock access to the GIL while an implementation of `__traverse__` is running pub fn during_traverse() -> Self { Self::new(GIL_LOCKED_DURING_TRAVERSE) } fn new(reason: isize) -> Self { let count = GIL_COUNT.with(|c| c.replace(reason)); Self { count } } #[cold] fn bail(current: isize) { match current { GIL_LOCKED_DURING_TRAVERSE => panic!( "Access to the GIL is prohibited while a __traverse__ implmentation is running." ), _ => panic!("Access to the GIL is currently prohibited."), } } } impl Drop for LockGIL { fn drop(&mut self) { GIL_COUNT.with(|c| c.set(self.count)); } } /// Increments the reference count of a Python object if the GIL is held. If /// the GIL is not held, this function will panic. /// /// # Safety /// The object must be an owned Python reference. #[cfg(feature = "py-clone")] #[track_caller] pub unsafe fn register_incref(obj: NonNull) { if gil_is_acquired() { unsafe { ffi::Py_INCREF(obj.as_ptr()) } } else { panic!("Cannot clone pointer into Python heap without the GIL being held."); } } /// Registers a Python object pointer inside the release pool, to have its reference count decreased /// the next time the GIL is acquired in pyo3. /// /// If the GIL is held, the reference count will be decreased immediately instead of being queued /// for later. /// /// # Safety /// The object must be an owned Python reference. #[track_caller] pub unsafe fn register_decref(obj: NonNull) { if gil_is_acquired() { unsafe { ffi::Py_DECREF(obj.as_ptr()) } } else { #[cfg(not(pyo3_disable_reference_pool))] POOL.register_decref(obj); #[cfg(all( pyo3_disable_reference_pool, not(pyo3_leak_on_drop_without_reference_pool) ))] { let _trap = PanicTrap::new("Aborting the process to avoid panic-from-drop."); panic!("Cannot drop pointer into Python heap without the GIL being held."); } } } /// Increments pyo3's internal GIL count - to be called whenever GILPool or GILGuard is created. #[inline(always)] fn increment_gil_count() { // Ignores the error in case this function called from `atexit`. let _ = GIL_COUNT.try_with(|c| { let current = c.get(); if current < 0 { LockGIL::bail(current); } c.set(current + 1); }); } /// Decrements pyo3's internal GIL count - to be called whenever GILPool or GILGuard is dropped. #[inline(always)] fn decrement_gil_count() { // Ignores the error in case this function called from `atexit`. let _ = GIL_COUNT.try_with(|c| { let current = c.get(); debug_assert!( current > 0, "Negative GIL count detected. Please report this error to the PyO3 repo as a bug." ); c.set(current - 1); }); } #[cfg(test)] mod tests { use super::GIL_COUNT; #[cfg(not(pyo3_disable_reference_pool))] use super::{gil_is_acquired, POOL}; use crate::{ffi, PyObject, Python}; use crate::{gil::GILGuard, types::any::PyAnyMethods}; use std::ptr::NonNull; fn get_object(py: Python<'_>) -> PyObject { py.eval(ffi::c_str!("object()"), None, None) .unwrap() .unbind() } #[cfg(not(pyo3_disable_reference_pool))] fn pool_dec_refs_does_not_contain(obj: &PyObject) -> bool { !POOL .pending_decrefs .lock() .unwrap() .contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) }) } // with no GIL, threads can empty the POOL at any time, so this // function does not test anything meaningful #[cfg(not(any(pyo3_disable_reference_pool, Py_GIL_DISABLED)))] fn pool_dec_refs_contains(obj: &PyObject) -> bool { POOL.pending_decrefs .lock() .unwrap() .contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) }) } #[test] fn test_pyobject_drop_with_gil_decreases_refcnt() { Python::with_gil(|py| { let obj = get_object(py); // Create a reference to drop with the GIL. let reference = obj.clone_ref(py); assert_eq!(obj.get_refcnt(py), 2); #[cfg(not(pyo3_disable_reference_pool))] assert!(pool_dec_refs_does_not_contain(&obj)); // With the GIL held, reference count will be decreased immediately. drop(reference); assert_eq!(obj.get_refcnt(py), 1); #[cfg(not(any(pyo3_disable_reference_pool)))] assert!(pool_dec_refs_does_not_contain(&obj)); }); } #[test] #[cfg(all(not(pyo3_disable_reference_pool), not(target_arch = "wasm32")))] // We are building wasm Python with pthreads disabled fn test_pyobject_drop_without_gil_doesnt_decrease_refcnt() { let obj = Python::with_gil(|py| { let obj = get_object(py); // Create a reference to drop without the GIL. let reference = obj.clone_ref(py); assert_eq!(obj.get_refcnt(py), 2); assert!(pool_dec_refs_does_not_contain(&obj)); // Drop reference in a separate thread which doesn't have the GIL. std::thread::spawn(move || drop(reference)).join().unwrap(); // The reference count should not have changed (the GIL has always // been held by this thread), it is remembered to release later. assert_eq!(obj.get_refcnt(py), 2); #[cfg(not(Py_GIL_DISABLED))] assert!(pool_dec_refs_contains(&obj)); obj }); // Next time the GIL is acquired, the reference is released #[allow(unused)] Python::with_gil(|py| { // with no GIL, another thread could still be processing // DECREFs after releasing the lock on the POOL, so the // refcnt could still be 2 when this assert happens #[cfg(not(Py_GIL_DISABLED))] assert_eq!(obj.get_refcnt(py), 1); assert!(pool_dec_refs_does_not_contain(&obj)); }); } #[test] #[allow(deprecated)] fn test_gil_counts() { // Check with_gil and GILGuard both increase counts correctly let get_gil_count = || GIL_COUNT.with(|c| c.get()); assert_eq!(get_gil_count(), 0); Python::with_gil(|_| { assert_eq!(get_gil_count(), 1); let pool = unsafe { GILGuard::assume() }; assert_eq!(get_gil_count(), 2); let pool2 = unsafe { GILGuard::assume() }; assert_eq!(get_gil_count(), 3); drop(pool); assert_eq!(get_gil_count(), 2); Python::with_gil(|_| { // nested with_gil updates gil count assert_eq!(get_gil_count(), 3); }); assert_eq!(get_gil_count(), 2); drop(pool2); assert_eq!(get_gil_count(), 1); }); assert_eq!(get_gil_count(), 0); } #[test] fn test_allow_threads() { assert!(!gil_is_acquired()); Python::with_gil(|py| { assert!(gil_is_acquired()); py.allow_threads(move || { assert!(!gil_is_acquired()); Python::with_gil(|_| assert!(gil_is_acquired())); assert!(!gil_is_acquired()); }); assert!(gil_is_acquired()); }); assert!(!gil_is_acquired()); } #[cfg(feature = "py-clone")] #[test] #[should_panic] fn test_allow_threads_updates_refcounts() { Python::with_gil(|py| { // Make a simple object with 1 reference let obj = get_object(py); assert!(obj.get_refcnt(py) == 1); // Clone the object without the GIL which should panic py.allow_threads(|| obj.clone()); }); } #[test] fn dropping_gil_does_not_invalidate_references() { // Acquiring GIL for the second time should be safe - see #864 Python::with_gil(|py| { let obj = Python::with_gil(|_| py.eval(ffi::c_str!("object()"), None, None).unwrap()); // After gil2 drops, obj should still have a reference count of one assert_eq!(obj.get_refcnt(), 1); }) } #[cfg(feature = "py-clone")] #[test] fn test_clone_with_gil() { Python::with_gil(|py| { let obj = get_object(py); let count = obj.get_refcnt(py); // Cloning with the GIL should increase reference count immediately #[allow(clippy::redundant_clone)] let c = obj.clone(); assert_eq!(count + 1, c.get_refcnt(py)); }) } #[test] #[cfg(not(pyo3_disable_reference_pool))] fn test_update_counts_does_not_deadlock() { // update_counts can run arbitrary Python code during Py_DECREF. // if the locking is implemented incorrectly, it will deadlock. use crate::ffi; use crate::gil::GILGuard; Python::with_gil(|py| { let obj = get_object(py); unsafe extern "C" fn capsule_drop(capsule: *mut ffi::PyObject) { // This line will implicitly call update_counts // -> and so cause deadlock if update_counts is not handling recursion correctly. let pool = unsafe { GILGuard::assume() }; // Rebuild obj so that it can be dropped unsafe { PyObject::from_owned_ptr( pool.python(), ffi::PyCapsule_GetPointer(capsule, std::ptr::null()) as _, ) }; } let ptr = obj.into_ptr(); let capsule = unsafe { ffi::PyCapsule_New(ptr as _, std::ptr::null(), Some(capsule_drop)) }; POOL.register_decref(NonNull::new(capsule).unwrap()); // Updating the counts will call decref on the capsule, which calls capsule_drop POOL.update_counts(py); }) } #[test] #[cfg(not(pyo3_disable_reference_pool))] fn test_gil_guard_update_counts() { use crate::gil::GILGuard; Python::with_gil(|py| { let obj = get_object(py); // For GILGuard::acquire POOL.register_decref(NonNull::new(obj.clone_ref(py).into_ptr()).unwrap()); #[cfg(not(Py_GIL_DISABLED))] assert!(pool_dec_refs_contains(&obj)); let _guard = GILGuard::acquire(); assert!(pool_dec_refs_does_not_contain(&obj)); // For GILGuard::assume POOL.register_decref(NonNull::new(obj.clone_ref(py).into_ptr()).unwrap()); #[cfg(not(Py_GIL_DISABLED))] assert!(pool_dec_refs_contains(&obj)); let _guard2 = unsafe { GILGuard::assume() }; assert!(pool_dec_refs_does_not_contain(&obj)); }) } } pyo3/src/coroutine/0000775000175000017500000000000015105742312014074 5ustar bdrungbdrungpyo3/src/coroutine/waker.rs0000644000175000017500000000731315105742312015555 0ustar bdrungbdrunguse crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::PyCFunction; use crate::{intern, wrap_pyfunction, Bound, Py, PyAny, PyObject, PyResult, Python}; use pyo3_macros::pyfunction; use std::sync::Arc; use std::task::Wake; /// Lazy `asyncio.Future` wrapper, implementing [`Wake`] by calling `Future.set_result`. /// /// asyncio future is let uninitialized until [`initialize_future`][1] is called. /// If [`wake`][2] is called before future initialization (during Rust future polling), /// [`initialize_future`][1] will return `None` (it is roughly equivalent to `asyncio.sleep(0)`) /// /// [1]: AsyncioWaker::initialize_future /// [2]: AsyncioWaker::wake pub struct AsyncioWaker(GILOnceCell>); impl AsyncioWaker { pub(super) fn new() -> Self { Self(GILOnceCell::new()) } pub(super) fn reset(&mut self) { self.0.take(); } pub(super) fn initialize_future<'py>( &self, py: Python<'py>, ) -> PyResult>> { let init = || LoopAndFuture::new(py).map(Some); let loop_and_future = self.0.get_or_try_init(py, init)?.as_ref(); Ok(loop_and_future.map(|LoopAndFuture { future, .. }| future.bind(py))) } } impl Wake for AsyncioWaker { fn wake(self: Arc) { self.wake_by_ref() } fn wake_by_ref(self: &Arc) { Python::with_gil(|py| { if let Some(loop_and_future) = self.0.get_or_init(py, || None) { loop_and_future .set_result(py) .expect("unexpected error in coroutine waker"); } }); } } struct LoopAndFuture { event_loop: PyObject, future: PyObject, } impl LoopAndFuture { fn new(py: Python<'_>) -> PyResult { static GET_RUNNING_LOOP: GILOnceCell = GILOnceCell::new(); let import = || -> PyResult<_> { let module = py.import("asyncio")?; Ok(module.getattr("get_running_loop")?.into()) }; let event_loop = GET_RUNNING_LOOP.get_or_try_init(py, import)?.call0(py)?; let future = event_loop.call_method0(py, "create_future")?; Ok(Self { event_loop, future }) } fn set_result(&self, py: Python<'_>) -> PyResult<()> { static RELEASE_WAITER: GILOnceCell> = GILOnceCell::new(); let release_waiter = RELEASE_WAITER.get_or_try_init(py, || { wrap_pyfunction!(release_waiter, py).map(Bound::unbind) })?; // `Future.set_result` must be called in event loop thread, // so it requires `call_soon_threadsafe` let call_soon_threadsafe = self.event_loop.call_method1( py, intern!(py, "call_soon_threadsafe"), (release_waiter, self.future.bind(py)), ); if let Err(err) = call_soon_threadsafe { // `call_soon_threadsafe` will raise if the event loop is closed; // instead of catching an unspecific `RuntimeError`, check directly if it's closed. let is_closed = self.event_loop.call_method0(py, "is_closed")?; if !is_closed.extract(py)? { return Err(err); } } Ok(()) } } /// Call `future.set_result` if the future is not done. /// /// Future can be cancelled by the event loop before being waken. /// See #[pyfunction(crate = "crate")] fn release_waiter(future: &Bound<'_, PyAny>) -> PyResult<()> { let done = future.call_method0(intern!(future.py(), "done"))?; if !done.extract::()? { future.call_method1(intern!(future.py(), "set_result"), (future.py().None(),))?; } Ok(()) } pyo3/src/coroutine/cancel.rs0000644000175000017500000000414715105742312015673 0ustar bdrungbdrunguse crate::{Py, PyAny, PyObject}; use std::future::Future; use std::pin::Pin; use std::sync::{Arc, Mutex}; use std::task::{Context, Poll, Waker}; #[derive(Debug, Default)] struct Inner { exception: Option, waker: Option, } /// Helper used to wait and retrieve exception thrown in [`Coroutine`](super::Coroutine). /// /// Only the last exception thrown can be retrieved. #[derive(Debug, Default)] pub struct CancelHandle(Arc>); impl CancelHandle { /// Create a new `CoroutineCancel`. pub fn new() -> Self { Default::default() } /// Returns whether the associated coroutine has been cancelled. pub fn is_cancelled(&self) -> bool { self.0.lock().unwrap().exception.is_some() } /// Poll to retrieve the exception thrown in the associated coroutine. pub fn poll_cancelled(&mut self, cx: &mut Context<'_>) -> Poll { let mut inner = self.0.lock().unwrap(); if let Some(exc) = inner.exception.take() { return Poll::Ready(exc); } if let Some(ref waker) = inner.waker { if cx.waker().will_wake(waker) { return Poll::Pending; } } inner.waker = Some(cx.waker().clone()); Poll::Pending } /// Retrieve the exception thrown in the associated coroutine. pub async fn cancelled(&mut self) -> PyObject { Cancelled(self).await } #[doc(hidden)] pub fn throw_callback(&self) -> ThrowCallback { ThrowCallback(self.0.clone()) } } // Because `poll_fn` is not available in MSRV struct Cancelled<'a>(&'a mut CancelHandle); impl Future for Cancelled<'_> { type Output = PyObject; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.0.poll_cancelled(cx) } } #[doc(hidden)] pub struct ThrowCallback(Arc>); impl ThrowCallback { pub(super) fn throw(&self, exc: Py) { let mut inner = self.0.lock().unwrap(); inner.exception = Some(exc); if let Some(waker) = inner.waker.take() { waker.wake(); } } } pyo3/src/ffi_ptr_ext.rs0000644000175000017500000000603515105742312014746 0ustar bdrungbdrunguse crate::sealed::Sealed; use crate::{ ffi, instance::{Borrowed, Bound}, PyAny, PyResult, Python, }; pub(crate) trait FfiPtrExt: Sealed { /// Assumes this pointer carries a Python reference which needs to be decref'd. /// /// If the pointer is NULL, this function will fetch an error. unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult>; /// Same as `assume_owned_or_err`, but doesn't fetch an error on NULL. unsafe fn assume_owned_or_opt(self, py: Python<'_>) -> Option>; /// Same as `assume_owned_or_err`, but panics on NULL. unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny>; /// Same as `assume_owned_or_err`, but does not check for NULL. unsafe fn assume_owned_unchecked(self, py: Python<'_>) -> Bound<'_, PyAny>; /// Assumes this pointer is borrowed from a parent object. /// /// Warning: the lifetime `'a` is not bounded by the function arguments; the caller is /// responsible to ensure this is tied to some appropriate lifetime. unsafe fn assume_borrowed_or_err<'a>(self, py: Python<'_>) -> PyResult>; /// Same as `assume_borrowed_or_err`, but doesn't fetch an error on NULL. unsafe fn assume_borrowed_or_opt<'a>(self, py: Python<'_>) -> Option>; /// Same as `assume_borrowed_or_err`, but panics on NULL. unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny>; /// Same as `assume_borrowed_or_err`, but does not check for NULL. unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny>; } impl FfiPtrExt for *mut ffi::PyObject { #[inline] unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult> { unsafe { Bound::from_owned_ptr_or_err(py, self) } } #[inline] unsafe fn assume_owned_or_opt(self, py: Python<'_>) -> Option> { unsafe { Bound::from_owned_ptr_or_opt(py, self) } } #[inline] #[track_caller] unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny> { unsafe { Bound::from_owned_ptr(py, self) } } #[inline] unsafe fn assume_owned_unchecked(self, py: Python<'_>) -> Bound<'_, PyAny> { unsafe { Bound::from_owned_ptr_unchecked(py, self) } } #[inline] unsafe fn assume_borrowed_or_err<'a>( self, py: Python<'_>, ) -> PyResult> { unsafe { Borrowed::from_ptr_or_err(py, self) } } #[inline] unsafe fn assume_borrowed_or_opt<'a>(self, py: Python<'_>) -> Option> { unsafe { Borrowed::from_ptr_or_opt(py, self) } } #[inline] #[track_caller] unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny> { unsafe { Borrowed::from_ptr(py, self) } } #[inline] unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny> { unsafe { Borrowed::from_ptr_unchecked(py, self) } } } pyo3/src/conversions/0000775000175000017500000000000015105742312014435 5ustar bdrungbdrungpyo3/src/conversions/mod.rs0000644000175000017500000000066015105742312015562 0ustar bdrungbdrung//! This module contains conversions between various Rust object and their representation in Python. pub mod anyhow; pub mod bigdecimal; pub mod chrono; pub mod chrono_tz; pub mod either; pub mod eyre; pub mod hashbrown; pub mod indexmap; pub mod jiff; pub mod num_bigint; pub mod num_complex; pub mod num_rational; pub mod ordered_float; pub mod rust_decimal; pub mod serde; pub mod smallvec; mod std; pub mod time; pub mod uuid; pyo3/src/conversions/ordered_float.rs0000644000175000017500000002635115105742312017621 0ustar bdrungbdrung#![cfg(feature = "ordered-float")] //! Conversions to and from [ordered-float](https://docs.rs/ordered-float) types. //! [`NotNan`]`<`[`f32`]`>` and [`NotNan`]`<`[`f64`]`>`. //! [`OrderedFloat`]`<`[`f32`]`>` and [`OrderedFloat`]`<`[`f64`]`>`. //! //! This is useful for converting between Python's float into and from a native Rust type. //! //! Take care when comparing sorted collections of float types between Python and Rust. //! They will likely differ due to the ambiguous sort order of NaNs in Python. // //! //! To use this feature, add to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"ordered-float\"] }")] //! ordered-float = "5.0.0" //! ``` //! //! # Example //! //! Rust code to create functions that add ordered floats: //! //! ```rust,no_run //! use ordered_float::{NotNan, OrderedFloat}; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_not_nans(a: NotNan, b: NotNan) -> NotNan { //! a + b //! } //! //! #[pyfunction] //! fn add_ordered_floats(a: OrderedFloat, b: OrderedFloat) -> OrderedFloat { //! a + b //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_not_nans, m)?)?; //! m.add_function(wrap_pyfunction!(add_ordered_floats, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that validates the functionality: //! ```python //! from my_module import add_not_nans, add_ordered_floats //! //! assert add_not_nans(1.0,2.0) == 3.0 //! assert add_ordered_floats(1.0,2.0) == 3.0 //! ``` use crate::conversion::IntoPyObject; use crate::exceptions::PyValueError; use crate::types::{any::PyAnyMethods, PyFloat}; use crate::{Bound, FromPyObject, PyAny, PyResult, Python}; use ordered_float::{NotNan, OrderedFloat}; use std::convert::Infallible; macro_rules! float_conversions { ($wrapper:ident, $float_type:ty, $constructor:expr) => { impl FromPyObject<'_> for $wrapper<$float_type> { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let val: $float_type = obj.extract()?; $constructor(val) } } impl<'py> IntoPyObject<'py> for $wrapper<$float_type> { type Target = PyFloat; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { self.into_inner().into_pyobject(py) } } impl<'py> IntoPyObject<'py> for &$wrapper<$float_type> { type Target = PyFloat; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } }; } float_conversions!(OrderedFloat, f32, |val| Ok(OrderedFloat(val))); float_conversions!(OrderedFloat, f64, |val| Ok(OrderedFloat(val))); float_conversions!(NotNan, f32, |val| NotNan::new(val) .map_err(|e| PyValueError::new_err(e.to_string()))); float_conversions!(NotNan, f64, |val| NotNan::new(val) .map_err(|e| PyValueError::new_err(e.to_string()))); #[cfg(test)] mod test_ordered_float { use super::*; use crate::ffi::c_str; use crate::py_run; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; macro_rules! float_roundtrip_tests { ($wrapper:ident, $float_type:ty, $constructor:expr, $standard_test:ident, $wasm_test:ident, $infinity_test:ident, $zero_test:ident) => { #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn $standard_test(inner_f: $float_type) { let f = $constructor(inner_f); Python::with_gil(|py| { let f_py: Bound<'_, PyFloat> = f.into_pyobject(py).unwrap(); py_run!( py, f_py, &format!( "import math\nassert math.isclose(f_py, {})", inner_f as f64 // Always interpret the literal rs float value as f64 // so that it's comparable with the python float ) ); let roundtripped_f: $wrapper<$float_type> = f_py.extract().unwrap(); assert_eq!(f, roundtripped_f); }) } } #[cfg(target_arch = "wasm32")] #[test] fn $wasm_test() { let inner_f = 10.0; let f = $constructor(inner_f); Python::with_gil(|py| { let f_py: Bound<'_, PyFloat> = f.into_pyobject(py).unwrap(); py_run!( py, f_py, &format!( "import math\nassert math.isclose(f_py, {})", inner_f as f64 // Always interpret the literal rs float value as f64 // so that it's comparable with the python float ) ); let roundtripped_f: $wrapper<$float_type> = f_py.extract().unwrap(); assert_eq!(f, roundtripped_f); }) } #[test] fn $infinity_test() { let inner_pinf = <$float_type>::INFINITY; let pinf = $constructor(inner_pinf); let inner_ninf = <$float_type>::NEG_INFINITY; let ninf = $constructor(inner_ninf); Python::with_gil(|py| { let pinf_py: Bound<'_, PyFloat> = pinf.into_pyobject(py).unwrap(); let ninf_py: Bound<'_, PyFloat> = ninf.into_pyobject(py).unwrap(); py_run!( py, pinf_py ninf_py, "\ assert pinf_py == float('inf')\n\ assert ninf_py == float('-inf')" ); let roundtripped_pinf: $wrapper<$float_type> = pinf_py.extract().unwrap(); let roundtripped_ninf: $wrapper<$float_type> = ninf_py.extract().unwrap(); assert_eq!(pinf, roundtripped_pinf); assert_eq!(ninf, roundtripped_ninf); }) } #[test] fn $zero_test() { let inner_pzero: $float_type = 0.0; let pzero = $constructor(inner_pzero); let inner_nzero: $float_type = -0.0; let nzero = $constructor(inner_nzero); Python::with_gil(|py| { let pzero_py: Bound<'_, PyFloat> = pzero.into_pyobject(py).unwrap(); let nzero_py: Bound<'_, PyFloat> = nzero.into_pyobject(py).unwrap(); // This python script verifies that the values are 0.0 in magnitude // and that the signs are correct(+0.0 vs -0.0) py_run!( py, pzero_py nzero_py, "\ import math\n\ assert pzero_py == 0.0\n\ assert math.copysign(1.0, pzero_py) > 0.0\n\ assert nzero_py == 0.0\n\ assert math.copysign(1.0, nzero_py) < 0.0" ); let roundtripped_pzero: $wrapper<$float_type> = pzero_py.extract().unwrap(); let roundtripped_nzero: $wrapper<$float_type> = nzero_py.extract().unwrap(); assert_eq!(pzero, roundtripped_pzero); assert_eq!(roundtripped_pzero.signum(), 1.0); assert_eq!(nzero, roundtripped_nzero); assert_eq!(roundtripped_nzero.signum(), -1.0); }) } }; } float_roundtrip_tests!( OrderedFloat, f32, OrderedFloat, ordered_float_f32_standard, ordered_float_f32_wasm, ordered_float_f32_infinity, ordered_float_f32_zero ); float_roundtrip_tests!( OrderedFloat, f64, OrderedFloat, ordered_float_f64_standard, ordered_float_f64_wasm, ordered_float_f64_infinity, ordered_float_f64_zero ); float_roundtrip_tests!( NotNan, f32, |val| NotNan::new(val).unwrap(), not_nan_f32_standard, not_nan_f32_wasm, not_nan_f32_infinity, not_nan_f32_zero ); float_roundtrip_tests!( NotNan, f64, |val| NotNan::new(val).unwrap(), not_nan_f64_standard, not_nan_f64_wasm, not_nan_f64_infinity, not_nan_f64_zero ); macro_rules! ordered_float_pynan_tests { ($test_name:ident, $float_type:ty) => { #[test] fn $test_name() { let inner_nan: $float_type = <$float_type>::NAN; let nan = OrderedFloat(inner_nan); Python::with_gil(|py| { let nan_py: Bound<'_, PyFloat> = nan.into_pyobject(py).unwrap(); py_run!( py, nan_py, "\ import math\n\ assert math.isnan(nan_py)" ); let roundtripped_nan: OrderedFloat<$float_type> = nan_py.extract().unwrap(); assert_eq!(nan, roundtripped_nan); }) } }; } ordered_float_pynan_tests!(test_ordered_float_pynan_f32, f32); ordered_float_pynan_tests!(test_ordered_float_pynan_f64, f64); macro_rules! not_nan_pynan_tests { ($test_name:ident, $float_type:ty) => { #[test] fn $test_name() { Python::with_gil(|py| { let nan_py = py.eval(c_str!("float('nan')"), None, None).unwrap(); let nan_rs: PyResult> = nan_py.extract(); assert!(nan_rs.is_err()); }) } }; } not_nan_pynan_tests!(test_not_nan_pynan_f32, f32); not_nan_pynan_tests!(test_not_nan_pynan_f64, f64); macro_rules! py64_rs32 { ($test_name:ident, $wrapper:ident, $float_type:ty) => { #[test] fn $test_name() { Python::with_gil(|py| { let py_64 = py .import("sys") .unwrap() .getattr("float_info") .unwrap() .getattr("max") .unwrap(); let rs_32 = py_64.extract::<$wrapper>().unwrap(); // The python f64 is not representable in a rust f32 assert!(rs_32.is_infinite()); }) } }; } py64_rs32!(ordered_float_f32, OrderedFloat, f32); py64_rs32!(ordered_float_f64, OrderedFloat, f64); py64_rs32!(not_nan_f32, NotNan, f32); py64_rs32!(not_nan_f64, NotNan, f64); } pyo3/src/conversions/serde.rs0000644000175000017500000000237315105742312016110 0ustar bdrungbdrung#![cfg(feature = "serde")] //! Enables (de)serialization of [`Py`]`` objects via [serde](https://docs.rs/serde). //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"serde\"] }")] //! serde = "1.0" //! ``` use crate::{Py, PyAny, PyClass, Python}; use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer}; impl Serialize for Py where T: Serialize + PyClass, { fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> where S: Serializer, { Python::with_gil(|py| { self.try_borrow(py) .map_err(|e| ser::Error::custom(e.to_string()))? .serialize(serializer) }) } } impl<'de, T> Deserialize<'de> for Py where T: PyClass + Deserialize<'de>, { fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let deserialized = T::deserialize(deserializer)?; Python::with_gil(|py| { Py::new(py, deserialized).map_err(|e| de::Error::custom(e.to_string())) }) } } pyo3/src/conversions/num_rational.rs0000644000175000017500000002116315105742312017474 0ustar bdrungbdrung#![cfg(feature = "num-rational")] //! Conversions to and from [num-rational](https://docs.rs/num-rational) types. //! //! This is useful for converting between Python's [fractions.Fraction](https://docs.python.org/3/library/fractions.html) into and from a native Rust //! type. //! //! //! To use this feature, add to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"num-rational\"] }")] //! num-rational = "0.4.1" //! ``` //! //! # Example //! //! Rust code to create a function that adds five to a fraction: //! //! ```rust,no_run //! use num_rational::Ratio; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_five_to_fraction(fraction: Ratio) -> Ratio { //! fraction + Ratio::new(5, 1) //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_five_to_fraction, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that validates the functionality: //! ```python //! from my_module import add_five_to_fraction //! from fractions import Fraction //! //! fraction = Fraction(2,1) //! fraction_plus_five = add_five_to_fraction(f) //! assert fraction + 5 == fraction_plus_five //! ``` use crate::conversion::IntoPyObject; use crate::ffi; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::PyType; use crate::{Bound, FromPyObject, Py, PyAny, PyErr, PyResult, Python}; #[cfg(feature = "num-bigint")] use num_bigint::BigInt; use num_rational::Ratio; static FRACTION_CLS: GILOnceCell> = GILOnceCell::new(); fn get_fraction_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { FRACTION_CLS.import(py, "fractions", "Fraction") } macro_rules! rational_conversion { ($int: ty) => { impl<'py> FromPyObject<'py> for Ratio<$int> { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { let py = obj.py(); let py_numerator_obj = obj.getattr(crate::intern!(py, "numerator"))?; let py_denominator_obj = obj.getattr(crate::intern!(py, "denominator"))?; let numerator_owned = unsafe { Bound::from_owned_ptr_or_err(py, ffi::PyNumber_Long(py_numerator_obj.as_ptr()))? }; let denominator_owned = unsafe { Bound::from_owned_ptr_or_err( py, ffi::PyNumber_Long(py_denominator_obj.as_ptr()), )? }; let rs_numerator: $int = numerator_owned.extract()?; let rs_denominator: $int = denominator_owned.extract()?; Ok(Ratio::new(rs_numerator, rs_denominator)) } } impl<'py> IntoPyObject<'py> for Ratio<$int> { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (&self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for &Ratio<$int> { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { get_fraction_cls(py)?.call1((self.numer().clone(), self.denom().clone())) } } }; } rational_conversion!(i8); rational_conversion!(i16); rational_conversion!(i32); rational_conversion!(isize); rational_conversion!(i64); #[cfg(feature = "num-bigint")] rational_conversion!(BigInt); #[cfg(test)] mod tests { use super::*; use crate::types::dict::PyDictMethods; use crate::types::PyDict; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; #[test] fn test_negative_fraction() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import fractions\npy_frac = fractions.Fraction(-0.125)"), None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("py_frac").unwrap().unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); let rs_frac = Ratio::new(-1, 8); assert_eq!(roundtripped, rs_frac); }) } #[test] fn test_obj_with_incorrect_atts() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("not_fraction = \"contains_incorrect_atts\""), None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("not_fraction").unwrap().unwrap(); assert!(py_frac.extract::>().is_err()); }) } #[test] fn test_fraction_with_fraction_type() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!( "import fractions\npy_frac = fractions.Fraction(fractions.Fraction(10))" ), None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("py_frac").unwrap().unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); let rs_frac = Ratio::new(10, 1); assert_eq!(roundtripped, rs_frac); }) } #[test] fn test_fraction_with_decimal() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import fractions\n\nfrom decimal import Decimal\npy_frac = fractions.Fraction(Decimal(\"1.1\"))"), None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("py_frac").unwrap().unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); let rs_frac = Ratio::new(11, 10); assert_eq!(roundtripped, rs_frac); }) } #[test] fn test_fraction_with_num_den() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import fractions\npy_frac = fractions.Fraction(10,5)"), None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("py_frac").unwrap().unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); let rs_frac = Ratio::new(10, 5); assert_eq!(roundtripped, rs_frac); }) } #[cfg(target_arch = "wasm32")] #[test] fn test_int_roundtrip() { Python::with_gil(|py| { let rs_frac = Ratio::new(1i32, 2); let py_frac = rs_frac.into_pyobject(py).unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); assert_eq!(rs_frac, roundtripped); // float conversion }) } #[cfg(target_arch = "wasm32")] #[test] fn test_big_int_roundtrip() { Python::with_gil(|py| { let rs_frac = Ratio::from_float(5.5).unwrap(); let py_frac = rs_frac.clone().into_pyobject(py).unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); assert_eq!(rs_frac, roundtripped); }) } #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_int_roundtrip(num in any::(), den in any::()) { Python::with_gil(|py| { let rs_frac = Ratio::new(num, den); let py_frac = rs_frac.into_pyobject(py).unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); assert_eq!(rs_frac, roundtripped); }) } #[test] #[cfg(feature = "num-bigint")] fn test_big_int_roundtrip(num in any::()) { Python::with_gil(|py| { let rs_frac = Ratio::from_float(num).unwrap(); let py_frac = rs_frac.clone().into_pyobject(py).unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); assert_eq!(roundtripped, rs_frac); }) } } #[test] fn test_infinity() { Python::with_gil(|py| { let locals = PyDict::new(py); let py_bound = py.run( ffi::c_str!("import fractions\npy_frac = fractions.Fraction(\"Infinity\")"), None, Some(&locals), ); assert!(py_bound.is_err()); }) } } pyo3/src/conversions/bigdecimal.rs0000644000175000017500000001501515105742312017063 0ustar bdrungbdrung#![cfg(feature = "bigdecimal")] //! Conversions to and from [bigdecimal](https://docs.rs/bigdecimal)'s [`BigDecimal`] type. //! //! This is useful for converting Python's decimal.Decimal into and from a native Rust type. //! //! # Setup //! //! To use this feature, add to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"bigdecimal\"] }")] //! bigdecimal = "0.4" //! ``` //! //! Note that you must use a compatible version of bigdecimal and PyO3. //! The required bigdecimal version may vary based on the version of PyO3. //! //! # Example //! //! Rust code to create a function that adds one to a BigDecimal //! //! ```rust //! use bigdecimal::BigDecimal; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_one(d: BigDecimal) -> BigDecimal { //! d + 1 //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_one, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that validates the functionality //! //! //! ```python //! from my_module import add_one //! from decimal import Decimal //! //! d = Decimal("2") //! value = add_one(d) //! //! assert d + 1 == value //! ``` use std::str::FromStr; use crate::{ exceptions::PyValueError, sync::GILOnceCell, types::{PyAnyMethods, PyStringMethods, PyType}, Bound, FromPyObject, IntoPyObject, Py, PyAny, PyErr, PyResult, Python, }; use bigdecimal::BigDecimal; static DECIMAL_CLS: GILOnceCell> = GILOnceCell::new(); fn get_decimal_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { DECIMAL_CLS.import(py, "decimal", "Decimal") } impl FromPyObject<'_> for BigDecimal { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let py_str = &obj.str()?; let rs_str = &py_str.to_cow()?; BigDecimal::from_str(rs_str).map_err(|e| PyValueError::new_err(e.to_string())) } } impl<'py> IntoPyObject<'py> for BigDecimal { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let cls = get_decimal_cls(py)?; cls.call1((self.to_string(),)) } } #[cfg(test)] mod test_bigdecimal { use super::*; use crate::types::dict::PyDictMethods; use crate::types::PyDict; use std::ffi::CString; use crate::ffi; use bigdecimal::{One, Zero}; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; macro_rules! convert_constants { ($name:ident, $rs:expr, $py:literal) => { #[test] fn $name() { Python::with_gil(|py| { let rs_orig = $rs; let rs_dec = rs_orig.clone().into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("rs_dec", &rs_dec).unwrap(); // Checks if BigDecimal -> Python Decimal conversion is correct py.run( &CString::new(format!( "import decimal\npy_dec = decimal.Decimal(\"{}\")\nassert py_dec == rs_dec", $py )) .unwrap(), None, Some(&locals), ) .unwrap(); // Checks if Python Decimal -> BigDecimal conversion is correct let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let py_result: BigDecimal = py_dec.extract().unwrap(); assert_eq!(rs_orig, py_result); }) } }; } convert_constants!(convert_zero, BigDecimal::zero(), "0"); convert_constants!(convert_one, BigDecimal::one(), "1"); convert_constants!(convert_neg_one, -BigDecimal::one(), "-1"); convert_constants!(convert_two, BigDecimal::from(2), "2"); convert_constants!(convert_ten, BigDecimal::from_str("10").unwrap(), "10"); convert_constants!( convert_one_hundred_point_one, BigDecimal::from_str("100.1").unwrap(), "100.1" ); convert_constants!( convert_one_thousand, BigDecimal::from_str("1000").unwrap(), "1000" ); convert_constants!( convert_scientific, BigDecimal::from_str("1e10").unwrap(), "1e10" ); #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_roundtrip( number in 0..28u32 ) { let num = BigDecimal::from(number); Python::with_gil(|py| { let rs_dec = num.clone().into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("rs_dec", &rs_dec).unwrap(); py.run( &CString::new(format!( "import decimal\npy_dec = decimal.Decimal(\"{num}\")\nassert py_dec == rs_dec")).unwrap(), None, Some(&locals)).unwrap(); let roundtripped: BigDecimal = rs_dec.extract().unwrap(); assert_eq!(num, roundtripped); }) } #[test] fn test_integers(num in any::()) { Python::with_gil(|py| { let py_num = num.into_pyobject(py).unwrap(); let roundtripped: BigDecimal = py_num.extract().unwrap(); let rs_dec = BigDecimal::from(num); assert_eq!(rs_dec, roundtripped); }) } } #[test] fn test_nan() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import decimal\npy_dec = decimal.Decimal(\"NaN\")"), None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Result = py_dec.extract(); assert!(roundtripped.is_err()); }) } #[test] fn test_infinity() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import decimal\npy_dec = decimal.Decimal(\"Infinity\")"), None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Result = py_dec.extract(); assert!(roundtripped.is_err()); }) } } pyo3/src/conversions/chrono_tz.rs0000644000175000017500000001230715105742312017011 0ustar bdrungbdrung#![cfg(all(Py_3_9, feature = "chrono-tz"))] //! Conversions to and from [chrono-tz](https://docs.rs/chrono-tz/)’s `Tz`. //! //! This feature requires at least Python 3.9. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! chrono-tz = "0.8" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"chrono-tz\"] }")] //! ``` //! //! Note that you must use compatible versions of chrono, chrono-tz and PyO3. //! The required chrono version may vary based on the version of PyO3. //! //! # Example: Convert a `zoneinfo.ZoneInfo` to chrono-tz's `Tz` //! //! ```rust,no_run //! use chrono_tz::Tz; //! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods}; //! //! fn main() -> PyResult<()> { //! pyo3::prepare_freethreaded_python(); //! Python::with_gil(|py| { //! // Convert to Python //! let py_tzinfo = Tz::Europe__Paris.into_pyobject(py)?; //! // Convert back to Rust //! assert_eq!(py_tzinfo.extract::()?, Tz::Europe__Paris); //! Ok(()) //! }) //! } //! ``` use crate::conversion::IntoPyObject; use crate::exceptions::PyValueError; use crate::pybacked::PyBackedStr; use crate::types::{any::PyAnyMethods, PyTzInfo}; use crate::{intern, Bound, FromPyObject, PyAny, PyErr, PyResult, Python}; use chrono_tz::Tz; use std::str::FromStr; impl<'py> IntoPyObject<'py> for Tz { type Target = PyTzInfo; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { PyTzInfo::timezone(py, self.name()) } } impl<'py> IntoPyObject<'py> for &Tz { type Target = PyTzInfo; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl FromPyObject<'_> for Tz { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { Tz::from_str( &ob.getattr(intern!(ob.py(), "key"))? .extract::()?, ) .map_err(|e| PyValueError::new_err(e.to_string())) } } #[cfg(all(test, not(windows)))] // Troubles loading timezones on Windows mod tests { use super::*; use crate::prelude::PyAnyMethods; use crate::types::PyTzInfo; use crate::Python; use chrono::{DateTime, Utc}; use chrono_tz::Tz; #[test] fn test_frompyobject() { Python::with_gil(|py| { assert_eq!( new_zoneinfo(py, "Europe/Paris").extract::().unwrap(), Tz::Europe__Paris ); assert_eq!(new_zoneinfo(py, "UTC").extract::().unwrap(), Tz::UTC); assert_eq!( new_zoneinfo(py, "Etc/GMT-5").extract::().unwrap(), Tz::Etc__GMTMinus5 ); }); } #[test] fn test_ambiguous_datetime_to_pyobject() { let dates = [ DateTime::::from_str("2020-10-24 23:00:00 UTC").unwrap(), DateTime::::from_str("2020-10-25 00:00:00 UTC").unwrap(), DateTime::::from_str("2020-10-25 01:00:00 UTC").unwrap(), ]; let dates = dates.map(|dt| dt.with_timezone(&Tz::Europe__London)); assert_eq!( dates.map(|dt| dt.to_string()), [ "2020-10-25 00:00:00 BST", "2020-10-25 01:00:00 BST", "2020-10-25 01:00:00 GMT" ] ); let dates = Python::with_gil(|py| { let pydates = dates.map(|dt| dt.into_pyobject(py).unwrap()); assert_eq!( pydates .clone() .map(|dt| dt.getattr("hour").unwrap().extract::().unwrap()), [0, 1, 1] ); assert_eq!( pydates .clone() .map(|dt| dt.getattr("fold").unwrap().extract::().unwrap() > 0), [false, false, true] ); pydates.map(|dt| dt.extract::>().unwrap()) }); assert_eq!( dates.map(|dt| dt.to_string()), [ "2020-10-25 00:00:00 BST", "2020-10-25 01:00:00 BST", "2020-10-25 01:00:00 GMT" ] ); } #[test] #[cfg(not(Py_GIL_DISABLED))] // https://github.com/python/cpython/issues/116738#issuecomment-2404360445 fn test_into_pyobject() { Python::with_gil(|py| { let assert_eq = |l: Bound<'_, PyTzInfo>, r: Bound<'_, PyTzInfo>| { assert!(l.eq(&r).unwrap(), "{l:?} != {r:?}"); }; assert_eq( Tz::Europe__Paris.into_pyobject(py).unwrap(), new_zoneinfo(py, "Europe/Paris"), ); assert_eq(Tz::UTC.into_pyobject(py).unwrap(), new_zoneinfo(py, "UTC")); assert_eq( Tz::Etc__GMTMinus5.into_pyobject(py).unwrap(), new_zoneinfo(py, "Etc/GMT-5"), ); }); } fn new_zoneinfo<'py>(py: Python<'py>, name: &str) -> Bound<'py, PyTzInfo> { PyTzInfo::timezone(py, name).unwrap() } } pyo3/src/conversions/rust_decimal.rs0000644000175000017500000001720515105742312017461 0ustar bdrungbdrung#![cfg(feature = "rust_decimal")] //! Conversions to and from [rust_decimal](https://docs.rs/rust_decimal)'s [`Decimal`] type. //! //! This is useful for converting Python's decimal.Decimal into and from a native Rust type. //! //! # Setup //! //! To use this feature, add to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"rust_decimal\"] }")] //! rust_decimal = "1.0" //! ``` //! //! Note that you must use a compatible version of rust_decimal and PyO3. //! The required rust_decimal version may vary based on the version of PyO3. //! //! # Example //! //! Rust code to create a function that adds one to a Decimal //! //! ```rust,no_run //! use rust_decimal::Decimal; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_one(d: Decimal) -> Decimal { //! d + Decimal::ONE //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_one, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that validates the functionality //! //! //! ```python //! from my_module import add_one //! from decimal import Decimal //! //! d = Decimal("2") //! value = add_one(d) //! //! assert d + 1 == value //! ``` use crate::conversion::IntoPyObject; use crate::exceptions::PyValueError; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::string::PyStringMethods; use crate::types::PyType; use crate::{Bound, FromPyObject, Py, PyAny, PyErr, PyResult, Python}; use rust_decimal::Decimal; use std::str::FromStr; impl FromPyObject<'_> for Decimal { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { // use the string representation to not be lossy if let Ok(val) = obj.extract() { Ok(Decimal::new(val, 0)) } else { let py_str = &obj.str()?; let rs_str = &py_str.to_cow()?; Decimal::from_str(rs_str).or_else(|_| { Decimal::from_scientific(rs_str).map_err(|e| PyValueError::new_err(e.to_string())) }) } } } static DECIMAL_CLS: GILOnceCell> = GILOnceCell::new(); fn get_decimal_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { DECIMAL_CLS.import(py, "decimal", "Decimal") } impl<'py> IntoPyObject<'py> for Decimal { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dec_cls = get_decimal_cls(py)?; // now call the constructor with the Rust Decimal string-ified // to not be lossy dec_cls.call1((self.to_string(),)) } } impl<'py> IntoPyObject<'py> for &Decimal { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } #[cfg(test)] mod test_rust_decimal { use super::*; use crate::types::dict::PyDictMethods; use crate::types::PyDict; use std::ffi::CString; use crate::ffi; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; macro_rules! convert_constants { ($name:ident, $rs:expr, $py:literal) => { #[test] fn $name() { Python::with_gil(|py| { let rs_orig = $rs; let rs_dec = rs_orig.into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("rs_dec", &rs_dec).unwrap(); // Checks if Rust Decimal -> Python Decimal conversion is correct py.run( &CString::new(format!( "import decimal\npy_dec = decimal.Decimal({})\nassert py_dec == rs_dec", $py )) .unwrap(), None, Some(&locals), ) .unwrap(); // Checks if Python Decimal -> Rust Decimal conversion is correct let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let py_result: Decimal = py_dec.extract().unwrap(); assert_eq!(rs_orig, py_result); }) } }; } convert_constants!(convert_zero, Decimal::ZERO, "0"); convert_constants!(convert_one, Decimal::ONE, "1"); convert_constants!(convert_neg_one, Decimal::NEGATIVE_ONE, "-1"); convert_constants!(convert_two, Decimal::TWO, "2"); convert_constants!(convert_ten, Decimal::TEN, "10"); convert_constants!(convert_one_hundred, Decimal::ONE_HUNDRED, "100"); convert_constants!(convert_one_thousand, Decimal::ONE_THOUSAND, "1000"); #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_roundtrip( lo in any::(), mid in any::(), high in any::(), negative in any::(), scale in 0..28u32 ) { let num = Decimal::from_parts(lo, mid, high, negative, scale); Python::with_gil(|py| { let rs_dec = num.into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("rs_dec", &rs_dec).unwrap(); py.run( &CString::new(format!( "import decimal\npy_dec = decimal.Decimal(\"{num}\")\nassert py_dec == rs_dec")).unwrap(), None, Some(&locals)).unwrap(); let roundtripped: Decimal = rs_dec.extract().unwrap(); assert_eq!(num, roundtripped); }) } #[test] fn test_integers(num in any::()) { Python::with_gil(|py| { let py_num = num.into_pyobject(py).unwrap(); let roundtripped: Decimal = py_num.extract().unwrap(); let rs_dec = Decimal::new(num, 0); assert_eq!(rs_dec, roundtripped); }) } } #[test] fn test_nan() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import decimal\npy_dec = decimal.Decimal(\"NaN\")"), None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Result = py_dec.extract(); assert!(roundtripped.is_err()); }) } #[test] fn test_scientific_notation() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import decimal\npy_dec = decimal.Decimal(\"1e3\")"), None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Decimal = py_dec.extract().unwrap(); let rs_dec = Decimal::from_scientific("1e3").unwrap(); assert_eq!(rs_dec, roundtripped); }) } #[test] fn test_infinity() { Python::with_gil(|py| { let locals = PyDict::new(py); py.run( ffi::c_str!("import decimal\npy_dec = decimal.Decimal(\"Infinity\")"), None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Result = py_dec.extract(); assert!(roundtripped.is_err()); }) } } pyo3/src/conversions/num_bigint.rs0000644000175000017500000003540115105742312017137 0ustar bdrungbdrung#![cfg(feature = "num-bigint")] //! Conversions to and from [num-bigint](https://docs.rs/num-bigint)’s [`BigInt`] and [`BigUint`] types. //! //! This is useful for converting Python integers when they may not fit in Rust's built-in integer types. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! num-bigint = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"num-bigint\"] }")] //! ``` //! //! Note that you must use compatible versions of num-bigint and PyO3. //! The required num-bigint version may vary based on the version of PyO3. //! //! ## Examples //! //! Using [`BigInt`] to correctly increment an arbitrary precision integer. //! This is not possible with Rust's native integers if the Python integer is too large, //! in which case it will fail its conversion and raise `OverflowError`. //! ```rust,no_run //! use num_bigint::BigInt; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_one(n: BigInt) -> BigInt { //! n + 1 //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_one, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code: //! ```python //! from my_module import add_one //! //! n = 1 << 1337 //! value = add_one(n) //! //! assert n + 1 == value //! ``` #[cfg(Py_LIMITED_API)] use crate::types::{bytes::PyBytesMethods, PyBytes}; use crate::{ conversion::IntoPyObject, ffi, instance::Bound, types::{any::PyAnyMethods, PyInt}, FromPyObject, Py, PyAny, PyErr, PyResult, Python, }; use num_bigint::{BigInt, BigUint}; #[cfg(not(Py_LIMITED_API))] use num_bigint::Sign; // for identical functionality between BigInt and BigUint macro_rules! bigint_conversion { ($rust_ty: ty, $is_signed: literal, $to_bytes: path) => { #[cfg_attr(docsrs, doc(cfg(feature = "num-bigint")))] impl<'py> IntoPyObject<'py> for $rust_ty { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (&self).into_pyobject(py) } } #[cfg_attr(docsrs, doc(cfg(feature = "num-bigint")))] impl<'py> IntoPyObject<'py> for &$rust_ty { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[cfg(not(Py_LIMITED_API))] fn into_pyobject(self, py: Python<'py>) -> Result { use crate::ffi_ptr_ext::FfiPtrExt; let bytes = $to_bytes(&self); unsafe { Ok(ffi::_PyLong_FromByteArray( bytes.as_ptr().cast(), bytes.len(), 1, $is_signed.into(), ) .assume_owned(py) .downcast_into_unchecked()) } } #[cfg(Py_LIMITED_API)] fn into_pyobject(self, py: Python<'py>) -> Result { use $crate::py_result_ext::PyResultExt; let bytes = $to_bytes(&self); let bytes_obj = PyBytes::new(py, &bytes); let kwargs = if $is_signed { let kwargs = crate::types::PyDict::new(py); kwargs.set_item(crate::intern!(py, "signed"), true)?; Some(kwargs) } else { None }; unsafe { py.get_type::() .call_method("from_bytes", (bytes_obj, "little"), kwargs.as_ref()) .downcast_into_unchecked() } } } }; } bigint_conversion!(BigUint, false, BigUint::to_bytes_le); bigint_conversion!(BigInt, true, BigInt::to_signed_bytes_le); #[cfg_attr(docsrs, doc(cfg(feature = "num-bigint")))] impl<'py> FromPyObject<'py> for BigInt { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let py = ob.py(); // fast path - checking for subclass of `int` just checks a bit in the type object let num_owned: Py; let num = if let Ok(long) = ob.downcast::() { long } else { num_owned = unsafe { Py::from_owned_ptr_or_err(py, ffi::PyNumber_Index(ob.as_ptr()))? }; num_owned.bind(py) }; #[cfg(not(Py_LIMITED_API))] { let mut buffer = int_to_u32_vec::(num)?; let sign = if buffer.last().copied().map_or(false, |last| last >> 31 != 0) { // BigInt::new takes an unsigned array, so need to convert from two's complement // flip all bits, 'subtract' 1 (by adding one to the unsigned array) let mut elements = buffer.iter_mut(); for element in elements.by_ref() { *element = (!*element).wrapping_add(1); if *element != 0 { // if the element didn't wrap over, no need to keep adding further ... break; } } // ... so just two's complement the rest for element in elements { *element = !*element; } Sign::Minus } else { Sign::Plus }; Ok(BigInt::new(sign, buffer)) } #[cfg(Py_LIMITED_API)] { let n_bits = int_n_bits(num)?; if n_bits == 0 { return Ok(BigInt::from(0isize)); } let bytes = int_to_py_bytes(num, (n_bits + 8) / 8, true)?; Ok(BigInt::from_signed_bytes_le(bytes.as_bytes())) } } } #[cfg_attr(docsrs, doc(cfg(feature = "num-bigint")))] impl<'py> FromPyObject<'py> for BigUint { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let py = ob.py(); // fast path - checking for subclass of `int` just checks a bit in the type object let num_owned: Py; let num = if let Ok(long) = ob.downcast::() { long } else { num_owned = unsafe { Py::from_owned_ptr_or_err(py, ffi::PyNumber_Index(ob.as_ptr()))? }; num_owned.bind(py) }; #[cfg(not(Py_LIMITED_API))] { let buffer = int_to_u32_vec::(num)?; Ok(BigUint::new(buffer)) } #[cfg(Py_LIMITED_API)] { let n_bits = int_n_bits(num)?; if n_bits == 0 { return Ok(BigUint::from(0usize)); } let bytes = int_to_py_bytes(num, (n_bits + 7) / 8, false)?; Ok(BigUint::from_bytes_le(bytes.as_bytes())) } } } #[cfg(not(any(Py_LIMITED_API, Py_3_13)))] #[inline] fn int_to_u32_vec(long: &Bound<'_, PyInt>) -> PyResult> { let mut buffer = Vec::new(); let n_bits = int_n_bits(long)?; if n_bits == 0 { return Ok(buffer); } let n_digits = if SIGNED { (n_bits + 32) / 32 } else { (n_bits + 31) / 32 }; buffer.reserve_exact(n_digits); unsafe { crate::err::error_on_minusone( long.py(), ffi::_PyLong_AsByteArray( long.as_ptr().cast(), buffer.as_mut_ptr() as *mut u8, n_digits * 4, 1, SIGNED.into(), ), )?; buffer.set_len(n_digits) }; buffer .iter_mut() .for_each(|chunk| *chunk = u32::from_le(*chunk)); Ok(buffer) } #[cfg(all(not(Py_LIMITED_API), Py_3_13))] #[inline] fn int_to_u32_vec(long: &Bound<'_, PyInt>) -> PyResult> { let mut buffer = Vec::new(); let mut flags = ffi::Py_ASNATIVEBYTES_LITTLE_ENDIAN; if !SIGNED { flags |= ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER | ffi::Py_ASNATIVEBYTES_REJECT_NEGATIVE; } let n_bytes = unsafe { ffi::PyLong_AsNativeBytes(long.as_ptr().cast(), std::ptr::null_mut(), 0, flags) }; let n_bytes_unsigned: usize = n_bytes .try_into() .map_err(|_| crate::PyErr::fetch(long.py()))?; if n_bytes == 0 { return Ok(buffer); } // TODO: use div_ceil when MSRV >= 1.73 let n_digits = { let adjust = if n_bytes % 4 == 0 { 0 } else { 1 }; (n_bytes_unsigned / 4) + adjust }; buffer.reserve_exact(n_digits); unsafe { ffi::PyLong_AsNativeBytes( long.as_ptr().cast(), buffer.as_mut_ptr().cast(), (n_digits * 4).try_into().unwrap(), flags, ); buffer.set_len(n_digits); }; buffer .iter_mut() .for_each(|chunk| *chunk = u32::from_le(*chunk)); Ok(buffer) } #[cfg(Py_LIMITED_API)] fn int_to_py_bytes<'py>( long: &Bound<'py, PyInt>, n_bytes: usize, is_signed: bool, ) -> PyResult> { use crate::intern; let py = long.py(); let kwargs = if is_signed { let kwargs = crate::types::PyDict::new(py); kwargs.set_item(intern!(py, "signed"), true)?; Some(kwargs) } else { None }; let bytes = long.call_method( intern!(py, "to_bytes"), (n_bytes, intern!(py, "little")), kwargs.as_ref(), )?; Ok(bytes.downcast_into()?) } #[inline] #[cfg(any(not(Py_3_13), Py_LIMITED_API))] fn int_n_bits(long: &Bound<'_, PyInt>) -> PyResult { let py = long.py(); #[cfg(not(Py_LIMITED_API))] { // fast path let n_bits = unsafe { ffi::_PyLong_NumBits(long.as_ptr()) }; if n_bits == (-1isize as usize) { return Err(crate::PyErr::fetch(py)); } Ok(n_bits) } #[cfg(Py_LIMITED_API)] { // slow path long.call_method0(crate::intern!(py, "bit_length")) .and_then(|any| any.extract()) } } #[cfg(test)] mod tests { use super::*; use crate::tests::common::generate_unique_module_name; use crate::types::{PyDict, PyModule}; use indoc::indoc; use pyo3_ffi::c_str; fn rust_fib() -> impl Iterator where T: From, for<'a> &'a T: std::ops::Add, { let mut f0: T = T::from(1); let mut f1: T = T::from(1); std::iter::from_fn(move || { let f2 = &f0 + &f1; Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2))) }) } fn python_fib(py: Python<'_>) -> impl Iterator> + '_ { let mut f0 = 1i32.into_pyobject(py).unwrap().into_any(); let mut f1 = 1i32.into_pyobject(py).unwrap().into_any(); std::iter::from_fn(move || { let f2 = f0.call_method1("__add__", (&f1,)).unwrap(); Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2))) }) } #[test] fn convert_biguint() { Python::with_gil(|py| { // check the first 2000 numbers in the fibonacci sequence for (py_result, rs_result) in python_fib(py).zip(rust_fib::()).take(2000) { // Python -> Rust assert_eq!(py_result.extract::().unwrap(), rs_result); // Rust -> Python assert!(py_result.eq(rs_result).unwrap()); } }); } #[test] fn convert_bigint() { Python::with_gil(|py| { // check the first 2000 numbers in the fibonacci sequence for (py_result, rs_result) in python_fib(py).zip(rust_fib::()).take(2000) { // Python -> Rust assert_eq!(py_result.extract::().unwrap(), rs_result); // Rust -> Python assert!(py_result.eq(&rs_result).unwrap()); // negate let rs_result = rs_result * -1; let py_result = py_result.call_method0("__neg__").unwrap(); // Python -> Rust assert_eq!(py_result.extract::().unwrap(), rs_result); // Rust -> Python assert!(py_result.eq(rs_result).unwrap()); } }); } fn python_index_class(py: Python<'_>) -> Bound<'_, PyModule> { let index_code = c_str!(indoc!( r#" class C: def __init__(self, x): self.x = x def __index__(self): return self.x "# )); PyModule::from_code( py, index_code, c_str!("index.py"), &generate_unique_module_name("index"), ) .unwrap() } #[test] fn convert_index_class() { Python::with_gil(|py| { let index = python_index_class(py); let locals = PyDict::new(py); locals.set_item("index", index).unwrap(); let ob = py .eval(ffi::c_str!("index.C(10)"), None, Some(&locals)) .unwrap(); let _: BigInt = ob.extract().unwrap(); }); } #[test] fn handle_zero() { Python::with_gil(|py| { let zero: BigInt = 0i32.into_pyobject(py).unwrap().extract().unwrap(); assert_eq!(zero, BigInt::from(0)); }) } /// `OverflowError` on converting Python int to BigInt, see issue #629 #[test] fn check_overflow() { Python::with_gil(|py| { macro_rules! test { ($T:ty, $value:expr, $py:expr) => { let value = $value; println!("{}: {}", stringify!($T), value); let python_value = value.clone().into_pyobject(py).unwrap(); let roundtrip_value = python_value.extract::<$T>().unwrap(); assert_eq!(value, roundtrip_value); }; } for i in 0..=256usize { // test a lot of values to help catch other bugs too test!(BigInt, BigInt::from(i), py); test!(BigUint, BigUint::from(i), py); test!(BigInt, -BigInt::from(i), py); test!(BigInt, BigInt::from(1) << i, py); test!(BigUint, BigUint::from(1u32) << i, py); test!(BigInt, -BigInt::from(1) << i, py); test!(BigInt, (BigInt::from(1) << i) + 1u32, py); test!(BigUint, (BigUint::from(1u32) << i) + 1u32, py); test!(BigInt, (-BigInt::from(1) << i) + 1u32, py); test!(BigInt, (BigInt::from(1) << i) - 1u32, py); test!(BigUint, (BigUint::from(1u32) << i) - 1u32, py); test!(BigInt, (-BigInt::from(1) << i) - 1u32, py); } }); } } pyo3/src/conversions/uuid.rs0000644000175000017500000001230015105742312015743 0ustar bdrungbdrung#![cfg(feature = "uuid")] //! Conversions to and from [uuid](https://docs.rs/uuid/latest/uuid/)'s [`Uuid`] type. //! //! This is useful for converting Python's uuid.UUID into and from a native Rust type. //! //! # Setup //! //! To use this feature, add to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"uuid\"] }")] //! uuid = "1.11.0" //! ``` //! //! Note that you must use a compatible version of uuid and PyO3. //! The required uuid version may vary based on the version of PyO3. //! //! # Example //! //! Rust code to create a function that parses a UUID string and returns it as a `Uuid`: //! //! ```rust,no_run //! use pyo3::prelude::*; //! use pyo3::exceptions::PyValueError; //! use uuid::Uuid; //! //! /// Parse a UUID from a string. //! #[pyfunction] //! fn get_uuid_from_str(s: &str) -> PyResult { //! Uuid::parse_str(s).map_err(|e| PyValueError::new_err(e.to_string())) //! } //! //! /// Passing a Python uuid.UUID directly to Rust. //! #[pyfunction] //! fn get_uuid(u: Uuid) -> Uuid { //! u //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(get_uuid_from_str, m)?)?; //! m.add_function(wrap_pyfunction!(get_uuid, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that validates the functionality //! //! //! ```python //! from my_module import get_uuid_from_str, get_uuid //! import uuid //! //! py_uuid = uuid.uuid4() //! //! # Convert string to Rust Uuid //! rust_uuid = get_uuid_from_str(str(py_uuid)) //! assert py_uuid == rust_uuid //! //! # Pass Python UUID directly to Rust //! returned_uuid = get_uuid(py_uuid) //! assert py_uuid == returned_uuid //! ``` use uuid::Uuid; use crate::conversion::IntoPyObject; use crate::exceptions::PyTypeError; use crate::instance::Bound; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::PyType; use crate::{intern, FromPyObject, Py, PyAny, PyErr, PyResult, Python}; fn get_uuid_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { static UUID_CLS: GILOnceCell> = GILOnceCell::new(); UUID_CLS.import(py, "uuid", "UUID") } impl FromPyObject<'_> for Uuid { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let py = obj.py(); let uuid_cls = get_uuid_cls(py)?; if obj.is_instance(uuid_cls)? { let uuid_int: u128 = obj.getattr(intern!(py, "int"))?.extract()?; Ok(Uuid::from_u128(uuid_int)) } else { Err(PyTypeError::new_err("Expected a `uuid.UUID` instance.")) } } } impl<'py> IntoPyObject<'py> for Uuid { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let uuid_cls = get_uuid_cls(py)?; uuid_cls.call1((py.None(), py.None(), py.None(), py.None(), self.as_u128())) } } impl<'py> IntoPyObject<'py> for &Uuid { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } #[cfg(test)] mod tests { use super::*; use crate::types::dict::PyDictMethods; use crate::types::PyDict; use std::ffi::CString; use uuid::Uuid; macro_rules! convert_constants { ($name:ident, $rs:expr, $py:literal) => { #[test] fn $name() -> PyResult<()> { Python::with_gil(|py| { let rs_orig = $rs; let rs_uuid = rs_orig.into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("rs_uuid", &rs_uuid).unwrap(); py.run( &CString::new(format!( "import uuid\npy_uuid = uuid.UUID('{}')\nassert py_uuid == rs_uuid", $py )) .unwrap(), None, Some(&locals), ) .unwrap(); let py_uuid = locals.get_item("py_uuid").unwrap().unwrap(); let py_result: Uuid = py_uuid.extract().unwrap(); assert_eq!(rs_orig, py_result); Ok(()) }) } }; } convert_constants!( convert_nil, Uuid::nil(), "00000000-0000-0000-0000-000000000000" ); convert_constants!( convert_max, Uuid::max(), "ffffffff-ffff-ffff-ffff-ffffffffffff" ); convert_constants!( convert_uuid_v4, Uuid::parse_str("a4f6d1b9-1898-418f-b11d-ecc6fe1e1f00").unwrap(), "a4f6d1b9-1898-418f-b11d-ecc6fe1e1f00" ); convert_constants!( convert_uuid_v3, Uuid::parse_str("6fa459ea-ee8a-3ca4-894e-db77e160355e").unwrap(), "6fa459ea-ee8a-3ca4-894e-db77e160355e" ); convert_constants!( convert_uuid_v1, Uuid::parse_str("a6cc5730-2261-11ee-9c43-2eb5a363657c").unwrap(), "a6cc5730-2261-11ee-9c43-2eb5a363657c" ); } pyo3/src/conversions/num_complex.rs0000644000175000017500000003005615105742312017333 0ustar bdrungbdrung#![cfg(feature = "num-complex")] //! Conversions to and from [num-complex](https://docs.rs/num-complex)’ //! [`Complex`]`<`[`f32`]`>` and [`Complex`]`<`[`f64`]`>`. //! //! num-complex’ [`Complex`] supports more operations than PyO3's [`PyComplex`] //! and can be used with the rest of the Rust ecosystem. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! num-complex = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"num-complex\"] }")] //! ``` //! //! Note that you must use compatible versions of num-complex and PyO3. //! The required num-complex version may vary based on the version of PyO3. //! //! # Examples //! //! Using [num-complex](https://docs.rs/num-complex) and [nalgebra](https://docs.rs/nalgebra) //! to create a pyfunction that calculates the eigenvalues of a 2x2 matrix. //! ```ignore //! # // not tested because nalgebra isn't supported on msrv //! # // please file an issue if it breaks! //! use nalgebra::base::{dimension::Const, Matrix}; //! use num_complex::Complex; //! use pyo3::prelude::*; //! //! type T = Complex; //! //! #[pyfunction] //! fn get_eigenvalues(m11: T, m12: T, m21: T, m22: T) -> Vec { //! let mat = Matrix::, Const<2>, _>::new(m11, m12, m21, m22); //! //! match mat.eigenvalues() { //! Some(e) => e.data.as_slice().to_vec(), //! None => vec![], //! } //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(get_eigenvalues, m)?)?; //! Ok(()) //! } //! # // test //! # use assert_approx_eq::assert_approx_eq; //! # use nalgebra::ComplexField; //! # use pyo3::types::PyComplex; //! # //! # fn main() -> PyResult<()> { //! # Python::with_gil(|py| -> PyResult<()> { //! # let module = PyModule::new(py, "my_module")?; //! # //! # module.add_function(&wrap_pyfunction!(get_eigenvalues, module)?)?; //! # //! # let m11 = PyComplex::from_doubles(py, 0_f64, -1_f64); //! # let m12 = PyComplex::from_doubles(py, 1_f64, 0_f64); //! # let m21 = PyComplex::from_doubles(py, 2_f64, -1_f64); //! # let m22 = PyComplex::from_doubles(py, -1_f64, 0_f64); //! # //! # let result = module //! # .getattr("get_eigenvalues")? //! # .call1((m11, m12, m21, m22))?; //! # println!("eigenvalues: {:?}", result); //! # //! # let result = result.extract::>()?; //! # let e0 = result[0]; //! # let e1 = result[1]; //! # //! # assert_approx_eq!(e0, Complex::new(1_f64, -1_f64)); //! # assert_approx_eq!(e1, Complex::new(-2_f64, 0_f64)); //! # //! # Ok(()) //! # }) //! # } //! ``` //! //! Python code: //! ```python //! from my_module import get_eigenvalues //! //! m11 = complex(0,-1) //! m12 = complex(1,0) //! m21 = complex(2,-1) //! m22 = complex(-1,0) //! //! result = get_eigenvalues(m11,m12,m21,m22) //! assert result == [complex(1,-1), complex(-2,0)] //! ``` use crate::{ ffi, ffi_ptr_ext::FfiPtrExt, types::{any::PyAnyMethods, PyComplex}, Bound, FromPyObject, PyAny, PyErr, PyResult, Python, }; use num_complex::Complex; use std::os::raw::c_double; impl PyComplex { /// Creates a new Python `PyComplex` object from `num_complex`'s [`Complex`]. pub fn from_complex_bound>( py: Python<'_>, complex: Complex, ) -> Bound<'_, PyComplex> { unsafe { ffi::PyComplex_FromDoubles(complex.re.into(), complex.im.into()) .assume_owned(py) .downcast_into_unchecked() } } } macro_rules! complex_conversion { ($float: ty) => { #[cfg_attr(docsrs, doc(cfg(feature = "num-complex")))] impl<'py> crate::conversion::IntoPyObject<'py> for Complex<$float> { type Target = PyComplex; type Output = Bound<'py, Self::Target>; type Error = std::convert::Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { unsafe { Ok( ffi::PyComplex_FromDoubles(self.re as c_double, self.im as c_double) .assume_owned(py) .downcast_into_unchecked(), ) } } } #[cfg_attr(docsrs, doc(cfg(feature = "num-complex")))] impl<'py> crate::conversion::IntoPyObject<'py> for &Complex<$float> { type Target = PyComplex; type Output = Bound<'py, Self::Target>; type Error = std::convert::Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } #[cfg_attr(docsrs, doc(cfg(feature = "num-complex")))] impl FromPyObject<'_> for Complex<$float> { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult> { #[cfg(not(any(Py_LIMITED_API, PyPy)))] unsafe { let val = ffi::PyComplex_AsCComplex(obj.as_ptr()); if val.real == -1.0 { if let Some(err) = PyErr::take(obj.py()) { return Err(err); } } Ok(Complex::new(val.real as $float, val.imag as $float)) } #[cfg(any(Py_LIMITED_API, PyPy))] unsafe { let complex; let obj = if obj.is_instance_of::() { obj } else if let Some(method) = obj.lookup_special(crate::intern!(obj.py(), "__complex__"))? { complex = method.call0()?; &complex } else { // `obj` might still implement `__float__` or `__index__`, which will be // handled by `PyComplex_{Real,Imag}AsDouble`, including propagating any // errors if those methods don't exist / raise exceptions. obj }; let ptr = obj.as_ptr(); let real = ffi::PyComplex_RealAsDouble(ptr); if real == -1.0 { if let Some(err) = PyErr::take(obj.py()) { return Err(err); } } let imag = ffi::PyComplex_ImagAsDouble(ptr); Ok(Complex::new(real as $float, imag as $float)) } } } }; } complex_conversion!(f32); complex_conversion!(f64); #[cfg(test)] mod tests { use super::*; use crate::tests::common::generate_unique_module_name; use crate::types::{complex::PyComplexMethods, PyModule}; use crate::IntoPyObject; use pyo3_ffi::c_str; #[test] fn from_complex() { Python::with_gil(|py| { let complex = Complex::new(3.0, 1.2); let py_c = PyComplex::from_complex_bound(py, complex); assert_eq!(py_c.real(), 3.0); assert_eq!(py_c.imag(), 1.2); }); } #[test] fn to_from_complex() { Python::with_gil(|py| { let val = Complex::new(3.0f64, 1.2); let obj = val.into_pyobject(py).unwrap(); assert_eq!(obj.extract::>().unwrap(), val); }); } #[test] fn from_complex_err() { Python::with_gil(|py| { let obj = vec![1i32].into_pyobject(py).unwrap(); assert!(obj.extract::>().is_err()); }); } #[test] fn from_python_magic() { Python::with_gil(|py| { let module = PyModule::from_code( py, c_str!( r#" class A: def __complex__(self): return 3.0+1.2j class B: def __float__(self): return 3.0 class C: def __index__(self): return 3 "# ), c_str!("test.py"), &generate_unique_module_name("test"), ) .unwrap(); let from_complex = module.getattr("A").unwrap().call0().unwrap(); assert_eq!( from_complex.extract::>().unwrap(), Complex::new(3.0, 1.2) ); let from_float = module.getattr("B").unwrap().call0().unwrap(); assert_eq!( from_float.extract::>().unwrap(), Complex::new(3.0, 0.0) ); // Before Python 3.8, `__index__` wasn't tried by `float`/`complex`. #[cfg(Py_3_8)] { let from_index = module.getattr("C").unwrap().call0().unwrap(); assert_eq!( from_index.extract::>().unwrap(), Complex::new(3.0, 0.0) ); } }) } #[test] fn from_python_inherited_magic() { Python::with_gil(|py| { let module = PyModule::from_code( py, c_str!( r#" class First: pass class ComplexMixin: def __complex__(self): return 3.0+1.2j class FloatMixin: def __float__(self): return 3.0 class IndexMixin: def __index__(self): return 3 class A(First, ComplexMixin): pass class B(First, FloatMixin): pass class C(First, IndexMixin): pass "# ), c_str!("test.py"), &generate_unique_module_name("test"), ) .unwrap(); let from_complex = module.getattr("A").unwrap().call0().unwrap(); assert_eq!( from_complex.extract::>().unwrap(), Complex::new(3.0, 1.2) ); let from_float = module.getattr("B").unwrap().call0().unwrap(); assert_eq!( from_float.extract::>().unwrap(), Complex::new(3.0, 0.0) ); #[cfg(Py_3_8)] { let from_index = module.getattr("C").unwrap().call0().unwrap(); assert_eq!( from_index.extract::>().unwrap(), Complex::new(3.0, 0.0) ); } }) } #[test] fn from_python_noncallable_descriptor_magic() { // Functions and lambdas implement the descriptor protocol in a way that makes // `type(inst).attr(inst)` equivalent to `inst.attr()` for methods, but this isn't the only // way the descriptor protocol might be implemented. Python::with_gil(|py| { let module = PyModule::from_code( py, c_str!( r#" class A: @property def __complex__(self): return lambda: 3.0+1.2j "# ), c_str!("test.py"), &generate_unique_module_name("test"), ) .unwrap(); let obj = module.getattr("A").unwrap().call0().unwrap(); assert_eq!( obj.extract::>().unwrap(), Complex::new(3.0, 1.2) ); }) } #[test] fn from_python_nondescriptor_magic() { // Magic methods don't need to implement the descriptor protocol, if they're callable. Python::with_gil(|py| { let module = PyModule::from_code( py, c_str!( r#" class MyComplex: def __call__(self): return 3.0+1.2j class A: __complex__ = MyComplex() "# ), c_str!("test.py"), &generate_unique_module_name("test"), ) .unwrap(); let obj = module.getattr("A").unwrap().call0().unwrap(); assert_eq!( obj.extract::>().unwrap(), Complex::new(3.0, 1.2) ); }) } } pyo3/src/conversions/either.rs0000644000175000017500000001271215105742312016264 0ustar bdrungbdrung#![cfg(feature = "either")] //! Conversion to/from //! [either](https://docs.rs/either/ "A library for easy idiomatic error handling and reporting in Rust applications")’s //! [`Either`] type to a union of two Python types. //! //! Use of a generic sum type like [either] is common when you want to either accept one of two possible //! types as an argument or return one of two possible types from a function, without having to define //! a helper type manually yourself. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! ## change * to the version you want to use, ideally the latest. //! either = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"either\"] }")] //! ``` //! //! Note that you must use compatible versions of either and PyO3. //! The required either version may vary based on the version of PyO3. //! //! # Example: Convert a `int | str` to `Either`. //! //! ```rust //! use either::Either; //! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods}; //! //! fn main() -> PyResult<()> { //! pyo3::prepare_freethreaded_python(); //! Python::with_gil(|py| { //! // Create a string and an int in Python. //! let py_str = "crab".into_pyobject(py)?; //! let py_int = 42i32.into_pyobject(py)?; //! // Now convert it to an Either. //! let either_str: Either = py_str.extract()?; //! let either_int: Either = py_int.extract()?; //! Ok(()) //! }) //! } //! ``` //! //! [either](https://docs.rs/either/ "A library for easy idiomatic error handling and reporting in Rust applications")’s #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ exceptions::PyTypeError, types::any::PyAnyMethods, Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, PyAny, PyErr, PyResult, Python, }; use either::Either; #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl<'py, L, R> IntoPyObject<'py> for Either where L: IntoPyObject<'py>, R: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { match self { Either::Left(l) => l.into_bound_py_any(py), Either::Right(r) => r.into_bound_py_any(py), } } } #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl<'a, 'py, L, R> IntoPyObject<'py> for &'a Either where &'a L: IntoPyObject<'py>, &'a R: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { match self { Either::Left(l) => l.into_bound_py_any(py), Either::Right(r) => r.into_bound_py_any(py), } } } #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl<'py, L, R> FromPyObject<'py> for Either where L: FromPyObject<'py>, R: FromPyObject<'py>, { #[inline] fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { if let Ok(l) = obj.extract::() { Ok(Either::Left(l)) } else if let Ok(r) = obj.extract::() { Ok(Either::Right(r)) } else { // TODO: it might be nice to use the `type_input()` name here once `type_input` // is not experimental, rather than the Rust type names. let err_msg = format!( "failed to convert the value to 'Union[{}, {}]'", std::any::type_name::(), std::any::type_name::() ); Err(PyTypeError::new_err(err_msg)) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::union_of(&[L::type_input(), R::type_input()]) } } #[cfg(test)] mod tests { use std::borrow::Cow; use crate::exceptions::PyTypeError; use crate::{IntoPyObject, Python}; use crate::types::PyAnyMethods; use either::Either; #[test] fn test_either_conversion() { type E = Either; type E1 = Either; type E2 = Either; Python::with_gil(|py| { let l = E::Left(42); let obj_l = (&l).into_pyobject(py).unwrap(); assert_eq!(obj_l.extract::().unwrap(), 42); assert_eq!(obj_l.extract::().unwrap(), l); let r = E::Right("foo".to_owned()); let obj_r = (&r).into_pyobject(py).unwrap(); assert_eq!(obj_r.extract::>().unwrap(), "foo"); assert_eq!(obj_r.extract::().unwrap(), r); let obj_s = "foo".into_pyobject(py).unwrap(); let err = obj_s.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); assert_eq!( err.to_string(), "TypeError: failed to convert the value to 'Union[i32, f32]'" ); let obj_i = 42i32.into_pyobject(py).unwrap(); assert_eq!(obj_i.extract::().unwrap(), E1::Left(42)); assert_eq!(obj_i.extract::().unwrap(), E2::Left(42.0)); let obj_f = 42.0f64.into_pyobject(py).unwrap(); assert_eq!(obj_f.extract::().unwrap(), E1::Right(42.0)); assert_eq!(obj_f.extract::().unwrap(), E2::Left(42.0)); }); } } pyo3/src/conversions/indexmap.rs0000644000175000017500000001517315105742312016615 0ustar bdrungbdrung#![cfg(feature = "indexmap")] //! Conversions to and from [indexmap](https://docs.rs/indexmap/)’s //! `IndexMap`. //! //! [`indexmap::IndexMap`] is a hash table that is closely compatible with the standard [`std::collections::HashMap`], //! with the difference that it preserves the insertion order when iterating over keys. It was inspired //! by Python's 3.6+ dict implementation. //! //! Dictionary order is guaranteed to be insertion order in Python, hence IndexMap is a good candidate //! for maintaining an equivalent behaviour in Rust. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! indexmap = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"indexmap\"] }")] //! ``` //! //! Note that you must use compatible versions of indexmap and PyO3. //! The required indexmap version may vary based on the version of PyO3. //! //! # Examples //! //! Using [indexmap](https://docs.rs/indexmap) to return a dictionary with some statistics //! about a list of numbers. Because of the insertion order guarantees, the Python code will //! always print the same result, matching users' expectations about Python's dict. //! ```rust //! use indexmap::{indexmap, IndexMap}; //! use pyo3::prelude::*; //! //! fn median(data: &Vec) -> f32 { //! let sorted_data = data.clone().sort(); //! let mid = data.len() / 2; //! if data.len() % 2 == 0 { //! data[mid] as f32 //! } //! else { //! (data[mid] + data[mid - 1]) as f32 / 2.0 //! } //! } //! //! fn mean(data: &Vec) -> f32 { //! data.iter().sum::() as f32 / data.len() as f32 //! } //! fn mode(data: &Vec) -> f32 { //! let mut frequency = IndexMap::new(); // we can use IndexMap as any hash table //! //! for &element in data { //! *frequency.entry(element).or_insert(0) += 1; //! } //! //! frequency //! .iter() //! .max_by(|a, b| a.1.cmp(&b.1)) //! .map(|(k, _v)| *k) //! .unwrap() as f32 //! } //! //! #[pyfunction] //! fn calculate_statistics(data: Vec) -> IndexMap<&'static str, f32> { //! indexmap! { //! "median" => median(&data), //! "mean" => mean(&data), //! "mode" => mode(&data), //! } //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(calculate_statistics, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code: //! ```python //! from my_module import calculate_statistics //! //! data = [1, 1, 1, 3, 4, 5] //! print(calculate_statistics(data)) //! # always prints {"median": 2.0, "mean": 2.5, "mode": 1.0} in the same order //! # if another hash table was used, the order could be random //! ``` use crate::conversion::IntoPyObject; use crate::types::*; use crate::{Bound, FromPyObject, PyErr, Python}; use std::{cmp, hash}; impl<'py, K, V, H> IntoPyObject<'py> for indexmap::IndexMap where K: IntoPyObject<'py> + cmp::Eq + hash::Hash, V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } } impl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a indexmap::IndexMap where &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash, &'a V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } } impl<'py, K, V, S> FromPyObject<'py> for indexmap::IndexMap where K: FromPyObject<'py> + cmp::Eq + hash::Hash, V: FromPyObject<'py>, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> Result { let dict = ob.downcast::()?; let mut ret = indexmap::IndexMap::with_capacity_and_hasher(dict.len(), S::default()); for (k, v) in dict { ret.insert(k.extract()?, v.extract()?); } Ok(ret) } } #[cfg(test)] mod test_indexmap { use crate::types::*; use crate::{IntoPyObject, Python}; #[test] fn test_indexmap_indexmap_into_pyobject() { Python::with_gil(|py| { let mut map = indexmap::IndexMap::::new(); map.insert(1, 1); let py_map = (&map).into_pyobject(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!( map, py_map.extract::>().unwrap() ); }); } #[test] fn test_indexmap_indexmap_into_dict() { Python::with_gil(|py| { let mut map = indexmap::IndexMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_indexmap_indexmap_insertion_order_round_trip() { Python::with_gil(|py| { let n = 20; let mut map = indexmap::IndexMap::::new(); for i in 1..=n { if i % 2 == 1 { map.insert(i, i); } else { map.insert(n - i, i); } } let py_map = (&map).into_py_dict(py).unwrap(); let trip_map = py_map.extract::>().unwrap(); for (((k1, v1), (k2, v2)), (k3, v3)) in map.iter().zip(py_map.iter()).zip(trip_map.iter()) { let k2 = k2.extract::().unwrap(); let v2 = v2.extract::().unwrap(); assert_eq!((k1, v1), (&k2, &v2)); assert_eq!((k1, v1), (k3, v3)); assert_eq!((&k2, &v2), (k3, v3)); } }); } } pyo3/src/conversions/jiff.rs0000644000175000017500000012052315105742312015722 0ustar bdrungbdrung#![cfg(feature = "jiff-02")] //! Conversions to and from [jiff](https://docs.rs/jiff/)’s `Span`, `SignedDuration`, `TimeZone`, //! `Offset`, `Date`, `Time`, `DateTime`, `Zoned`, and `Timestamp`. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! jiff = "0.2" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"jiff-02\"] }")] //! ``` //! //! Note that you must use compatible versions of jiff and PyO3. //! The required jiff version may vary based on the version of PyO3. Jiff also requires a MSRV //! of 1.70. //! //! # Example: Convert a `datetime.datetime` to jiff `Zoned` //! //! ```rust //! # #![cfg_attr(windows, allow(unused_imports))] //! # use jiff_02 as jiff; //! use jiff::{Zoned, SignedDuration, ToSpan}; //! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods}; //! //! # #[cfg(windows)] //! # fn main() -> () {} //! # #[cfg(not(windows))] //! fn main() -> PyResult<()> { //! pyo3::prepare_freethreaded_python(); //! Python::with_gil(|py| { //! // Build some jiff values //! let jiff_zoned = Zoned::now(); //! let jiff_span = 1.second(); //! // Convert them to Python //! let py_datetime = jiff_zoned.into_pyobject(py)?; //! let py_timedelta = SignedDuration::try_from(jiff_span)?.into_pyobject(py)?; //! // Do an operation in Python //! let py_sum = py_datetime.call_method1("__add__", (py_timedelta,))?; //! // Convert back to Rust //! let jiff_sum: Zoned = py_sum.extract()?; //! println!("Zoned: {}", jiff_sum); //! Ok(()) //! }) //! } //! ``` use crate::exceptions::{PyTypeError, PyValueError}; use crate::pybacked::PyBackedStr; use crate::types::{PyAnyMethods, PyNone}; use crate::types::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo, PyTzInfoAccess}; #[cfg(not(Py_LIMITED_API))] use crate::types::{PyDateAccess, PyDeltaAccess, PyTimeAccess}; use crate::{intern, Bound, FromPyObject, IntoPyObject, PyAny, PyErr, PyResult, Python}; use jiff::civil::{Date, DateTime, Time}; use jiff::tz::{Offset, TimeZone}; use jiff::{SignedDuration, Span, Timestamp, Zoned}; #[cfg(feature = "jiff-02")] use jiff_02 as jiff; fn datetime_to_pydatetime<'py>( py: Python<'py>, datetime: &DateTime, fold: bool, timezone: Option<&TimeZone>, ) -> PyResult> { PyDateTime::new_with_fold( py, datetime.year().into(), datetime.month().try_into()?, datetime.day().try_into()?, datetime.hour().try_into()?, datetime.minute().try_into()?, datetime.second().try_into()?, (datetime.subsec_nanosecond() / 1000).try_into()?, timezone .map(|tz| tz.into_pyobject(py)) .transpose()? .as_ref(), fold, ) } #[cfg(not(Py_LIMITED_API))] fn pytime_to_time(time: &impl PyTimeAccess) -> PyResult where A: Array, A::Item: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; /// Turns [`SmallVec`] into [`PyBytes`], all other `T`s will be turned into a [`PyList`] /// /// [`PyBytes`]: crate::types::PyBytes /// [`PyList`]: crate::types::PyList #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { ::owned_sequence_into_pyobject(self, py, crate::conversion::private::Token) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::list_of(A::Item::type_output()) } } impl<'a, 'py, A> IntoPyObject<'py> for &'a SmallVec where A: Array, &'a A::Item: IntoPyObject<'py>, A::Item: 'a, // MSRV { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.as_slice().into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::list_of(<&A::Item>::type_output()) } } impl<'py, A> FromPyObject<'py> for SmallVec where A: Array, A::Item: FromPyObject<'py>, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { if obj.is_instance_of::() { return Err(PyTypeError::new_err("Can't extract `str` to `SmallVec`")); } extract_sequence(obj) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::sequence_of(A::Item::type_input()) } } fn extract_sequence<'py, A>(obj: &Bound<'py, PyAny>) -> PyResult> where A: Array, A::Item: FromPyObject<'py>, { // Types that pass `PySequence_Check` usually implement enough of the sequence protocol // to support this function and if not, we will only fail extraction safely. let seq = unsafe { if ffi::PySequence_Check(obj.as_ptr()) != 0 { obj.downcast_unchecked::() } else { return Err(DowncastError::new(obj, "Sequence").into()); } }; let mut sv = SmallVec::with_capacity(seq.len().unwrap_or(0)); for item in seq.try_iter()? { sv.push(item?.extract::()?); } Ok(sv) } #[cfg(test)] mod tests { use super::*; use crate::types::{PyBytes, PyBytesMethods, PyDict, PyList}; #[test] fn test_smallvec_from_py_object() { Python::with_gil(|py| { let l = PyList::new(py, [1, 2, 3, 4, 5]).unwrap(); let sv: SmallVec<[u64; 8]> = l.extract().unwrap(); assert_eq!(sv.as_slice(), [1, 2, 3, 4, 5]); }); } #[test] fn test_smallvec_from_py_object_fails() { Python::with_gil(|py| { let dict = PyDict::new(py); let sv: PyResult> = dict.extract(); assert_eq!( sv.unwrap_err().to_string(), "TypeError: 'dict' object cannot be converted to 'Sequence'" ); }); } #[test] fn test_smallvec_into_pyobject() { Python::with_gil(|py| { let sv: SmallVec<[u64; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect(); let hso = sv.into_pyobject(py).unwrap(); let l = PyList::new(py, [1, 2, 3, 4, 5]).unwrap(); assert!(l.eq(hso).unwrap()); }); } #[test] fn test_smallvec_intopyobject_impl() { Python::with_gil(|py| { let bytes: SmallVec<[u8; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect(); let obj = bytes.clone().into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); let obj = obj.downcast_into::().unwrap(); assert_eq!(obj.as_bytes(), &*bytes); let nums: SmallVec<[u16; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect(); let obj = nums.into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); }); } } pyo3/src/conversions/std/0000775000175000017500000000000015105742312015227 5ustar bdrungbdrungpyo3/src/conversions/std/mod.rs0000644000175000017500000000020715105742312016351 0ustar bdrungbdrungmod array; mod cell; mod ipaddr; mod map; mod num; mod option; mod osstr; mod path; mod set; mod slice; mod string; mod time; mod vec; pyo3/src/conversions/std/array.rs0000644000175000017500000002133115105742312016711 0ustar bdrungbdrunguse crate::conversion::IntoPyObject; use crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::types::PySequence; use crate::{err::DowncastError, ffi, FromPyObject, PyAny, PyResult, Python}; use crate::{exceptions, PyErr}; impl<'py, T, const N: usize> IntoPyObject<'py> for [T; N] where T: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; /// Turns [`[u8; N]`](std::array) into [`PyBytes`], all other `T`s will be turned into a [`PyList`] /// /// [`PyBytes`]: crate::types::PyBytes /// [`PyList`]: crate::types::PyList #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { T::owned_sequence_into_pyobject(self, py, crate::conversion::private::Token) } } impl<'a, 'py, T, const N: usize> IntoPyObject<'py> for &'a [T; N] where &'a T: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.as_slice().into_pyobject(py) } } impl<'py, T, const N: usize> FromPyObject<'py> for [T; N] where T: FromPyObject<'py>, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { create_array_from_obj(obj) } } fn create_array_from_obj<'py, T, const N: usize>(obj: &Bound<'py, PyAny>) -> PyResult<[T; N]> where T: FromPyObject<'py>, { // Types that pass `PySequence_Check` usually implement enough of the sequence protocol // to support this function and if not, we will only fail extraction safely. let seq = unsafe { if ffi::PySequence_Check(obj.as_ptr()) != 0 { obj.downcast_unchecked::() } else { return Err(DowncastError::new(obj, "Sequence").into()); } }; let seq_len = seq.len()?; if seq_len != N { return Err(invalid_sequence_length(N, seq_len)); } array_try_from_fn(|idx| seq.get_item(idx).and_then(|any| any.extract())) } // TODO use std::array::try_from_fn, if that stabilises: // (https://github.com/rust-lang/rust/issues/89379) fn array_try_from_fn(mut cb: F) -> Result<[T; N], E> where F: FnMut(usize) -> Result, { // Helper to safely create arrays since the standard library doesn't // provide one yet. Shouldn't be necessary in the future. struct ArrayGuard { dst: *mut T, initialized: usize, } impl Drop for ArrayGuard { fn drop(&mut self) { debug_assert!(self.initialized <= N); let initialized_part = core::ptr::slice_from_raw_parts_mut(self.dst, self.initialized); unsafe { core::ptr::drop_in_place(initialized_part); } } } // [MaybeUninit; N] would be "nicer" but is actually difficult to create - there are nightly // APIs which would make this easier. let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit(); let mut guard: ArrayGuard = ArrayGuard { dst: array.as_mut_ptr() as _, initialized: 0, }; unsafe { let mut value_ptr = array.as_mut_ptr() as *mut T; for i in 0..N { core::ptr::write(value_ptr, cb(i)?); value_ptr = value_ptr.offset(1); guard.initialized += 1; } core::mem::forget(guard); Ok(array.assume_init()) } } fn invalid_sequence_length(expected: usize, actual: usize) -> PyErr { exceptions::PyValueError::new_err(format!( "expected a sequence of length {expected} (got {actual})" )) } #[cfg(test)] mod tests { use std::{ panic, sync::atomic::{AtomicUsize, Ordering}, }; use crate::{ conversion::IntoPyObject, ffi, types::{any::PyAnyMethods, PyBytes, PyBytesMethods}, }; use crate::{types::PyList, PyResult, Python}; #[test] fn array_try_from_fn() { static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); struct CountDrop; impl Drop for CountDrop { fn drop(&mut self) { DROP_COUNTER.fetch_add(1, Ordering::SeqCst); } } let _ = catch_unwind_silent(move || { let _: Result<[CountDrop; 4], ()> = super::array_try_from_fn(|idx| { #[allow(clippy::manual_assert)] if idx == 2 { panic!("peek a boo"); } Ok(CountDrop) }); }); assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); } #[test] fn test_extract_bytearray_to_array() { Python::with_gil(|py| { let v: [u8; 33] = py .eval( ffi::c_str!("bytearray(b'abcabcabcabcabcabcabcabcabcabcabc')"), None, None, ) .unwrap() .extract() .unwrap(); assert!(&v == b"abcabcabcabcabcabcabcabcabcabcabc"); }) } #[test] fn test_extract_small_bytearray_to_array() { Python::with_gil(|py| { let v: [u8; 3] = py .eval(ffi::c_str!("bytearray(b'abc')"), None, None) .unwrap() .extract() .unwrap(); assert!(&v == b"abc"); }); } #[test] fn test_into_pyobject_array_conversion() { Python::with_gil(|py| { let array: [f32; 4] = [0.0, -16.0, 16.0, 42.0]; let pyobject = array.into_pyobject(py).unwrap(); let pylist = pyobject.downcast::().unwrap(); assert_eq!(pylist.get_item(0).unwrap().extract::().unwrap(), 0.0); assert_eq!(pylist.get_item(1).unwrap().extract::().unwrap(), -16.0); assert_eq!(pylist.get_item(2).unwrap().extract::().unwrap(), 16.0); assert_eq!(pylist.get_item(3).unwrap().extract::().unwrap(), 42.0); }); } #[test] fn test_extract_invalid_sequence_length() { Python::with_gil(|py| { let v: PyResult<[u8; 3]> = py .eval(ffi::c_str!("bytearray(b'abcdefg')"), None, None) .unwrap() .extract(); assert_eq!( v.unwrap_err().to_string(), "ValueError: expected a sequence of length 3 (got 7)" ); }) } #[test] fn test_intopyobject_array_conversion() { Python::with_gil(|py| { let array: [f32; 4] = [0.0, -16.0, 16.0, 42.0]; let pylist = array .into_pyobject(py) .unwrap() .downcast_into::() .unwrap(); assert_eq!(pylist.get_item(0).unwrap().extract::().unwrap(), 0.0); assert_eq!(pylist.get_item(1).unwrap().extract::().unwrap(), -16.0); assert_eq!(pylist.get_item(2).unwrap().extract::().unwrap(), 16.0); assert_eq!(pylist.get_item(3).unwrap().extract::().unwrap(), 42.0); }); } #[test] fn test_array_intopyobject_impl() { Python::with_gil(|py| { let bytes: [u8; 6] = *b"foobar"; let obj = bytes.into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); let obj = obj.downcast_into::().unwrap(); assert_eq!(obj.as_bytes(), &bytes); let nums: [u16; 4] = [0, 1, 2, 3]; let obj = nums.into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); }); } #[test] fn test_extract_non_iterable_to_array() { Python::with_gil(|py| { let v = py.eval(ffi::c_str!("42"), None, None).unwrap(); v.extract::().unwrap(); v.extract::<[i32; 1]>().unwrap_err(); }); } #[cfg(feature = "macros")] #[test] fn test_pyclass_intopy_array_conversion() { #[crate::pyclass(crate = "crate")] struct Foo; Python::with_gil(|py| { let array: [Foo; 8] = [Foo, Foo, Foo, Foo, Foo, Foo, Foo, Foo]; let list = array .into_pyobject(py) .unwrap() .downcast_into::() .unwrap(); let _bound = list.get_item(4).unwrap().downcast::().unwrap(); }); } // https://stackoverflow.com/a/59211505 fn catch_unwind_silent(f: F) -> std::thread::Result where F: FnOnce() -> R + panic::UnwindSafe, { let prev_hook = panic::take_hook(); panic::set_hook(Box::new(|_| {})); let result = panic::catch_unwind(f); panic::set_hook(prev_hook); result } } pyo3/src/conversions/std/option.rs0000644000175000017500000000240115105742312017100 0ustar bdrungbdrunguse crate::{ conversion::IntoPyObject, types::any::PyAnyMethods, Bound, BoundObject, FromPyObject, PyAny, PyResult, Python, }; impl<'py, T> IntoPyObject<'py> for Option where T: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = T::Error; fn into_pyobject(self, py: Python<'py>) -> Result { self.map_or_else( || Ok(py.None().into_bound(py)), |val| { val.into_pyobject(py) .map(BoundObject::into_any) .map(BoundObject::into_bound) }, ) } } impl<'a, 'py, T> IntoPyObject<'py> for &'a Option where &'a T: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = <&'a T as IntoPyObject<'py>>::Error; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.as_ref().into_pyobject(py) } } impl<'py, T> FromPyObject<'py> for Option where T: FromPyObject<'py>, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { if obj.is_none() { Ok(None) } else { obj.extract().map(Some) } } } pyo3/src/conversions/std/slice.rs0000644000175000017500000001360215105742312016674 0ustar bdrungbdrunguse std::borrow::Cow; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ conversion::IntoPyObject, types::{PyByteArray, PyByteArrayMethods, PyBytes}, Bound, PyAny, PyErr, PyResult, Python, }; impl<'a, 'py, T> IntoPyObject<'py> for &'a [T] where &'a T: IntoPyObject<'py>, T: 'a, // MSRV { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; /// Turns [`&[u8]`](std::slice) into [`PyBytes`], all other `T`s will be turned into a [`PyList`] /// /// [`PyBytes`]: crate::types::PyBytes /// [`PyList`]: crate::types::PyList #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { <&T>::borrowed_sequence_into_pyobject(self, py, crate::conversion::private::Token) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::union_of(&[ TypeInfo::builtin("bytes"), TypeInfo::list_of(<&T>::type_output()), ]) } } impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for &'a [u8] { fn from_py_object_bound(obj: crate::Borrowed<'a, '_, PyAny>) -> PyResult { Ok(obj.downcast::()?.as_bytes()) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::builtin("bytes") } } /// Special-purpose trait impl to efficiently handle both `bytes` and `bytearray` /// /// If the source object is a `bytes` object, the `Cow` will be borrowed and /// pointing into the source object, and no copying or heap allocations will happen. /// If it is a `bytearray`, its contents will be copied to an owned `Cow`. impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for Cow<'a, [u8]> { fn from_py_object_bound(ob: crate::Borrowed<'a, '_, PyAny>) -> PyResult { if let Ok(bytes) = ob.downcast::() { return Ok(Cow::Borrowed(bytes.as_bytes())); } let byte_array = ob.downcast::()?; Ok(Cow::Owned(byte_array.to_vec())) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } impl<'py, T> IntoPyObject<'py> for Cow<'_, [T]> where T: Clone, for<'a> &'a T: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; /// Turns `Cow<[u8]>` into [`PyBytes`], all other `T`s will be turned into a [`PyList`] /// /// [`PyBytes`]: crate::types::PyBytes /// [`PyList`]: crate::types::PyList #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { <&T>::borrowed_sequence_into_pyobject(self.as_ref(), py, crate::conversion::private::Token) } } #[cfg(test)] mod tests { use std::borrow::Cow; use crate::{ conversion::IntoPyObject, ffi, types::{any::PyAnyMethods, PyBytes, PyBytesMethods, PyList}, Python, }; #[test] fn test_extract_bytes() { Python::with_gil(|py| { let py_bytes = py.eval(ffi::c_str!("b'Hello Python'"), None, None).unwrap(); let bytes: &[u8] = py_bytes.extract().unwrap(); assert_eq!(bytes, b"Hello Python"); }); } #[test] fn test_cow_impl() { Python::with_gil(|py| { let bytes = py.eval(ffi::c_str!(r#"b"foobar""#), None, None).unwrap(); let cow = bytes.extract::>().unwrap(); assert_eq!(cow, Cow::<[u8]>::Borrowed(b"foobar")); let byte_array = py .eval(ffi::c_str!(r#"bytearray(b"foobar")"#), None, None) .unwrap(); let cow = byte_array.extract::>().unwrap(); assert_eq!(cow, Cow::<[u8]>::Owned(b"foobar".to_vec())); let something_else_entirely = py.eval(ffi::c_str!("42"), None, None).unwrap(); something_else_entirely .extract::>() .unwrap_err(); let cow = Cow::<[u8]>::Borrowed(b"foobar").into_pyobject(py).unwrap(); assert!(cow.is_instance_of::()); let cow = Cow::<[u8]>::Owned(b"foobar".to_vec()) .into_pyobject(py) .unwrap(); assert!(cow.is_instance_of::()); }); } #[test] fn test_slice_intopyobject_impl() { Python::with_gil(|py| { let bytes: &[u8] = b"foobar"; let obj = bytes.into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); let obj = obj.downcast_into::().unwrap(); assert_eq!(obj.as_bytes(), bytes); let nums: &[u16] = &[0, 1, 2, 3]; let obj = nums.into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); }); } #[test] fn test_cow_intopyobject_impl() { Python::with_gil(|py| { let borrowed_bytes = Cow::<[u8]>::Borrowed(b"foobar"); let obj = borrowed_bytes.clone().into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); let obj = obj.downcast_into::().unwrap(); assert_eq!(obj.as_bytes(), &*borrowed_bytes); let owned_bytes = Cow::<[u8]>::Owned(b"foobar".to_vec()); let obj = owned_bytes.clone().into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); let obj = obj.downcast_into::().unwrap(); assert_eq!(obj.as_bytes(), &*owned_bytes); let borrowed_nums = Cow::<[u16]>::Borrowed(&[0, 1, 2, 3]); let obj = borrowed_nums.into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); let owned_nums = Cow::<[u16]>::Owned(vec![0, 1, 2, 3]); let obj = owned_nums.into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); }); } } pyo3/src/conversions/std/set.rs0000644000175000017500000001261015105742312016366 0ustar bdrungbdrunguse std::{cmp, collections, hash}; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ conversion::IntoPyObject, instance::Bound, types::{ any::PyAnyMethods, frozenset::PyFrozenSetMethods, set::{try_new_from_iter, PySetMethods}, PyFrozenSet, PySet, }, FromPyObject, PyAny, PyErr, PyResult, Python, }; impl<'py, K, S> IntoPyObject<'py> for collections::HashSet where K: IntoPyObject<'py> + Eq + hash::Hash, S: hash::BuildHasher + Default, { type Target = PySet; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::set_of(K::type_output()) } } impl<'a, 'py, K, H> IntoPyObject<'py> for &'a collections::HashSet where &'a K: IntoPyObject<'py> + Eq + hash::Hash, K: 'a, // MSRV H: hash::BuildHasher, { type Target = PySet; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self.iter()) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::set_of(<&K>::type_output()) } } impl<'py, K, S> FromPyObject<'py> for collections::HashSet where K: FromPyObject<'py> + cmp::Eq + hash::Hash, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { match ob.downcast::() { Ok(set) => set.iter().map(|any| any.extract()).collect(), Err(err) => { if let Ok(frozen_set) = ob.downcast::() { frozen_set.iter().map(|any| any.extract()).collect() } else { Err(PyErr::from(err)) } } } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::set_of(K::type_input()) } } impl<'py, K> IntoPyObject<'py> for collections::BTreeSet where K: IntoPyObject<'py> + cmp::Ord, { type Target = PySet; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::set_of(K::type_output()) } } impl<'a, 'py, K> IntoPyObject<'py> for &'a collections::BTreeSet where &'a K: IntoPyObject<'py> + cmp::Ord, K: 'a, { type Target = PySet; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self.iter()) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::set_of(<&K>::type_output()) } } impl<'py, K> FromPyObject<'py> for collections::BTreeSet where K: FromPyObject<'py> + cmp::Ord, { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { match ob.downcast::() { Ok(set) => set.iter().map(|any| any.extract()).collect(), Err(err) => { if let Ok(frozen_set) = ob.downcast::() { frozen_set.iter().map(|any| any.extract()).collect() } else { Err(PyErr::from(err)) } } } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::set_of(K::type_input()) } } #[cfg(test)] mod tests { use crate::types::{any::PyAnyMethods, PyFrozenSet, PySet}; use crate::{IntoPyObject, Python}; use std::collections::{BTreeSet, HashSet}; #[test] fn test_extract_hashset() { Python::with_gil(|py| { let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap(); let hash_set: HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); let set = PyFrozenSet::new(py, [1, 2, 3, 4, 5]).unwrap(); let hash_set: HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); }); } #[test] fn test_extract_btreeset() { Python::with_gil(|py| { let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap(); let hash_set: BTreeSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); let set = PyFrozenSet::new(py, [1, 2, 3, 4, 5]).unwrap(); let hash_set: BTreeSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); }); } #[test] fn test_set_into_pyobject() { Python::with_gil(|py| { let bt: BTreeSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let hs: HashSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let bto = (&bt).into_pyobject(py).unwrap(); let hso = (&hs).into_pyobject(py).unwrap(); assert_eq!(bt, bto.extract().unwrap()); assert_eq!(hs, hso.extract().unwrap()); }); } } pyo3/src/conversions/std/cell.rs0000644000175000017500000000162715105742312016520 0ustar bdrungbdrunguse std::cell::Cell; use crate::{ conversion::IntoPyObject, types::any::PyAnyMethods, Bound, FromPyObject, PyAny, PyResult, Python, }; impl<'py, T: Copy + IntoPyObject<'py>> IntoPyObject<'py> for Cell { type Target = T::Target; type Output = T::Output; type Error = T::Error; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.get().into_pyobject(py) } } impl<'py, T: Copy + IntoPyObject<'py>> IntoPyObject<'py> for &Cell { type Target = T::Target; type Output = T::Output; type Error = T::Error; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.get().into_pyobject(py) } } impl<'py, T: FromPyObject<'py>> FromPyObject<'py> for Cell { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { ob.extract().map(Cell::new) } } pyo3/src/conversions/std/ipaddr.rs0000644000175000017500000001065515105742312017045 0ustar bdrungbdrunguse std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use crate::conversion::IntoPyObject; use crate::exceptions::PyValueError; use crate::instance::Bound; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::string::PyStringMethods; use crate::types::PyType; use crate::{intern, FromPyObject, Py, PyAny, PyErr, PyResult, Python}; impl FromPyObject<'_> for IpAddr { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { match obj.getattr(intern!(obj.py(), "packed")) { Ok(packed) => { if let Ok(packed) = packed.extract::<[u8; 4]>() { Ok(IpAddr::V4(Ipv4Addr::from(packed))) } else if let Ok(packed) = packed.extract::<[u8; 16]>() { Ok(IpAddr::V6(Ipv6Addr::from(packed))) } else { Err(PyValueError::new_err("invalid packed length")) } } Err(_) => { // We don't have a .packed attribute, so we try to construct an IP from str(). obj.str()?.to_cow()?.parse().map_err(PyValueError::new_err) } } } } impl<'py> IntoPyObject<'py> for Ipv4Addr { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { static IPV4_ADDRESS: GILOnceCell> = GILOnceCell::new(); IPV4_ADDRESS .import(py, "ipaddress", "IPv4Address")? .call1((u32::from_be_bytes(self.octets()),)) } } impl<'py> IntoPyObject<'py> for &Ipv4Addr { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for Ipv6Addr { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { static IPV6_ADDRESS: GILOnceCell> = GILOnceCell::new(); IPV6_ADDRESS .import(py, "ipaddress", "IPv6Address")? .call1((u128::from_be_bytes(self.octets()),)) } } impl<'py> IntoPyObject<'py> for &Ipv6Addr { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for IpAddr { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { match self { IpAddr::V4(ip) => ip.into_pyobject(py), IpAddr::V6(ip) => ip.into_pyobject(py), } } } impl<'py> IntoPyObject<'py> for &IpAddr { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } #[cfg(test)] mod test_ipaddr { use std::str::FromStr; use crate::types::PyString; use super::*; #[test] fn test_roundtrip() { Python::with_gil(|py| { fn roundtrip(py: Python<'_>, ip: &str) { let ip = IpAddr::from_str(ip).unwrap(); let py_cls = if ip.is_ipv4() { "IPv4Address" } else { "IPv6Address" }; let pyobj = ip.into_pyobject(py).unwrap(); let repr = pyobj.repr().unwrap(); let repr = repr.to_string_lossy(); assert_eq!(repr, format!("{py_cls}('{ip}')")); let ip2: IpAddr = pyobj.extract().unwrap(); assert_eq!(ip, ip2); } roundtrip(py, "127.0.0.1"); roundtrip(py, "::1"); roundtrip(py, "0.0.0.0"); }); } #[test] fn test_from_pystring() { Python::with_gil(|py| { let py_str = PyString::new(py, "0:0:0:0:0:0:0:1"); let ip: IpAddr = py_str.extract().unwrap(); assert_eq!(ip, IpAddr::from_str("::1").unwrap()); let py_str = PyString::new(py, "invalid"); assert!(py_str.extract::().is_err()); }); } } pyo3/src/conversions/std/osstr.rs0000644000175000017500000001713015105742312016747 0ustar bdrungbdrunguse crate::conversion::IntoPyObject; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::types::PyString; use crate::{ffi, FromPyObject, PyAny, PyResult, Python}; use std::borrow::Cow; use std::convert::Infallible; use std::ffi::{OsStr, OsString}; impl<'py> IntoPyObject<'py> for &OsStr { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { // If the string is UTF-8, take the quick and easy shortcut if let Some(valid_utf8_path) = self.to_str() { return valid_utf8_path.into_pyobject(py); } // All targets besides windows support the std::os::unix::ffi::OsStrExt API: // https://doc.rust-lang.org/src/std/sys_common/mod.rs.html#59 #[cfg(not(windows))] { #[cfg(target_os = "wasi")] let bytes = std::os::wasi::ffi::OsStrExt::as_bytes(self); #[cfg(not(target_os = "wasi"))] let bytes = std::os::unix::ffi::OsStrExt::as_bytes(self); let ptr = bytes.as_ptr().cast(); let len = bytes.len() as ffi::Py_ssize_t; unsafe { // DecodeFSDefault automatically chooses an appropriate decoding mechanism to // parse os strings losslessly (i.e. surrogateescape most of the time) Ok(ffi::PyUnicode_DecodeFSDefaultAndSize(ptr, len) .assume_owned(py) .downcast_into_unchecked::()) } } #[cfg(windows)] { let wstr: Vec = std::os::windows::ffi::OsStrExt::encode_wide(self).collect(); unsafe { // This will not panic because the data from encode_wide is well-formed Windows // string data Ok( ffi::PyUnicode_FromWideChar(wstr.as_ptr(), wstr.len() as ffi::Py_ssize_t) .assume_owned(py) .downcast_into_unchecked::(), ) } } } } impl<'py> IntoPyObject<'py> for &&OsStr { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } // There's no FromPyObject implementation for &OsStr because albeit possible on Unix, this would // be impossible to implement on Windows. Hence it's omitted entirely impl FromPyObject<'_> for OsString { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { let pystring = ob.downcast::()?; #[cfg(not(windows))] { // Decode from Python's lossless bytes string representation back into raw bytes let fs_encoded_bytes = unsafe { crate::Py::::from_owned_ptr( ob.py(), ffi::PyUnicode_EncodeFSDefault(pystring.as_ptr()), ) }; // Create an OsStr view into the raw bytes from Python #[cfg(target_os = "wasi")] let os_str: &OsStr = std::os::wasi::ffi::OsStrExt::from_bytes(fs_encoded_bytes.as_bytes(ob.py())); #[cfg(not(target_os = "wasi"))] let os_str: &OsStr = std::os::unix::ffi::OsStrExt::from_bytes(fs_encoded_bytes.as_bytes(ob.py())); Ok(os_str.to_os_string()) } #[cfg(windows)] { use crate::types::string::PyStringMethods; // Take the quick and easy shortcut if UTF-8 if let Ok(utf8_string) = pystring.to_cow() { return Ok(utf8_string.into_owned().into()); } // Get an owned allocated wide char buffer from PyString, which we have to deallocate // ourselves let size = unsafe { ffi::PyUnicode_AsWideChar(pystring.as_ptr(), std::ptr::null_mut(), 0) }; crate::err::error_on_minusone(ob.py(), size)?; let mut buffer = vec![0; size as usize]; let bytes_read = unsafe { ffi::PyUnicode_AsWideChar(pystring.as_ptr(), buffer.as_mut_ptr(), size) }; assert_eq!(bytes_read, size); // Copy wide char buffer into OsString let os_string = std::os::windows::ffi::OsStringExt::from_wide(&buffer); Ok(os_string) } } } impl<'py> IntoPyObject<'py> for Cow<'_, OsStr> { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for &Cow<'_, OsStr> { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (&**self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for OsString { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.as_os_str().into_pyobject(py) } } impl<'py> IntoPyObject<'py> for &OsString { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.as_os_str().into_pyobject(py) } } #[cfg(test)] mod tests { use crate::types::{PyAnyMethods, PyString, PyStringMethods}; use crate::{BoundObject, IntoPyObject, Python}; use std::fmt::Debug; use std::{ borrow::Cow, ffi::{OsStr, OsString}, }; #[test] #[cfg(not(windows))] fn test_non_utf8_conversion() { Python::with_gil(|py| { #[cfg(not(target_os = "wasi"))] use std::os::unix::ffi::OsStrExt; #[cfg(target_os = "wasi")] use std::os::wasi::ffi::OsStrExt; // this is not valid UTF-8 let payload = &[250, 251, 252, 253, 254, 255, 0, 255]; let os_str = OsStr::from_bytes(payload); // do a roundtrip into Pythonland and back and compare let py_str = os_str.into_pyobject(py).unwrap(); let os_str_2: OsString = py_str.extract().unwrap(); assert_eq!(os_str, os_str_2); }); } #[test] fn test_intopyobject_roundtrip() { Python::with_gil(|py| { fn test_roundtrip<'py, T>(py: Python<'py>, obj: T) where T: IntoPyObject<'py> + AsRef + Debug + Clone, T::Error: Debug, { let pyobject = obj.clone().into_pyobject(py).unwrap().into_any(); let pystring = pyobject.as_borrowed().downcast::().unwrap(); assert_eq!(pystring.to_string_lossy(), obj.as_ref().to_string_lossy()); let roundtripped_obj: OsString = pystring.extract().unwrap(); assert_eq!(obj.as_ref(), roundtripped_obj.as_os_str()); } let os_str = OsStr::new("Hello\0\n🐍"); test_roundtrip::<&OsStr>(py, os_str); test_roundtrip::>(py, Cow::Borrowed(os_str)); test_roundtrip::>(py, Cow::Owned(os_str.to_os_string())); test_roundtrip::(py, os_str.to_os_string()); }); } } pyo3/src/conversions/std/string.rs0000644000175000017500000001717015105742312017107 0ustar bdrungbdrunguse std::{borrow::Cow, convert::Infallible}; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ conversion::IntoPyObject, instance::Bound, types::{any::PyAnyMethods, string::PyStringMethods, PyString}, FromPyObject, PyAny, PyResult, Python, }; impl<'py> IntoPyObject<'py> for &str { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyString::new(py, self)) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } impl<'py> IntoPyObject<'py> for &&str { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } impl<'py> IntoPyObject<'py> for Cow<'_, str> { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } impl<'py> IntoPyObject<'py> for &Cow<'_, str> { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (&**self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } impl<'py> IntoPyObject<'py> for char { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { let mut bytes = [0u8; 4]; Ok(PyString::new(py, self.encode_utf8(&mut bytes))) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } impl<'py> IntoPyObject<'py> for &char { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } impl<'py> IntoPyObject<'py> for String { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyString::new(py, &self)) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("str") } } impl<'py> IntoPyObject<'py> for &String { type Target = PyString; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyString::new(py, self)) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for &'a str { fn from_py_object_bound(ob: crate::Borrowed<'a, '_, PyAny>) -> PyResult { ob.downcast::()?.to_str() } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for Cow<'a, str> { fn from_py_object_bound(ob: crate::Borrowed<'a, '_, PyAny>) -> PyResult { ob.downcast::()?.to_cow() } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } /// Allows extracting strings from Python objects. /// Accepts Python `str` and `unicode` objects. impl FromPyObject<'_> for String { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { obj.downcast::()?.to_cow().map(Cow::into_owned) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } impl FromPyObject<'_> for char { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let s = obj.downcast::()?.to_cow()?; let mut iter = s.chars(); if let (Some(ch), None) = (iter.next(), iter.next()) { Ok(ch) } else { Err(crate::exceptions::PyValueError::new_err( "expected a string of length 1", )) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } #[cfg(test)] mod tests { use crate::types::any::PyAnyMethods; use crate::{IntoPyObject, Python}; use std::borrow::Cow; #[test] fn test_cow_into_pyobject() { Python::with_gil(|py| { let s = "Hello Python"; let py_string = Cow::Borrowed(s).into_pyobject(py).unwrap(); assert_eq!(s, py_string.extract::>().unwrap()); let py_string = Cow::::Owned(s.into()).into_pyobject(py).unwrap(); assert_eq!(s, py_string.extract::>().unwrap()); }) } #[test] fn test_non_bmp() { Python::with_gil(|py| { let s = "\u{1F30F}"; let py_string = s.into_pyobject(py).unwrap(); assert_eq!(s, py_string.extract::().unwrap()); }) } #[test] fn test_extract_str() { Python::with_gil(|py| { let s = "Hello Python"; let py_string = s.into_pyobject(py).unwrap(); let s2: Cow<'_, str> = py_string.extract().unwrap(); assert_eq!(s, s2); }) } #[test] fn test_extract_char() { Python::with_gil(|py| { let ch = '😃'; let py_string = ch.into_pyobject(py).unwrap(); let ch2: char = py_string.extract().unwrap(); assert_eq!(ch, ch2); }) } #[test] fn test_extract_char_err() { Python::with_gil(|py| { let s = "Hello Python"; let py_string = s.into_pyobject(py).unwrap(); let err: crate::PyResult = py_string.extract(); assert!(err .unwrap_err() .to_string() .contains("expected a string of length 1")); }) } #[test] fn test_string_into_pyobject() { Python::with_gil(|py| { let s = "Hello Python"; let s2 = s.to_owned(); let s3 = &s2; assert_eq!( s, s3.into_pyobject(py) .unwrap() .extract::>() .unwrap() ); assert_eq!( s, s2.into_pyobject(py) .unwrap() .extract::>() .unwrap() ); assert_eq!( s, s.into_pyobject(py) .unwrap() .extract::>() .unwrap() ); }) } } pyo3/src/conversions/std/map.rs0000644000175000017500000001442015105742312016351 0ustar bdrungbdrunguse std::{cmp, collections, hash}; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ conversion::IntoPyObject, instance::Bound, types::{any::PyAnyMethods, dict::PyDictMethods, PyDict}, FromPyObject, PyAny, PyErr, Python, }; impl<'py, K, V, H> IntoPyObject<'py> for collections::HashMap where K: IntoPyObject<'py> + cmp::Eq + hash::Hash, V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::dict_of(K::type_output(), V::type_output()) } } impl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a collections::HashMap where &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash, &'a V: IntoPyObject<'py>, K: 'a, // MSRV V: 'a, // MSRV H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::dict_of(<&K>::type_output(), <&V>::type_output()) } } impl<'py, K, V> IntoPyObject<'py> for collections::BTreeMap where K: IntoPyObject<'py> + cmp::Eq, V: IntoPyObject<'py>, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::dict_of(K::type_output(), V::type_output()) } } impl<'a, 'py, K, V> IntoPyObject<'py> for &'a collections::BTreeMap where &'a K: IntoPyObject<'py> + cmp::Eq, &'a V: IntoPyObject<'py>, K: 'a, V: 'a, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::dict_of(<&K>::type_output(), <&V>::type_output()) } } impl<'py, K, V, S> FromPyObject<'py> for collections::HashMap where K: FromPyObject<'py> + cmp::Eq + hash::Hash, V: FromPyObject<'py>, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> Result { let dict = ob.downcast::()?; let mut ret = collections::HashMap::with_capacity_and_hasher(dict.len(), S::default()); for (k, v) in dict { ret.insert(k.extract()?, v.extract()?); } Ok(ret) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::mapping_of(K::type_input(), V::type_input()) } } impl<'py, K, V> FromPyObject<'py> for collections::BTreeMap where K: FromPyObject<'py> + cmp::Ord, V: FromPyObject<'py>, { fn extract_bound(ob: &Bound<'py, PyAny>) -> Result { let dict = ob.downcast::()?; let mut ret = collections::BTreeMap::new(); for (k, v) in dict { ret.insert(k.extract()?, v.extract()?); } Ok(ret) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::mapping_of(K::type_input(), V::type_input()) } } #[cfg(test)] mod tests { use super::*; use std::collections::{BTreeMap, HashMap}; #[test] fn test_hashmap_to_python() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let py_map = (&map).into_pyobject(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!(map, py_map.extract().unwrap()); }); } #[test] fn test_btreemap_to_python() { Python::with_gil(|py| { let mut map = BTreeMap::::new(); map.insert(1, 1); let py_map = (&map).into_pyobject(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!(map, py_map.extract().unwrap()); }); } #[test] fn test_hashmap_into_python() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let py_map = map.into_pyobject(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); }); } #[test] fn test_btreemap_into_py() { Python::with_gil(|py| { let mut map = BTreeMap::::new(); map.insert(1, 1); let py_map = map.into_pyobject(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); }); } } pyo3/src/conversions/std/path.rs0000644000175000017500000001077515105742312016541 0ustar bdrungbdrunguse crate::conversion::IntoPyObject; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::{ffi, FromPyObject, PyAny, PyErr, PyObject, PyResult, Python}; use std::borrow::Cow; use std::ffi::OsString; use std::path::{Path, PathBuf}; // See osstr.rs for why there's no FromPyObject impl for &Path impl FromPyObject<'_> for PathBuf { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { // We use os.fspath to get the underlying path as bytes or str let path = unsafe { ffi::PyOS_FSPath(ob.as_ptr()).assume_owned_or_err(ob.py())? }; Ok(path.extract::()?.into()) } } impl<'py> IntoPyObject<'py> for &Path { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { static PY_PATH: GILOnceCell = GILOnceCell::new(); PY_PATH .import(py, "pathlib", "Path")? .call((self.as_os_str(),), None) } } impl<'py> IntoPyObject<'py> for &&Path { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for Cow<'_, Path> { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for &Cow<'_, Path> { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (&**self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for PathBuf { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (&self).into_pyobject(py) } } impl<'py> IntoPyObject<'py> for &PathBuf { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (&**self).into_pyobject(py) } } #[cfg(test)] mod tests { use crate::types::{PyAnyMethods, PyString}; use crate::{IntoPyObject, IntoPyObjectExt, Python}; use std::borrow::Cow; use std::fmt::Debug; use std::path::{Path, PathBuf}; #[test] #[cfg(not(windows))] fn test_non_utf8_conversion() { Python::with_gil(|py| { use std::ffi::OsStr; #[cfg(not(target_os = "wasi"))] use std::os::unix::ffi::OsStrExt; #[cfg(target_os = "wasi")] use std::os::wasi::ffi::OsStrExt; // this is not valid UTF-8 let payload = &[250, 251, 252, 253, 254, 255, 0, 255]; let path = Path::new(OsStr::from_bytes(payload)); // do a roundtrip into Pythonland and back and compare let py_str = path.into_pyobject(py).unwrap(); let path_2: PathBuf = py_str.extract().unwrap(); assert_eq!(path, path_2); }); } #[test] fn test_intopyobject_roundtrip() { Python::with_gil(|py| { fn test_roundtrip<'py, T>(py: Python<'py>, obj: T) where T: IntoPyObject<'py> + AsRef + Debug + Clone, T::Error: Debug, { let pyobject = obj.clone().into_bound_py_any(py).unwrap(); let roundtripped_obj: PathBuf = pyobject.extract().unwrap(); assert_eq!(obj.as_ref(), roundtripped_obj.as_path()); } let path = Path::new("Hello\0\n🐍"); test_roundtrip::<&Path>(py, path); test_roundtrip::>(py, Cow::Borrowed(path)); test_roundtrip::>(py, Cow::Owned(path.to_path_buf())); test_roundtrip::(py, path.to_path_buf()); }); } #[test] fn test_from_pystring() { Python::with_gil(|py| { let path = "Hello\0\n🐍"; let pystring = PyString::new(py, path); let roundtrip: PathBuf = pystring.extract().unwrap(); assert_eq!(roundtrip, Path::new(path)); }); } } pyo3/src/conversions/std/num.rs0000644000175000017500000010476115105742312016403 0ustar bdrungbdrunguse crate::conversion::private::Reference; use crate::conversion::IntoPyObject; use crate::ffi_ptr_ext::FfiPtrExt; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::types::any::PyAnyMethods; use crate::types::{PyBytes, PyInt}; use crate::{exceptions, ffi, Bound, FromPyObject, PyAny, PyErr, PyResult, Python}; use std::convert::Infallible; use std::num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, }; use std::os::raw::c_long; macro_rules! int_fits_larger_int { ($rust_type:ty, $larger_type:ty) => { impl<'py> IntoPyObject<'py> for $rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { (self as $larger_type).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { <$larger_type>::type_output() } } impl<'py> IntoPyObject<'py> for &$rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { <$larger_type>::type_output() } } impl FromPyObject<'_> for $rust_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let val: $larger_type = obj.extract()?; <$rust_type>::try_from(val) .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string())) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { <$larger_type>::type_input() } } }; } macro_rules! extract_int { ($obj:ident, $error_val:expr, $pylong_as:expr) => { extract_int!($obj, $error_val, $pylong_as, false) }; ($obj:ident, $error_val:expr, $pylong_as:expr, $force_index_call: literal) => { // In python 3.8+ `PyLong_AsLong` and friends takes care of calling `PyNumber_Index`, // however 3.8 & 3.9 do lossy conversion of floats, hence we only use the // simplest logic for 3.10+ where that was fixed - python/cpython#82180. // `PyLong_AsUnsignedLongLong` does not call `PyNumber_Index`, hence the `force_index_call` argument // See https://github.com/PyO3/pyo3/pull/3742 for detials if cfg!(Py_3_10) && !$force_index_call { err_if_invalid_value($obj.py(), $error_val, unsafe { $pylong_as($obj.as_ptr()) }) } else if let Ok(long) = $obj.downcast::() { // fast path - checking for subclass of `int` just checks a bit in the type $object err_if_invalid_value($obj.py(), $error_val, unsafe { $pylong_as(long.as_ptr()) }) } else { unsafe { let num = ffi::PyNumber_Index($obj.as_ptr()).assume_owned_or_err($obj.py())?; err_if_invalid_value($obj.py(), $error_val, $pylong_as(num.as_ptr())) } } }; } macro_rules! int_convert_u64_or_i64 { ($rust_type:ty, $pylong_from_ll_or_ull:expr, $pylong_as_ll_or_ull:expr, $force_index_call:literal) => { impl<'py> IntoPyObject<'py> for $rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { unsafe { Ok($pylong_from_ll_or_ull(self) .assume_owned(py) .downcast_into_unchecked()) } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl<'py> IntoPyObject<'py> for &$rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl FromPyObject<'_> for $rust_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<$rust_type> { extract_int!(obj, !0, $pylong_as_ll_or_ull, $force_index_call) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } }; } macro_rules! int_fits_c_long { ($rust_type:ty) => { impl<'py> IntoPyObject<'py> for $rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { unsafe { Ok(ffi::PyLong_FromLong(self as c_long) .assume_owned(py) .downcast_into_unchecked()) } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl<'py> IntoPyObject<'py> for &$rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl<'py> FromPyObject<'py> for $rust_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let val: c_long = extract_int!(obj, -1, ffi::PyLong_AsLong)?; <$rust_type>::try_from(val) .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string())) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } }; } impl<'py> IntoPyObject<'py> for u8 { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { unsafe { Ok(ffi::PyLong_FromLong(self as c_long) .assume_owned(py) .downcast_into_unchecked()) } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } #[inline] fn owned_sequence_into_pyobject( iter: I, py: Python<'py>, _: crate::conversion::private::Token, ) -> Result, PyErr> where I: AsRef<[u8]>, { Ok(PyBytes::new(py, iter.as_ref()).into_any()) } } impl<'py> IntoPyObject<'py> for &'_ u8 { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { u8::into_pyobject(*self, py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } #[inline] fn borrowed_sequence_into_pyobject( iter: I, py: Python<'py>, _: crate::conversion::private::Token, ) -> Result, PyErr> where // I: AsRef<[u8]>, but the compiler needs it expressed via the trait for some reason I: AsRef<[::BaseType]>, { Ok(PyBytes::new(py, iter.as_ref()).into_any()) } } impl FromPyObject<'_> for u8 { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let val: c_long = extract_int!(obj, -1, ffi::PyLong_AsLong)?; u8::try_from(val).map_err(|e| exceptions::PyOverflowError::new_err(e.to_string())) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } int_fits_c_long!(i8); int_fits_c_long!(i16); int_fits_c_long!(u16); int_fits_c_long!(i32); // If c_long is 64-bits, we can use more types with int_fits_c_long!: #[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] int_fits_c_long!(u32); #[cfg(any(target_pointer_width = "32", target_os = "windows"))] int_fits_larger_int!(u32, u64); #[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] int_fits_c_long!(i64); // manual implementation for i64 on systems with 32-bit long #[cfg(any(target_pointer_width = "32", target_os = "windows"))] int_convert_u64_or_i64!(i64, ffi::PyLong_FromLongLong, ffi::PyLong_AsLongLong, false); #[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] int_fits_c_long!(isize); #[cfg(any(target_pointer_width = "32", target_os = "windows"))] int_fits_larger_int!(isize, i64); int_fits_larger_int!(usize, u64); // u64 has a manual implementation as it never fits into signed long int_convert_u64_or_i64!( u64, ffi::PyLong_FromUnsignedLongLong, ffi::PyLong_AsUnsignedLongLong, true ); #[cfg(all(not(Py_LIMITED_API), not(GraalPy)))] mod fast_128bit_int_conversion { use super::*; // for 128bit Integers macro_rules! int_convert_128 { ($rust_type: ty, $is_signed: literal) => { impl<'py> IntoPyObject<'py> for $rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { #[cfg(not(Py_3_13))] { let bytes = self.to_le_bytes(); unsafe { Ok(ffi::_PyLong_FromByteArray( bytes.as_ptr().cast(), bytes.len(), 1, $is_signed.into(), ) .assume_owned(py) .downcast_into_unchecked()) } } #[cfg(Py_3_13)] { let bytes = self.to_ne_bytes(); if $is_signed { unsafe { Ok(ffi::PyLong_FromNativeBytes( bytes.as_ptr().cast(), bytes.len(), ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN, ) .assume_owned(py) .downcast_into_unchecked()) } } else { unsafe { Ok(ffi::PyLong_FromUnsignedNativeBytes( bytes.as_ptr().cast(), bytes.len(), ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN, ) .assume_owned(py) .downcast_into_unchecked()) } } } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl<'py> IntoPyObject<'py> for &$rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl FromPyObject<'_> for $rust_type { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<$rust_type> { let num = unsafe { ffi::PyNumber_Index(ob.as_ptr()).assume_owned_or_err(ob.py())? }; let mut buffer = [0u8; std::mem::size_of::<$rust_type>()]; #[cfg(not(Py_3_13))] { crate::err::error_on_minusone(ob.py(), unsafe { ffi::_PyLong_AsByteArray( num.as_ptr() as *mut ffi::PyLongObject, buffer.as_mut_ptr(), buffer.len(), 1, $is_signed.into(), ) })?; Ok(<$rust_type>::from_le_bytes(buffer)) } #[cfg(Py_3_13)] { let mut flags = ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN; if !$is_signed { flags |= ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER | ffi::Py_ASNATIVEBYTES_REJECT_NEGATIVE; } let actual_size: usize = unsafe { ffi::PyLong_AsNativeBytes( num.as_ptr(), buffer.as_mut_ptr().cast(), buffer .len() .try_into() .expect("length of buffer fits in Py_ssize_t"), flags, ) } .try_into() .map_err(|_| PyErr::fetch(ob.py()))?; if actual_size as usize > buffer.len() { return Err(crate::exceptions::PyOverflowError::new_err( "Python int larger than 128 bits", )); } Ok(<$rust_type>::from_ne_bytes(buffer)) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } }; } int_convert_128!(i128, true); int_convert_128!(u128, false); } // For ABI3 we implement the conversion manually. #[cfg(any(Py_LIMITED_API, GraalPy))] mod slow_128bit_int_conversion { use super::*; const SHIFT: usize = 64; // for 128bit Integers macro_rules! int_convert_128 { ($rust_type: ty, $half_type: ty) => { impl<'py> IntoPyObject<'py> for $rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { let lower = (self as u64).into_pyobject(py)?; let upper = ((self >> SHIFT) as $half_type).into_pyobject(py)?; let shift = SHIFT.into_pyobject(py)?; unsafe { let shifted = ffi::PyNumber_Lshift(upper.as_ptr(), shift.as_ptr()).assume_owned(py); Ok(ffi::PyNumber_Or(shifted.as_ptr(), lower.as_ptr()) .assume_owned(py) .downcast_into_unchecked()) } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl<'py> IntoPyObject<'py> for &$rust_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl FromPyObject<'_> for $rust_type { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<$rust_type> { let py = ob.py(); unsafe { let lower = err_if_invalid_value( py, -1 as _, ffi::PyLong_AsUnsignedLongLongMask(ob.as_ptr()), )? as $rust_type; let shift = SHIFT.into_pyobject(py)?; let shifted = Bound::from_owned_ptr_or_err( py, ffi::PyNumber_Rshift(ob.as_ptr(), shift.as_ptr()), )?; let upper: $half_type = shifted.extract()?; Ok((<$rust_type>::from(upper) << SHIFT) | lower) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } }; } int_convert_128!(i128, i64); int_convert_128!(u128, u64); } fn err_if_invalid_value( py: Python<'_>, invalid_value: T, actual_value: T, ) -> PyResult { if actual_value == invalid_value { if let Some(err) = PyErr::take(py) { return Err(err); } } Ok(actual_value) } macro_rules! nonzero_int_impl { ($nonzero_type:ty, $primitive_type:ty) => { impl<'py> IntoPyObject<'py> for $nonzero_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { self.get().into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl<'py> IntoPyObject<'py> for &$nonzero_type { type Target = PyInt; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl FromPyObject<'_> for $nonzero_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let val: $primitive_type = obj.extract()?; <$nonzero_type>::try_from(val) .map_err(|_| exceptions::PyValueError::new_err("invalid zero value")) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { <$primitive_type>::type_input() } } }; } nonzero_int_impl!(NonZeroI8, i8); nonzero_int_impl!(NonZeroI16, i16); nonzero_int_impl!(NonZeroI32, i32); nonzero_int_impl!(NonZeroI64, i64); nonzero_int_impl!(NonZeroI128, i128); nonzero_int_impl!(NonZeroIsize, isize); nonzero_int_impl!(NonZeroU8, u8); nonzero_int_impl!(NonZeroU16, u16); nonzero_int_impl!(NonZeroU32, u32); nonzero_int_impl!(NonZeroU64, u64); nonzero_int_impl!(NonZeroU128, u128); nonzero_int_impl!(NonZeroUsize, usize); #[cfg(test)] mod test_128bit_integers { use super::*; #[cfg(not(target_arch = "wasm32"))] use crate::types::PyDict; #[cfg(not(target_arch = "wasm32"))] use crate::types::dict::PyDictMethods; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; #[cfg(not(target_arch = "wasm32"))] use std::ffi::CString; #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_i128_roundtrip(x: i128) { Python::with_gil(|py| { let x_py = x.into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("x_py", &x_py).unwrap(); py.run(&CString::new(format!("assert x_py == {x}")).unwrap(), None, Some(&locals)).unwrap(); let roundtripped: i128 = x_py.extract().unwrap(); assert_eq!(x, roundtripped); }) } #[test] fn test_nonzero_i128_roundtrip( x in any::() .prop_filter("Values must not be 0", |x| x != &0) .prop_map(|x| NonZeroI128::new(x).unwrap()) ) { Python::with_gil(|py| { let x_py = x.into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("x_py", &x_py).unwrap(); py.run(&CString::new(format!("assert x_py == {x}")).unwrap(), None, Some(&locals)).unwrap(); let roundtripped: NonZeroI128 = x_py.extract().unwrap(); assert_eq!(x, roundtripped); }) } } #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_u128_roundtrip(x: u128) { Python::with_gil(|py| { let x_py = x.into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("x_py", &x_py).unwrap(); py.run(&CString::new(format!("assert x_py == {x}")).unwrap(), None, Some(&locals)).unwrap(); let roundtripped: u128 = x_py.extract().unwrap(); assert_eq!(x, roundtripped); }) } #[test] fn test_nonzero_u128_roundtrip( x in any::() .prop_filter("Values must not be 0", |x| x != &0) .prop_map(|x| NonZeroU128::new(x).unwrap()) ) { Python::with_gil(|py| { let x_py = x.into_pyobject(py).unwrap(); let locals = PyDict::new(py); locals.set_item("x_py", &x_py).unwrap(); py.run(&CString::new(format!("assert x_py == {x}")).unwrap(), None, Some(&locals)).unwrap(); let roundtripped: NonZeroU128 = x_py.extract().unwrap(); assert_eq!(x, roundtripped); }) } } #[test] fn test_i128_max() { Python::with_gil(|py| { let v = i128::MAX; let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert_eq!(v as u128, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); }) } #[test] fn test_i128_min() { Python::with_gil(|py| { let v = i128::MIN; let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); assert!(obj.extract::().is_err()); }) } #[test] fn test_u128_max() { Python::with_gil(|py| { let v = u128::MAX; let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); }) } #[test] fn test_i128_overflow() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("(1 << 130) * -1"), None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_u128_overflow() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("1 << 130"), None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_nonzero_i128_max() { Python::with_gil(|py| { let v = NonZeroI128::new(i128::MAX).unwrap(); let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert_eq!( NonZeroU128::new(v.get() as u128).unwrap(), obj.extract::().unwrap() ); assert!(obj.extract::().is_err()); }) } #[test] fn test_nonzero_i128_min() { Python::with_gil(|py| { let v = NonZeroI128::new(i128::MIN).unwrap(); let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); assert!(obj.extract::().is_err()); }) } #[test] fn test_nonzero_u128_max() { Python::with_gil(|py| { let v = NonZeroU128::new(u128::MAX).unwrap(); let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); }) } #[test] fn test_nonzero_i128_overflow() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("(1 << 130) * -1"), None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_nonzero_u128_overflow() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("1 << 130"), None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_nonzero_i128_zero_value() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("0"), None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_nonzero_u128_zero_value() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("0"), None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } } #[cfg(test)] mod tests { use crate::types::PyAnyMethods; use crate::{IntoPyObject, Python}; use std::num::*; #[test] fn test_u32_max() { Python::with_gil(|py| { let v = u32::MAX; let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert_eq!(u64::from(v), obj.extract::().unwrap()); assert!(obj.extract::().is_err()); }); } #[test] fn test_i64_max() { Python::with_gil(|py| { let v = i64::MAX; let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert_eq!(v as u64, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); }); } #[test] fn test_i64_min() { Python::with_gil(|py| { let v = i64::MIN; let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); assert!(obj.extract::().is_err()); }); } #[test] fn test_u64_max() { Python::with_gil(|py| { let v = u64::MAX; let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); }); } macro_rules! test_common ( ($test_mod_name:ident, $t:ty) => ( mod $test_mod_name { use crate::exceptions; use crate::conversion::IntoPyObject; use crate::types::PyAnyMethods; use crate::Python; #[test] fn from_py_string_type_error() { Python::with_gil(|py| { let obj = ("123").into_pyobject(py).unwrap(); let err = obj.extract::<$t>().unwrap_err(); assert!(err.is_instance_of::(py)); }); } #[test] fn from_py_float_type_error() { Python::with_gil(|py| { let obj = (12.3f64).into_pyobject(py).unwrap(); let err = obj.extract::<$t>().unwrap_err(); assert!(err.is_instance_of::(py));}); } #[test] fn to_py_object_and_back() { Python::with_gil(|py| { let val = 123 as $t; let obj = val.into_pyobject(py).unwrap(); assert_eq!(obj.extract::<$t>().unwrap(), val as $t);}); } } ) ); test_common!(i8, i8); test_common!(u8, u8); test_common!(i16, i16); test_common!(u16, u16); test_common!(i32, i32); test_common!(u32, u32); test_common!(i64, i64); test_common!(u64, u64); test_common!(isize, isize); test_common!(usize, usize); test_common!(i128, i128); test_common!(u128, u128); #[test] fn test_nonzero_u32_max() { Python::with_gil(|py| { let v = NonZeroU32::new(u32::MAX).unwrap(); let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert_eq!(NonZeroU64::from(v), obj.extract::().unwrap()); assert!(obj.extract::().is_err()); }); } #[test] fn test_nonzero_i64_max() { Python::with_gil(|py| { let v = NonZeroI64::new(i64::MAX).unwrap(); let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert_eq!( NonZeroU64::new(v.get() as u64).unwrap(), obj.extract::().unwrap() ); assert!(obj.extract::().is_err()); }); } #[test] fn test_nonzero_i64_min() { Python::with_gil(|py| { let v = NonZeroI64::new(i64::MIN).unwrap(); let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); assert!(obj.extract::().is_err()); }); } #[test] fn test_nonzero_u64_max() { Python::with_gil(|py| { let v = NonZeroU64::new(u64::MAX).unwrap(); let obj = v.into_pyobject(py).unwrap(); assert_eq!(v, obj.extract::().unwrap()); assert!(obj.extract::().is_err()); }); } macro_rules! test_nonzero_common ( ($test_mod_name:ident, $t:ty) => ( mod $test_mod_name { use crate::exceptions; use crate::conversion::IntoPyObject; use crate::types::PyAnyMethods; use crate::Python; use std::num::*; #[test] fn from_py_string_type_error() { Python::with_gil(|py| { let obj = ("123").into_pyobject(py).unwrap(); let err = obj.extract::<$t>().unwrap_err(); assert!(err.is_instance_of::(py)); }); } #[test] fn from_py_float_type_error() { Python::with_gil(|py| { let obj = (12.3f64).into_pyobject(py).unwrap(); let err = obj.extract::<$t>().unwrap_err(); assert!(err.is_instance_of::(py));}); } #[test] fn to_py_object_and_back() { Python::with_gil(|py| { let val = <$t>::new(123).unwrap(); let obj = val.into_pyobject(py).unwrap(); assert_eq!(obj.extract::<$t>().unwrap(), val);}); } } ) ); test_nonzero_common!(nonzero_i8, NonZeroI8); test_nonzero_common!(nonzero_u8, NonZeroU8); test_nonzero_common!(nonzero_i16, NonZeroI16); test_nonzero_common!(nonzero_u16, NonZeroU16); test_nonzero_common!(nonzero_i32, NonZeroI32); test_nonzero_common!(nonzero_u32, NonZeroU32); test_nonzero_common!(nonzero_i64, NonZeroI64); test_nonzero_common!(nonzero_u64, NonZeroU64); test_nonzero_common!(nonzero_isize, NonZeroIsize); test_nonzero_common!(nonzero_usize, NonZeroUsize); test_nonzero_common!(nonzero_i128, NonZeroI128); test_nonzero_common!(nonzero_u128, NonZeroU128); #[test] fn test_i64_bool() { Python::with_gil(|py| { let obj = true.into_pyobject(py).unwrap(); assert_eq!(1, obj.extract::().unwrap()); let obj = false.into_pyobject(py).unwrap(); assert_eq!(0, obj.extract::().unwrap()); }) } #[test] fn test_i64_f64() { Python::with_gil(|py| { let obj = 12.34f64.into_pyobject(py).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); // with no remainder let obj = 12f64.into_pyobject(py).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } } pyo3/src/conversions/std/time.rs0000644000175000017500000002727415105742312016545 0ustar bdrungbdrunguse crate::conversion::IntoPyObject; use crate::exceptions::{PyOverflowError, PyValueError}; #[cfg(Py_LIMITED_API)] use crate::intern; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; #[cfg(not(Py_LIMITED_API))] use crate::types::PyDeltaAccess; use crate::types::{PyDateTime, PyDelta, PyTzInfo}; use crate::{Borrowed, Bound, FromPyObject, Py, PyAny, PyErr, PyResult, Python}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; const SECONDS_PER_DAY: u64 = 24 * 60 * 60; impl FromPyObject<'_> for Duration { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let delta = obj.downcast::()?; #[cfg(not(Py_LIMITED_API))] let (days, seconds, microseconds) = { ( delta.get_days(), delta.get_seconds(), delta.get_microseconds(), ) }; #[cfg(Py_LIMITED_API)] let (days, seconds, microseconds): (i32, i32, i32) = { let py = delta.py(); ( delta.getattr(intern!(py, "days"))?.extract()?, delta.getattr(intern!(py, "seconds"))?.extract()?, delta.getattr(intern!(py, "microseconds"))?.extract()?, ) }; // We cast let days = u64::try_from(days).map_err(|_| { PyValueError::new_err( "It is not possible to convert a negative timedelta to a Rust Duration", ) })?; let seconds = u64::try_from(seconds).unwrap(); // 0 <= seconds < 3600*24 let microseconds = u32::try_from(microseconds).unwrap(); // 0 <= microseconds < 1000000 // We convert let total_seconds = days * SECONDS_PER_DAY + seconds; // We casted from i32, this can't overflow let nanoseconds = microseconds.checked_mul(1_000).unwrap(); // 0 <= microseconds < 1000000 Ok(Duration::new(total_seconds, nanoseconds)) } } impl<'py> IntoPyObject<'py> for Duration { type Target = PyDelta; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let days = self.as_secs() / SECONDS_PER_DAY; let seconds = self.as_secs() % SECONDS_PER_DAY; let microseconds = self.subsec_micros(); PyDelta::new( py, days.try_into()?, seconds.try_into()?, microseconds.try_into()?, false, ) } } impl<'py> IntoPyObject<'py> for &Duration { type Target = PyDelta; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } // Conversions between SystemTime and datetime do not rely on the floating point timestamp of the // timestamp/fromtimestamp APIs to avoid possible precision loss but goes through the // timedelta/std::time::Duration types by taking for reference point the UNIX epoch. // // TODO: it might be nice to investigate using timestamps anyway, at least when the datetime is a safe range. impl FromPyObject<'_> for SystemTime { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let duration_since_unix_epoch: Duration = obj.sub(unix_epoch_py(obj.py())?)?.extract()?; UNIX_EPOCH .checked_add(duration_since_unix_epoch) .ok_or_else(|| { PyOverflowError::new_err("Overflow error when converting the time to Rust") }) } } impl<'py> IntoPyObject<'py> for SystemTime { type Target = PyDateTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let duration_since_unix_epoch = self.duration_since(UNIX_EPOCH).unwrap().into_pyobject(py)?; unix_epoch_py(py)? .add(duration_since_unix_epoch)? .downcast_into() .map_err(Into::into) } } impl<'py> IntoPyObject<'py> for &SystemTime { type Target = PyDateTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } fn unix_epoch_py(py: Python<'_>) -> PyResult> { static UNIX_EPOCH: GILOnceCell> = GILOnceCell::new(); Ok(UNIX_EPOCH .get_or_try_init(py, || { let utc = PyTzInfo::utc(py)?; Ok::<_, PyErr>(PyDateTime::new(py, 1970, 1, 1, 0, 0, 0, 0, Some(&utc))?.into()) })? .bind_borrowed(py)) } #[cfg(test)] mod tests { use super::*; use crate::types::PyDict; #[test] fn test_duration_frompyobject() { Python::with_gil(|py| { assert_eq!( new_timedelta(py, 0, 0, 0).extract::().unwrap(), Duration::new(0, 0) ); assert_eq!( new_timedelta(py, 1, 0, 0).extract::().unwrap(), Duration::new(86400, 0) ); assert_eq!( new_timedelta(py, 0, 1, 0).extract::().unwrap(), Duration::new(1, 0) ); assert_eq!( new_timedelta(py, 0, 0, 1).extract::().unwrap(), Duration::new(0, 1_000) ); assert_eq!( new_timedelta(py, 1, 1, 1).extract::().unwrap(), Duration::new(86401, 1_000) ); assert_eq!( timedelta_class(py) .getattr("max") .unwrap() .extract::() .unwrap(), Duration::new(86399999999999, 999999000) ); }); } #[test] fn test_duration_frompyobject_negative() { Python::with_gil(|py| { assert_eq!( new_timedelta(py, 0, -1, 0) .extract::() .unwrap_err() .to_string(), "ValueError: It is not possible to convert a negative timedelta to a Rust Duration" ); }) } #[test] fn test_duration_into_pyobject() { Python::with_gil(|py| { let assert_eq = |l: Bound<'_, PyAny>, r: Bound<'_, PyAny>| { assert!(l.eq(r).unwrap()); }; assert_eq( Duration::new(0, 0).into_pyobject(py).unwrap().into_any(), new_timedelta(py, 0, 0, 0), ); assert_eq( Duration::new(86400, 0) .into_pyobject(py) .unwrap() .into_any(), new_timedelta(py, 1, 0, 0), ); assert_eq( Duration::new(1, 0).into_pyobject(py).unwrap().into_any(), new_timedelta(py, 0, 1, 0), ); assert_eq( Duration::new(0, 1_000) .into_pyobject(py) .unwrap() .into_any(), new_timedelta(py, 0, 0, 1), ); assert_eq( Duration::new(0, 1).into_pyobject(py).unwrap().into_any(), new_timedelta(py, 0, 0, 0), ); assert_eq( Duration::new(86401, 1_000) .into_pyobject(py) .unwrap() .into_any(), new_timedelta(py, 1, 1, 1), ); assert_eq( Duration::new(86399999999999, 999999000) .into_pyobject(py) .unwrap() .into_any(), timedelta_class(py).getattr("max").unwrap(), ); }); } #[test] fn test_duration_into_pyobject_overflow() { Python::with_gil(|py| { assert!(Duration::MAX.into_pyobject(py).is_err()); }) } #[test] fn test_time_frompyobject() { Python::with_gil(|py| { assert_eq!( new_datetime(py, 1970, 1, 1, 0, 0, 0, 0) .extract::() .unwrap(), UNIX_EPOCH ); assert_eq!( new_datetime(py, 2020, 2, 3, 4, 5, 6, 7) .extract::() .unwrap(), UNIX_EPOCH .checked_add(Duration::new(1580702706, 7000)) .unwrap() ); assert_eq!( max_datetime(py).extract::().unwrap(), UNIX_EPOCH .checked_add(Duration::new(253402300799, 999999000)) .unwrap() ); }); } #[test] fn test_time_frompyobject_before_epoch() { Python::with_gil(|py| { assert_eq!( new_datetime(py, 1950, 1, 1, 0, 0, 0, 0) .extract::() .unwrap_err() .to_string(), "ValueError: It is not possible to convert a negative timedelta to a Rust Duration" ); }) } #[test] fn test_time_intopyobject() { Python::with_gil(|py| { let assert_eq = |l: Bound<'_, PyDateTime>, r: Bound<'_, PyDateTime>| { assert!(l.eq(r).unwrap()); }; assert_eq( UNIX_EPOCH .checked_add(Duration::new(1580702706, 7123)) .unwrap() .into_pyobject(py) .unwrap(), new_datetime(py, 2020, 2, 3, 4, 5, 6, 7), ); assert_eq( UNIX_EPOCH .checked_add(Duration::new(253402300799, 999999000)) .unwrap() .into_pyobject(py) .unwrap(), max_datetime(py), ); }); } #[allow(clippy::too_many_arguments)] fn new_datetime( py: Python<'_>, year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8, microsecond: u32, ) -> Bound<'_, PyDateTime> { let utc = PyTzInfo::utc(py).unwrap(); PyDateTime::new( py, year, month, day, hour, minute, second, microsecond, Some(&utc), ) .unwrap() } fn max_datetime(py: Python<'_>) -> Bound<'_, PyDateTime> { let naive_max = datetime_class(py).getattr("max").unwrap(); let kargs = PyDict::new(py); kargs .set_item("tzinfo", PyTzInfo::utc(py).unwrap()) .unwrap(); naive_max .call_method("replace", (), Some(&kargs)) .unwrap() .downcast_into() .unwrap() } #[test] fn test_time_intopyobject_overflow() { let big_system_time = UNIX_EPOCH .checked_add(Duration::new(300000000000, 0)) .unwrap(); Python::with_gil(|py| { assert!(big_system_time.into_pyobject(py).is_err()); }) } fn new_timedelta( py: Python<'_>, days: i32, seconds: i32, microseconds: i32, ) -> Bound<'_, PyAny> { timedelta_class(py) .call1((days, seconds, microseconds)) .unwrap() } fn datetime_class(py: Python<'_>) -> Bound<'_, PyAny> { py.import("datetime").unwrap().getattr("datetime").unwrap() } fn timedelta_class(py: Python<'_>) -> Bound<'_, PyAny> { py.import("datetime").unwrap().getattr("timedelta").unwrap() } } pyo3/src/conversions/std/vec.rs0000644000175000017500000000537515105742312016362 0ustar bdrungbdrunguse crate::conversion::IntoPyObject; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{Bound, PyAny, PyErr, Python}; impl<'py, T> IntoPyObject<'py> for Vec where T: IntoPyObject<'py>, { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; /// Turns [`Vec`] into [`PyBytes`], all other `T`s will be turned into a [`PyList`] /// /// [`PyBytes`]: crate::types::PyBytes /// [`PyList`]: crate::types::PyList #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { T::owned_sequence_into_pyobject(self, py, crate::conversion::private::Token) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::list_of(T::type_output()) } } impl<'a, 'py, T> IntoPyObject<'py> for &'a Vec where &'a T: IntoPyObject<'py>, T: 'a, // MSRV { type Target = PyAny; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { // NB: we could actually not cast to `PyAny`, which would be nice for // `&Vec`, but that'd be inconsistent with the `IntoPyObject` impl // above which always returns a `PyAny` for `Vec`. self.as_slice().into_pyobject(py).map(Bound::into_any) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::list_of(<&T>::type_output()) } } #[cfg(test)] mod tests { use crate::conversion::IntoPyObject; use crate::types::{PyAnyMethods, PyBytes, PyBytesMethods, PyList}; use crate::Python; #[test] fn test_vec_intopyobject_impl() { Python::with_gil(|py| { let bytes: Vec = b"foobar".to_vec(); let obj = bytes.clone().into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); let obj = obj.downcast_into::().unwrap(); assert_eq!(obj.as_bytes(), &bytes); let nums: Vec = vec![0, 1, 2, 3]; let obj = nums.into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); }); } #[test] fn test_vec_reference_intopyobject_impl() { Python::with_gil(|py| { let bytes: Vec = b"foobar".to_vec(); let obj = (&bytes).into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); let obj = obj.downcast_into::().unwrap(); assert_eq!(obj.as_bytes(), &bytes); let nums: Vec = vec![0, 1, 2, 3]; let obj = (&nums).into_pyobject(py).unwrap(); assert!(obj.is_instance_of::()); }); } } pyo3/src/conversions/eyre.rs0000644000175000017500000001554315105742312015755 0ustar bdrungbdrung#![cfg(feature = "eyre")] //! A conversion from //! [eyre](https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications.")’s //! [`Report`] type to [`PyErr`]. //! //! Use of an error handling library like [eyre] is common in application code and when you just //! want error handling to be easy. If you are writing a library or you need more control over your //! errors you might want to design your own error type instead. //! //! When the inner error is a [`PyErr`] without source, it will be extracted out. //! Otherwise a Python [`RuntimeError`] will be created. //! You might find that you need to map the error from your Rust code into another Python exception. //! See [`PyErr::new`] for more information about that. //! //! For information about error handling in general, see the [Error handling] chapter of the Rust //! book. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! ## change * to the version you want to use, ideally the latest. //! eyre = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"eyre\"] }")] //! ``` //! //! Note that you must use compatible versions of eyre and PyO3. //! The required eyre version may vary based on the version of PyO3. //! //! # Example: Propagating a `PyErr` into [`eyre::Report`] //! //! ```rust //! use pyo3::prelude::*; //! use std::path::PathBuf; //! //! // A wrapper around a Rust function. //! // The pyfunction macro performs the conversion to a PyErr //! #[pyfunction] //! fn py_open(filename: PathBuf) -> eyre::Result> { //! let data = std::fs::read(filename)?; //! Ok(data) //! } //! //! fn main() { //! let error = Python::with_gil(|py| -> PyResult> { //! let fun = wrap_pyfunction!(py_open, py)?; //! let text = fun.call1(("foo.txt",))?.extract::>()?; //! Ok(text) //! }).unwrap_err(); //! //! println!("{}", error); //! } //! ``` //! //! # Example: Using `eyre` in general //! //! Note that you don't need this feature to convert a [`PyErr`] into an [`eyre::Report`], because //! it can already convert anything that implements [`Error`](std::error::Error): //! //! ```rust //! use pyo3::prelude::*; //! use pyo3::types::PyBytes; //! //! // An example function that must handle multiple error types. //! // //! // To do this you usually need to design your own error type or use //! // `Box`. `eyre` is a convenient alternative for this. //! pub fn decompress(bytes: &[u8]) -> eyre::Result { //! // An arbitrary example of a Python api you //! // could call inside an application... //! // This might return a `PyErr`. //! let res = Python::with_gil(|py| { //! let zlib = PyModule::import(py, "zlib")?; //! let decompress = zlib.getattr("decompress")?; //! let bytes = PyBytes::new(py, bytes); //! let value = decompress.call1((bytes,))?; //! value.extract::>() //! })?; //! //! // This might be a `FromUtf8Error`. //! let text = String::from_utf8(res)?; //! //! Ok(text) //! } //! //! fn main() -> eyre::Result<()> { //! let bytes: &[u8] = b"x\x9c\x8b\xcc/U(\xce\xc8/\xcdIQ((\xcaOJL\xca\xa9T\ //! (-NU(\xc9HU\xc8\xc9LJ\xcbI,IUH.\x02\x91\x99y\xc5%\ //! \xa9\x89)z\x00\xf2\x15\x12\xfe"; //! let text = decompress(bytes)?; //! //! println!("The text is \"{}\"", text); //! # assert_eq!(text, "You should probably use the libflate crate instead."); //! Ok(()) //! } //! ``` //! //! [eyre]: https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications." //! [`RuntimeError`]: https://docs.python.org/3/library/exceptions.html#RuntimeError "Built-in Exceptions — Python documentation" //! [Error handling]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html "Recoverable Errors with Result - The Rust Programming Language" use crate::exceptions::PyRuntimeError; use crate::PyErr; use eyre::Report; /// Converts [`eyre::Report`] to a [`PyErr`] containing a [`PyRuntimeError`]. /// /// If you want to raise a different Python exception you will have to do so manually. See /// [`PyErr::new`] for more information about that. impl From for PyErr { fn from(mut error: Report) -> Self { // Errors containing a PyErr without chain or context are returned as the underlying error if error.source().is_none() { error = match error.downcast::() { Ok(py_err) => return py_err, Err(error) => error, }; } PyRuntimeError::new_err(format!("{error:?}")) } } #[cfg(test)] mod tests { use crate::exceptions::{PyRuntimeError, PyValueError}; use crate::types::IntoPyDict; use crate::{ffi, prelude::*}; use eyre::{bail, eyre, Report, Result, WrapErr}; fn f() -> Result<()> { use std::io; bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!")); } fn g() -> Result<()> { f().wrap_err("f failed") } fn h() -> Result<()> { g().wrap_err("g failed") } #[test] fn test_pyo3_exception_contents() { let err = h().unwrap_err(); let expected_contents = format!("{err:?}"); let pyerr = PyErr::from(err); Python::with_gil(|py| { let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } fn k() -> Result<()> { Err(eyre!("Some sort of error")) } #[test] fn test_pyo3_exception_contents2() { let err = k().unwrap_err(); let expected_contents = format!("{err:?}"); let pyerr = PyErr::from(err); Python::with_gil(|py| { let locals = [("err", pyerr)].into_py_dict(py).unwrap(); let pyerr = py .run(ffi::c_str!("raise err"), None, Some(&locals)) .unwrap_err(); assert_eq!(pyerr.value(py).to_string(), expected_contents); }) } #[test] fn test_pyo3_unwrap_simple_err() { let origin_exc = PyValueError::new_err("Value Error"); let report: Report = origin_exc.into(); let converted: PyErr = report.into(); assert!(Python::with_gil( |py| converted.is_instance_of::(py) )) } #[test] fn test_pyo3_unwrap_complex_err() { let origin_exc = PyValueError::new_err("Value Error"); let mut report: Report = origin_exc.into(); report = report.wrap_err("Wrapped"); let converted: PyErr = report.into(); assert!(Python::with_gil( |py| converted.is_instance_of::(py) )) } } pyo3/src/conversions/hashbrown.rs0000644000175000017500000001335415105742312017002 0ustar bdrungbdrung#![cfg(feature = "hashbrown")] //! Conversions to and from [hashbrown](https://docs.rs/hashbrown/)’s //! `HashMap` and `HashSet`. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! hashbrown = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"hashbrown\"] }")] //! ``` //! //! Note that you must use compatible versions of hashbrown and PyO3. //! The required hashbrown version may vary based on the version of PyO3. use crate::{ conversion::IntoPyObject, types::{ any::PyAnyMethods, dict::PyDictMethods, frozenset::PyFrozenSetMethods, set::{try_new_from_iter, PySetMethods}, PyDict, PyFrozenSet, PySet, }, Bound, FromPyObject, PyAny, PyErr, PyResult, Python, }; use std::{cmp, hash}; impl<'py, K, V, H> IntoPyObject<'py> for hashbrown::HashMap where K: IntoPyObject<'py> + cmp::Eq + hash::Hash, V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } } impl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a hashbrown::HashMap where &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash, &'a V: IntoPyObject<'py>, H: hash::BuildHasher, { type Target = PyDict; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let dict = PyDict::new(py); for (k, v) in self { dict.set_item(k, v)?; } Ok(dict) } } impl<'py, K, V, S> FromPyObject<'py> for hashbrown::HashMap where K: FromPyObject<'py> + cmp::Eq + hash::Hash, V: FromPyObject<'py>, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> Result { let dict = ob.downcast::()?; let mut ret = hashbrown::HashMap::with_capacity_and_hasher(dict.len(), S::default()); for (k, v) in dict { ret.insert(k.extract()?, v.extract()?); } Ok(ret) } } impl<'py, K, H> IntoPyObject<'py> for hashbrown::HashSet where K: IntoPyObject<'py> + cmp::Eq + hash::Hash, H: hash::BuildHasher, { type Target = PySet; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self) } } impl<'a, 'py, K, H> IntoPyObject<'py> for &'a hashbrown::HashSet where &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash, H: hash::BuildHasher, { type Target = PySet; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self) } } impl<'py, K, S> FromPyObject<'py> for hashbrown::HashSet where K: FromPyObject<'py> + cmp::Eq + hash::Hash, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { match ob.downcast::() { Ok(set) => set.iter().map(|any| any.extract()).collect(), Err(err) => { if let Ok(frozen_set) = ob.downcast::() { frozen_set.iter().map(|any| any.extract()).collect() } else { Err(PyErr::from(err)) } } } } } #[cfg(test)] mod tests { use super::*; use crate::types::IntoPyDict; #[test] fn test_hashbrown_hashmap_into_pyobject() { Python::with_gil(|py| { let mut map = hashbrown::HashMap::::new(); map.insert(1, 1); let py_map = (&map).into_pyobject(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!(map, py_map.extract().unwrap()); }); } #[test] fn test_hashbrown_hashmap_into_dict() { Python::with_gil(|py| { let mut map = hashbrown::HashMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_extract_hashbrown_hashset() { Python::with_gil(|py| { let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap(); let hash_set: hashbrown::HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); let set = PyFrozenSet::new(py, [1, 2, 3, 4, 5]).unwrap(); let hash_set: hashbrown::HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); }); } #[test] fn test_hashbrown_hashset_into_pyobject() { Python::with_gil(|py| { let hs: hashbrown::HashSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let hso = hs.clone().into_pyobject(py).unwrap(); assert_eq!(hs, hso.extract().unwrap()); }); } } pyo3/src/conversions/time.rs0000644000175000017500000015527215105742312015753 0ustar bdrungbdrung#![cfg(feature = "time")] //! Conversions to and from [time](https://docs.rs/time/)’s `Date`, //! `Duration`, `OffsetDateTime`, `PrimitiveDateTime`, `Time`, `UtcDateTime` and `UtcOffset`. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! time = "0.3" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"time\"] }")] //! ``` //! //! Note that you must use compatible versions of time and PyO3. //! The required time version may vary based on the version of PyO3. //! //! ```rust //! use time::{Duration, OffsetDateTime, PrimitiveDateTime, Date, Time, Month}; //! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods}; //! //! fn main() -> PyResult<()> { //! pyo3::prepare_freethreaded_python(); //! Python::with_gil(|py| { //! // Create a fixed date and time (2022-01-01 12:00:00 UTC) //! let date = Date::from_calendar_date(2022, Month::January, 1).unwrap(); //! let time = Time::from_hms(12, 0, 0).unwrap(); //! let primitive_dt = PrimitiveDateTime::new(date, time); //! //! // Convert to OffsetDateTime with UTC offset //! let datetime = primitive_dt.assume_utc(); //! //! // Create a duration of 1 hour //! let duration = Duration::hours(1); //! //! // Convert to Python objects //! let py_datetime = datetime.into_pyobject(py)?; //! let py_timedelta = duration.into_pyobject(py)?; //! //! // Add the duration to the datetime in Python //! let py_result = py_datetime.add(py_timedelta)?; //! //! // Convert the result back to Rust //! let result: OffsetDateTime = py_result.extract()?; //! assert_eq!(result.hour(), 13); //! //! Ok(()) //! }) //! } //! ``` use crate::exceptions::{PyTypeError, PyValueError}; #[cfg(Py_LIMITED_API)] use crate::intern; #[cfg(not(Py_LIMITED_API))] use crate::types::datetime::{PyDateAccess, PyDeltaAccess}; use crate::types::{PyAnyMethods, PyDate, PyDateTime, PyDelta, PyNone, PyTime, PyTzInfo}; #[cfg(not(Py_LIMITED_API))] use crate::types::{PyTimeAccess, PyTzInfoAccess}; use crate::{Bound, FromPyObject, IntoPyObject, PyAny, PyErr, PyResult, Python}; use time::{ Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset, }; const SECONDS_PER_DAY: i64 = 86_400; // Macro for reference implementation macro_rules! impl_into_py_for_ref { ($type:ty, $target:ty) => { impl<'py> IntoPyObject<'py> for &$type { type Target = $target; type Output = Bound<'py, Self::Target>; type Error = PyErr; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } } }; } // Macro for month conversion macro_rules! month_from_number { ($month:expr) => { match $month { 1 => Month::January, 2 => Month::February, 3 => Month::March, 4 => Month::April, 5 => Month::May, 6 => Month::June, 7 => Month::July, 8 => Month::August, 9 => Month::September, 10 => Month::October, 11 => Month::November, 12 => Month::December, _ => return Err(PyValueError::new_err("invalid month value")), } }; } fn extract_date_time(dt: &Bound<'_, PyAny>) -> PyResult<(Date, Time)> { #[cfg(not(Py_LIMITED_API))] { let dt = dt.downcast::()?; let date = Date::from_calendar_date( dt.get_year(), month_from_number!(dt.get_month()), dt.get_day(), ) .map_err(|_| PyValueError::new_err("invalid or out-of-range date"))?; let time = Time::from_hms_micro( dt.get_hour(), dt.get_minute(), dt.get_second(), dt.get_microsecond(), ) .map_err(|_| PyValueError::new_err("invalid or out-of-range time"))?; Ok((date, time)) } #[cfg(Py_LIMITED_API)] { let date = Date::from_calendar_date( dt.getattr(intern!(dt.py(), "year"))?.extract()?, month_from_number!(dt.getattr(intern!(dt.py(), "month"))?.extract::()?), dt.getattr(intern!(dt.py(), "day"))?.extract()?, ) .map_err(|_| PyValueError::new_err("invalid or out-of-range date"))?; let time = Time::from_hms_micro( dt.getattr(intern!(dt.py(), "hour"))?.extract()?, dt.getattr(intern!(dt.py(), "minute"))?.extract()?, dt.getattr(intern!(dt.py(), "second"))?.extract()?, dt.getattr(intern!(dt.py(), "microsecond"))?.extract()?, ) .map_err(|_| PyValueError::new_err("invalid or out-of-range time"))?; Ok((date, time)) } } impl<'py> IntoPyObject<'py> for Duration { type Target = PyDelta; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let total_seconds = self.whole_seconds(); let micro_seconds = self.subsec_microseconds(); // For negative durations, Python expects days to be negative and // seconds/microseconds to be positive or zero let (days, seconds) = if total_seconds < 0 && total_seconds % SECONDS_PER_DAY != 0 { // For negative values, we need to round down (toward more negative) // e.g., -10 seconds should be -1 days + 86390 seconds let days = total_seconds.div_euclid(SECONDS_PER_DAY); let seconds = total_seconds.rem_euclid(SECONDS_PER_DAY); (days, seconds) } else { // For positive or exact negative days, use normal division ( total_seconds / SECONDS_PER_DAY, total_seconds % SECONDS_PER_DAY, ) }; // Create the timedelta with days, seconds, microseconds // Safe to unwrap as we've verified the values are within bounds PyDelta::new( py, days.try_into().expect("days overflow"), seconds.try_into().expect("seconds overflow"), micro_seconds, true, ) } } impl FromPyObject<'_> for Duration { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { #[cfg(not(Py_LIMITED_API))] let (days, seconds, microseconds) = { let delta = ob.downcast::()?; ( delta.get_days().into(), delta.get_seconds().into(), delta.get_microseconds().into(), ) }; #[cfg(Py_LIMITED_API)] let (days, seconds, microseconds) = { ( ob.getattr(intern!(ob.py(), "days"))?.extract()?, ob.getattr(intern!(ob.py(), "seconds"))?.extract()?, ob.getattr(intern!(ob.py(), "microseconds"))?.extract()?, ) }; Ok( Duration::days(days) + Duration::seconds(seconds) + Duration::microseconds(microseconds), ) } } impl<'py> IntoPyObject<'py> for Date { type Target = PyDate; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let year = self.year(); let month = self.month() as u8; let day = self.day(); PyDate::new(py, year, month, day) } } impl FromPyObject<'_> for Date { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { let (year, month, day) = { #[cfg(not(Py_LIMITED_API))] { let date = ob.downcast::()?; (date.get_year(), date.get_month(), date.get_day()) } #[cfg(Py_LIMITED_API)] { let year = ob.getattr(intern!(ob.py(), "year"))?.extract()?; let month: u8 = ob.getattr(intern!(ob.py(), "month"))?.extract()?; let day = ob.getattr(intern!(ob.py(), "day"))?.extract()?; (year, month, day) } }; // Convert the month number to time::Month enum let month = month_from_number!(month); Date::from_calendar_date(year, month, day) .map_err(|_| PyValueError::new_err("invalid or out-of-range date")) } } impl<'py> IntoPyObject<'py> for Time { type Target = PyTime; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { let hour = self.hour(); let minute = self.minute(); let second = self.second(); let microsecond = self.microsecond(); PyTime::new(py, hour, minute, second, microsecond, None) } } impl FromPyObject<'_> for Time { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult

(&mut self, mut predicate: P) -> Option where Self: Sized, P: FnMut(Self::Item) -> bool, { self.inner.with_critical_section(&self.dict, |inner| { let mut acc = 0; while let Some(x) = unsafe { inner.next_unchecked(&self.dict) } { if predicate(x) { return Some(acc); } acc += 1; } None }) } } impl ExactSizeIterator for BoundDictIterator<'_> { fn len(&self) -> usize { match self.inner { DictIterImpl::DictIter { remaining, .. } => remaining as usize, } } } impl<'py> BoundDictIterator<'py> { fn new(dict: Bound<'py, PyDict>) -> Self { let remaining = dict_len(&dict); Self { dict, inner: DictIterImpl::DictIter { ppos: 0, di_used: remaining, remaining, }, } } } impl<'py> IntoIterator for Bound<'py, PyDict> { type Item = (Bound<'py, PyAny>, Bound<'py, PyAny>); type IntoIter = BoundDictIterator<'py>; fn into_iter(self) -> Self::IntoIter { BoundDictIterator::new(self) } } impl<'py> IntoIterator for &Bound<'py, PyDict> { type Item = (Bound<'py, PyAny>, Bound<'py, PyAny>); type IntoIter = BoundDictIterator<'py>; fn into_iter(self) -> Self::IntoIter { self.iter() } } mod borrowed_iter { use super::*; /// Variant of the above which is used to iterate the items of the dictionary /// without incrementing reference counts. This is only safe if it's known /// that the dictionary will not be modified during iteration. pub struct BorrowedDictIter<'a, 'py> { dict: Borrowed<'a, 'py, PyDict>, ppos: ffi::Py_ssize_t, len: ffi::Py_ssize_t, } impl<'a, 'py> Iterator for BorrowedDictIter<'a, 'py> { type Item = (Borrowed<'a, 'py, PyAny>, Borrowed<'a, 'py, PyAny>); #[inline] fn next(&mut self) -> Option { let mut key: *mut ffi::PyObject = std::ptr::null_mut(); let mut value: *mut ffi::PyObject = std::ptr::null_mut(); // Safety: self.dict lives sufficiently long that the pointer is not dangling if unsafe { ffi::PyDict_Next(self.dict.as_ptr(), &mut self.ppos, &mut key, &mut value) } != 0 { let py = self.dict.py(); self.len -= 1; // Safety: // - PyDict_Next returns borrowed values // - we have already checked that `PyDict_Next` succeeded, so we can assume these to be non-null Some(unsafe { (key.assume_borrowed(py), value.assume_borrowed(py)) }) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } #[inline] fn count(self) -> usize where Self: Sized, { self.len() } } impl ExactSizeIterator for BorrowedDictIter<'_, '_> { fn len(&self) -> usize { self.len as usize } } impl<'a, 'py> BorrowedDictIter<'a, 'py> { pub(super) fn new(dict: Borrowed<'a, 'py, PyDict>) -> Self { let len = dict_len(&dict); BorrowedDictIter { dict, ppos: 0, len } } } } pub(crate) use borrowed_iter::BorrowedDictIter; /// Conversion trait that allows a sequence of tuples to be converted into `PyDict` /// Primary use case for this trait is `call` and `call_method` methods as keywords argument. pub trait IntoPyDict<'py>: Sized { /// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed /// depends on implementation. fn into_py_dict(self, py: Python<'py>) -> PyResult>; } impl<'py, T, I> IntoPyDict<'py> for I where T: PyDictItem<'py>, I: IntoIterator, { fn into_py_dict(self, py: Python<'py>) -> PyResult> { let dict = PyDict::new(py); self.into_iter().try_for_each(|item| { let (key, value) = item.unpack(); dict.set_item(key, value) })?; Ok(dict) } } /// Represents a tuple which can be used as a PyDict item. trait PyDictItem<'py> { type K: IntoPyObject<'py>; type V: IntoPyObject<'py>; fn unpack(self) -> (Self::K, Self::V); } impl<'py, K, V> PyDictItem<'py> for (K, V) where K: IntoPyObject<'py>, V: IntoPyObject<'py>, { type K = K; type V = V; fn unpack(self) -> (Self::K, Self::V) { (self.0, self.1) } } impl<'a, 'py, K, V> PyDictItem<'py> for &'a (K, V) where &'a K: IntoPyObject<'py>, &'a V: IntoPyObject<'py>, { type K = &'a K; type V = &'a V; fn unpack(self) -> (Self::K, Self::V) { (&self.0, &self.1) } } #[cfg(test)] mod tests { use super::*; use crate::types::PyTuple; use std::collections::{BTreeMap, HashMap}; #[test] fn test_new() { Python::with_gil(|py| { let dict = [(7, 32)].into_py_dict(py).unwrap(); assert_eq!( 32, dict.get_item(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert!(dict.get_item(8i32).unwrap().is_none()); let map: HashMap = [(7, 32)].iter().cloned().collect(); assert_eq!(map, dict.extract().unwrap()); let map: BTreeMap = [(7, 32)].iter().cloned().collect(); assert_eq!(map, dict.extract().unwrap()); }); } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn test_from_sequence() { Python::with_gil(|py| { let items = PyList::new(py, vec![("a", 1), ("b", 2)]).unwrap(); let dict = PyDict::from_sequence(&items).unwrap(); assert_eq!( 1, dict.get_item("a") .unwrap() .unwrap() .extract::() .unwrap() ); assert_eq!( 2, dict.get_item("b") .unwrap() .unwrap() .extract::() .unwrap() ); let map: HashMap = [("a".into(), 1), ("b".into(), 2)].into_iter().collect(); assert_eq!(map, dict.extract().unwrap()); let map: BTreeMap = [("a".into(), 1), ("b".into(), 2)].into_iter().collect(); assert_eq!(map, dict.extract().unwrap()); }); } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn test_from_sequence_err() { Python::with_gil(|py| { let items = PyList::new(py, vec!["a", "b"]).unwrap(); assert!(PyDict::from_sequence(&items).is_err()); }); } #[test] fn test_copy() { Python::with_gil(|py| { let dict = [(7, 32)].into_py_dict(py).unwrap(); let ndict = dict.copy().unwrap(); assert_eq!( 32, ndict .get_item(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert!(ndict.get_item(8i32).unwrap().is_none()); }); } #[test] fn test_len() { Python::with_gil(|py| { let mut v = HashMap::::new(); let dict = (&v).into_pyobject(py).unwrap(); assert_eq!(0, dict.len()); v.insert(7, 32); let dict2 = v.into_pyobject(py).unwrap(); assert_eq!(1, dict2.len()); }); } #[test] fn test_contains() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let dict = v.into_pyobject(py).unwrap(); assert!(dict.contains(7i32).unwrap()); assert!(!dict.contains(8i32).unwrap()); }); } #[test] fn test_get_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let dict = v.into_pyobject(py).unwrap(); assert_eq!( 32, dict.get_item(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert!(dict.get_item(8i32).unwrap().is_none()); }); } #[cfg(feature = "macros")] #[test] fn test_get_item_error_path() { use crate::exceptions::PyTypeError; #[crate::pyclass(crate = "crate")] struct HashErrors; #[crate::pymethods(crate = "crate")] impl HashErrors { #[new] fn new() -> Self { HashErrors {} } fn __hash__(&self) -> PyResult { Err(PyTypeError::new_err("Error from __hash__")) } } Python::with_gil(|py| { let class = py.get_type::(); let instance = class.call0().unwrap(); let d = PyDict::new(py); match d.get_item(instance) { Ok(_) => { panic!("this get_item call should always error") } Err(err) => { assert!(err.is_instance_of::(py)); assert!(err.value(py).to_string().contains("Error from __hash__")); } } }) } #[test] fn test_set_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let dict = v.into_pyobject(py).unwrap(); assert!(dict.set_item(7i32, 42i32).is_ok()); // change assert!(dict.set_item(8i32, 123i32).is_ok()); // insert assert_eq!( 42i32, dict.get_item(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert_eq!( 123i32, dict.get_item(8i32) .unwrap() .unwrap() .extract::() .unwrap() ); }); } #[test] fn test_set_item_refcnt() { Python::with_gil(|py| { let cnt; let obj = py.eval(ffi::c_str!("object()"), None, None).unwrap(); { cnt = obj.get_refcnt(); let _dict = [(10, &obj)].into_py_dict(py); } { assert_eq!(cnt, obj.get_refcnt()); } }); } #[test] fn test_set_item_does_not_update_original_object() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let dict = (&v).into_pyobject(py).unwrap(); assert!(dict.set_item(7i32, 42i32).is_ok()); // change assert!(dict.set_item(8i32, 123i32).is_ok()); // insert assert_eq!(32i32, v[&7i32]); // not updated! assert_eq!(None, v.get(&8i32)); }); } #[test] fn test_del_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let dict = v.into_pyobject(py).unwrap(); assert!(dict.del_item(7i32).is_ok()); assert_eq!(0, dict.len()); assert!(dict.get_item(7i32).unwrap().is_none()); }); } #[test] fn test_del_item_does_not_update_original_object() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let dict = (&v).into_pyobject(py).unwrap(); assert!(dict.del_item(7i32).is_ok()); // change assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated! }); } #[test] fn test_items() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_pyobject(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; let mut value_sum = 0; for el in dict.items() { let tuple = el.downcast::().unwrap(); key_sum += tuple.get_item(0).unwrap().extract::().unwrap(); value_sum += tuple.get_item(1).unwrap().extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_keys() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_pyobject(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; for el in dict.keys() { key_sum += el.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); }); } #[test] fn test_values() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_pyobject(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut values_sum = 0; for el in dict.values() { values_sum += el.extract::().unwrap(); } assert_eq!(32 + 42 + 123, values_sum); }); } #[test] fn test_iter() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_pyobject(py).unwrap(); let mut key_sum = 0; let mut value_sum = 0; for (key, value) in dict { key_sum += key.extract::().unwrap(); value_sum += value.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_iter_bound() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_pyobject(py).unwrap(); let mut key_sum = 0; let mut value_sum = 0; for (key, value) in dict { key_sum += key.extract::().unwrap(); value_sum += value.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_iter_value_mutated() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = (&v).into_pyobject(py).unwrap(); for (key, value) in &dict { dict.set_item(key, value.extract::().unwrap() + 7) .unwrap(); } }); } #[test] #[should_panic] fn test_iter_key_mutated() { Python::with_gil(|py| { let mut v = HashMap::new(); for i in 0..10 { v.insert(i * 2, i * 2); } let dict = v.into_pyobject(py).unwrap(); for (i, (key, value)) in dict.iter().enumerate() { let key = key.extract::().unwrap(); let value = value.extract::().unwrap(); dict.set_item(key + 1, value + 1).unwrap(); if i > 1000 { // avoid this test just running out of memory if it fails break; }; } }); } #[test] #[should_panic] fn test_iter_key_mutated_constant_len() { Python::with_gil(|py| { let mut v = HashMap::new(); for i in 0..10 { v.insert(i * 2, i * 2); } let dict = v.into_pyobject(py).unwrap(); for (i, (key, value)) in dict.iter().enumerate() { let key = key.extract::().unwrap(); let value = value.extract::().unwrap(); dict.del_item(key).unwrap(); dict.set_item(key + 1, value + 1).unwrap(); if i > 1000 { // avoid this test just running out of memory if it fails break; }; } }); } #[test] fn test_iter_size_hint() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = (&v).into_pyobject(py).unwrap(); let mut iter = dict.iter(); assert_eq!(iter.size_hint(), (v.len(), Some(v.len()))); iter.next(); assert_eq!(iter.size_hint(), (v.len() - 1, Some(v.len() - 1))); // Exhaust iterator. for _ in &mut iter {} assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert_eq!(iter.size_hint(), (0, Some(0))); }); } #[test] fn test_into_iter() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_pyobject(py).unwrap(); let mut key_sum = 0; let mut value_sum = 0; for (key, value) in dict { key_sum += key.extract::().unwrap(); value_sum += value.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_hashmap_into_dict() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_btreemap_into_dict() { Python::with_gil(|py| { let mut map = BTreeMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_vec_into_dict() { Python::with_gil(|py| { let vec = vec![("a", 1), ("b", 2), ("c", 3)]; let py_map = vec.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 3); assert_eq!( py_map .get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); }); } #[test] fn test_slice_into_dict() { Python::with_gil(|py| { let arr = [("a", 1), ("b", 2), ("c", 3)]; let py_map = arr.into_py_dict(py).unwrap(); assert_eq!(py_map.len(), 3); assert_eq!( py_map .get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); }); } #[test] fn dict_as_mapping() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict(py).unwrap(); assert_eq!(py_map.as_mapping().len().unwrap(), 1); assert_eq!( py_map .as_mapping() .get_item(1) .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn dict_into_mapping() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict(py).unwrap(); let py_mapping = py_map.into_mapping(); assert_eq!(py_mapping.len().unwrap(), 1); assert_eq!(py_mapping.get_item(1).unwrap().extract::().unwrap(), 1); }); } #[cfg(not(any(PyPy, GraalPy)))] fn abc_dict(py: Python<'_>) -> Bound<'_, PyDict> { let mut map = HashMap::<&'static str, i32>::new(); map.insert("a", 1); map.insert("b", 2); map.insert("c", 3); map.into_py_dict(py).unwrap() } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn dict_keys_view() { Python::with_gil(|py| { let dict = abc_dict(py); let keys = dict.call_method0("keys").unwrap(); assert!(keys.is_instance(&py.get_type::()).unwrap()); }) } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn dict_values_view() { Python::with_gil(|py| { let dict = abc_dict(py); let values = dict.call_method0("values").unwrap(); assert!(values.is_instance(&py.get_type::()).unwrap()); }) } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn dict_items_view() { Python::with_gil(|py| { let dict = abc_dict(py); let items = dict.call_method0("items").unwrap(); assert!(items.is_instance(&py.get_type::()).unwrap()); }) } #[test] fn dict_update() { Python::with_gil(|py| { let dict = [("a", 1), ("b", 2), ("c", 3)].into_py_dict(py).unwrap(); let other = [("b", 4), ("c", 5), ("d", 6)].into_py_dict(py).unwrap(); dict.update(other.as_mapping()).unwrap(); assert_eq!(dict.len(), 4); assert_eq!( dict.get_item("a") .unwrap() .unwrap() .extract::() .unwrap(), 1 ); assert_eq!( dict.get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 4 ); assert_eq!( dict.get_item("c") .unwrap() .unwrap() .extract::() .unwrap(), 5 ); assert_eq!( dict.get_item("d") .unwrap() .unwrap() .extract::() .unwrap(), 6 ); assert_eq!(other.len(), 3); assert_eq!( other .get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 4 ); assert_eq!( other .get_item("c") .unwrap() .unwrap() .extract::() .unwrap(), 5 ); assert_eq!( other .get_item("d") .unwrap() .unwrap() .extract::() .unwrap(), 6 ); }) } #[test] fn dict_update_if_missing() { Python::with_gil(|py| { let dict = [("a", 1), ("b", 2), ("c", 3)].into_py_dict(py).unwrap(); let other = [("b", 4), ("c", 5), ("d", 6)].into_py_dict(py).unwrap(); dict.update_if_missing(other.as_mapping()).unwrap(); assert_eq!(dict.len(), 4); assert_eq!( dict.get_item("a") .unwrap() .unwrap() .extract::() .unwrap(), 1 ); assert_eq!( dict.get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); assert_eq!( dict.get_item("c") .unwrap() .unwrap() .extract::() .unwrap(), 3 ); assert_eq!( dict.get_item("d") .unwrap() .unwrap() .extract::() .unwrap(), 6 ); assert_eq!(other.len(), 3); assert_eq!( other .get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 4 ); assert_eq!( other .get_item("c") .unwrap() .unwrap() .extract::() .unwrap(), 5 ); assert_eq!( other .get_item("d") .unwrap() .unwrap() .extract::() .unwrap(), 6 ); }) } #[test] fn test_iter_all() { Python::with_gil(|py| { let dict = [(1, true), (2, true), (3, true)].into_py_dict(py).unwrap(); assert!(dict.iter().all(|(_, v)| v.extract::().unwrap())); let dict = [(1, true), (2, false), (3, true)].into_py_dict(py).unwrap(); assert!(!dict.iter().all(|(_, v)| v.extract::().unwrap())); }); } #[test] fn test_iter_any() { Python::with_gil(|py| { let dict = [(1, true), (2, false), (3, false)] .into_py_dict(py) .unwrap(); assert!(dict.iter().any(|(_, v)| v.extract::().unwrap())); let dict = [(1, false), (2, false), (3, false)] .into_py_dict(py) .unwrap(); assert!(!dict.iter().any(|(_, v)| v.extract::().unwrap())); }); } #[test] #[allow(clippy::search_is_some)] fn test_iter_find() { Python::with_gil(|py| { let dict = [(1, false), (2, true), (3, false)] .into_py_dict(py) .unwrap(); assert_eq!( Some((2, true)), dict.iter() .find(|(_, v)| v.extract::().unwrap()) .map(|(k, v)| (k.extract().unwrap(), v.extract().unwrap())) ); let dict = [(1, false), (2, false), (3, false)] .into_py_dict(py) .unwrap(); assert!(dict .iter() .find(|(_, v)| v.extract::().unwrap()) .is_none()); }); } #[test] #[allow(clippy::search_is_some)] fn test_iter_position() { Python::with_gil(|py| { let dict = [(1, false), (2, false), (3, true)] .into_py_dict(py) .unwrap(); assert_eq!( Some(2), dict.iter().position(|(_, v)| v.extract::().unwrap()) ); let dict = [(1, false), (2, false), (3, false)] .into_py_dict(py) .unwrap(); assert!(dict .iter() .position(|(_, v)| v.extract::().unwrap()) .is_none()); }); } #[test] fn test_iter_fold() { Python::with_gil(|py| { let dict = [(1, 1), (2, 2), (3, 3)].into_py_dict(py).unwrap(); let sum = dict .iter() .fold(0, |acc, (_, v)| acc + v.extract::().unwrap()); assert_eq!(sum, 6); }); } #[test] fn test_iter_try_fold() { Python::with_gil(|py| { let dict = [(1, 1), (2, 2), (3, 3)].into_py_dict(py).unwrap(); let sum = dict .iter() .try_fold(0, |acc, (_, v)| PyResult::Ok(acc + v.extract::()?)) .unwrap(); assert_eq!(sum, 6); let dict = [(1, "foo"), (2, "bar")].into_py_dict(py).unwrap(); assert!(dict .iter() .try_fold(0, |acc, (_, v)| PyResult::Ok(acc + v.extract::()?)) .is_err()); }); } #[test] fn test_iter_count() { Python::with_gil(|py| { let dict = [(1, 1), (2, 2), (3, 3)].into_py_dict(py).unwrap(); assert_eq!(dict.iter().count(), 3); }) } } pyo3/src/types/set.rs0000644000175000017500000003037515105742312014400 0ustar bdrungbdrunguse crate::types::PyIterator; use crate::{ err::{self, PyErr, PyResult}, ffi_ptr_ext::FfiPtrExt, instance::Bound, py_result_ext::PyResultExt, types::any::PyAnyMethods, }; use crate::{ffi, Borrowed, BoundObject, IntoPyObject, IntoPyObjectExt, PyAny, Python}; use std::ptr; /// Represents a Python `set`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PySet>`][Bound]. /// /// For APIs available on `set` objects, see the [`PySetMethods`] trait which is implemented for /// [`Bound<'py, PySet>`][Bound]. #[repr(transparent)] pub struct PySet(PyAny); #[cfg(not(any(PyPy, GraalPy)))] pyobject_subclassable_native_type!(PySet, crate::ffi::PySetObject); #[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type!( PySet, ffi::PySetObject, pyobject_native_static_type_object!(ffi::PySet_Type), #checkfunction=ffi::PySet_Check ); #[cfg(any(PyPy, GraalPy))] pyobject_native_type_core!( PySet, pyobject_native_static_type_object!(ffi::PySet_Type), #checkfunction=ffi::PySet_Check ); impl PySet { /// Creates a new set with elements from the given slice. /// /// Returns an error if some element is not hashable. #[inline] pub fn new<'py, T>( py: Python<'py>, elements: impl IntoIterator, ) -> PyResult> where T: IntoPyObject<'py>, { try_new_from_iter(py, elements) } /// Creates a new empty set. pub fn empty(py: Python<'_>) -> PyResult> { unsafe { ffi::PySet_New(ptr::null_mut()) .assume_owned_or_err(py) .downcast_into_unchecked() } } } /// Implementation of functionality for [`PySet`]. /// /// These methods are defined for the `Bound<'py, PySet>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PySet")] pub trait PySetMethods<'py>: crate::sealed::Sealed { /// Removes all elements from the set. fn clear(&self); /// Returns the number of items in the set. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> usize; /// Checks if set is empty. fn is_empty(&self) -> bool { self.len() == 0 } /// Determines if the set contains the specified key. /// /// This is equivalent to the Python expression `key in self`. fn contains(&self, key: K) -> PyResult where K: IntoPyObject<'py>; /// Removes the element from the set if it is present. /// /// Returns `true` if the element was present in the set. fn discard(&self, key: K) -> PyResult where K: IntoPyObject<'py>; /// Adds an element to the set. fn add(&self, key: K) -> PyResult<()> where K: IntoPyObject<'py>; /// Removes and returns an arbitrary element from the set. fn pop(&self) -> Option>; /// Returns an iterator of values in this set. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. fn iter(&self) -> BoundSetIterator<'py>; } impl<'py> PySetMethods<'py> for Bound<'py, PySet> { #[inline] fn clear(&self) { unsafe { ffi::PySet_Clear(self.as_ptr()); } } #[inline] fn len(&self) -> usize { unsafe { ffi::PySet_Size(self.as_ptr()) as usize } } fn contains(&self, key: K) -> PyResult where K: IntoPyObject<'py>, { fn inner(set: &Bound<'_, PySet>, key: Borrowed<'_, '_, PyAny>) -> PyResult { match unsafe { ffi::PySet_Contains(set.as_ptr(), key.as_ptr()) } { 1 => Ok(true), 0 => Ok(false), _ => Err(PyErr::fetch(set.py())), } } let py = self.py(); inner( self, key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn discard(&self, key: K) -> PyResult where K: IntoPyObject<'py>, { fn inner(set: &Bound<'_, PySet>, key: Borrowed<'_, '_, PyAny>) -> PyResult { match unsafe { ffi::PySet_Discard(set.as_ptr(), key.as_ptr()) } { 1 => Ok(true), 0 => Ok(false), _ => Err(PyErr::fetch(set.py())), } } let py = self.py(); inner( self, key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn add(&self, key: K) -> PyResult<()> where K: IntoPyObject<'py>, { fn inner(set: &Bound<'_, PySet>, key: Borrowed<'_, '_, PyAny>) -> PyResult<()> { err::error_on_minusone(set.py(), unsafe { ffi::PySet_Add(set.as_ptr(), key.as_ptr()) }) } let py = self.py(); inner( self, key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn pop(&self) -> Option> { let element = unsafe { ffi::PySet_Pop(self.as_ptr()).assume_owned_or_err(self.py()) }; element.ok() } fn iter(&self) -> BoundSetIterator<'py> { BoundSetIterator::new(self.clone()) } } impl<'py> IntoIterator for Bound<'py, PySet> { type Item = Bound<'py, PyAny>; type IntoIter = BoundSetIterator<'py>; /// Returns an iterator of values in this set. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. fn into_iter(self) -> Self::IntoIter { BoundSetIterator::new(self) } } impl<'py> IntoIterator for &Bound<'py, PySet> { type Item = Bound<'py, PyAny>; type IntoIter = BoundSetIterator<'py>; /// Returns an iterator of values in this set. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. fn into_iter(self) -> Self::IntoIter { self.iter() } } /// PyO3 implementation of an iterator for a Python `set` object. pub struct BoundSetIterator<'p> { it: Bound<'p, PyIterator>, // Remaining elements in the set. This is fine to store because // Python will error if the set changes size during iteration. remaining: usize, } impl<'py> BoundSetIterator<'py> { pub(super) fn new(set: Bound<'py, PySet>) -> Self { Self { it: PyIterator::from_object(&set).unwrap(), remaining: set.len(), } } } impl<'py> Iterator for BoundSetIterator<'py> { type Item = Bound<'py, super::PyAny>; /// Advances the iterator and returns the next value. fn next(&mut self) -> Option { self.remaining = self.remaining.saturating_sub(1); self.it.next().map(Result::unwrap) } fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } #[inline] fn count(self) -> usize where Self: Sized, { self.len() } } impl ExactSizeIterator for BoundSetIterator<'_> { fn len(&self) -> usize { self.remaining } } #[inline] pub(crate) fn try_new_from_iter<'py, T>( py: Python<'py>, elements: impl IntoIterator, ) -> PyResult> where T: IntoPyObject<'py>, { let set = unsafe { // We create the `Bound` pointer because its Drop cleans up the set if // user code errors or panics. ffi::PySet_New(std::ptr::null_mut()) .assume_owned_or_err(py)? .downcast_into_unchecked() }; let ptr = set.as_ptr(); elements.into_iter().try_for_each(|element| { let obj = element.into_pyobject_or_pyerr(py)?; err::error_on_minusone(py, unsafe { ffi::PySet_Add(ptr, obj.as_ptr()) }) })?; Ok(set) } #[cfg(test)] mod tests { use super::PySet; use crate::{ conversion::IntoPyObject, ffi, types::{PyAnyMethods, PySetMethods}, Python, }; use std::collections::HashSet; #[test] fn test_set_new() { Python::with_gil(|py| { let set = PySet::new(py, [1]).unwrap(); assert_eq!(1, set.len()); let v = vec![1]; assert!(PySet::new(py, &[v]).is_err()); }); } #[test] fn test_set_empty() { Python::with_gil(|py| { let set = PySet::empty(py).unwrap(); assert_eq!(0, set.len()); assert!(set.is_empty()); }); } #[test] fn test_set_len() { Python::with_gil(|py| { let mut v = HashSet::::new(); let ob = (&v).into_pyobject(py).unwrap(); let set = ob.downcast::().unwrap(); assert_eq!(0, set.len()); v.insert(7); let ob = v.into_pyobject(py).unwrap(); let set2 = ob.downcast::().unwrap(); assert_eq!(1, set2.len()); }); } #[test] fn test_set_clear() { Python::with_gil(|py| { let set = PySet::new(py, [1]).unwrap(); assert_eq!(1, set.len()); set.clear(); assert_eq!(0, set.len()); }); } #[test] fn test_set_contains() { Python::with_gil(|py| { let set = PySet::new(py, [1]).unwrap(); assert!(set.contains(1).unwrap()); }); } #[test] fn test_set_discard() { Python::with_gil(|py| { let set = PySet::new(py, [1]).unwrap(); assert!(!set.discard(2).unwrap()); assert_eq!(1, set.len()); assert!(set.discard(1).unwrap()); assert_eq!(0, set.len()); assert!(!set.discard(1).unwrap()); assert!(set.discard(vec![1, 2]).is_err()); }); } #[test] fn test_set_add() { Python::with_gil(|py| { let set = PySet::new(py, [1, 2]).unwrap(); set.add(1).unwrap(); // Add a dupliated element assert!(set.contains(1).unwrap()); }); } #[test] fn test_set_pop() { Python::with_gil(|py| { let set = PySet::new(py, [1]).unwrap(); let val = set.pop(); assert!(val.is_some()); let val2 = set.pop(); assert!(val2.is_none()); assert!(py .eval( ffi::c_str!("print('Exception state should not be set.')"), None, None ) .is_ok()); }); } #[test] fn test_set_iter() { Python::with_gil(|py| { let set = PySet::new(py, [1]).unwrap(); for el in set { assert_eq!(1i32, el.extract::<'_, i32>().unwrap()); } }); } #[test] fn test_set_iter_bound() { use crate::types::any::PyAnyMethods; Python::with_gil(|py| { let set = PySet::new(py, [1]).unwrap(); for el in &set { assert_eq!(1i32, el.extract::().unwrap()); } }); } #[test] #[should_panic] fn test_set_iter_mutation() { Python::with_gil(|py| { let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap(); for _ in &set { let _ = set.add(42); } }); } #[test] #[should_panic] fn test_set_iter_mutation_same_len() { Python::with_gil(|py| { let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap(); for item in &set { let item: i32 = item.extract().unwrap(); let _ = set.del_item(item); let _ = set.add(item + 10); } }); } #[test] fn test_set_iter_size_hint() { Python::with_gil(|py| { let set = PySet::new(py, [1]).unwrap(); let mut iter = set.iter(); // Exact size assert_eq!(iter.len(), 1); assert_eq!(iter.size_hint(), (1, Some(1))); iter.next(); assert_eq!(iter.len(), 0); assert_eq!(iter.size_hint(), (0, Some(0))); }); } #[test] fn test_iter_count() { Python::with_gil(|py| { let set = PySet::new(py, vec![1, 2, 3]).unwrap(); assert_eq!(set.iter().count(), 3); }) } } pyo3/src/types/mapping.rs0000644000175000017500000002561715105742312015243 0ustar bdrungbdrunguse crate::conversion::IntoPyObject; use crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::py_result_ext::PyResultExt; use crate::sync::GILOnceCell; use crate::type_object::PyTypeInfo; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyDict, PyList, PyType}; use crate::{ffi, Py, PyTypeCheck, Python}; /// Represents a reference to a Python object supporting the mapping protocol. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyMapping>`][Bound]. /// /// For APIs available on mapping objects, see the [`PyMappingMethods`] trait which is implemented for /// [`Bound<'py, PyMapping>`][Bound]. #[repr(transparent)] pub struct PyMapping(PyAny); pyobject_native_type_named!(PyMapping); impl PyMapping { /// Register a pyclass as a subclass of `collections.abc.Mapping` (from the Python standard /// library). This is equivalent to `collections.abc.Mapping.register(T)` in Python. /// This registration is required for a pyclass to be downcastable from `PyAny` to `PyMapping`. pub fn register(py: Python<'_>) -> PyResult<()> { let ty = T::type_object(py); get_mapping_abc(py)?.call_method1("register", (ty,))?; Ok(()) } } /// Implementation of functionality for [`PyMapping`]. /// /// These methods are defined for the `Bound<'py, PyMapping>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyMapping")] pub trait PyMappingMethods<'py>: crate::sealed::Sealed { /// Returns the number of objects in the mapping. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> PyResult; /// Returns whether the mapping is empty. fn is_empty(&self) -> PyResult; /// Determines if the mapping contains the specified key. /// /// This is equivalent to the Python expression `key in self`. fn contains(&self, key: K) -> PyResult where K: IntoPyObject<'py>; /// Gets the item in self with key `key`. /// /// Returns an `Err` if the item with specified key is not found, usually `KeyError`. /// /// This is equivalent to the Python expression `self[key]`. fn get_item(&self, key: K) -> PyResult> where K: IntoPyObject<'py>; /// Sets the item in self with key `key`. /// /// This is equivalent to the Python expression `self[key] = value`. fn set_item(&self, key: K, value: V) -> PyResult<()> where K: IntoPyObject<'py>, V: IntoPyObject<'py>; /// Deletes the item with key `key`. /// /// This is equivalent to the Python statement `del self[key]`. fn del_item(&self, key: K) -> PyResult<()> where K: IntoPyObject<'py>; /// Returns a list containing all keys in the mapping. fn keys(&self) -> PyResult>; /// Returns a list containing all values in the mapping. fn values(&self) -> PyResult>; /// Returns a list of all (key, value) pairs in the mapping. fn items(&self) -> PyResult>; } impl<'py> PyMappingMethods<'py> for Bound<'py, PyMapping> { #[inline] fn len(&self) -> PyResult { let v = unsafe { ffi::PyMapping_Size(self.as_ptr()) }; crate::err::error_on_minusone(self.py(), v)?; Ok(v as usize) } #[inline] fn is_empty(&self) -> PyResult { self.len().map(|l| l == 0) } fn contains(&self, key: K) -> PyResult where K: IntoPyObject<'py>, { PyAnyMethods::contains(&**self, key) } #[inline] fn get_item(&self, key: K) -> PyResult> where K: IntoPyObject<'py>, { PyAnyMethods::get_item(&**self, key) } #[inline] fn set_item(&self, key: K, value: V) -> PyResult<()> where K: IntoPyObject<'py>, V: IntoPyObject<'py>, { PyAnyMethods::set_item(&**self, key, value) } #[inline] fn del_item(&self, key: K) -> PyResult<()> where K: IntoPyObject<'py>, { PyAnyMethods::del_item(&**self, key) } #[inline] fn keys(&self) -> PyResult> { unsafe { ffi::PyMapping_Keys(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn values(&self) -> PyResult> { unsafe { ffi::PyMapping_Values(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn items(&self) -> PyResult> { unsafe { ffi::PyMapping_Items(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } } fn get_mapping_abc(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { static MAPPING_ABC: GILOnceCell> = GILOnceCell::new(); MAPPING_ABC.import(py, "collections.abc", "Mapping") } impl PyTypeCheck for PyMapping { const NAME: &'static str = "Mapping"; #[inline] fn type_check(object: &Bound<'_, PyAny>) -> bool { // Using `is_instance` for `collections.abc.Mapping` is slow, so provide // optimized case dict as a well-known mapping PyDict::is_type_of(object) || get_mapping_abc(object.py()) .and_then(|abc| object.is_instance(abc)) .unwrap_or_else(|err| { err.write_unraisable(object.py(), Some(object)); false }) } } #[cfg(test)] mod tests { use std::collections::HashMap; use crate::{exceptions::PyKeyError, types::PyTuple}; use super::*; use crate::conversion::IntoPyObject; #[test] fn test_len() { Python::with_gil(|py| { let mut v = HashMap::::new(); let ob = (&v).into_pyobject(py).unwrap(); let mapping = ob.downcast::().unwrap(); assert_eq!(0, mapping.len().unwrap()); assert!(mapping.is_empty().unwrap()); v.insert(7, 32); let ob = v.into_pyobject(py).unwrap(); let mapping2 = ob.downcast::().unwrap(); assert_eq!(1, mapping2.len().unwrap()); assert!(!mapping2.is_empty().unwrap()); }); } #[test] fn test_contains() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert("key0", 1234); let ob = v.into_pyobject(py).unwrap(); let mapping = ob.downcast::().unwrap(); mapping.set_item("key1", "foo").unwrap(); assert!(mapping.contains("key0").unwrap()); assert!(mapping.contains("key1").unwrap()); assert!(!mapping.contains("key2").unwrap()); }); } #[test] fn test_get_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.into_pyobject(py).unwrap(); let mapping = ob.downcast::().unwrap(); assert_eq!( 32, mapping.get_item(7i32).unwrap().extract::().unwrap() ); assert!(mapping .get_item(8i32) .unwrap_err() .is_instance_of::(py)); }); } #[test] fn test_set_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.into_pyobject(py).unwrap(); let mapping = ob.downcast::().unwrap(); assert!(mapping.set_item(7i32, 42i32).is_ok()); // change assert!(mapping.set_item(8i32, 123i32).is_ok()); // insert assert_eq!( 42i32, mapping.get_item(7i32).unwrap().extract::().unwrap() ); assert_eq!( 123i32, mapping.get_item(8i32).unwrap().extract::().unwrap() ); }); } #[test] fn test_del_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.into_pyobject(py).unwrap(); let mapping = ob.downcast::().unwrap(); assert!(mapping.del_item(7i32).is_ok()); assert_eq!(0, mapping.len().unwrap()); assert!(mapping .get_item(7i32) .unwrap_err() .is_instance_of::(py)); }); } #[test] fn test_items() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.into_pyobject(py).unwrap(); let mapping = ob.downcast::().unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; let mut value_sum = 0; for el in mapping.items().unwrap().try_iter().unwrap() { let tuple = el.unwrap().downcast_into::().unwrap(); key_sum += tuple.get_item(0).unwrap().extract::().unwrap(); value_sum += tuple.get_item(1).unwrap().extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_keys() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.into_pyobject(py).unwrap(); let mapping = ob.downcast::().unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; for el in mapping.keys().unwrap().try_iter().unwrap() { key_sum += el.unwrap().extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); }); } #[test] fn test_values() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.into_pyobject(py).unwrap(); let mapping = ob.downcast::().unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut values_sum = 0; for el in mapping.values().unwrap().try_iter().unwrap() { values_sum += el.unwrap().extract::().unwrap(); } assert_eq!(32 + 42 + 123, values_sum); }); } } pyo3/src/types/float.rs0000644000175000017500000002465715105742312014720 0ustar bdrungbdrunguse super::any::PyAnyMethods; use crate::conversion::IntoPyObject; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ ffi, ffi_ptr_ext::FfiPtrExt, instance::Bound, Borrowed, FromPyObject, PyAny, PyErr, PyResult, Python, }; use std::convert::Infallible; use std::os::raw::c_double; /// Represents a Python `float` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyFloat>`][Bound]. /// /// For APIs available on `float` objects, see the [`PyFloatMethods`] trait which is implemented for /// [`Bound<'py, PyFloat>`][Bound]. /// /// You can usually avoid directly working with this type /// by using [`IntoPyObject`] and [`extract`][PyAnyMethods::extract] /// with [`f32`]/[`f64`]. #[repr(transparent)] pub struct PyFloat(PyAny); pyobject_subclassable_native_type!(PyFloat, crate::ffi::PyFloatObject); pyobject_native_type!( PyFloat, ffi::PyFloatObject, pyobject_native_static_type_object!(ffi::PyFloat_Type), #checkfunction=ffi::PyFloat_Check ); impl PyFloat { /// Creates a new Python `float` object. pub fn new(py: Python<'_>, val: c_double) -> Bound<'_, PyFloat> { unsafe { ffi::PyFloat_FromDouble(val) .assume_owned(py) .downcast_into_unchecked() } } } /// Implementation of functionality for [`PyFloat`]. /// /// These methods are defined for the `Bound<'py, PyFloat>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyFloat")] pub trait PyFloatMethods<'py>: crate::sealed::Sealed { /// Gets the value of this float. fn value(&self) -> c_double; } impl<'py> PyFloatMethods<'py> for Bound<'py, PyFloat> { fn value(&self) -> c_double { #[cfg(not(Py_LIMITED_API))] unsafe { // Safety: self is PyFloat object ffi::PyFloat_AS_DOUBLE(self.as_ptr()) } #[cfg(Py_LIMITED_API)] unsafe { ffi::PyFloat_AsDouble(self.as_ptr()) } } } impl<'py> IntoPyObject<'py> for f64 { type Target = PyFloat; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyFloat::new(py, self)) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("float") } } impl<'py> IntoPyObject<'py> for &f64 { type Target = PyFloat; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("float") } } impl<'py> FromPyObject<'py> for f64 { // PyFloat_AsDouble returns -1.0 upon failure #![allow(clippy::float_cmp)] fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { // On non-limited API, .value() uses PyFloat_AS_DOUBLE which // allows us to have an optimized fast path for the case when // we have exactly a `float` object (it's not worth going through // `isinstance` machinery for subclasses). #[cfg(not(Py_LIMITED_API))] if let Ok(float) = obj.downcast_exact::() { return Ok(float.value()); } let v = unsafe { ffi::PyFloat_AsDouble(obj.as_ptr()) }; if v == -1.0 { if let Some(err) = PyErr::take(obj.py()) { return Err(err); } } Ok(v) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } impl<'py> IntoPyObject<'py> for f32 { type Target = PyFloat; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyFloat::new(py, self.into())) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("float") } } impl<'py> IntoPyObject<'py> for &f32 { type Target = PyFloat; type Output = Bound<'py, Self::Target>; type Error = Infallible; #[inline] fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("float") } } impl<'py> FromPyObject<'py> for f32 { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { Ok(obj.extract::()? as f32) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } macro_rules! impl_partial_eq_for_float { ($float_type: ty) => { impl PartialEq<$float_type> for Bound<'_, PyFloat> { #[inline] fn eq(&self, other: &$float_type) -> bool { self.value() as $float_type == *other } } impl PartialEq<$float_type> for &Bound<'_, PyFloat> { #[inline] fn eq(&self, other: &$float_type) -> bool { self.value() as $float_type == *other } } impl PartialEq<&$float_type> for Bound<'_, PyFloat> { #[inline] fn eq(&self, other: &&$float_type) -> bool { self.value() as $float_type == **other } } impl PartialEq> for $float_type { #[inline] fn eq(&self, other: &Bound<'_, PyFloat>) -> bool { other.value() as $float_type == *self } } impl PartialEq<&'_ Bound<'_, PyFloat>> for $float_type { #[inline] fn eq(&self, other: &&'_ Bound<'_, PyFloat>) -> bool { other.value() as $float_type == *self } } impl PartialEq> for &'_ $float_type { #[inline] fn eq(&self, other: &Bound<'_, PyFloat>) -> bool { other.value() as $float_type == **self } } impl PartialEq<$float_type> for Borrowed<'_, '_, PyFloat> { #[inline] fn eq(&self, other: &$float_type) -> bool { self.value() as $float_type == *other } } impl PartialEq<&$float_type> for Borrowed<'_, '_, PyFloat> { #[inline] fn eq(&self, other: &&$float_type) -> bool { self.value() as $float_type == **other } } impl PartialEq> for $float_type { #[inline] fn eq(&self, other: &Borrowed<'_, '_, PyFloat>) -> bool { other.value() as $float_type == *self } } impl PartialEq> for &$float_type { #[inline] fn eq(&self, other: &Borrowed<'_, '_, PyFloat>) -> bool { other.value() as $float_type == **self } } }; } impl_partial_eq_for_float!(f64); impl_partial_eq_for_float!(f32); #[cfg(test)] mod tests { use crate::{ conversion::IntoPyObject, types::{PyAnyMethods, PyFloat, PyFloatMethods}, Python, }; macro_rules! num_to_py_object_and_back ( ($func_name:ident, $t1:ty, $t2:ty) => ( #[test] fn $func_name() { use assert_approx_eq::assert_approx_eq; Python::with_gil(|py| { let val = 123 as $t1; let obj = val.into_pyobject(py).unwrap(); assert_approx_eq!(obj.extract::<$t2>().unwrap(), val as $t2); }); } ) ); num_to_py_object_and_back!(to_from_f64, f64, f64); num_to_py_object_and_back!(to_from_f32, f32, f32); num_to_py_object_and_back!(int_to_float, i32, f64); #[test] fn test_float_value() { use assert_approx_eq::assert_approx_eq; Python::with_gil(|py| { let v = 1.23f64; let obj = PyFloat::new(py, 1.23); assert_approx_eq!(v, obj.value()); }); } #[test] fn test_pyfloat_comparisons() { Python::with_gil(|py| { let f_64 = 1.01f64; let py_f64 = PyFloat::new(py, 1.01); let py_f64_ref = &py_f64; let py_f64_borrowed = py_f64.as_borrowed(); // Bound<'_, PyFloat> == f64 and vice versa assert_eq!(py_f64, f_64); assert_eq!(f_64, py_f64); // Bound<'_, PyFloat> == &f64 and vice versa assert_eq!(py_f64, &f_64); assert_eq!(&f_64, py_f64); // &Bound<'_, PyFloat> == &f64 and vice versa assert_eq!(py_f64_ref, f_64); assert_eq!(f_64, py_f64_ref); // &Bound<'_, PyFloat> == &f64 and vice versa assert_eq!(py_f64_ref, &f_64); assert_eq!(&f_64, py_f64_ref); // Borrowed<'_, '_, PyFloat> == f64 and vice versa assert_eq!(py_f64_borrowed, f_64); assert_eq!(f_64, py_f64_borrowed); // Borrowed<'_, '_, PyFloat> == &f64 and vice versa assert_eq!(py_f64_borrowed, &f_64); assert_eq!(&f_64, py_f64_borrowed); let f_32 = 2.02f32; let py_f32 = PyFloat::new(py, 2.02); let py_f32_ref = &py_f32; let py_f32_borrowed = py_f32.as_borrowed(); // Bound<'_, PyFloat> == f32 and vice versa assert_eq!(py_f32, f_32); assert_eq!(f_32, py_f32); // Bound<'_, PyFloat> == &f32 and vice versa assert_eq!(py_f32, &f_32); assert_eq!(&f_32, py_f32); // &Bound<'_, PyFloat> == &f32 and vice versa assert_eq!(py_f32_ref, f_32); assert_eq!(f_32, py_f32_ref); // &Bound<'_, PyFloat> == &f32 and vice versa assert_eq!(py_f32_ref, &f_32); assert_eq!(&f_32, py_f32_ref); // Borrowed<'_, '_, PyFloat> == f32 and vice versa assert_eq!(py_f32_borrowed, f_32); assert_eq!(f_32, py_f32_borrowed); // Borrowed<'_, '_, PyFloat> == &f32 and vice versa assert_eq!(py_f32_borrowed, &f_32); assert_eq!(&f_32, py_f32_borrowed); }); } } pyo3/src/types/pysuper.rs0000644000175000017500000000354715105742312015315 0ustar bdrungbdrunguse crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::types::PyType; use crate::{ffi, PyTypeInfo}; use crate::{PyAny, PyResult}; /// Represents a Python `super` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PySuper>`][Bound]. #[repr(transparent)] pub struct PySuper(PyAny); pyobject_native_type_core!( PySuper, pyobject_native_static_type_object!(ffi::PySuper_Type) ); impl PySuper { /// Constructs a new super object. More read about super object: [docs](https://docs.python.org/3/library/functions.html#super) /// /// # Examples /// /// ```rust,no_run /// use pyo3::prelude::*; /// /// #[pyclass(subclass)] /// struct BaseClass { /// val1: usize, /// } /// /// #[pymethods] /// impl BaseClass { /// #[new] /// fn new() -> Self { /// BaseClass { val1: 10 } /// } /// /// pub fn method(&self) -> usize { /// self.val1 /// } /// } /// /// #[pyclass(extends=BaseClass)] /// struct SubClass {} /// /// #[pymethods] /// impl SubClass { /// #[new] /// fn new() -> (Self, BaseClass) { /// (SubClass {}, BaseClass::new()) /// } /// /// fn method<'py>(self_: &Bound<'py, Self>) -> PyResult> { /// let super_ = self_.py_super()?; /// super_.call_method("method", (), None) /// } /// } /// ``` pub fn new<'py>( ty: &Bound<'py, PyType>, obj: &Bound<'py, PyAny>, ) -> PyResult> { PySuper::type_object(ty.py()).call1((ty, obj)).map(|any| { // Safety: super() always returns instance of super unsafe { any.downcast_into_unchecked() } }) } } pyo3/src/types/tuple.rs0000644000175000017500000015714715105742312014745 0ustar bdrungbdrunguse crate::ffi::{self, Py_ssize_t}; use crate::ffi_ptr_ext::FfiPtrExt; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::instance::Borrowed; use crate::internal_tricks::get_ssize_index; use crate::types::{any::PyAnyMethods, sequence::PySequenceMethods, PyList, PySequence}; use crate::{ exceptions, Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, PyAny, PyErr, PyResult, Python, }; use std::iter::FusedIterator; #[cfg(feature = "nightly")] use std::num::NonZero; #[inline] #[track_caller] fn try_new_from_iter<'py>( py: Python<'py>, mut elements: impl ExactSizeIterator>>, ) -> PyResult> { unsafe { // PyTuple_New checks for overflow but has a bad error message, so we check ourselves let len: Py_ssize_t = elements .len() .try_into() .expect("out of range integral type conversion attempted on `elements.len()`"); let ptr = ffi::PyTuple_New(len); // - Panics if the ptr is null // - Cleans up the tuple if `convert` or the asserts panic let tup = ptr.assume_owned(py).downcast_into_unchecked(); let mut counter: Py_ssize_t = 0; for obj in (&mut elements).take(len as usize) { #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] ffi::PyTuple_SET_ITEM(ptr, counter, obj?.into_ptr()); #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] ffi::PyTuple_SetItem(ptr, counter, obj?.into_ptr()); counter += 1; } assert!(elements.next().is_none(), "Attempted to create PyTuple but `elements` was larger than reported by its `ExactSizeIterator` implementation."); assert_eq!(len, counter, "Attempted to create PyTuple but `elements` was smaller than reported by its `ExactSizeIterator` implementation."); Ok(tup) } } /// Represents a Python `tuple` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyTuple>`][Bound]. /// /// For APIs available on `tuple` objects, see the [`PyTupleMethods`] trait which is implemented for /// [`Bound<'py, PyTuple>`][Bound]. #[repr(transparent)] pub struct PyTuple(PyAny); pyobject_native_type_core!(PyTuple, pyobject_native_static_type_object!(ffi::PyTuple_Type), #checkfunction=ffi::PyTuple_Check); impl PyTuple { /// Constructs a new tuple with the given elements. /// /// If you want to create a [`PyTuple`] with elements of different or unknown types, or from an /// iterable that doesn't implement [`ExactSizeIterator`], create a Rust tuple with the given /// elements and convert it at once using `into_py`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyTuple; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let elements: Vec = vec![0, 1, 2, 3, 4, 5]; /// let tuple = PyTuple::new(py, elements)?; /// assert_eq!(format!("{:?}", tuple), "(0, 1, 2, 3, 4, 5)"); /// # Ok(()) /// }) /// # } /// ``` /// /// # Panics /// /// This function will panic if `element`'s [`ExactSizeIterator`] implementation is incorrect. /// All standard library structures implement this trait correctly, if they do, so calling this /// function using [`Vec`]`` or `&[T]` will always succeed. #[track_caller] pub fn new<'py, T, U>( py: Python<'py>, elements: impl IntoIterator, ) -> PyResult> where T: IntoPyObject<'py>, U: ExactSizeIterator, { let elements = elements.into_iter().map(|e| e.into_bound_py_any(py)); try_new_from_iter(py, elements) } /// Constructs an empty tuple (on the Python side, a singleton object). pub fn empty(py: Python<'_>) -> Bound<'_, PyTuple> { unsafe { ffi::PyTuple_New(0) .assume_owned(py) .downcast_into_unchecked() } } } /// Implementation of functionality for [`PyTuple`]. /// /// These methods are defined for the `Bound<'py, PyTuple>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyTuple")] pub trait PyTupleMethods<'py>: crate::sealed::Sealed { /// Gets the length of the tuple. fn len(&self) -> usize; /// Checks if the tuple is empty. fn is_empty(&self) -> bool; /// Returns `self` cast as a `PySequence`. fn as_sequence(&self) -> &Bound<'py, PySequence>; /// Returns `self` cast as a `PySequence`. fn into_sequence(self) -> Bound<'py, PySequence>; /// Takes the slice `self[low:high]` and returns it as a new tuple. /// /// Indices must be nonnegative, and out-of-range indices are clipped to /// `self.len()`. fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyTuple>; /// Gets the tuple item at the specified index. /// # Example /// ``` /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let tuple = (1, 2, 3).into_pyobject(py)?; /// let obj = tuple.get_item(0); /// assert_eq!(obj?.extract::()?, 1); /// Ok(()) /// }) /// # } /// ``` fn get_item(&self, index: usize) -> PyResult>; /// Like [`get_item`][PyTupleMethods::get_item], but returns a borrowed object, which is a slight performance optimization /// by avoiding a reference count change. fn get_borrowed_item<'a>(&'a self, index: usize) -> PyResult>; /// Gets the tuple item at the specified index. Undefined behavior on bad index. Use with caution. /// /// # Safety /// /// Caller must verify that the index is within the bounds of the tuple. #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny>; /// Like [`get_item_unchecked`][PyTupleMethods::get_item_unchecked], but returns a borrowed object, /// which is a slight performance optimization by avoiding a reference count change. /// /// # Safety /// /// Caller must verify that the index is within the bounds of the tuple. #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny>; /// Returns `self` as a slice of objects. #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn as_slice(&self) -> &[Bound<'py, PyAny>]; /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. fn contains(&self, value: V) -> PyResult where V: IntoPyObject<'py>; /// Returns the first index `i` for which `self[i] == value`. /// /// This is equivalent to the Python expression `self.index(value)`. fn index(&self, value: V) -> PyResult where V: IntoPyObject<'py>; /// Returns an iterator over the tuple items. fn iter(&self) -> BoundTupleIterator<'py>; /// Like [`iter`][PyTupleMethods::iter], but produces an iterator which returns borrowed objects, /// which is a slight performance optimization by avoiding a reference count change. fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py>; /// Return a new list containing the contents of this tuple; equivalent to the Python expression `list(tuple)`. /// /// This method is equivalent to `self.as_sequence().to_list()` and faster than `PyList::new(py, self)`. fn to_list(&self) -> Bound<'py, PyList>; } impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> { fn len(&self) -> usize { unsafe { #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] let size = ffi::PyTuple_GET_SIZE(self.as_ptr()); #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] let size = ffi::PyTuple_Size(self.as_ptr()); // non-negative Py_ssize_t should always fit into Rust uint size as usize } } fn is_empty(&self) -> bool { self.len() == 0 } fn as_sequence(&self) -> &Bound<'py, PySequence> { unsafe { self.downcast_unchecked() } } fn into_sequence(self) -> Bound<'py, PySequence> { unsafe { self.into_any().downcast_into_unchecked() } } fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyTuple> { unsafe { ffi::PyTuple_GetSlice(self.as_ptr(), get_ssize_index(low), get_ssize_index(high)) .assume_owned(self.py()) .downcast_into_unchecked() } } fn get_item(&self, index: usize) -> PyResult> { self.get_borrowed_item(index).map(Borrowed::to_owned) } fn get_borrowed_item<'a>(&'a self, index: usize) -> PyResult> { self.as_borrowed().get_borrowed_item(index) } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny> { unsafe { self.get_borrowed_item_unchecked(index).to_owned() } } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny> { unsafe { self.as_borrowed().get_borrowed_item_unchecked(index) } } #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn as_slice(&self) -> &[Bound<'py, PyAny>] { // SAFETY: self is known to be a tuple object, and tuples are immutable let items = unsafe { &(*self.as_ptr().cast::()).ob_item }; // SAFETY: Bound<'py, PyAny> has the same memory layout as *mut ffi::PyObject unsafe { std::slice::from_raw_parts(items.as_ptr().cast(), self.len()) } } #[inline] fn contains(&self, value: V) -> PyResult where V: IntoPyObject<'py>, { self.as_sequence().contains(value) } #[inline] fn index(&self, value: V) -> PyResult where V: IntoPyObject<'py>, { self.as_sequence().index(value) } fn iter(&self) -> BoundTupleIterator<'py> { BoundTupleIterator::new(self.clone()) } fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py> { self.as_borrowed().iter_borrowed() } fn to_list(&self) -> Bound<'py, PyList> { self.as_sequence() .to_list() .expect("failed to convert tuple to list") } } impl<'a, 'py> Borrowed<'a, 'py, PyTuple> { fn get_borrowed_item(self, index: usize) -> PyResult> { unsafe { ffi::PyTuple_GetItem(self.as_ptr(), index as Py_ssize_t) .assume_borrowed_or_err(self.py()) } } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked(self, index: usize) -> Borrowed<'a, 'py, PyAny> { unsafe { ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t).assume_borrowed(self.py()) } } pub(crate) fn iter_borrowed(self) -> BorrowedTupleIterator<'a, 'py> { BorrowedTupleIterator::new(self) } } /// Used by `PyTuple::into_iter()`. pub struct BoundTupleIterator<'py> { tuple: Bound<'py, PyTuple>, index: usize, length: usize, } impl<'py> BoundTupleIterator<'py> { fn new(tuple: Bound<'py, PyTuple>) -> Self { let length = tuple.len(); BoundTupleIterator { tuple, index: 0, length, } } } impl<'py> Iterator for BoundTupleIterator<'py> { type Item = Bound<'py, PyAny>; #[inline] fn next(&mut self) -> Option { if self.index < self.length { let item = unsafe { BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), self.index).to_owned() }; self.index += 1; Some(item) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } #[inline] fn count(self) -> usize where Self: Sized, { self.len() } #[inline] fn last(mut self) -> Option where Self: Sized, { self.next_back() } #[inline] #[cfg(not(feature = "nightly"))] fn nth(&mut self, n: usize) -> Option { let length = self.length.min(self.tuple.len()); let target_index = self.index + n; if target_index < length { let item = unsafe { BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), target_index).to_owned() }; self.index = target_index + 1; Some(item) } else { None } } #[inline] #[cfg(feature = "nightly")] fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { let max_len = self.length.min(self.tuple.len()); let currently_at = self.index; if currently_at >= max_len { if n == 0 { return Ok(()); } else { return Err(unsafe { NonZero::new_unchecked(n) }); } } let items_left = max_len - currently_at; if n <= items_left { self.index += n; Ok(()) } else { self.index = max_len; let remainder = n - items_left; Err(unsafe { NonZero::new_unchecked(remainder) }) } } } impl DoubleEndedIterator for BoundTupleIterator<'_> { #[inline] fn next_back(&mut self) -> Option { if self.index < self.length { let item = unsafe { BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), self.length - 1) .to_owned() }; self.length -= 1; Some(item) } else { None } } #[inline] #[cfg(not(feature = "nightly"))] fn nth_back(&mut self, n: usize) -> Option { let length_size = self.length.min(self.tuple.len()); if self.index + n < length_size { let target_index = length_size - n - 1; let item = unsafe { BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), target_index).to_owned() }; self.length = target_index; Some(item) } else { None } } #[inline] #[cfg(feature = "nightly")] fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { let max_len = self.length.min(self.tuple.len()); let currently_at = self.index; if currently_at >= max_len { if n == 0 { return Ok(()); } else { return Err(unsafe { NonZero::new_unchecked(n) }); } } let items_left = max_len - currently_at; if n <= items_left { self.length = max_len - n; Ok(()) } else { self.length = currently_at; let remainder = n - items_left; Err(unsafe { NonZero::new_unchecked(remainder) }) } } } impl ExactSizeIterator for BoundTupleIterator<'_> { fn len(&self) -> usize { self.length.saturating_sub(self.index) } } impl FusedIterator for BoundTupleIterator<'_> {} impl<'py> IntoIterator for Bound<'py, PyTuple> { type Item = Bound<'py, PyAny>; type IntoIter = BoundTupleIterator<'py>; fn into_iter(self) -> Self::IntoIter { BoundTupleIterator::new(self) } } impl<'py> IntoIterator for &Bound<'py, PyTuple> { type Item = Bound<'py, PyAny>; type IntoIter = BoundTupleIterator<'py>; fn into_iter(self) -> Self::IntoIter { self.iter() } } /// Used by `PyTuple::iter_borrowed()`. pub struct BorrowedTupleIterator<'a, 'py> { tuple: Borrowed<'a, 'py, PyTuple>, index: usize, length: usize, } impl<'a, 'py> BorrowedTupleIterator<'a, 'py> { fn new(tuple: Borrowed<'a, 'py, PyTuple>) -> Self { let length = tuple.len(); BorrowedTupleIterator { tuple, index: 0, length, } } unsafe fn get_item( tuple: Borrowed<'a, 'py, PyTuple>, index: usize, ) -> Borrowed<'a, 'py, PyAny> { #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] let item = tuple.get_borrowed_item(index).expect("tuple.get failed"); #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] let item = unsafe { tuple.get_borrowed_item_unchecked(index) }; item } } impl<'a, 'py> Iterator for BorrowedTupleIterator<'a, 'py> { type Item = Borrowed<'a, 'py, PyAny>; #[inline] fn next(&mut self) -> Option { if self.index < self.length { let item = unsafe { Self::get_item(self.tuple, self.index) }; self.index += 1; Some(item) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } #[inline] fn count(self) -> usize where Self: Sized, { self.len() } #[inline] fn last(mut self) -> Option where Self: Sized, { self.next_back() } } impl DoubleEndedIterator for BorrowedTupleIterator<'_, '_> { #[inline] fn next_back(&mut self) -> Option { if self.index < self.length { let item = unsafe { Self::get_item(self.tuple, self.length - 1) }; self.length -= 1; Some(item) } else { None } } } impl ExactSizeIterator for BorrowedTupleIterator<'_, '_> { fn len(&self) -> usize { self.length.saturating_sub(self.index) } } impl FusedIterator for BorrowedTupleIterator<'_, '_> {} #[cold] fn wrong_tuple_length(t: &Bound<'_, PyTuple>, expected_length: usize) -> PyErr { let msg = format!( "expected tuple of length {}, but got tuple of length {}", expected_length, t.len() ); exceptions::PyValueError::new_err(msg) } macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+} => { impl <'py, $($T),+> IntoPyObject<'py> for ($($T,)+) where $($T: IntoPyObject<'py>,)+ { type Target = PyTuple; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(array_into_tuple(py, [$(self.$n.into_bound_py_any(py)?),+])) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::Tuple(Some(vec![$( $T::type_output() ),+])) } } impl <'a, 'py, $($T),+> IntoPyObject<'py> for &'a ($($T,)+) where $(&'a $T: IntoPyObject<'py>,)+ $($T: 'a,)+ // MSRV { type Target = PyTuple; type Output = Bound<'py, Self::Target>; type Error = PyErr; fn into_pyobject(self, py: Python<'py>) -> Result { Ok(array_into_tuple(py, [$(self.$n.into_bound_py_any(py)?),+])) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::Tuple(Some(vec![$( <&$T>::type_output() ),+])) } } impl<'py, $($T),+> crate::call::private::Sealed for ($($T,)+) where $($T: IntoPyObject<'py>,)+ {} impl<'py, $($T),+> crate::call::PyCallArgs<'py> for ($($T,)+) where $($T: IntoPyObject<'py>,)+ { #[cfg(all(Py_3_9, not(any(PyPy, GraalPy, Py_LIMITED_API))))] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, '_, crate::types::PyDict>, _: crate::call::private::Token, ) -> PyResult> { let py = function.py(); // We need this to drop the arguments correctly. let args_bound = [$(self.$n.into_bound_py_any(py)?,)*]; // Prepend one null argument for `PY_VECTORCALL_ARGUMENTS_OFFSET`. let mut args = [std::ptr::null_mut(), $(args_bound[$n].as_ptr()),*]; unsafe { ffi::PyObject_VectorcallDict( function.as_ptr(), args.as_mut_ptr().add(1), $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET, kwargs.as_ptr(), ) .assume_owned_or_err(py) } } #[cfg(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12)))] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, _: crate::call::private::Token, ) -> PyResult> { let py = function.py(); // We need this to drop the arguments correctly. let args_bound = [$(self.$n.into_bound_py_any(py)?,)*]; #[cfg(not(Py_LIMITED_API))] if $length == 1 { return unsafe { ffi::PyObject_CallOneArg( function.as_ptr(), args_bound[0].as_ptr() ) .assume_owned_or_err(py) }; } // Prepend one null argument for `PY_VECTORCALL_ARGUMENTS_OFFSET`. let mut args = [std::ptr::null_mut(), $(args_bound[$n].as_ptr()),*]; unsafe { ffi::PyObject_Vectorcall( function.as_ptr(), args.as_mut_ptr().add(1), $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET, std::ptr::null_mut(), ) .assume_owned_or_err(py) } } #[cfg(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12)))] fn call_method_positional( self, object: Borrowed<'_, 'py, PyAny>, method_name: Borrowed<'_, 'py, crate::types::PyString>, _: crate::call::private::Token, ) -> PyResult> { let py = object.py(); // We need this to drop the arguments correctly. let args_bound = [$(self.$n.into_bound_py_any(py)?,)*]; #[cfg(not(Py_LIMITED_API))] if $length == 1 { return unsafe { ffi::PyObject_CallMethodOneArg( object.as_ptr(), method_name.as_ptr(), args_bound[0].as_ptr(), ) .assume_owned_or_err(py) }; } let mut args = [object.as_ptr(), $(args_bound[$n].as_ptr()),*]; unsafe { ffi::PyObject_VectorcallMethod( method_name.as_ptr(), args.as_mut_ptr(), // +1 for the receiver. 1 + $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET, std::ptr::null_mut(), ) .assume_owned_or_err(py) } } #[cfg(not(all(Py_3_9, not(any(PyPy, GraalPy, Py_LIMITED_API)))))] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, crate::types::PyDict>, token: crate::call::private::Token, ) -> PyResult> { self.into_pyobject_or_pyerr(function.py())?.call(function, kwargs, token) } #[cfg(not(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12))))] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: crate::call::private::Token, ) -> PyResult> { self.into_pyobject_or_pyerr(function.py())?.call_positional(function, token) } #[cfg(not(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12))))] fn call_method_positional( self, object: Borrowed<'_, 'py, PyAny>, method_name: Borrowed<'_, 'py, crate::types::PyString>, token: crate::call::private::Token, ) -> PyResult> { self.into_pyobject_or_pyerr(object.py())?.call_method_positional(object, method_name, token) } } impl<'a, 'py, $($T),+> crate::call::private::Sealed for &'a ($($T,)+) where $(&'a $T: IntoPyObject<'py>,)+ $($T: 'a,)+ /*MSRV */ {} impl<'a, 'py, $($T),+> crate::call::PyCallArgs<'py> for &'a ($($T,)+) where $(&'a $T: IntoPyObject<'py>,)+ $($T: 'a,)+ // MSRV { #[cfg(all(Py_3_9, not(any(PyPy, GraalPy, Py_LIMITED_API))))] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, '_, crate::types::PyDict>, _: crate::call::private::Token, ) -> PyResult> { let py = function.py(); // We need this to drop the arguments correctly. let args_bound = [$(self.$n.into_bound_py_any(py)?,)*]; // Prepend one null argument for `PY_VECTORCALL_ARGUMENTS_OFFSET`. let mut args = [std::ptr::null_mut(), $(args_bound[$n].as_ptr()),*]; unsafe { ffi::PyObject_VectorcallDict( function.as_ptr(), args.as_mut_ptr().add(1), $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET, kwargs.as_ptr(), ) .assume_owned_or_err(py) } } #[cfg(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12)))] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, _: crate::call::private::Token, ) -> PyResult> { let py = function.py(); // We need this to drop the arguments correctly. let args_bound = [$(self.$n.into_bound_py_any(py)?,)*]; #[cfg(not(Py_LIMITED_API))] if $length == 1 { return unsafe { ffi::PyObject_CallOneArg( function.as_ptr(), args_bound[0].as_ptr() ) .assume_owned_or_err(py) }; } // Prepend one null argument for `PY_VECTORCALL_ARGUMENTS_OFFSET`. let mut args = [std::ptr::null_mut(), $(args_bound[$n].as_ptr()),*]; unsafe { ffi::PyObject_Vectorcall( function.as_ptr(), args.as_mut_ptr().add(1), $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET, std::ptr::null_mut(), ) .assume_owned_or_err(py) } } #[cfg(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12)))] fn call_method_positional( self, object: Borrowed<'_, 'py, PyAny>, method_name: Borrowed<'_, 'py, crate::types::PyString>, _: crate::call::private::Token, ) -> PyResult> { let py = object.py(); // We need this to drop the arguments correctly. let args_bound = [$(self.$n.into_bound_py_any(py)?,)*]; #[cfg(not(Py_LIMITED_API))] if $length == 1 { return unsafe { ffi::PyObject_CallMethodOneArg( object.as_ptr(), method_name.as_ptr(), args_bound[0].as_ptr(), ) .assume_owned_or_err(py) }; } let mut args = [object.as_ptr(), $(args_bound[$n].as_ptr()),*]; unsafe { ffi::PyObject_VectorcallMethod( method_name.as_ptr(), args.as_mut_ptr(), // +1 for the receiver. 1 + $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET, std::ptr::null_mut(), ) .assume_owned_or_err(py) } } #[cfg(not(all(Py_3_9, not(any(PyPy, GraalPy, Py_LIMITED_API)))))] fn call( self, function: Borrowed<'_, 'py, PyAny>, kwargs: Borrowed<'_, 'py, crate::types::PyDict>, token: crate::call::private::Token, ) -> PyResult> { self.into_pyobject_or_pyerr(function.py())?.call(function, kwargs, token) } #[cfg(not(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12))))] fn call_positional( self, function: Borrowed<'_, 'py, PyAny>, token: crate::call::private::Token, ) -> PyResult> { self.into_pyobject_or_pyerr(function.py())?.call_positional(function, token) } #[cfg(not(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12))))] fn call_method_positional( self, object: Borrowed<'_, 'py, PyAny>, method_name: Borrowed<'_, 'py, crate::types::PyString>, token: crate::call::private::Token, ) -> PyResult> { self.into_pyobject_or_pyerr(object.py())?.call_method_positional(object, method_name, token) } } impl<'py, $($T: FromPyObject<'py>),+> FromPyObject<'py> for ($($T,)+) { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { let t = obj.downcast::()?; if t.len() == $length { #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] return Ok(($(t.get_borrowed_item($n)?.extract::<$T>()?,)+)); #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe {return Ok(($(t.get_borrowed_item_unchecked($n).extract::<$T>()?,)+));} } else { Err(wrong_tuple_length(t, $length)) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Tuple(Some(vec![$( $T::type_input() ),+])) } } }); fn array_into_tuple<'py, const N: usize>( py: Python<'py>, array: [Bound<'py, PyAny>; N], ) -> Bound<'py, PyTuple> { unsafe { let ptr = ffi::PyTuple_New(N.try_into().expect("0 < N <= 12")); let tup = ptr.assume_owned(py).downcast_into_unchecked(); for (index, obj) in array.into_iter().enumerate() { #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] ffi::PyTuple_SET_ITEM(ptr, index as ffi::Py_ssize_t, obj.into_ptr()); #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] ffi::PyTuple_SetItem(ptr, index as ffi::Py_ssize_t, obj.into_ptr()); } tup } } tuple_conversion!(1, (ref0, 0, T0)); tuple_conversion!(2, (ref0, 0, T0), (ref1, 1, T1)); tuple_conversion!(3, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2)); tuple_conversion!( 4, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3) ); tuple_conversion!( 5, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4) ); tuple_conversion!( 6, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5) ); tuple_conversion!( 7, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6) ); tuple_conversion!( 8, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7) ); tuple_conversion!( 9, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7), (ref8, 8, T8) ); tuple_conversion!( 10, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7), (ref8, 8, T8), (ref9, 9, T9) ); tuple_conversion!( 11, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7), (ref8, 8, T8), (ref9, 9, T9), (ref10, 10, T10) ); tuple_conversion!( 12, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7), (ref8, 8, T8), (ref9, 9, T9), (ref10, 10, T10), (ref11, 11, T11) ); #[cfg(test)] mod tests { use crate::types::{any::PyAnyMethods, tuple::PyTupleMethods, PyList, PyTuple}; use crate::{IntoPyObject, Python}; use std::collections::HashSet; #[cfg(feature = "nightly")] use std::num::NonZero; use std::ops::Range; #[test] fn test_new() { Python::with_gil(|py| { let ob = PyTuple::new(py, [1, 2, 3]).unwrap(); assert_eq!(3, ob.len()); let ob = ob.as_any(); assert_eq!((1, 2, 3), ob.extract().unwrap()); let mut map = HashSet::new(); map.insert(1); map.insert(2); PyTuple::new(py, map).unwrap(); }); } #[test] fn test_len() { Python::with_gil(|py| { let ob = (1, 2, 3).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); assert_eq!(3, tuple.len()); assert!(!tuple.is_empty()); let ob = tuple.as_any(); assert_eq!((1, 2, 3), ob.extract().unwrap()); }); } #[test] fn test_empty() { Python::with_gil(|py| { let tuple = PyTuple::empty(py); assert!(tuple.is_empty()); assert_eq!(0, tuple.len()); }); } #[test] fn test_slice() { Python::with_gil(|py| { let tup = PyTuple::new(py, [2, 3, 5, 7]).unwrap(); let slice = tup.get_slice(1, 3); assert_eq!(2, slice.len()); let slice = tup.get_slice(1, 7); assert_eq!(3, slice.len()); }); } #[test] fn test_iter() { Python::with_gil(|py| { let ob = (1, 2, 3).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); assert_eq!(3, tuple.len()); let mut iter = tuple.iter(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(1_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(2_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(3_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_iter_rev() { Python::with_gil(|py| { let ob = (1, 2, 3).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); assert_eq!(3, tuple.len()); let mut iter = tuple.iter().rev(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(3_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(2_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(1_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_bound_iter() { Python::with_gil(|py| { let tuple = PyTuple::new(py, [1, 2, 3]).unwrap(); assert_eq!(3, tuple.len()); let mut iter = tuple.iter(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(1, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(2, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(3, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_bound_iter_rev() { Python::with_gil(|py| { let tuple = PyTuple::new(py, [1, 2, 3]).unwrap(); assert_eq!(3, tuple.len()); let mut iter = tuple.iter().rev(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(3, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(2, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(1, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_into_iter() { Python::with_gil(|py| { let ob = (1, 2, 3).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); assert_eq!(3, tuple.len()); for (i, item) in tuple.iter().enumerate() { assert_eq!(i + 1, item.extract::<'_, usize>().unwrap()); } }); } #[test] fn test_into_iter_bound() { Python::with_gil(|py| { let tuple = (1, 2, 3).into_pyobject(py).unwrap(); assert_eq!(3, tuple.len()); let mut items = vec![]; for item in tuple { items.push(item.extract::().unwrap()); } assert_eq!(items, vec![1, 2, 3]); }); } #[test] #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn test_as_slice() { Python::with_gil(|py| { let ob = (1, 2, 3).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); let slice = tuple.as_slice(); assert_eq!(3, slice.len()); assert_eq!(1_i32, slice[0].extract::<'_, i32>().unwrap()); assert_eq!(2_i32, slice[1].extract::<'_, i32>().unwrap()); assert_eq!(3_i32, slice[2].extract::<'_, i32>().unwrap()); }); } #[test] fn test_tuple_lengths_up_to_12() { Python::with_gil(|py| { let t0 = (0,).into_pyobject(py).unwrap(); let t1 = (0, 1).into_pyobject(py).unwrap(); let t2 = (0, 1, 2).into_pyobject(py).unwrap(); let t3 = (0, 1, 2, 3).into_pyobject(py).unwrap(); let t4 = (0, 1, 2, 3, 4).into_pyobject(py).unwrap(); let t5 = (0, 1, 2, 3, 4, 5).into_pyobject(py).unwrap(); let t6 = (0, 1, 2, 3, 4, 5, 6).into_pyobject(py).unwrap(); let t7 = (0, 1, 2, 3, 4, 5, 6, 7).into_pyobject(py).unwrap(); let t8 = (0, 1, 2, 3, 4, 5, 6, 7, 8).into_pyobject(py).unwrap(); let t9 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9).into_pyobject(py).unwrap(); let t10 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .into_pyobject(py) .unwrap(); let t11 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) .into_pyobject(py) .unwrap(); assert_eq!(t0.extract::<(i32,)>().unwrap(), (0,)); assert_eq!(t1.extract::<(i32, i32)>().unwrap(), (0, 1,)); assert_eq!(t2.extract::<(i32, i32, i32)>().unwrap(), (0, 1, 2,)); assert_eq!( t3.extract::<(i32, i32, i32, i32,)>().unwrap(), (0, 1, 2, 3,) ); assert_eq!( t4.extract::<(i32, i32, i32, i32, i32,)>().unwrap(), (0, 1, 2, 3, 4,) ); assert_eq!( t5.extract::<(i32, i32, i32, i32, i32, i32,)>().unwrap(), (0, 1, 2, 3, 4, 5,) ); assert_eq!( t6.extract::<(i32, i32, i32, i32, i32, i32, i32,)>() .unwrap(), (0, 1, 2, 3, 4, 5, 6,) ); assert_eq!( t7.extract::<(i32, i32, i32, i32, i32, i32, i32, i32,)>() .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7,) ); assert_eq!( t8.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32,)>() .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7, 8,) ); assert_eq!( t9.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>() .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9,) ); assert_eq!( t10.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>() .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,) ); assert_eq!( t11.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>() .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,) ); }) } #[test] fn test_tuple_get_item_invalid_index() { Python::with_gil(|py| { let ob = (1, 2, 3).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); let obj = tuple.get_item(5); assert!(obj.is_err()); assert_eq!( obj.unwrap_err().to_string(), "IndexError: tuple index out of range" ); }); } #[test] fn test_tuple_get_item_sanity() { Python::with_gil(|py| { let ob = (1, 2, 3).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); let obj = tuple.get_item(0); assert_eq!(obj.unwrap().extract::().unwrap(), 1); }); } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[test] fn test_tuple_get_item_unchecked_sanity() { Python::with_gil(|py| { let ob = (1, 2, 3).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); let obj = unsafe { tuple.get_item_unchecked(0) }; assert_eq!(obj.extract::().unwrap(), 1); }); } #[test] fn test_tuple_contains() { Python::with_gil(|py| { let ob = (1, 1, 2, 3, 5, 8).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); assert_eq!(6, tuple.len()); let bad_needle = 7i32.into_pyobject(py).unwrap(); assert!(!tuple.contains(&bad_needle).unwrap()); let good_needle = 8i32.into_pyobject(py).unwrap(); assert!(tuple.contains(&good_needle).unwrap()); let type_coerced_needle = 8f32.into_pyobject(py).unwrap(); assert!(tuple.contains(&type_coerced_needle).unwrap()); }); } #[test] fn test_tuple_index() { Python::with_gil(|py| { let ob = (1, 1, 2, 3, 5, 8).into_pyobject(py).unwrap(); let tuple = ob.downcast::().unwrap(); assert_eq!(0, tuple.index(1i32).unwrap()); assert_eq!(2, tuple.index(2i32).unwrap()); assert_eq!(3, tuple.index(3i32).unwrap()); assert_eq!(4, tuple.index(5i32).unwrap()); assert_eq!(5, tuple.index(8i32).unwrap()); assert!(tuple.index(42i32).is_err()); }); } // An iterator that lies about its `ExactSizeIterator` implementation. // See https://github.com/PyO3/pyo3/issues/2118 struct FaultyIter(Range, usize); impl Iterator for FaultyIter { type Item = usize; fn next(&mut self) -> Option { self.0.next() } } impl ExactSizeIterator for FaultyIter { fn len(&self) -> usize { self.1 } } #[test] #[should_panic( expected = "Attempted to create PyTuple but `elements` was larger than reported by its `ExactSizeIterator` implementation." )] fn too_long_iterator() { Python::with_gil(|py| { let iter = FaultyIter(0..usize::MAX, 73); let _tuple = PyTuple::new(py, iter); }) } #[test] #[should_panic( expected = "Attempted to create PyTuple but `elements` was smaller than reported by its `ExactSizeIterator` implementation." )] fn too_short_iterator() { Python::with_gil(|py| { let iter = FaultyIter(0..35, 73); let _tuple = PyTuple::new(py, iter); }) } #[test] #[should_panic( expected = "out of range integral type conversion attempted on `elements.len()`" )] fn overflowing_size() { Python::with_gil(|py| { let iter = FaultyIter(0..0, usize::MAX); let _tuple = PyTuple::new(py, iter); }) } #[test] fn bad_intopyobject_doesnt_cause_leaks() { use crate::types::PyInt; use std::convert::Infallible; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; static NEEDS_DESTRUCTING_COUNT: AtomicUsize = AtomicUsize::new(0); struct Bad(usize); impl Drop for Bad { fn drop(&mut self) { NEEDS_DESTRUCTING_COUNT.fetch_sub(1, SeqCst); } } impl<'py> IntoPyObject<'py> for Bad { type Target = PyInt; type Output = crate::Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { // This panic should not lead to a memory leak assert_ne!(self.0, 42); self.0.into_pyobject(py) } } struct FaultyIter(Range, usize); impl Iterator for FaultyIter { type Item = Bad; fn next(&mut self) -> Option { self.0.next().map(|i| { NEEDS_DESTRUCTING_COUNT.fetch_add(1, SeqCst); Bad(i) }) } } impl ExactSizeIterator for FaultyIter { fn len(&self) -> usize { self.1 } } Python::with_gil(|py| { std::panic::catch_unwind(|| { let iter = FaultyIter(0..50, 50); let _tuple = PyTuple::new(py, iter); }) .unwrap_err(); }); assert_eq!( NEEDS_DESTRUCTING_COUNT.load(SeqCst), 0, "Some destructors did not run" ); } #[test] fn bad_intopyobject_doesnt_cause_leaks_2() { use crate::types::PyInt; use std::convert::Infallible; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; static NEEDS_DESTRUCTING_COUNT: AtomicUsize = AtomicUsize::new(0); struct Bad(usize); impl Drop for Bad { fn drop(&mut self) { NEEDS_DESTRUCTING_COUNT.fetch_sub(1, SeqCst); } } impl<'py> IntoPyObject<'py> for &Bad { type Target = PyInt; type Output = crate::Bound<'py, Self::Target>; type Error = Infallible; fn into_pyobject(self, py: Python<'py>) -> Result { // This panic should not lead to a memory leak assert_ne!(self.0, 3); self.0.into_pyobject(py) } } let s = (Bad(1), Bad(2), Bad(3), Bad(4)); NEEDS_DESTRUCTING_COUNT.store(4, SeqCst); Python::with_gil(|py| { std::panic::catch_unwind(|| { let _tuple = (&s).into_pyobject(py).unwrap(); }) .unwrap_err(); }); drop(s); assert_eq!( NEEDS_DESTRUCTING_COUNT.load(SeqCst), 0, "Some destructors did not run" ); } #[test] fn test_tuple_to_list() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap(); let list = tuple.to_list(); let list_expected = PyList::new(py, vec![1, 2, 3]).unwrap(); assert!(list.eq(list_expected).unwrap()); }) } #[test] fn test_tuple_as_sequence() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap(); let sequence = tuple.as_sequence(); assert!(tuple.get_item(0).unwrap().eq(1).unwrap()); assert!(sequence.get_item(0).unwrap().eq(1).unwrap()); assert_eq!(tuple.len(), 3); assert_eq!(sequence.len().unwrap(), 3); }) } #[test] fn test_tuple_into_sequence() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap(); let sequence = tuple.into_sequence(); assert!(sequence.get_item(0).unwrap().eq(1).unwrap()); assert_eq!(sequence.len().unwrap(), 3); }) } #[test] fn test_bound_tuple_get_item() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3, 4]).unwrap(); assert_eq!(tuple.len(), 4); assert_eq!(tuple.get_item(0).unwrap().extract::().unwrap(), 1); assert_eq!( tuple .get_borrowed_item(1) .unwrap() .extract::() .unwrap(), 2 ); #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] { assert_eq!( unsafe { tuple.get_item_unchecked(2) } .extract::() .unwrap(), 3 ); assert_eq!( unsafe { tuple.get_borrowed_item_unchecked(3) } .extract::() .unwrap(), 4 ); } }) } #[test] fn test_bound_tuple_nth() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3, 4]).unwrap(); let mut iter = tuple.iter(); assert_eq!(iter.nth(1).unwrap().extract::().unwrap(), 2); assert_eq!(iter.nth(1).unwrap().extract::().unwrap(), 4); assert!(iter.nth(1).is_none()); let tuple = PyTuple::new(py, Vec::::new()).unwrap(); let mut iter = tuple.iter(); iter.next(); assert!(iter.nth(1).is_none()); let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap(); let mut iter = tuple.iter(); assert!(iter.nth(10).is_none()); let tuple = PyTuple::new(py, vec![6, 7, 8, 9, 10]).unwrap(); let mut iter = tuple.iter(); assert_eq!(iter.next().unwrap().extract::().unwrap(), 6); assert_eq!(iter.nth(2).unwrap().extract::().unwrap(), 9); assert_eq!(iter.next().unwrap().extract::().unwrap(), 10); let mut iter = tuple.iter(); assert_eq!(iter.nth_back(1).unwrap().extract::().unwrap(), 9); assert_eq!(iter.nth(2).unwrap().extract::().unwrap(), 8); assert!(iter.next().is_none()); }); } #[test] fn test_bound_tuple_nth_back() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap(); let mut iter = tuple.iter(); assert_eq!(iter.nth_back(0).unwrap().extract::().unwrap(), 5); assert_eq!(iter.nth_back(1).unwrap().extract::().unwrap(), 3); assert!(iter.nth_back(2).is_none()); let tuple = PyTuple::new(py, Vec::::new()).unwrap(); let mut iter = tuple.iter(); assert!(iter.nth_back(0).is_none()); assert!(iter.nth_back(1).is_none()); let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap(); let mut iter = tuple.iter(); assert!(iter.nth_back(5).is_none()); let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap(); let mut iter = tuple.iter(); iter.next_back(); // Consume the last element assert_eq!(iter.nth_back(1).unwrap().extract::().unwrap(), 3); assert_eq!(iter.next_back().unwrap().extract::().unwrap(), 2); assert_eq!(iter.nth_back(0).unwrap().extract::().unwrap(), 1); let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap(); let mut iter = tuple.iter(); assert_eq!(iter.nth_back(1).unwrap().extract::().unwrap(), 4); assert_eq!(iter.nth_back(2).unwrap().extract::().unwrap(), 1); let mut iter2 = tuple.iter(); iter2.next_back(); assert_eq!(iter2.nth_back(1).unwrap().extract::().unwrap(), 3); assert_eq!(iter2.next_back().unwrap().extract::().unwrap(), 2); let mut iter3 = tuple.iter(); iter3.nth(1); assert_eq!(iter3.nth_back(2).unwrap().extract::().unwrap(), 3); assert!(iter3.nth_back(0).is_none()); }); } #[cfg(feature = "nightly")] #[test] fn test_bound_tuple_advance_by() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap(); let mut iter = tuple.iter(); assert_eq!(iter.advance_by(2), Ok(())); assert_eq!(iter.next().unwrap().extract::().unwrap(), 3); assert_eq!(iter.advance_by(0), Ok(())); assert_eq!(iter.advance_by(100), Err(NonZero::new(98).unwrap())); assert!(iter.next().is_none()); let mut iter2 = tuple.iter(); assert_eq!(iter2.advance_by(6), Err(NonZero::new(1).unwrap())); let mut iter3 = tuple.iter(); assert_eq!(iter3.advance_by(5), Ok(())); let mut iter4 = tuple.iter(); assert_eq!(iter4.advance_by(0), Ok(())); assert_eq!(iter4.next().unwrap().extract::().unwrap(), 1); }) } #[cfg(feature = "nightly")] #[test] fn test_bound_tuple_advance_back_by() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap(); let mut iter = tuple.iter(); assert_eq!(iter.advance_back_by(2), Ok(())); assert_eq!(iter.next_back().unwrap().extract::().unwrap(), 3); assert_eq!(iter.advance_back_by(0), Ok(())); assert_eq!(iter.advance_back_by(100), Err(NonZero::new(98).unwrap())); assert!(iter.next_back().is_none()); let mut iter2 = tuple.iter(); assert_eq!(iter2.advance_back_by(6), Err(NonZero::new(1).unwrap())); let mut iter3 = tuple.iter(); assert_eq!(iter3.advance_back_by(5), Ok(())); let mut iter4 = tuple.iter(); assert_eq!(iter4.advance_back_by(0), Ok(())); assert_eq!(iter4.next_back().unwrap().extract::().unwrap(), 5); }) } #[test] fn test_iter_last() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap(); let last = tuple.iter().last(); assert_eq!(last.unwrap().extract::().unwrap(), 3); }) } #[test] fn test_iter_count() { Python::with_gil(|py| { let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap(); assert_eq!(tuple.iter().count(), 3); }) } } pyo3/src/types/bytearray.rs0000644000175000017500000003615215105742312015606 0ustar bdrungbdrunguse crate::err::{PyErr, PyResult}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::{Borrowed, Bound}; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::{ffi, PyAny, Python}; use std::slice; /// Represents a Python `bytearray`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyByteArray>`][Bound]. /// /// For APIs available on `bytearray` objects, see the [`PyByteArrayMethods`] trait which is implemented for /// [`Bound<'py, PyByteArray>`][Bound]. #[repr(transparent)] pub struct PyByteArray(PyAny); pyobject_native_type_core!(PyByteArray, pyobject_native_static_type_object!(ffi::PyByteArray_Type), #checkfunction=ffi::PyByteArray_Check); impl PyByteArray { /// Creates a new Python bytearray object. /// /// The byte string is initialized by copying the data from the `&[u8]`. pub fn new<'py>(py: Python<'py>, src: &[u8]) -> Bound<'py, PyByteArray> { let ptr = src.as_ptr().cast(); let len = src.len() as ffi::Py_ssize_t; unsafe { ffi::PyByteArray_FromStringAndSize(ptr, len) .assume_owned(py) .downcast_into_unchecked() } } /// Creates a new Python `bytearray` object with an `init` closure to write its contents. /// Before calling `init` the bytearray is zero-initialised. /// * If Python raises a MemoryError on the allocation, `new_with` will return /// it inside `Err`. /// * If `init` returns `Err(e)`, `new_with` will return `Err(e)`. /// * If `init` returns `Ok(())`, `new_with` will return `Ok(&PyByteArray)`. /// /// # Examples /// /// ``` /// use pyo3::{prelude::*, types::PyByteArray}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let py_bytearray = PyByteArray::new_with(py, 10, |bytes: &mut [u8]| { /// bytes.copy_from_slice(b"Hello Rust"); /// Ok(()) /// })?; /// let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() }; /// assert_eq!(bytearray, b"Hello Rust"); /// Ok(()) /// }) /// # } /// ``` pub fn new_with(py: Python<'_>, len: usize, init: F) -> PyResult> where F: FnOnce(&mut [u8]) -> PyResult<()>, { unsafe { // Allocate buffer and check for an error let pybytearray: Bound<'_, Self> = ffi::PyByteArray_FromStringAndSize(std::ptr::null(), len as ffi::Py_ssize_t) .assume_owned_or_err(py)? .downcast_into_unchecked(); let buffer: *mut u8 = ffi::PyByteArray_AsString(pybytearray.as_ptr()).cast(); debug_assert!(!buffer.is_null()); // Zero-initialise the uninitialised bytearray std::ptr::write_bytes(buffer, 0u8, len); // (Further) Initialise the bytearray in init // If init returns an Err, pypybytearray will automatically deallocate the buffer init(std::slice::from_raw_parts_mut(buffer, len)).map(|_| pybytearray) } } /// Creates a new Python `bytearray` object from another Python object that /// implements the buffer protocol. pub fn from<'py>(src: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyByteArray_FromObject(src.as_ptr()) .assume_owned_or_err(src.py()) .downcast_into_unchecked() } } } /// Implementation of functionality for [`PyByteArray`]. /// /// These methods are defined for the `Bound<'py, PyByteArray>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyByteArray")] pub trait PyByteArrayMethods<'py>: crate::sealed::Sealed { /// Gets the length of the bytearray. fn len(&self) -> usize; /// Checks if the bytearray is empty. fn is_empty(&self) -> bool; /// Gets the start of the buffer containing the contents of the bytearray. /// /// # Safety /// /// See the safety requirements of [`PyByteArrayMethods::as_bytes`] and [`PyByteArrayMethods::as_bytes_mut`]. fn data(&self) -> *mut u8; /// Extracts a slice of the `ByteArray`'s entire buffer. /// /// # Safety /// /// Mutation of the `bytearray` invalidates the slice. If it is used afterwards, the behavior is /// undefined. /// /// These mutations may occur in Python code as well as from Rust: /// - Calling methods like [`PyByteArrayMethods::as_bytes_mut`] and [`PyByteArrayMethods::resize`] will /// invalidate the slice. /// - Actions like dropping objects or raising exceptions can invoke `__del__`methods or signal /// handlers, which may execute arbitrary Python code. This means that if Python code has a /// reference to the `bytearray` you cannot safely use the vast majority of PyO3's API whilst /// using the slice. /// /// As a result, this slice should only be used for short-lived operations without executing any /// Python code, such as copying into a Vec. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::exceptions::PyRuntimeError; /// use pyo3::types::PyByteArray; /// /// #[pyfunction] /// fn a_valid_function(bytes: &Bound<'_, PyByteArray>) -> PyResult<()> { /// let section = { /// // SAFETY: We promise to not let the interpreter regain control /// // or invoke any PyO3 APIs while using the slice. /// let slice = unsafe { bytes.as_bytes() }; /// /// // Copy only a section of `bytes` while avoiding /// // `to_vec` which copies the entire thing. /// let section = slice /// .get(6..11) /// .ok_or_else(|| PyRuntimeError::new_err("input is not long enough"))?; /// Vec::from(section) /// }; /// /// // Now we can do things with `section` and call PyO3 APIs again. /// // ... /// # assert_eq!(§ion, b"world"); /// /// Ok(()) /// } /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = wrap_pyfunction!(a_valid_function, py)?; /// # let locals = pyo3::types::PyDict::new(py); /// # locals.set_item("a_valid_function", fun)?; /// # /// # py.run(pyo3::ffi::c_str!( /// # r#"b = bytearray(b"hello world") /// # a_valid_function(b) /// # /// # try: /// # a_valid_function(bytearray()) /// # except RuntimeError as e: /// # assert str(e) == 'input is not long enough'"#), /// # None, /// # Some(&locals), /// # )?; /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// # Incorrect usage /// /// The following `bug` function is unsound ⚠️ /// /// ```rust,no_run /// # use pyo3::prelude::*; /// # use pyo3::types::PyByteArray; /// /// # #[allow(dead_code)] /// #[pyfunction] /// fn bug(py: Python<'_>, bytes: &Bound<'_, PyByteArray>) { /// let slice = unsafe { bytes.as_bytes() }; /// /// // This explicitly yields control back to the Python interpreter... /// // ...but it's not always this obvious. Many things do this implicitly. /// py.allow_threads(|| { /// // Python code could be mutating through its handle to `bytes`, /// // which makes reading it a data race, which is undefined behavior. /// println!("{:?}", slice[0]); /// }); /// /// // Python code might have mutated it, so we can not rely on the slice /// // remaining valid. As such this is also undefined behavior. /// println!("{:?}", slice[0]); /// } /// ``` unsafe fn as_bytes(&self) -> &[u8]; /// Extracts a mutable slice of the `ByteArray`'s entire buffer. /// /// # Safety /// /// Any other accesses of the `bytearray`'s buffer invalidate the slice. If it is used /// afterwards, the behavior is undefined. The safety requirements of [`PyByteArrayMethods::as_bytes`] /// apply to this function as well. #[allow(clippy::mut_from_ref)] unsafe fn as_bytes_mut(&self) -> &mut [u8]; /// Copies the contents of the bytearray to a Rust vector. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # use pyo3::types::PyByteArray; /// # Python::with_gil(|py| { /// let bytearray = PyByteArray::new(py, b"Hello World."); /// let mut copied_message = bytearray.to_vec(); /// assert_eq!(b"Hello World.", copied_message.as_slice()); /// /// copied_message[11] = b'!'; /// assert_eq!(b"Hello World!", copied_message.as_slice()); /// /// pyo3::py_run!(py, bytearray, "assert bytearray == b'Hello World.'"); /// # }); /// ``` fn to_vec(&self) -> Vec; /// Resizes the bytearray object to the new length `len`. /// /// Note that this will invalidate any pointers obtained by [PyByteArrayMethods::data], as well as /// any (unsafe) slices obtained from [PyByteArrayMethods::as_bytes] and [PyByteArrayMethods::as_bytes_mut]. fn resize(&self, len: usize) -> PyResult<()>; } impl<'py> PyByteArrayMethods<'py> for Bound<'py, PyByteArray> { #[inline] fn len(&self) -> usize { // non-negative Py_ssize_t should always fit into Rust usize unsafe { ffi::PyByteArray_Size(self.as_ptr()) as usize } } fn is_empty(&self) -> bool { self.len() == 0 } fn data(&self) -> *mut u8 { self.as_borrowed().data() } unsafe fn as_bytes(&self) -> &[u8] { unsafe { self.as_borrowed().as_bytes() } } #[allow(clippy::mut_from_ref)] unsafe fn as_bytes_mut(&self) -> &mut [u8] { unsafe { self.as_borrowed().as_bytes_mut() } } fn to_vec(&self) -> Vec { unsafe { self.as_bytes() }.to_vec() } fn resize(&self, len: usize) -> PyResult<()> { unsafe { let result = ffi::PyByteArray_Resize(self.as_ptr(), len as ffi::Py_ssize_t); if result == 0 { Ok(()) } else { Err(PyErr::fetch(self.py())) } } } } impl<'a> Borrowed<'a, '_, PyByteArray> { fn data(&self) -> *mut u8 { unsafe { ffi::PyByteArray_AsString(self.as_ptr()).cast() } } #[allow(clippy::wrong_self_convention)] unsafe fn as_bytes(self) -> &'a [u8] { unsafe { slice::from_raw_parts(self.data(), self.len()) } } #[allow(clippy::wrong_self_convention)] unsafe fn as_bytes_mut(self) -> &'a mut [u8] { unsafe { slice::from_raw_parts_mut(self.data(), self.len()) } } } impl<'py> TryFrom<&Bound<'py, PyAny>> for Bound<'py, PyByteArray> { type Error = crate::PyErr; /// Creates a new Python `bytearray` object from another Python object that /// implements the buffer protocol. fn try_from(value: &Bound<'py, PyAny>) -> Result { PyByteArray::from(value) } } #[cfg(test)] mod tests { use crate::types::{PyAnyMethods, PyByteArray, PyByteArrayMethods}; use crate::{exceptions, Bound, PyAny, PyObject, Python}; #[test] fn test_len() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new(py, src); assert_eq!(src.len(), bytearray.len()); }); } #[test] fn test_as_bytes() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new(py, src); let slice = unsafe { bytearray.as_bytes() }; assert_eq!(src, slice); assert_eq!(bytearray.data() as *const _, slice.as_ptr()); }); } #[test] fn test_as_bytes_mut() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new(py, src); let slice = unsafe { bytearray.as_bytes_mut() }; assert_eq!(src, slice); assert_eq!(bytearray.data(), slice.as_mut_ptr()); slice[0..5].copy_from_slice(b"Hi..."); assert_eq!(bytearray.str().unwrap(), "bytearray(b'Hi... Python')"); }); } #[test] fn test_to_vec() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new(py, src); let vec = bytearray.to_vec(); assert_eq!(src, vec.as_slice()); }); } #[test] fn test_from() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new(py, src); let ba: PyObject = bytearray.into(); let bytearray = PyByteArray::from(ba.bind(py)).unwrap(); assert_eq!(src, unsafe { bytearray.as_bytes() }); }); } #[test] fn test_from_err() { Python::with_gil(|py| { if let Err(err) = PyByteArray::from(py.None().bind(py)) { assert!(err.is_instance_of::(py)); } else { panic!("error"); } }); } #[test] fn test_try_from() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray: &Bound<'_, PyAny> = &PyByteArray::new(py, src); let bytearray: Bound<'_, PyByteArray> = TryInto::try_into(bytearray).unwrap(); assert_eq!(src, unsafe { bytearray.as_bytes() }); }); } #[test] fn test_resize() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new(py, src); bytearray.resize(20).unwrap(); assert_eq!(20, bytearray.len()); }); } #[test] fn test_byte_array_new_with() -> super::PyResult<()> { Python::with_gil(|py| -> super::PyResult<()> { let py_bytearray = PyByteArray::new_with(py, 10, |b: &mut [u8]| { b.copy_from_slice(b"Hello Rust"); Ok(()) })?; let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() }; assert_eq!(bytearray, b"Hello Rust"); Ok(()) }) } #[test] fn test_byte_array_new_with_zero_initialised() -> super::PyResult<()> { Python::with_gil(|py| -> super::PyResult<()> { let py_bytearray = PyByteArray::new_with(py, 10, |_b: &mut [u8]| Ok(()))?; let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() }; assert_eq!(bytearray, &[0; 10]); Ok(()) }) } #[test] fn test_byte_array_new_with_error() { use crate::exceptions::PyValueError; Python::with_gil(|py| { let py_bytearray_result = PyByteArray::new_with(py, 10, |_b: &mut [u8]| { Err(PyValueError::new_err("Hello Crustaceans!")) }); assert!(py_bytearray_result.is_err()); assert!(py_bytearray_result .err() .unwrap() .is_instance_of::(py)); }) } } pyo3/src/types/iterator.rs0000644000175000017500000002777115105742312015444 0ustar bdrungbdrunguse crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Borrowed; use crate::py_result_ext::PyResultExt; use crate::{ffi, Bound, PyAny, PyErr, PyResult, PyTypeCheck}; /// A Python iterator object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyIterator>`][Bound]. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::ffi::c_str; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let list = py.eval(c_str!("iter([1, 2, 3, 4])"), None, None)?; /// let numbers: PyResult> = list /// .try_iter()? /// .map(|i| i.and_then(|i|i.extract::())) /// .collect(); /// let sum: usize = numbers?.iter().sum(); /// assert_eq!(sum, 10); /// Ok(()) /// }) /// # } /// ``` #[repr(transparent)] pub struct PyIterator(PyAny); pyobject_native_type_named!(PyIterator); impl PyIterator { /// Builds an iterator for an iterable Python object; the equivalent of calling `iter(obj)` in Python. /// /// Usually it is more convenient to write [`obj.try_iter()`][crate::types::any::PyAnyMethods::try_iter], /// which is a more concise way of calling this function. pub fn from_object<'py>(obj: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyObject_GetIter(obj.as_ptr()) .assume_owned_or_err(obj.py()) .downcast_into_unchecked() } } } #[derive(Debug)] #[cfg(all(not(PyPy), Py_3_10))] pub enum PySendResult<'py> { Next(Bound<'py, PyAny>), Return(Bound<'py, PyAny>), } #[cfg(all(not(PyPy), Py_3_10))] impl<'py> Bound<'py, PyIterator> { /// Sends a value into a python generator. This is the equivalent of calling `generator.send(value)` in Python. /// This resumes the generator and continues its execution until the next `yield` or `return` statement. /// If the generator exits without returning a value, this function returns a `StopException`. /// The first call to `send` must be made with `None` as the argument to start the generator, failing to do so will raise a `TypeError`. #[inline] pub fn send(&self, value: &Bound<'py, PyAny>) -> PyResult> { let py = self.py(); let mut result = std::ptr::null_mut(); match unsafe { ffi::PyIter_Send(self.as_ptr(), value.as_ptr(), &mut result) } { ffi::PySendResult::PYGEN_ERROR => Err(PyErr::fetch(py)), ffi::PySendResult::PYGEN_RETURN => Ok(PySendResult::Return(unsafe { result.assume_owned_unchecked(py) })), ffi::PySendResult::PYGEN_NEXT => Ok(PySendResult::Next(unsafe { result.assume_owned_unchecked(py) })), } } } impl<'py> Iterator for Bound<'py, PyIterator> { type Item = PyResult>; /// Retrieves the next item from an iterator. /// /// Returns `None` when the iterator is exhausted. /// If an exception occurs, returns `Some(Err(..))`. /// Further `next()` calls after an exception occurs are likely /// to repeatedly result in the same exception. #[inline] fn next(&mut self) -> Option { Borrowed::from(&*self).next() } #[cfg(not(Py_LIMITED_API))] fn size_hint(&self) -> (usize, Option) { let hint = unsafe { ffi::PyObject_LengthHint(self.as_ptr(), 0) }; (hint.max(0) as usize, None) } } impl<'py> Borrowed<'_, 'py, PyIterator> { // TODO: this method is on Borrowed so that &'py PyIterator can use this; once that // implementation is deleted this method should be moved to the `Bound<'py, PyIterator> impl fn next(self) -> Option>> { let py = self.py(); match unsafe { ffi::PyIter_Next(self.as_ptr()).assume_owned_or_opt(py) } { Some(obj) => Some(Ok(obj)), None => PyErr::take(py).map(Err), } } } impl<'py> IntoIterator for &Bound<'py, PyIterator> { type Item = PyResult>; type IntoIter = Bound<'py, PyIterator>; fn into_iter(self) -> Self::IntoIter { self.clone() } } impl PyTypeCheck for PyIterator { const NAME: &'static str = "Iterator"; fn type_check(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::PyIter_Check(object.as_ptr()) != 0 } } } #[cfg(test)] mod tests { use super::PyIterator; #[cfg(all(not(PyPy), Py_3_10))] use super::PySendResult; use crate::exceptions::PyTypeError; #[cfg(all(not(PyPy), Py_3_10))] use crate::types::PyNone; use crate::types::{PyAnyMethods, PyDict, PyList, PyListMethods}; use crate::{ffi, IntoPyObject, Python}; #[test] fn vec_iter() { Python::with_gil(|py| { let inst = vec![10, 20].into_pyobject(py).unwrap(); let mut it = inst.try_iter().unwrap(); assert_eq!( 10_i32, it.next().unwrap().unwrap().extract::<'_, i32>().unwrap() ); assert_eq!( 20_i32, it.next().unwrap().unwrap().extract::<'_, i32>().unwrap() ); assert!(it.next().is_none()); }); } #[test] fn iter_refcnt() { let (obj, count) = Python::with_gil(|py| { let obj = vec![10, 20].into_pyobject(py).unwrap(); let count = obj.get_refcnt(); (obj.unbind(), count) }); Python::with_gil(|py| { let inst = obj.bind(py); let mut it = inst.try_iter().unwrap(); assert_eq!( 10_i32, it.next().unwrap().unwrap().extract::<'_, i32>().unwrap() ); }); Python::with_gil(move |py| { assert_eq!(count, obj.get_refcnt(py)); }); } #[test] fn iter_item_refcnt() { Python::with_gil(|py| { let count; let obj = py.eval(ffi::c_str!("object()"), None, None).unwrap(); let list = { let list = PyList::empty(py); list.append(10).unwrap(); list.append(&obj).unwrap(); count = obj.get_refcnt(); list }; { let mut it = list.iter(); assert_eq!(10_i32, it.next().unwrap().extract::<'_, i32>().unwrap()); assert!(it.next().unwrap().is(&obj)); assert!(it.next().is_none()); } assert_eq!(count, obj.get_refcnt()); }); } #[test] fn fibonacci_generator() { let fibonacci_generator = ffi::c_str!( r#" def fibonacci(target): a = 1 b = 1 for _ in range(target): yield a a, b = b, a + b "# ); Python::with_gil(|py| { let context = PyDict::new(py); py.run(fibonacci_generator, None, Some(&context)).unwrap(); let generator = py .eval(ffi::c_str!("fibonacci(5)"), None, Some(&context)) .unwrap(); for (actual, expected) in generator.try_iter().unwrap().zip(&[1, 1, 2, 3, 5]) { let actual = actual.unwrap().extract::().unwrap(); assert_eq!(actual, *expected) } }); } #[test] #[cfg(all(not(PyPy), Py_3_10))] fn send_generator() { let generator = ffi::c_str!( r#" def gen(): value = None while(True): value = yield value if value is None: return "# ); Python::with_gil(|py| { let context = PyDict::new(py); py.run(generator, None, Some(&context)).unwrap(); let generator = py.eval(ffi::c_str!("gen()"), None, Some(&context)).unwrap(); let one = 1i32.into_pyobject(py).unwrap(); assert!(matches!( generator.try_iter().unwrap().send(&PyNone::get(py)).unwrap(), PySendResult::Next(value) if value.is_none() )); assert!(matches!( generator.try_iter().unwrap().send(&one).unwrap(), PySendResult::Next(value) if value.is(&one) )); assert!(matches!( generator.try_iter().unwrap().send(&PyNone::get(py)).unwrap(), PySendResult::Return(value) if value.is_none() )); }); } #[test] fn fibonacci_generator_bound() { use crate::types::any::PyAnyMethods; use crate::Bound; let fibonacci_generator = ffi::c_str!( r#" def fibonacci(target): a = 1 b = 1 for _ in range(target): yield a a, b = b, a + b "# ); Python::with_gil(|py| { let context = PyDict::new(py); py.run(fibonacci_generator, None, Some(&context)).unwrap(); let generator: Bound<'_, PyIterator> = py .eval(ffi::c_str!("fibonacci(5)"), None, Some(&context)) .unwrap() .downcast_into() .unwrap(); let mut items = vec![]; for actual in &generator { let actual = actual.unwrap().extract::().unwrap(); items.push(actual); } assert_eq!(items, [1, 1, 2, 3, 5]); }); } #[test] fn int_not_iterable() { Python::with_gil(|py| { let x = 5i32.into_pyobject(py).unwrap(); let err = PyIterator::from_object(&x).unwrap_err(); assert!(err.is_instance_of::(py)); }); } #[test] #[cfg(feature = "macros")] fn python_class_not_iterator() { use crate::PyErr; #[crate::pyclass(crate = "crate")] struct Downcaster { failed: Option, } #[crate::pymethods(crate = "crate")] impl Downcaster { fn downcast_iterator(&mut self, obj: &crate::Bound<'_, crate::PyAny>) { self.failed = Some(obj.downcast::().unwrap_err().into()); } } // Regression test for 2913 Python::with_gil(|py| { let downcaster = crate::Py::new(py, Downcaster { failed: None }).unwrap(); crate::py_run!( py, downcaster, r#" from collections.abc import Sequence class MySequence(Sequence): def __init__(self): self._data = [1, 2, 3] def __getitem__(self, index): return self._data[index] def __len__(self): return len(self._data) downcaster.downcast_iterator(MySequence()) "# ); assert_eq!( downcaster.borrow_mut(py).failed.take().unwrap().to_string(), "TypeError: 'MySequence' object cannot be converted to 'Iterator'" ); }); } #[test] #[cfg(feature = "macros")] fn python_class_iterator() { #[crate::pyfunction(crate = "crate")] fn assert_iterator(obj: &crate::Bound<'_, crate::PyAny>) { assert!(obj.downcast::().is_ok()) } // Regression test for 2913 Python::with_gil(|py| { let assert_iterator = crate::wrap_pyfunction!(assert_iterator, py).unwrap(); crate::py_run!( py, assert_iterator, r#" class MyIter: def __next__(self): raise StopIteration assert_iterator(MyIter()) "# ); }); } #[test] #[cfg(not(Py_LIMITED_API))] fn length_hint_becomes_size_hint_lower_bound() { Python::with_gil(|py| { let list = py.eval(ffi::c_str!("[1, 2, 3]"), None, None).unwrap(); let iter = list.try_iter().unwrap(); let hint = iter.size_hint(); assert_eq!(hint, (3, None)); }); } } pyo3/src/types/frame.rs0000644000175000017500000000062615105742312014673 0ustar bdrungbdrunguse crate::ffi; use crate::PyAny; /// Represents a Python frame. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyFrame>`][crate::Bound]. #[repr(transparent)] pub struct PyFrame(PyAny); pyobject_native_type_core!( PyFrame, pyobject_native_static_type_object!(ffi::PyFrame_Type), #checkfunction=ffi::PyFrame_Check ); pyo3/src/types/function.rs0000644000175000017500000001506215105742312015426 0ustar bdrungbdrunguse crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; use crate::types::capsule::PyCapsuleMethods; use crate::types::module::PyModuleMethods; use crate::{ ffi, impl_::pymethods::{self, PyMethodDef}, types::{PyCapsule, PyDict, PyModule, PyString, PyTuple}, }; use crate::{Bound, Py, PyAny, PyResult, Python}; use std::cell::UnsafeCell; use std::ffi::CStr; /// Represents a builtin Python function object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyCFunction>`][Bound]. #[repr(transparent)] pub struct PyCFunction(PyAny); pyobject_native_type_core!(PyCFunction, pyobject_native_static_type_object!(ffi::PyCFunction_Type), #checkfunction=ffi::PyCFunction_Check); impl PyCFunction { /// Create a new built-in function with keywords (*args and/or **kwargs). /// /// To create `name` and `doc` static strings on Rust versions older than 1.77 (which added c"" literals), /// use the [`c_str!`](crate::ffi::c_str) macro. pub fn new_with_keywords<'py>( py: Python<'py>, fun: ffi::PyCFunctionWithKeywords, name: &'static CStr, doc: &'static CStr, module: Option<&Bound<'py, PyModule>>, ) -> PyResult> { Self::internal_new( py, &PyMethodDef::cfunction_with_keywords(name, fun, doc), module, ) } /// Create a new built-in function which takes no arguments. /// /// To create `name` and `doc` static strings on Rust versions older than 1.77 (which added c"" literals), /// use the [`c_str!`](crate::ffi::c_str) macro. pub fn new<'py>( py: Python<'py>, fun: ffi::PyCFunction, name: &'static CStr, doc: &'static CStr, module: Option<&Bound<'py, PyModule>>, ) -> PyResult> { Self::internal_new(py, &PyMethodDef::noargs(name, fun, doc), module) } /// Create a new function from a closure. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # use pyo3::{py_run, types::{PyCFunction, PyDict, PyTuple}}; /// /// Python::with_gil(|py| { /// let add_one = |args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>| -> PyResult<_> { /// let i = args.extract::<(i64,)>()?.0; /// Ok(i+1) /// }; /// let add_one = PyCFunction::new_closure(py, None, None, add_one).unwrap(); /// py_run!(py, add_one, "assert add_one(42) == 43"); /// }); /// ``` pub fn new_closure<'py, F, R>( py: Python<'py>, name: Option<&'static CStr>, doc: Option<&'static CStr>, closure: F, ) -> PyResult> where F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static, for<'p> R: crate::impl_::callback::IntoPyCallbackOutput<'p, *mut ffi::PyObject>, { let name = name.unwrap_or(ffi::c_str!("pyo3-closure")); let doc = doc.unwrap_or(ffi::c_str!("")); let method_def = pymethods::PyMethodDef::cfunction_with_keywords(name, run_closure::, doc); let def = method_def.as_method_def(); let capsule = PyCapsule::new( py, ClosureDestructor:: { closure, def: UnsafeCell::new(def), }, Some(CLOSURE_CAPSULE_NAME.to_owned()), )?; // Safety: just created the capsule with type ClosureDestructor above let data = unsafe { capsule.reference::>() }; unsafe { ffi::PyCFunction_NewEx(data.def.get(), capsule.as_ptr(), std::ptr::null_mut()) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[doc(hidden)] pub fn internal_new<'py>( py: Python<'py>, method_def: &PyMethodDef, module: Option<&Bound<'py, PyModule>>, ) -> PyResult> { let (mod_ptr, module_name): (_, Option>) = if let Some(m) = module { let mod_ptr = m.as_ptr(); (mod_ptr, Some(m.name()?.unbind())) } else { (std::ptr::null_mut(), None) }; let def = method_def.as_method_def(); // FIXME: stop leaking the def let def = Box::into_raw(Box::new(def)); let module_name_ptr = module_name .as_ref() .map_or(std::ptr::null_mut(), Py::as_ptr); unsafe { ffi::PyCFunction_NewEx(def, mod_ptr, module_name_ptr) .assume_owned_or_err(py) .downcast_into_unchecked() } } } static CLOSURE_CAPSULE_NAME: &CStr = ffi::c_str!("pyo3-closure"); unsafe extern "C" fn run_closure( capsule_ptr: *mut ffi::PyObject, args: *mut ffi::PyObject, kwargs: *mut ffi::PyObject, ) -> *mut ffi::PyObject where F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static, for<'py> R: crate::impl_::callback::IntoPyCallbackOutput<'py, *mut ffi::PyObject>, { use crate::types::any::PyAnyMethods; unsafe { crate::impl_::trampoline::cfunction_with_keywords( capsule_ptr, args, kwargs, |py, capsule_ptr, args, kwargs| { let boxed_fn: &ClosureDestructor = &*(ffi::PyCapsule_GetPointer(capsule_ptr, CLOSURE_CAPSULE_NAME.as_ptr()) as *mut ClosureDestructor); let args = Bound::ref_from_ptr(py, &args).downcast_unchecked::(); let kwargs = Bound::ref_from_ptr_or_opt(py, &kwargs) .as_ref() .map(|b| b.downcast_unchecked::()); let result = (boxed_fn.closure)(args, kwargs); crate::impl_::callback::convert(py, result) }, ) } } struct ClosureDestructor { closure: F, // Wrapped in UnsafeCell because Python C-API wants a *mut pointer // to this member. def: UnsafeCell, } // Safety: F is send and none of the fields are ever mutated unsafe impl Send for ClosureDestructor {} /// Represents a Python function object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyFunction>`][Bound]. #[repr(transparent)] #[cfg(not(Py_LIMITED_API))] pub struct PyFunction(PyAny); #[cfg(not(Py_LIMITED_API))] pyobject_native_type_core!(PyFunction, pyobject_native_static_type_object!(ffi::PyFunction_Type), #checkfunction=ffi::PyFunction_Check); pyo3/src/types/notimplemented.rs0000644000175000017500000000421615105742312016624 0ustar bdrungbdrunguse crate::{ ffi, ffi_ptr_ext::FfiPtrExt, types::any::PyAnyMethods, Borrowed, Bound, PyAny, PyTypeInfo, Python, }; /// Represents the Python `NotImplemented` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyNotImplemented>`][Bound]. #[repr(transparent)] pub struct PyNotImplemented(PyAny); pyobject_native_type_named!(PyNotImplemented); impl PyNotImplemented { /// Returns the `NotImplemented` object. #[inline] pub fn get(py: Python<'_>) -> Borrowed<'_, '_, PyNotImplemented> { unsafe { ffi::Py_NotImplemented() .assume_borrowed(py) .downcast_unchecked() } } } unsafe impl PyTypeInfo for PyNotImplemented { const NAME: &'static str = "NotImplementedType"; const MODULE: Option<&'static str> = None; fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject { unsafe { ffi::Py_TYPE(ffi::Py_NotImplemented()) } } #[inline] fn is_type_of(object: &Bound<'_, PyAny>) -> bool { // NotImplementedType is not usable as a base type Self::is_exact_type_of(object) } #[inline] fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool { object.is(&**Self::get(object.py())) } } #[cfg(test)] mod tests { use crate::types::any::PyAnyMethods; use crate::types::{PyDict, PyNotImplemented}; use crate::{PyTypeInfo, Python}; #[test] fn test_notimplemented_is_itself() { Python::with_gil(|py| { assert!(PyNotImplemented::get(py).is_instance_of::()); assert!(PyNotImplemented::get(py).is_exact_instance_of::()); }) } #[test] fn test_notimplemented_type_object_consistent() { Python::with_gil(|py| { assert!(PyNotImplemented::get(py) .get_type() .is(PyNotImplemented::type_object(py))); }) } #[test] fn test_dict_is_not_notimplemented() { Python::with_gil(|py| { assert!(PyDict::new(py).downcast::().is_err()); }) } } pyo3/src/types/any.rs0000644000175000017500000020563215105742312014374 0ustar bdrungbdrunguse crate::call::PyCallArgs; use crate::class::basic::CompareOp; use crate::conversion::{FromPyObjectBound, IntoPyObject}; use crate::err::{DowncastError, DowncastIntoError, PyErr, PyResult}; use crate::exceptions::{PyAttributeError, PyTypeError}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::internal::get_slot::TP_DESCR_GET; use crate::internal_tricks::ptr_from_ref; use crate::py_result_ext::PyResultExt; use crate::type_object::{PyTypeCheck, PyTypeInfo}; #[cfg(not(any(PyPy, GraalPy)))] use crate::types::PySuper; use crate::types::{PyDict, PyIterator, PyList, PyString, PyType}; use crate::{err, ffi, Borrowed, BoundObject, IntoPyObjectExt, Py, Python}; use std::cell::UnsafeCell; use std::cmp::Ordering; use std::os::raw::c_int; use std::ptr; /// Represents any Python object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyAny>`][Bound]. /// /// For APIs available on all Python objects, see the [`PyAnyMethods`] trait which is implemented for /// [`Bound<'py, PyAny>`][Bound]. /// /// See #[doc = concat!("[the guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/types.html#concrete-python-types)")] /// for an explanation of the different Python object types. #[repr(transparent)] pub struct PyAny(UnsafeCell); #[allow(non_snake_case)] // Copied here as the macro does not accept deprecated functions. // Originally ffi::object::PyObject_Check, but this is not in the Python C API. fn PyObject_Check(_: *mut ffi::PyObject) -> c_int { 1 } pyobject_native_type_info!( PyAny, pyobject_native_static_type_object!(ffi::PyBaseObject_Type), Some("builtins"), #checkfunction=PyObject_Check ); pyobject_native_type_sized!(PyAny, ffi::PyObject); // We cannot use `pyobject_subclassable_native_type!()` because it cfgs out on `Py_LIMITED_API`. impl crate::impl_::pyclass::PyClassBaseType for PyAny { type LayoutAsBase = crate::impl_::pycell::PyClassObjectBase; type BaseNativeType = PyAny; type Initializer = crate::impl_::pyclass_init::PyNativeTypeInitializer; type PyClassMutability = crate::pycell::impl_::ImmutableClass; } /// This trait represents the Python APIs which are usable on all Python objects. /// /// It is recommended you import this trait via `use pyo3::prelude::*` rather than /// by importing this trait directly. #[doc(alias = "PyAny")] pub trait PyAnyMethods<'py>: crate::sealed::Sealed { /// Returns whether `self` and `other` point to the same object. To compare /// the equality of two objects (the `==` operator), use [`eq`](PyAnyMethods::eq). /// /// This is equivalent to the Python expression `self is other`. fn is>>(&self, other: T) -> bool; /// Determines whether this object has the given attribute. /// /// This is equivalent to the Python expression `hasattr(self, attr_name)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn has_version(sys: &Bound<'_, PyModule>) -> PyResult { /// sys.hasattr(intern!(sys.py(), "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import("sys").unwrap(); /// # has_version(&sys).unwrap(); /// # }); /// ``` fn hasattr(&self, attr_name: N) -> PyResult where N: IntoPyObject<'py, Target = PyString>; /// Retrieves an attribute value. /// /// This is equivalent to the Python expression `self.attr_name`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn version<'py>(sys: &Bound<'py, PyModule>) -> PyResult> { /// sys.getattr(intern!(sys.py(), "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import("sys").unwrap(); /// # version(&sys).unwrap(); /// # }); /// ``` fn getattr(&self, attr_name: N) -> PyResult> where N: IntoPyObject<'py, Target = PyString>; /// Retrieves an attribute value optionally. /// /// This is equivalent to the Python expression `getattr(self, attr_name, None)`, which may /// be more efficient in some cases by simply returning `None` if the attribute is not found /// instead of raising `AttributeError`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. /// /// # Errors /// Returns `Err` if an exception other than `AttributeError` is raised during attribute lookup, /// such as a `ValueError` from a property or descriptor. /// /// # Example: Retrieving an optional attribute /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn get_version_if_exists<'py>(sys: &Bound<'py, PyModule>) -> PyResult>> { /// sys.getattr_opt(intern!(sys.py(), "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import("sys").unwrap(); /// # let version = get_version_if_exists(&sys).unwrap(); /// # assert!(version.is_some()); /// # }); /// ``` fn getattr_opt(&self, attr_name: N) -> PyResult>> where N: IntoPyObject<'py, Target = PyString>; /// Sets an attribute value. /// /// This is equivalent to the Python expression `self.attr_name = value`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn set_answer(ob: &Bound<'_, PyAny>) -> PyResult<()> { /// ob.setattr(intern!(ob.py(), "answer"), 42) /// } /// # /// # Python::with_gil(|py| { /// # let ob = PyModule::new(py, "empty").unwrap(); /// # set_answer(&ob).unwrap(); /// # }); /// ``` fn setattr(&self, attr_name: N, value: V) -> PyResult<()> where N: IntoPyObject<'py, Target = PyString>, V: IntoPyObject<'py>; /// Deletes an attribute. /// /// This is equivalent to the Python statement `del self.attr_name`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. fn delattr(&self, attr_name: N) -> PyResult<()> where N: IntoPyObject<'py, Target = PyString>; /// Returns an [`Ordering`] between `self` and `other`. /// /// This is equivalent to the following Python code: /// ```python /// if self == other: /// return Equal /// elif a < b: /// return Less /// elif a > b: /// return Greater /// else: /// raise TypeError("PyAny::compare(): All comparisons returned false") /// ``` /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyFloat; /// use std::cmp::Ordering; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a = PyFloat::new(py, 0_f64); /// let b = PyFloat::new(py, 42_f64); /// assert_eq!(a.compare(b)?, Ordering::Less); /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// It will return `PyErr` for values that cannot be compared: /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyFloat, PyString}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a = PyFloat::new(py, 0_f64); /// let b = PyString::new(py, "zero"); /// assert!(a.compare(b).is_err()); /// Ok(()) /// })?; /// # Ok(())} /// ``` fn compare(&self, other: O) -> PyResult where O: IntoPyObject<'py>; /// Tests whether two Python objects obey a given [`CompareOp`]. /// /// [`lt`](Self::lt), [`le`](Self::le), [`eq`](Self::eq), [`ne`](Self::ne), /// [`gt`](Self::gt) and [`ge`](Self::ge) are the specialized versions /// of this function. /// /// Depending on the value of `compare_op`, this is equivalent to one of the /// following Python expressions: /// /// | `compare_op` | Python expression | /// | :---: | :----: | /// | [`CompareOp::Eq`] | `self == other` | /// | [`CompareOp::Ne`] | `self != other` | /// | [`CompareOp::Lt`] | `self < other` | /// | [`CompareOp::Le`] | `self <= other` | /// | [`CompareOp::Gt`] | `self > other` | /// | [`CompareOp::Ge`] | `self >= other` | /// /// # Examples /// /// ```rust /// use pyo3::class::basic::CompareOp; /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a = 0_u8.into_pyobject(py)?; /// let b = 42_u8.into_pyobject(py)?; /// assert!(a.rich_compare(b, CompareOp::Le)?.is_truthy()?); /// Ok(()) /// })?; /// # Ok(())} /// ``` fn rich_compare(&self, other: O, compare_op: CompareOp) -> PyResult> where O: IntoPyObject<'py>; /// Computes the negative of self. /// /// Equivalent to the Python expression `-self`. fn neg(&self) -> PyResult>; /// Computes the positive of self. /// /// Equivalent to the Python expression `+self`. fn pos(&self) -> PyResult>; /// Computes the absolute of self. /// /// Equivalent to the Python expression `abs(self)`. fn abs(&self) -> PyResult>; /// Computes `~self`. fn bitnot(&self) -> PyResult>; /// Tests whether this object is less than another. /// /// This is equivalent to the Python expression `self < other`. fn lt(&self, other: O) -> PyResult where O: IntoPyObject<'py>; /// Tests whether this object is less than or equal to another. /// /// This is equivalent to the Python expression `self <= other`. fn le(&self, other: O) -> PyResult where O: IntoPyObject<'py>; /// Tests whether this object is equal to another. /// /// This is equivalent to the Python expression `self == other`. fn eq(&self, other: O) -> PyResult where O: IntoPyObject<'py>; /// Tests whether this object is not equal to another. /// /// This is equivalent to the Python expression `self != other`. fn ne(&self, other: O) -> PyResult where O: IntoPyObject<'py>; /// Tests whether this object is greater than another. /// /// This is equivalent to the Python expression `self > other`. fn gt(&self, other: O) -> PyResult where O: IntoPyObject<'py>; /// Tests whether this object is greater than or equal to another. /// /// This is equivalent to the Python expression `self >= other`. fn ge(&self, other: O) -> PyResult where O: IntoPyObject<'py>; /// Computes `self + other`. fn add(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self - other`. fn sub(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self * other`. fn mul(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self @ other`. fn matmul(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self / other`. fn div(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self // other`. fn floor_div(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self % other`. fn rem(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `divmod(self, other)`. fn divmod(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self << other`. fn lshift(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self >> other`. fn rshift(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self ** other % modulus` (`pow(self, other, modulus)`). /// `py.None()` may be passed for the `modulus`. fn pow(&self, other: O1, modulus: O2) -> PyResult> where O1: IntoPyObject<'py>, O2: IntoPyObject<'py>; /// Computes `self & other`. fn bitand(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self | other`. fn bitor(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Computes `self ^ other`. fn bitxor(&self, other: O) -> PyResult> where O: IntoPyObject<'py>; /// Determines whether this object appears callable. /// /// This is equivalent to Python's [`callable()`][1] function. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let builtins = PyModule::import(py, "builtins")?; /// let print = builtins.getattr("print")?; /// assert!(print.is_callable()); /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// This is equivalent to the Python statement `assert callable(print)`. /// /// Note that unless an API needs to distinguish between callable and /// non-callable objects, there is no point in checking for callability. /// Instead, it is better to just do the call and handle potential /// exceptions. /// /// [1]: https://docs.python.org/3/library/functions.html#callable fn is_callable(&self) -> bool; /// Calls the object. /// /// This is equivalent to the Python expression `self(*args, **kwargs)`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// use pyo3_ffi::c_str; /// use std::ffi::CStr; /// /// const CODE: &CStr = c_str!(r#" /// def function(*args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {"cruel": "world"} /// return "called with args and kwargs" /// "#); /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code(py, CODE, c_str!(""), c_str!(""))?; /// let fun = module.getattr("function")?; /// let args = ("hello",); /// let kwargs = PyDict::new(py); /// kwargs.set_item("cruel", "world")?; /// let result = fun.call(args, Some(&kwargs))?; /// assert_eq!(result.extract::()?, "called with args and kwargs"); /// Ok(()) /// }) /// # } /// ``` fn call(&self, args: A, kwargs: Option<&Bound<'py, PyDict>>) -> PyResult> where A: PyCallArgs<'py>; /// Calls the object without arguments. /// /// This is equivalent to the Python expression `self()`. /// /// # Examples /// /// ```no_run /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let module = PyModule::import(py, "builtins")?; /// let help = module.getattr("help")?; /// help.call0()?; /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// This is equivalent to the Python expression `help()`. fn call0(&self) -> PyResult>; /// Calls the object with only positional arguments. /// /// This is equivalent to the Python expression `self(*args)`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3_ffi::c_str; /// use std::ffi::CStr; /// /// const CODE: &CStr = c_str!(r#" /// def function(*args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {} /// return "called with args" /// "#); /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code(py, CODE, c_str!(""), c_str!(""))?; /// let fun = module.getattr("function")?; /// let args = ("hello",); /// let result = fun.call1(args)?; /// assert_eq!(result.extract::()?, "called with args"); /// Ok(()) /// }) /// # } /// ``` fn call1(&self, args: A) -> PyResult> where A: PyCallArgs<'py>; /// Calls a method on the object. /// /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// use pyo3_ffi::c_str; /// use std::ffi::CStr; /// /// const CODE: &CStr = c_str!(r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {"cruel": "world"} /// return "called with args and kwargs" /// a = A() /// "#); /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code(py, CODE, c_str!(""), c_str!(""))?; /// let instance = module.getattr("a")?; /// let args = ("hello",); /// let kwargs = PyDict::new(py); /// kwargs.set_item("cruel", "world")?; /// let result = instance.call_method("method", args, Some(&kwargs))?; /// assert_eq!(result.extract::()?, "called with args and kwargs"); /// Ok(()) /// }) /// # } /// ``` fn call_method( &self, name: N, args: A, kwargs: Option<&Bound<'py, PyDict>>, ) -> PyResult> where N: IntoPyObject<'py, Target = PyString>, A: PyCallArgs<'py>; /// Calls a method on the object without arguments. /// /// This is equivalent to the Python expression `self.name()`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3_ffi::c_str; /// use std::ffi::CStr; /// /// const CODE: &CStr = c_str!(r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == () /// assert kwargs == {} /// return "called with no arguments" /// a = A() /// "#); /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code(py, CODE, c_str!(""), c_str!(""))?; /// let instance = module.getattr("a")?; /// let result = instance.call_method0("method")?; /// assert_eq!(result.extract::()?, "called with no arguments"); /// Ok(()) /// }) /// # } /// ``` fn call_method0(&self, name: N) -> PyResult> where N: IntoPyObject<'py, Target = PyString>; /// Calls a method on the object with only positional arguments. /// /// This is equivalent to the Python expression `self.name(*args)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3_ffi::c_str; /// use std::ffi::CStr; /// /// const CODE: &CStr = c_str!(r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {} /// return "called with args" /// a = A() /// "#); /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code(py, CODE, c_str!(""), c_str!(""))?; /// let instance = module.getattr("a")?; /// let args = ("hello",); /// let result = instance.call_method1("method", args)?; /// assert_eq!(result.extract::()?, "called with args"); /// Ok(()) /// }) /// # } /// ``` fn call_method1(&self, name: N, args: A) -> PyResult> where N: IntoPyObject<'py, Target = PyString>, A: PyCallArgs<'py>; /// Returns whether the object is considered to be true. /// /// This is equivalent to the Python expression `bool(self)`. fn is_truthy(&self) -> PyResult; /// Returns whether the object is considered to be None. /// /// This is equivalent to the Python expression `self is None`. fn is_none(&self) -> bool; /// Returns true if the sequence or mapping has a length of 0. /// /// This is equivalent to the Python expression `len(self) == 0`. fn is_empty(&self) -> PyResult; /// Gets an item from the collection. /// /// This is equivalent to the Python expression `self[key]`. fn get_item(&self, key: K) -> PyResult> where K: IntoPyObject<'py>; /// Sets a collection item value. /// /// This is equivalent to the Python expression `self[key] = value`. fn set_item(&self, key: K, value: V) -> PyResult<()> where K: IntoPyObject<'py>, V: IntoPyObject<'py>; /// Deletes an item from the collection. /// /// This is equivalent to the Python expression `del self[key]`. fn del_item(&self, key: K) -> PyResult<()> where K: IntoPyObject<'py>; /// Takes an object and returns an iterator for it. Returns an error if the object is not /// iterable. /// /// This is typically a new iterator but if the argument is an iterator, /// this returns itself. /// /// # Example: Checking a Python object for iterability /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyAny, PyNone}; /// /// fn is_iterable(obj: &Bound<'_, PyAny>) -> bool { /// match obj.try_iter() { /// Ok(_) => true, /// Err(_) => false, /// } /// } /// /// Python::with_gil(|py| { /// assert!(is_iterable(&vec![1, 2, 3].into_pyobject(py).unwrap())); /// assert!(!is_iterable(&PyNone::get(py))); /// }); /// ``` fn try_iter(&self) -> PyResult>; /// Returns the Python type object for this object's type. fn get_type(&self) -> Bound<'py, PyType>; /// Returns the Python type pointer for this object. fn get_type_ptr(&self) -> *mut ffi::PyTypeObject; /// Downcast this `PyAny` to a concrete Python type or pyclass. /// /// Note that you can often avoid downcasting yourself by just specifying /// the desired type in function or method signatures. /// However, manual downcasting is sometimes necessary. /// /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). /// /// # Example: Downcasting to a specific Python object /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { /// let dict = PyDict::new(py); /// assert!(dict.is_instance_of::()); /// let any = dict.as_any(); /// /// assert!(any.downcast::().is_ok()); /// assert!(any.downcast::().is_err()); /// }); /// ``` /// /// # Example: Getting a reference to a pyclass /// /// This is useful if you want to mutate a `PyObject` that /// might actually be a pyclass. /// /// ```rust /// # fn main() -> Result<(), pyo3::PyErr> { /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Class { /// i: i32, /// } /// /// Python::with_gil(|py| { /// let class = Py::new(py, Class { i: 0 }).unwrap().into_bound(py).into_any(); /// /// let class_bound: &Bound<'_, Class> = class.downcast()?; /// /// class_bound.borrow_mut().i += 1; /// /// // Alternatively you can get a `PyRefMut` directly /// let class_ref: PyRefMut<'_, Class> = class.extract()?; /// assert_eq!(class_ref.i, 1); /// Ok(()) /// }) /// # } /// ``` fn downcast(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeCheck; /// Like `downcast` but takes ownership of `self`. /// /// In case of an error, it is possible to retrieve `self` again via [`DowncastIntoError::into_inner`]. /// /// # Example /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { /// let obj: Bound<'_, PyAny> = PyDict::new(py).into_any(); /// /// let obj: Bound<'_, PyAny> = match obj.downcast_into::() { /// Ok(_) => panic!("obj should not be a list"), /// Err(err) => err.into_inner(), /// }; /// /// // obj is a dictionary /// assert!(obj.downcast_into::().is_ok()); /// }) /// ``` fn downcast_into(self) -> Result, DowncastIntoError<'py>> where T: PyTypeCheck; /// Downcast this `PyAny` to a concrete Python type or pyclass (but not a subclass of it). /// /// It is almost always better to use [`PyAnyMethods::downcast`] because it accounts for Python /// subtyping. Use this method only when you do not want to allow subtypes. /// /// The advantage of this method over [`PyAnyMethods::downcast`] is that it is faster. The implementation /// of `downcast_exact` uses the equivalent of the Python expression `type(self) is T`, whereas /// `downcast` uses `isinstance(self, T)`. /// /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). /// /// # Example: Downcasting to a specific Python object but not a subtype /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyBool, PyInt}; /// /// Python::with_gil(|py| { /// let b = PyBool::new(py, true); /// assert!(b.is_instance_of::()); /// let any: &Bound<'_, PyAny> = b.as_any(); /// /// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int` /// // but `downcast_exact` will not. /// assert!(any.downcast::().is_ok()); /// assert!(any.downcast_exact::().is_err()); /// /// assert!(any.downcast_exact::().is_ok()); /// }); /// ``` fn downcast_exact(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeInfo; /// Like `downcast_exact` but takes ownership of `self`. fn downcast_into_exact(self) -> Result, DowncastIntoError<'py>> where T: PyTypeInfo; /// Converts this `PyAny` to a concrete Python type without checking validity. /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. unsafe fn downcast_unchecked(&self) -> &Bound<'py, T>; /// Like `downcast_unchecked` but takes ownership of `self`. /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. unsafe fn downcast_into_unchecked(self) -> Bound<'py, T>; /// Extracts some type from the Python object. /// /// This is a wrapper function around /// [`FromPyObject::extract_bound()`](crate::FromPyObject::extract_bound). fn extract<'a, T>(&'a self) -> PyResult where T: FromPyObjectBound<'a, 'py>; /// Returns the reference count for the Python object. fn get_refcnt(&self) -> isize; /// Computes the "repr" representation of self. /// /// This is equivalent to the Python expression `repr(self)`. fn repr(&self) -> PyResult>; /// Computes the "str" representation of self. /// /// This is equivalent to the Python expression `str(self)`. fn str(&self) -> PyResult>; /// Retrieves the hash code of self. /// /// This is equivalent to the Python expression `hash(self)`. fn hash(&self) -> PyResult; /// Returns the length of the sequence or mapping. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> PyResult; /// Returns the list of attributes of this object. /// /// This is equivalent to the Python expression `dir(self)`. fn dir(&self) -> PyResult>; /// Checks whether this object is an instance of type `ty`. /// /// This is equivalent to the Python expression `isinstance(self, ty)`. fn is_instance(&self, ty: &Bound<'py, PyAny>) -> PyResult; /// Checks whether this object is an instance of exactly type `ty` (not a subclass). /// /// This is equivalent to the Python expression `type(self) is ty`. fn is_exact_instance(&self, ty: &Bound<'py, PyAny>) -> bool; /// Checks whether this object is an instance of type `T`. /// /// This is equivalent to the Python expression `isinstance(self, T)`, /// if the type `T` is known at compile time. fn is_instance_of(&self) -> bool; /// Checks whether this object is an instance of exactly type `T`. /// /// This is equivalent to the Python expression `type(self) is T`, /// if the type `T` is known at compile time. fn is_exact_instance_of(&self) -> bool; /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. fn contains(&self, value: V) -> PyResult where V: IntoPyObject<'py>; /// Return a proxy object that delegates method calls to a parent or sibling class of type. /// /// This is equivalent to the Python expression `super()` #[cfg(not(any(PyPy, GraalPy)))] fn py_super(&self) -> PyResult>; } macro_rules! implement_binop { ($name:ident, $c_api:ident, $op:expr) => { #[doc = concat!("Computes `self ", $op, " other`.")] fn $name(&self, other: O) -> PyResult> where O: IntoPyObject<'py>, { fn inner<'py>( any: &Bound<'py, PyAny>, other: Borrowed<'_, 'py, PyAny>, ) -> PyResult> { unsafe { ffi::$c_api(any.as_ptr(), other.as_ptr()).assume_owned_or_err(any.py()) } } let py = self.py(); inner( self, other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } }; } impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { #[inline] fn is>>(&self, other: T) -> bool { ptr::eq(self.as_ptr(), other.as_ref().as_ptr()) } fn hasattr(&self, attr_name: N) -> PyResult where N: IntoPyObject<'py, Target = PyString>, { // PyObject_HasAttr suppresses all exceptions, which was the behaviour of `hasattr` in Python 2. // Use an implementation which suppresses only AttributeError, which is consistent with `hasattr` in Python 3. fn inner(py: Python<'_>, getattr_result: PyResult>) -> PyResult { match getattr_result { Ok(_) => Ok(true), Err(err) if err.is_instance_of::(py) => Ok(false), Err(e) => Err(e), } } inner(self.py(), self.getattr(attr_name)) } fn getattr(&self, attr_name: N) -> PyResult> where N: IntoPyObject<'py, Target = PyString>, { fn inner<'py>( any: &Bound<'py, PyAny>, attr_name: Borrowed<'_, '_, PyString>, ) -> PyResult> { unsafe { ffi::PyObject_GetAttr(any.as_ptr(), attr_name.as_ptr()) .assume_owned_or_err(any.py()) } } inner( self, attr_name .into_pyobject(self.py()) .map_err(Into::into)? .as_borrowed(), ) } fn getattr_opt(&self, attr_name: N) -> PyResult>> where N: IntoPyObject<'py, Target = PyString>, { fn inner<'py>( any: &Bound<'py, PyAny>, attr_name: Borrowed<'_, 'py, PyString>, ) -> PyResult>> { #[cfg(Py_3_13)] { let mut resp_ptr: *mut ffi::PyObject = std::ptr::null_mut(); match unsafe { ffi::PyObject_GetOptionalAttr(any.as_ptr(), attr_name.as_ptr(), &mut resp_ptr) } { // Attribute found, result is a new strong reference 1 => { let bound = unsafe { Bound::from_owned_ptr(any.py(), resp_ptr) }; Ok(Some(bound)) } // Attribute not found, result is NULL 0 => Ok(None), // An error occurred (other than AttributeError) _ => Err(PyErr::fetch(any.py())), } } #[cfg(not(Py_3_13))] { match any.getattr(attr_name) { Ok(bound) => Ok(Some(bound)), Err(err) => { let err_type = err .get_type(any.py()) .is(PyType::new::(any.py())); match err_type { true => Ok(None), false => Err(err), } } } } } let py = self.py(); inner(self, attr_name.into_pyobject_or_pyerr(py)?.as_borrowed()) } fn setattr(&self, attr_name: N, value: V) -> PyResult<()> where N: IntoPyObject<'py, Target = PyString>, V: IntoPyObject<'py>, { fn inner( any: &Bound<'_, PyAny>, attr_name: Borrowed<'_, '_, PyString>, value: Borrowed<'_, '_, PyAny>, ) -> PyResult<()> { err::error_on_minusone(any.py(), unsafe { ffi::PyObject_SetAttr(any.as_ptr(), attr_name.as_ptr(), value.as_ptr()) }) } let py = self.py(); inner( self, attr_name.into_pyobject_or_pyerr(py)?.as_borrowed(), value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn delattr(&self, attr_name: N) -> PyResult<()> where N: IntoPyObject<'py, Target = PyString>, { fn inner(any: &Bound<'_, PyAny>, attr_name: Borrowed<'_, '_, PyString>) -> PyResult<()> { err::error_on_minusone(any.py(), unsafe { ffi::PyObject_DelAttr(any.as_ptr(), attr_name.as_ptr()) }) } let py = self.py(); inner(self, attr_name.into_pyobject_or_pyerr(py)?.as_borrowed()) } fn compare(&self, other: O) -> PyResult where O: IntoPyObject<'py>, { fn inner(any: &Bound<'_, PyAny>, other: Borrowed<'_, '_, PyAny>) -> PyResult { let other = other.as_ptr(); // Almost the same as ffi::PyObject_RichCompareBool, but this one doesn't try self == other. // See https://github.com/PyO3/pyo3/issues/985 for more. let do_compare = |other, op| unsafe { ffi::PyObject_RichCompare(any.as_ptr(), other, op) .assume_owned_or_err(any.py()) .and_then(|obj| obj.is_truthy()) }; if do_compare(other, ffi::Py_EQ)? { Ok(Ordering::Equal) } else if do_compare(other, ffi::Py_LT)? { Ok(Ordering::Less) } else if do_compare(other, ffi::Py_GT)? { Ok(Ordering::Greater) } else { Err(PyTypeError::new_err( "PyAny::compare(): All comparisons returned false", )) } } let py = self.py(); inner( self, other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn rich_compare(&self, other: O, compare_op: CompareOp) -> PyResult> where O: IntoPyObject<'py>, { fn inner<'py>( any: &Bound<'py, PyAny>, other: Borrowed<'_, 'py, PyAny>, compare_op: CompareOp, ) -> PyResult> { unsafe { ffi::PyObject_RichCompare(any.as_ptr(), other.as_ptr(), compare_op as c_int) .assume_owned_or_err(any.py()) } } let py = self.py(); inner( self, other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), compare_op, ) } fn neg(&self) -> PyResult> { unsafe { ffi::PyNumber_Negative(self.as_ptr()).assume_owned_or_err(self.py()) } } fn pos(&self) -> PyResult> { fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyNumber_Positive(any.as_ptr()).assume_owned_or_err(any.py()) } } inner(self) } fn abs(&self) -> PyResult> { fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyNumber_Absolute(any.as_ptr()).assume_owned_or_err(any.py()) } } inner(self) } fn bitnot(&self) -> PyResult> { fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyNumber_Invert(any.as_ptr()).assume_owned_or_err(any.py()) } } inner(self) } fn lt(&self, other: O) -> PyResult where O: IntoPyObject<'py>, { self.rich_compare(other, CompareOp::Lt) .and_then(|any| any.is_truthy()) } fn le(&self, other: O) -> PyResult where O: IntoPyObject<'py>, { self.rich_compare(other, CompareOp::Le) .and_then(|any| any.is_truthy()) } fn eq(&self, other: O) -> PyResult where O: IntoPyObject<'py>, { self.rich_compare(other, CompareOp::Eq) .and_then(|any| any.is_truthy()) } fn ne(&self, other: O) -> PyResult where O: IntoPyObject<'py>, { self.rich_compare(other, CompareOp::Ne) .and_then(|any| any.is_truthy()) } fn gt(&self, other: O) -> PyResult where O: IntoPyObject<'py>, { self.rich_compare(other, CompareOp::Gt) .and_then(|any| any.is_truthy()) } fn ge(&self, other: O) -> PyResult where O: IntoPyObject<'py>, { self.rich_compare(other, CompareOp::Ge) .and_then(|any| any.is_truthy()) } implement_binop!(add, PyNumber_Add, "+"); implement_binop!(sub, PyNumber_Subtract, "-"); implement_binop!(mul, PyNumber_Multiply, "*"); implement_binop!(matmul, PyNumber_MatrixMultiply, "@"); implement_binop!(div, PyNumber_TrueDivide, "/"); implement_binop!(floor_div, PyNumber_FloorDivide, "//"); implement_binop!(rem, PyNumber_Remainder, "%"); implement_binop!(lshift, PyNumber_Lshift, "<<"); implement_binop!(rshift, PyNumber_Rshift, ">>"); implement_binop!(bitand, PyNumber_And, "&"); implement_binop!(bitor, PyNumber_Or, "|"); implement_binop!(bitxor, PyNumber_Xor, "^"); /// Computes `divmod(self, other)`. fn divmod(&self, other: O) -> PyResult> where O: IntoPyObject<'py>, { fn inner<'py>( any: &Bound<'py, PyAny>, other: Borrowed<'_, 'py, PyAny>, ) -> PyResult> { unsafe { ffi::PyNumber_Divmod(any.as_ptr(), other.as_ptr()).assume_owned_or_err(any.py()) } } let py = self.py(); inner( self, other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } /// Computes `self ** other % modulus` (`pow(self, other, modulus)`). /// `py.None()` may be passed for the `modulus`. fn pow(&self, other: O1, modulus: O2) -> PyResult> where O1: IntoPyObject<'py>, O2: IntoPyObject<'py>, { fn inner<'py>( any: &Bound<'py, PyAny>, other: Borrowed<'_, 'py, PyAny>, modulus: Borrowed<'_, 'py, PyAny>, ) -> PyResult> { unsafe { ffi::PyNumber_Power(any.as_ptr(), other.as_ptr(), modulus.as_ptr()) .assume_owned_or_err(any.py()) } } let py = self.py(); inner( self, other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), modulus.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn is_callable(&self) -> bool { unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 } } fn call(&self, args: A, kwargs: Option<&Bound<'py, PyDict>>) -> PyResult> where A: PyCallArgs<'py>, { if let Some(kwargs) = kwargs { args.call( self.as_borrowed(), kwargs.as_borrowed(), crate::call::private::Token, ) } else { args.call_positional(self.as_borrowed(), crate::call::private::Token) } } #[inline] fn call0(&self) -> PyResult> { unsafe { ffi::compat::PyObject_CallNoArgs(self.as_ptr()).assume_owned_or_err(self.py()) } } fn call1(&self, args: A) -> PyResult> where A: PyCallArgs<'py>, { args.call_positional(self.as_borrowed(), crate::call::private::Token) } #[inline] fn call_method( &self, name: N, args: A, kwargs: Option<&Bound<'py, PyDict>>, ) -> PyResult> where N: IntoPyObject<'py, Target = PyString>, A: PyCallArgs<'py>, { if kwargs.is_none() { self.call_method1(name, args) } else { self.getattr(name) .and_then(|method| method.call(args, kwargs)) } } #[inline] fn call_method0(&self, name: N) -> PyResult> where N: IntoPyObject<'py, Target = PyString>, { let py = self.py(); let name = name.into_pyobject_or_pyerr(py)?.into_bound(); unsafe { ffi::compat::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr()) .assume_owned_or_err(py) } } fn call_method1(&self, name: N, args: A) -> PyResult> where N: IntoPyObject<'py, Target = PyString>, A: PyCallArgs<'py>, { let name = name.into_pyobject_or_pyerr(self.py())?; args.call_method_positional( self.as_borrowed(), name.as_borrowed(), crate::call::private::Token, ) } fn is_truthy(&self) -> PyResult { let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; err::error_on_minusone(self.py(), v)?; Ok(v != 0) } #[inline] fn is_none(&self) -> bool { unsafe { ptr::eq(ffi::Py_None(), self.as_ptr()) } } fn is_empty(&self) -> PyResult { self.len().map(|l| l == 0) } fn get_item(&self, key: K) -> PyResult> where K: IntoPyObject<'py>, { fn inner<'py>( any: &Bound<'py, PyAny>, key: Borrowed<'_, 'py, PyAny>, ) -> PyResult> { unsafe { ffi::PyObject_GetItem(any.as_ptr(), key.as_ptr()).assume_owned_or_err(any.py()) } } let py = self.py(); inner( self, key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn set_item(&self, key: K, value: V) -> PyResult<()> where K: IntoPyObject<'py>, V: IntoPyObject<'py>, { fn inner( any: &Bound<'_, PyAny>, key: Borrowed<'_, '_, PyAny>, value: Borrowed<'_, '_, PyAny>, ) -> PyResult<()> { err::error_on_minusone(any.py(), unsafe { ffi::PyObject_SetItem(any.as_ptr(), key.as_ptr(), value.as_ptr()) }) } let py = self.py(); inner( self, key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn del_item(&self, key: K) -> PyResult<()> where K: IntoPyObject<'py>, { fn inner(any: &Bound<'_, PyAny>, key: Borrowed<'_, '_, PyAny>) -> PyResult<()> { err::error_on_minusone(any.py(), unsafe { ffi::PyObject_DelItem(any.as_ptr(), key.as_ptr()) }) } let py = self.py(); inner( self, key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } fn try_iter(&self) -> PyResult> { PyIterator::from_object(self) } fn get_type(&self) -> Bound<'py, PyType> { unsafe { PyType::from_borrowed_type_ptr(self.py(), ffi::Py_TYPE(self.as_ptr())) } } #[inline] fn get_type_ptr(&self) -> *mut ffi::PyTypeObject { unsafe { ffi::Py_TYPE(self.as_ptr()) } } #[inline] fn downcast(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeCheck, { if T::type_check(self) { // Safety: type_check is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_unchecked() }) } else { Err(DowncastError::new(self, T::NAME)) } } #[inline] fn downcast_into(self) -> Result, DowncastIntoError<'py>> where T: PyTypeCheck, { if T::type_check(&self) { // Safety: type_check is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_into_unchecked() }) } else { Err(DowncastIntoError::new(self, T::NAME)) } } #[inline] fn downcast_exact(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeInfo, { if self.is_exact_instance_of::() { // Safety: is_exact_instance_of is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_unchecked() }) } else { Err(DowncastError::new(self, T::NAME)) } } #[inline] fn downcast_into_exact(self) -> Result, DowncastIntoError<'py>> where T: PyTypeInfo, { if self.is_exact_instance_of::() { // Safety: is_exact_instance_of is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_into_unchecked() }) } else { Err(DowncastIntoError::new(self, T::NAME)) } } #[inline] unsafe fn downcast_unchecked(&self) -> &Bound<'py, T> { unsafe { &*ptr_from_ref(self).cast() } } #[inline] unsafe fn downcast_into_unchecked(self) -> Bound<'py, T> { unsafe { std::mem::transmute(self) } } fn extract<'a, T>(&'a self) -> PyResult where T: FromPyObjectBound<'a, 'py>, { FromPyObjectBound::from_py_object_bound(self.as_borrowed()) } fn get_refcnt(&self) -> isize { unsafe { ffi::Py_REFCNT(self.as_ptr()) } } fn repr(&self) -> PyResult> { unsafe { ffi::PyObject_Repr(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } fn str(&self) -> PyResult> { unsafe { ffi::PyObject_Str(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } fn hash(&self) -> PyResult { let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) }; crate::err::error_on_minusone(self.py(), v)?; Ok(v) } fn len(&self) -> PyResult { let v = unsafe { ffi::PyObject_Size(self.as_ptr()) }; crate::err::error_on_minusone(self.py(), v)?; Ok(v as usize) } fn dir(&self) -> PyResult> { unsafe { ffi::PyObject_Dir(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn is_instance(&self, ty: &Bound<'py, PyAny>) -> PyResult { let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), ty.as_ptr()) }; err::error_on_minusone(self.py(), result)?; Ok(result == 1) } #[inline] fn is_exact_instance(&self, ty: &Bound<'py, PyAny>) -> bool { self.get_type().is(ty) } #[inline] fn is_instance_of(&self) -> bool { T::is_type_of(self) } #[inline] fn is_exact_instance_of(&self) -> bool { T::is_exact_type_of(self) } fn contains(&self, value: V) -> PyResult where V: IntoPyObject<'py>, { fn inner(any: &Bound<'_, PyAny>, value: Borrowed<'_, '_, PyAny>) -> PyResult { match unsafe { ffi::PySequence_Contains(any.as_ptr(), value.as_ptr()) } { 0 => Ok(false), 1 => Ok(true), _ => Err(PyErr::fetch(any.py())), } } let py = self.py(); inner( self, value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(), ) } #[cfg(not(any(PyPy, GraalPy)))] fn py_super(&self) -> PyResult> { PySuper::new(&self.get_type(), self) } } impl<'py> Bound<'py, PyAny> { /// Retrieve an attribute value, skipping the instance dictionary during the lookup but still /// binding the object to the instance. /// /// This is useful when trying to resolve Python's "magic" methods like `__getitem__`, which /// are looked up starting from the type object. This returns an `Option` as it is not /// typically a direct error for the special lookup to fail, as magic methods are optional in /// many situations in which they might be called. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. #[allow(dead_code)] // Currently only used with num-complex+abi3, so dead without that. pub(crate) fn lookup_special(&self, attr_name: N) -> PyResult>> where N: IntoPyObject<'py, Target = PyString>, { let py = self.py(); let self_type = self.get_type(); let attr = if let Ok(attr) = self_type.getattr(attr_name) { attr } else { return Ok(None); }; // Manually resolve descriptor protocol. (Faster than going through Python.) if let Some(descr_get) = attr.get_type().get_slot(TP_DESCR_GET) { // attribute is a descriptor, resolve it unsafe { descr_get(attr.as_ptr(), self.as_ptr(), self_type.as_ptr()) .assume_owned_or_err(py) .map(Some) } } else { Ok(Some(attr)) } } } #[cfg(test)] mod tests { use crate::{ basic::CompareOp, ffi, tests::common::generate_unique_module_name, types::{IntoPyDict, PyAny, PyAnyMethods, PyBool, PyInt, PyList, PyModule, PyTypeMethods}, Bound, BoundObject, IntoPyObject, PyTypeInfo, Python, }; use pyo3_ffi::c_str; use std::fmt::Debug; #[test] fn test_lookup_special() { Python::with_gil(|py| { let module = PyModule::from_code( py, c_str!( r#" class CustomCallable: def __call__(self): return 1 class SimpleInt: def __int__(self): return 1 class InheritedInt(SimpleInt): pass class NoInt: pass class NoDescriptorInt: __int__ = CustomCallable() class InstanceOverrideInt: def __int__(self): return 1 instance_override = InstanceOverrideInt() instance_override.__int__ = lambda self: 2 class ErrorInDescriptorInt: @property def __int__(self): raise ValueError("uh-oh!") class NonHeapNonDescriptorInt: # A static-typed callable that doesn't implement `__get__`. These are pretty hard to come by. __int__ = int "# ), c_str!("test.py"), &generate_unique_module_name("test"), ) .unwrap(); let int = crate::intern!(py, "__int__"); let eval_int = |obj: Bound<'_, PyAny>| obj.lookup_special(int)?.unwrap().call0()?.extract::(); let simple = module.getattr("SimpleInt").unwrap().call0().unwrap(); assert_eq!(eval_int(simple).unwrap(), 1); let inherited = module.getattr("InheritedInt").unwrap().call0().unwrap(); assert_eq!(eval_int(inherited).unwrap(), 1); let no_descriptor = module.getattr("NoDescriptorInt").unwrap().call0().unwrap(); assert_eq!(eval_int(no_descriptor).unwrap(), 1); let missing = module.getattr("NoInt").unwrap().call0().unwrap(); assert!(missing.lookup_special(int).unwrap().is_none()); // Note the instance override should _not_ call the instance method that returns 2, // because that's not how special lookups are meant to work. let instance_override = module.getattr("instance_override").unwrap(); assert_eq!(eval_int(instance_override).unwrap(), 1); let descriptor_error = module .getattr("ErrorInDescriptorInt") .unwrap() .call0() .unwrap(); assert!(descriptor_error.lookup_special(int).is_err()); let nonheap_nondescriptor = module .getattr("NonHeapNonDescriptorInt") .unwrap() .call0() .unwrap(); assert_eq!(eval_int(nonheap_nondescriptor).unwrap(), 0); }) } #[test] fn test_getattr_opt() { Python::with_gil(|py| { let module = PyModule::from_code( py, c_str!( r#" class Test: class_str_attribute = "class_string" @property def error(self): raise ValueError("This is an intentional error") "# ), c_str!("test.py"), &generate_unique_module_name("test"), ) .unwrap(); // Get the class Test let class_test = module.getattr_opt("Test").unwrap().unwrap(); // Test attribute that exist let cls_attr_str = class_test .getattr_opt("class_str_attribute") .unwrap() .unwrap(); assert_eq!(cls_attr_str.extract::().unwrap(), "class_string"); // Test non-existent attribute let do_not_exist = class_test.getattr_opt("doNotExist").unwrap(); assert!(do_not_exist.is_none()); // Test error attribute let instance = class_test.call0().unwrap(); let error = instance.getattr_opt("error"); assert!(error.is_err()); assert!(error .unwrap_err() .to_string() .contains("This is an intentional error")); }); } #[test] fn test_call_for_non_existing_method() { Python::with_gil(|py| { let a = py.eval(ffi::c_str!("42"), None, None).unwrap(); a.call_method0("__str__").unwrap(); // ok assert!(a.call_method("nonexistent_method", (1,), None).is_err()); assert!(a.call_method0("nonexistent_method").is_err()); assert!(a.call_method1("nonexistent_method", (1,)).is_err()); }); } #[test] fn test_call_with_kwargs() { Python::with_gil(|py| { let list = vec![3, 6, 5, 4, 7].into_pyobject(py).unwrap(); let dict = vec![("reverse", true)].into_py_dict(py).unwrap(); list.call_method("sort", (), Some(&dict)).unwrap(); assert_eq!(list.extract::>().unwrap(), vec![7, 6, 5, 4, 3]); }); } #[test] fn test_call_method0() { Python::with_gil(|py| { let module = PyModule::from_code( py, c_str!( r#" class SimpleClass: def foo(self): return 42 "# ), c_str!(file!()), &generate_unique_module_name("test_module"), ) .expect("module creation failed"); let simple_class = module.getattr("SimpleClass").unwrap().call0().unwrap(); assert_eq!( simple_class .call_method0("foo") .unwrap() .extract::() .unwrap(), 42 ); }) } #[test] fn test_type() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("42"), None, None).unwrap(); assert_eq!(obj.get_type().as_type_ptr(), obj.get_type_ptr()); }); } #[test] fn test_dir() { Python::with_gil(|py| { let obj = py.eval(ffi::c_str!("42"), None, None).unwrap(); let dir = py .eval(ffi::c_str!("dir(42)"), None, None) .unwrap() .downcast_into::() .unwrap(); let a = obj .dir() .unwrap() .into_iter() .map(|x| x.extract::().unwrap()); let b = dir.into_iter().map(|x| x.extract::().unwrap()); assert!(a.eq(b)); }); } #[test] fn test_hasattr() { Python::with_gil(|py| { let x = 5i32.into_pyobject(py).unwrap(); assert!(x.is_instance_of::()); assert!(x.hasattr("to_bytes").unwrap()); assert!(!x.hasattr("bbbbbbytes").unwrap()); }) } #[cfg(feature = "macros")] #[test] #[allow(unknown_lints, non_local_definitions)] fn test_hasattr_error() { use crate::exceptions::PyValueError; use crate::prelude::*; #[pyclass(crate = "crate")] struct GetattrFail; #[pymethods(crate = "crate")] impl GetattrFail { fn __getattr__(&self, attr: PyObject) -> PyResult { Err(PyValueError::new_err(attr)) } } Python::with_gil(|py| { let obj = Py::new(py, GetattrFail).unwrap(); let obj = obj.bind(py).as_any(); assert!(obj .hasattr("foo") .unwrap_err() .is_instance_of::(py)); }) } #[test] fn test_nan_eq() { Python::with_gil(|py| { let nan = py.eval(ffi::c_str!("float('nan')"), None, None).unwrap(); assert!(nan.compare(&nan).is_err()); }); } #[test] fn test_any_is_instance_of() { Python::with_gil(|py| { let x = 5i32.into_pyobject(py).unwrap(); assert!(x.is_instance_of::()); let l = vec![&x, &x].into_pyobject(py).unwrap(); assert!(l.is_instance_of::()); }); } #[test] fn test_any_is_instance() { Python::with_gil(|py| { let l = vec![1i8, 2].into_pyobject(py).unwrap(); assert!(l.is_instance(&py.get_type::()).unwrap()); }); } #[test] fn test_any_is_exact_instance_of() { Python::with_gil(|py| { let x = 5i32.into_pyobject(py).unwrap(); assert!(x.is_exact_instance_of::()); let t = PyBool::new(py, true); assert!(t.is_instance_of::()); assert!(!t.is_exact_instance_of::()); assert!(t.is_exact_instance_of::()); let l = vec![&x, &x].into_pyobject(py).unwrap(); assert!(l.is_exact_instance_of::()); }); } #[test] fn test_any_is_exact_instance() { Python::with_gil(|py| { let t = PyBool::new(py, true); assert!(t.is_instance(&py.get_type::()).unwrap()); assert!(!t.is_exact_instance(&py.get_type::())); assert!(t.is_exact_instance(&py.get_type::())); }); } #[test] fn test_any_contains() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.into_pyobject(py).unwrap(); let bad_needle = 7i32.into_pyobject(py).unwrap(); assert!(!ob.contains(&bad_needle).unwrap()); let good_needle = 8i32.into_pyobject(py).unwrap(); assert!(ob.contains(&good_needle).unwrap()); let type_coerced_needle = 8f32.into_pyobject(py).unwrap(); assert!(ob.contains(&type_coerced_needle).unwrap()); let n: u32 = 42; let bad_haystack = n.into_pyobject(py).unwrap(); let irrelevant_needle = 0i32.into_pyobject(py).unwrap(); assert!(bad_haystack.contains(&irrelevant_needle).is_err()); }); } // This is intentionally not a test, it's a generic function used by the tests below. fn test_eq_methods_generic<'a, T>(list: &'a [T]) where T: PartialEq + PartialOrd, for<'py> &'a T: IntoPyObject<'py>, for<'py> <&'a T as IntoPyObject<'py>>::Error: Debug, { Python::with_gil(|py| { for a in list { for b in list { let a_py = a.into_pyobject(py).unwrap().into_any().into_bound(); let b_py = b.into_pyobject(py).unwrap().into_any().into_bound(); assert_eq!( a.lt(b), a_py.lt(&b_py).unwrap(), "{} < {} should be {}.", a_py, b_py, a.lt(b) ); assert_eq!( a.le(b), a_py.le(&b_py).unwrap(), "{} <= {} should be {}.", a_py, b_py, a.le(b) ); assert_eq!( a.eq(b), a_py.eq(&b_py).unwrap(), "{} == {} should be {}.", a_py, b_py, a.eq(b) ); assert_eq!( a.ne(b), a_py.ne(&b_py).unwrap(), "{} != {} should be {}.", a_py, b_py, a.ne(b) ); assert_eq!( a.gt(b), a_py.gt(&b_py).unwrap(), "{} > {} should be {}.", a_py, b_py, a.gt(b) ); assert_eq!( a.ge(b), a_py.ge(&b_py).unwrap(), "{} >= {} should be {}.", a_py, b_py, a.ge(b) ); } } }); } #[test] fn test_eq_methods_integers() { let ints = [-4, -4, 1, 2, 0, -100, 1_000_000]; test_eq_methods_generic::(&ints); } #[test] fn test_eq_methods_strings() { let strings = ["Let's", "test", "some", "eq", "methods"]; test_eq_methods_generic::<&str>(&strings); } #[test] fn test_eq_methods_floats() { let floats = [ -1.0, 2.5, 0.0, 3.0, std::f64::consts::PI, 10.0, 10.0 / 3.0, -1_000_000.0, ]; test_eq_methods_generic::(&floats); } #[test] fn test_eq_methods_bools() { let bools = [true, false]; test_eq_methods_generic::(&bools); } #[test] fn test_rich_compare_type_error() { Python::with_gil(|py| { let py_int = 1i32.into_pyobject(py).unwrap(); let py_str = "1".into_pyobject(py).unwrap(); assert!(py_int.rich_compare(&py_str, CompareOp::Lt).is_err()); assert!(!py_int .rich_compare(py_str, CompareOp::Eq) .unwrap() .is_truthy() .unwrap()); }) } #[test] fn test_is_callable() { Python::with_gil(|py| { assert!(PyList::type_object(py).is_callable()); let not_callable = 5i32.into_pyobject(py).unwrap(); assert!(!not_callable.is_callable()); }); } #[test] fn test_is_empty() { Python::with_gil(|py| { let empty_list = PyList::empty(py).into_any(); assert!(empty_list.is_empty().unwrap()); let list = PyList::new(py, vec![1, 2, 3]).unwrap().into_any(); assert!(!list.is_empty().unwrap()); let not_container = 5i32.into_pyobject(py).unwrap(); assert!(not_container.is_empty().is_err()); }); } #[cfg(feature = "macros")] #[test] #[allow(unknown_lints, non_local_definitions)] fn test_fallible_dir() { use crate::exceptions::PyValueError; use crate::prelude::*; #[pyclass(crate = "crate")] struct DirFail; #[pymethods(crate = "crate")] impl DirFail { fn __dir__(&self) -> PyResult { Err(PyValueError::new_err("uh-oh!")) } } Python::with_gil(|py| { let obj = Bound::new(py, DirFail).unwrap(); assert!(obj.dir().unwrap_err().is_instance_of::(py)); }) } } pyo3/src/types/range.rs0000644000175000017500000000554115105742312014676 0ustar bdrungbdrunguse crate::sealed::Sealed; use crate::types::PyAnyMethods; use crate::{ffi, Bound, PyAny, PyResult, PyTypeInfo, Python}; /// Represents a Python `range`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyRange>`][Bound]. /// /// For APIs available on `range` objects, see the [`PyRangeMethods`] trait which is implemented for /// [`Bound<'py, PyRange>`][Bound]. #[repr(transparent)] pub struct PyRange(PyAny); pyobject_native_type_core!(PyRange, pyobject_native_static_type_object!(ffi::PyRange_Type), #checkfunction=ffi::PyRange_Check); impl<'py> PyRange { /// Creates a new Python `range` object with a default step of 1. pub fn new(py: Python<'py>, start: isize, stop: isize) -> PyResult> { Self::new_with_step(py, start, stop, 1) } /// Creates a new Python `range` object with a specified step. pub fn new_with_step( py: Python<'py>, start: isize, stop: isize, step: isize, ) -> PyResult> { unsafe { Ok(Self::type_object(py) .call1((start, stop, step))? .downcast_into_unchecked()) } } } /// Implementation of functionality for [`PyRange`]. /// /// These methods are defined for the `Bound<'py, PyRange>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyRange")] pub trait PyRangeMethods<'py>: Sealed { /// Returns the start of the range. fn start(&self) -> PyResult; /// Returns the exclusive end of the range. fn stop(&self) -> PyResult; /// Returns the step of the range. fn step(&self) -> PyResult; } impl<'py> PyRangeMethods<'py> for Bound<'py, PyRange> { fn start(&self) -> PyResult { self.getattr(intern!(self.py(), "start"))?.extract() } fn stop(&self) -> PyResult { self.getattr(intern!(self.py(), "stop"))?.extract() } fn step(&self) -> PyResult { self.getattr(intern!(self.py(), "step"))?.extract() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_py_range_new() { Python::with_gil(|py| { let range = PyRange::new(py, isize::MIN, isize::MAX).unwrap(); assert_eq!(range.start().unwrap(), isize::MIN); assert_eq!(range.stop().unwrap(), isize::MAX); assert_eq!(range.step().unwrap(), 1); }); } #[test] fn test_py_range_new_with_step() { Python::with_gil(|py| { let range = PyRange::new_with_step(py, 1, 10, 2).unwrap(); assert_eq!(range.start().unwrap(), 1); assert_eq!(range.stop().unwrap(), 10); assert_eq!(range.step().unwrap(), 2); }); } } pyo3/src/types/datetime.rs0000644000175000017500000010361315105742312015375 0ustar bdrungbdrung//! Safe Rust wrappers for types defined in the Python `datetime` library //! //! For more details about these types, see the [Python //! documentation](https://docs.python.org/3/library/datetime.html) use crate::err::PyResult; #[cfg(not(Py_3_9))] use crate::exceptions::PyImportError; #[cfg(not(Py_LIMITED_API))] use crate::ffi::{ self, PyDateTime_CAPI, PyDateTime_DATE_GET_FOLD, PyDateTime_DATE_GET_HOUR, PyDateTime_DATE_GET_MICROSECOND, PyDateTime_DATE_GET_MINUTE, PyDateTime_DATE_GET_SECOND, PyDateTime_DELTA_GET_DAYS, PyDateTime_DELTA_GET_MICROSECONDS, PyDateTime_DELTA_GET_SECONDS, PyDateTime_FromTimestamp, PyDateTime_GET_DAY, PyDateTime_GET_MONTH, PyDateTime_GET_YEAR, PyDateTime_IMPORT, PyDateTime_TIME_GET_FOLD, PyDateTime_TIME_GET_HOUR, PyDateTime_TIME_GET_MICROSECOND, PyDateTime_TIME_GET_MINUTE, PyDateTime_TIME_GET_SECOND, PyDate_FromTimestamp, }; #[cfg(all(Py_3_10, not(Py_LIMITED_API)))] use crate::ffi::{PyDateTime_DATE_GET_TZINFO, PyDateTime_TIME_GET_TZINFO, Py_IsNone}; use crate::types::{any::PyAnyMethods, PyString, PyType}; #[cfg(not(Py_LIMITED_API))] use crate::{ffi_ptr_ext::FfiPtrExt, py_result_ext::PyResultExt, types::PyTuple, BoundObject}; use crate::{sync::GILOnceCell, Py}; #[cfg(Py_LIMITED_API)] use crate::{types::IntoPyDict, PyTypeCheck}; use crate::{Borrowed, Bound, IntoPyObject, PyAny, PyErr, Python}; #[cfg(not(Py_LIMITED_API))] use std::os::raw::c_int; #[cfg(not(Py_LIMITED_API))] fn ensure_datetime_api(py: Python<'_>) -> PyResult<&'static PyDateTime_CAPI> { if let Some(api) = unsafe { pyo3_ffi::PyDateTimeAPI().as_ref() } { Ok(api) } else { unsafe { PyDateTime_IMPORT(); pyo3_ffi::PyDateTimeAPI().as_ref() } .ok_or_else(|| PyErr::fetch(py)) } } #[cfg(not(Py_LIMITED_API))] fn expect_datetime_api(py: Python<'_>) -> &'static PyDateTime_CAPI { ensure_datetime_api(py).expect("failed to import `datetime` C API") } #[cfg(Py_LIMITED_API)] struct DatetimeTypes { date: Py, datetime: Py, time: Py, timedelta: Py, timezone: Py, tzinfo: Py, } #[cfg(Py_LIMITED_API)] impl DatetimeTypes { fn get(py: Python<'_>) -> &Self { Self::try_get(py).expect("failed to load datetime module") } fn try_get(py: Python<'_>) -> PyResult<&Self> { static TYPES: GILOnceCell = GILOnceCell::new(); TYPES.get_or_try_init(py, || { let datetime = py.import("datetime")?; Ok::<_, PyErr>(Self { date: datetime.getattr("date")?.downcast_into()?.into(), datetime: datetime.getattr("datetime")?.downcast_into()?.into(), time: datetime.getattr("time")?.downcast_into()?.into(), timedelta: datetime.getattr("timedelta")?.downcast_into()?.into(), timezone: datetime.getattr("timezone")?.downcast_into()?.into(), tzinfo: datetime.getattr("tzinfo")?.downcast_into()?.into(), }) }) } } // Type Check macros // // These are bindings around the C API typecheck macros, all of them return // `1` if True and `0` if False. In all type check macros, the argument (`op`) // must not be `NULL`. The implementations here all call ensure_datetime_api // to ensure that the PyDateTimeAPI is initialized before use // // // # Safety // // These functions must only be called when the GIL is held! #[cfg(not(Py_LIMITED_API))] macro_rules! ffi_fun_with_autoinit { ($(#[$outer:meta] unsafe fn $name: ident($arg: ident: *mut PyObject) -> $ret: ty;)*) => { $( #[$outer] #[allow(non_snake_case)] /// # Safety /// /// Must only be called while the GIL is held unsafe fn $name($arg: *mut crate::ffi::PyObject) -> $ret { let _ = ensure_datetime_api(unsafe { Python::assume_gil_acquired() }); unsafe { crate::ffi::$name($arg) } } )* }; } #[cfg(not(Py_LIMITED_API))] ffi_fun_with_autoinit! { /// Check if `op` is a `PyDateTimeAPI.DateType` or subtype. unsafe fn PyDate_Check(op: *mut PyObject) -> c_int; /// Check if `op` is a `PyDateTimeAPI.DateTimeType` or subtype. unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int; /// Check if `op` is a `PyDateTimeAPI.TimeType` or subtype. unsafe fn PyTime_Check(op: *mut PyObject) -> c_int; /// Check if `op` is a `PyDateTimeAPI.DetaType` or subtype. unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int; /// Check if `op` is a `PyDateTimeAPI.TZInfoType` or subtype. unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int; } // Access traits /// Trait for accessing the date components of a struct containing a date. #[cfg(not(Py_LIMITED_API))] pub trait PyDateAccess { /// Returns the year, as a positive int. /// /// Implementations should conform to the upstream documentation: /// fn get_year(&self) -> i32; /// Returns the month, as an int from 1 through 12. /// /// Implementations should conform to the upstream documentation: /// fn get_month(&self) -> u8; /// Returns the day, as an int from 1 through 31. /// /// Implementations should conform to the upstream documentation: /// fn get_day(&self) -> u8; } /// Trait for accessing the components of a struct containing a timedelta. /// /// Note: These access the individual components of a (day, second, /// microsecond) representation of the delta, they are *not* intended as /// aliases for calculating the total duration in each of these units. #[cfg(not(Py_LIMITED_API))] pub trait PyDeltaAccess { /// Returns the number of days, as an int from -999999999 to 999999999. /// /// Implementations should conform to the upstream documentation: /// fn get_days(&self) -> i32; /// Returns the number of seconds, as an int from 0 through 86399. /// /// Implementations should conform to the upstream documentation: /// fn get_seconds(&self) -> i32; /// Returns the number of microseconds, as an int from 0 through 999999. /// /// Implementations should conform to the upstream documentation: /// fn get_microseconds(&self) -> i32; } /// Trait for accessing the time components of a struct containing a time. #[cfg(not(Py_LIMITED_API))] pub trait PyTimeAccess { /// Returns the hour, as an int from 0 through 23. /// /// Implementations should conform to the upstream documentation: /// fn get_hour(&self) -> u8; /// Returns the minute, as an int from 0 through 59. /// /// Implementations should conform to the upstream documentation: /// fn get_minute(&self) -> u8; /// Returns the second, as an int from 0 through 59. /// /// Implementations should conform to the upstream documentation: /// fn get_second(&self) -> u8; /// Returns the microsecond, as an int from 0 through 999999. /// /// Implementations should conform to the upstream documentation: /// fn get_microsecond(&self) -> u32; /// Returns whether this date is the later of two moments with the /// same representation, during a repeated interval. /// /// This typically occurs at the end of daylight savings time. Only valid if the /// represented time is ambiguous. /// See [PEP 495](https://www.python.org/dev/peps/pep-0495/) for more detail. fn get_fold(&self) -> bool; } /// Trait for accessing the components of a struct containing a tzinfo. pub trait PyTzInfoAccess<'py> { /// Returns the tzinfo (which may be None). /// /// Implementations should conform to the upstream documentation: /// /// fn get_tzinfo(&self) -> Option>; } /// Bindings around `datetime.date`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyDate>`][Bound]. #[repr(transparent)] pub struct PyDate(PyAny); #[cfg(not(Py_LIMITED_API))] pyobject_native_type!( PyDate, crate::ffi::PyDateTime_Date, |py| expect_datetime_api(py).DateType, #module=Some("datetime"), #checkfunction=PyDate_Check ); #[cfg(not(Py_LIMITED_API))] pyobject_subclassable_native_type!(PyDate, crate::ffi::PyDateTime_Date); #[cfg(Py_LIMITED_API)] pyobject_native_type_named!(PyDate); #[cfg(Py_LIMITED_API)] impl PyTypeCheck for PyDate { const NAME: &'static str = "PyDate"; fn type_check(object: &Bound<'_, PyAny>) -> bool { let py = object.py(); DatetimeTypes::try_get(py) .and_then(|module| object.is_instance(module.date.bind(py))) .unwrap_or_default() } } impl PyDate { /// Creates a new `datetime.date`. pub fn new(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult> { #[cfg(not(Py_LIMITED_API))] { let api = ensure_datetime_api(py)?; unsafe { (api.Date_FromDate)(year, c_int::from(month), c_int::from(day), api.DateType) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] unsafe { Ok(DatetimeTypes::try_get(py)? .date .bind(py) .call((year, month, day), None)? .downcast_into_unchecked()) } } /// Construct a `datetime.date` from a POSIX timestamp /// /// This is equivalent to `datetime.date.fromtimestamp` pub fn from_timestamp(py: Python<'_>, timestamp: i64) -> PyResult> { #[cfg(not(Py_LIMITED_API))] { let time_tuple = PyTuple::new(py, [timestamp])?; // safety ensure that the API is loaded let _api = ensure_datetime_api(py)?; unsafe { PyDate_FromTimestamp(time_tuple.as_ptr()) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] unsafe { Ok(DatetimeTypes::try_get(py)? .date .bind(py) .call_method1("fromtimestamp", (timestamp,))? .downcast_into_unchecked()) } } } #[cfg(not(Py_LIMITED_API))] impl PyDateAccess for Bound<'_, PyDate> { fn get_year(&self) -> i32 { unsafe { PyDateTime_GET_YEAR(self.as_ptr()) } } fn get_month(&self) -> u8 { unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 } } fn get_day(&self) -> u8 { unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 } } } /// Bindings for `datetime.datetime`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyDateTime>`][Bound]. #[repr(transparent)] pub struct PyDateTime(PyAny); #[cfg(not(Py_LIMITED_API))] pyobject_native_type!( PyDateTime, crate::ffi::PyDateTime_DateTime, |py| expect_datetime_api(py).DateTimeType, #module=Some("datetime"), #checkfunction=PyDateTime_Check ); #[cfg(not(Py_LIMITED_API))] pyobject_subclassable_native_type!(PyDateTime, crate::ffi::PyDateTime_DateTime); #[cfg(Py_LIMITED_API)] pyobject_native_type_named!(PyDateTime); #[cfg(Py_LIMITED_API)] impl PyTypeCheck for PyDateTime { const NAME: &'static str = "PyDateTime"; fn type_check(object: &Bound<'_, PyAny>) -> bool { let py = object.py(); DatetimeTypes::try_get(py) .and_then(|module| object.is_instance(module.datetime.bind(py))) .unwrap_or_default() } } impl PyDateTime { /// Creates a new `datetime.datetime` object. #[allow(clippy::too_many_arguments)] pub fn new<'py>( py: Python<'py>, year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&Bound<'py, PyTzInfo>>, ) -> PyResult> { #[cfg(not(Py_LIMITED_API))] { let api = ensure_datetime_api(py)?; unsafe { (api.DateTime_FromDateAndTime)( year, c_int::from(month), c_int::from(day), c_int::from(hour), c_int::from(minute), c_int::from(second), microsecond as c_int, opt_to_pyobj(tzinfo), api.DateTimeType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] unsafe { Ok(DatetimeTypes::try_get(py)? .datetime .bind(py) .call( (year, month, day, hour, minute, second, microsecond, tzinfo), None, )? .downcast_into_unchecked()) } } /// Alternate constructor that takes a `fold` parameter. A `true` value for this parameter /// signifies this this datetime is the later of two moments with the same representation, /// during a repeated interval. /// /// This typically occurs at the end of daylight savings time. Only valid if the /// represented time is ambiguous. /// See [PEP 495](https://www.python.org/dev/peps/pep-0495/) for more detail. #[allow(clippy::too_many_arguments)] pub fn new_with_fold<'py>( py: Python<'py>, year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&Bound<'py, PyTzInfo>>, fold: bool, ) -> PyResult> { #[cfg(not(Py_LIMITED_API))] { let api = ensure_datetime_api(py)?; unsafe { (api.DateTime_FromDateAndTimeAndFold)( year, c_int::from(month), c_int::from(day), c_int::from(hour), c_int::from(minute), c_int::from(second), microsecond as c_int, opt_to_pyobj(tzinfo), c_int::from(fold), api.DateTimeType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] unsafe { Ok(DatetimeTypes::try_get(py)? .datetime .bind(py) .call( (year, month, day, hour, minute, second, microsecond, tzinfo), Some(&[("fold", fold)].into_py_dict(py)?), )? .downcast_into_unchecked()) } } /// Construct a `datetime` object from a POSIX timestamp /// /// This is equivalent to `datetime.datetime.fromtimestamp` pub fn from_timestamp<'py>( py: Python<'py>, timestamp: f64, tzinfo: Option<&Bound<'py, PyTzInfo>>, ) -> PyResult> { #[cfg(not(Py_LIMITED_API))] { let args = (timestamp, tzinfo).into_pyobject(py)?; // safety ensure API is loaded let _api = ensure_datetime_api(py)?; unsafe { PyDateTime_FromTimestamp(args.as_ptr()) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] unsafe { Ok(DatetimeTypes::try_get(py)? .datetime .bind(py) .call_method1("fromtimestamp", (timestamp, tzinfo))? .downcast_into_unchecked()) } } } #[cfg(not(Py_LIMITED_API))] impl PyDateAccess for Bound<'_, PyDateTime> { fn get_year(&self) -> i32 { unsafe { PyDateTime_GET_YEAR(self.as_ptr()) } } fn get_month(&self) -> u8 { unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 } } fn get_day(&self) -> u8 { unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 } } } #[cfg(not(Py_LIMITED_API))] impl PyTimeAccess for Bound<'_, PyDateTime> { fn get_hour(&self) -> u8 { unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as u8 } } fn get_minute(&self) -> u8 { unsafe { PyDateTime_DATE_GET_MINUTE(self.as_ptr()) as u8 } } fn get_second(&self) -> u8 { unsafe { PyDateTime_DATE_GET_SECOND(self.as_ptr()) as u8 } } fn get_microsecond(&self) -> u32 { unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as u32 } } fn get_fold(&self) -> bool { unsafe { PyDateTime_DATE_GET_FOLD(self.as_ptr()) > 0 } } } impl<'py> PyTzInfoAccess<'py> for Bound<'py, PyDateTime> { fn get_tzinfo(&self) -> Option> { #[cfg(all(not(Py_3_10), not(Py_LIMITED_API)))] unsafe { let ptr = self.as_ptr() as *mut ffi::PyDateTime_DateTime; if (*ptr).hastzinfo != 0 { Some( (*ptr) .tzinfo .assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked(), ) } else { None } } #[cfg(all(Py_3_10, not(Py_LIMITED_API)))] unsafe { let res = PyDateTime_DATE_GET_TZINFO(self.as_ptr()); if Py_IsNone(res) == 1 { None } else { Some( res.assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked(), ) } } #[cfg(Py_LIMITED_API)] unsafe { let tzinfo = self.getattr(intern!(self.py(), "tzinfo")).ok()?; if tzinfo.is_none() { None } else { Some(tzinfo.downcast_into_unchecked()) } } } } /// Bindings for `datetime.time`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyTime>`][Bound]. #[repr(transparent)] pub struct PyTime(PyAny); #[cfg(not(Py_LIMITED_API))] pyobject_native_type!( PyTime, crate::ffi::PyDateTime_Time, |py| expect_datetime_api(py).TimeType, #module=Some("datetime"), #checkfunction=PyTime_Check ); #[cfg(not(Py_LIMITED_API))] pyobject_subclassable_native_type!(PyTime, crate::ffi::PyDateTime_Time); #[cfg(Py_LIMITED_API)] pyobject_native_type_named!(PyTime); #[cfg(Py_LIMITED_API)] impl PyTypeCheck for PyTime { const NAME: &'static str = "PyTime"; fn type_check(object: &Bound<'_, PyAny>) -> bool { let py = object.py(); DatetimeTypes::try_get(py) .and_then(|module| object.is_instance(module.time.bind(py))) .unwrap_or_default() } } impl PyTime { /// Creates a new `datetime.time` object. pub fn new<'py>( py: Python<'py>, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&Bound<'py, PyTzInfo>>, ) -> PyResult> { #[cfg(not(Py_LIMITED_API))] { let api = ensure_datetime_api(py)?; unsafe { (api.Time_FromTime)( c_int::from(hour), c_int::from(minute), c_int::from(second), microsecond as c_int, opt_to_pyobj(tzinfo), api.TimeType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] unsafe { Ok(DatetimeTypes::try_get(py)? .time .bind(py) .call((hour, minute, second, microsecond, tzinfo), None)? .downcast_into_unchecked()) } } /// Alternate constructor that takes a `fold` argument. See [`PyDateTime::new_with_fold`]. pub fn new_with_fold<'py>( py: Python<'py>, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&Bound<'py, PyTzInfo>>, fold: bool, ) -> PyResult> { #[cfg(not(Py_LIMITED_API))] { let api = ensure_datetime_api(py)?; unsafe { (api.Time_FromTimeAndFold)( c_int::from(hour), c_int::from(minute), c_int::from(second), microsecond as c_int, opt_to_pyobj(tzinfo), fold as c_int, api.TimeType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] #[cfg(Py_LIMITED_API)] unsafe { Ok(DatetimeTypes::try_get(py)? .time .bind(py) .call( (hour, minute, second, microsecond, tzinfo), Some(&[("fold", fold)].into_py_dict(py)?), )? .downcast_into_unchecked()) } } } #[cfg(not(Py_LIMITED_API))] impl PyTimeAccess for Bound<'_, PyTime> { fn get_hour(&self) -> u8 { unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as u8 } } fn get_minute(&self) -> u8 { unsafe { PyDateTime_TIME_GET_MINUTE(self.as_ptr()) as u8 } } fn get_second(&self) -> u8 { unsafe { PyDateTime_TIME_GET_SECOND(self.as_ptr()) as u8 } } fn get_microsecond(&self) -> u32 { unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as u32 } } fn get_fold(&self) -> bool { unsafe { PyDateTime_TIME_GET_FOLD(self.as_ptr()) != 0 } } } impl<'py> PyTzInfoAccess<'py> for Bound<'py, PyTime> { fn get_tzinfo(&self) -> Option> { #[cfg(all(not(Py_3_10), not(Py_LIMITED_API)))] unsafe { let ptr = self.as_ptr() as *mut ffi::PyDateTime_Time; if (*ptr).hastzinfo != 0 { Some( (*ptr) .tzinfo .assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked(), ) } else { None } } #[cfg(all(Py_3_10, not(Py_LIMITED_API)))] unsafe { let res = PyDateTime_TIME_GET_TZINFO(self.as_ptr()); if Py_IsNone(res) == 1 { None } else { Some( res.assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked(), ) } } #[cfg(Py_LIMITED_API)] unsafe { let tzinfo = self.getattr(intern!(self.py(), "tzinfo")).ok()?; if tzinfo.is_none() { None } else { Some(tzinfo.downcast_into_unchecked()) } } } } /// Bindings for `datetime.tzinfo`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyTzInfo>`][Bound]. /// /// This is an abstract base class and cannot be constructed directly. /// For concrete time zone implementations, see [`timezone_utc`] and /// the [`zoneinfo` module](https://docs.python.org/3/library/zoneinfo.html). #[repr(transparent)] pub struct PyTzInfo(PyAny); #[cfg(not(Py_LIMITED_API))] pyobject_native_type!( PyTzInfo, crate::ffi::PyObject, |py| expect_datetime_api(py).TZInfoType, #module=Some("datetime"), #checkfunction=PyTZInfo_Check ); #[cfg(not(Py_LIMITED_API))] pyobject_subclassable_native_type!(PyTzInfo, crate::ffi::PyObject); #[cfg(Py_LIMITED_API)] pyobject_native_type_named!(PyTzInfo); #[cfg(Py_LIMITED_API)] impl PyTypeCheck for PyTzInfo { const NAME: &'static str = "PyTzInfo"; fn type_check(object: &Bound<'_, PyAny>) -> bool { let py = object.py(); DatetimeTypes::try_get(py) .and_then(|module| object.is_instance(module.tzinfo.bind(py))) .unwrap_or_default() } } impl PyTzInfo { /// Equivalent to `datetime.timezone.utc` pub fn utc(py: Python<'_>) -> PyResult> { #[cfg(not(Py_LIMITED_API))] unsafe { Ok(ensure_datetime_api(py)? .TimeZone_UTC .assume_borrowed(py) .downcast_unchecked()) } #[cfg(Py_LIMITED_API)] { static UTC: GILOnceCell> = GILOnceCell::new(); UTC.get_or_try_init(py, || { Ok(DatetimeTypes::get(py) .timezone .bind(py) .getattr("utc")? .downcast_into()? .unbind()) }) .map(|utc| utc.bind_borrowed(py)) } } /// Equivalent to `zoneinfo.ZoneInfo` constructor pub fn timezone<'py, T>(py: Python<'py>, iana_name: T) -> PyResult> where T: IntoPyObject<'py, Target = PyString>, { static ZONE_INFO: GILOnceCell> = GILOnceCell::new(); let zoneinfo = ZONE_INFO.import(py, "zoneinfo", "ZoneInfo"); #[cfg(not(Py_3_9))] let zoneinfo = zoneinfo .or_else(|_| ZONE_INFO.import(py, "backports.zoneinfo", "ZoneInfo")) .map_err(|_| PyImportError::new_err("Could not import \"backports.zoneinfo.ZoneInfo\". ZoneInfo is required when converting timezone-aware DateTime's. Please install \"backports.zoneinfo\" on python < 3.9")); zoneinfo? .call1((iana_name,))? .downcast_into() .map_err(Into::into) } /// Equivalent to `datetime.timezone` constructor pub fn fixed_offset<'py, T>(py: Python<'py>, offset: T) -> PyResult> where T: IntoPyObject<'py, Target = PyDelta>, { #[cfg(not(Py_LIMITED_API))] { let api = ensure_datetime_api(py)?; let delta = offset.into_pyobject(py).map_err(Into::into)?; unsafe { (api.TimeZone_FromTimeZone)(delta.as_ptr(), std::ptr::null_mut()) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] unsafe { Ok(DatetimeTypes::try_get(py)? .timezone .bind(py) .call1((offset,))? .downcast_into_unchecked()) } } } /// Equivalent to `datetime.timezone.utc` #[deprecated(since = "0.25.0", note = "use `PyTzInfo::utc` instead")] pub fn timezone_utc(py: Python<'_>) -> Bound<'_, PyTzInfo> { PyTzInfo::utc(py) .expect("failed to import datetime.timezone.utc") .to_owned() } /// Bindings for `datetime.timedelta`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyDelta>`][Bound]. #[repr(transparent)] pub struct PyDelta(PyAny); #[cfg(not(Py_LIMITED_API))] pyobject_native_type!( PyDelta, crate::ffi::PyDateTime_Delta, |py| expect_datetime_api(py).DeltaType, #module=Some("datetime"), #checkfunction=PyDelta_Check ); #[cfg(not(Py_LIMITED_API))] pyobject_subclassable_native_type!(PyDelta, crate::ffi::PyDateTime_Delta); #[cfg(Py_LIMITED_API)] pyobject_native_type_named!(PyDelta); #[cfg(Py_LIMITED_API)] impl PyTypeCheck for PyDelta { const NAME: &'static str = "PyDelta"; fn type_check(object: &Bound<'_, PyAny>) -> bool { let py = object.py(); DatetimeTypes::try_get(py) .and_then(|module| object.is_instance(module.timedelta.bind(py))) .unwrap_or_default() } } impl PyDelta { /// Creates a new `timedelta`. pub fn new( py: Python<'_>, days: i32, seconds: i32, microseconds: i32, normalize: bool, ) -> PyResult> { #[cfg(not(Py_LIMITED_API))] { let api = ensure_datetime_api(py)?; unsafe { (api.Delta_FromDelta)( days as c_int, seconds as c_int, microseconds as c_int, normalize as c_int, api.DeltaType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[cfg(Py_LIMITED_API)] unsafe { let _ = normalize; Ok(DatetimeTypes::try_get(py)? .timedelta .bind(py) .call1((days, seconds, microseconds))? .downcast_into_unchecked()) } } } #[cfg(not(Py_LIMITED_API))] impl PyDeltaAccess for Bound<'_, PyDelta> { fn get_days(&self) -> i32 { unsafe { PyDateTime_DELTA_GET_DAYS(self.as_ptr()) } } fn get_seconds(&self) -> i32 { unsafe { PyDateTime_DELTA_GET_SECONDS(self.as_ptr()) } } fn get_microseconds(&self) -> i32 { unsafe { PyDateTime_DELTA_GET_MICROSECONDS(self.as_ptr()) } } } // Utility function which returns a borrowed reference to either // the underlying tzinfo or None. #[cfg(not(Py_LIMITED_API))] fn opt_to_pyobj(opt: Option<&Bound<'_, PyTzInfo>>) -> *mut ffi::PyObject { match opt { Some(tzi) => tzi.as_ptr(), None => unsafe { ffi::Py_None() }, } } #[cfg(test)] mod tests { use super::*; #[cfg(feature = "macros")] use crate::py_run; #[test] #[cfg(feature = "macros")] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_datetime_fromtimestamp() { Python::with_gil(|py| { let dt = PyDateTime::from_timestamp(py, 100.0, None).unwrap(); py_run!( py, dt, "import datetime; assert dt == datetime.datetime.fromtimestamp(100)" ); let utc = PyTzInfo::utc(py).unwrap(); let dt = PyDateTime::from_timestamp(py, 100.0, Some(&utc)).unwrap(); py_run!( py, dt, "import datetime; assert dt == datetime.datetime.fromtimestamp(100, datetime.timezone.utc)" ); }) } #[test] #[cfg(feature = "macros")] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_date_fromtimestamp() { Python::with_gil(|py| { let dt = PyDate::from_timestamp(py, 100).unwrap(); py_run!( py, dt, "import datetime; assert dt == datetime.date.fromtimestamp(100)" ); }) } #[test] #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_new_with_fold() { Python::with_gil(|py| { let a = PyDateTime::new_with_fold(py, 2021, 1, 23, 20, 32, 40, 341516, None, false); let b = PyDateTime::new_with_fold(py, 2021, 1, 23, 20, 32, 40, 341516, None, true); assert!(!a.unwrap().get_fold()); assert!(b.unwrap().get_fold()); }); } #[test] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_get_tzinfo() { crate::Python::with_gil(|py| { let utc = PyTzInfo::utc(py).unwrap(); let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap(); assert!(dt.get_tzinfo().unwrap().eq(utc).unwrap()); let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap(); assert!(dt.get_tzinfo().is_none()); let t = PyTime::new(py, 0, 0, 0, 0, Some(&utc)).unwrap(); assert!(t.get_tzinfo().unwrap().eq(utc).unwrap()); let t = PyTime::new(py, 0, 0, 0, 0, None).unwrap(); assert!(t.get_tzinfo().is_none()); }); } #[test] #[cfg(all(feature = "macros", feature = "chrono"))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_timezone_from_offset() { use crate::types::PyNone; Python::with_gil(|py| { assert!( PyTzInfo::fixed_offset(py, PyDelta::new(py, 0, -3600, 0, true).unwrap()) .unwrap() .call_method1("utcoffset", (PyNone::get(py),)) .unwrap() .downcast_into::() .unwrap() .eq(PyDelta::new(py, 0, -3600, 0, true).unwrap()) .unwrap() ); assert!( PyTzInfo::fixed_offset(py, PyDelta::new(py, 0, 3600, 0, true).unwrap()) .unwrap() .call_method1("utcoffset", (PyNone::get(py),)) .unwrap() .downcast_into::() .unwrap() .eq(PyDelta::new(py, 0, 3600, 0, true).unwrap()) .unwrap() ); PyTzInfo::fixed_offset(py, PyDelta::new(py, 1, 0, 0, true).unwrap()).unwrap_err(); }) } } pyo3/src/types/mappingproxy.rs0000644000175000017500000004366215105742312016345 0ustar bdrungbdrung// Copyright (c) 2017-present PyO3 Project and Contributors use super::PyMapping; use crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyIterator, PyList}; use crate::{ffi, Python}; use std::os::raw::c_int; /// Represents a Python `mappingproxy`. #[repr(transparent)] pub struct PyMappingProxy(PyAny); #[inline] unsafe fn dict_proxy_check(op: *mut ffi::PyObject) -> c_int { unsafe { ffi::Py_IS_TYPE(op, std::ptr::addr_of_mut!(ffi::PyDictProxy_Type)) } } pyobject_native_type_core!( PyMappingProxy, pyobject_native_static_type_object!(ffi::PyDictProxy_Type), #checkfunction=dict_proxy_check ); impl PyMappingProxy { /// Creates a mappingproxy from an object. pub fn new<'py>( py: Python<'py>, elements: &Bound<'py, PyMapping>, ) -> Bound<'py, PyMappingProxy> { unsafe { ffi::PyDictProxy_New(elements.as_ptr()) .assume_owned(py) .downcast_into_unchecked() } } } /// Implementation of functionality for [`PyMappingProxy`]. /// /// These methods are defined for the `Bound<'py, PyMappingProxy>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyMappingProxy")] pub trait PyMappingProxyMethods<'py, 'a>: crate::sealed::Sealed { /// Checks if the mappingproxy is empty, i.e. `len(self) == 0`. fn is_empty(&self) -> PyResult; /// Returns a list containing all keys in the mapping. fn keys(&self) -> PyResult>; /// Returns a list containing all values in the mapping. fn values(&self) -> PyResult>; /// Returns a list of tuples of all (key, value) pairs in the mapping. fn items(&self) -> PyResult>; /// Returns `self` cast as a `PyMapping`. fn as_mapping(&self) -> &Bound<'py, PyMapping>; /// Takes an object and returns an iterator for it. Returns an error if the object is not /// iterable. fn try_iter(&'a self) -> PyResult>; } impl<'py, 'a> PyMappingProxyMethods<'py, 'a> for Bound<'py, PyMappingProxy> { fn is_empty(&self) -> PyResult { Ok(self.len()? == 0) } #[inline] fn keys(&self) -> PyResult> { unsafe { Ok(ffi::PyMapping_Keys(self.as_ptr()) .assume_owned_or_err(self.py())? .downcast_into_unchecked()) } } #[inline] fn values(&self) -> PyResult> { unsafe { Ok(ffi::PyMapping_Values(self.as_ptr()) .assume_owned_or_err(self.py())? .downcast_into_unchecked()) } } #[inline] fn items(&self) -> PyResult> { unsafe { Ok(ffi::PyMapping_Items(self.as_ptr()) .assume_owned_or_err(self.py())? .downcast_into_unchecked()) } } fn as_mapping(&self) -> &Bound<'py, PyMapping> { unsafe { self.downcast_unchecked() } } fn try_iter(&'a self) -> PyResult> { Ok(BoundMappingProxyIterator { iterator: PyIterator::from_object(self)?, mappingproxy: self, }) } } pub struct BoundMappingProxyIterator<'py, 'a> { iterator: Bound<'py, PyIterator>, mappingproxy: &'a Bound<'py, PyMappingProxy>, } impl<'py> Iterator for BoundMappingProxyIterator<'py, '_> { type Item = PyResult<(Bound<'py, PyAny>, Bound<'py, PyAny>)>; #[inline] fn next(&mut self) -> Option { self.iterator.next().map(|key| match key { Ok(key) => match self.mappingproxy.get_item(&key) { Ok(value) => Ok((key, value)), Err(e) => Err(e), }, Err(e) => Err(e), }) } } #[cfg(test)] mod tests { use super::*; use crate::types::dict::*; use crate::Python; use crate::{ exceptions::PyKeyError, types::{PyInt, PyTuple}, }; use std::collections::{BTreeMap, HashMap}; #[test] fn test_new() { Python::with_gil(|py| { let pydict = [(7, 32)].into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, pydict.as_mapping()); mappingproxy.get_item(7i32).unwrap(); assert_eq!( 32, mappingproxy .get_item(7i32) .unwrap() .extract::() .unwrap() ); assert!(mappingproxy .get_item(8i32) .unwrap_err() .is_instance_of::(py)); }); } #[test] fn test_len() { Python::with_gil(|py| { let mut v = HashMap::new(); let dict = v.clone().into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!(mappingproxy.len().unwrap(), 0); v.insert(7, 32); let dict2 = v.clone().into_py_dict(py).unwrap(); let mp2 = PyMappingProxy::new(py, dict2.as_mapping()); assert_eq!(mp2.len().unwrap(), 1); }); } #[test] fn test_contains() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let dict = v.clone().into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); assert!(mappingproxy.contains(7i32).unwrap()); assert!(!mappingproxy.contains(8i32).unwrap()); }); } #[test] fn test_get_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let dict = v.clone().into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!( 32, mappingproxy .get_item(7i32) .unwrap() .extract::() .unwrap() ); assert!(mappingproxy .get_item(8i32) .unwrap_err() .is_instance_of::(py)); }); } #[test] fn test_set_item_refcnt() { Python::with_gil(|py| { let cnt; { let none = py.None(); cnt = none.get_refcnt(py); let dict = [(10, none)].into_py_dict(py).unwrap(); let _mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); } { assert_eq!(cnt, py.None().get_refcnt(py)); } }); } #[test] fn test_isempty() { Python::with_gil(|py| { let map: HashMap = HashMap::new(); let dict = map.into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); assert!(mappingproxy.is_empty().unwrap()); }); } #[test] fn test_keys() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; for el in mappingproxy.keys().unwrap().try_iter().unwrap() { key_sum += el.unwrap().extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); }); } #[test] fn test_values() { Python::with_gil(|py| { let mut v: HashMap = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut values_sum = 0; for el in mappingproxy.values().unwrap().try_iter().unwrap() { values_sum += el.unwrap().extract::().unwrap(); } assert_eq!(32 + 42 + 123, values_sum); }); } #[test] fn test_items() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; let mut value_sum = 0; for res in mappingproxy.items().unwrap().try_iter().unwrap() { let el = res.unwrap(); let tuple = el.downcast::().unwrap(); key_sum += tuple.get_item(0).unwrap().extract::().unwrap(); value_sum += tuple.get_item(1).unwrap().extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_iter() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let dict = v.into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); let mut key_sum = 0; let mut value_sum = 0; for res in mappingproxy.try_iter().unwrap() { let (key, value) = res.unwrap(); key_sum += key.extract::().unwrap(); value_sum += value.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_hashmap_into_python() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let dict = map.clone().into_py_dict(py).unwrap(); let py_map = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!(py_map.len().unwrap(), 1); assert_eq!(py_map.get_item(1).unwrap().extract::().unwrap(), 1); }); } #[test] fn test_hashmap_into_mappingproxy() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let dict = map.clone().into_py_dict(py).unwrap(); let py_map = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!(py_map.len().unwrap(), 1); assert_eq!(py_map.get_item(1).unwrap().extract::().unwrap(), 1); }); } #[test] fn test_btreemap_into_py() { Python::with_gil(|py| { let mut map = BTreeMap::::new(); map.insert(1, 1); let dict = map.clone().into_py_dict(py).unwrap(); let py_map = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!(py_map.len().unwrap(), 1); assert_eq!(py_map.get_item(1).unwrap().extract::().unwrap(), 1); }); } #[test] fn test_btreemap_into_mappingproxy() { Python::with_gil(|py| { let mut map = BTreeMap::::new(); map.insert(1, 1); let dict = map.clone().into_py_dict(py).unwrap(); let py_map = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!(py_map.len().unwrap(), 1); assert_eq!(py_map.get_item(1).unwrap().extract::().unwrap(), 1); }); } #[test] fn test_vec_into_mappingproxy() { Python::with_gil(|py| { let vec = vec![("a", 1), ("b", 2), ("c", 3)]; let dict = vec.clone().into_py_dict(py).unwrap(); let py_map = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!(py_map.len().unwrap(), 3); assert_eq!(py_map.get_item("b").unwrap().extract::().unwrap(), 2); }); } #[test] fn test_slice_into_mappingproxy() { Python::with_gil(|py| { let arr = [("a", 1), ("b", 2), ("c", 3)]; let dict = arr.into_py_dict(py).unwrap(); let py_map = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!(py_map.len().unwrap(), 3); assert_eq!(py_map.get_item("b").unwrap().extract::().unwrap(), 2); }); } #[test] fn mappingproxy_as_mapping() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let dict = map.clone().into_py_dict(py).unwrap(); let py_map = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!(py_map.as_mapping().len().unwrap(), 1); assert_eq!( py_map .as_mapping() .get_item(1) .unwrap() .extract::() .unwrap(), 1 ); }); } #[cfg(not(any(PyPy, GraalPy)))] fn abc_mappingproxy(py: Python<'_>) -> Bound<'_, PyMappingProxy> { let mut map = HashMap::<&'static str, i32>::new(); map.insert("a", 1); map.insert("b", 2); map.insert("c", 3); let dict = map.clone().into_py_dict(py).unwrap(); PyMappingProxy::new(py, dict.as_mapping()) } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn mappingproxy_keys_view() { Python::with_gil(|py| { let mappingproxy = abc_mappingproxy(py); let keys = mappingproxy.call_method0("keys").unwrap(); assert!(keys.is_instance(&py.get_type::()).unwrap()); }) } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn mappingproxy_values_view() { Python::with_gil(|py| { let mappingproxy = abc_mappingproxy(py); let values = mappingproxy.call_method0("values").unwrap(); assert!(values.is_instance(&py.get_type::()).unwrap()); }) } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn mappingproxy_items_view() { Python::with_gil(|py| { let mappingproxy = abc_mappingproxy(py); let items = mappingproxy.call_method0("items").unwrap(); assert!(items.is_instance(&py.get_type::()).unwrap()); }) } #[test] fn get_value_from_mappingproxy_of_strings() { Python::with_gil(|py: Python<'_>| { let mut map = HashMap::new(); map.insert("first key".to_string(), "first value".to_string()); map.insert("second key".to_string(), "second value".to_string()); map.insert("third key".to_string(), "third value".to_string()); let dict = map.clone().into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!( map.into_iter().collect::>(), mappingproxy .try_iter() .unwrap() .map(|object| { let tuple = object.unwrap(); ( tuple.0.extract::().unwrap(), tuple.1.extract::().unwrap(), ) }) .collect::>() ); }) } #[test] fn get_value_from_mappingproxy_of_integers() { Python::with_gil(|py: Python<'_>| { const LEN: usize = 10_000; let items: Vec<(usize, usize)> = (1..LEN).map(|i| (i, i - 1)).collect(); let dict = items.clone().into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); assert_eq!( items, mappingproxy .clone() .try_iter() .unwrap() .map(|object| { let tuple = object.unwrap(); ( tuple .0 .downcast::() .unwrap() .extract::() .unwrap(), tuple .1 .downcast::() .unwrap() .extract::() .unwrap(), ) }) .collect::>() ); for index in 1..LEN { assert_eq!( mappingproxy .clone() .get_item(index) .unwrap() .extract::() .unwrap(), index - 1 ); } }) } #[test] fn iter_mappingproxy_nosegv() { Python::with_gil(|py| { const LEN: usize = 1_000; let items = (0..LEN as u64).map(|i| (i, i * 2)); let dict = items.clone().into_py_dict(py).unwrap(); let mappingproxy = PyMappingProxy::new(py, dict.as_mapping()); let mut sum = 0; for result in mappingproxy.try_iter().unwrap() { let (k, _v) = result.unwrap(); let i: u64 = k.extract().unwrap(); sum += i; } assert_eq!(sum, 499_500); }) } } pyo3/src/types/traceback.rs0000644000175000017500000001155515105742312015523 0ustar bdrungbdrunguse crate::err::{error_on_minusone, PyResult}; use crate::types::{any::PyAnyMethods, string::PyStringMethods, PyString}; use crate::{ffi, Bound, PyAny}; /// Represents a Python traceback. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyTraceback>`][Bound]. /// /// For APIs available on traceback objects, see the [`PyTracebackMethods`] trait which is implemented for /// [`Bound<'py, PyTraceback>`][Bound]. #[repr(transparent)] pub struct PyTraceback(PyAny); pyobject_native_type_core!( PyTraceback, pyobject_native_static_type_object!(ffi::PyTraceBack_Type), #checkfunction=ffi::PyTraceBack_Check ); /// Implementation of functionality for [`PyTraceback`]. /// /// These methods are defined for the `Bound<'py, PyTraceback>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyTraceback")] pub trait PyTracebackMethods<'py>: crate::sealed::Sealed { /// Formats the traceback as a string. /// /// This does not include the exception type and value. The exception type and value can be /// formatted using the `Display` implementation for `PyErr`. /// /// # Example /// /// The following code formats a Python traceback and exception pair from Rust: /// /// ```rust /// # use pyo3::{Python, PyResult, prelude::PyTracebackMethods, ffi::c_str}; /// # let result: PyResult<()> = /// Python::with_gil(|py| { /// let err = py /// .run(c_str!("raise Exception('banana')"), None, None) /// .expect_err("raise will create a Python error"); /// /// let traceback = err.traceback(py).expect("raised exception will have a traceback"); /// assert_eq!( /// format!("{}{}", traceback.format()?, err), /// "\ /// Traceback (most recent call last): /// File \"\", line 1, in /// Exception: banana\ /// " /// ); /// Ok(()) /// }) /// # ; /// # result.expect("example failed"); /// ``` fn format(&self) -> PyResult; } impl<'py> PyTracebackMethods<'py> for Bound<'py, PyTraceback> { fn format(&self) -> PyResult { let py = self.py(); let string_io = py .import(intern!(py, "io"))? .getattr(intern!(py, "StringIO"))? .call0()?; let result = unsafe { ffi::PyTraceBack_Print(self.as_ptr(), string_io.as_ptr()) }; error_on_minusone(py, result)?; let formatted = string_io .getattr(intern!(py, "getvalue"))? .call0()? .downcast::()? .to_cow()? .into_owned(); Ok(formatted) } } #[cfg(test)] mod tests { use crate::IntoPyObject; use crate::{ ffi, types::{any::PyAnyMethods, dict::PyDictMethods, traceback::PyTracebackMethods, PyDict}, PyErr, Python, }; #[test] fn format_traceback() { Python::with_gil(|py| { let err = py .run(ffi::c_str!("raise Exception('banana')"), None, None) .expect_err("raising should have given us an error"); assert_eq!( err.traceback(py).unwrap().format().unwrap(), "Traceback (most recent call last):\n File \"\", line 1, in \n" ); }) } #[test] fn test_err_from_value() { Python::with_gil(|py| { let locals = PyDict::new(py); // Produce an error from python so that it has a traceback py.run( ffi::c_str!( r" try: raise ValueError('raised exception') except Exception as e: err = e " ), None, Some(&locals), ) .unwrap(); let err = PyErr::from_value(locals.get_item("err").unwrap().unwrap()); let traceback = err.value(py).getattr("__traceback__").unwrap(); assert!(err.traceback(py).unwrap().is(&traceback)); }) } #[test] fn test_err_into_py() { Python::with_gil(|py| { let locals = PyDict::new(py); // Produce an error from python so that it has a traceback py.run( ffi::c_str!( r" def f(): raise ValueError('raised exception') " ), None, Some(&locals), ) .unwrap(); let f = locals.get_item("f").unwrap().unwrap(); let err = f.call0().unwrap_err(); let traceback = err.traceback(py).unwrap(); let err_object = err.clone_ref(py).into_pyobject(py).unwrap(); assert!(err_object.getattr("__traceback__").unwrap().is(&traceback)); }) } } pyo3/src/types/module.rs0000644000175000017500000004413215105742312015066 0ustar bdrungbdrunguse crate::err::{PyErr, PyResult}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::impl_::callback::IntoPyCallbackOutput; use crate::py_result_ext::PyResultExt; use crate::pyclass::PyClass; use crate::types::{ any::PyAnyMethods, list::PyListMethods, PyAny, PyCFunction, PyDict, PyList, PyString, }; use crate::{ exceptions, ffi, Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt, PyObject, Python, }; use std::ffi::CStr; #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))] use std::os::raw::c_int; use std::str; /// Represents a Python [`module`][1] object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyModule>`][Bound]. /// /// For APIs available on `module` objects, see the [`PyModuleMethods`] trait which is implemented for /// [`Bound<'py, PyModule>`][Bound]. /// /// As with all other Python objects, modules are first class citizens. /// This means they can be passed to or returned from functions, /// created dynamically, assigned to variables and so forth. /// /// [1]: https://docs.python.org/3/tutorial/modules.html #[repr(transparent)] pub struct PyModule(PyAny); pyobject_native_type_core!(PyModule, pyobject_native_static_type_object!(ffi::PyModule_Type), #checkfunction=ffi::PyModule_Check); impl PyModule { /// Creates a new module object with the `__name__` attribute set to `name`. /// /// # Examples /// /// ``` rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let module = PyModule::new(py, "my_module")?; /// /// assert_eq!(module.name()?, "my_module"); /// Ok(()) /// })?; /// # Ok(())} /// ``` pub fn new<'py>(py: Python<'py>, name: &str) -> PyResult> { let name = PyString::new(py, name); unsafe { ffi::PyModule_NewObject(name.as_ptr()) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Imports the Python module with the specified name. /// /// # Examples /// /// ```no_run /// # fn main() { /// use pyo3::prelude::*; /// /// Python::with_gil(|py| { /// let module = PyModule::import(py, "antigravity").expect("No flying for you."); /// }); /// # } /// ``` /// /// This is equivalent to the following Python expression: /// ```python /// import antigravity /// ``` /// /// If you want to import a class, you can store a reference to it with /// [`GILOnceCell::import`][crate::sync::GILOnceCell#method.import]. pub fn import<'py, N>(py: Python<'py>, name: N) -> PyResult> where N: IntoPyObject<'py, Target = PyString>, { let name = name.into_pyobject_or_pyerr(py)?; unsafe { ffi::PyImport_Import(name.as_ptr()) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Creates and loads a module named `module_name`, /// containing the Python code passed to `code` /// and pretending to live at `file_name`. /// ///