Vendor dependencies
Let's see how I like this workflow.
This commit is contained in:
parent
34d1830413
commit
9c435dc440
7500 changed files with 1665121 additions and 99 deletions
1
vendor/rustix/.cargo-checksum.json
vendored
Normal file
1
vendor/rustix/.cargo-checksum.json
vendored
Normal file
File diff suppressed because one or more lines are too long
49
vendor/rustix/CODE_OF_CONDUCT.md
vendored
Normal file
49
vendor/rustix/CODE_OF_CONDUCT.md
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
*Note*: this Code of Conduct pertains to individuals' behavior. Please also see the [Organizational Code of Conduct][OCoC].
|
||||
|
||||
## 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, gender identity and expression, level of experience, 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 Bytecode Alliance CoC team at [report@bytecodealliance.org](mailto:report@bytecodealliance.org). The CoC team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The CoC 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 Bytecode Alliance's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[OCoC]: https://github.com/bytecodealliance/rustix/blob/main/ORG_CODE_OF_CONDUCT.md
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[version]: https://www.contributor-covenant.org/version/1/4/
|
||||
27
vendor/rustix/CONTRIBUTING.md
vendored
Normal file
27
vendor/rustix/CONTRIBUTING.md
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Contributing to rustix
|
||||
|
||||
Rustix is a [Bytecode Alliance] project. It follows the Bytecode Alliance's
|
||||
[Code of Conduct] and [Organizational Code of Conduct].
|
||||
|
||||
## Testing
|
||||
|
||||
To keep compile times low, most features in rustix's API are behind cargo
|
||||
features. A special feature, `all-apis` enables all APIs, which is useful
|
||||
for testing.
|
||||
|
||||
```
|
||||
cargo test --features=all-apis
|
||||
```
|
||||
|
||||
And, rustix has two backends, linux_raw and libc, and only one is used in
|
||||
any given build. To test with the libc backend explicitly, additionally
|
||||
enable the `use-libc` feature:
|
||||
|
||||
```
|
||||
cargo test --features=all-apis,use-libc
|
||||
```
|
||||
|
||||
Beyond that, rustix's CI tests many targets and configurations. Asking for
|
||||
help is always welcome, and it's especially encouraged when the issue is
|
||||
getting all the `cfg`s lined up to get everything compiling on all the
|
||||
configurations on CI.
|
||||
29
vendor/rustix/COPYRIGHT
vendored
Normal file
29
vendor/rustix/COPYRIGHT
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
Short version for non-lawyers:
|
||||
|
||||
`rustix` is triple-licensed under Apache 2.0 with the LLVM Exception,
|
||||
Apache 2.0, and MIT terms.
|
||||
|
||||
|
||||
Longer version:
|
||||
|
||||
Copyrights in the `rustix` project are retained by their contributors.
|
||||
No copyright assignment is required to contribute to the `rustix`
|
||||
project.
|
||||
|
||||
Some files include code derived from Rust's `libstd`; see the comments in
|
||||
the code for details.
|
||||
|
||||
Except as otherwise noted (below and/or in individual files), `rustix`
|
||||
is licensed under:
|
||||
|
||||
- the Apache License, Version 2.0, with the LLVM Exception
|
||||
<LICENSE-Apache-2.0_WITH_LLVM-exception> or
|
||||
<http://llvm.org/foundation/relicensing/LICENSE.txt>
|
||||
- the Apache License, Version 2.0
|
||||
<LICENSE-APACHE> or
|
||||
<http://www.apache.org/licenses/LICENSE-2.0>,
|
||||
- or the MIT license
|
||||
<LICENSE-MIT> or
|
||||
<http://opensource.org/licenses/MIT>,
|
||||
|
||||
at your option.
|
||||
236
vendor/rustix/Cargo.toml
vendored
Normal file
236
vendor/rustix/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
# 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.48"
|
||||
name = "rustix"
|
||||
version = "0.36.5"
|
||||
authors = [
|
||||
"Dan Gohman <dev@sunfishcode.online>",
|
||||
"Jakub Konka <kubkon@jakubkonka.com>",
|
||||
]
|
||||
include = [
|
||||
"src",
|
||||
"build.rs",
|
||||
"Cargo.toml",
|
||||
"COPYRIGHT",
|
||||
"LICENSE*",
|
||||
"/*.md",
|
||||
"benches",
|
||||
]
|
||||
description = "Safe Rust bindings to POSIX/Unix/Linux/Winsock2-like syscalls"
|
||||
documentation = "https://docs.rs/rustix"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"api",
|
||||
"file",
|
||||
"network",
|
||||
"safe",
|
||||
"syscall",
|
||||
]
|
||||
categories = [
|
||||
"os::unix-apis",
|
||||
"date-and-time",
|
||||
"filesystem",
|
||||
"network-programming",
|
||||
]
|
||||
license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT"
|
||||
repository = "https://github.com/bytecodealliance/rustix"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["all-apis"]
|
||||
rustdoc-args = [
|
||||
"--cfg",
|
||||
"doc_cfg",
|
||||
]
|
||||
targets = [
|
||||
"x86_64-unknown-linux-gnu",
|
||||
"i686-unknown-linux-gnu",
|
||||
"x86_64-apple-darwin",
|
||||
"x86_64-pc-windows-msvc",
|
||||
]
|
||||
|
||||
[[bench]]
|
||||
name = "mod"
|
||||
harness = false
|
||||
|
||||
[dependencies.alloc]
|
||||
version = "1.0.0"
|
||||
optional = true
|
||||
package = "rustc-std-workspace-alloc"
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "1.2.1"
|
||||
|
||||
[dependencies.compiler_builtins]
|
||||
version = "0.1.49"
|
||||
optional = true
|
||||
|
||||
[dependencies.core]
|
||||
version = "1.0.0"
|
||||
optional = true
|
||||
package = "rustc-std-workspace-core"
|
||||
|
||||
[dependencies.io-lifetimes]
|
||||
version = "1.0.0"
|
||||
features = ["close"]
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.itoa]
|
||||
version = "1.0.1"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.flate2]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.io-lifetimes]
|
||||
version = "1.0.0"
|
||||
features = ["close"]
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.libc]
|
||||
version = "0.2.133"
|
||||
|
||||
[dev-dependencies.libc_errno]
|
||||
version = "0.2.8"
|
||||
default-features = false
|
||||
package = "errno"
|
||||
|
||||
[dev-dependencies.memoffset]
|
||||
version = "0.7.1"
|
||||
|
||||
[dev-dependencies.serial_test]
|
||||
version = "0.6"
|
||||
|
||||
[dev-dependencies.tempfile]
|
||||
version = "3.2.0"
|
||||
|
||||
[build-dependencies.cc]
|
||||
version = "1.0.68"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
all-apis = [
|
||||
"fs",
|
||||
"io_uring",
|
||||
"mm",
|
||||
"net",
|
||||
"param",
|
||||
"process",
|
||||
"procfs",
|
||||
"rand",
|
||||
"runtime",
|
||||
"termios",
|
||||
"thread",
|
||||
"time",
|
||||
]
|
||||
all-impls = [
|
||||
"os_pipe",
|
||||
"fs-err",
|
||||
]
|
||||
default = [
|
||||
"std",
|
||||
"use-libc-auxv",
|
||||
]
|
||||
fs = []
|
||||
fs-err = ["io-lifetimes/fs-err"]
|
||||
io_uring = [
|
||||
"fs",
|
||||
"net",
|
||||
]
|
||||
mm = []
|
||||
net = []
|
||||
os_pipe = ["io-lifetimes/os_pipe"]
|
||||
param = ["fs"]
|
||||
process = []
|
||||
procfs = [
|
||||
"once_cell",
|
||||
"itoa",
|
||||
"fs",
|
||||
]
|
||||
rand = []
|
||||
runtime = []
|
||||
rustc-dep-of-std = [
|
||||
"core",
|
||||
"alloc",
|
||||
"compiler_builtins",
|
||||
"linux-raw-sys/rustc-dep-of-std",
|
||||
"bitflags/rustc-dep-of-std",
|
||||
]
|
||||
std = ["io-lifetimes"]
|
||||
termios = []
|
||||
thread = []
|
||||
time = []
|
||||
use-libc = [
|
||||
"libc_errno",
|
||||
"libc",
|
||||
]
|
||||
use-libc-auxv = ["libc"]
|
||||
|
||||
[target."cfg(all(any(target_os = \"android\", target_os = \"linux\"), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"), all(target_endian = \"little\", any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"powerpc64\", target_arch = \"riscv64\", target_arch = \"mips\", target_arch = \"mips64\"))))))))".dependencies.linux-raw-sys]
|
||||
version = "0.1.2"
|
||||
features = [
|
||||
"general",
|
||||
"no_std",
|
||||
]
|
||||
default-features = false
|
||||
|
||||
[target."cfg(all(criterion, not(any(target_os = \"emscripten\", target_os = \"wasi\"))))".dev-dependencies.criterion]
|
||||
version = "0.4"
|
||||
|
||||
[target."cfg(all(not(rustix_use_libc), not(miri), target_os = \"linux\", any(target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"), all(target_endian = \"little\", any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"powerpc64\", target_arch = \"riscv64\", target_arch = \"mips\", target_arch = \"mips64\")))))".dependencies.libc]
|
||||
version = "0.2.133"
|
||||
features = ["extra_traits"]
|
||||
optional = true
|
||||
|
||||
[target."cfg(all(not(rustix_use_libc), not(miri), target_os = \"linux\", any(target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"), all(target_endian = \"little\", any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"powerpc64\", target_arch = \"riscv64\", target_arch = \"mips\", target_arch = \"mips64\")))))".dependencies.libc_errno]
|
||||
version = "0.2.8"
|
||||
optional = true
|
||||
default-features = false
|
||||
package = "errno"
|
||||
|
||||
[target."cfg(all(not(rustix_use_libc), not(miri), target_os = \"linux\", any(target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"), all(target_endian = \"little\", any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"powerpc64\", target_arch = \"riscv64\", target_arch = \"mips\", target_arch = \"mips64\")))))".dependencies.linux-raw-sys]
|
||||
version = "0.1.2"
|
||||
features = [
|
||||
"general",
|
||||
"errno",
|
||||
"ioctl",
|
||||
"no_std",
|
||||
]
|
||||
default-features = false
|
||||
|
||||
[target."cfg(any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"), all(target_endian = \"little\", any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"powerpc64\", target_arch = \"riscv64\", target_arch = \"mips\", target_arch = \"mips64\")))))))".dependencies.libc]
|
||||
version = "0.2.133"
|
||||
features = ["extra_traits"]
|
||||
|
||||
[target."cfg(any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"), all(target_endian = \"little\", any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"powerpc64\", target_arch = \"riscv64\", target_arch = \"mips\", target_arch = \"mips64\")))))))".dependencies.libc_errno]
|
||||
version = "0.2.8"
|
||||
default-features = false
|
||||
package = "errno"
|
||||
|
||||
[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dependencies.once_cell]
|
||||
version = "1.5.2"
|
||||
optional = true
|
||||
|
||||
[target."cfg(windows)".dependencies.windows-sys]
|
||||
version = "0.42.0"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Networking_WinSock",
|
||||
"Win32_NetworkManagement_IpHelper",
|
||||
"Win32_System_Threading",
|
||||
]
|
||||
|
||||
[target."cfg(windows)".dev-dependencies.ctor]
|
||||
version = "0.1.21"
|
||||
201
vendor/rustix/LICENSE-APACHE
vendored
Normal file
201
vendor/rustix/LICENSE-APACHE
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
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.
|
||||
220
vendor/rustix/LICENSE-Apache-2.0_WITH_LLVM-exception
vendored
Normal file
220
vendor/rustix/LICENSE-Apache-2.0_WITH_LLVM-exception
vendored
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
|
||||
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.
|
||||
|
||||
|
||||
--- LLVM Exceptions to the Apache 2.0 License ----
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into an Object form of such source code, you
|
||||
may redistribute such embedded portions in such Object form without complying
|
||||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision (Section
|
||||
3), the indemnity provision (Section 9) or other Section of the License
|
||||
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||
the License, but only in their entirety and only with respect to the Combined
|
||||
Software.
|
||||
|
||||
23
vendor/rustix/LICENSE-MIT
vendored
Normal file
23
vendor/rustix/LICENSE-MIT
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
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.
|
||||
143
vendor/rustix/ORG_CODE_OF_CONDUCT.md
vendored
Normal file
143
vendor/rustix/ORG_CODE_OF_CONDUCT.md
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
# Bytecode Alliance Organizational Code of Conduct (OCoC)
|
||||
|
||||
*Note*: this Code of Conduct pertains to organizations' behavior. Please also see the [Individual Code of Conduct](CODE_OF_CONDUCT.md).
|
||||
|
||||
## Preamble
|
||||
|
||||
The Bytecode Alliance (BA) welcomes involvement from organizations,
|
||||
including commercial organizations. This document is an
|
||||
*organizational* code of conduct, intended particularly to provide
|
||||
guidance to commercial organizations. It is distinct from the
|
||||
[Individual Code of Conduct (ICoC)](CODE_OF_CONDUCT.md), and does not
|
||||
replace the ICoC. This OCoC applies to any group of people acting in
|
||||
concert as a BA member or as a participant in BA activities, whether
|
||||
or not that group is formally incorporated in some jurisdiction.
|
||||
|
||||
The code of conduct described below is not a set of rigid rules, and
|
||||
we did not write it to encompass every conceivable scenario that might
|
||||
arise. For example, it is theoretically possible there would be times
|
||||
when asserting patents is in the best interest of the BA community as
|
||||
a whole. In such instances, consult with the BA, strive for
|
||||
consensus, and interpret these rules with an intent that is generous
|
||||
to the community the BA serves.
|
||||
|
||||
While we may revise these guidelines from time to time based on
|
||||
real-world experience, overall they are based on a simple principle:
|
||||
|
||||
*Bytecode Alliance members should observe the distinction between
|
||||
public community functions and private functions — especially
|
||||
commercial ones — and should ensure that the latter support, or at
|
||||
least do not harm, the former.*
|
||||
|
||||
## Guidelines
|
||||
|
||||
* **Do not cause confusion about Wasm standards or interoperability.**
|
||||
|
||||
Having an interoperable WebAssembly core is a high priority for
|
||||
the BA, and members should strive to preserve that core. It is fine
|
||||
to develop additional non-standard features or APIs, but they
|
||||
should always be clearly distinguished from the core interoperable
|
||||
Wasm.
|
||||
|
||||
Treat the WebAssembly name and any BA-associated names with
|
||||
respect, and follow BA trademark and branding guidelines. If you
|
||||
distribute a customized version of software originally produced by
|
||||
the BA, or if you build a product or service using BA-derived
|
||||
software, use names that clearly distinguish your work from the
|
||||
original. (You should still provide proper attribution to the
|
||||
original, of course, wherever such attribution would normally be
|
||||
given.)
|
||||
|
||||
Further, do not use the WebAssembly name or BA-associated names in
|
||||
other public namespaces in ways that could cause confusion, e.g.,
|
||||
in company names, names of commercial service offerings, domain
|
||||
names, publicly-visible social media accounts or online service
|
||||
accounts, etc. It may sometimes be reasonable, however, to
|
||||
register such a name in a new namespace and then immediately donate
|
||||
control of that account to the BA, because that would help the project
|
||||
maintain its identity.
|
||||
|
||||
For further guidance, see the BA Trademark and Branding Policy
|
||||
[TODO: create policy, then insert link].
|
||||
|
||||
* **Do not restrict contributors.** If your company requires
|
||||
employees or contractors to sign non-compete agreements, those
|
||||
agreements must not prevent people from participating in the BA or
|
||||
contributing to related projects.
|
||||
|
||||
This does not mean that all non-compete agreements are incompatible
|
||||
with this code of conduct. For example, a company may restrict an
|
||||
employee's ability to solicit the company's customers. However, an
|
||||
agreement must not block any form of technical or social
|
||||
participation in BA activities, including but not limited to the
|
||||
implementation of particular features.
|
||||
|
||||
The accumulation of experience and expertise in individual persons,
|
||||
who are ultimately free to direct their energy and attention as
|
||||
they decide, is one of the most important drivers of progress in
|
||||
open source projects. A company that limits this freedom may hinder
|
||||
the success of the BA's efforts.
|
||||
|
||||
* **Do not use patents as offensive weapons.** If any BA participant
|
||||
prevents the adoption or development of BA technologies by
|
||||
asserting its patents, that undermines the purpose of the
|
||||
coalition. The collaboration fostered by the BA cannot include
|
||||
members who act to undermine its work.
|
||||
|
||||
* **Practice responsible disclosure** for security vulnerabilities.
|
||||
Use designated, non-public reporting channels to disclose technical
|
||||
vulnerabilities, and give the project a reasonable period to
|
||||
respond, remediate, and patch. [TODO: optionally include the
|
||||
security vulnerability reporting URL here.]
|
||||
|
||||
Vulnerability reporters may patch their company's own offerings, as
|
||||
long as that patching does not significantly delay the reporting of
|
||||
the vulnerability. Vulnerability information should never be used
|
||||
for unilateral commercial advantage. Vendors may legitimately
|
||||
compete on the speed and reliability with which they deploy
|
||||
security fixes, but withholding vulnerability information damages
|
||||
everyone in the long run by risking harm to the BA project's
|
||||
reputation and to the security of all users.
|
||||
|
||||
* **Respect the letter and spirit of open source practice.** While
|
||||
there is not space to list here all possible aspects of standard
|
||||
open source practice, some examples will help show what we mean:
|
||||
|
||||
* Abide by all applicable open source license terms. Do not engage
|
||||
in copyright violation or misattribution of any kind.
|
||||
|
||||
* Do not claim others' ideas or designs as your own.
|
||||
|
||||
* When others engage in publicly visible work (e.g., an upcoming
|
||||
demo that is coordinated in a public issue tracker), do not
|
||||
unilaterally announce early releases or early demonstrations of
|
||||
that work ahead of their schedule in order to secure private
|
||||
advantage (such as marketplace advantage) for yourself.
|
||||
|
||||
The BA reserves the right to determine what constitutes good open
|
||||
source practices and to take action as it deems appropriate to
|
||||
encourage, and if necessary enforce, such practices.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of organizational behavior in violation of the OCoC may
|
||||
be reported by contacting the Bytecode Alliance CoC team at
|
||||
[report@bytecodealliance.org](mailto:report@bytecodealliance.org). The
|
||||
CoC team will review and investigate all complaints, and will respond
|
||||
in a way that it deems appropriate to the circumstances. The CoC team
|
||||
is obligated to maintain confidentiality with regard to the reporter of
|
||||
an incident. Further details of specific enforcement policies may be
|
||||
posted separately.
|
||||
|
||||
When the BA deems an organization in violation of this OCoC, the BA
|
||||
will, at its sole discretion, determine what action to take. The BA
|
||||
will decide what type, degree, and duration of corrective action is
|
||||
needed, if any, before a violating organization can be considered for
|
||||
membership (if it was not already a member) or can have its membership
|
||||
reinstated (if it was a member and the BA canceled its membership due
|
||||
to the violation).
|
||||
|
||||
In practice, the BA's first approach will be to start a conversation,
|
||||
with punitive enforcement used only as a last resort. Violations
|
||||
often turn out to be unintentional and swiftly correctable with all
|
||||
parties acting in good faith.
|
||||
159
vendor/rustix/README.md
vendored
Normal file
159
vendor/rustix/README.md
vendored
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
<div align="center">
|
||||
<h1><code>rustix</code></h1>
|
||||
|
||||
<p>
|
||||
<strong>Safe Rust bindings to POSIX/Unix/Linux/Winsock2 syscalls</strong>
|
||||
</p>
|
||||
|
||||
<strong>A <a href="https://bytecodealliance.org/">Bytecode Alliance</a> project</strong>
|
||||
|
||||
<p>
|
||||
<a href="https://github.com/bytecodealliance/rustix/actions?query=workflow%3ACI"><img src="https://github.com/bytecodealliance/rustix/workflows/CI/badge.svg" alt="Github Actions CI Status" /></a>
|
||||
<a href="https://bytecodealliance.zulipchat.com/#narrow/stream/206238-general"><img src="https://img.shields.io/badge/zulip-join_chat-brightgreen.svg" alt="zulip chat" /></a>
|
||||
<a href="https://crates.io/crates/rustix"><img src="https://img.shields.io/crates/v/rustix.svg" alt="crates.io page" /></a>
|
||||
<a href="https://docs.rs/rustix"><img src="https://docs.rs/rustix/badge.svg" alt="docs.rs docs" /></a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
`rustix` provides efficient memory-safe and [I/O-safe] wrappers to POSIX-like,
|
||||
Unix-like, Linux, and Winsock2 syscall-like APIs, with configurable backends.
|
||||
It uses Rust references, slices, and return values instead of raw pointers, and
|
||||
[`io-lifetimes`] instead of raw file descriptors, providing memory safety,
|
||||
[I/O safety], and [provenance]. It uses `Result`s for reporting errors,
|
||||
[`bitflags`] instead of bare integer flags, an [`Arg`] trait with optimizations
|
||||
to efficiently accept any Rust string type, and several other efficient
|
||||
conveniences.
|
||||
|
||||
`rustix` is low-level and, and while the `net` API supports Winsock2 on
|
||||
Windows, the rest of the APIs do not support Windows; for higher-level and more
|
||||
portable APIs built on this functionality, see the [`system-interface`],
|
||||
[`cap-std`], and [`fs-set-times`] crates, for example.
|
||||
|
||||
`rustix` currently has two backends available:
|
||||
|
||||
* linux_raw, which uses raw Linux system calls and vDSO calls, and is
|
||||
supported on Linux on x86-64, x86, aarch64, riscv64gc, powerpc64le,
|
||||
arm (v5 onwards), mipsel, and mips64el, with stable, nightly, and 1.48 Rust.
|
||||
- By being implemented entirely in Rust, avoiding `libc`, `errno`, and pthread
|
||||
cancellation, and employing some specialized optimizations, most functions
|
||||
compile down to very efficient code. On nightly Rust, they can often be
|
||||
fully inlined into user code.
|
||||
- Most functions in `linux_raw` preserve memory, I/O safety, and pointer
|
||||
provenance all the way down to the syscalls.
|
||||
|
||||
* libc, which uses the [`libc`] crate which provides bindings to native `libc`
|
||||
libraries on Unix-family platforms, and [`windows-sys`] for Winsock2 on
|
||||
Windows, and is portable to many OS's.
|
||||
|
||||
The linux_raw backend is enabled by default on platforms which support it. To
|
||||
enable the libc backend instead, either enable the "use-libc" cargo feature,
|
||||
or set the `RUSTFLAGS` environment variable to `--cfg=rustix_use_libc` when
|
||||
building.
|
||||
|
||||
## Cargo features
|
||||
|
||||
The modules [`rustix::io`], [`rustix::fd`], and [`rustix::ffi`] are enabled
|
||||
by default. The rest of the API is conditional with cargo feature flags:
|
||||
|
||||
| Name | Description
|
||||
| ---------- | ---------------------
|
||||
| `fs` | [`rustix::fs`] and [`rustix::path`]—Filesystem operations.
|
||||
| `io_uring` | [`rustix::io_uring`]—Linux io_uring.
|
||||
| `mm` | [`rustix::mm`]—Memory map operations.
|
||||
| `net` | [`rustix::net`] and [`rustix::path`]—Network-related operations.
|
||||
| `param` | [`rustix::param`]—Process parameters.
|
||||
| `process` | [`rustix::process`]—Process-associated operations.
|
||||
| `rand` | [`rustix::rand`]—Random-related operations.
|
||||
| `termios` | [`rustix::termios`]—Terminal I/O stream operations.
|
||||
| `thread` | [`rustix::thread`]—Thread-associated operations.
|
||||
| `time` | [`rustix::time`]—Time-related operations.
|
||||
| |
|
||||
| `use-libc` | Enable the libc backend.
|
||||
|
||||
[`rustix::fs`]: https://docs.rs/rustix/latest/rustix/fs/index.html
|
||||
[`rustix::io_uring`]: https://docs.rs/rustix/latest/rustix/io_uring/index.html
|
||||
[`rustix::mm`]: https://docs.rs/rustix/latest/rustix/mm/index.html
|
||||
[`rustix::net`]: https://docs.rs/rustix/latest/rustix/net/index.html
|
||||
[`rustix::param`]: https://docs.rs/rustix/latest/rustix/param/index.html
|
||||
[`rustix::process`]: https://docs.rs/rustix/latest/rustix/process/index.html
|
||||
[`rustix::rand`]: https://docs.rs/rustix/latest/rustix/rand/index.html
|
||||
[`rustix::termios`]: https://docs.rs/rustix/latest/rustix/termios/index.html
|
||||
[`rustix::thread`]: https://docs.rs/rustix/latest/rustix/thread/index.html
|
||||
[`rustix::time`]: https://docs.rs/rustix/latest/rustix/time/index.html
|
||||
[`rustix::io`]: https://docs.rs/rustix/latest/rustix/io/index.html
|
||||
[`rustix::fd`]: https://docs.rs/rustix/latest/rustix/fd/index.html
|
||||
[`rustix::ffi`]: https://docs.rs/rustix/latest/rustix/ffi/index.html
|
||||
[`rustix::path`]: https://docs.rs/rustix/latest/rustix/path/index.html
|
||||
|
||||
## Similar crates
|
||||
|
||||
`rustix` is similar to [`nix`], [`simple_libc`], [`unix`], [`nc`], and
|
||||
[`uapi`]. `rustix` is architected for [I/O safety] with most APIs using
|
||||
[`OwnedFd`] and [`AsFd`] to manipulate file descriptors rather than `File` or
|
||||
even `c_int`, and supporting multiple backends so that it can use direct
|
||||
syscalls while still being usable on all platforms `libc` supports. Like `nix`,
|
||||
`rustix` has an optimized and flexible filename argument mechanism that allows
|
||||
users to use a variety of string types, including non-UTF-8 string types.
|
||||
|
||||
[`relibc`] is a similar project which aims to be a full "libc", including
|
||||
C-compatible interfaces and higher-level C/POSIX standard-library
|
||||
functionality; `rustix` just aims to provide safe and idiomatic Rust interfaces
|
||||
to low-level syscalls. `relibc` also doesn't tend to support features not
|
||||
supported on Redox, such as `*at` functions like `openat`, which are important
|
||||
features for `rustix`.
|
||||
|
||||
`rustix` has its own code for making direct syscalls, similar to the [`sc`] and
|
||||
[`scall`] crates, though `rustix` can use either the Rust `asm!` macro or
|
||||
out-of-line `.s` files so it supports Rust versions from 1.48 though Nightly.
|
||||
`rustix` can also use Linux's vDSO mechanism to optimize Linux `clock_gettime`
|
||||
on all architectures, and all Linux system calls on x86. And `rustix`'s
|
||||
syscalls report errors using an optimized `Errno` type.
|
||||
|
||||
`rustix`'s `*at` functions are similar to the [`openat`] crate, but `rustix`
|
||||
provides them as free functions rather than associated functions of a `Dir`
|
||||
type. `rustix`'s `cwd()` function exposes the special `AT_FDCWD` value in a safe
|
||||
way, so users don't need to open `.` to get a current-directory handle.
|
||||
|
||||
`rustix`'s `openat2` function is similar to the [`openat2`] crate, but uses
|
||||
I/O safety types rather than `RawFd`. `rustix` does not provide dynamic feature
|
||||
detection, so users must handle the [`NOSYS`] error themselves.
|
||||
|
||||
`rustix`'s `termios` module is similar to the [`termios`] crate, but uses
|
||||
I/O safety types rather than `RawFd`, and the flags parameters to functions
|
||||
such as `tcsetattr` are `enum`s rather than bare integers. And, rustix calls
|
||||
its `tcgetattr` function `tcgetattr`, rather than `Termios::from_fd`.
|
||||
|
||||
## Minimum Supported Rust Version (MSRV)
|
||||
|
||||
This crate currently works on the version of [Rust on Debian stable], which is
|
||||
currently Rust 1.48. This policy may change in the future, in minor version
|
||||
releases, so users using a fixed version of Rust should pin to a specific
|
||||
version of this crate.
|
||||
|
||||
[Rust on Debian stable]: https://packages.debian.org/stable/rust/rustc
|
||||
[`nix`]: https://crates.io/crates/nix
|
||||
[`unix`]: https://crates.io/crates/unix
|
||||
[`nc`]: https://crates.io/crates/nc
|
||||
[`simple_libc`]: https://crates.io/crates/simple_libc
|
||||
[`uapi`]: https://crates.io/crates/uapi
|
||||
[`relibc`]: https://github.com/redox-os/relibc
|
||||
[`syscall`]: https://crates.io/crates/syscall
|
||||
[`sc`]: https://crates.io/crates/sc
|
||||
[`scall`]: https://crates.io/crates/scall
|
||||
[`system-interface`]: https://crates.io/crates/system-interface
|
||||
[`openat`]: https://crates.io/crates/openat
|
||||
[`openat2`]: https://crates.io/crates/openat2
|
||||
[`fs-set-times`]: https://crates.io/crates/fs-set-times
|
||||
[`io-lifetimes`]: https://crates.io/crates/io-lifetimes
|
||||
[`termios`]: https://crates.io/crates/termios
|
||||
[`libc`]: https://crates.io/crates/libc
|
||||
[`windows-sys`]: https://crates.io/crates/windows-sys
|
||||
[`cap-std`]: https://crates.io/crates/cap-std
|
||||
[`bitflags`]: https://crates.io/crates/bitflags
|
||||
[`Arg`]: https://docs.rs/rustix/latest/rustix/path/trait.Arg.html
|
||||
[I/O-safe]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md
|
||||
[I/O safety]: https://github.com/rust-lang/rfcs/blob/master/text/3128-io-safety.md
|
||||
[provenance]: https://github.com/rust-lang/rust/issues/95228
|
||||
[`OwnedFd`]: https://docs.rs/io-lifetimes/latest/io_lifetimes/struct.OwnedFd.html
|
||||
[`AsFd`]: https://docs.rs/io-lifetimes/latest/io_lifetimes/trait.AsFd.html
|
||||
[`NOSYS`]: https://docs.rs/rustix/latest/rustix/io/struct.Errno.html#associatedconstant.NOSYS
|
||||
29
vendor/rustix/SECURITY.md
vendored
Normal file
29
vendor/rustix/SECURITY.md
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Security Policy
|
||||
|
||||
Building secure foundations for software development is at the core of what we do in the Bytecode Alliance. Contributions of external security researchers are a vital part of that.
|
||||
|
||||
## Scope
|
||||
|
||||
If you believe you've found a security issue in any website, service, or software owned or operated by the Bytecode Alliance, we encourage you to notify us.
|
||||
|
||||
## How to Submit a Report
|
||||
|
||||
To submit a vulnerability report to the Bytecode Alliance, please contact us at [security@bytecodealliance.org](mailto:security@bytecodealliance.org). Your submission will be reviewed and validated by a member of our security team.
|
||||
|
||||
## Safe Harbor
|
||||
|
||||
The Bytecode Alliance supports safe harbor for security researchers who:
|
||||
|
||||
* Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our services.
|
||||
* Only interact with accounts you own or with explicit permission of the account holder. If you do encounter Personally Identifiable Information (PII) contact us immediately, do not proceed with access, and immediately purge any local information.
|
||||
* Provide us with a reasonable amount of time to resolve vulnerabilities prior to any disclosure to the public or a third-party.
|
||||
|
||||
We will consider activities conducted consistent with this policy to constitute "authorized" conduct and will not pursue civil action or initiate a complaint to law enforcement. We will help to the extent we can if legal action is initiated by a third party against you.
|
||||
|
||||
Please submit a report to us before engaging in conduct that may be inconsistent with or unaddressed by this policy.
|
||||
|
||||
## Preferences
|
||||
|
||||
* Please provide detailed reports with reproducible steps and a clearly defined impact.
|
||||
* Submit one vulnerability per report.
|
||||
* Social engineering (e.g. phishing, vishing, smishing) is prohibited.
|
||||
182
vendor/rustix/benches/mod.rs
vendored
Normal file
182
vendor/rustix/benches/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/// Benchmarks for rustix.
|
||||
///
|
||||
/// To enable these benchmarks, add `--cfg=criterion` to RUSTFLAGS and enable
|
||||
/// the "fs", "time", and "process" cargo features.
|
||||
|
||||
#[cfg(any(
|
||||
not(criterion),
|
||||
not(feature = "fs"),
|
||||
not(feature = "process"),
|
||||
not(feature = "time"),
|
||||
windows,
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
))]
|
||||
fn main() {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
not(criterion),
|
||||
not(feature = "fs"),
|
||||
not(feature = "process"),
|
||||
not(feature = "time"),
|
||||
windows,
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
use criterion::{criterion_group, criterion_main};
|
||||
|
||||
#[cfg(not(any(
|
||||
not(criterion),
|
||||
not(feature = "fs"),
|
||||
not(feature = "process"),
|
||||
not(feature = "time"),
|
||||
windows,
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
mod suite {
|
||||
use criterion::Criterion;
|
||||
|
||||
pub(super) fn simple_statat(c: &mut Criterion) {
|
||||
use rustix::fs::{cwd, statat, AtFlags};
|
||||
|
||||
c.bench_function("simple statat", |b| {
|
||||
b.iter(|| {
|
||||
statat(cwd(), "/", AtFlags::empty()).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) fn simple_statat_libc(c: &mut Criterion) {
|
||||
c.bench_function("simple statat libc", |b| {
|
||||
b.iter(|| {
|
||||
let mut s = std::mem::MaybeUninit::<libc::stat>::uninit();
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
libc::fstatat(
|
||||
libc::AT_FDCWD,
|
||||
std::ffi::CString::new("/").unwrap().as_c_str().as_ptr() as _,
|
||||
s.as_mut_ptr(),
|
||||
0
|
||||
),
|
||||
0
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) fn simple_statat_libc_cstr(c: &mut Criterion) {
|
||||
c.bench_function("simple statat libc cstr", |b| {
|
||||
b.iter(|| {
|
||||
let mut s = std::mem::MaybeUninit::<libc::stat>::uninit();
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
libc::fstatat(
|
||||
libc::AT_FDCWD,
|
||||
rustix::cstr!("/").as_ptr() as _,
|
||||
s.as_mut_ptr(),
|
||||
0
|
||||
),
|
||||
0
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
pub(super) fn simple_statat_cstr(c: &mut Criterion) {
|
||||
use rustix::fs::{cwd, statat, AtFlags};
|
||||
|
||||
c.bench_function("simple statat cstr", |b| {
|
||||
b.iter(|| {
|
||||
statat(cwd(), rustix::cstr!("/"), AtFlags::empty()).unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(super) fn simple_clock_gettime(c: &mut Criterion) {
|
||||
use rustix::time::{clock_gettime, ClockId};
|
||||
|
||||
c.bench_function("simple clock_gettime", |b| {
|
||||
b.iter(|| {
|
||||
let _ = clock_gettime(ClockId::Monotonic);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(super) fn simple_clock_gettime_libc(c: &mut Criterion) {
|
||||
c.bench_function("simple clock_gettime libc", |b| {
|
||||
b.iter(|| {
|
||||
let mut s = std::mem::MaybeUninit::<libc::timespec>::uninit();
|
||||
unsafe {
|
||||
assert_eq!(
|
||||
libc::clock_gettime(libc::CLOCK_MONOTONIC, s.as_mut_ptr()),
|
||||
0
|
||||
);
|
||||
let _ = s.assume_init();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(super) fn simple_getpid(c: &mut Criterion) {
|
||||
use rustix::process::getpid;
|
||||
|
||||
c.bench_function("simple getpid", |b| {
|
||||
b.iter(|| {
|
||||
let _ = getpid();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(super) fn simple_getpid_libc(c: &mut Criterion) {
|
||||
c.bench_function("simple getpid libc", |b| {
|
||||
b.iter(|| unsafe {
|
||||
let _ = libc::getpid();
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
not(criterion),
|
||||
not(feature = "fs"),
|
||||
not(feature = "process"),
|
||||
not(feature = "time"),
|
||||
windows,
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
criterion_group!(
|
||||
benches,
|
||||
suite::simple_statat,
|
||||
suite::simple_statat_libc,
|
||||
suite::simple_statat_libc_cstr,
|
||||
suite::simple_statat_cstr,
|
||||
suite::simple_clock_gettime,
|
||||
suite::simple_clock_gettime_libc,
|
||||
suite::simple_getpid,
|
||||
suite::simple_getpid_libc
|
||||
);
|
||||
#[cfg(not(any(
|
||||
not(criterion),
|
||||
not(feature = "fs"),
|
||||
not(feature = "process"),
|
||||
not(feature = "time"),
|
||||
windows,
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
criterion_main!(benches);
|
||||
205
vendor/rustix/build.rs
vendored
Normal file
205
vendor/rustix/build.rs
vendored
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
#[cfg(feature = "cc")]
|
||||
use cc::Build;
|
||||
use std::env::var;
|
||||
use std::io::Write;
|
||||
|
||||
/// The directory for out-of-line ("outline") libraries.
|
||||
const OUTLINE_PATH: &str = "src/backend/linux_raw/arch/outline";
|
||||
|
||||
fn main() {
|
||||
// Don't rerun this on changes other than build.rs, as we only depend on
|
||||
// the rustc version.
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
use_feature_or_nothing("rustc_attrs");
|
||||
|
||||
// Features only used in no-std configurations.
|
||||
#[cfg(not(feature = "std"))]
|
||||
{
|
||||
use_feature_or_nothing("const_raw_ptr_deref");
|
||||
use_feature_or_nothing("core_ffi_c");
|
||||
use_feature_or_nothing("core_c_str");
|
||||
use_feature_or_nothing("alloc_c_string");
|
||||
}
|
||||
|
||||
// Gather target information.
|
||||
let arch = var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
let asm_name = format!("{}/{}.s", OUTLINE_PATH, arch);
|
||||
let asm_name_present = std::fs::metadata(&asm_name).is_ok();
|
||||
let os_name = var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
let pointer_width = var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
|
||||
let endian = var("CARGO_CFG_TARGET_ENDIAN").unwrap();
|
||||
|
||||
// Check for special target variants.
|
||||
let is_x32 = arch == "x86_64" && pointer_width == "32";
|
||||
let is_arm64_ilp32 = arch == "aarch64" && pointer_width == "32";
|
||||
let is_powerpc64be = arch == "powerpc64" && endian == "big";
|
||||
let is_mipseb = arch == "mips" && endian == "big";
|
||||
let is_mips64eb = arch == "mips64" && endian == "big";
|
||||
let is_unsupported_abi = is_x32 || is_arm64_ilp32 || is_powerpc64be || is_mipseb || is_mips64eb;
|
||||
|
||||
// Check for `--features=use-libc`. This allows crate users to enable the
|
||||
// libc backend.
|
||||
let feature_use_libc = var("CARGO_FEATURE_USE_LIBC").is_ok();
|
||||
|
||||
// Check for `--features=rustc-dep-of-std`. This is used when rustix is
|
||||
// being used to build std, in which case `can_compile` doesn't work
|
||||
// because `core` isn't available yet, but also, we can assume we have a
|
||||
// recent compiler.
|
||||
let feature_rustc_dep_of_std = var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok();
|
||||
|
||||
// Check for `RUSTFLAGS=--cfg=rustix_use_libc`. This allows end users to
|
||||
// enable the libc backend even if rustix is depended on transitively.
|
||||
let cfg_use_libc = var("CARGO_CFG_RUSTIX_USE_LIBC").is_ok();
|
||||
|
||||
// Check for eg. `RUSTFLAGS=--cfg=rustix_use_experimental_asm`. This is a
|
||||
// rustc flag rather than a cargo feature flag because it's experimental
|
||||
// and not something we want accidentally enabled via `--all-features`.
|
||||
let rustix_use_experimental_asm = var("CARGO_CFG_RUSTIX_USE_EXPERIMENTAL_ASM").is_ok();
|
||||
|
||||
// Miri doesn't support inline asm, and has builtin support for recognizing
|
||||
// libc FFI calls, so if we're running under miri, use the libc backend.
|
||||
let miri = var("CARGO_CFG_MIRI").is_ok();
|
||||
|
||||
// If the libc backend is requested, or if we're not on a platform for
|
||||
// which we have linux_raw support, use the libc backend.
|
||||
//
|
||||
// For now Android uses the libc backend; in theory it could use the
|
||||
// linux_raw backend, but to do that we'll need to figure out how to
|
||||
// install the toolchain for it.
|
||||
if feature_use_libc
|
||||
|| cfg_use_libc
|
||||
|| os_name != "linux"
|
||||
|| !asm_name_present
|
||||
|| is_unsupported_abi
|
||||
|| miri
|
||||
{
|
||||
// Use the libc backend.
|
||||
use_feature("libc");
|
||||
} else {
|
||||
// Use the linux_raw backend.
|
||||
use_feature("linux_raw");
|
||||
use_feature_or_nothing("core_intrinsics");
|
||||
|
||||
// Use inline asm if we have it, or outline asm otherwise. On PowerPC
|
||||
// and MIPS, Rust's inline asm is considered experimental, so only use
|
||||
// it if `--cfg=rustix_use_experimental_asm` is given.
|
||||
if (feature_rustc_dep_of_std || can_compile("use std::arch::asm;"))
|
||||
&& (arch != "x86" || has_feature("naked_functions"))
|
||||
&& ((arch != "powerpc64" && arch != "mips" && arch != "mips64")
|
||||
|| rustix_use_experimental_asm)
|
||||
{
|
||||
use_feature("asm");
|
||||
if arch == "x86" {
|
||||
use_feature("naked_functions");
|
||||
}
|
||||
if rustix_use_experimental_asm {
|
||||
use_feature("asm_experimental_arch");
|
||||
}
|
||||
} else {
|
||||
link_in_librustix_outline(&arch, &asm_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect whether the compiler requires us to use thumb mode on ARM.
|
||||
if arch == "arm" && use_thumb_mode() {
|
||||
use_feature("thumb_mode");
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-env-changed=CARGO_CFG_RUSTIX_USE_EXPERIMENTAL_ASM");
|
||||
}
|
||||
|
||||
/// Link in the desired version of librustix_outline_{arch}.a, containing the
|
||||
/// outline assembly code for making syscalls.
|
||||
fn link_in_librustix_outline(arch: &str, asm_name: &str) {
|
||||
let name = format!("rustix_outline_{}", arch);
|
||||
let profile = var("PROFILE").unwrap();
|
||||
let to = format!("{}/{}/lib{}.a", OUTLINE_PATH, profile, name);
|
||||
println!("cargo:rerun-if-changed={}", to);
|
||||
|
||||
// If "cc" is not enabled, use a pre-built library.
|
||||
#[cfg(not(feature = "cc"))]
|
||||
{
|
||||
let _ = asm_name;
|
||||
println!("cargo:rustc-link-search={}/{}", OUTLINE_PATH, profile);
|
||||
println!("cargo:rustc-link-lib=static={}", name);
|
||||
}
|
||||
|
||||
// If "cc" is enabled, build the library from source, update the pre-built
|
||||
// version, and assert that the pre-built version is checked in.
|
||||
#[cfg(feature = "cc")]
|
||||
{
|
||||
let out_dir = var("OUT_DIR").unwrap();
|
||||
Build::new().file(&asm_name).compile(&name);
|
||||
println!("cargo:rerun-if-changed={}", asm_name);
|
||||
if std::fs::metadata(".git").is_ok() {
|
||||
let from = format!("{}/lib{}.a", out_dir, name);
|
||||
let prev_metadata = std::fs::metadata(&to);
|
||||
std::fs::copy(&from, &to).unwrap();
|
||||
assert!(
|
||||
prev_metadata.is_ok(),
|
||||
"{} didn't previously exist; please inspect the new file and `git add` it",
|
||||
to
|
||||
);
|
||||
assert!(
|
||||
std::process::Command::new("git")
|
||||
.arg("diff")
|
||||
.arg("--quiet")
|
||||
.arg(&to)
|
||||
.status()
|
||||
.unwrap()
|
||||
.success(),
|
||||
"{} changed; please inspect the change and `git commit` it",
|
||||
to
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn use_thumb_mode() -> bool {
|
||||
// In thumb mode, r7 is reserved.
|
||||
!can_compile("pub unsafe fn f() { core::arch::asm!(\"udf #16\", in(\"r7\") 0); }")
|
||||
}
|
||||
|
||||
fn use_feature_or_nothing(feature: &str) {
|
||||
if has_feature(feature) {
|
||||
use_feature(feature);
|
||||
}
|
||||
}
|
||||
|
||||
fn use_feature(feature: &str) {
|
||||
println!("cargo:rustc-cfg={}", feature);
|
||||
}
|
||||
|
||||
/// Test whether the rustc at `var("RUSTC")` supports the given feature.
|
||||
fn has_feature(feature: &str) -> bool {
|
||||
can_compile(&format!(
|
||||
"#![allow(stable_features)]\n#![feature({})]",
|
||||
feature
|
||||
))
|
||||
}
|
||||
|
||||
/// Test whether the rustc at `var("RUSTC")` can compile the given code.
|
||||
fn can_compile(code: &str) -> bool {
|
||||
use std::process::Stdio;
|
||||
let out_dir = var("OUT_DIR").unwrap();
|
||||
let rustc = var("RUSTC").unwrap();
|
||||
let target = var("TARGET").unwrap();
|
||||
|
||||
let mut child = std::process::Command::new(rustc)
|
||||
.arg("--crate-type=rlib") // Don't require `main`.
|
||||
.arg("--emit=metadata") // Do as little as possible but still parse.
|
||||
.arg("--target")
|
||||
.arg(target)
|
||||
.arg("--out-dir")
|
||||
.arg(out_dir) // Put the output somewhere inconsequential.
|
||||
.arg("-") // Read from stdin.
|
||||
.stdin(Stdio::piped()) // Stdin is a pipe.
|
||||
.stderr(Stdio::null())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
|
||||
writeln!(child.stdin.take().unwrap(), "{}", code).unwrap();
|
||||
|
||||
child.wait().unwrap().success()
|
||||
}
|
||||
222
vendor/rustix/src/backend/libc/conv.rs
vendored
Normal file
222
vendor/rustix/src/backend/libc/conv.rs
vendored
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
//! Libc call arguments and return values are often things like `c_int`,
|
||||
//! `c_uint`, or libc-specific pointer types. This module provides functions
|
||||
//! for converting between rustix's types and libc types.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use super::c;
|
||||
use super::fd::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, LibcFd, OwnedFd, RawFd};
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "fs")]
|
||||
use super::offset::libc_off_t;
|
||||
#[cfg(not(windows))]
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
#[cfg(windows)]
|
||||
use core::convert::TryInto;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(super) fn c_str(c: &CStr) -> *const c::c_char {
|
||||
c.as_ptr()
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(super) fn no_fd() -> LibcFd {
|
||||
-1
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn borrowed_fd(fd: BorrowedFd<'_>) -> LibcFd {
|
||||
fd.as_raw_fd() as LibcFd
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn owned_fd(fd: OwnedFd) -> LibcFd {
|
||||
fd.into_raw_fd() as LibcFd
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn ret(raw: c::c_int) -> io::Result<()> {
|
||||
if raw == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Errno::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn syscall_ret(raw: c::c_long) -> io::Result<()> {
|
||||
if raw == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Errno::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn nonnegative_ret(raw: c::c_int) -> io::Result<()> {
|
||||
if raw >= 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Errno::last_os_error())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) unsafe fn ret_infallible(raw: c::c_int) {
|
||||
debug_assert_eq!(raw, 0, "unexpected error: {:?}", io::Errno::last_os_error());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn ret_c_int(raw: c::c_int) -> io::Result<c::c_int> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(raw)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn ret_u32(raw: c::c_int) -> io::Result<u32> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(raw as u32)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn ret_ssize_t(raw: c::ssize_t) -> io::Result<c::ssize_t> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(raw)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn syscall_ret_ssize_t(raw: c::c_long) -> io::Result<c::ssize_t> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(raw as c::ssize_t)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(super) fn syscall_ret_u32(raw: c::c_long) -> io::Result<u32> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
let r32 = raw as u32;
|
||||
|
||||
// Converting `raw` to `u32` should be lossless.
|
||||
debug_assert_eq!(r32 as c::c_long, raw);
|
||||
|
||||
Ok(r32)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "fs")]
|
||||
#[inline]
|
||||
pub(super) fn ret_off_t(raw: libc_off_t) -> io::Result<libc_off_t> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(raw)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(super) fn ret_pid_t(raw: c::pid_t) -> io::Result<c::pid_t> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(raw)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `c_int` returned from a libc function to an `OwnedFd`, if valid.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that this is the return value of a libc function
|
||||
/// which returns an owned file descriptor.
|
||||
#[inline]
|
||||
pub(super) unsafe fn ret_owned_fd(raw: LibcFd) -> io::Result<OwnedFd> {
|
||||
if raw == !0 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(OwnedFd::from_raw_fd(raw as RawFd))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn ret_discarded_fd(raw: LibcFd) -> io::Result<()> {
|
||||
if raw == !0 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn ret_discarded_char_ptr(raw: *mut c::c_char) -> io::Result<()> {
|
||||
if raw.is_null() {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `c_long` returned from `syscall` to an `OwnedFd`, if valid.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that this is the return value of a `syscall` call
|
||||
/// which returns an owned file descriptor.
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(super) unsafe fn syscall_ret_owned_fd(raw: c::c_long) -> io::Result<OwnedFd> {
|
||||
if raw == -1 {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(OwnedFd::from_raw_fd(raw as RawFd))
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the buffer-length argument value of a `send` or `recv` call.
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(super) fn send_recv_len(len: usize) -> usize {
|
||||
len
|
||||
}
|
||||
|
||||
/// Convert the buffer-length argument value of a `send` or `recv` call.
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(super) fn send_recv_len(len: usize) -> i32 {
|
||||
// On Windows, the length argument has type `i32`; saturate the length,
|
||||
// since `send` and `recv` are allowed to send and recv less data than
|
||||
// requested.
|
||||
len.try_into().unwrap_or(i32::MAX)
|
||||
}
|
||||
|
||||
/// Convert the return value of a `send` or `recv` call.
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(super) fn ret_send_recv(len: isize) -> io::Result<c::ssize_t> {
|
||||
ret_ssize_t(len)
|
||||
}
|
||||
|
||||
/// Convert the return value of a `send` or `recv` call.
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(super) fn ret_send_recv(len: i32) -> io::Result<c::ssize_t> {
|
||||
ret_ssize_t(len as isize)
|
||||
}
|
||||
487
vendor/rustix/src/backend/libc/fs/dir.rs
vendored
Normal file
487
vendor/rustix/src/backend/libc/fs/dir.rs
vendored
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
use super::super::c;
|
||||
use super::super::conv::owned_fd;
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
use super::types::FileType;
|
||||
use crate::fd::{AsFd, BorrowedFd};
|
||||
use crate::ffi::CStr;
|
||||
#[cfg(target_os = "wasi")]
|
||||
use crate::ffi::CString;
|
||||
use crate::fs::{fcntl_getfl, fstat, openat, Mode, OFlags, Stat};
|
||||
#[cfg(not(any(
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "netbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
use crate::fs::{fstatfs, StatFs};
|
||||
#[cfg(not(any(
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
use crate::fs::{fstatvfs, StatVfs};
|
||||
use crate::io;
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
use crate::process::fchdir;
|
||||
#[cfg(target_os = "wasi")]
|
||||
use alloc::borrow::ToOwned;
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
use c::dirent as libc_dirent;
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
)))]
|
||||
use c::readdir as libc_readdir;
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
))]
|
||||
use c::{dirent64 as libc_dirent, readdir64 as libc_readdir};
|
||||
use core::fmt;
|
||||
use core::mem::zeroed;
|
||||
use core::ptr::NonNull;
|
||||
use libc_errno::{errno, set_errno, Errno};
|
||||
|
||||
/// `DIR*`
|
||||
#[repr(transparent)]
|
||||
pub struct Dir(NonNull<c::DIR>);
|
||||
|
||||
impl Dir {
|
||||
/// Construct a `Dir` that reads entries from the given directory
|
||||
/// file descriptor.
|
||||
#[inline]
|
||||
pub fn read_from<Fd: AsFd>(fd: Fd) -> io::Result<Self> {
|
||||
Self::_read_from(fd.as_fd())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn _read_from(fd: BorrowedFd<'_>) -> io::Result<Self> {
|
||||
// Given an arbitrary `OwnedFd`, it's impossible to know whether the
|
||||
// user holds a `dup`'d copy which could continue to modify the
|
||||
// file description state, which would cause Undefined Behavior after
|
||||
// our call to `fdopendir`. To prevent this, we obtain an independent
|
||||
// `OwnedFd`.
|
||||
let flags = fcntl_getfl(fd)?;
|
||||
let fd_for_dir = openat(fd, cstr!("."), flags | OFlags::CLOEXEC, Mode::empty())?;
|
||||
|
||||
let raw = owned_fd(fd_for_dir);
|
||||
unsafe {
|
||||
let libc_dir = c::fdopendir(raw);
|
||||
|
||||
if let Some(libc_dir) = NonNull::new(libc_dir) {
|
||||
Ok(Self(libc_dir))
|
||||
} else {
|
||||
let err = io::Errno::last_os_error();
|
||||
let _ = c::close(raw);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `rewinddir(self)`
|
||||
#[inline]
|
||||
pub fn rewind(&mut self) {
|
||||
unsafe { c::rewinddir(self.0.as_ptr()) }
|
||||
}
|
||||
|
||||
/// `readdir(self)`, where `None` means the end of the directory.
|
||||
pub fn read(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
set_errno(Errno(0));
|
||||
let dirent_ptr = unsafe { libc_readdir(self.0.as_ptr()) };
|
||||
if dirent_ptr.is_null() {
|
||||
let curr_errno = errno().0;
|
||||
if curr_errno == 0 {
|
||||
// We successfully reached the end of the stream.
|
||||
None
|
||||
} else {
|
||||
// `errno` is unknown or non-zero, so an error occurred.
|
||||
Some(Err(io::Errno(curr_errno)))
|
||||
}
|
||||
} else {
|
||||
// We successfully read an entry.
|
||||
unsafe {
|
||||
// We have our own copy of OpenBSD's dirent; check that the
|
||||
// layout minimally matches libc's.
|
||||
#[cfg(target_os = "openbsd")]
|
||||
check_dirent_layout(&*dirent_ptr);
|
||||
|
||||
let result = DirEntry {
|
||||
dirent: read_dirent(&*dirent_ptr.cast()),
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
name: CStr::from_ptr((*dirent_ptr).d_name.as_ptr()).to_owned(),
|
||||
};
|
||||
|
||||
Some(Ok(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `fstat(self)`
|
||||
#[inline]
|
||||
pub fn stat(&self) -> io::Result<Stat> {
|
||||
fstat(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
|
||||
}
|
||||
|
||||
/// `fstatfs(self)`
|
||||
#[cfg(not(any(
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "netbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[inline]
|
||||
pub fn statfs(&self) -> io::Result<StatFs> {
|
||||
fstatfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
|
||||
}
|
||||
|
||||
/// `fstatvfs(self)`
|
||||
#[cfg(not(any(
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[inline]
|
||||
pub fn statvfs(&self) -> io::Result<StatVfs> {
|
||||
fstatvfs(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
|
||||
}
|
||||
|
||||
/// `fchdir(self)`
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub fn chdir(&self) -> io::Result<()> {
|
||||
fchdir(unsafe { BorrowedFd::borrow_raw(c::dirfd(self.0.as_ptr())) })
|
||||
}
|
||||
}
|
||||
|
||||
// A `dirent` pointer returned from `readdir` may not point to a full `dirent`
|
||||
// struct, as the name is NUL-terminated and memory may not be allocated for
|
||||
// the full extent of the struct. Copy the fields one at a time.
|
||||
unsafe fn read_dirent(input: &libc_dirent) -> libc_dirent {
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "solaris"
|
||||
)))]
|
||||
let d_type = input.d_type;
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
let d_off = input.d_off;
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
let d_offset = input.d_offset;
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
let d_ino = input.d_ino;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
let d_fileno = input.d_fileno;
|
||||
|
||||
#[cfg(not(any(target_os = "dragonfly", target_os = "wasi")))]
|
||||
let d_reclen = input.d_reclen;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
))]
|
||||
let d_namlen = input.d_namlen;
|
||||
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
let d_seekoff = input.d_seekoff;
|
||||
|
||||
#[cfg(target_os = "haiku")]
|
||||
let d_dev = input.d_dev;
|
||||
#[cfg(target_os = "haiku")]
|
||||
let d_pdev = input.d_pdev;
|
||||
#[cfg(target_os = "haiku")]
|
||||
let d_pino = input.d_pino;
|
||||
|
||||
// Construct the input. Rust will give us an error if any OS has a input
|
||||
// with a field that we missed here. And we can avoid blindly copying the
|
||||
// whole `d_name` field, which may not be entirely allocated.
|
||||
#[cfg_attr(target_os = "wasi", allow(unused_mut))]
|
||||
#[cfg(not(any(target_os = "freebsd", target_os = "dragonfly")))]
|
||||
let mut dirent = libc_dirent {
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "solaris"
|
||||
)))]
|
||||
d_type,
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "freebsd", // Until FreeBSD 12
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
d_off,
|
||||
#[cfg(target_os = "aix")]
|
||||
d_offset,
|
||||
#[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))]
|
||||
d_ino,
|
||||
#[cfg(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
|
||||
d_fileno,
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
d_reclen,
|
||||
#[cfg(any(
|
||||
target_os = "aix",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
d_namlen,
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
d_seekoff,
|
||||
// The `d_name` field is NUL-terminated, and we need to be careful not
|
||||
// to read bytes past the NUL, even though they're within the nominal
|
||||
// extent of the `struct dirent`, because they may not be allocated. So
|
||||
// don't read it from `dirent_ptr`.
|
||||
//
|
||||
// In theory this could use `MaybeUninit::uninit().assume_init()`, but
|
||||
// that [invokes undefined behavior].
|
||||
//
|
||||
// [invokes undefined behavior]: https://doc.rust-lang.org/stable/core/mem/union.MaybeUninit.html#initialization-invariant
|
||||
d_name: zeroed(),
|
||||
#[cfg(target_os = "openbsd")]
|
||||
__d_padding: zeroed(),
|
||||
#[cfg(target_os = "haiku")]
|
||||
d_dev,
|
||||
#[cfg(target_os = "haiku")]
|
||||
d_pdev,
|
||||
#[cfg(target_os = "haiku")]
|
||||
d_pino,
|
||||
};
|
||||
/*
|
||||
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
|
||||
// */
|
||||
|
||||
// On dragonfly and FreeBSD 12, `dirent` has some non-public padding fields
|
||||
// so we can't directly initialize it.
|
||||
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
|
||||
let mut dirent = {
|
||||
let mut dirent: libc_dirent = zeroed();
|
||||
dirent.d_fileno = d_fileno;
|
||||
dirent.d_namlen = d_namlen;
|
||||
dirent.d_type = d_type;
|
||||
#[cfg(target_os = "freebsd")]
|
||||
{
|
||||
dirent.d_reclen = d_reclen;
|
||||
}
|
||||
dirent
|
||||
};
|
||||
|
||||
// Copy from d_name, reading up to and including the first NUL.
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
{
|
||||
let name_len = CStr::from_ptr(input.d_name.as_ptr())
|
||||
.to_bytes_with_nul()
|
||||
.len();
|
||||
dirent.d_name[..name_len].copy_from_slice(&input.d_name[..name_len]);
|
||||
}
|
||||
|
||||
dirent
|
||||
}
|
||||
|
||||
/// `Dir` implements `Send` but not `Sync`, because we use `readdir` which is
|
||||
/// not guaranteed to be thread-safe. Users can wrap this in a `Mutex` if they
|
||||
/// need `Sync`, which is effectively what'd need to do to implement `Sync`
|
||||
/// ourselves.
|
||||
unsafe impl Send for Dir {}
|
||||
|
||||
impl Drop for Dir {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe { c::closedir(self.0.as_ptr()) };
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Dir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
Self::read(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Dir {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Dir")
|
||||
.field("fd", unsafe { &c::dirfd(self.0.as_ptr()) })
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// `struct dirent`
|
||||
#[derive(Debug)]
|
||||
pub struct DirEntry {
|
||||
dirent: libc_dirent,
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
name: CString,
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
/// Returns the file name of this directory entry.
|
||||
#[inline]
|
||||
pub fn file_name(&self) -> &CStr {
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
unsafe {
|
||||
CStr::from_ptr(self.dirent.d_name.as_ptr())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
&self.name
|
||||
}
|
||||
|
||||
/// Returns the type of this directory entry.
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "solaris"
|
||||
)))]
|
||||
#[inline]
|
||||
pub fn file_type(&self) -> FileType {
|
||||
FileType::from_dirent_d_type(self.dirent.d_type)
|
||||
}
|
||||
|
||||
/// Return the inode number of this directory entry.
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
#[inline]
|
||||
pub fn ino(&self) -> u64 {
|
||||
self.dirent.d_ino as u64
|
||||
}
|
||||
|
||||
/// Return the inode number of this directory entry.
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
#[inline]
|
||||
pub fn ino(&self) -> u64 {
|
||||
#[allow(clippy::useless_conversion)]
|
||||
self.dirent.d_fileno.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// libc's OpenBSD `dirent` has a private field so we can't construct it
|
||||
/// directly, so we declare it ourselves to make all fields accessible.
|
||||
#[cfg(target_os = "openbsd")]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
struct libc_dirent {
|
||||
d_fileno: c::ino_t,
|
||||
d_off: c::off_t,
|
||||
d_reclen: u16,
|
||||
d_type: u8,
|
||||
d_namlen: u8,
|
||||
__d_padding: [u8; 4],
|
||||
d_name: [c::c_char; 256],
|
||||
}
|
||||
|
||||
/// We have our own copy of OpenBSD's dirent; check that the layout
|
||||
/// minimally matches libc's.
|
||||
#[cfg(target_os = "openbsd")]
|
||||
fn check_dirent_layout(dirent: &c::dirent) {
|
||||
use crate::utils::as_ptr;
|
||||
use core::mem::{align_of, size_of};
|
||||
|
||||
// Check that the basic layouts match.
|
||||
assert_eq!(size_of::<libc_dirent>(), size_of::<c::dirent>());
|
||||
assert_eq!(align_of::<libc_dirent>(), align_of::<c::dirent>());
|
||||
|
||||
// Check that the field offsets match.
|
||||
assert_eq!(
|
||||
{
|
||||
let z = libc_dirent {
|
||||
d_fileno: 0_u64,
|
||||
d_off: 0_i64,
|
||||
d_reclen: 0_u16,
|
||||
d_type: 0_u8,
|
||||
d_namlen: 0_u8,
|
||||
__d_padding: [0_u8; 4],
|
||||
d_name: [0 as c::c_char; 256],
|
||||
};
|
||||
let base = as_ptr(&z) as usize;
|
||||
(
|
||||
(as_ptr(&z.d_fileno) as usize) - base,
|
||||
(as_ptr(&z.d_off) as usize) - base,
|
||||
(as_ptr(&z.d_reclen) as usize) - base,
|
||||
(as_ptr(&z.d_type) as usize) - base,
|
||||
(as_ptr(&z.d_namlen) as usize) - base,
|
||||
(as_ptr(&z.d_name) as usize) - base,
|
||||
)
|
||||
},
|
||||
{
|
||||
let z = dirent;
|
||||
let base = as_ptr(z) as usize;
|
||||
(
|
||||
(as_ptr(&z.d_fileno) as usize) - base,
|
||||
(as_ptr(&z.d_off) as usize) - base,
|
||||
(as_ptr(&z.d_reclen) as usize) - base,
|
||||
(as_ptr(&z.d_type) as usize) - base,
|
||||
(as_ptr(&z.d_namlen) as usize) - base,
|
||||
(as_ptr(&z.d_name) as usize) - base,
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
90
vendor/rustix/src/backend/libc/fs/makedev.rs
vendored
Normal file
90
vendor/rustix/src/backend/libc/fs/makedev.rs
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#[cfg(not(all(target_os = "android", target_pointer_width = "32")))]
|
||||
use super::super::c;
|
||||
use crate::fs::Dev;
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "emscripten")))]
|
||||
#[inline]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
c::makedev(maj, min)
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "android", not(target_pointer_width = "32")))]
|
||||
#[inline]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
// Android's `makedev` oddly has signed argument types.
|
||||
c::makedev(maj, min)
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
|
||||
#[inline]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
// 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit,
|
||||
// so we do it ourselves.
|
||||
((u64::from(maj) & 0xffff_f000_u64) << 32)
|
||||
| ((u64::from(maj) & 0x0000_0fff_u64) << 8)
|
||||
| ((u64::from(min) & 0xffff_ff00_u64) << 12)
|
||||
| (u64::from(min) & 0x0000_00ff_u64)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "emscripten")]
|
||||
#[inline]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
// Emscripten's `makedev` has a 32-bit return value.
|
||||
Dev::from(c::makedev(maj, min))
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "emscripten")))]
|
||||
#[inline]
|
||||
pub(crate) fn major(dev: Dev) -> u32 {
|
||||
unsafe { c::major(dev) }
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "android", not(target_pointer_width = "32")))]
|
||||
#[inline]
|
||||
pub(crate) fn major(dev: Dev) -> u32 {
|
||||
// Android's `major` oddly has signed return types.
|
||||
(unsafe { c::major(dev) }) as u32
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
|
||||
#[inline]
|
||||
pub(crate) fn major(dev: Dev) -> u32 {
|
||||
// 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit,
|
||||
// so we do it ourselves.
|
||||
(((dev >> 31 >> 1) & 0xffff_f000) | ((dev >> 8) & 0x0000_0fff)) as u32
|
||||
}
|
||||
|
||||
#[cfg(target_os = "emscripten")]
|
||||
#[inline]
|
||||
pub(crate) fn major(dev: Dev) -> u32 {
|
||||
// Emscripten's `major` has a 32-bit argument value.
|
||||
unsafe { c::major(dev as u32) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "emscripten")))]
|
||||
#[inline]
|
||||
pub(crate) fn minor(dev: Dev) -> u32 {
|
||||
unsafe { c::minor(dev) }
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "android", not(target_pointer_width = "32")))]
|
||||
#[inline]
|
||||
pub(crate) fn minor(dev: Dev) -> u32 {
|
||||
// Android's `minor` oddly has signed return types.
|
||||
(unsafe { c::minor(dev) }) as u32
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
|
||||
#[inline]
|
||||
pub(crate) fn minor(dev: Dev) -> u32 {
|
||||
// 32-bit Android's `dev_t` is 32-bit, but its `st_dev` is 64-bit,
|
||||
// so we do it ourselves.
|
||||
(((dev >> 12) & 0xffff_ff00) | (dev & 0x0000_00ff)) as u32
|
||||
}
|
||||
|
||||
#[cfg(target_os = "emscripten")]
|
||||
#[inline]
|
||||
pub(crate) fn minor(dev: Dev) -> u32 {
|
||||
// Emscripten's `minor` has a 32-bit argument value.
|
||||
unsafe { c::minor(dev as u32) }
|
||||
}
|
||||
19
vendor/rustix/src/backend/libc/fs/mod.rs
vendored
Normal file
19
vendor/rustix/src/backend/libc/fs/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#[cfg(not(target_os = "redox"))]
|
||||
pub(crate) mod dir;
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub(crate) mod makedev;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
1772
vendor/rustix/src/backend/libc/fs/syscalls.rs
vendored
Normal file
1772
vendor/rustix/src/backend/libc/fs/syscalls.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
1116
vendor/rustix/src/backend/libc/fs/types.rs
vendored
Normal file
1116
vendor/rustix/src/backend/libc/fs/types.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
573
vendor/rustix/src/backend/libc/io/epoll.rs
vendored
Normal file
573
vendor/rustix/src/backend/libc/io/epoll.rs
vendored
Normal file
|
|
@ -0,0 +1,573 @@
|
|||
//! epoll support.
|
||||
//!
|
||||
//! This is an experiment, and it isn't yet clear whether epoll is the right
|
||||
//! level of abstraction at which to introduce safety. But it works fairly well
|
||||
//! in simple examples 🙂.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! # #![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
|
||||
//! # #[cfg(feature = "net")]
|
||||
//! # fn main() -> std::io::Result<()> {
|
||||
//! use io_lifetimes::AsFd;
|
||||
//! use rustix::io::epoll::{self, Epoll};
|
||||
//! use rustix::io::{ioctl_fionbio, read, write};
|
||||
//! use rustix::net::{
|
||||
//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4,
|
||||
//! SocketType,
|
||||
//! };
|
||||
//! use std::os::unix::io::AsRawFd;
|
||||
//!
|
||||
//! // Create a socket and listen on it.
|
||||
//! let listen_sock = socket(AddressFamily::INET, SocketType::STREAM, Protocol::default())?;
|
||||
//! bind_v4(&listen_sock, &SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0))?;
|
||||
//! listen(&listen_sock, 1)?;
|
||||
//!
|
||||
//! // Create an epoll object. Using `Owning` here means the epoll object will
|
||||
//! // take ownership of the file descriptors registered with it.
|
||||
//! let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC, epoll::Owning::new())?;
|
||||
//!
|
||||
//! // Remember the socket raw fd, which we use for comparisons only.
|
||||
//! let raw_listen_sock = listen_sock.as_fd().as_raw_fd();
|
||||
//!
|
||||
//! // Register the socket with the epoll object.
|
||||
//! epoll.add(listen_sock, epoll::EventFlags::IN)?;
|
||||
//!
|
||||
//! // Process events.
|
||||
//! let mut event_list = epoll::EventVec::with_capacity(4);
|
||||
//! loop {
|
||||
//! epoll.wait(&mut event_list, -1)?;
|
||||
//! for (_event_flags, target) in &event_list {
|
||||
//! if target.as_raw_fd() == raw_listen_sock {
|
||||
//! // Accept a new connection, set it to non-blocking, and
|
||||
//! // register to be notified when it's ready to write to.
|
||||
//! let conn_sock = accept(&*target)?;
|
||||
//! ioctl_fionbio(&conn_sock, true)?;
|
||||
//! epoll.add(conn_sock, epoll::EventFlags::OUT | epoll::EventFlags::ET)?;
|
||||
//! } else {
|
||||
//! // Write a message to the stream and then unregister it.
|
||||
//! write(&*target, b"hello\n")?;
|
||||
//! let _ = epoll.del(target)?;
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! # }
|
||||
//! # #[cfg(not(feature = "net"))]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
|
||||
use super::super::c;
|
||||
use super::super::conv::{ret, ret_owned_fd, ret_u32};
|
||||
use crate::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
use crate::fd::{FromRawFd, IntoRawFd};
|
||||
use crate::io;
|
||||
use alloc::vec::Vec;
|
||||
use bitflags::bitflags;
|
||||
use core::convert::TryInto;
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::Deref;
|
||||
use core::ptr::{null, null_mut};
|
||||
|
||||
bitflags! {
|
||||
/// `EPOLL_*` for use with [`Epoll::new`].
|
||||
pub struct CreateFlags: c::c_int {
|
||||
/// `EPOLL_CLOEXEC`
|
||||
const CLOEXEC = c::EPOLL_CLOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `EPOLL*` for use with [`Epoll::add`].
|
||||
#[derive(Default)]
|
||||
pub struct EventFlags: u32 {
|
||||
/// `EPOLLIN`
|
||||
const IN = c::EPOLLIN as u32;
|
||||
|
||||
/// `EPOLLOUT`
|
||||
const OUT = c::EPOLLOUT as u32;
|
||||
|
||||
/// `EPOLLPRI`
|
||||
const PRI = c::EPOLLPRI as u32;
|
||||
|
||||
/// `EPOLLERR`
|
||||
const ERR = c::EPOLLERR as u32;
|
||||
|
||||
/// `EPOLLHUP`
|
||||
const HUP = c::EPOLLHUP as u32;
|
||||
|
||||
/// `EPOLLET`
|
||||
const ET = c::EPOLLET as u32;
|
||||
|
||||
/// `EPOLLONESHOT`
|
||||
const ONESHOT = c::EPOLLONESHOT as u32;
|
||||
|
||||
/// `EPOLLWAKEUP`
|
||||
const WAKEUP = c::EPOLLWAKEUP as u32;
|
||||
|
||||
/// `EPOLLEXCLUSIVE`
|
||||
#[cfg(not(target_os = "android"))]
|
||||
const EXCLUSIVE = c::EPOLLEXCLUSIVE as u32;
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a `T`.
|
||||
pub struct Ref<'a, T> {
|
||||
t: T,
|
||||
_phantom: PhantomData<&'a T>,
|
||||
}
|
||||
|
||||
impl<'a, T> Ref<'a, T> {
|
||||
#[inline]
|
||||
fn new(t: T) -> Self {
|
||||
Self {
|
||||
t,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn consume(self) -> T {
|
||||
self.t
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for Ref<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &T {
|
||||
&self.t
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.t.fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for data stored within an [`Epoll`] instance.
|
||||
pub trait Context {
|
||||
/// The type of an element owned by this context.
|
||||
type Data;
|
||||
|
||||
/// The type of a value used to refer to an element owned by this context.
|
||||
type Target: AsFd;
|
||||
|
||||
/// Assume ownership of `data`, and returning a `Target`.
|
||||
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target>;
|
||||
|
||||
/// Encode `target` as a `u64`. The only requirement on this value is that
|
||||
/// it be decodable by `decode`.
|
||||
fn encode(&self, target: Ref<'_, Self::Target>) -> u64;
|
||||
|
||||
/// Decode `raw`, which is a value encoded by `encode`, into a `Target`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `raw` must be a `u64` value returned from `encode`, from the same
|
||||
/// context, and within the context's lifetime.
|
||||
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target>;
|
||||
|
||||
/// Release ownership of the value referred to by `target` and return it.
|
||||
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data;
|
||||
}
|
||||
|
||||
/// A type implementing [`Context`] where the `Data` type is `BorrowedFd<'a>`.
|
||||
pub struct Borrowing<'a> {
|
||||
_phantom: PhantomData<BorrowedFd<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> Context for Borrowing<'a> {
|
||||
type Data = BorrowedFd<'a>;
|
||||
type Target = BorrowedFd<'a>;
|
||||
|
||||
#[inline]
|
||||
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
|
||||
Ref::new(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
|
||||
target.as_raw_fd() as u64
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
|
||||
Ref::new(BorrowedFd::<'a>::borrow_raw(raw as RawFd))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
|
||||
target.consume()
|
||||
}
|
||||
}
|
||||
|
||||
/// A type implementing [`Context`] where the `Data` type is `T`, a type
|
||||
/// implementing `From<OwnedFd>` and `From<T> for OwnedFd`.
|
||||
///
|
||||
/// This may be used with [`OwnedFd`], or higher-level types like
|
||||
/// [`std::fs::File`] or [`std::net::TcpStream`].
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
pub struct Owning<'context, T: Into<OwnedFd> + From<OwnedFd>> {
|
||||
_phantom: PhantomData<&'context T>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
impl<'context, T: Into<OwnedFd> + From<OwnedFd>> Owning<'context, T> {
|
||||
/// Creates a new empty `Owning`.
|
||||
#[allow(clippy::new_without_default)] // This is a specialized type that doesn't need to be generically constructible.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> Context for Owning<'context, T> {
|
||||
type Data = T;
|
||||
type Target = BorrowedFd<'context>;
|
||||
|
||||
#[inline]
|
||||
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
|
||||
let fd: OwnedFd = data.into();
|
||||
let raw_fd = fd.into_raw_fd();
|
||||
// Safety: `epoll` will assign ownership of the file descriptor to the
|
||||
// kernel epoll object. We use `Into<OwnedFd>`+`IntoRawFd` to consume
|
||||
// the `Data` and extract the raw file descriptor and then "borrow" it
|
||||
// with `borrow_raw` knowing that the borrow won't outlive the
|
||||
// kernel epoll object.
|
||||
unsafe { Ref::new(BorrowedFd::<'context>::borrow_raw(raw_fd)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
|
||||
target.as_fd().as_raw_fd() as u64
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
|
||||
Ref::new(BorrowedFd::<'context>::borrow_raw(raw as RawFd))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
|
||||
// The file descriptor was held by the kernel epoll object and is now
|
||||
// being released, so we can create a new `OwnedFd` that assumes
|
||||
// ownership.
|
||||
let raw_fd = target.consume().as_raw_fd();
|
||||
unsafe { T::from(OwnedFd::from_raw_fd(raw_fd).into()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// An "epoll", an interface to an OS object allowing one to repeatedly wait
|
||||
/// for events from a set of file descriptors efficiently.
|
||||
pub struct Epoll<Context: self::Context> {
|
||||
epoll_fd: OwnedFd,
|
||||
context: Context,
|
||||
}
|
||||
|
||||
impl<Context: self::Context> Epoll<Context> {
|
||||
/// `epoll_create1(flags)`—Creates a new `Epoll`.
|
||||
///
|
||||
/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
|
||||
/// descriptor from being implicitly passed across `exec` boundaries.
|
||||
#[inline]
|
||||
#[doc(alias = "epoll_create1")]
|
||||
pub fn new(flags: CreateFlags, context: Context) -> io::Result<Self> {
|
||||
// Safety: We're calling `epoll_create1` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
Ok(Self {
|
||||
epoll_fd: ret_owned_fd(c::epoll_create1(flags.bits()))?,
|
||||
context,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_ADD, data, event)`—Adds an element to an
|
||||
/// `Epoll`.
|
||||
///
|
||||
/// This registers interest in any of the events set in `events` occurring
|
||||
/// on the file descriptor associated with `data`.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
pub fn add(
|
||||
&self,
|
||||
data: Context::Data,
|
||||
event_flags: EventFlags,
|
||||
) -> io::Result<Ref<'_, Context::Target>> {
|
||||
// Safety: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
let target = self.context.acquire(data);
|
||||
let raw_fd = target.as_fd().as_raw_fd();
|
||||
let encoded = self.context.encode(target);
|
||||
ret(c::epoll_ctl(
|
||||
self.epoll_fd.as_fd().as_raw_fd(),
|
||||
c::EPOLL_CTL_ADD,
|
||||
raw_fd,
|
||||
&mut c::epoll_event {
|
||||
events: event_flags.bits(),
|
||||
r#u64: encoded,
|
||||
},
|
||||
))?;
|
||||
Ok(self.context.decode(encoded))
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_MOD, target, event)`—Modifies an element in
|
||||
/// this `Epoll`.
|
||||
///
|
||||
/// This sets the events of interest with `target` to `events`.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
pub fn mod_(
|
||||
&self,
|
||||
target: Ref<'_, Context::Target>,
|
||||
event_flags: EventFlags,
|
||||
) -> io::Result<()> {
|
||||
let raw_fd = target.as_fd().as_raw_fd();
|
||||
let encoded = self.context.encode(target);
|
||||
// Safety: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
ret(c::epoll_ctl(
|
||||
self.epoll_fd.as_fd().as_raw_fd(),
|
||||
c::EPOLL_CTL_MOD,
|
||||
raw_fd,
|
||||
&mut c::epoll_event {
|
||||
events: event_flags.bits(),
|
||||
r#u64: encoded,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// `epoll_ctl(self, EPOLL_CTL_DEL, target, NULL)`—Removes an element in
|
||||
/// this `Epoll`.
|
||||
///
|
||||
/// This also returns the owning `Data`.
|
||||
#[doc(alias = "epoll_ctl")]
|
||||
pub fn del(&self, target: Ref<'_, Context::Target>) -> io::Result<Context::Data> {
|
||||
// Safety: We're calling `epoll_ctl` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
let raw_fd = target.as_fd().as_raw_fd();
|
||||
ret(c::epoll_ctl(
|
||||
self.epoll_fd.as_fd().as_raw_fd(),
|
||||
c::EPOLL_CTL_DEL,
|
||||
raw_fd,
|
||||
null_mut(),
|
||||
))?;
|
||||
}
|
||||
Ok(self.context.release(target))
|
||||
}
|
||||
|
||||
/// `epoll_wait(self, events, timeout)`—Waits for registered events of
|
||||
/// interest.
|
||||
///
|
||||
/// For each event of interest, an element is written to `events`. On
|
||||
/// success, this returns the number of written elements.
|
||||
#[doc(alias = "epoll_wait")]
|
||||
pub fn wait<'context>(
|
||||
&'context self,
|
||||
event_list: &mut EventVec<'context, Context>,
|
||||
timeout: c::c_int,
|
||||
) -> io::Result<()> {
|
||||
// Safety: We're calling `epoll_wait` via FFI and we know how it
|
||||
// behaves.
|
||||
unsafe {
|
||||
event_list.events.set_len(0);
|
||||
let nfds = ret_u32(c::epoll_wait(
|
||||
self.epoll_fd.as_fd().as_raw_fd(),
|
||||
event_list.events.as_mut_ptr().cast::<c::epoll_event>(),
|
||||
event_list.events.capacity().try_into().unwrap_or(i32::MAX),
|
||||
timeout,
|
||||
))?;
|
||||
event_list.events.set_len(nfds as usize);
|
||||
event_list.context = &self.context;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> AsRawFd for Epoll<Owning<'context, T>> {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.epoll_fd.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> IntoRawFd for Epoll<Owning<'context, T>> {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.epoll_fd.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> FromRawFd for Epoll<Owning<'context, T>> {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
Self {
|
||||
epoll_fd: OwnedFd::from_raw_fd(fd),
|
||||
context: Owning::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> AsFd for Epoll<Owning<'context, T>> {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.epoll_fd.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> From<Epoll<Owning<'context, T>>>
|
||||
for OwnedFd
|
||||
{
|
||||
fn from(epoll: Epoll<Owning<'context, T>>) -> Self {
|
||||
epoll.epoll_fd
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> From<OwnedFd>
|
||||
for Epoll<Owning<'context, T>>
|
||||
{
|
||||
fn from(fd: OwnedFd) -> Self {
|
||||
Self {
|
||||
epoll_fd: fd,
|
||||
context: Owning::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the `Event`s in an `EventVec`.
|
||||
pub struct Iter<'context, Context: self::Context> {
|
||||
iter: core::slice::Iter<'context, Event>,
|
||||
context: *const Context,
|
||||
_phantom: PhantomData<&'context Context>,
|
||||
}
|
||||
|
||||
impl<'context, Context: self::Context> Iterator for Iter<'context, Context> {
|
||||
type Item = (EventFlags, Ref<'context, Context::Target>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Safety: `self.context` is guaranteed to be valid because we hold
|
||||
// `'context` for it. And we know this event is associated with this
|
||||
// context because `wait` sets both.
|
||||
self.iter.next().map(|event| {
|
||||
(event.event_flags, unsafe {
|
||||
(*self.context).decode(event.encoded)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A record of an event that occurred.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(
|
||||
any(
|
||||
all(
|
||||
target_arch = "x86",
|
||||
not(target_env = "musl"),
|
||||
not(target_os = "android"),
|
||||
),
|
||||
target_arch = "x86_64",
|
||||
),
|
||||
repr(packed)
|
||||
)]
|
||||
struct Event {
|
||||
// Match the layout of `c::epoll_event`. We just use a `u64` instead of
|
||||
// the full union; `Context` implementations will simply need to deal with
|
||||
// casting the value into and out of the `u64` themselves.
|
||||
event_flags: EventFlags,
|
||||
encoded: u64,
|
||||
}
|
||||
|
||||
/// A vector of `Event`s, plus context for interpreting them.
|
||||
pub struct EventVec<'context, Context: self::Context> {
|
||||
events: Vec<Event>,
|
||||
context: *const Context,
|
||||
_phantom: PhantomData<&'context Context>,
|
||||
}
|
||||
|
||||
impl<'context, Context: self::Context> EventVec<'context, Context> {
|
||||
/// Constructs an `EventVec` with memory for `capacity` `Event`s.
|
||||
#[inline]
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
Self {
|
||||
events: Vec::with_capacity(capacity),
|
||||
context: null(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the current `Event` capacity of this `EventVec`.
|
||||
#[inline]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.events.capacity()
|
||||
}
|
||||
|
||||
/// Reserves enough memory for at least `additional` more `Event`s.
|
||||
#[inline]
|
||||
pub fn reserve(&mut self, additional: usize) {
|
||||
self.events.reserve(additional);
|
||||
}
|
||||
|
||||
/// Reserves enough memory for exactly `additional` more `Event`s.
|
||||
#[inline]
|
||||
pub fn reserve_exact(&mut self, additional: usize) {
|
||||
self.events.reserve_exact(additional);
|
||||
}
|
||||
|
||||
/// Clears all the `Events` out of this `EventVec`.
|
||||
#[inline]
|
||||
pub fn clear(&mut self) {
|
||||
self.events.clear();
|
||||
}
|
||||
|
||||
/// Shrinks the capacity of this `EventVec` as much as possible.
|
||||
#[inline]
|
||||
pub fn shrink_to_fit(&mut self) {
|
||||
self.events.shrink_to_fit();
|
||||
}
|
||||
|
||||
/// Returns an iterator over the `Event`s in this `EventVec`.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> Iter<'_, Context> {
|
||||
Iter {
|
||||
iter: self.events.iter(),
|
||||
context: self.context,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of `Event`s logically contained in this `EventVec`.
|
||||
#[inline]
|
||||
pub fn len(&mut self) -> usize {
|
||||
self.events.len()
|
||||
}
|
||||
|
||||
/// Tests whether this `EventVec` is logically empty.
|
||||
#[inline]
|
||||
pub fn is_empty(&mut self) -> bool {
|
||||
self.events.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'context, Context: self::Context> IntoIterator for &'context EventVec<'context, Context> {
|
||||
type IntoIter = Iter<'context, Context>;
|
||||
type Item = (EventFlags, Ref<'context, Context::Target>);
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
1106
vendor/rustix/src/backend/libc/io/errno.rs
vendored
Normal file
1106
vendor/rustix/src/backend/libc/io/errno.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
87
vendor/rustix/src/backend/libc/io/io_slice.rs
vendored
Normal file
87
vendor/rustix/src/backend/libc/io/io_slice.rs
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
//! The following is derived from Rust's
|
||||
//! library/std/src/sys/unix/io.rs
|
||||
//! dca3f1b786efd27be3b325ed1e01e247aa589c3b.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use super::super::c;
|
||||
use core::marker::PhantomData;
|
||||
use core::slice;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct IoSlice<'a> {
|
||||
vec: c::iovec,
|
||||
_p: PhantomData<&'a [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> IoSlice<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
||||
IoSlice {
|
||||
vec: c::iovec {
|
||||
iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void,
|
||||
iov_len: buf.len(),
|
||||
},
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
if self.vec.iov_len < n {
|
||||
panic!("advancing IoSlice beyond its length");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.vec.iov_len -= n;
|
||||
self.vec.iov_base = self.vec.iov_base.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceMut<'a> {
|
||||
vec: c::iovec,
|
||||
_p: PhantomData<&'a mut [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> IoSliceMut<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
||||
IoSliceMut {
|
||||
vec: c::iovec {
|
||||
iov_base: buf.as_mut_ptr() as *mut c::c_void,
|
||||
iov_len: buf.len(),
|
||||
},
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
if self.vec.iov_len < n {
|
||||
panic!("advancing IoSliceMut beyond its length");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.vec.iov_len -= n;
|
||||
self.vec.iov_base = self.vec.iov_base.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
|
||||
}
|
||||
}
|
||||
13
vendor/rustix/src/backend/libc/io/mod.rs
vendored
Normal file
13
vendor/rustix/src/backend/libc/io/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
pub(crate) mod errno;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) mod io_slice;
|
||||
pub(crate) mod poll_fd;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod types;
|
||||
|
||||
#[cfg_attr(windows, path = "windows_syscalls.rs")]
|
||||
pub(crate) mod syscalls;
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
pub mod epoll;
|
||||
136
vendor/rustix/src/backend/libc/io/poll_fd.rs
vendored
Normal file
136
vendor/rustix/src/backend/libc/io/poll_fd.rs
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
use super::super::c;
|
||||
use super::super::conv::borrowed_fd;
|
||||
#[cfg(windows)]
|
||||
use super::super::fd::RawFd;
|
||||
use super::super::fd::{AsFd, AsRawFd, BorrowedFd, LibcFd};
|
||||
use bitflags::bitflags;
|
||||
use core::marker::PhantomData;
|
||||
#[cfg(windows)]
|
||||
use std::fmt;
|
||||
|
||||
bitflags! {
|
||||
/// `POLL*` flags for use with [`poll`].
|
||||
///
|
||||
/// [`poll`]: crate::io::poll
|
||||
pub struct PollFlags: c::c_short {
|
||||
/// `POLLIN`
|
||||
const IN = c::POLLIN;
|
||||
/// `POLLPRI`
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
const PRI = c::POLLPRI;
|
||||
/// `POLLOUT`
|
||||
const OUT = c::POLLOUT;
|
||||
/// `POLLRDNORM`
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
const RDNORM = c::POLLRDNORM;
|
||||
/// `POLLWRNORM`
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
const WRNORM = c::POLLWRNORM;
|
||||
/// `POLLRDBAND`
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
const RDBAND = c::POLLRDBAND;
|
||||
/// `POLLWRBAND`
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
const WRBAND = c::POLLWRBAND;
|
||||
/// `POLLERR`
|
||||
const ERR = c::POLLERR;
|
||||
/// `POLLHUP`
|
||||
const HUP = c::POLLHUP;
|
||||
/// `POLLNVAL`
|
||||
const NVAL = c::POLLNVAL;
|
||||
/// `POLLRDHUP`
|
||||
#[cfg(all(
|
||||
any(target_os = "android", target_os = "linux"),
|
||||
not(any(target_arch = "sparc", target_arch = "sparc64"))),
|
||||
)]
|
||||
const RDHUP = c::POLLRDHUP;
|
||||
}
|
||||
}
|
||||
|
||||
/// `struct pollfd`—File descriptor and flags for use with [`poll`].
|
||||
///
|
||||
/// [`poll`]: crate::io::poll
|
||||
#[doc(alias = "pollfd")]
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(not(windows), derive(Debug))]
|
||||
#[repr(transparent)]
|
||||
pub struct PollFd<'fd> {
|
||||
pollfd: c::pollfd,
|
||||
_phantom: PhantomData<BorrowedFd<'fd>>,
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl<'fd> fmt::Debug for PollFd<'fd> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_struct("pollfd")
|
||||
.field("fd", &self.pollfd.fd)
|
||||
.field("events", &self.pollfd.events)
|
||||
.field("revents", &self.pollfd.revents)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'fd> PollFd<'fd> {
|
||||
/// Constructs a new `PollFd` holding `fd` and `events`.
|
||||
#[inline]
|
||||
pub fn new<Fd: AsFd>(fd: &'fd Fd, events: PollFlags) -> Self {
|
||||
Self::from_borrowed_fd(fd.as_fd(), events)
|
||||
}
|
||||
|
||||
/// Sets the contained file descriptor to `fd`.
|
||||
#[inline]
|
||||
pub fn set_fd<Fd: AsFd>(&mut self, fd: &'fd Fd) {
|
||||
self.pollfd.fd = fd.as_fd().as_raw_fd() as LibcFd;
|
||||
}
|
||||
|
||||
/// Clears the ready events.
|
||||
#[inline]
|
||||
pub fn clear_revents(&mut self) {
|
||||
self.pollfd.revents = 0;
|
||||
}
|
||||
|
||||
/// Constructs a new `PollFd` holding `fd` and `events`.
|
||||
///
|
||||
/// This is the same as `new`, but can be used to avoid borrowing the
|
||||
/// `BorrowedFd`, which can be tricky in situations where the `BorrowedFd`
|
||||
/// is a temporary.
|
||||
#[inline]
|
||||
pub fn from_borrowed_fd(fd: BorrowedFd<'fd>, events: PollFlags) -> Self {
|
||||
Self {
|
||||
pollfd: c::pollfd {
|
||||
fd: borrowed_fd(fd),
|
||||
events: events.bits(),
|
||||
revents: 0,
|
||||
},
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the ready events.
|
||||
#[inline]
|
||||
pub fn revents(&self) -> PollFlags {
|
||||
// Use `unwrap()` here because in theory we know we know all the bits
|
||||
// the OS might set here, but OS's have added extensions in the past.
|
||||
PollFlags::from_bits(self.pollfd.revents).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
impl<'fd> AsFd for PollFd<'fd> {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
// Safety: Our constructors and `set_fd` require `pollfd.fd` to be
|
||||
// valid for the `fd lifetime.
|
||||
unsafe { BorrowedFd::borrow_raw(self.pollfd.fd) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl<'fd> io_lifetimes::AsSocket for PollFd<'fd> {
|
||||
#[inline]
|
||||
fn as_socket(&self) -> BorrowedFd<'_> {
|
||||
// Safety: Our constructors and `set_fd` require `pollfd.fd` to be
|
||||
// valid for the `fd lifetime.
|
||||
unsafe { BorrowedFd::borrow_raw(self.pollfd.fd as RawFd) }
|
||||
}
|
||||
}
|
||||
533
vendor/rustix/src/backend/libc/io/syscalls.rs
vendored
Normal file
533
vendor/rustix/src/backend/libc/io/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
//! libc syscalls supporting `rustix::io`.
|
||||
|
||||
use super::super::c;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use super::super::conv::syscall_ret_owned_fd;
|
||||
use super::super::conv::{
|
||||
borrowed_fd, ret, ret_c_int, ret_discarded_fd, ret_owned_fd, ret_ssize_t,
|
||||
};
|
||||
use super::super::offset::{libc_pread, libc_pwrite};
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))]
|
||||
use super::super::offset::{libc_preadv, libc_pwritev};
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
use super::super::offset::{libc_preadv2, libc_pwritev2};
|
||||
use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
|
||||
#[cfg(not(any(target_os = "aix", target_os = "wasi")))]
|
||||
use crate::io::DupFlags;
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
use crate::io::PipeFlags;
|
||||
use crate::io::{self, FdFlags, IoSlice, IoSliceMut, PollFd};
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use crate::io::{EventfdFlags, IoSliceRaw, ReadWriteFlags, SpliceFlags};
|
||||
use core::cmp::min;
|
||||
use core::convert::TryInto;
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use core::ptr;
|
||||
#[cfg(all(feature = "fs", feature = "net"))]
|
||||
use libc_errno::errno;
|
||||
|
||||
pub(crate) fn read(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let nread = unsafe {
|
||||
ret_ssize_t(c::read(
|
||||
borrowed_fd(fd),
|
||||
buf.as_mut_ptr().cast(),
|
||||
min(buf.len(), READ_LIMIT),
|
||||
))?
|
||||
};
|
||||
Ok(nread as usize)
|
||||
}
|
||||
|
||||
pub(crate) fn write(fd: BorrowedFd<'_>, buf: &[u8]) -> io::Result<usize> {
|
||||
let nwritten = unsafe {
|
||||
ret_ssize_t(c::write(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
min(buf.len(), READ_LIMIT),
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], offset: u64) -> io::Result<usize> {
|
||||
let len = min(buf.len(), READ_LIMIT);
|
||||
|
||||
// Silently cast; we'll get `EINVAL` if the value is negative.
|
||||
let offset = offset as i64;
|
||||
|
||||
let nread = unsafe {
|
||||
ret_ssize_t(libc_pread(
|
||||
borrowed_fd(fd),
|
||||
buf.as_mut_ptr().cast(),
|
||||
len,
|
||||
offset,
|
||||
))?
|
||||
};
|
||||
Ok(nread as usize)
|
||||
}
|
||||
|
||||
pub(crate) fn pwrite(fd: BorrowedFd<'_>, buf: &[u8], offset: u64) -> io::Result<usize> {
|
||||
let len = min(buf.len(), READ_LIMIT);
|
||||
|
||||
// Silently cast; we'll get `EINVAL` if the value is negative.
|
||||
let offset = offset as i64;
|
||||
|
||||
let nwritten = unsafe {
|
||||
ret_ssize_t(libc_pwrite(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
len,
|
||||
offset,
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
|
||||
let nread = unsafe {
|
||||
ret_ssize_t(c::readv(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), max_iov()) as c::c_int,
|
||||
))?
|
||||
};
|
||||
Ok(nread as usize)
|
||||
}
|
||||
|
||||
pub(crate) fn writev(fd: BorrowedFd<'_>, bufs: &[IoSlice]) -> io::Result<usize> {
|
||||
let nwritten = unsafe {
|
||||
ret_ssize_t(c::writev(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), max_iov()) as c::c_int,
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))]
|
||||
pub(crate) fn preadv(
|
||||
fd: BorrowedFd<'_>,
|
||||
bufs: &mut [IoSliceMut],
|
||||
offset: u64,
|
||||
) -> io::Result<usize> {
|
||||
// Silently cast; we'll get `EINVAL` if the value is negative.
|
||||
let offset = offset as i64;
|
||||
let nread = unsafe {
|
||||
ret_ssize_t(libc_preadv(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), max_iov()) as c::c_int,
|
||||
offset,
|
||||
))?
|
||||
};
|
||||
Ok(nread as usize)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))]
|
||||
pub(crate) fn pwritev(fd: BorrowedFd<'_>, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
|
||||
// Silently cast; we'll get `EINVAL` if the value is negative.
|
||||
let offset = offset as i64;
|
||||
let nwritten = unsafe {
|
||||
ret_ssize_t(libc_pwritev(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), max_iov()) as c::c_int,
|
||||
offset,
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
pub(crate) fn preadv2(
|
||||
fd: BorrowedFd<'_>,
|
||||
bufs: &mut [IoSliceMut],
|
||||
offset: u64,
|
||||
flags: ReadWriteFlags,
|
||||
) -> io::Result<usize> {
|
||||
// Silently cast; we'll get `EINVAL` if the value is negative.
|
||||
let offset = offset as i64;
|
||||
let nread = unsafe {
|
||||
ret_ssize_t(libc_preadv2(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), max_iov()) as c::c_int,
|
||||
offset,
|
||||
flags.bits(),
|
||||
))?
|
||||
};
|
||||
Ok(nread as usize)
|
||||
}
|
||||
|
||||
/// At present, `libc` only has `preadv2` defined for glibc. On other
|
||||
/// ABIs, `ReadWriteFlags` has no flags defined, and we use plain `preadv`.
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
all(target_os = "linux", not(target_env = "gnu")),
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn preadv2(
|
||||
fd: BorrowedFd<'_>,
|
||||
bufs: &mut [IoSliceMut],
|
||||
offset: u64,
|
||||
flags: ReadWriteFlags,
|
||||
) -> io::Result<usize> {
|
||||
assert!(flags.is_empty());
|
||||
preadv(fd, bufs, offset)
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
pub(crate) fn pwritev2(
|
||||
fd: BorrowedFd<'_>,
|
||||
bufs: &[IoSlice],
|
||||
offset: u64,
|
||||
flags: ReadWriteFlags,
|
||||
) -> io::Result<usize> {
|
||||
// Silently cast; we'll get `EINVAL` if the value is negative.
|
||||
let offset = offset as i64;
|
||||
let nwritten = unsafe {
|
||||
ret_ssize_t(libc_pwritev2(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), max_iov()) as c::c_int,
|
||||
offset,
|
||||
flags.bits(),
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
/// At present, `libc` only has `pwritev2` defined for glibc. On other
|
||||
/// ABIs, `ReadWriteFlags` has no flags defined, and we use plain `pwritev`.
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
all(target_os = "linux", not(target_env = "gnu")),
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn pwritev2(
|
||||
fd: BorrowedFd<'_>,
|
||||
bufs: &[IoSlice],
|
||||
offset: u64,
|
||||
flags: ReadWriteFlags,
|
||||
) -> io::Result<usize> {
|
||||
assert!(flags.is_empty());
|
||||
pwritev(fd, bufs, offset)
|
||||
}
|
||||
|
||||
// These functions are derived from Rust's library/std/src/sys/unix/fd.rs at
|
||||
// revision a77da2d454e6caa227a85b16410b95f93495e7e0.
|
||||
|
||||
// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, with the
|
||||
// man page quoting that if the count of bytes to read is greater than
|
||||
// `SSIZE_MAX` the result is "unspecified".
|
||||
//
|
||||
// On macOS, however, apparently the 64-bit libc is either buggy or
|
||||
// intentionally showing odd behavior by rejecting any read with a size larger
|
||||
// than or equal to `INT_MAX`. To handle both of these the read size is capped
|
||||
// on both platforms.
|
||||
#[cfg(target_os = "macos")]
|
||||
const READ_LIMIT: usize = c::c_int::MAX as usize - 1;
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
const READ_LIMIT: usize = c::ssize_t::MAX as usize;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
const fn max_iov() -> usize {
|
||||
c::IOV_MAX as usize
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
|
||||
const fn max_iov() -> usize {
|
||||
c::UIO_MAXIOV as usize
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "linux",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
const fn max_iov() -> usize {
|
||||
16 // The minimum value required by POSIX.
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn close(raw_fd: RawFd) {
|
||||
let _ = c::close(raw_fd as c::c_int);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
|
||||
unsafe { syscall_ret_owned_fd(c::syscall(c::SYS_eventfd2, initval, flags.bits())) }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) fn ioctl_blksszget(fd: BorrowedFd) -> io::Result<u32> {
|
||||
let mut result = MaybeUninit::<c::c_uint>::uninit();
|
||||
unsafe {
|
||||
ret(c::ioctl(borrowed_fd(fd), c::BLKSSZGET, result.as_mut_ptr()))?;
|
||||
Ok(result.assume_init() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result<u32> {
|
||||
let mut result = MaybeUninit::<c::c_uint>::uninit();
|
||||
unsafe {
|
||||
ret(c::ioctl(
|
||||
borrowed_fd(fd),
|
||||
c::BLKPBSZGET,
|
||||
result.as_mut_ptr(),
|
||||
))?;
|
||||
Ok(result.assume_init() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub(crate) fn ioctl_fionread(fd: BorrowedFd<'_>) -> io::Result<u64> {
|
||||
let mut nread = MaybeUninit::<c::c_int>::uninit();
|
||||
unsafe {
|
||||
ret(c::ioctl(borrowed_fd(fd), c::FIONREAD, nread.as_mut_ptr()))?;
|
||||
// `FIONREAD` returns the number of bytes silently casted to a `c_int`,
|
||||
// even when this is lossy. The best we can do is convert it back to a
|
||||
// `u64` without sign-extending it back first.
|
||||
Ok(u64::from(nread.assume_init() as c::c_uint))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
|
||||
unsafe {
|
||||
let data = value as c::c_int;
|
||||
ret(c::ioctl(borrowed_fd(fd), c::FIONBIO, &data))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
#[cfg(all(feature = "fs", feature = "net"))]
|
||||
pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
|
||||
let (mut read, mut write) = crate::fs::fd::_is_file_read_write(fd)?;
|
||||
let mut not_socket = false;
|
||||
if read {
|
||||
// Do a `recv` with `PEEK` and `DONTWAIT` for 1 byte. A 0 indicates
|
||||
// the read side is shut down; an `EWOULDBLOCK` indicates the read
|
||||
// side is still open.
|
||||
match unsafe {
|
||||
c::recv(
|
||||
borrowed_fd(fd),
|
||||
MaybeUninit::<[u8; 1]>::uninit()
|
||||
.as_mut_ptr()
|
||||
.cast::<c::c_void>(),
|
||||
1,
|
||||
c::MSG_PEEK | c::MSG_DONTWAIT,
|
||||
)
|
||||
} {
|
||||
0 => read = false,
|
||||
-1 => {
|
||||
#[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK`
|
||||
match errno().0 {
|
||||
c::EAGAIN | c::EWOULDBLOCK => (),
|
||||
c::ENOTSOCK => not_socket = true,
|
||||
err => return Err(io::Errno(err)),
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
if write && !not_socket {
|
||||
// Do a `send` with `DONTWAIT` for 0 bytes. An `EPIPE` indicates
|
||||
// the write side is shut down.
|
||||
if unsafe { c::send(borrowed_fd(fd), [].as_ptr(), 0, c::MSG_DONTWAIT) } == -1 {
|
||||
#[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK`
|
||||
match errno().0 {
|
||||
c::EAGAIN | c::EWOULDBLOCK => (),
|
||||
c::ENOTSOCK => (),
|
||||
c::EPIPE => write = false,
|
||||
err => return Err(io::Errno(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((read, write))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
#[cfg(all(feature = "fs", feature = "net"))]
|
||||
pub(crate) fn is_read_write(_fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
|
||||
todo!("Implement is_read_write for WASI in terms of fd_fdstat_get");
|
||||
}
|
||||
|
||||
pub(crate) fn fcntl_getfd(fd: BorrowedFd<'_>) -> io::Result<FdFlags> {
|
||||
unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFD)).map(FdFlags::from_bits_truncate) }
|
||||
}
|
||||
|
||||
pub(crate) fn fcntl_setfd(fd: BorrowedFd<'_>, flags: FdFlags) -> io::Result<()> {
|
||||
unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETFD, flags.bits())) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn fcntl_dupfd_cloexec(fd: BorrowedFd<'_>, min: RawFd) -> io::Result<OwnedFd> {
|
||||
unsafe { ret_owned_fd(c::fcntl(borrowed_fd(fd), c::F_DUPFD_CLOEXEC, min)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn dup(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
|
||||
unsafe { ret_owned_fd(c::dup(borrowed_fd(fd))) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn dup2(fd: BorrowedFd<'_>, new: &mut OwnedFd) -> io::Result<()> {
|
||||
unsafe { ret_discarded_fd(c::dup2(borrowed_fd(fd), borrowed_fd(new.as_fd()))) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret_discarded_fd(c::dup3(
|
||||
borrowed_fd(fd),
|
||||
borrowed_fd(new.as_fd()),
|
||||
flags.bits(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "redox",
|
||||
))]
|
||||
pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, _flags: DupFlags) -> io::Result<()> {
|
||||
// Android 5.0 has `dup3`, but libc doesn't have bindings. Emulate it
|
||||
// using `dup2`. We don't need to worry about the difference between
|
||||
// `dup2` and `dup3` when the file descriptors are equal because we
|
||||
// have an `&mut OwnedFd` which means `fd` doesn't alias it.
|
||||
dup2(fd, new)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
pub(crate) fn ioctl_fioclex(fd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe { ret(c::ioctl(borrowed_fd(fd), c::FIOCLEX)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn ioctl_tiocexcl(fd: BorrowedFd) -> io::Result<()> {
|
||||
unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCEXCL as _)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd) -> io::Result<()> {
|
||||
unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCNXCL as _)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> {
|
||||
unsafe {
|
||||
let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
|
||||
ret(c::pipe(result.as_mut_ptr().cast::<i32>()))?;
|
||||
let [p0, p1] = result.assume_init();
|
||||
Ok((p0, p1))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "wasi"
|
||||
)))]
|
||||
pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> {
|
||||
unsafe {
|
||||
let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
|
||||
ret(c::pipe2(result.as_mut_ptr().cast::<i32>(), flags.bits()))?;
|
||||
let [p0, p1] = result.assume_init();
|
||||
Ok((p0, p1))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
|
||||
let nfds = fds
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|_convert_err| io::Errno::INVAL)?;
|
||||
|
||||
ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) })
|
||||
.map(|nready| nready as usize)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub fn splice(
|
||||
fd_in: BorrowedFd,
|
||||
off_in: Option<&mut u64>,
|
||||
fd_out: BorrowedFd,
|
||||
off_out: Option<&mut u64>,
|
||||
len: usize,
|
||||
flags: SpliceFlags,
|
||||
) -> io::Result<usize> {
|
||||
let off_in = off_in
|
||||
.map(|off| (off as *mut u64).cast())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
|
||||
let off_out = off_out
|
||||
.map(|off| (off as *mut u64).cast())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
|
||||
ret_ssize_t(unsafe {
|
||||
c::splice(
|
||||
borrowed_fd(fd_in),
|
||||
off_in,
|
||||
borrowed_fd(fd_out),
|
||||
off_out,
|
||||
len,
|
||||
flags.bits(),
|
||||
)
|
||||
})
|
||||
.map(|spliced| spliced as usize)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub unsafe fn vmsplice(
|
||||
fd: BorrowedFd,
|
||||
bufs: &[IoSliceRaw],
|
||||
flags: SpliceFlags,
|
||||
) -> io::Result<usize> {
|
||||
ret_ssize_t(c::vmsplice(
|
||||
borrowed_fd(fd),
|
||||
bufs.as_ptr().cast::<c::iovec>(),
|
||||
min(bufs.len(), max_iov()),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(|spliced| spliced as usize)
|
||||
}
|
||||
164
vendor/rustix/src/backend/libc/io/types.rs
vendored
Normal file
164
vendor/rustix/src/backend/libc/io/types.rs
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
use super::super::c;
|
||||
use bitflags::bitflags;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use core::marker::PhantomData;
|
||||
|
||||
bitflags! {
|
||||
/// `FD_*` constants for use with [`fcntl_getfd`] and [`fcntl_setfd`].
|
||||
///
|
||||
/// [`fcntl_getfd`]: crate::io::fcntl_getfd
|
||||
/// [`fcntl_setfd`]: crate::io::fcntl_setfd
|
||||
pub struct FdFlags: c::c_int {
|
||||
/// `FD_CLOEXEC`
|
||||
const CLOEXEC = c::FD_CLOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
bitflags! {
|
||||
/// `RWF_*` constants for use with [`preadv2`] and [`pwritev2`].
|
||||
///
|
||||
/// [`preadv2`]: crate::io::preadv2
|
||||
/// [`pwritev2`]: crate::io::pwritev
|
||||
pub struct ReadWriteFlags: c::c_int {
|
||||
/// `RWF_DSYNC` (since Linux 4.7)
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
const DSYNC = c::RWF_DSYNC;
|
||||
/// `RWF_HIPRI` (since Linux 4.6)
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
const HIPRI = c::RWF_HIPRI;
|
||||
/// `RWF_SYNC` (since Linux 4.7)
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
const SYNC = c::RWF_SYNC;
|
||||
/// `RWF_NOWAIT` (since Linux 4.14)
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
const NOWAIT = c::RWF_NOWAIT;
|
||||
/// `RWF_APPEND` (since Linux 4.16)
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
const APPEND = c::RWF_APPEND;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
bitflags! {
|
||||
/// `SPLICE_F_*` constants for use with [`splice`] and [`vmsplice`].
|
||||
pub struct SpliceFlags: c::c_uint {
|
||||
/// `SPLICE_F_MOVE`
|
||||
const MOVE = c::SPLICE_F_MOVE;
|
||||
/// `SPLICE_F_NONBLOCK`
|
||||
const NONBLOCK = c::SPLICE_F_NONBLOCK;
|
||||
/// `SPLICE_F_MORE`
|
||||
const MORE = c::SPLICE_F_MORE;
|
||||
/// `SPLICE_F_GIFT`
|
||||
const GIFT = c::SPLICE_F_GIFT;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
bitflags! {
|
||||
/// `O_*` constants for use with [`dup2`].
|
||||
///
|
||||
/// [`dup2`]: crate::io::dup2
|
||||
pub struct DupFlags: c::c_int {
|
||||
/// `O_CLOEXEC`
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "redox",
|
||||
)))] // Android 5.0 has dup3, but libc doesn't have bindings
|
||||
const CLOEXEC = c::O_CLOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
|
||||
bitflags! {
|
||||
/// `O_*` constants for use with [`pipe_with`].
|
||||
///
|
||||
/// [`pipe_with`]: crate::io::pipe_with
|
||||
pub struct PipeFlags: c::c_int {
|
||||
/// `O_CLOEXEC`
|
||||
const CLOEXEC = c::O_CLOEXEC;
|
||||
/// `O_DIRECT`
|
||||
#[cfg(not(any(
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const DIRECT = c::O_DIRECT;
|
||||
/// `O_NONBLOCK`
|
||||
const NONBLOCK = c::O_NONBLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
bitflags! {
|
||||
/// `EFD_*` flags for use with [`eventfd`].
|
||||
///
|
||||
/// [`eventfd`]: crate::io::eventfd
|
||||
pub struct EventfdFlags: c::c_int {
|
||||
/// `EFD_CLOEXEC`
|
||||
const CLOEXEC = c::EFD_CLOEXEC;
|
||||
/// `EFD_NONBLOCK`
|
||||
const NONBLOCK = c::EFD_NONBLOCK;
|
||||
/// `EFD_SEMAPHORE`
|
||||
const SEMAPHORE = c::EFD_SEMAPHORE;
|
||||
}
|
||||
}
|
||||
|
||||
/// `PIPE_BUF`—The maximum size of a write to a pipe guaranteed to be atomic.
|
||||
#[cfg(not(any(
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub const PIPE_BUF: usize = c::PIPE_BUF;
|
||||
|
||||
#[cfg(not(any(windows, target_os = "redox")))]
|
||||
pub(crate) const AT_FDCWD: c::c_int = c::AT_FDCWD;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) const STDIN_FILENO: c::c_int = c::STDIN_FILENO;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) const STDOUT_FILENO: c::c_int = c::STDOUT_FILENO;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) const STDERR_FILENO: c::c_int = c::STDERR_FILENO;
|
||||
|
||||
/// A buffer type used with `vmsplice`.
|
||||
/// It is guaranteed to be ABI compatible with the iovec type on Unix platforms and WSABUF on Windows.
|
||||
/// Unlike `IoSlice` and `IoSliceMut` it is semantically like a raw pointer,
|
||||
/// and therefore can be shared or mutated as needed.
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceRaw<'a> {
|
||||
_buf: c::iovec,
|
||||
_lifetime: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
impl<'a> IoSliceRaw<'a> {
|
||||
/// Creates a new IoSlice wrapping a byte slice.
|
||||
pub fn from_slice(buf: &'a [u8]) -> Self {
|
||||
IoSliceRaw {
|
||||
_buf: c::iovec {
|
||||
iov_base: buf.as_ptr() as *mut u8 as *mut c::c_void,
|
||||
iov_len: buf.len() as _,
|
||||
},
|
||||
_lifetime: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new IoSlice wrapping a mutable byte slice.
|
||||
pub fn from_slice_mut(buf: &'a mut [u8]) -> Self {
|
||||
IoSliceRaw {
|
||||
_buf: c::iovec {
|
||||
iov_base: buf.as_mut_ptr() as *mut c::c_void,
|
||||
iov_len: buf.len() as _,
|
||||
},
|
||||
_lifetime: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
39
vendor/rustix/src/backend/libc/io/windows_syscalls.rs
vendored
Normal file
39
vendor/rustix/src/backend/libc/io/windows_syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//! Windows system calls in the `io` module.
|
||||
|
||||
use super::super::c;
|
||||
use super::super::conv::{borrowed_fd, ret, ret_c_int};
|
||||
use super::super::fd::LibcFd;
|
||||
use crate::fd::{BorrowedFd, RawFd};
|
||||
use crate::io;
|
||||
use crate::io::PollFd;
|
||||
use core::convert::TryInto;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
pub(crate) unsafe fn close(raw_fd: RawFd) {
|
||||
let _ = c::close(raw_fd as LibcFd);
|
||||
}
|
||||
|
||||
pub(crate) fn ioctl_fionread(fd: BorrowedFd<'_>) -> io::Result<u64> {
|
||||
let mut nread = MaybeUninit::<c::c_ulong>::uninit();
|
||||
unsafe {
|
||||
ret(c::ioctl(borrowed_fd(fd), c::FIONREAD, nread.as_mut_ptr()))?;
|
||||
Ok(u64::from(nread.assume_init()))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
|
||||
unsafe {
|
||||
let mut data = value as c::c_uint;
|
||||
ret(c::ioctl(borrowed_fd(fd), c::FIONBIO, &mut data))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
|
||||
let nfds = fds
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|_convert_err| io::Errno::INVAL)?;
|
||||
|
||||
ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) })
|
||||
.map(|nready| nready as usize)
|
||||
}
|
||||
77
vendor/rustix/src/backend/libc/io_lifetimes.rs
vendored
Normal file
77
vendor/rustix/src/backend/libc/io_lifetimes.rs
vendored
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//! `io_lifetimes` types for Windows assuming that Fd is Socket.
|
||||
//!
|
||||
//! We can make this assumption since `rustix` supports only `rustix::net` on
|
||||
//! Windows.
|
||||
|
||||
pub use io_lifetimes::{BorrowedSocket as BorrowedFd, OwnedSocket as OwnedFd};
|
||||
#[cfg(feature = "std")]
|
||||
pub use std::os::windows::io::RawSocket as RawFd;
|
||||
pub(crate) use windows_sys::Win32::Networking::WinSock::SOCKET as LibcFd;
|
||||
|
||||
// Re-export the `Socket` traits so that users can implement them.
|
||||
pub use io_lifetimes::AsSocket;
|
||||
|
||||
/// A version of [`AsRawFd`] for use with Winsock2 API.
|
||||
///
|
||||
/// [`AsRawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsRawFd.html
|
||||
pub trait AsRawFd {
|
||||
/// A version of [`as_raw_fd`] for use with Winsock2 API.
|
||||
///
|
||||
/// [`as_raw_fd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html#tymethod.as_raw_fd
|
||||
fn as_raw_fd(&self) -> RawFd;
|
||||
}
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: std::os::windows::io::AsRawSocket> AsRawFd for T {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of [`IntoRawFd`] for use with Winsock2 API.
|
||||
///
|
||||
/// [`IntoRawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.IntoRawFd.html
|
||||
pub trait IntoRawFd {
|
||||
/// A version of [`into_raw_fd`] for use with Winsock2 API.
|
||||
///
|
||||
/// [`into_raw_fd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html#tymethod.into_raw_fd
|
||||
fn into_raw_fd(self) -> RawFd;
|
||||
}
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: std::os::windows::io::IntoRawSocket> IntoRawFd for T {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.into_raw_socket()
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of [`FromRawFd`] for use with Winsock2 API.
|
||||
///
|
||||
/// [`FromRawFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html
|
||||
pub trait FromRawFd {
|
||||
/// A version of [`from_raw_fd`] for use with Winsock2 API.
|
||||
///
|
||||
/// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html#tymethod.from_raw_fd
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self;
|
||||
}
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: std::os::windows::io::FromRawSocket> FromRawFd for T {
|
||||
#[inline]
|
||||
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||
Self::from_raw_socket(raw_fd)
|
||||
}
|
||||
}
|
||||
|
||||
/// A version of [`AsFd`] for use with Winsock2 API.
|
||||
///
|
||||
/// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.AsFd.html
|
||||
pub trait AsFd {
|
||||
/// An `as_fd` function for Winsock2, where a `Fd` is a `Socket`.
|
||||
fn as_fd(&self) -> BorrowedFd;
|
||||
}
|
||||
impl<T: AsSocket> AsFd for T {
|
||||
#[inline]
|
||||
fn as_fd(&self) -> BorrowedFd {
|
||||
self.as_socket()
|
||||
}
|
||||
}
|
||||
1
vendor/rustix/src/backend/libc/io_uring/mod.rs
vendored
Normal file
1
vendor/rustix/src/backend/libc/io_uring/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod syscalls;
|
||||
55
vendor/rustix/src/backend/libc/io_uring/syscalls.rs
vendored
Normal file
55
vendor/rustix/src/backend/libc/io_uring/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
//! libc syscalls supporting `rustix::io_uring`.
|
||||
|
||||
use super::super::c;
|
||||
use super::super::conv::{borrowed_fd, syscall_ret, syscall_ret_owned_fd, syscall_ret_u32};
|
||||
use crate::fd::{BorrowedFd, OwnedFd};
|
||||
use crate::io;
|
||||
use crate::io_uring::{io_uring_params, IoringEnterFlags, IoringRegisterOp};
|
||||
use linux_raw_sys::general::{__NR_io_uring_enter, __NR_io_uring_register, __NR_io_uring_setup};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn io_uring_setup(entries: u32, params: &mut io_uring_params) -> io::Result<OwnedFd> {
|
||||
unsafe {
|
||||
syscall_ret_owned_fd(c::syscall(
|
||||
__NR_io_uring_setup as _,
|
||||
entries as usize,
|
||||
params,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn io_uring_register(
|
||||
fd: BorrowedFd<'_>,
|
||||
opcode: IoringRegisterOp,
|
||||
arg: *const c::c_void,
|
||||
nr_args: u32,
|
||||
) -> io::Result<()> {
|
||||
syscall_ret(c::syscall(
|
||||
__NR_io_uring_register as _,
|
||||
borrowed_fd(fd),
|
||||
opcode as u32 as usize,
|
||||
arg,
|
||||
nr_args as usize,
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn io_uring_enter(
|
||||
fd: BorrowedFd<'_>,
|
||||
to_submit: u32,
|
||||
min_complete: u32,
|
||||
flags: IoringEnterFlags,
|
||||
arg: *const c::c_void,
|
||||
size: usize,
|
||||
) -> io::Result<u32> {
|
||||
syscall_ret_u32(c::syscall(
|
||||
__NR_io_uring_enter as _,
|
||||
borrowed_fd(fd),
|
||||
to_submit as usize,
|
||||
min_complete as usize,
|
||||
flags.bits() as usize,
|
||||
arg,
|
||||
size,
|
||||
))
|
||||
}
|
||||
2
vendor/rustix/src/backend/libc/mm/mod.rs
vendored
Normal file
2
vendor/rustix/src/backend/libc/mm/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
218
vendor/rustix/src/backend/libc/mm/syscalls.rs
vendored
Normal file
218
vendor/rustix/src/backend/libc/mm/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
//! libc syscalls supporting `rustix::mm`.
|
||||
|
||||
use super::super::c;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use super::super::conv::syscall_ret_owned_fd;
|
||||
use super::super::conv::{borrowed_fd, no_fd, ret};
|
||||
use super::super::offset::libc_mmap;
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use super::types::Advice;
|
||||
#[cfg(target_os = "linux")]
|
||||
use super::types::MremapFlags;
|
||||
use super::types::{MapFlags, MprotectFlags, MsyncFlags, ProtFlags};
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use super::types::{MlockFlags, UserfaultfdFlags};
|
||||
use crate::fd::BorrowedFd;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use crate::fd::OwnedFd;
|
||||
use crate::io;
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub(crate) fn madvise(addr: *mut c::c_void, len: usize, advice: Advice) -> io::Result<()> {
|
||||
// On Linux platforms, `MADV_DONTNEED` has the same value as
|
||||
// `POSIX_MADV_DONTNEED` but different behavior. We remap it to a different
|
||||
// value, and check for it here.
|
||||
#[cfg(target_os = "linux")]
|
||||
if let Advice::LinuxDontNeed = advice {
|
||||
return unsafe { ret(c::madvise(addr, len, c::MADV_DONTNEED)) };
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
{
|
||||
let err = unsafe { c::posix_madvise(addr, len, advice as c::c_int) };
|
||||
|
||||
// `posix_madvise` returns its error status rather than using `errno`.
|
||||
if err == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Errno(err))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
{
|
||||
if let Advice::DontNeed = advice {
|
||||
// Do nothing. Linux's `MADV_DONTNEED` isn't the same as
|
||||
// `POSIX_MADV_DONTNEED`, so just discard `MADV_DONTNEED`.
|
||||
Ok(())
|
||||
} else {
|
||||
unsafe { ret(c::madvise(addr, len, advice as c::c_int)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn msync(addr: *mut c::c_void, len: usize, flags: MsyncFlags) -> io::Result<()> {
|
||||
let err = c::msync(addr, len, flags.bits());
|
||||
|
||||
// `msync` returns its error status rather than using `errno`.
|
||||
if err == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(io::Errno(err))
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `mmap` is primarily unsafe due to the `addr` parameter, as anything working
|
||||
/// with memory pointed to by raw pointers is unsafe.
|
||||
pub(crate) unsafe fn mmap(
|
||||
ptr: *mut c::c_void,
|
||||
len: usize,
|
||||
prot: ProtFlags,
|
||||
flags: MapFlags,
|
||||
fd: BorrowedFd<'_>,
|
||||
offset: u64,
|
||||
) -> io::Result<*mut c::c_void> {
|
||||
let res = libc_mmap(
|
||||
ptr,
|
||||
len,
|
||||
prot.bits(),
|
||||
flags.bits(),
|
||||
borrowed_fd(fd),
|
||||
offset as i64,
|
||||
);
|
||||
if res == c::MAP_FAILED {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `mmap` is primarily unsafe due to the `addr` parameter, as anything working
|
||||
/// with memory pointed to by raw pointers is unsafe.
|
||||
pub(crate) unsafe fn mmap_anonymous(
|
||||
ptr: *mut c::c_void,
|
||||
len: usize,
|
||||
prot: ProtFlags,
|
||||
flags: MapFlags,
|
||||
) -> io::Result<*mut c::c_void> {
|
||||
let res = libc_mmap(
|
||||
ptr,
|
||||
len,
|
||||
prot.bits(),
|
||||
flags.bits() | c::MAP_ANONYMOUS,
|
||||
no_fd(),
|
||||
0,
|
||||
);
|
||||
if res == c::MAP_FAILED {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn mprotect(
|
||||
ptr: *mut c::c_void,
|
||||
len: usize,
|
||||
flags: MprotectFlags,
|
||||
) -> io::Result<()> {
|
||||
ret(c::mprotect(ptr, len, flags.bits()))
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn munmap(ptr: *mut c::c_void, len: usize) -> io::Result<()> {
|
||||
ret(c::munmap(ptr, len))
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `mremap` is primarily unsafe due to the `old_address` parameter, as
|
||||
/// anything working with memory pointed to by raw pointers is unsafe.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) unsafe fn mremap(
|
||||
old_address: *mut c::c_void,
|
||||
old_size: usize,
|
||||
new_size: usize,
|
||||
flags: MremapFlags,
|
||||
) -> io::Result<*mut c::c_void> {
|
||||
let res = c::mremap(old_address, old_size, new_size, flags.bits());
|
||||
if res == c::MAP_FAILED {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `mremap_fixed` is primarily unsafe due to the `old_address` and
|
||||
/// `new_address` parameters, as anything working with memory pointed to by raw
|
||||
/// pointers is unsafe.
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) unsafe fn mremap_fixed(
|
||||
old_address: *mut c::c_void,
|
||||
old_size: usize,
|
||||
new_size: usize,
|
||||
flags: MremapFlags,
|
||||
new_address: *mut c::c_void,
|
||||
) -> io::Result<*mut c::c_void> {
|
||||
let res = c::mremap(
|
||||
old_address,
|
||||
old_size,
|
||||
new_size,
|
||||
flags.bits() | c::MAP_FIXED,
|
||||
new_address,
|
||||
);
|
||||
if res == c::MAP_FAILED {
|
||||
Err(io::Errno::last_os_error())
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `mlock` operates on raw pointers and may round out to the nearest page
|
||||
/// boundaries.
|
||||
#[inline]
|
||||
pub(crate) unsafe fn mlock(addr: *mut c::c_void, length: usize) -> io::Result<()> {
|
||||
ret(c::mlock(addr, length))
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `mlock_with` operates on raw pointers and may round out to the nearest page
|
||||
/// boundaries.
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) unsafe fn mlock_with(
|
||||
addr: *mut c::c_void,
|
||||
length: usize,
|
||||
flags: MlockFlags,
|
||||
) -> io::Result<()> {
|
||||
weak_or_syscall! {
|
||||
fn mlock2(
|
||||
addr: *const c::c_void,
|
||||
len: c::size_t,
|
||||
flags: c::c_int
|
||||
) via SYS_mlock2 -> c::c_int
|
||||
}
|
||||
|
||||
ret(mlock2(addr, length, flags.bits()))
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// `munlock` operates on raw pointers and may round out to the nearest page
|
||||
/// boundaries.
|
||||
#[inline]
|
||||
pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result<()> {
|
||||
ret(c::munlock(addr, length))
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> {
|
||||
syscall_ret_owned_fd(c::syscall(c::SYS_userfaultfd, flags.bits()))
|
||||
}
|
||||
428
vendor/rustix/src/backend/libc/mm/types.rs
vendored
Normal file
428
vendor/rustix/src/backend/libc/mm/types.rs
vendored
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
use super::super::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `PROT_*` flags for use with [`mmap`].
|
||||
///
|
||||
/// For `PROT_NONE`, use `ProtFlags::empty()`.
|
||||
///
|
||||
/// [`mmap`]: crate::io::mmap
|
||||
pub struct ProtFlags: c::c_int {
|
||||
/// `PROT_READ`
|
||||
const READ = c::PROT_READ;
|
||||
/// `PROT_WRITE`
|
||||
const WRITE = c::PROT_WRITE;
|
||||
/// `PROT_EXEC`
|
||||
const EXEC = c::PROT_EXEC;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `PROT_*` flags for use with [`mprotect`].
|
||||
///
|
||||
/// For `PROT_NONE`, use `MprotectFlags::empty()`.
|
||||
///
|
||||
/// [`mprotect`]: crate::io::mprotect
|
||||
pub struct MprotectFlags: c::c_int {
|
||||
/// `PROT_READ`
|
||||
const READ = c::PROT_READ;
|
||||
/// `PROT_WRITE`
|
||||
const WRITE = c::PROT_WRITE;
|
||||
/// `PROT_EXEC`
|
||||
const EXEC = c::PROT_EXEC;
|
||||
/// `PROT_GROWSUP`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
const GROWSUP = c::PROT_GROWSUP;
|
||||
/// `PROT_GROWSDOWN`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
const GROWSDOWN = c::PROT_GROWSDOWN;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `MAP_*` flags for use with [`mmap`].
|
||||
///
|
||||
/// For `MAP_ANONYMOUS` (aka `MAP_ANON`), see [`mmap_anonymous`].
|
||||
///
|
||||
/// [`mmap`]: crate::io::mmap
|
||||
/// [`mmap_anonymous`]: crates::io::mmap_anonymous
|
||||
pub struct MapFlags: c::c_int {
|
||||
/// `MAP_SHARED`
|
||||
const SHARED = c::MAP_SHARED;
|
||||
/// `MAP_SHARED_VALIDATE`
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const SHARED_VALIDATE = c::MAP_SHARED_VALIDATE;
|
||||
/// `MAP_PRIVATE`
|
||||
const PRIVATE = c::MAP_PRIVATE;
|
||||
/// `MAP_DENYWRITE`
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const DENYWRITE = c::MAP_DENYWRITE;
|
||||
/// `MAP_FIXED`
|
||||
const FIXED = c::MAP_FIXED;
|
||||
/// `MAP_FIXED_NOREPLACE`
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const FIXED_NOREPLACE = c::MAP_FIXED_NOREPLACE;
|
||||
/// `MAP_GROWSDOWN`
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const GROWSDOWN = c::MAP_GROWSDOWN;
|
||||
/// `MAP_HUGETLB`
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const HUGETLB = c::MAP_HUGETLB;
|
||||
/// `MAP_HUGE_2MB`
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const HUGE_2MB = c::MAP_HUGE_2MB;
|
||||
/// `MAP_HUGE_1GB`
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const HUGE_1GB = c::MAP_HUGE_1GB;
|
||||
/// `MAP_LOCKED`
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const LOCKED = c::MAP_LOCKED;
|
||||
/// `MAP_NOCORE`
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
|
||||
const NOCORE = c::MAP_NOCORE;
|
||||
/// `MAP_NORESERVE`
|
||||
#[cfg(not(any(target_os = "dragonfly", target_os = "freebsd", target_os = "redox")))]
|
||||
const NORESERVE = c::MAP_NORESERVE;
|
||||
/// `MAP_NOSYNC`
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
|
||||
const NOSYNC = c::MAP_NOSYNC;
|
||||
/// `MAP_POPULATE`
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const POPULATE = c::MAP_POPULATE;
|
||||
/// `MAP_STACK`
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const STACK = c::MAP_STACK;
|
||||
/// `MAP_PREFAULT_READ`
|
||||
#[cfg(target_os = "freebsd")]
|
||||
const PREFAULT_READ = c::MAP_PREFAULT_READ;
|
||||
/// `MAP_SYNC`
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
all(
|
||||
any(target_os = "android", target_os = "linux"),
|
||||
any(target_arch = "mips", target_arch = "mips64"),
|
||||
)
|
||||
)))]
|
||||
const SYNC = c::MAP_SYNC;
|
||||
/// `MAP_UNINITIALIZED`
|
||||
#[cfg(any())]
|
||||
const UNINITIALIZED = c::MAP_UNINITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
bitflags! {
|
||||
/// `MREMAP_*` flags for use with [`mremap`].
|
||||
///
|
||||
/// For `MREMAP_FIXED`, see [`mremap_fixed`].
|
||||
///
|
||||
/// [`mremap`]: crate::io::mremap
|
||||
/// [`mremap_fixed`]: crate::io::mremap_fixed
|
||||
pub struct MremapFlags: i32 {
|
||||
/// `MREMAP_MAYMOVE`
|
||||
const MAYMOVE = c::MREMAP_MAYMOVE;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `MS_*` flags for use with [`msync`].
|
||||
///
|
||||
/// [`msync`]: crate::io::msync
|
||||
pub struct MsyncFlags: i32 {
|
||||
/// `MS_SYNC`—Requests an update and waits for it to complete.
|
||||
const SYNC = c::MS_SYNC;
|
||||
/// `MS_ASYNC`—Specifies that an update be scheduled, but the call
|
||||
/// returns immediately.
|
||||
const ASYNC = c::MS_ASYNC;
|
||||
/// `MS_INVALIDATE`—Asks to invalidate other mappings of the same
|
||||
/// file (so that they can be updated with the fresh values just
|
||||
/// written).
|
||||
const INVALIDATE = c::MS_INVALIDATE;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
bitflags! {
|
||||
/// `MLOCK_*` flags for use with [`mlock_with`].
|
||||
///
|
||||
/// [`mlock_with`]: crate::io::mlock_with
|
||||
pub struct MlockFlags: i32 {
|
||||
/// `MLOCK_ONFAULT`
|
||||
const ONFAULT = c::MLOCK_ONFAULT as _;
|
||||
}
|
||||
}
|
||||
|
||||
/// `POSIX_MADV_*` constants for use with [`madvise`].
|
||||
///
|
||||
/// [`madvise`]: crate::mm::madvise
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
#[non_exhaustive]
|
||||
pub enum Advice {
|
||||
/// `POSIX_MADV_NORMAL`
|
||||
#[cfg(not(any(target_os = "android", target_os = "haiku")))]
|
||||
Normal = c::POSIX_MADV_NORMAL,
|
||||
|
||||
/// `POSIX_MADV_NORMAL`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
Normal = c::MADV_NORMAL,
|
||||
|
||||
/// `POSIX_MADV_SEQUENTIAL`
|
||||
#[cfg(not(any(target_os = "android", target_os = "haiku")))]
|
||||
Sequential = c::POSIX_MADV_SEQUENTIAL,
|
||||
|
||||
/// `POSIX_MADV_SEQUENTIAL`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
Sequential = c::MADV_SEQUENTIAL,
|
||||
|
||||
/// `POSIX_MADV_RANDOM`
|
||||
#[cfg(not(any(target_os = "android", target_os = "haiku")))]
|
||||
Random = c::POSIX_MADV_RANDOM,
|
||||
|
||||
/// `POSIX_MADV_RANDOM`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
Random = c::MADV_RANDOM,
|
||||
|
||||
/// `POSIX_MADV_WILLNEED`
|
||||
#[cfg(not(any(target_os = "android", target_os = "haiku")))]
|
||||
WillNeed = c::POSIX_MADV_WILLNEED,
|
||||
|
||||
/// `POSIX_MADV_WILLNEED`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
WillNeed = c::MADV_WILLNEED,
|
||||
|
||||
/// `POSIX_MADV_DONTNEED`
|
||||
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "haiku")))]
|
||||
DontNeed = c::POSIX_MADV_DONTNEED,
|
||||
|
||||
/// `POSIX_MADV_DONTNEED`
|
||||
#[cfg(any(target_os = "android", target_os = "haiku"))]
|
||||
DontNeed = i32::MAX - 1,
|
||||
|
||||
/// `MADV_DONTNEED`
|
||||
// `MADV_DONTNEED` has the same value as `POSIX_MADV_DONTNEED`. We don't
|
||||
// have a separate `posix_madvise` from `madvise`, so we expose a special
|
||||
// value which we special-case.
|
||||
#[cfg(target_os = "linux")]
|
||||
LinuxDontNeed = i32::MAX,
|
||||
|
||||
/// `MADV_DONTNEED`
|
||||
#[cfg(target_os = "android")]
|
||||
LinuxDontNeed = c::MADV_DONTNEED,
|
||||
/// `MADV_FREE`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxFree = c::MADV_FREE,
|
||||
/// `MADV_REMOVE`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxRemove = c::MADV_REMOVE,
|
||||
/// `MADV_DONTFORK`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxDontFork = c::MADV_DONTFORK,
|
||||
/// `MADV_DOFORK`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxDoFork = c::MADV_DOFORK,
|
||||
/// `MADV_HWPOISON`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxHwPoison = c::MADV_HWPOISON,
|
||||
/// `MADV_SOFT_OFFLINE`
|
||||
#[cfg(all(
|
||||
any(target_os = "android", target_os = "linux"),
|
||||
not(any(target_arch = "mips", target_arch = "mips64")),
|
||||
))]
|
||||
LinuxSoftOffline = c::MADV_SOFT_OFFLINE,
|
||||
/// `MADV_MERGEABLE`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxMergeable = c::MADV_MERGEABLE,
|
||||
/// `MADV_UNMERGEABLE`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxUnmergeable = c::MADV_UNMERGEABLE,
|
||||
/// `MADV_HUGEPAGE` (since Linux 2.6.38)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxHugepage = c::MADV_HUGEPAGE,
|
||||
/// `MADV_NOHUGEPAGE` (since Linux 2.6.38)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxNoHugepage = c::MADV_NOHUGEPAGE,
|
||||
/// `MADV_DONTDUMP` (since Linux 3.4)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxDontDump = c::MADV_DONTDUMP,
|
||||
/// `MADV_DODUMP` (since Linux 3.4)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
LinuxDoDump = c::MADV_DODUMP,
|
||||
/// `MADV_WIPEONFORK` (since Linux 4.14)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[cfg(feature = "mm")]
|
||||
LinuxWipeOnFork = linux_raw_sys::general::MADV_WIPEONFORK as i32,
|
||||
/// `MADV_KEEPONFORK` (since Linux 4.14)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[cfg(feature = "mm")]
|
||||
LinuxKeepOnFork = linux_raw_sys::general::MADV_KEEPONFORK as i32,
|
||||
/// `MADV_COLD` (since Linux 5.4)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[cfg(feature = "mm")]
|
||||
LinuxCold = linux_raw_sys::general::MADV_COLD as i32,
|
||||
/// `MADV_PAGEOUT` (since Linux 5.4)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[cfg(feature = "mm")]
|
||||
LinuxPageOut = linux_raw_sys::general::MADV_PAGEOUT as i32,
|
||||
/// `MADV_POPULATE_READ` (since Linux 5.14)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[cfg(feature = "mm")]
|
||||
LinuxPopulateRead = linux_raw_sys::general::MADV_POPULATE_READ as i32,
|
||||
/// `MADV_POPULATE_WRITE` (since Linux 5.14)
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[cfg(feature = "mm")]
|
||||
LinuxPopulateWrite = linux_raw_sys::general::MADV_POPULATE_WRITE as i32,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "emscripten")]
|
||||
impl Advice {
|
||||
/// `POSIX_MADV_DONTNEED`
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const DontNeed: Self = Self::Normal;
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
bitflags! {
|
||||
/// `O_*` flags for use with [`userfaultfd`].
|
||||
///
|
||||
/// [`userfaultfd`]: crate::io::userfaultfd
|
||||
pub struct UserfaultfdFlags: c::c_int {
|
||||
/// `O_CLOEXEC`
|
||||
const CLOEXEC = c::O_CLOEXEC;
|
||||
/// `O_NONBLOCK`
|
||||
const NONBLOCK = c::O_NONBLOCK;
|
||||
}
|
||||
}
|
||||
110
vendor/rustix/src/backend/libc/mod.rs
vendored
Normal file
110
vendor/rustix/src/backend/libc/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
//! The libc backend.
|
||||
//!
|
||||
//! On most platforms, this uses the `libc` crate to make system calls. On
|
||||
//! Windows, this uses the Winsock2 API in `windows-sys`, which can be adapted
|
||||
//! to have a very `libc`-like interface.
|
||||
|
||||
// Every FFI call requires an unsafe block, and there are a lot of FFI
|
||||
// calls. For now, set this to allow for the libc backend.
|
||||
#![allow(clippy::undocumented_unsafe_blocks)]
|
||||
// Lots of libc types vary between platforms, so we often need a `.into()` on
|
||||
// one platform where it's redundant on another.
|
||||
#![allow(clippy::useless_conversion)]
|
||||
|
||||
#[cfg(not(any(windows, target_os = "wasi")))]
|
||||
#[macro_use]
|
||||
mod weak;
|
||||
|
||||
mod conv;
|
||||
mod offset;
|
||||
|
||||
#[cfg(windows)]
|
||||
mod io_lifetimes;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) mod fd {
|
||||
pub(crate) use super::c::c_int as LibcFd;
|
||||
pub use crate::io::fd::*;
|
||||
}
|
||||
#[cfg(windows)]
|
||||
pub(crate) mod fd {
|
||||
pub use super::io_lifetimes::*;
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) mod fd {
|
||||
pub use io_lifetimes::*;
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use super::c::c_int as LibcFd;
|
||||
#[cfg(unix)]
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use std::os::unix::io::RawFd as LibcFd;
|
||||
#[cfg(unix)]
|
||||
pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(target_os = "wasi")]
|
||||
pub use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
}
|
||||
|
||||
// On Windows we emulate selected libc-compatible interfaces. On non-Windows,
|
||||
// we just use libc here, since this is the libc backend.
|
||||
#[cfg(windows)]
|
||||
#[path = "winsock_c.rs"]
|
||||
pub(crate) mod c;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) use libc as c;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(crate) mod fs;
|
||||
pub(crate) mod io;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[cfg(feature = "io_uring")]
|
||||
pub(crate) mod io_uring;
|
||||
#[cfg(not(any(windows, target_os = "wasi")))]
|
||||
#[cfg(feature = "mm")]
|
||||
pub(crate) mod mm;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
#[cfg(feature = "net")]
|
||||
pub(crate) mod net;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(any(
|
||||
feature = "param",
|
||||
feature = "runtime",
|
||||
feature = "time",
|
||||
target_arch = "x86",
|
||||
))]
|
||||
pub(crate) mod param;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod process;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "rand")]
|
||||
pub(crate) mod rand;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "termios")]
|
||||
pub(crate) mod termios;
|
||||
#[cfg(not(windows))]
|
||||
#[cfg(feature = "thread")]
|
||||
pub(crate) mod thread;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod time;
|
||||
|
||||
/// If the host libc is glibc, return `true` if it is less than version 2.25.
|
||||
///
|
||||
/// To restate and clarify, this function returning true does not mean the libc
|
||||
/// is glibc just that if it is glibc, it is less than version 2.25.
|
||||
///
|
||||
/// For now, this function is only available on Linux, but if it ends up being
|
||||
/// used beyond that, this could be changed to e.g. `#[cfg(unix)]`.
|
||||
#[cfg(all(unix, target_env = "gnu"))]
|
||||
pub(crate) fn if_glibc_is_less_than_2_25() -> bool {
|
||||
// This is also defined inside `weak_or_syscall!` in
|
||||
// backend/libc/rand/syscalls.rs, but it's not convenient to re-export the weak
|
||||
// symbol from that macro, so we duplicate it at a small cost here.
|
||||
weak! { fn getrandom(*mut c::c_void, c::size_t, c::c_uint) -> c::ssize_t }
|
||||
|
||||
// glibc 2.25 has `getrandom`, which is how we satisfy the API contract of
|
||||
// this function. But, there are likely other libc versions which have it.
|
||||
getrandom.get().is_none()
|
||||
}
|
||||
330
vendor/rustix/src/backend/libc/net/addr.rs
vendored
Normal file
330
vendor/rustix/src/backend/libc/net/addr.rs
vendored
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
//! IPv4, IPv6, and Socket addresses.
|
||||
|
||||
use super::super::c;
|
||||
#[cfg(unix)]
|
||||
use crate::ffi::CStr;
|
||||
#[cfg(unix)]
|
||||
use crate::io;
|
||||
#[cfg(unix)]
|
||||
use crate::path;
|
||||
#[cfg(not(windows))]
|
||||
use core::convert::TryInto;
|
||||
#[cfg(unix)]
|
||||
use core::fmt;
|
||||
#[cfg(unix)]
|
||||
use core::slice;
|
||||
|
||||
/// `struct sockaddr_un`
|
||||
#[cfg(unix)]
|
||||
#[derive(Clone)]
|
||||
#[doc(alias = "sockaddr_un")]
|
||||
pub struct SocketAddrUnix {
|
||||
pub(crate) unix: c::sockaddr_un,
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
len: c::socklen_t,
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl SocketAddrUnix {
|
||||
/// Construct a new Unix-domain address from a filesystem path.
|
||||
#[inline]
|
||||
pub fn new<P: path::Arg>(path: P) -> io::Result<Self> {
|
||||
path.into_with_c_str(Self::_new)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn _new(path: &CStr) -> io::Result<Self> {
|
||||
let mut unix = Self::init();
|
||||
let bytes = path.to_bytes_with_nul();
|
||||
if bytes.len() > unix.sun_path.len() {
|
||||
return Err(io::Errno::NAMETOOLONG);
|
||||
}
|
||||
for (i, b) in bytes.iter().enumerate() {
|
||||
unix.sun_path[i] = *b as c::c_char;
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
{
|
||||
unix.sun_len = (offsetof_sun_path() + bytes.len()).try_into().unwrap();
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
unix,
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
len: (offsetof_sun_path() + bytes.len()).try_into().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Construct a new abstract Unix-domain address from a byte slice.
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub fn new_abstract_name(name: &[u8]) -> io::Result<Self> {
|
||||
let mut unix = Self::init();
|
||||
if 1 + name.len() > unix.sun_path.len() {
|
||||
return Err(io::Errno::NAMETOOLONG);
|
||||
}
|
||||
unix.sun_path[0] = b'\0' as c::c_char;
|
||||
for (i, b) in name.iter().enumerate() {
|
||||
unix.sun_path[1 + i] = *b as c::c_char;
|
||||
}
|
||||
let len = offsetof_sun_path() + 1 + name.len();
|
||||
let len = len.try_into().unwrap();
|
||||
Ok(Self {
|
||||
unix,
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
len,
|
||||
})
|
||||
}
|
||||
|
||||
fn init() -> c::sockaddr_un {
|
||||
c::sockaddr_un {
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sun_len: 0,
|
||||
sun_family: c::AF_UNIX as _,
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sun_path: [0; 104],
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
sun_path: [0; 108],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sun_path: [0; 126],
|
||||
}
|
||||
}
|
||||
|
||||
/// For a filesystem path address, return the path.
|
||||
#[inline]
|
||||
pub fn path(&self) -> Option<&CStr> {
|
||||
let len = self.len();
|
||||
if len != 0 && self.unix.sun_path[0] != b'\0' as c::c_char {
|
||||
let end = len as usize - offsetof_sun_path();
|
||||
let bytes = &self.unix.sun_path[..end];
|
||||
// Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`. And
|
||||
// `from_bytes_with_nul_unchecked` since the string is NUL-terminated.
|
||||
unsafe {
|
||||
Some(CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
|
||||
bytes.as_ptr().cast(),
|
||||
bytes.len(),
|
||||
)))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// For an abstract address, return the identifier.
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub fn abstract_name(&self) -> Option<&[u8]> {
|
||||
let len = self.len();
|
||||
if len != 0 && self.unix.sun_path[0] == b'\0' as c::c_char {
|
||||
let end = len as usize - offsetof_sun_path();
|
||||
let bytes = &self.unix.sun_path[1..end];
|
||||
// Safety: `from_raw_parts` to convert from `&[c_char]` to `&[u8]`.
|
||||
unsafe { Some(slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len())) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn addr_len(&self) -> c::socklen_t {
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
{
|
||||
self.len
|
||||
}
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
{
|
||||
c::socklen_t::from(self.unix.sun_len)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn len(&self) -> usize {
|
||||
self.addr_len() as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl PartialEq for SocketAddrUnix {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let self_len = self.len() - offsetof_sun_path();
|
||||
let other_len = other.len() - offsetof_sun_path();
|
||||
self.unix.sun_path[..self_len].eq(&other.unix.sun_path[..other_len])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl Eq for SocketAddrUnix {}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl PartialOrd for SocketAddrUnix {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
|
||||
let self_len = self.len() - offsetof_sun_path();
|
||||
let other_len = other.len() - offsetof_sun_path();
|
||||
self.unix.sun_path[..self_len].partial_cmp(&other.unix.sun_path[..other_len])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl Ord for SocketAddrUnix {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
|
||||
let self_len = self.len() - offsetof_sun_path();
|
||||
let other_len = other.len() - offsetof_sun_path();
|
||||
self.unix.sun_path[..self_len].cmp(&other.unix.sun_path[..other_len])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl core::hash::Hash for SocketAddrUnix {
|
||||
#[inline]
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
let self_len = self.len() - offsetof_sun_path();
|
||||
self.unix.sun_path[..self_len].hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl fmt::Debug for SocketAddrUnix {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if let Some(path) = self.path() {
|
||||
path.fmt(fmt)
|
||||
} else {
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
if let Some(name) = self.abstract_name() {
|
||||
return name.fmt(fmt);
|
||||
}
|
||||
|
||||
"(unnamed)".fmt(fmt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `struct sockaddr_storage` as a raw struct.
|
||||
pub type SocketAddrStorage = c::sockaddr_storage;
|
||||
|
||||
/// Return the offset of the `sun_path` field of `sockaddr_un`.
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) fn offsetof_sun_path() -> usize {
|
||||
let z = c::sockaddr_un {
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sun_len: 0_u8,
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sun_family: 0_u8,
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
sun_family: 0_u16,
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sun_path: [0; 104],
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
sun_path: [0; 108],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sun_path: [0; 126],
|
||||
};
|
||||
(crate::utils::as_ptr(&z.sun_path) as usize) - (crate::utils::as_ptr(&z) as usize)
|
||||
}
|
||||
210
vendor/rustix/src/backend/libc/net/ext.rs
vendored
Normal file
210
vendor/rustix/src/backend/libc/net/ext.rs
vendored
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
use super::super::c;
|
||||
|
||||
/// The windows `sockaddr_in6` type is a union with accessor functions which
|
||||
/// are not `const fn`. Define our own layout-compatible version so that we
|
||||
/// can transmute in and out of it.
|
||||
#[cfg(windows)]
|
||||
#[repr(C)]
|
||||
struct sockaddr_in6 {
|
||||
sin6_family: u16,
|
||||
sin6_port: u16,
|
||||
sin6_flowinfo: u32,
|
||||
sin6_addr: c::in6_addr,
|
||||
sin6_scope_id: u32,
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 {
|
||||
addr.s_addr
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 {
|
||||
// This should be `*addr.S_un.S_addr()`, except that isn't a `const fn`.
|
||||
unsafe { core::mem::transmute(addr) }
|
||||
}
|
||||
|
||||
// TODO: With Rust 1.55, we can use the above `in_addr_s_addr` definition that
|
||||
// uses a const-fn transmute.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) fn in_addr_s_addr(addr: c::in_addr) -> u32 {
|
||||
// This should be `*addr.S_un.S_addr()`, except that isn't a `const fn`.
|
||||
unsafe { core::mem::transmute(addr) }
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr {
|
||||
c::in_addr { s_addr }
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr {
|
||||
unsafe { core::mem::transmute(s_addr) }
|
||||
}
|
||||
|
||||
// TODO: With Rust 1.55, we can use the above `in_addr_new` definition that
|
||||
// uses a const-fn transmute.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) fn in_addr_new(s_addr: u32) -> c::in_addr {
|
||||
unsafe { core::mem::transmute(s_addr) }
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
|
||||
addr.s6_addr
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
|
||||
unsafe { core::mem::transmute(addr) }
|
||||
}
|
||||
|
||||
// TODO: With Rust 1.55, we can use the above `in6_addr_s6_addr` definition
|
||||
// that uses a const-fn transmute.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
|
||||
unsafe { core::mem::transmute(addr) }
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
|
||||
c::in6_addr { s6_addr }
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
|
||||
unsafe { core::mem::transmute(s6_addr) }
|
||||
}
|
||||
|
||||
// TODO: With Rust 1.55, we can use the above `in6_addr_new` definition that
|
||||
// uses a const-fn transmute.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
|
||||
unsafe { core::mem::transmute(s6_addr) }
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
|
||||
addr.sin6_scope_id
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
|
||||
let addr: sockaddr_in6 = unsafe { core::mem::transmute(addr) };
|
||||
addr.sin6_scope_id
|
||||
}
|
||||
|
||||
// TODO: With Rust 1.55, we can use the above `sockaddr_in6_sin6_scope_id`
|
||||
// definition that uses a const-fn transmute.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
|
||||
let addr: sockaddr_in6 = unsafe { core::mem::transmute(addr) };
|
||||
addr.sin6_scope_id
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) const fn sockaddr_in6_new(
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sin6_len: u8,
|
||||
sin6_family: c::sa_family_t,
|
||||
sin6_port: u16,
|
||||
sin6_flowinfo: u32,
|
||||
sin6_addr: c::in6_addr,
|
||||
sin6_scope_id: u32,
|
||||
) -> c::sockaddr_in6 {
|
||||
c::sockaddr_in6 {
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sin6_len,
|
||||
sin6_family,
|
||||
sin6_port,
|
||||
sin6_flowinfo,
|
||||
sin6_addr,
|
||||
sin6_scope_id,
|
||||
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
|
||||
__sin6_src_id: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) const fn sockaddr_in6_new(
|
||||
sin6_family: u16,
|
||||
sin6_port: u16,
|
||||
sin6_flowinfo: u32,
|
||||
sin6_addr: c::in6_addr,
|
||||
sin6_scope_id: u32,
|
||||
) -> c::sockaddr_in6 {
|
||||
let addr = sockaddr_in6 {
|
||||
sin6_family,
|
||||
sin6_port,
|
||||
sin6_flowinfo,
|
||||
sin6_addr,
|
||||
sin6_scope_id,
|
||||
};
|
||||
unsafe { core::mem::transmute(addr) }
|
||||
}
|
||||
|
||||
// TODO: With Rust 1.55, we can use the above `sockaddr_in6_new` definition
|
||||
// that uses a const-fn transmute.
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) fn sockaddr_in6_new(
|
||||
sin6_family: u16,
|
||||
sin6_port: u16,
|
||||
sin6_flowinfo: u32,
|
||||
sin6_addr: c::in6_addr,
|
||||
sin6_scope_id: u32,
|
||||
) -> c::sockaddr_in6 {
|
||||
let addr = sockaddr_in6 {
|
||||
sin6_family,
|
||||
sin6_port,
|
||||
sin6_flowinfo,
|
||||
sin6_addr,
|
||||
sin6_scope_id,
|
||||
};
|
||||
unsafe { core::mem::transmute(addr) }
|
||||
}
|
||||
7
vendor/rustix/src/backend/libc/net/mod.rs
vendored
Normal file
7
vendor/rustix/src/backend/libc/net/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
pub(crate) mod addr;
|
||||
pub(crate) mod ext;
|
||||
pub(crate) mod read_sockaddr;
|
||||
pub(crate) mod send_recv;
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
pub(crate) mod write_sockaddr;
|
||||
255
vendor/rustix/src/backend/libc/net/read_sockaddr.rs
vendored
Normal file
255
vendor/rustix/src/backend/libc/net/read_sockaddr.rs
vendored
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
use super::super::c;
|
||||
#[cfg(unix)]
|
||||
use super::addr::SocketAddrUnix;
|
||||
use super::ext::{in6_addr_s6_addr, in_addr_s_addr, sockaddr_in6_sin6_scope_id};
|
||||
#[cfg(not(windows))]
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddrAny, SocketAddrV4, SocketAddrV6};
|
||||
#[cfg(not(windows))]
|
||||
use alloc::vec::Vec;
|
||||
use core::mem::size_of;
|
||||
|
||||
// This must match the header of `sockaddr`.
|
||||
#[repr(C)]
|
||||
struct sockaddr_header {
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sa_len: u8,
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
ss_family: u8,
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
ss_family: u16,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn read_ss_family(storage: *const c::sockaddr_storage) -> u16 {
|
||||
// Assert that we know the layout of `sockaddr`.
|
||||
let _ = c::sockaddr {
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sa_len: 0_u8,
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sa_family: 0_u8,
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
sa_family: 0_u16,
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
sa_data: [0; 14],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sa_data: [0; 30],
|
||||
};
|
||||
|
||||
(*storage.cast::<sockaddr_header>()).ss_family.into()
|
||||
}
|
||||
|
||||
/// Set the `ss_family` field of a socket address to `AF_UNSPEC`, so that we
|
||||
/// can test for `AF_UNSPEC` to test whether it was stored to.
|
||||
pub(crate) unsafe fn initialize_family_to_unspec(storage: *mut c::sockaddr_storage) {
|
||||
(*storage.cast::<sockaddr_header>()).ss_family = c::AF_UNSPEC as _;
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn read_sockaddr(
|
||||
storage: *const c::sockaddr_storage,
|
||||
len: usize,
|
||||
) -> io::Result<SocketAddrAny> {
|
||||
#[cfg(unix)]
|
||||
let offsetof_sun_path = super::addr::offsetof_sun_path();
|
||||
|
||||
if len < size_of::<c::sa_family_t>() {
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
match read_ss_family(storage).into() {
|
||||
c::AF_INET => {
|
||||
if len < size_of::<c::sockaddr_in>() {
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
let decode = *storage.cast::<c::sockaddr_in>();
|
||||
Ok(SocketAddrAny::V4(SocketAddrV4::new(
|
||||
Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))),
|
||||
u16::from_be(decode.sin_port),
|
||||
)))
|
||||
}
|
||||
c::AF_INET6 => {
|
||||
if len < size_of::<c::sockaddr_in6>() {
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
let decode = *storage.cast::<c::sockaddr_in6>();
|
||||
#[cfg(not(windows))]
|
||||
let s6_addr = decode.sin6_addr.s6_addr;
|
||||
#[cfg(windows)]
|
||||
let s6_addr = decode.sin6_addr.u.Byte;
|
||||
#[cfg(not(windows))]
|
||||
let sin6_scope_id = decode.sin6_scope_id;
|
||||
#[cfg(windows)]
|
||||
let sin6_scope_id = decode.Anonymous.sin6_scope_id;
|
||||
Ok(SocketAddrAny::V6(SocketAddrV6::new(
|
||||
Ipv6Addr::from(s6_addr),
|
||||
u16::from_be(decode.sin6_port),
|
||||
u32::from_be(decode.sin6_flowinfo),
|
||||
sin6_scope_id,
|
||||
)))
|
||||
}
|
||||
#[cfg(unix)]
|
||||
c::AF_UNIX => {
|
||||
if len < offsetof_sun_path {
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
if len == offsetof_sun_path {
|
||||
Ok(SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap()))
|
||||
} else {
|
||||
let decode = *storage.cast::<c::sockaddr_un>();
|
||||
|
||||
// Trim off unused bytes from the end of `path_bytes`.
|
||||
let path_bytes = if cfg!(target_os = "freebsd") {
|
||||
// FreeBSD sometimes sets the length to longer than the length
|
||||
// of the NUL-terminated string. Find the NUL and truncate the
|
||||
// string accordingly.
|
||||
&decode.sun_path[..decode.sun_path.iter().position(|b| *b == 0).unwrap()]
|
||||
} else {
|
||||
// Otherwise, use the provided length.
|
||||
let provided_len = len - 1 - offsetof_sun_path;
|
||||
if decode.sun_path[provided_len] != b'\0' as c::c_char {
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
debug_assert_eq!(
|
||||
CStr::from_ptr(decode.sun_path.as_ptr()).to_bytes().len(),
|
||||
provided_len
|
||||
);
|
||||
&decode.sun_path[..provided_len]
|
||||
};
|
||||
|
||||
Ok(SocketAddrAny::Unix(
|
||||
SocketAddrUnix::new(path_bytes.iter().map(|c| *c as u8).collect::<Vec<u8>>())
|
||||
.unwrap(),
|
||||
))
|
||||
}
|
||||
}
|
||||
_ => Err(io::Errno::INVAL),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn maybe_read_sockaddr_os(
|
||||
storage: *const c::sockaddr_storage,
|
||||
len: usize,
|
||||
) -> Option<SocketAddrAny> {
|
||||
if len == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
assert!(len >= size_of::<c::sa_family_t>());
|
||||
let family = read_ss_family(storage).into();
|
||||
if family == c::AF_UNSPEC {
|
||||
None
|
||||
} else {
|
||||
Some(inner_read_sockaddr_os(family, storage, len))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn read_sockaddr_os(
|
||||
storage: *const c::sockaddr_storage,
|
||||
len: usize,
|
||||
) -> SocketAddrAny {
|
||||
assert!(len >= size_of::<c::sa_family_t>());
|
||||
let family = read_ss_family(storage).into();
|
||||
inner_read_sockaddr_os(family, storage, len)
|
||||
}
|
||||
|
||||
unsafe fn inner_read_sockaddr_os(
|
||||
family: c::c_int,
|
||||
storage: *const c::sockaddr_storage,
|
||||
len: usize,
|
||||
) -> SocketAddrAny {
|
||||
#[cfg(unix)]
|
||||
let offsetof_sun_path = super::addr::offsetof_sun_path();
|
||||
|
||||
assert!(len >= size_of::<c::sa_family_t>());
|
||||
match family {
|
||||
c::AF_INET => {
|
||||
assert!(len >= size_of::<c::sockaddr_in>());
|
||||
let decode = *storage.cast::<c::sockaddr_in>();
|
||||
SocketAddrAny::V4(SocketAddrV4::new(
|
||||
Ipv4Addr::from(u32::from_be(in_addr_s_addr(decode.sin_addr))),
|
||||
u16::from_be(decode.sin_port),
|
||||
))
|
||||
}
|
||||
c::AF_INET6 => {
|
||||
assert!(len >= size_of::<c::sockaddr_in6>());
|
||||
let decode = *storage.cast::<c::sockaddr_in6>();
|
||||
SocketAddrAny::V6(SocketAddrV6::new(
|
||||
Ipv6Addr::from(in6_addr_s6_addr(decode.sin6_addr)),
|
||||
u16::from_be(decode.sin6_port),
|
||||
u32::from_be(decode.sin6_flowinfo),
|
||||
sockaddr_in6_sin6_scope_id(decode),
|
||||
))
|
||||
}
|
||||
#[cfg(unix)]
|
||||
c::AF_UNIX => {
|
||||
assert!(len >= offsetof_sun_path);
|
||||
if len == offsetof_sun_path {
|
||||
SocketAddrAny::Unix(SocketAddrUnix::new(&[][..]).unwrap())
|
||||
} else {
|
||||
let decode = *storage.cast::<c::sockaddr_un>();
|
||||
assert_eq!(
|
||||
decode.sun_path[len - 1 - offsetof_sun_path],
|
||||
b'\0' as c::c_char
|
||||
);
|
||||
let path_bytes = &decode.sun_path[..len - 1 - offsetof_sun_path];
|
||||
|
||||
// FreeBSD sometimes sets the length to longer than the length
|
||||
// of the NUL-terminated string. Find the NUL and truncate the
|
||||
// string accordingly.
|
||||
#[cfg(target_os = "freebsd")]
|
||||
let path_bytes = &path_bytes[..path_bytes.iter().position(|b| *b == 0).unwrap()];
|
||||
|
||||
SocketAddrAny::Unix(
|
||||
SocketAddrUnix::new(path_bytes.iter().map(|c| *c as u8).collect::<Vec<u8>>())
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
other => unimplemented!("{:?}", other),
|
||||
}
|
||||
}
|
||||
83
vendor/rustix/src/backend/libc/net/send_recv.rs
vendored
Normal file
83
vendor/rustix/src/backend/libc/net/send_recv.rs
vendored
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
use super::super::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `MSG_*`
|
||||
pub struct SendFlags: i32 {
|
||||
/// `MSG_CONFIRM`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const CONFIRM = c::MSG_CONFIRM;
|
||||
/// `MSG_DONTROUTE`
|
||||
const DONTROUTE = c::MSG_DONTROUTE;
|
||||
/// `MSG_DONTWAIT`
|
||||
#[cfg(not(windows))]
|
||||
const DONTWAIT = c::MSG_DONTWAIT;
|
||||
/// `MSG_EOR`
|
||||
#[cfg(not(windows))]
|
||||
const EOT = c::MSG_EOR;
|
||||
/// `MSG_MORE`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const MORE = c::MSG_MORE;
|
||||
#[cfg(not(any(windows, target_os = "ios", target_os = "macos")))]
|
||||
/// `MSG_NOSIGNAL`
|
||||
const NOSIGNAL = c::MSG_NOSIGNAL;
|
||||
/// `MSG_OOB`
|
||||
const OOB = c::MSG_OOB;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `MSG_*`
|
||||
pub struct RecvFlags: i32 {
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "illumos", target_os = "ios", target_os = "macos", target_os = "solaris")))]
|
||||
/// `MSG_CMSG_CLOEXEC`
|
||||
const CMSG_CLOEXEC = c::MSG_CMSG_CLOEXEC;
|
||||
/// `MSG_DONTWAIT`
|
||||
#[cfg(not(windows))]
|
||||
const DONTWAIT = c::MSG_DONTWAIT;
|
||||
/// `MSG_ERRQUEUE`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
const ERRQUEUE = c::MSG_ERRQUEUE;
|
||||
/// `MSG_OOB`
|
||||
const OOB = c::MSG_OOB;
|
||||
/// `MSG_PEEK`
|
||||
const PEEK = c::MSG_PEEK;
|
||||
/// `MSG_TRUNC`
|
||||
const TRUNC = c::MSG_TRUNC as c::c_int;
|
||||
/// `MSG_WAITALL`
|
||||
const WAITALL = c::MSG_WAITALL;
|
||||
}
|
||||
}
|
||||
886
vendor/rustix/src/backend/libc/net/syscalls.rs
vendored
Normal file
886
vendor/rustix/src/backend/libc/net/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,886 @@
|
|||
//! libc syscalls supporting `rustix::net`.
|
||||
|
||||
use super::super::c;
|
||||
use super::super::conv::{borrowed_fd, ret, ret_owned_fd, ret_send_recv, send_recv_len};
|
||||
#[cfg(unix)]
|
||||
use super::addr::SocketAddrUnix;
|
||||
use super::ext::{in6_addr_new, in_addr_new};
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
use super::read_sockaddr::initialize_family_to_unspec;
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
use super::read_sockaddr::{maybe_read_sockaddr_os, read_sockaddr_os};
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
use super::send_recv::{RecvFlags, SendFlags};
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
use super::types::{AcceptFlags, AddressFamily, Protocol, Shutdown, SocketFlags, SocketType};
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
use super::write_sockaddr::{encode_sockaddr_v4, encode_sockaddr_v6};
|
||||
use crate::fd::{BorrowedFd, OwnedFd};
|
||||
use crate::io;
|
||||
use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6};
|
||||
use crate::utils::as_ptr;
|
||||
use core::convert::TryInto;
|
||||
use core::mem::{size_of, MaybeUninit};
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
use core::ptr::null_mut;
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn recv(fd: BorrowedFd<'_>, buf: &mut [u8], flags: RecvFlags) -> io::Result<usize> {
|
||||
let nrecv = unsafe {
|
||||
ret_send_recv(c::recv(
|
||||
borrowed_fd(fd),
|
||||
buf.as_mut_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
flags.bits(),
|
||||
))?
|
||||
};
|
||||
Ok(nrecv as usize)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn send(fd: BorrowedFd<'_>, buf: &[u8], flags: SendFlags) -> io::Result<usize> {
|
||||
let nwritten = unsafe {
|
||||
ret_send_recv(c::send(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
flags.bits(),
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn recvfrom(
|
||||
fd: BorrowedFd<'_>,
|
||||
buf: &mut [u8],
|
||||
flags: RecvFlags,
|
||||
) -> io::Result<(usize, Option<SocketAddrAny>)> {
|
||||
unsafe {
|
||||
let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
|
||||
let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
|
||||
|
||||
// `recvfrom` does not write to the storage if the socket is
|
||||
// connection-oriented sockets, so we initialize the family field to
|
||||
// `AF_UNSPEC` so that we can detect this case.
|
||||
initialize_family_to_unspec(storage.as_mut_ptr());
|
||||
|
||||
let nread = ret_send_recv(c::recvfrom(
|
||||
borrowed_fd(fd),
|
||||
buf.as_mut_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
flags.bits(),
|
||||
storage.as_mut_ptr().cast(),
|
||||
&mut len,
|
||||
))?;
|
||||
Ok((
|
||||
nread as usize,
|
||||
maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn sendto_v4(
|
||||
fd: BorrowedFd<'_>,
|
||||
buf: &[u8],
|
||||
flags: SendFlags,
|
||||
addr: &SocketAddrV4,
|
||||
) -> io::Result<usize> {
|
||||
let nwritten = unsafe {
|
||||
ret_send_recv(c::sendto(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
flags.bits(),
|
||||
as_ptr(&encode_sockaddr_v4(addr)).cast::<c::sockaddr>(),
|
||||
size_of::<SocketAddrV4>() as _,
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn sendto_v6(
|
||||
fd: BorrowedFd<'_>,
|
||||
buf: &[u8],
|
||||
flags: SendFlags,
|
||||
addr: &SocketAddrV6,
|
||||
) -> io::Result<usize> {
|
||||
let nwritten = unsafe {
|
||||
ret_send_recv(c::sendto(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
flags.bits(),
|
||||
as_ptr(&encode_sockaddr_v6(addr)).cast::<c::sockaddr>(),
|
||||
size_of::<SocketAddrV6>() as _,
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn sendto_unix(
|
||||
fd: BorrowedFd<'_>,
|
||||
buf: &[u8],
|
||||
flags: SendFlags,
|
||||
addr: &SocketAddrUnix,
|
||||
) -> io::Result<usize> {
|
||||
let nwritten = unsafe {
|
||||
ret_send_recv(c::sendto(
|
||||
borrowed_fd(fd),
|
||||
buf.as_ptr().cast(),
|
||||
send_recv_len(buf.len()),
|
||||
flags.bits(),
|
||||
as_ptr(&addr.unix).cast(),
|
||||
addr.addr_len(),
|
||||
))?
|
||||
};
|
||||
Ok(nwritten as usize)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn socket(
|
||||
domain: AddressFamily,
|
||||
type_: SocketType,
|
||||
protocol: Protocol,
|
||||
) -> io::Result<OwnedFd> {
|
||||
unsafe {
|
||||
ret_owned_fd(c::socket(
|
||||
domain.0 as c::c_int,
|
||||
type_.0 as c::c_int,
|
||||
protocol.0,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn socket_with(
|
||||
domain: AddressFamily,
|
||||
type_: SocketType,
|
||||
flags: SocketFlags,
|
||||
protocol: Protocol,
|
||||
) -> io::Result<OwnedFd> {
|
||||
unsafe {
|
||||
ret_owned_fd(c::socket(
|
||||
domain.0 as c::c_int,
|
||||
type_.0 as c::c_int | flags.bits(),
|
||||
protocol.0,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn bind_v4(sockfd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::bind(
|
||||
borrowed_fd(sockfd),
|
||||
as_ptr(&encode_sockaddr_v4(addr)).cast(),
|
||||
size_of::<c::sockaddr_in>() as c::socklen_t,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn bind_v6(sockfd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::bind(
|
||||
borrowed_fd(sockfd),
|
||||
as_ptr(&encode_sockaddr_v6(addr)).cast(),
|
||||
size_of::<c::sockaddr_in6>() as c::socklen_t,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn bind_unix(sockfd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::bind(
|
||||
borrowed_fd(sockfd),
|
||||
as_ptr(&addr.unix).cast(),
|
||||
addr.addr_len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn connect_v4(sockfd: BorrowedFd<'_>, addr: &SocketAddrV4) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::connect(
|
||||
borrowed_fd(sockfd),
|
||||
as_ptr(&encode_sockaddr_v4(addr)).cast(),
|
||||
size_of::<c::sockaddr_in>() as c::socklen_t,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn connect_v6(sockfd: BorrowedFd<'_>, addr: &SocketAddrV6) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::connect(
|
||||
borrowed_fd(sockfd),
|
||||
as_ptr(&encode_sockaddr_v6(addr)).cast(),
|
||||
size_of::<c::sockaddr_in6>() as c::socklen_t,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn connect_unix(sockfd: BorrowedFd<'_>, addr: &SocketAddrUnix) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::connect(
|
||||
borrowed_fd(sockfd),
|
||||
as_ptr(&addr.unix).cast(),
|
||||
addr.addr_len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn listen(sockfd: BorrowedFd<'_>, backlog: c::c_int) -> io::Result<()> {
|
||||
unsafe { ret(c::listen(borrowed_fd(sockfd), backlog)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn accept(sockfd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
|
||||
unsafe {
|
||||
let owned_fd = ret_owned_fd(c::accept(borrowed_fd(sockfd), null_mut(), null_mut()))?;
|
||||
Ok(owned_fd)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, flags: AcceptFlags) -> io::Result<OwnedFd> {
|
||||
unsafe {
|
||||
let owned_fd = ret_owned_fd(c::accept4(
|
||||
borrowed_fd(sockfd),
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
flags.bits(),
|
||||
))?;
|
||||
Ok(owned_fd)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn acceptfrom(sockfd: BorrowedFd<'_>) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
|
||||
unsafe {
|
||||
let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
|
||||
let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
|
||||
let owned_fd = ret_owned_fd(c::accept(
|
||||
borrowed_fd(sockfd),
|
||||
storage.as_mut_ptr().cast(),
|
||||
&mut len,
|
||||
))?;
|
||||
Ok((
|
||||
owned_fd,
|
||||
maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub(crate) fn acceptfrom_with(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
flags: AcceptFlags,
|
||||
) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
|
||||
unsafe {
|
||||
let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
|
||||
let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
|
||||
let owned_fd = ret_owned_fd(c::accept4(
|
||||
borrowed_fd(sockfd),
|
||||
storage.as_mut_ptr().cast(),
|
||||
&mut len,
|
||||
flags.bits(),
|
||||
))?;
|
||||
Ok((
|
||||
owned_fd,
|
||||
maybe_read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Darwin lacks `accept4`, but does have `accept`. We define
|
||||
/// `AcceptFlags` to have no flags, so we can discard it here.
|
||||
#[cfg(any(windows, target_os = "haiku", target_os = "ios", target_os = "macos"))]
|
||||
pub(crate) fn accept_with(sockfd: BorrowedFd<'_>, _flags: AcceptFlags) -> io::Result<OwnedFd> {
|
||||
accept(sockfd)
|
||||
}
|
||||
|
||||
/// Darwin lacks `accept4`, but does have `accept`. We define
|
||||
/// `AcceptFlags` to have no flags, so we can discard it here.
|
||||
#[cfg(any(windows, target_os = "haiku", target_os = "ios", target_os = "macos"))]
|
||||
pub(crate) fn acceptfrom_with(
|
||||
sockfd: BorrowedFd<'_>,
|
||||
_flags: AcceptFlags,
|
||||
) -> io::Result<(OwnedFd, Option<SocketAddrAny>)> {
|
||||
acceptfrom(sockfd)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn shutdown(sockfd: BorrowedFd<'_>, how: Shutdown) -> io::Result<()> {
|
||||
unsafe { ret(c::shutdown(borrowed_fd(sockfd), how as c::c_int)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn getsockname(sockfd: BorrowedFd<'_>) -> io::Result<SocketAddrAny> {
|
||||
unsafe {
|
||||
let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
|
||||
let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
|
||||
ret(c::getsockname(
|
||||
borrowed_fd(sockfd),
|
||||
storage.as_mut_ptr().cast(),
|
||||
&mut len,
|
||||
))?;
|
||||
Ok(read_sockaddr_os(storage.as_ptr(), len.try_into().unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn getpeername(sockfd: BorrowedFd<'_>) -> io::Result<Option<SocketAddrAny>> {
|
||||
unsafe {
|
||||
let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
|
||||
let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
|
||||
ret(c::getpeername(
|
||||
borrowed_fd(sockfd),
|
||||
storage.as_mut_ptr().cast(),
|
||||
&mut len,
|
||||
))?;
|
||||
Ok(maybe_read_sockaddr_os(
|
||||
storage.as_ptr(),
|
||||
len.try_into().unwrap(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) fn socketpair(
|
||||
domain: AddressFamily,
|
||||
type_: SocketType,
|
||||
flags: SocketFlags,
|
||||
protocol: Protocol,
|
||||
) -> io::Result<(OwnedFd, OwnedFd)> {
|
||||
unsafe {
|
||||
let mut fds = MaybeUninit::<[OwnedFd; 2]>::uninit();
|
||||
ret(c::socketpair(
|
||||
c::c_int::from(domain.0),
|
||||
type_.0 as c::c_int | flags.bits(),
|
||||
protocol.0,
|
||||
fds.as_mut_ptr().cast::<c::c_int>(),
|
||||
))?;
|
||||
|
||||
let [fd0, fd1] = fds.assume_init();
|
||||
Ok((fd0, fd1))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
pub(crate) mod sockopt {
|
||||
use super::{c, in6_addr_new, in_addr_new, BorrowedFd};
|
||||
use crate::io;
|
||||
use crate::net::sockopt::Timeout;
|
||||
use crate::net::{Ipv4Addr, Ipv6Addr, SocketType};
|
||||
use crate::utils::as_mut_ptr;
|
||||
use core::convert::TryInto;
|
||||
use core::time::Duration;
|
||||
#[cfg(windows)]
|
||||
use windows_sys::Win32::Foundation::BOOL;
|
||||
|
||||
// TODO: With Rust 1.53 we can use `Duration::ZERO` instead.
|
||||
const DURATION_ZERO: Duration = Duration::from_secs(0);
|
||||
|
||||
#[inline]
|
||||
fn getsockopt<T: Copy>(fd: BorrowedFd<'_>, level: i32, optname: i32) -> io::Result<T> {
|
||||
use super::*;
|
||||
|
||||
let mut optlen = core::mem::size_of::<T>().try_into().unwrap();
|
||||
debug_assert!(
|
||||
optlen as usize >= core::mem::size_of::<c::c_int>(),
|
||||
"Socket APIs don't ever use `bool` directly"
|
||||
);
|
||||
|
||||
unsafe {
|
||||
let mut value = core::mem::zeroed::<T>();
|
||||
ret(c::getsockopt(
|
||||
borrowed_fd(fd),
|
||||
level,
|
||||
optname,
|
||||
as_mut_ptr(&mut value).cast(),
|
||||
&mut optlen,
|
||||
))?;
|
||||
// On Windows at least, `getsockopt` has been observed writing 1
|
||||
// byte on at least (`IPPROTO_TCP`, `TCP_NODELAY`), even though
|
||||
// Windows' documentation says that should write a 4-byte `BOOL`.
|
||||
// So, we initialize the memory to zeros above, and just assert
|
||||
// that `getsockopt` doesn't write too many bytes here.
|
||||
assert!(
|
||||
optlen as usize <= size_of::<T>(),
|
||||
"unexpected getsockopt size"
|
||||
);
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn setsockopt<T: Copy>(
|
||||
fd: BorrowedFd<'_>,
|
||||
level: i32,
|
||||
optname: i32,
|
||||
value: T,
|
||||
) -> io::Result<()> {
|
||||
use super::*;
|
||||
|
||||
let optlen = core::mem::size_of::<T>().try_into().unwrap();
|
||||
debug_assert!(
|
||||
optlen as usize >= core::mem::size_of::<c::c_int>(),
|
||||
"Socket APIs don't ever use `bool` directly"
|
||||
);
|
||||
|
||||
unsafe {
|
||||
ret(c::setsockopt(
|
||||
borrowed_fd(fd),
|
||||
level,
|
||||
optname,
|
||||
as_ptr(&value).cast(),
|
||||
optlen,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_socket_type(fd: BorrowedFd<'_>) -> io::Result<SocketType> {
|
||||
getsockopt(fd, c::SOL_SOCKET as _, c::SO_TYPE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_socket_reuseaddr(fd: BorrowedFd<'_>, reuseaddr: bool) -> io::Result<()> {
|
||||
setsockopt(
|
||||
fd,
|
||||
c::SOL_SOCKET as _,
|
||||
c::SO_REUSEADDR,
|
||||
from_bool(reuseaddr),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_socket_broadcast(fd: BorrowedFd<'_>, broadcast: bool) -> io::Result<()> {
|
||||
setsockopt(
|
||||
fd,
|
||||
c::SOL_SOCKET as _,
|
||||
c::SO_BROADCAST,
|
||||
from_bool(broadcast),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_socket_broadcast(fd: BorrowedFd<'_>) -> io::Result<bool> {
|
||||
getsockopt(fd, c::SOL_SOCKET as _, c::SO_BROADCAST).map(to_bool)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_socket_linger(
|
||||
fd: BorrowedFd<'_>,
|
||||
linger: Option<Duration>,
|
||||
) -> io::Result<()> {
|
||||
// Convert `linger` to seconds, rounding up.
|
||||
let l_linger = if let Some(linger) = linger {
|
||||
let mut l_linger = linger.as_secs();
|
||||
if linger.subsec_nanos() != 0 {
|
||||
l_linger = l_linger.checked_add(1).ok_or(io::Errno::INVAL)?;
|
||||
}
|
||||
l_linger.try_into().map_err(|_e| io::Errno::INVAL)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let linger = c::linger {
|
||||
l_onoff: linger.is_some() as _,
|
||||
l_linger,
|
||||
};
|
||||
setsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER, linger)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_socket_linger(fd: BorrowedFd<'_>) -> io::Result<Option<Duration>> {
|
||||
let linger: c::linger = getsockopt(fd, c::SOL_SOCKET as _, c::SO_LINGER)?;
|
||||
// TODO: With Rust 1.50, this could use `.then`.
|
||||
Ok(if linger.l_onoff != 0 {
|
||||
Some(Duration::from_secs(linger.l_linger as u64))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) fn set_socket_passcred(fd: BorrowedFd<'_>, passcred: bool) -> io::Result<()> {
|
||||
setsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED, from_bool(passcred))
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) fn get_socket_passcred(fd: BorrowedFd<'_>) -> io::Result<bool> {
|
||||
getsockopt(fd, c::SOL_SOCKET as _, c::SO_PASSCRED).map(to_bool)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_socket_timeout(
|
||||
fd: BorrowedFd<'_>,
|
||||
id: Timeout,
|
||||
timeout: Option<Duration>,
|
||||
) -> io::Result<()> {
|
||||
let optname = match id {
|
||||
Timeout::Recv => c::SO_RCVTIMEO,
|
||||
Timeout::Send => c::SO_SNDTIMEO,
|
||||
};
|
||||
|
||||
#[cfg(not(windows))]
|
||||
let timeout = match timeout {
|
||||
Some(timeout) => {
|
||||
if timeout == DURATION_ZERO {
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
|
||||
let tv_sec = timeout.as_secs().try_into();
|
||||
#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
|
||||
let tv_sec = tv_sec.unwrap_or(c::c_long::MAX);
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
|
||||
let tv_sec = tv_sec.unwrap_or(i64::MAX);
|
||||
|
||||
// `subsec_micros` rounds down, so we use `subsec_nanos` and
|
||||
// manually round up.
|
||||
let mut timeout = c::timeval {
|
||||
tv_sec,
|
||||
tv_usec: ((timeout.subsec_nanos() + 999) / 1000) as _,
|
||||
};
|
||||
if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
|
||||
timeout.tv_usec = 1;
|
||||
}
|
||||
timeout
|
||||
}
|
||||
None => c::timeval {
|
||||
tv_sec: 0,
|
||||
tv_usec: 0,
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
let timeout: u32 = match timeout {
|
||||
Some(timeout) => {
|
||||
if timeout == DURATION_ZERO {
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
|
||||
// `as_millis` rounds down, so we use `as_nanos` and
|
||||
// manually round up.
|
||||
let mut timeout: u32 = ((timeout.as_nanos() + 999_999) / 1_000_000)
|
||||
.try_into()
|
||||
.map_err(|_convert_err| io::Errno::INVAL)?;
|
||||
if timeout == 0 {
|
||||
timeout = 1;
|
||||
}
|
||||
timeout
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
|
||||
setsockopt(fd, c::SOL_SOCKET, optname, timeout)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_socket_timeout(
|
||||
fd: BorrowedFd<'_>,
|
||||
id: Timeout,
|
||||
) -> io::Result<Option<Duration>> {
|
||||
let optname = match id {
|
||||
Timeout::Recv => c::SO_RCVTIMEO,
|
||||
Timeout::Send => c::SO_SNDTIMEO,
|
||||
};
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
let timeout: c::timeval = getsockopt(fd, c::SOL_SOCKET, optname)?;
|
||||
if timeout.tv_sec == 0 && timeout.tv_usec == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(
|
||||
Duration::from_secs(timeout.tv_sec as u64)
|
||||
+ Duration::from_micros(timeout.tv_usec as u64),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let timeout: u32 = getsockopt(fd, c::SOL_SOCKET, optname)?;
|
||||
if timeout == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(Duration::from_millis(timeout as u64)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ip_ttl(fd: BorrowedFd<'_>, ttl: u32) -> io::Result<()> {
|
||||
setsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL, ttl)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_ip_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
|
||||
getsockopt(fd, c::IPPROTO_IP as _, c::IP_TTL)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ipv6_v6only(fd: BorrowedFd<'_>, only_v6: bool) -> io::Result<()> {
|
||||
setsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY, from_bool(only_v6))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_ipv6_v6only(fd: BorrowedFd<'_>) -> io::Result<bool> {
|
||||
getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_V6ONLY).map(to_bool)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ip_multicast_loop(
|
||||
fd: BorrowedFd<'_>,
|
||||
multicast_loop: bool,
|
||||
) -> io::Result<()> {
|
||||
setsockopt(
|
||||
fd,
|
||||
c::IPPROTO_IP as _,
|
||||
c::IP_MULTICAST_LOOP,
|
||||
from_bool(multicast_loop),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_ip_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
|
||||
getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_LOOP).map(to_bool)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ip_multicast_ttl(fd: BorrowedFd<'_>, multicast_ttl: u32) -> io::Result<()> {
|
||||
setsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL, multicast_ttl)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_ip_multicast_ttl(fd: BorrowedFd<'_>) -> io::Result<u32> {
|
||||
getsockopt(fd, c::IPPROTO_IP as _, c::IP_MULTICAST_TTL)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ipv6_multicast_loop(
|
||||
fd: BorrowedFd<'_>,
|
||||
multicast_loop: bool,
|
||||
) -> io::Result<()> {
|
||||
setsockopt(
|
||||
fd,
|
||||
c::IPPROTO_IPV6 as _,
|
||||
c::IPV6_MULTICAST_LOOP,
|
||||
from_bool(multicast_loop),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_ipv6_multicast_loop(fd: BorrowedFd<'_>) -> io::Result<bool> {
|
||||
getsockopt(fd, c::IPPROTO_IPV6 as _, c::IPV6_MULTICAST_LOOP).map(to_bool)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ipv6_multicast_hops(
|
||||
fd: BorrowedFd<'_>,
|
||||
multicast_hops: u32,
|
||||
) -> io::Result<()> {
|
||||
setsockopt(
|
||||
fd,
|
||||
c::IPPROTO_IP as _,
|
||||
c::IPV6_MULTICAST_LOOP,
|
||||
multicast_hops,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_ipv6_multicast_hops(fd: BorrowedFd<'_>) -> io::Result<u32> {
|
||||
getsockopt(fd, c::IPPROTO_IP as _, c::IPV6_MULTICAST_LOOP)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ip_add_membership(
|
||||
fd: BorrowedFd<'_>,
|
||||
multiaddr: &Ipv4Addr,
|
||||
interface: &Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
let mreq = to_imr(multiaddr, interface);
|
||||
setsockopt(fd, c::IPPROTO_IP as _, c::IP_ADD_MEMBERSHIP, mreq)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ipv6_add_membership(
|
||||
fd: BorrowedFd<'_>,
|
||||
multiaddr: &Ipv6Addr,
|
||||
interface: u32,
|
||||
) -> io::Result<()> {
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "l4re",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
use c::IPV6_ADD_MEMBERSHIP;
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "l4re",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
))]
|
||||
use c::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
|
||||
|
||||
let mreq = to_ipv6mr(multiaddr, interface);
|
||||
setsockopt(fd, c::IPPROTO_IPV6 as _, IPV6_ADD_MEMBERSHIP, mreq)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ip_drop_membership(
|
||||
fd: BorrowedFd<'_>,
|
||||
multiaddr: &Ipv4Addr,
|
||||
interface: &Ipv4Addr,
|
||||
) -> io::Result<()> {
|
||||
let mreq = to_imr(multiaddr, interface);
|
||||
setsockopt(fd, c::IPPROTO_IP as _, c::IP_DROP_MEMBERSHIP, mreq)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_ipv6_drop_membership(
|
||||
fd: BorrowedFd<'_>,
|
||||
multiaddr: &Ipv6Addr,
|
||||
interface: u32,
|
||||
) -> io::Result<()> {
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "l4re",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
use c::IPV6_DROP_MEMBERSHIP;
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "l4re",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
))]
|
||||
use c::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
|
||||
|
||||
let mreq = to_ipv6mr(multiaddr, interface);
|
||||
setsockopt(fd, c::IPPROTO_IPV6 as _, IPV6_DROP_MEMBERSHIP, mreq)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn set_tcp_nodelay(fd: BorrowedFd<'_>, nodelay: bool) -> io::Result<()> {
|
||||
setsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY, from_bool(nodelay))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn get_tcp_nodelay(fd: BorrowedFd<'_>) -> io::Result<bool> {
|
||||
getsockopt(fd, c::IPPROTO_TCP as _, c::TCP_NODELAY).map(to_bool)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_imr(multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> c::ip_mreq {
|
||||
c::ip_mreq {
|
||||
imr_multiaddr: to_imr_addr(multiaddr),
|
||||
imr_interface: to_imr_addr(interface),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_imr_addr(addr: &Ipv4Addr) -> c::in_addr {
|
||||
in_addr_new(u32::from_ne_bytes(addr.octets()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_ipv6mr(multiaddr: &Ipv6Addr, interface: u32) -> c::ipv6_mreq {
|
||||
c::ipv6_mreq {
|
||||
ipv6mr_multiaddr: to_ipv6mr_multiaddr(multiaddr),
|
||||
ipv6mr_interface: to_ipv6mr_interface(interface),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_ipv6mr_multiaddr(multiaddr: &Ipv6Addr) -> c::in6_addr {
|
||||
in6_addr_new(multiaddr.octets())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[inline]
|
||||
fn to_ipv6mr_interface(interface: u32) -> c::c_int {
|
||||
interface as c::c_int
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
#[inline]
|
||||
fn to_ipv6mr_interface(interface: u32) -> c::c_uint {
|
||||
interface as c::c_uint
|
||||
}
|
||||
|
||||
// `getsockopt` and `setsockopt` represent boolean values as integers.
|
||||
#[cfg(not(windows))]
|
||||
type RawSocketBool = c::c_int;
|
||||
#[cfg(windows)]
|
||||
type RawSocketBool = BOOL;
|
||||
|
||||
// Wrap `RawSocketBool` in a newtype to discourage misuse.
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct SocketBool(RawSocketBool);
|
||||
|
||||
// Convert from a `bool` to a `SocketBool`.
|
||||
#[inline]
|
||||
fn from_bool(value: bool) -> SocketBool {
|
||||
SocketBool(value as _)
|
||||
}
|
||||
|
||||
// Convert from a `SocketBool` to a `bool`.
|
||||
#[inline]
|
||||
fn to_bool(value: SocketBool) -> bool {
|
||||
value.0 != 0
|
||||
}
|
||||
}
|
||||
687
vendor/rustix/src/backend/libc/net/types.rs
vendored
Normal file
687
vendor/rustix/src/backend/libc/net/types.rs
vendored
Normal file
|
|
@ -0,0 +1,687 @@
|
|||
use super::super::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// A type for holding raw integer socket types.
|
||||
#[doc(hidden)]
|
||||
pub type RawSocketType = u32;
|
||||
|
||||
/// `SOCK_*` constants for use with [`socket`].
|
||||
///
|
||||
/// [`socket`]: crate::net::socket
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct SocketType(pub(crate) RawSocketType);
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl SocketType {
|
||||
/// `SOCK_STREAM`
|
||||
pub const STREAM: Self = Self(c::SOCK_STREAM as u32);
|
||||
|
||||
/// `SOCK_DGRAM`
|
||||
pub const DGRAM: Self = Self(c::SOCK_DGRAM as u32);
|
||||
|
||||
/// `SOCK_SEQPACKET`
|
||||
pub const SEQPACKET: Self = Self(c::SOCK_SEQPACKET as u32);
|
||||
|
||||
/// `SOCK_RAW`
|
||||
pub const RAW: Self = Self(c::SOCK_RAW as u32);
|
||||
|
||||
/// `SOCK_RDM`
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
pub const RDM: Self = Self(c::SOCK_RDM as u32);
|
||||
|
||||
/// Constructs a `SocketType` from a raw integer.
|
||||
#[inline]
|
||||
pub const fn from_raw(raw: RawSocketType) -> Self {
|
||||
Self(raw)
|
||||
}
|
||||
|
||||
/// Returns the raw integer for this `SocketType`.
|
||||
#[inline]
|
||||
pub const fn as_raw(self) -> RawSocketType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A type for holding raw integer address families.
|
||||
#[doc(hidden)]
|
||||
pub type RawAddressFamily = c::sa_family_t;
|
||||
|
||||
/// `AF_*` constants.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct AddressFamily(pub(crate) RawAddressFamily);
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl AddressFamily {
|
||||
/// `AF_UNSPEC`
|
||||
pub const UNSPEC: Self = Self(c::AF_UNSPEC as _);
|
||||
/// `AF_INET`
|
||||
pub const INET: Self = Self(c::AF_INET as _);
|
||||
/// `AF_INET6`
|
||||
pub const INET6: Self = Self(c::AF_INET6 as _);
|
||||
/// `AF_NETLINK`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const NETLINK: Self = Self(c::AF_NETLINK as _);
|
||||
/// `AF_UNIX`, aka `AF_LOCAL`
|
||||
#[doc(alias = "LOCAL")]
|
||||
pub const UNIX: Self = Self(c::AF_UNIX as _);
|
||||
/// `AF_AX25`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const AX25: Self = Self(c::AF_AX25 as _);
|
||||
/// `AF_IPX`
|
||||
pub const IPX: Self = Self(c::AF_IPX as _);
|
||||
/// `AF_APPLETALK`
|
||||
pub const APPLETALK: Self = Self(c::AF_APPLETALK as _);
|
||||
/// `AF_NETROM`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const NETROM: Self = Self(c::AF_NETROM as _);
|
||||
/// `AF_BRIDGE`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const BRIDGE: Self = Self(c::AF_BRIDGE as _);
|
||||
/// `AF_ATMPVC`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const ATMPVC: Self = Self(c::AF_ATMPVC as _);
|
||||
/// `AF_X25`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
pub const X25: Self = Self(c::AF_X25 as _);
|
||||
/// `AF_ROSE`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const ROSE: Self = Self(c::AF_ROSE as _);
|
||||
/// `AF_DECnet`
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
pub const DECnet: Self = Self(c::AF_DECnet as _);
|
||||
/// `AF_NETBEUI`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const NETBEUI: Self = Self(c::AF_NETBEUI as _);
|
||||
/// `AF_SECURITY`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const SECURITY: Self = Self(c::AF_SECURITY as _);
|
||||
/// `AF_KEY`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
pub const KEY: Self = Self(c::AF_KEY as _);
|
||||
/// `AF_PACKET`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
pub const PACKET: Self = Self(c::AF_PACKET as _);
|
||||
/// `AF_ASH`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const ASH: Self = Self(c::AF_ASH as _);
|
||||
/// `AF_ECONET`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const ECONET: Self = Self(c::AF_ECONET as _);
|
||||
/// `AF_ATMSVC`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const ATMSVC: Self = Self(c::AF_ATMSVC as _);
|
||||
/// `AF_RDS`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const RDS: Self = Self(c::AF_RDS as _);
|
||||
/// `AF_SNA`
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
pub const SNA: Self = Self(c::AF_SNA as _);
|
||||
/// `AF_IRDA`
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const IRDA: Self = Self(c::AF_IRDA as _);
|
||||
/// `AF_PPPOX`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const PPPOX: Self = Self(c::AF_PPPOX as _);
|
||||
/// `AF_WANPIPE`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const WANPIPE: Self = Self(c::AF_WANPIPE as _);
|
||||
/// `AF_LLC`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const LLC: Self = Self(c::AF_LLC as _);
|
||||
/// `AF_CAN`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const CAN: Self = Self(c::AF_CAN as _);
|
||||
/// `AF_TIPC`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const TIPC: Self = Self(c::AF_TIPC as _);
|
||||
/// `AF_BLUETOOTH`
|
||||
#[cfg(not(any(windows, target_os = "illumos", target_os = "ios", target_os = "macos", target_os = "solaris")))]
|
||||
pub const BLUETOOTH: Self = Self(c::AF_BLUETOOTH as _);
|
||||
/// `AF_IUCV`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const IUCV: Self = Self(c::AF_IUCV as _);
|
||||
/// `AF_RXRPC`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const RXRPC: Self = Self(c::AF_RXRPC as _);
|
||||
/// `AF_ISDN`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const ISDN: Self = Self(c::AF_ISDN as _);
|
||||
/// `AF_PHONET`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const PHONET: Self = Self(c::AF_PHONET as _);
|
||||
/// `AF_IEEE802154`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const IEEE802154: Self = Self(c::AF_IEEE802154 as _);
|
||||
|
||||
/// Constructs a `AddressFamily` from a raw integer.
|
||||
#[inline]
|
||||
pub const fn from_raw(raw: RawAddressFamily) -> Self {
|
||||
Self(raw)
|
||||
}
|
||||
|
||||
/// Returns the raw integer for this `AddressFamily`.
|
||||
#[inline]
|
||||
pub const fn as_raw(self) -> RawAddressFamily {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A type for holding raw integer protocols.
|
||||
#[doc(hidden)]
|
||||
pub type RawProtocol = i32;
|
||||
|
||||
/// `IPPROTO_*`
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct Protocol(pub(crate) RawProtocol);
|
||||
|
||||
#[rustfmt::skip]
|
||||
impl Protocol {
|
||||
/// `IPPROTO_IP`
|
||||
pub const IP: Self = Self(c::IPPROTO_IP as _);
|
||||
/// `IPPROTO_ICMP`
|
||||
pub const ICMP: Self = Self(c::IPPROTO_ICMP as _);
|
||||
/// `IPPROTO_IGMP`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const IGMP: Self = Self(c::IPPROTO_IGMP as _);
|
||||
/// `IPPROTO_IPIP`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const IPIP: Self = Self(c::IPPROTO_IPIP as _);
|
||||
/// `IPPROTO_TCP`
|
||||
pub const TCP: Self = Self(c::IPPROTO_TCP as _);
|
||||
/// `IPPROTO_EGP`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const EGP: Self = Self(c::IPPROTO_EGP as _);
|
||||
/// `IPPROTO_PUP`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const PUP: Self = Self(c::IPPROTO_PUP as _);
|
||||
/// `IPPROTO_UDP`
|
||||
pub const UDP: Self = Self(c::IPPROTO_UDP as _);
|
||||
/// `IPPROTO_IDP`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const IDP: Self = Self(c::IPPROTO_IDP as _);
|
||||
/// `IPPROTO_TP`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const TP: Self = Self(c::IPPROTO_TP as _);
|
||||
/// `IPPROTO_DCCP`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const DCCP: Self = Self(c::IPPROTO_DCCP as _);
|
||||
/// `IPPROTO_IPV6`
|
||||
pub const IPV6: Self = Self(c::IPPROTO_IPV6 as _);
|
||||
/// `IPPROTO_RSVP`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const RSVP: Self = Self(c::IPPROTO_RSVP as _);
|
||||
/// `IPPROTO_GRE`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const GRE: Self = Self(c::IPPROTO_GRE as _);
|
||||
/// `IPPROTO_ESP`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const ESP: Self = Self(c::IPPROTO_ESP as _);
|
||||
/// `IPPROTO_AH`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const AH: Self = Self(c::IPPROTO_AH as _);
|
||||
/// `IPPROTO_MTP`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const MTP: Self = Self(c::IPPROTO_MTP as _);
|
||||
/// `IPPROTO_BEETPH`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const BEETPH: Self = Self(c::IPPROTO_BEETPH as _);
|
||||
/// `IPPROTO_ENCAP`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const ENCAP: Self = Self(c::IPPROTO_ENCAP as _);
|
||||
/// `IPPROTO_PIM`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const PIM: Self = Self(c::IPPROTO_PIM as _);
|
||||
/// `IPPROTO_COMP`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const COMP: Self = Self(c::IPPROTO_COMP as _);
|
||||
/// `IPPROTO_SCTP`
|
||||
#[cfg(not(any(target_os = "dragonfly", target_os = "haiku", target_os = "illumos", target_os = "openbsd", target_os = "solaris")))]
|
||||
pub const SCTP: Self = Self(c::IPPROTO_SCTP as _);
|
||||
/// `IPPROTO_UDPLITE`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const UDPLITE: Self = Self(c::IPPROTO_UDPLITE as _);
|
||||
/// `IPPROTO_MPLS`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const MPLS: Self = Self(c::IPPROTO_MPLS as _);
|
||||
/// `IPPROTO_RAW`
|
||||
pub const RAW: Self = Self(c::IPPROTO_RAW as _);
|
||||
/// `IPPROTO_MPTCP`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const MPTCP: Self = Self(c::IPPROTO_MPTCP as _);
|
||||
/// `IPPROTO_FRAGMENT`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const FRAGMENT: Self = Self(c::IPPROTO_FRAGMENT as _);
|
||||
/// `IPPROTO_ICMPV6`
|
||||
pub const ICMPV6: Self = Self(c::IPPROTO_ICMPV6 as _);
|
||||
/// `IPPROTO_MH`
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub const MH: Self = Self(c::IPPROTO_MH as _);
|
||||
/// `IPPROTO_ROUTING`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
pub const ROUTING: Self = Self(c::IPPROTO_ROUTING as _);
|
||||
|
||||
/// Constructs a `Protocol` from a raw integer.
|
||||
#[inline]
|
||||
pub const fn from_raw(raw: RawProtocol) -> Self {
|
||||
Self(raw)
|
||||
}
|
||||
|
||||
/// Returns the raw integer for this `Protocol`.
|
||||
#[inline]
|
||||
pub const fn as_raw(self) -> RawProtocol {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// `SHUT_*` constants for use with [`shutdown`].
|
||||
///
|
||||
/// [`shutdown`]: crate::net::shutdown
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[repr(i32)]
|
||||
pub enum Shutdown {
|
||||
/// `SHUT_RD`—Disable further read operations.
|
||||
Read = c::SHUT_RD,
|
||||
/// `SHUT_WR`—Disable further write operations.
|
||||
Write = c::SHUT_WR,
|
||||
/// `SHUT_RDWR`—Disable further read and write operations.
|
||||
ReadWrite = c::SHUT_RDWR,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `SOCK_*` constants for use with [`accept_with`] and [`acceptfrom_with`].
|
||||
///
|
||||
/// [`accept_with`]: crate::net::accept_with
|
||||
/// [`acceptfrom_with`]: crate::net::acceptfrom_with
|
||||
pub struct AcceptFlags: c::c_int {
|
||||
/// `SOCK_NONBLOCK`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "ios", target_os = "macos")))]
|
||||
const NONBLOCK = c::SOCK_NONBLOCK;
|
||||
|
||||
/// `SOCK_CLOEXEC`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "ios", target_os = "macos")))]
|
||||
const CLOEXEC = c::SOCK_CLOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `SOCK_*` constants for use with [`socket`].
|
||||
///
|
||||
/// [`socket`]: crate::net::socket
|
||||
pub struct SocketFlags: c::c_int {
|
||||
/// `SOCK_NONBLOCK`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "ios", target_os = "macos")))]
|
||||
const NONBLOCK = c::SOCK_NONBLOCK;
|
||||
|
||||
/// `SOCK_CLOEXEC`
|
||||
#[cfg(not(any(windows, target_os = "haiku", target_os = "ios", target_os = "macos")))]
|
||||
const CLOEXEC = c::SOCK_CLOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
/// Timeout identifier for use with [`set_socket_timeout`] and
|
||||
/// [`get_socket_timeout`].
|
||||
///
|
||||
/// [`set_socket_timeout`]: crate::net::sockopt::set_socket_timeout.
|
||||
/// [`get_socket_timeout`]: crate::net::sockopt::get_socket_timeout.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[repr(i32)]
|
||||
pub enum Timeout {
|
||||
/// `SO_RCVTIMEO`—Timeout for receiving.
|
||||
Recv = c::SO_RCVTIMEO,
|
||||
|
||||
/// `SO_SNDTIMEO`—Timeout for sending.
|
||||
Send = c::SO_SNDTIMEO,
|
||||
}
|
||||
102
vendor/rustix/src/backend/libc/net/write_sockaddr.rs
vendored
Normal file
102
vendor/rustix/src/backend/libc/net/write_sockaddr.rs
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
//! The BSD sockets API requires us to read the `ss_family` field before
|
||||
//! we can interpret the rest of a `sockaddr` produced by the kernel.
|
||||
|
||||
use super::super::c;
|
||||
use super::addr::SocketAddrStorage;
|
||||
#[cfg(unix)]
|
||||
use super::addr::SocketAddrUnix;
|
||||
use super::ext::{in6_addr_new, in_addr_new, sockaddr_in6_new};
|
||||
use crate::net::{SocketAddrAny, SocketAddrV4, SocketAddrV6};
|
||||
use core::mem::size_of;
|
||||
|
||||
pub(crate) unsafe fn write_sockaddr(
|
||||
addr: &SocketAddrAny,
|
||||
storage: *mut SocketAddrStorage,
|
||||
) -> usize {
|
||||
match addr {
|
||||
SocketAddrAny::V4(v4) => write_sockaddr_v4(v4, storage),
|
||||
SocketAddrAny::V6(v6) => write_sockaddr_v6(v6, storage),
|
||||
#[cfg(unix)]
|
||||
SocketAddrAny::Unix(unix) => write_sockaddr_unix(unix, storage),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn encode_sockaddr_v4(v4: &SocketAddrV4) -> c::sockaddr_in {
|
||||
c::sockaddr_in {
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
sin_len: size_of::<c::sockaddr_in>() as _,
|
||||
sin_family: c::AF_INET as _,
|
||||
sin_port: u16::to_be(v4.port()),
|
||||
sin_addr: in_addr_new(u32::from_ne_bytes(v4.ip().octets())),
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
sin_zero: [0; 8_usize],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sin_zero: [0; 24_usize],
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn write_sockaddr_v4(v4: &SocketAddrV4, storage: *mut SocketAddrStorage) -> usize {
|
||||
let encoded = encode_sockaddr_v4(v4);
|
||||
core::ptr::write(storage.cast(), encoded);
|
||||
size_of::<c::sockaddr_in>()
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn encode_sockaddr_v6(v6: &SocketAddrV6) -> c::sockaddr_in6 {
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
))]
|
||||
{
|
||||
sockaddr_in6_new(
|
||||
size_of::<c::sockaddr_in6>() as _,
|
||||
c::AF_INET6 as _,
|
||||
u16::to_be(v6.port()),
|
||||
u32::to_be(v6.flowinfo()),
|
||||
in6_addr_new(v6.ip().octets()),
|
||||
v6.scope_id(),
|
||||
)
|
||||
}
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
{
|
||||
sockaddr_in6_new(
|
||||
c::AF_INET6 as _,
|
||||
u16::to_be(v6.port()),
|
||||
u32::to_be(v6.flowinfo()),
|
||||
in6_addr_new(v6.ip().octets()),
|
||||
v6.scope_id(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn write_sockaddr_v6(v6: &SocketAddrV6, storage: *mut SocketAddrStorage) -> usize {
|
||||
let encoded = encode_sockaddr_v6(v6);
|
||||
core::ptr::write(storage.cast(), encoded);
|
||||
size_of::<c::sockaddr_in6>()
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
unsafe fn write_sockaddr_unix(unix: &SocketAddrUnix, storage: *mut SocketAddrStorage) -> usize {
|
||||
core::ptr::write(storage.cast(), unix.unix);
|
||||
unix.len()
|
||||
}
|
||||
406
vendor/rustix/src/backend/libc/offset.rs
vendored
Normal file
406
vendor/rustix/src/backend/libc/offset.rs
vendored
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
//! Automatically enable “large file” support features.
|
||||
|
||||
#[cfg(not(windows))]
|
||||
use super::c;
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
)))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::{
|
||||
fstat as libc_fstat, fstatat as libc_fstatat, ftruncate as libc_ftruncate, lseek as libc_lseek,
|
||||
off_t as libc_off_t,
|
||||
};
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::{
|
||||
fstat64 as libc_fstat, fstatat64 as libc_fstatat, ftruncate64 as libc_ftruncate,
|
||||
lseek64 as libc_lseek, off64_t as libc_off_t,
|
||||
};
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
))]
|
||||
pub(super) use c::rlimit64 as libc_rlimit;
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[cfg(feature = "mm")]
|
||||
pub(super) use c::mmap as libc_mmap;
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "fuchsia",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub(super) use c::{rlimit as libc_rlimit, RLIM_INFINITY as LIBC_RLIM_INFINITY};
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "linux",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub(super) use c::{getrlimit as libc_getrlimit, setrlimit as libc_setrlimit};
|
||||
|
||||
// TODO: Add `RLIM64_INFINITY` to upstream libc.
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
))]
|
||||
pub(super) const LIBC_RLIM_INFINITY: u64 = !0_u64;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
))]
|
||||
pub(super) use c::{getrlimit64 as libc_getrlimit, setrlimit64 as libc_setrlimit};
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
))]
|
||||
#[cfg(feature = "mm")]
|
||||
pub(super) use c::mmap64 as libc_mmap;
|
||||
|
||||
// `prlimit64` wasn't supported in glibc until 2.13.
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
weak_or_syscall! {
|
||||
fn prlimit64(
|
||||
pid: c::pid_t,
|
||||
resource: c::__rlimit_resource_t,
|
||||
new_limit: *const c::rlimit64,
|
||||
old_limit: *mut c::rlimit64
|
||||
) via SYS_prlimit64 -> c::c_int
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_env = "musl"))]
|
||||
weak_or_syscall! {
|
||||
fn prlimit64(
|
||||
pid: c::pid_t,
|
||||
resource: c::c_int,
|
||||
new_limit: *const c::rlimit64,
|
||||
old_limit: *mut c::rlimit64
|
||||
) via SYS_prlimit64 -> c::c_int
|
||||
}
|
||||
#[cfg(target_os = "android")]
|
||||
weak_or_syscall! {
|
||||
fn prlimit64(
|
||||
pid: c::pid_t,
|
||||
resource: c::c_int,
|
||||
new_limit: *const c::rlimit64,
|
||||
old_limit: *mut c::rlimit64
|
||||
) via SYS_prlimit64 -> c::c_int
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
pub(super) unsafe fn libc_prlimit(
|
||||
pid: c::pid_t,
|
||||
resource: c::__rlimit_resource_t,
|
||||
new_limit: *const c::rlimit64,
|
||||
old_limit: *mut c::rlimit64,
|
||||
) -> c::c_int {
|
||||
prlimit64(pid, resource, new_limit, old_limit)
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_env = "musl"))]
|
||||
pub(super) unsafe fn libc_prlimit(
|
||||
pid: c::pid_t,
|
||||
resource: c::c_int,
|
||||
new_limit: *const c::rlimit64,
|
||||
old_limit: *mut c::rlimit64,
|
||||
) -> c::c_int {
|
||||
prlimit64(pid, resource, new_limit, old_limit)
|
||||
}
|
||||
#[cfg(target_os = "android")]
|
||||
pub(super) unsafe fn libc_prlimit(
|
||||
pid: c::pid_t,
|
||||
resource: c::c_int,
|
||||
new_limit: *const c::rlimit64,
|
||||
old_limit: *mut c::rlimit64,
|
||||
) -> c::c_int {
|
||||
prlimit64(pid, resource, new_limit, old_limit)
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "redox",
|
||||
)))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::openat as libc_openat;
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::openat64 as libc_openat;
|
||||
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::fallocate as libc_fallocate;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::fallocate64 as libc_fallocate;
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "linux",
|
||||
target_os = "l4re",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::posix_fadvise as libc_posix_fadvise;
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "linux",
|
||||
target_os = "l4re",
|
||||
))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::posix_fadvise64 as libc_posix_fadvise;
|
||||
|
||||
#[cfg(all(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "emscripten",
|
||||
))))]
|
||||
pub(super) use c::{pread as libc_pread, pwrite as libc_pwrite};
|
||||
#[cfg(any(target_os = "android", target_os = "linux", target_os = "emscripten"))]
|
||||
pub(super) use c::{pread64 as libc_pread, pwrite64 as libc_pwrite};
|
||||
#[cfg(any(target_os = "linux", target_os = "emscripten"))]
|
||||
pub(super) use c::{preadv64 as libc_preadv, pwritev64 as libc_pwritev};
|
||||
#[cfg(target_os = "android")]
|
||||
mod readwrite_pv64 {
|
||||
use super::c;
|
||||
|
||||
// 64-bit offsets on 32-bit platforms are passed in endianness-specific
|
||||
// lo/hi pairs. See src/backend/linux_raw/conv.rs for details.
|
||||
#[cfg(all(target_endian = "little", target_pointer_width = "32"))]
|
||||
fn lo(x: u64) -> usize {
|
||||
(x >> 32) as usize
|
||||
}
|
||||
#[cfg(all(target_endian = "little", target_pointer_width = "32"))]
|
||||
fn hi(x: u64) -> usize {
|
||||
(x & 0xffff_ffff) as usize
|
||||
}
|
||||
#[cfg(all(target_endian = "big", target_pointer_width = "32"))]
|
||||
fn lo(x: u64) -> usize {
|
||||
(x & 0xffff_ffff) as usize
|
||||
}
|
||||
#[cfg(all(target_endian = "big", target_pointer_width = "32"))]
|
||||
fn hi(x: u64) -> usize {
|
||||
(x >> 32) as usize
|
||||
}
|
||||
|
||||
pub(in super::super) unsafe fn preadv64(
|
||||
fd: c::c_int,
|
||||
iov: *const c::iovec,
|
||||
iovcnt: c::c_int,
|
||||
offset: c::off64_t,
|
||||
) -> c::ssize_t {
|
||||
// Older Android libc lacks `preadv64`, so use the `weak!` mechanism to
|
||||
// test for it, and call back to `c::syscall`. We don't use
|
||||
// `weak_or_syscall` here because we need to pass the 64-bit offset
|
||||
// specially.
|
||||
weak! {
|
||||
fn preadv64(c::c_int, *const c::iovec, c::c_int, c::off64_t) -> c::ssize_t
|
||||
}
|
||||
if let Some(fun) = preadv64.get() {
|
||||
fun(fd, iov, iovcnt, offset)
|
||||
} else {
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
{
|
||||
c::syscall(
|
||||
c::SYS_preadv,
|
||||
fd,
|
||||
iov,
|
||||
iovcnt,
|
||||
hi(offset as u64),
|
||||
lo(offset as u64),
|
||||
) as c::ssize_t
|
||||
}
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
{
|
||||
c::syscall(c::SYS_preadv, fd, iov, iovcnt, offset) as c::ssize_t
|
||||
}
|
||||
}
|
||||
}
|
||||
pub(in super::super) unsafe fn pwritev64(
|
||||
fd: c::c_int,
|
||||
iov: *const c::iovec,
|
||||
iovcnt: c::c_int,
|
||||
offset: c::off64_t,
|
||||
) -> c::ssize_t {
|
||||
// See the comments in `preadv64`.
|
||||
weak! {
|
||||
fn pwritev64(c::c_int, *const c::iovec, c::c_int, c::off64_t) -> c::ssize_t
|
||||
}
|
||||
if let Some(fun) = pwritev64.get() {
|
||||
fun(fd, iov, iovcnt, offset)
|
||||
} else {
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
{
|
||||
c::syscall(
|
||||
c::SYS_pwritev,
|
||||
fd,
|
||||
iov,
|
||||
iovcnt,
|
||||
hi(offset as u64),
|
||||
lo(offset as u64),
|
||||
) as c::ssize_t
|
||||
}
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
{
|
||||
c::syscall(c::SYS_pwritev, fd, iov, iovcnt, offset) as c::ssize_t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "linux",
|
||||
target_os = "macos",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
pub(super) use c::{preadv as libc_preadv, pwritev as libc_pwritev};
|
||||
#[cfg(target_os = "android")]
|
||||
pub(super) use readwrite_pv64::{preadv64 as libc_preadv, pwritev64 as libc_pwritev};
|
||||
// macOS added preadv and pwritev in version 11.0
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
mod readwrite_pv {
|
||||
use super::c;
|
||||
|
||||
weakcall! {
|
||||
pub(in super::super) fn preadv(
|
||||
fd: c::c_int,
|
||||
iov: *const c::iovec,
|
||||
iovcnt: c::c_int,
|
||||
offset: c::off_t
|
||||
) -> c::ssize_t
|
||||
}
|
||||
weakcall! {
|
||||
pub(in super::super) fn pwritev(
|
||||
fd: c::c_int,
|
||||
iov: *const c::iovec,
|
||||
iovcnt: c::c_int, offset: c::off_t
|
||||
) -> c::ssize_t
|
||||
}
|
||||
}
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
pub(super) use c::{preadv64v2 as libc_preadv2, pwritev64v2 as libc_pwritev2};
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
pub(super) use readwrite_pv::{preadv as libc_preadv, pwritev as libc_pwritev};
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "linux",
|
||||
target_os = "l4re",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::posix_fallocate as libc_posix_fallocate;
|
||||
#[cfg(target_os = "l4re")]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use c::posix_fallocate64 as libc_posix_fallocate;
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "l4re",
|
||||
target_os = "netbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use {c::fstatfs as libc_fstatfs, c::statfs as libc_statfs};
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "l4re",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use {c::fstatvfs as libc_fstatvfs, c::statvfs as libc_statvfs};
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "linux",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub(super) use {
|
||||
c::fstatfs64 as libc_fstatfs, c::fstatvfs64 as libc_fstatvfs, c::statfs64 as libc_statfs,
|
||||
c::statvfs64 as libc_statvfs,
|
||||
};
|
||||
54
vendor/rustix/src/backend/libc/param/auxv.rs
vendored
Normal file
54
vendor/rustix/src/backend/libc/param/auxv.rs
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use super::super::c;
|
||||
#[cfg(any(
|
||||
all(target_os = "android", target_pointer_width = "64"),
|
||||
target_os = "linux",
|
||||
))]
|
||||
use crate::ffi::CStr;
|
||||
|
||||
// `getauxval` wasn't supported in glibc until 2.16.
|
||||
#[cfg(any(
|
||||
all(target_os = "android", target_pointer_width = "64"),
|
||||
target_os = "linux",
|
||||
))]
|
||||
weak!(fn getauxval(c::c_ulong) -> *mut c::c_void);
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn page_size() -> usize {
|
||||
unsafe { c::sysconf(c::_SC_PAGESIZE) as usize }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn clock_ticks_per_second() -> u64 {
|
||||
unsafe { c::sysconf(c::_SC_CLK_TCK) as u64 }
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
all(target_os = "android", target_pointer_width = "64"),
|
||||
target_os = "linux",
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn linux_hwcap() -> (usize, usize) {
|
||||
if let Some(libc_getauxval) = getauxval.get() {
|
||||
unsafe {
|
||||
let hwcap = libc_getauxval(c::AT_HWCAP) as usize;
|
||||
let hwcap2 = libc_getauxval(c::AT_HWCAP2) as usize;
|
||||
(hwcap, hwcap2)
|
||||
}
|
||||
} else {
|
||||
(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
all(target_os = "android", target_pointer_width = "64"),
|
||||
target_os = "linux",
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn linux_execfn() -> &'static CStr {
|
||||
if let Some(libc_getauxval) = getauxval.get() {
|
||||
unsafe { CStr::from_ptr(libc_getauxval(c::AT_EXECFN).cast()) }
|
||||
} else {
|
||||
cstr!("")
|
||||
}
|
||||
}
|
||||
1
vendor/rustix/src/backend/libc/param/mod.rs
vendored
Normal file
1
vendor/rustix/src/backend/libc/param/mod.rs
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub(crate) mod auxv;
|
||||
49
vendor/rustix/src/backend/libc/process/cpu_set.rs
vendored
Normal file
49
vendor/rustix/src/backend/libc/process/cpu_set.rs
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#![allow(non_snake_case)]
|
||||
|
||||
use super::super::c;
|
||||
use super::types::{RawCpuSet, CPU_SETSIZE};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn CPU_SET(cpu: usize, cpuset: &mut RawCpuSet) {
|
||||
assert!(
|
||||
cpu < CPU_SETSIZE,
|
||||
"cpu out of bounds: the cpu max is {} but the cpu is {}",
|
||||
CPU_SETSIZE,
|
||||
cpu
|
||||
);
|
||||
unsafe { c::CPU_SET(cpu, cpuset) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn CPU_ZERO(cpuset: &mut RawCpuSet) {
|
||||
unsafe { c::CPU_ZERO(cpuset) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn CPU_CLR(cpu: usize, cpuset: &mut RawCpuSet) {
|
||||
assert!(
|
||||
cpu < CPU_SETSIZE,
|
||||
"cpu out of bounds: the cpu max is {} but the cpu is {}",
|
||||
CPU_SETSIZE,
|
||||
cpu
|
||||
);
|
||||
unsafe { c::CPU_CLR(cpu, cpuset) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn CPU_ISSET(cpu: usize, cpuset: &RawCpuSet) -> bool {
|
||||
assert!(
|
||||
cpu < CPU_SETSIZE,
|
||||
"cpu out of bounds: the cpu max is {} but the cpu is {}",
|
||||
CPU_SETSIZE,
|
||||
cpu
|
||||
);
|
||||
unsafe { c::CPU_ISSET(cpu, cpuset) }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) fn CPU_COUNT(cpuset: &RawCpuSet) -> u32 {
|
||||
use core::convert::TryInto;
|
||||
unsafe { c::CPU_COUNT(cpuset).try_into().unwrap() }
|
||||
}
|
||||
12
vendor/rustix/src/backend/libc/process/mod.rs
vendored
Normal file
12
vendor/rustix/src/backend/libc/process/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
))]
|
||||
pub(crate) mod cpu_set;
|
||||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) mod wait;
|
||||
465
vendor/rustix/src/backend/libc/process/syscalls.rs
vendored
Normal file
465
vendor/rustix/src/backend/libc/process/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,465 @@
|
|||
//! libc syscalls supporting `rustix::process`.
|
||||
|
||||
use super::super::c;
|
||||
#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
|
||||
use super::super::conv::borrowed_fd;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use super::super::conv::ret_pid_t;
|
||||
use super::super::conv::{c_str, ret, ret_c_int, ret_discarded_char_ptr};
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use super::super::conv::{syscall_ret, syscall_ret_u32};
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
))]
|
||||
use super::types::RawCpuSet;
|
||||
#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
|
||||
use crate::fd::BorrowedFd;
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
use {
|
||||
super::super::conv::ret_infallible,
|
||||
super::super::offset::{libc_getrlimit, libc_rlimit, libc_setrlimit, LIBC_RLIM_INFINITY},
|
||||
crate::process::{Resource, Rlimit},
|
||||
core::convert::TryInto,
|
||||
};
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use {
|
||||
super::super::offset::libc_prlimit,
|
||||
crate::process::{Cpuid, MembarrierCommand, MembarrierQuery},
|
||||
};
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use {
|
||||
super::types::RawUname,
|
||||
crate::process::{Gid, Pid, RawNonZeroPid, RawPid, Signal, Uid, WaitOptions, WaitStatus},
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn chdir(path: &CStr) -> io::Result<()> {
|
||||
unsafe { ret(c::chdir(c_str(path))) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
|
||||
pub(crate) fn fchdir(dirfd: BorrowedFd<'_>) -> io::Result<()> {
|
||||
unsafe { ret(c::fchdir(borrowed_fd(dirfd))) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn getcwd(buf: &mut [u8]) -> io::Result<()> {
|
||||
unsafe { ret_discarded_char_ptr(c::getcwd(buf.as_mut_ptr().cast(), buf.len())) }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
pub(crate) fn membarrier_query() -> MembarrierQuery {
|
||||
// GLIBC does not have a wrapper for `membarrier`; [the documentation]
|
||||
// says to use `syscall`.
|
||||
//
|
||||
// [the documentation]: https://man7.org/linux/man-pages/man2/membarrier.2.html#NOTES
|
||||
const MEMBARRIER_CMD_QUERY: u32 = 0;
|
||||
unsafe {
|
||||
match syscall_ret_u32(c::syscall(c::SYS_membarrier, MEMBARRIER_CMD_QUERY, 0)) {
|
||||
Ok(query) => MembarrierQuery::from_bits_unchecked(query),
|
||||
Err(_) => MembarrierQuery::empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
pub(crate) fn membarrier(cmd: MembarrierCommand) -> io::Result<()> {
|
||||
unsafe { syscall_ret(c::syscall(c::SYS_membarrier, cmd as u32, 0)) }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
pub(crate) fn membarrier_cpu(cmd: MembarrierCommand, cpu: Cpuid) -> io::Result<()> {
|
||||
const MEMBARRIER_CMD_FLAG_CPU: u32 = 1;
|
||||
unsafe {
|
||||
syscall_ret(c::syscall(
|
||||
c::SYS_membarrier,
|
||||
cmd as u32,
|
||||
MEMBARRIER_CMD_FLAG_CPU,
|
||||
cpu.as_raw(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn getuid() -> Uid {
|
||||
unsafe {
|
||||
let uid = c::getuid();
|
||||
Uid::from_raw(uid)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn geteuid() -> Uid {
|
||||
unsafe {
|
||||
let uid = c::geteuid();
|
||||
Uid::from_raw(uid)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn getgid() -> Gid {
|
||||
unsafe {
|
||||
let gid = c::getgid();
|
||||
Gid::from_raw(gid)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn getegid() -> Gid {
|
||||
unsafe {
|
||||
let gid = c::getegid();
|
||||
Gid::from_raw(gid)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn getpid() -> Pid {
|
||||
unsafe {
|
||||
let pid = c::getpid();
|
||||
debug_assert_ne!(pid, 0);
|
||||
Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn getppid() -> Option<Pid> {
|
||||
unsafe {
|
||||
let pid: i32 = c::getppid();
|
||||
Pid::from_raw(pid)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn getpgid(pid: Option<Pid>) -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pgid = ret_pid_t(c::getpgid(Pid::as_raw(pid) as _))?;
|
||||
debug_assert_ne!(pgid, 0);
|
||||
Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pgid)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn getpgrp() -> Pid {
|
||||
unsafe {
|
||||
let pgid = c::getpgrp();
|
||||
debug_assert_ne!(pgid, 0);
|
||||
Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pgid))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn sched_getaffinity(pid: Option<Pid>, cpuset: &mut RawCpuSet) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::sched_getaffinity(
|
||||
Pid::as_raw(pid) as _,
|
||||
core::mem::size_of::<RawCpuSet>(),
|
||||
cpuset,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn sched_setaffinity(pid: Option<Pid>, cpuset: &RawCpuSet) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::sched_setaffinity(
|
||||
Pid::as_raw(pid) as _,
|
||||
core::mem::size_of::<RawCpuSet>(),
|
||||
cpuset,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn sched_yield() {
|
||||
unsafe {
|
||||
let _ = c::sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn uname() -> RawUname {
|
||||
let mut uname = MaybeUninit::<RawUname>::uninit();
|
||||
unsafe {
|
||||
ret(c::uname(uname.as_mut_ptr())).unwrap();
|
||||
uname.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn nice(inc: i32) -> io::Result<i32> {
|
||||
libc_errno::set_errno(libc_errno::Errno(0));
|
||||
let r = unsafe { c::nice(inc) };
|
||||
if libc_errno::errno().0 != 0 {
|
||||
ret_c_int(r)
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn getpriority_user(uid: Uid) -> io::Result<i32> {
|
||||
libc_errno::set_errno(libc_errno::Errno(0));
|
||||
let r = unsafe { c::getpriority(c::PRIO_USER, uid.as_raw() as _) };
|
||||
if libc_errno::errno().0 != 0 {
|
||||
ret_c_int(r)
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn getpriority_pgrp(pgid: Option<Pid>) -> io::Result<i32> {
|
||||
libc_errno::set_errno(libc_errno::Errno(0));
|
||||
let r = unsafe { c::getpriority(c::PRIO_PGRP, Pid::as_raw(pgid) as _) };
|
||||
if libc_errno::errno().0 != 0 {
|
||||
ret_c_int(r)
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn getpriority_process(pid: Option<Pid>) -> io::Result<i32> {
|
||||
libc_errno::set_errno(libc_errno::Errno(0));
|
||||
let r = unsafe { c::getpriority(c::PRIO_PROCESS, Pid::as_raw(pid) as _) };
|
||||
if libc_errno::errno().0 != 0 {
|
||||
ret_c_int(r)
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn setpriority_user(uid: Uid, priority: i32) -> io::Result<()> {
|
||||
unsafe { ret(c::setpriority(c::PRIO_USER, uid.as_raw() as _, priority)) }
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn setpriority_pgrp(pgid: Option<Pid>, priority: i32) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::setpriority(
|
||||
c::PRIO_PGRP,
|
||||
Pid::as_raw(pgid) as _,
|
||||
priority,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn setpriority_process(pid: Option<Pid>, priority: i32) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::setpriority(
|
||||
c::PRIO_PROCESS,
|
||||
Pid::as_raw(pid) as _,
|
||||
priority,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn getrlimit(limit: Resource) -> Rlimit {
|
||||
let mut result = MaybeUninit::<libc_rlimit>::uninit();
|
||||
unsafe {
|
||||
ret_infallible(libc_getrlimit(limit as _, result.as_mut_ptr()));
|
||||
rlimit_from_libc(result.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub(crate) fn setrlimit(limit: Resource, new: Rlimit) -> io::Result<()> {
|
||||
let lim = rlimit_to_libc(new)?;
|
||||
unsafe { ret(libc_setrlimit(limit as _, &lim)) }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) fn prlimit(pid: Option<Pid>, limit: Resource, new: Rlimit) -> io::Result<Rlimit> {
|
||||
let lim = rlimit_to_libc(new)?;
|
||||
let mut result = MaybeUninit::<libc_rlimit>::uninit();
|
||||
unsafe {
|
||||
ret(libc_prlimit(
|
||||
Pid::as_raw(pid),
|
||||
limit as _,
|
||||
&lim,
|
||||
result.as_mut_ptr(),
|
||||
))?;
|
||||
Ok(rlimit_from_libc(result.assume_init()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a Rust [`Rlimit`] to a C `libc_rlimit`.
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
fn rlimit_from_libc(lim: libc_rlimit) -> Rlimit {
|
||||
let current = if lim.rlim_cur == LIBC_RLIM_INFINITY {
|
||||
None
|
||||
} else {
|
||||
Some(lim.rlim_cur.try_into().unwrap())
|
||||
};
|
||||
let maximum = if lim.rlim_max == LIBC_RLIM_INFINITY {
|
||||
None
|
||||
} else {
|
||||
Some(lim.rlim_max.try_into().unwrap())
|
||||
};
|
||||
Rlimit { current, maximum }
|
||||
}
|
||||
|
||||
/// Convert a C `libc_rlimit` to a Rust `Rlimit`.
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
fn rlimit_to_libc(lim: Rlimit) -> io::Result<libc_rlimit> {
|
||||
let Rlimit { current, maximum } = lim;
|
||||
let rlim_cur = match current {
|
||||
Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?,
|
||||
None => LIBC_RLIM_INFINITY as _,
|
||||
};
|
||||
let rlim_max = match maximum {
|
||||
Some(r) => r.try_into().map_err(|_e| io::Errno::INVAL)?,
|
||||
None => LIBC_RLIM_INFINITY as _,
|
||||
};
|
||||
Ok(libc_rlimit { rlim_cur, rlim_max })
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn wait(waitopts: WaitOptions) -> io::Result<Option<(Pid, WaitStatus)>> {
|
||||
_waitpid(!0, waitopts)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn waitpid(
|
||||
pid: Option<Pid>,
|
||||
waitopts: WaitOptions,
|
||||
) -> io::Result<Option<(Pid, WaitStatus)>> {
|
||||
_waitpid(Pid::as_raw(pid), waitopts)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn _waitpid(
|
||||
pid: RawPid,
|
||||
waitopts: WaitOptions,
|
||||
) -> io::Result<Option<(Pid, WaitStatus)>> {
|
||||
unsafe {
|
||||
let mut status: c::c_int = 0;
|
||||
let pid = ret_c_int(c::waitpid(pid as _, &mut status, waitopts.bits() as _))?;
|
||||
Ok(RawNonZeroPid::new(pid).map(|non_zero| {
|
||||
(
|
||||
Pid::from_raw_nonzero(non_zero),
|
||||
WaitStatus::new(status as _),
|
||||
)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn exit_group(code: c::c_int) -> ! {
|
||||
// `_exit` and `_Exit` are the same; it's just a matter of which ones
|
||||
// the libc bindings expose.
|
||||
#[cfg(any(target_os = "wasi", target_os = "solid"))]
|
||||
unsafe {
|
||||
c::_Exit(code)
|
||||
}
|
||||
#[cfg(unix)]
|
||||
unsafe {
|
||||
c::_exit(code)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn setsid() -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pid = ret_c_int(c::setsid())?;
|
||||
debug_assert_ne!(pid, 0);
|
||||
Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn kill_process(pid: Pid, sig: Signal) -> io::Result<()> {
|
||||
unsafe { ret(c::kill(pid.as_raw_nonzero().get(), sig as i32)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn kill_process_group(pid: Pid, sig: Signal) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::kill(
|
||||
pid.as_raw_nonzero().get().wrapping_neg(),
|
||||
sig as i32,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn kill_current_process_group(sig: Signal) -> io::Result<()> {
|
||||
unsafe { ret(c::kill(0, sig as i32)) }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) unsafe fn prctl(
|
||||
option: c::c_int,
|
||||
arg2: *mut c::c_void,
|
||||
arg3: *mut c::c_void,
|
||||
arg4: *mut c::c_void,
|
||||
arg5: *mut c::c_void,
|
||||
) -> io::Result<c::c_int> {
|
||||
ret_c_int(c::prctl(option, arg2, arg3, arg4, arg5))
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
|
||||
#[inline]
|
||||
pub(crate) unsafe fn procctl(
|
||||
idtype: c::idtype_t,
|
||||
id: c::id_t,
|
||||
option: c::c_int,
|
||||
data: *mut c::c_void,
|
||||
) -> io::Result<()> {
|
||||
ret(c::procctl(idtype, id, option, data))
|
||||
}
|
||||
414
vendor/rustix/src/backend/libc/process/types.rs
vendored
Normal file
414
vendor/rustix/src/backend/libc/process/types.rs
vendored
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
use super::super::c;
|
||||
|
||||
/// A command for use with [`membarrier`] and [`membarrier_cpu`].
|
||||
///
|
||||
/// For `MEMBARRIER_CMD_QUERY`, see [`membarrier_query`].
|
||||
///
|
||||
/// [`membarrier`]: crate::process::membarrier
|
||||
/// [`membarrier_cpu`]: crate::process::membarrier_cpu
|
||||
/// [`membarrier_query`]: crate::process::membarrier_query
|
||||
// TODO: These are not yet exposed through libc, so we define the
|
||||
// constants ourselves.
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum MembarrierCommand {
|
||||
/// `MEMBARRIER_CMD_GLOBAL`
|
||||
#[doc(alias = "Shared")]
|
||||
#[doc(alias = "MEMBARRIER_CMD_SHARED")]
|
||||
Global = 1,
|
||||
/// `MEMBARRIER_CMD_GLOBAL_EXPEDITED`
|
||||
GlobalExpedited = 2,
|
||||
/// `MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED`
|
||||
RegisterGlobalExpedited = 4,
|
||||
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED`
|
||||
PrivateExpedited = 8,
|
||||
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED`
|
||||
RegisterPrivateExpedited = 16,
|
||||
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE`
|
||||
PrivateExpeditedSyncCore = 32,
|
||||
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE`
|
||||
RegisterPrivateExpeditedSyncCore = 64,
|
||||
/// `MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
|
||||
PrivateExpeditedRseq = 128,
|
||||
/// `MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ` (since Linux 5.10)
|
||||
RegisterPrivateExpeditedRseq = 256,
|
||||
}
|
||||
|
||||
/// A resource value for use with [`getrlimit`], [`setrlimit`], and
|
||||
/// [`prlimit`].
|
||||
///
|
||||
/// [`getrlimit`]: crate::process::getrlimit
|
||||
/// [`setrlimit`]: crate::process::setrlimit
|
||||
/// [`prlimit`]: crate::process::prlimit
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "redox", target_os = "wasi")))]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
pub enum Resource {
|
||||
/// `RLIMIT_CPU`
|
||||
Cpu = c::RLIMIT_CPU as c::c_int,
|
||||
/// `RLIMIT_FSIZE`
|
||||
Fsize = c::RLIMIT_FSIZE as c::c_int,
|
||||
/// `RLIMIT_DATA`
|
||||
Data = c::RLIMIT_DATA as c::c_int,
|
||||
/// `RLIMIT_STACK`
|
||||
Stack = c::RLIMIT_STACK as c::c_int,
|
||||
/// `RLIMIT_CORE`
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
Core = c::RLIMIT_CORE as c::c_int,
|
||||
/// `RLIMIT_RSS`
|
||||
#[cfg(not(any(
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
Rss = c::RLIMIT_RSS as c::c_int,
|
||||
/// `RLIMIT_NPROC`
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))]
|
||||
Nproc = c::RLIMIT_NPROC as c::c_int,
|
||||
/// `RLIMIT_NOFILE`
|
||||
Nofile = c::RLIMIT_NOFILE as c::c_int,
|
||||
/// `RLIMIT_MEMLOCK`
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "solaris"
|
||||
)))]
|
||||
Memlock = c::RLIMIT_MEMLOCK as c::c_int,
|
||||
/// `RLIMIT_AS`
|
||||
#[cfg(not(target_os = "openbsd"))]
|
||||
As = c::RLIMIT_AS as c::c_int,
|
||||
/// `RLIMIT_LOCKS`
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
Locks = c::RLIMIT_LOCKS as c::c_int,
|
||||
/// `RLIMIT_SIGPENDING`
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
Sigpending = c::RLIMIT_SIGPENDING as c::c_int,
|
||||
/// `RLIMIT_MSGQUEUE`
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
Msgqueue = c::RLIMIT_MSGQUEUE as c::c_int,
|
||||
/// `RLIMIT_NICE`
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
Nice = c::RLIMIT_NICE as c::c_int,
|
||||
/// `RLIMIT_RTPRIO`
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
Rtprio = c::RLIMIT_RTPRIO as c::c_int,
|
||||
/// `RLIMIT_RTTIME`
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
Rttime = c::RLIMIT_RTTIME as c::c_int,
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
impl Resource {
|
||||
/// `RLIMIT_RSS`
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const Rss: Self = Self::As;
|
||||
}
|
||||
|
||||
/// A signal number for use with [`kill_process`], [`kill_process_group`],
|
||||
/// and [`kill_current_process_group`].
|
||||
///
|
||||
/// [`kill_process`]: crate::process::kill_process
|
||||
/// [`kill_process_group`]: crate::process::kill_process_group
|
||||
/// [`kill_current_process_group`]: crate::process::kill_current_process_group
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[repr(i32)]
|
||||
pub enum Signal {
|
||||
/// `SIGHUP`
|
||||
Hup = c::SIGHUP,
|
||||
/// `SIGINT`
|
||||
Int = c::SIGINT,
|
||||
/// `SIGQUIT`
|
||||
Quit = c::SIGQUIT,
|
||||
/// `SIGILL`
|
||||
Ill = c::SIGILL,
|
||||
/// `SIGTRAP`
|
||||
Trap = c::SIGTRAP,
|
||||
/// `SIGABRT`, aka `SIGIOT`
|
||||
#[doc(alias = "Iot")]
|
||||
#[doc(alias = "Abrt")]
|
||||
Abort = c::SIGABRT,
|
||||
/// `SIGBUS`
|
||||
Bus = c::SIGBUS,
|
||||
/// `SIGFPE`
|
||||
Fpe = c::SIGFPE,
|
||||
/// `SIGKILL`
|
||||
Kill = c::SIGKILL,
|
||||
/// `SIGUSR1`
|
||||
Usr1 = c::SIGUSR1,
|
||||
/// `SIGSEGV`
|
||||
Segv = c::SIGSEGV,
|
||||
/// `SIGUSR2`
|
||||
Usr2 = c::SIGUSR2,
|
||||
/// `SIGPIPE`
|
||||
Pipe = c::SIGPIPE,
|
||||
/// `SIGALRM`
|
||||
#[doc(alias = "Alrm")]
|
||||
Alarm = c::SIGALRM,
|
||||
/// `SIGTERM`
|
||||
Term = c::SIGTERM,
|
||||
/// `SIGSTKFLT`
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
all(
|
||||
any(target_os = "android", target_os = "linux"),
|
||||
any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
),
|
||||
)
|
||||
)))]
|
||||
Stkflt = c::SIGSTKFLT,
|
||||
/// `SIGCHLD`
|
||||
#[doc(alias = "Chld")]
|
||||
Child = c::SIGCHLD,
|
||||
/// `SIGCONT`
|
||||
Cont = c::SIGCONT,
|
||||
/// `SIGSTOP`
|
||||
Stop = c::SIGSTOP,
|
||||
/// `SIGTSTP`
|
||||
Tstp = c::SIGTSTP,
|
||||
/// `SIGTTIN`
|
||||
Ttin = c::SIGTTIN,
|
||||
/// `SIGTTOU`
|
||||
Ttou = c::SIGTTOU,
|
||||
/// `SIGURG`
|
||||
Urg = c::SIGURG,
|
||||
/// `SIGXCPU`
|
||||
Xcpu = c::SIGXCPU,
|
||||
/// `SIGXFSZ`
|
||||
Xfsz = c::SIGXFSZ,
|
||||
/// `SIGVTALRM`
|
||||
#[doc(alias = "Vtalrm")]
|
||||
Vtalarm = c::SIGVTALRM,
|
||||
/// `SIGPROF`
|
||||
Prof = c::SIGPROF,
|
||||
/// `SIGWINCH`
|
||||
Winch = c::SIGWINCH,
|
||||
/// `SIGIO`, aka `SIGPOLL`
|
||||
#[doc(alias = "Poll")]
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
Io = c::SIGIO,
|
||||
/// `SIGPWR`
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
#[doc(alias = "Pwr")]
|
||||
Power = c::SIGPWR,
|
||||
/// `SIGSYS`, aka `SIGUNUSED`
|
||||
#[doc(alias = "Unused")]
|
||||
Sys = c::SIGSYS,
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
impl Signal {
|
||||
/// Convert a raw signal number into a `Signal`, if possible.
|
||||
pub fn from_raw(sig: i32) -> Option<Self> {
|
||||
match sig as _ {
|
||||
c::SIGHUP => Some(Self::Hup),
|
||||
c::SIGINT => Some(Self::Int),
|
||||
c::SIGQUIT => Some(Self::Quit),
|
||||
c::SIGILL => Some(Self::Ill),
|
||||
c::SIGTRAP => Some(Self::Trap),
|
||||
c::SIGABRT => Some(Self::Abort),
|
||||
c::SIGBUS => Some(Self::Bus),
|
||||
c::SIGFPE => Some(Self::Fpe),
|
||||
c::SIGKILL => Some(Self::Kill),
|
||||
c::SIGUSR1 => Some(Self::Usr1),
|
||||
c::SIGSEGV => Some(Self::Segv),
|
||||
c::SIGUSR2 => Some(Self::Usr2),
|
||||
c::SIGPIPE => Some(Self::Pipe),
|
||||
c::SIGALRM => Some(Self::Alarm),
|
||||
c::SIGTERM => Some(Self::Term),
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
all(
|
||||
any(target_os = "android", target_os = "linux"),
|
||||
any(
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64",
|
||||
target_arch = "sparc",
|
||||
target_arch = "sparc64"
|
||||
),
|
||||
)
|
||||
)))]
|
||||
c::SIGSTKFLT => Some(Self::Stkflt),
|
||||
c::SIGCHLD => Some(Self::Child),
|
||||
c::SIGCONT => Some(Self::Cont),
|
||||
c::SIGSTOP => Some(Self::Stop),
|
||||
c::SIGTSTP => Some(Self::Tstp),
|
||||
c::SIGTTIN => Some(Self::Ttin),
|
||||
c::SIGTTOU => Some(Self::Ttou),
|
||||
c::SIGURG => Some(Self::Urg),
|
||||
c::SIGXCPU => Some(Self::Xcpu),
|
||||
c::SIGXFSZ => Some(Self::Xfsz),
|
||||
c::SIGVTALRM => Some(Self::Vtalarm),
|
||||
c::SIGPROF => Some(Self::Prof),
|
||||
c::SIGWINCH => Some(Self::Winch),
|
||||
#[cfg(not(target_os = "haiku"))]
|
||||
c::SIGIO => Some(Self::Io),
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
)))]
|
||||
c::SIGPWR => Some(Self::Power),
|
||||
c::SIGSYS => Some(Self::Sys),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const EXIT_SUCCESS: c::c_int = c::EXIT_SUCCESS;
|
||||
pub const EXIT_FAILURE: c::c_int = c::EXIT_FAILURE;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub const EXIT_SIGNALED_SIGABRT: c::c_int = 128 + c::SIGABRT;
|
||||
|
||||
/// A process identifier as a raw integer.
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub type RawPid = c::pid_t;
|
||||
/// A non-zero process identifier as a raw non-zero integer.
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub type RawNonZeroPid = core::num::NonZeroI32;
|
||||
/// A group identifier as a raw integer.
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub type RawGid = c::gid_t;
|
||||
/// A user identifier as a raw integer.
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub type RawUid = c::uid_t;
|
||||
/// A CPU identifier as a raw integer.
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
pub type RawCpuid = u32;
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub type RawId = c::id_t;
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) type RawUname = c::utsname;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
))]
|
||||
pub(crate) type RawCpuSet = c::cpu_set_t;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "linux",
|
||||
))]
|
||||
#[inline]
|
||||
pub(crate) fn raw_cpu_set_new() -> RawCpuSet {
|
||||
let mut set = unsafe { core::mem::zeroed() };
|
||||
super::cpu_set::CPU_ZERO(&mut set);
|
||||
set
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
pub(crate) const CPU_SETSIZE: usize = c::CPU_SETSIZE as usize;
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub(crate) const CPU_SETSIZE: usize = 256;
|
||||
6
vendor/rustix/src/backend/libc/process/wait.rs
vendored
Normal file
6
vendor/rustix/src/backend/libc/process/wait.rs
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
use super::super::c;
|
||||
|
||||
pub(crate) use c::{
|
||||
WCONTINUED, WEXITSTATUS, WIFCONTINUED, WIFEXITED, WIFSIGNALED, WIFSTOPPED, WNOHANG, WSTOPSIG,
|
||||
WTERMSIG, WUNTRACED,
|
||||
};
|
||||
2
vendor/rustix/src/backend/libc/rand/mod.rs
vendored
Normal file
2
vendor/rustix/src/backend/libc/rand/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
16
vendor/rustix/src/backend/libc/rand/syscalls.rs
vendored
Normal file
16
vendor/rustix/src/backend/libc/rand/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//! libc syscalls supporting `rustix::rand`.
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use {super::super::c, super::super::conv::ret_ssize_t, crate::io, crate::rand::GetRandomFlags};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub(crate) fn getrandom(buf: &mut [u8], flags: GetRandomFlags) -> io::Result<usize> {
|
||||
// `getrandom` wasn't supported in glibc until 2.25.
|
||||
weak_or_syscall! {
|
||||
fn getrandom(buf: *mut c::c_void, buflen: c::size_t, flags: c::c_uint) via SYS_getrandom -> c::ssize_t
|
||||
}
|
||||
|
||||
let nread =
|
||||
unsafe { ret_ssize_t(getrandom(buf.as_mut_ptr().cast(), buf.len(), flags.bits()))? };
|
||||
Ok(nread as usize)
|
||||
}
|
||||
19
vendor/rustix/src/backend/libc/rand/types.rs
vendored
Normal file
19
vendor/rustix/src/backend/libc/rand/types.rs
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#[cfg(target_os = "linux")]
|
||||
use super::super::c;
|
||||
#[cfg(target_os = "linux")]
|
||||
use bitflags::bitflags;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
bitflags! {
|
||||
/// `GRND_*` flags for use with [`getrandom`].
|
||||
///
|
||||
/// [`getrandom`]: crate::rand::getrandom
|
||||
pub struct GetRandomFlags: u32 {
|
||||
/// `GRND_RANDOM`
|
||||
const RANDOM = c::GRND_RANDOM;
|
||||
/// `GRND_NONBLOCK`
|
||||
const NONBLOCK = c::GRND_NONBLOCK;
|
||||
/// `GRND_INSECURE`
|
||||
const INSECURE = c::GRND_INSECURE;
|
||||
}
|
||||
}
|
||||
3
vendor/rustix/src/backend/libc/termios/mod.rs
vendored
Normal file
3
vendor/rustix/src/backend/libc/termios/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
pub(crate) mod syscalls;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) mod types;
|
||||
163
vendor/rustix/src/backend/libc/termios/syscalls.rs
vendored
Normal file
163
vendor/rustix/src/backend/libc/termios/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
//! libc syscalls supporting `rustix::termios`.
|
||||
//!
|
||||
//! # Safety
|
||||
//!
|
||||
//! See the `rustix::backend::syscalls` module documentation for details.
|
||||
|
||||
use super::super::c;
|
||||
use super::super::conv::{borrowed_fd, ret, ret_pid_t};
|
||||
use crate::fd::BorrowedFd;
|
||||
#[cfg(feature = "procfs")]
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
use crate::ffi::CStr;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::io;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::process::{Pid, RawNonZeroPid};
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::termios::{Action, OptionalActions, QueueSelector, Speed, Termios, Winsize};
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcgetattr(fd: BorrowedFd<'_>) -> io::Result<Termios> {
|
||||
let mut result = MaybeUninit::<Termios>::uninit();
|
||||
unsafe {
|
||||
ret(c::tcgetattr(borrowed_fd(fd), result.as_mut_ptr()))?;
|
||||
Ok(result.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcgetpgrp(fd: BorrowedFd<'_>) -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pid = ret_pid_t(c::tcgetpgrp(borrowed_fd(fd)))?;
|
||||
debug_assert_ne!(pid, 0);
|
||||
Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcsetpgrp(fd: BorrowedFd<'_>, pid: Pid) -> io::Result<()> {
|
||||
unsafe { ret(c::tcsetpgrp(borrowed_fd(fd), pid.as_raw_nonzero().get())) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcsetattr(
|
||||
fd: BorrowedFd,
|
||||
optional_actions: OptionalActions,
|
||||
termios: &Termios,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
ret(c::tcsetattr(
|
||||
borrowed_fd(fd),
|
||||
optional_actions as _,
|
||||
termios,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcsendbreak(fd: BorrowedFd) -> io::Result<()> {
|
||||
unsafe { ret(c::tcsendbreak(borrowed_fd(fd), 0)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcdrain(fd: BorrowedFd) -> io::Result<()> {
|
||||
unsafe { ret(c::tcdrain(borrowed_fd(fd))) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcflush(fd: BorrowedFd, queue_selector: QueueSelector) -> io::Result<()> {
|
||||
unsafe { ret(c::tcflush(borrowed_fd(fd), queue_selector as _)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcflow(fd: BorrowedFd, action: Action) -> io::Result<()> {
|
||||
unsafe { ret(c::tcflow(borrowed_fd(fd), action as _)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcgetsid(fd: BorrowedFd) -> io::Result<Pid> {
|
||||
unsafe {
|
||||
let pid = ret_pid_t(c::tcgetsid(borrowed_fd(fd)))?;
|
||||
debug_assert_ne!(pid, 0);
|
||||
Ok(Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(pid)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcsetwinsize(fd: BorrowedFd, winsize: Winsize) -> io::Result<()> {
|
||||
unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCSWINSZ, &winsize)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) fn tcgetwinsize(fd: BorrowedFd) -> io::Result<Winsize> {
|
||||
unsafe {
|
||||
let mut buf = MaybeUninit::<Winsize>::uninit();
|
||||
ret(c::ioctl(
|
||||
borrowed_fd(fd),
|
||||
c::TIOCGWINSZ.into(),
|
||||
buf.as_mut_ptr(),
|
||||
))?;
|
||||
Ok(buf.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn cfgetospeed(termios: &Termios) -> Speed {
|
||||
unsafe { c::cfgetospeed(termios) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn cfgetispeed(termios: &Termios) -> Speed {
|
||||
unsafe { c::cfgetispeed(termios) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn cfmakeraw(termios: &mut Termios) {
|
||||
unsafe { c::cfmakeraw(termios) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn cfsetospeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
|
||||
unsafe { ret(c::cfsetospeed(termios, speed)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn cfsetispeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
|
||||
unsafe { ret(c::cfsetispeed(termios, speed)) }
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn cfsetspeed(termios: &mut Termios, speed: Speed) -> io::Result<()> {
|
||||
unsafe { ret(c::cfsetspeed(termios, speed)) }
|
||||
}
|
||||
|
||||
pub(crate) fn isatty(fd: BorrowedFd<'_>) -> bool {
|
||||
// Use the return value of `isatty` alone. We don't check `errno` because
|
||||
// we return `bool` rather than `io::Result<bool>`, because we assume
|
||||
// `BorrrowedFd` protects us from `EBADF`, and any other reasonably
|
||||
// anticipated errno value would end up interpreted as "assume it's not a
|
||||
// terminal" anyway.
|
||||
unsafe { c::isatty(borrowed_fd(fd)) != 0 }
|
||||
}
|
||||
|
||||
#[cfg(feature = "procfs")]
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
pub(crate) fn ttyname(dirfd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
// `ttyname_r` returns its error status rather than using `errno`.
|
||||
match c::ttyname_r(borrowed_fd(dirfd), buf.as_mut_ptr().cast(), buf.len()) {
|
||||
0 => Ok(CStr::from_ptr(buf.as_ptr().cast()).to_bytes().len()),
|
||||
err => Err(io::Errno::from_raw_os_error(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
1046
vendor/rustix/src/backend/libc/termios/types.rs
vendored
Normal file
1046
vendor/rustix/src/backend/libc/termios/types.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
2
vendor/rustix/src/backend/libc/thread/mod.rs
vendored
Normal file
2
vendor/rustix/src/backend/libc/thread/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
301
vendor/rustix/src/backend/libc/thread/syscalls.rs
vendored
Normal file
301
vendor/rustix/src/backend/libc/thread/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
//! libc syscalls supporting `rustix::thread`.
|
||||
|
||||
use super::super::c;
|
||||
use super::super::conv::ret;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use super::super::conv::{borrowed_fd, ret_c_int};
|
||||
use super::super::time::types::LibcTimespec;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use crate::fd::BorrowedFd;
|
||||
use crate::io;
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
use crate::process::{Pid, RawNonZeroPid};
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
use crate::thread::{NanosleepRelativeResult, Timespec};
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
use {crate::thread::ClockId, core::ptr::null_mut};
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
weak!(fn __clock_nanosleep_time64(c::clockid_t, c::c_int, *const LibcTimespec, *mut LibcTimespec) -> c::c_int);
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
weak!(fn __nanosleep64(*const LibcTimespec, *mut LibcTimespec) -> c::c_int);
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
|
||||
let mut remain = MaybeUninit::<LibcTimespec>::uninit();
|
||||
let flags = 0;
|
||||
|
||||
// 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe by
|
||||
// default.
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
unsafe {
|
||||
if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
|
||||
match libc_clock_nanosleep(
|
||||
id as c::clockid_t,
|
||||
flags,
|
||||
&request.clone().into(),
|
||||
remain.as_mut_ptr(),
|
||||
) {
|
||||
0 => NanosleepRelativeResult::Ok,
|
||||
err if err == io::Errno::INTR.0 => {
|
||||
NanosleepRelativeResult::Interrupted(remain.assume_init().into())
|
||||
}
|
||||
err => NanosleepRelativeResult::Err(io::Errno(err)),
|
||||
}
|
||||
} else {
|
||||
clock_nanosleep_relative_old(id, request)
|
||||
}
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `clock_nanosleep`.
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
unsafe {
|
||||
match c::clock_nanosleep(id as c::clockid_t, flags, request, remain.as_mut_ptr()) {
|
||||
0 => NanosleepRelativeResult::Ok,
|
||||
err if err == io::Errno::INTR.0 => {
|
||||
NanosleepRelativeResult::Interrupted(remain.assume_init())
|
||||
}
|
||||
err => NanosleepRelativeResult::Err(io::Errno(err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
unsafe fn clock_nanosleep_relative_old(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
|
||||
use core::convert::TryInto;
|
||||
let tv_sec = match request.tv_sec.try_into() {
|
||||
Ok(tv_sec) => tv_sec,
|
||||
Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW),
|
||||
};
|
||||
let tv_nsec = match request.tv_nsec.try_into() {
|
||||
Ok(tv_nsec) => tv_nsec,
|
||||
Err(_) => return NanosleepRelativeResult::Err(io::Errno::INVAL),
|
||||
};
|
||||
let old_request = c::timespec { tv_sec, tv_nsec };
|
||||
let mut old_remain = MaybeUninit::<c::timespec>::uninit();
|
||||
let flags = 0;
|
||||
|
||||
match c::clock_nanosleep(
|
||||
id as c::clockid_t,
|
||||
flags,
|
||||
&old_request,
|
||||
old_remain.as_mut_ptr(),
|
||||
) {
|
||||
0 => NanosleepRelativeResult::Ok,
|
||||
err if err == io::Errno::INTR.0 => {
|
||||
let old_remain = old_remain.assume_init();
|
||||
let remain = Timespec {
|
||||
tv_sec: old_remain.tv_sec.into(),
|
||||
tv_nsec: old_remain.tv_nsec.into(),
|
||||
};
|
||||
NanosleepRelativeResult::Interrupted(remain)
|
||||
}
|
||||
err => NanosleepRelativeResult::Err(io::Errno(err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "emscripten",
|
||||
target_os = "freebsd", // FreeBSD 12 has clock_nanosleep, but libc targets FreeBSD 11.
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
#[inline]
|
||||
pub(crate) fn clock_nanosleep_absolute(id: ClockId, request: &Timespec) -> io::Result<()> {
|
||||
let flags = c::TIMER_ABSTIME;
|
||||
|
||||
// 32-bit gnu version: libc has `clock_nanosleep` but it is not y2038 safe by
|
||||
// default.
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
{
|
||||
if let Some(libc_clock_nanosleep) = __clock_nanosleep_time64.get() {
|
||||
match unsafe {
|
||||
libc_clock_nanosleep(
|
||||
id as c::clockid_t,
|
||||
flags,
|
||||
&request.clone().into(),
|
||||
null_mut(),
|
||||
)
|
||||
} {
|
||||
0 => Ok(()),
|
||||
err => Err(io::Errno(err)),
|
||||
}
|
||||
} else {
|
||||
clock_nanosleep_absolute_old(id, request)
|
||||
}
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `clock_nanosleep`.
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
match unsafe { c::clock_nanosleep(id as c::clockid_t, flags, request, null_mut()) } {
|
||||
0 => Ok(()),
|
||||
err => Err(io::Errno(err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
fn clock_nanosleep_absolute_old(id: ClockId, request: &Timespec) -> io::Result<()> {
|
||||
use core::convert::TryInto;
|
||||
|
||||
let flags = c::TIMER_ABSTIME;
|
||||
|
||||
let old_request = c::timespec {
|
||||
tv_sec: request.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?,
|
||||
tv_nsec: request.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
|
||||
};
|
||||
match unsafe { c::clock_nanosleep(id as c::clockid_t, flags, &old_request, null_mut()) } {
|
||||
0 => Ok(()),
|
||||
err => Err(io::Errno(err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
#[inline]
|
||||
pub(crate) fn nanosleep(request: &Timespec) -> NanosleepRelativeResult {
|
||||
let mut remain = MaybeUninit::<LibcTimespec>::uninit();
|
||||
|
||||
// 32-bit gnu version: libc has `nanosleep` but it is not y2038 safe by
|
||||
// default.
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
unsafe {
|
||||
if let Some(libc_nanosleep) = __nanosleep64.get() {
|
||||
match ret(libc_nanosleep(&request.clone().into(), remain.as_mut_ptr())) {
|
||||
Ok(()) => NanosleepRelativeResult::Ok,
|
||||
Err(io::Errno::INTR) => {
|
||||
NanosleepRelativeResult::Interrupted(remain.assume_init().into())
|
||||
}
|
||||
Err(err) => NanosleepRelativeResult::Err(err),
|
||||
}
|
||||
} else {
|
||||
nanosleep_old(request)
|
||||
}
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `nanosleep`.
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
unsafe {
|
||||
match ret(c::nanosleep(request, remain.as_mut_ptr())) {
|
||||
Ok(()) => NanosleepRelativeResult::Ok,
|
||||
Err(io::Errno::INTR) => NanosleepRelativeResult::Interrupted(remain.assume_init()),
|
||||
Err(err) => NanosleepRelativeResult::Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
unsafe fn nanosleep_old(request: &Timespec) -> NanosleepRelativeResult {
|
||||
use core::convert::TryInto;
|
||||
let tv_sec = match request.tv_sec.try_into() {
|
||||
Ok(tv_sec) => tv_sec,
|
||||
Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW),
|
||||
};
|
||||
let tv_nsec = match request.tv_nsec.try_into() {
|
||||
Ok(tv_nsec) => tv_nsec,
|
||||
Err(_) => return NanosleepRelativeResult::Err(io::Errno::INVAL),
|
||||
};
|
||||
let old_request = c::timespec { tv_sec, tv_nsec };
|
||||
let mut old_remain = MaybeUninit::<c::timespec>::uninit();
|
||||
|
||||
match ret(c::nanosleep(&old_request, old_remain.as_mut_ptr())) {
|
||||
Ok(()) => NanosleepRelativeResult::Ok,
|
||||
Err(io::Errno::INTR) => {
|
||||
let old_remain = old_remain.assume_init();
|
||||
let remain = Timespec {
|
||||
tv_sec: old_remain.tv_sec.into(),
|
||||
tv_nsec: old_remain.tv_nsec.into(),
|
||||
};
|
||||
NanosleepRelativeResult::Interrupted(remain)
|
||||
}
|
||||
Err(err) => NanosleepRelativeResult::Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn gettid() -> Pid {
|
||||
// `gettid` wasn't supported in glibc until 2.30, and musl until 1.2.2,
|
||||
// so use `syscall`.
|
||||
// <https://sourceware.org/bugzilla/show_bug.cgi?id=6399#c62>
|
||||
weak_or_syscall! {
|
||||
fn gettid() via SYS_gettid -> c::pid_t
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let tid = gettid();
|
||||
debug_assert_ne!(tid, 0);
|
||||
Pid::from_raw_nonzero(RawNonZeroPid::new_unchecked(tid))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) fn setns(fd: BorrowedFd, nstype: c::c_int) -> io::Result<c::c_int> {
|
||||
unsafe { ret_c_int(c::setns(borrowed_fd(fd), nstype)) }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[inline]
|
||||
pub(crate) fn unshare(flags: crate::thread::UnshareFlags) -> io::Result<()> {
|
||||
unsafe { ret(c::unshare(flags.bits() as i32)) }
|
||||
}
|
||||
3
vendor/rustix/src/backend/libc/time/mod.rs
vendored
Normal file
3
vendor/rustix/src/backend/libc/time/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#[cfg(not(windows))]
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
414
vendor/rustix/src/backend/libc/time/syscalls.rs
vendored
Normal file
414
vendor/rustix/src/backend/libc/time/syscalls.rs
vendored
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
//! libc syscalls supporting `rustix::time`.
|
||||
|
||||
use super::super::c;
|
||||
use super::super::conv::ret;
|
||||
#[cfg(feature = "time")]
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
use super::super::time::types::LibcItimerspec;
|
||||
use super::super::time::types::LibcTimespec;
|
||||
use super::types::Timespec;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use super::types::{ClockId, DynamicClockId};
|
||||
use crate::io;
|
||||
use core::mem::MaybeUninit;
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(feature = "time")]
|
||||
use {
|
||||
super::super::conv::{borrowed_fd, ret_owned_fd},
|
||||
crate::fd::{BorrowedFd, OwnedFd},
|
||||
crate::time::{Itimerspec, TimerfdClockId, TimerfdFlags, TimerfdTimerFlags},
|
||||
};
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
weak!(fn __clock_gettime64(c::clockid_t, *mut LibcTimespec) -> c::c_int);
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
weak!(fn __clock_getres64(c::clockid_t, *mut LibcTimespec) -> c::c_int);
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[cfg(feature = "time")]
|
||||
weak!(fn __timerfd_gettime64(c::c_int, *mut LibcItimerspec) -> c::c_int);
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[cfg(feature = "time")]
|
||||
weak!(fn __timerfd_settime64(c::c_int, c::c_int, *const LibcItimerspec, *mut LibcItimerspec) -> c::c_int);
|
||||
|
||||
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn clock_getres(id: ClockId) -> Timespec {
|
||||
let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
|
||||
|
||||
// 32-bit gnu version: libc has `clock_getres` but it is not y2038 safe by
|
||||
// default.
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
unsafe {
|
||||
if let Some(libc_clock_getres) = __clock_getres64.get() {
|
||||
ret(libc_clock_getres(id as c::clockid_t, timespec.as_mut_ptr())).unwrap();
|
||||
timespec.assume_init().into()
|
||||
} else {
|
||||
clock_getres_old(id)
|
||||
}
|
||||
}
|
||||
|
||||
// Main version: libc is y2038 safe and has `clock_getres`.
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
unsafe {
|
||||
let _ = c::clock_getres(id as c::clockid_t, timespec.as_mut_ptr());
|
||||
timespec.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[must_use]
|
||||
unsafe fn clock_getres_old(id: ClockId) -> Timespec {
|
||||
let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
|
||||
ret(c::clock_getres(
|
||||
id as c::clockid_t,
|
||||
old_timespec.as_mut_ptr(),
|
||||
))
|
||||
.unwrap();
|
||||
let old_timespec = old_timespec.assume_init();
|
||||
Timespec {
|
||||
tv_sec: old_timespec.tv_sec.into(),
|
||||
tv_nsec: old_timespec.tv_nsec.into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn clock_gettime(id: ClockId) -> Timespec {
|
||||
let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
unsafe {
|
||||
if let Some(libc_clock_gettime) = __clock_gettime64.get() {
|
||||
ret(libc_clock_gettime(
|
||||
id as c::clockid_t,
|
||||
timespec.as_mut_ptr(),
|
||||
))
|
||||
.unwrap();
|
||||
timespec.assume_init().into()
|
||||
} else {
|
||||
clock_gettime_old(id)
|
||||
}
|
||||
}
|
||||
|
||||
// Use `unwrap()` here because `clock_getres` can fail if the clock itself
|
||||
// overflows a number of seconds, but if that happens, the monotonic clocks
|
||||
// can't maintain their invariants, or the realtime clocks aren't properly
|
||||
// configured.
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
unsafe {
|
||||
ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr())).unwrap();
|
||||
timespec.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[must_use]
|
||||
unsafe fn clock_gettime_old(id: ClockId) -> Timespec {
|
||||
let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
|
||||
ret(c::clock_gettime(
|
||||
id as c::clockid_t,
|
||||
old_timespec.as_mut_ptr(),
|
||||
))
|
||||
.unwrap();
|
||||
let old_timespec = old_timespec.assume_init();
|
||||
Timespec {
|
||||
tv_sec: old_timespec.tv_sec.into(),
|
||||
tv_nsec: old_timespec.tv_nsec.into(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[inline]
|
||||
pub(crate) fn clock_gettime_dynamic(id: DynamicClockId<'_>) -> io::Result<Timespec> {
|
||||
let mut timespec = MaybeUninit::<LibcTimespec>::uninit();
|
||||
unsafe {
|
||||
let id: c::clockid_t = match id {
|
||||
DynamicClockId::Known(id) => id as c::clockid_t,
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
DynamicClockId::Dynamic(fd) => {
|
||||
use crate::fd::AsRawFd;
|
||||
const CLOCKFD: i32 = 3;
|
||||
(!fd.as_raw_fd() << 3) | CLOCKFD
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
|
||||
DynamicClockId::Dynamic(_fd) => {
|
||||
// Dynamic clocks are not supported on this platform.
|
||||
return Err(io::Errno::INVAL);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
DynamicClockId::RealtimeAlarm => c::CLOCK_REALTIME_ALARM,
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
DynamicClockId::Tai => c::CLOCK_TAI,
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
DynamicClockId::Boottime => c::CLOCK_BOOTTIME,
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
DynamicClockId::BoottimeAlarm => c::CLOCK_BOOTTIME_ALARM,
|
||||
};
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
{
|
||||
if let Some(libc_clock_gettime) = __clock_gettime64.get() {
|
||||
ret(libc_clock_gettime(
|
||||
id as c::clockid_t,
|
||||
timespec.as_mut_ptr(),
|
||||
))?;
|
||||
|
||||
Ok(timespec.assume_init().into())
|
||||
} else {
|
||||
clock_gettime_dynamic_old(id)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
{
|
||||
ret(c::clock_gettime(id as c::clockid_t, timespec.as_mut_ptr()))?;
|
||||
|
||||
Ok(timespec.assume_init())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[inline]
|
||||
unsafe fn clock_gettime_dynamic_old(id: c::clockid_t) -> io::Result<Timespec> {
|
||||
let mut old_timespec = MaybeUninit::<c::timespec>::uninit();
|
||||
|
||||
ret(c::clock_gettime(
|
||||
id as c::clockid_t,
|
||||
old_timespec.as_mut_ptr(),
|
||||
))?;
|
||||
|
||||
let old_timespec = old_timespec.assume_init();
|
||||
Ok(Timespec {
|
||||
tv_sec: old_timespec.tv_sec.into(),
|
||||
tv_nsec: old_timespec.tv_nsec.into(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(feature = "time")]
|
||||
pub(crate) fn timerfd_create(id: TimerfdClockId, flags: TimerfdFlags) -> io::Result<OwnedFd> {
|
||||
unsafe { ret_owned_fd(c::timerfd_create(id as c::clockid_t, flags.bits())) }
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(feature = "time")]
|
||||
pub(crate) fn timerfd_settime(
|
||||
fd: BorrowedFd<'_>,
|
||||
flags: TimerfdTimerFlags,
|
||||
new_value: &Itimerspec,
|
||||
) -> io::Result<Itimerspec> {
|
||||
let mut result = MaybeUninit::<LibcItimerspec>::uninit();
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
unsafe {
|
||||
if let Some(libc_timerfd_settime) = __timerfd_settime64.get() {
|
||||
ret(libc_timerfd_settime(
|
||||
borrowed_fd(fd),
|
||||
flags.bits(),
|
||||
&new_value.clone().into(),
|
||||
result.as_mut_ptr(),
|
||||
))?;
|
||||
Ok(result.assume_init().into())
|
||||
} else {
|
||||
timerfd_settime_old(fd, flags, new_value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
unsafe {
|
||||
ret(c::timerfd_settime(
|
||||
borrowed_fd(fd),
|
||||
flags.bits(),
|
||||
new_value,
|
||||
result.as_mut_ptr(),
|
||||
))?;
|
||||
Ok(result.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[cfg(feature = "time")]
|
||||
unsafe fn timerfd_settime_old(
|
||||
fd: BorrowedFd<'_>,
|
||||
flags: TimerfdTimerFlags,
|
||||
new_value: &Itimerspec,
|
||||
) -> io::Result<Itimerspec> {
|
||||
use core::convert::TryInto;
|
||||
|
||||
let mut old_result = MaybeUninit::<c::itimerspec>::uninit();
|
||||
|
||||
// Convert `new_value` to the old `itimerspec` format.
|
||||
let old_new_value = c::itimerspec {
|
||||
it_interval: c::timespec {
|
||||
tv_sec: new_value
|
||||
.it_interval
|
||||
.tv_sec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
tv_nsec: new_value
|
||||
.it_interval
|
||||
.tv_nsec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::INVAL)?,
|
||||
},
|
||||
it_value: c::timespec {
|
||||
tv_sec: new_value
|
||||
.it_value
|
||||
.tv_sec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
tv_nsec: new_value
|
||||
.it_value
|
||||
.tv_nsec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::INVAL)?,
|
||||
},
|
||||
};
|
||||
|
||||
ret(c::timerfd_settime(
|
||||
borrowed_fd(fd),
|
||||
flags.bits(),
|
||||
&old_new_value,
|
||||
old_result.as_mut_ptr(),
|
||||
))?;
|
||||
|
||||
let old_result = old_result.assume_init();
|
||||
Ok(Itimerspec {
|
||||
it_interval: Timespec {
|
||||
tv_sec: old_result
|
||||
.it_interval
|
||||
.tv_sec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
tv_nsec: old_result.it_interval.tv_nsec as _,
|
||||
},
|
||||
it_value: Timespec {
|
||||
tv_sec: old_result
|
||||
.it_interval
|
||||
.tv_sec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
tv_nsec: old_result.it_interval.tv_nsec as _,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(feature = "time")]
|
||||
pub(crate) fn timerfd_gettime(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
|
||||
let mut result = MaybeUninit::<LibcItimerspec>::uninit();
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
unsafe {
|
||||
if let Some(libc_timerfd_gettime) = __timerfd_gettime64.get() {
|
||||
ret(libc_timerfd_gettime(borrowed_fd(fd), result.as_mut_ptr()))?;
|
||||
Ok(result.assume_init().into())
|
||||
} else {
|
||||
timerfd_gettime_old(fd)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
unsafe {
|
||||
ret(c::timerfd_gettime(borrowed_fd(fd), result.as_mut_ptr()))?;
|
||||
Ok(result.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[cfg(feature = "time")]
|
||||
unsafe fn timerfd_gettime_old(fd: BorrowedFd<'_>) -> io::Result<Itimerspec> {
|
||||
use core::convert::TryInto;
|
||||
|
||||
let mut old_result = MaybeUninit::<c::itimerspec>::uninit();
|
||||
|
||||
ret(c::timerfd_gettime(borrowed_fd(fd), old_result.as_mut_ptr()))?;
|
||||
|
||||
let old_result = old_result.assume_init();
|
||||
Ok(Itimerspec {
|
||||
it_interval: Timespec {
|
||||
tv_sec: old_result
|
||||
.it_interval
|
||||
.tv_sec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
tv_nsec: old_result.it_interval.tv_nsec as _,
|
||||
},
|
||||
it_value: Timespec {
|
||||
tv_sec: old_result
|
||||
.it_interval
|
||||
.tv_sec
|
||||
.try_into()
|
||||
.map_err(|_| io::Errno::OVERFLOW)?,
|
||||
tv_nsec: old_result.it_interval.tv_nsec as _,
|
||||
},
|
||||
})
|
||||
}
|
||||
364
vendor/rustix/src/backend/libc/time/types.rs
vendored
Normal file
364
vendor/rustix/src/backend/libc/time/types.rs
vendored
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
use super::super::c;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::fd::BorrowedFd;
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
use bitflags::bitflags;
|
||||
|
||||
/// `struct timespec`
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
pub type Timespec = c::timespec;
|
||||
|
||||
/// `struct timespec`
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct Timespec {
|
||||
/// Seconds.
|
||||
pub tv_sec: Secs,
|
||||
|
||||
/// Nanoseconds. Must be less than 1_000_000_000.
|
||||
pub tv_nsec: Nsecs,
|
||||
}
|
||||
|
||||
/// A type for the `tv_sec` field of [`Timespec`].
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
#[allow(deprecated)]
|
||||
pub type Secs = c::time_t;
|
||||
|
||||
/// A type for the `tv_sec` field of [`Timespec`].
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
pub type Secs = i64;
|
||||
|
||||
/// A type for the `tv_nsec` field of [`Timespec`].
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
|
||||
pub type Nsecs = i64;
|
||||
|
||||
/// A type for the `tv_nsec` field of [`Timespec`].
|
||||
#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
|
||||
pub type Nsecs = c::c_long;
|
||||
|
||||
/// On most platforms, `LibcTimespec` is just `Timespec`.
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
pub(crate) type LibcTimespec = Timespec;
|
||||
|
||||
/// On 32-bit glibc platforms, `timespec` has anonymous padding fields, which
|
||||
/// Rust doesn't support yet (see `unnamed_fields`), so we define our own
|
||||
/// struct with explicit padding, with bidirectional `From` impls.
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct LibcTimespec {
|
||||
pub(crate) tv_sec: Secs,
|
||||
|
||||
#[cfg(target_endian = "big")]
|
||||
padding: core::mem::MaybeUninit<u32>,
|
||||
|
||||
pub(crate) tv_nsec: Nsecs,
|
||||
|
||||
#[cfg(target_endian = "little")]
|
||||
padding: core::mem::MaybeUninit<u32>,
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
impl From<LibcTimespec> for Timespec {
|
||||
#[inline]
|
||||
fn from(t: LibcTimespec) -> Self {
|
||||
Self {
|
||||
tv_sec: t.tv_sec,
|
||||
tv_nsec: t.tv_nsec,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
impl From<Timespec> for LibcTimespec {
|
||||
#[inline]
|
||||
fn from(t: Timespec) -> Self {
|
||||
Self {
|
||||
tv_sec: t.tv_sec,
|
||||
tv_nsec: t.tv_nsec,
|
||||
padding: core::mem::MaybeUninit::uninit(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `CLOCK_*` constants for use with [`clock_gettime`].
|
||||
///
|
||||
/// These constants are always supported at runtime so `clock_gettime` never
|
||||
/// has to fail with `INVAL` due to an unsupported clock. See
|
||||
/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not
|
||||
/// all of them are always supported.
|
||||
///
|
||||
/// [`clock_gettime`]: crate::time::clock_gettime
|
||||
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "wasi")))]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(not(target_os = "dragonfly"), repr(i32))]
|
||||
#[cfg_attr(target_os = "dragonfly", repr(u64))]
|
||||
#[non_exhaustive]
|
||||
pub enum ClockId {
|
||||
/// `CLOCK_REALTIME`
|
||||
Realtime = c::CLOCK_REALTIME,
|
||||
|
||||
/// `CLOCK_MONOTONIC`
|
||||
Monotonic = c::CLOCK_MONOTONIC,
|
||||
|
||||
/// `CLOCK_PROCESS_CPUTIME_ID`
|
||||
#[cfg(not(any(
|
||||
target_os = "illumos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
ProcessCPUTime = c::CLOCK_PROCESS_CPUTIME_ID,
|
||||
|
||||
/// `CLOCK_THREAD_CPUTIME_ID`
|
||||
#[cfg(not(any(
|
||||
target_os = "illumos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
)))]
|
||||
ThreadCPUTime = c::CLOCK_THREAD_CPUTIME_ID,
|
||||
|
||||
/// `CLOCK_REALTIME_COARSE`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
RealtimeCoarse = c::CLOCK_REALTIME_COARSE,
|
||||
|
||||
/// `CLOCK_MONOTONIC_COARSE`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
MonotonicCoarse = c::CLOCK_MONOTONIC_COARSE,
|
||||
|
||||
/// `CLOCK_MONOTONIC_RAW`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
MonotonicRaw = c::CLOCK_MONOTONIC_RAW,
|
||||
}
|
||||
|
||||
/// `CLOCK_*` constants for use with [`clock_gettime`].
|
||||
///
|
||||
/// These constants are always supported at runtime so `clock_gettime` never
|
||||
/// has to fail with `INVAL` due to an unsupported clock. See
|
||||
/// [`DynamicClockId`] for a greater set of clocks, with the caveat that not
|
||||
/// all of them are always supported.
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[repr(u32)]
|
||||
#[non_exhaustive]
|
||||
pub enum ClockId {
|
||||
/// `CLOCK_REALTIME`
|
||||
Realtime = c::CLOCK_REALTIME,
|
||||
|
||||
/// `CLOCK_MONOTONIC`
|
||||
Monotonic = c::CLOCK_MONOTONIC,
|
||||
|
||||
/// `CLOCK_PROCESS_CPUTIME_ID`
|
||||
ProcessCPUTime = c::CLOCK_PROCESS_CPUTIME_ID,
|
||||
|
||||
/// `CLOCK_THREAD_CPUTIME_ID`
|
||||
ThreadCPUTime = c::CLOCK_THREAD_CPUTIME_ID,
|
||||
}
|
||||
|
||||
/// `CLOCK_*` constants for use with [`clock_gettime_dynamic`].
|
||||
///
|
||||
/// These constants may be unsupported at runtime, depending on the OS version,
|
||||
/// and `clock_gettime_dynamic` may fail with `INVAL`. See [`ClockId`] for
|
||||
/// clocks which are always supported at runtime.
|
||||
///
|
||||
/// [`clock_gettime_dynamic`]: crate::time::clock_gettime_dynamic
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum DynamicClockId<'a> {
|
||||
/// `ClockId` values that are always supported at runtime.
|
||||
Known(ClockId),
|
||||
|
||||
/// Linux dynamic clocks.
|
||||
Dynamic(BorrowedFd<'a>),
|
||||
|
||||
/// `CLOCK_REALTIME_ALARM`, available on Linux >= 3.0
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
RealtimeAlarm,
|
||||
|
||||
/// `CLOCK_TAI`, available on Linux >= 3.10
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
Tai,
|
||||
|
||||
/// `CLOCK_BOOTTIME`, available on Linux >= 2.6.39
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
Boottime,
|
||||
|
||||
/// `CLOCK_BOOTTIME_ALARM`, available on Linux >= 2.6.39
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
BoottimeAlarm,
|
||||
}
|
||||
|
||||
/// `struct itimerspec`
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
pub type Itimerspec = c::itimerspec;
|
||||
|
||||
/// `struct itimerspec`
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[allow(missing_docs)]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Itimerspec {
|
||||
pub it_interval: Timespec,
|
||||
pub it_value: Timespec,
|
||||
}
|
||||
|
||||
/// On most platforms, `LibcItimerspec` is just `Itimerspec`.
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(not(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
)))]
|
||||
pub(crate) type LibcItimerspec = Itimerspec;
|
||||
|
||||
/// On 32-bit glibc platforms, `LibcTimespec` differs from `Timespec`, so we
|
||||
/// define our own struct, with bidirectional `From` impls.
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct LibcItimerspec {
|
||||
pub it_interval: LibcTimespec,
|
||||
pub it_value: LibcTimespec,
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
impl From<LibcItimerspec> for Itimerspec {
|
||||
#[inline]
|
||||
fn from(t: LibcItimerspec) -> Self {
|
||||
Self {
|
||||
it_interval: t.it_interval.into(),
|
||||
it_value: t.it_value.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[cfg(all(
|
||||
any(target_arch = "arm", target_arch = "mips", target_arch = "x86"),
|
||||
target_env = "gnu",
|
||||
))]
|
||||
impl From<Itimerspec> for LibcItimerspec {
|
||||
#[inline]
|
||||
fn from(t: Itimerspec) -> Self {
|
||||
Self {
|
||||
it_interval: t.it_interval.into(),
|
||||
it_value: t.it_value.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
bitflags! {
|
||||
/// `TFD_*` flags for use with [`timerfd_create`].
|
||||
pub struct TimerfdFlags: c::c_int {
|
||||
/// `TFD_NONBLOCK`
|
||||
const NONBLOCK = c::TFD_NONBLOCK;
|
||||
|
||||
/// `TFD_CLOEXEC`
|
||||
const CLOEXEC = c::TFD_CLOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
bitflags! {
|
||||
/// `TFD_TIMER_*` flags for use with [`timerfd_settime`].
|
||||
pub struct TimerfdTimerFlags: c::c_int {
|
||||
/// `TFD_TIMER_ABSTIME`
|
||||
const ABSTIME = c::TFD_TIMER_ABSTIME;
|
||||
|
||||
/// `TFD_TIMER_CANCEL_ON_SET`
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
const CANCEL_ON_SET = 2; // TODO: upstream TFD_TIMER_CANCEL_ON_SET
|
||||
}
|
||||
}
|
||||
|
||||
/// `CLOCK_*` constants for use with [`timerfd_create`].
|
||||
///
|
||||
/// [`timerfd_create`]: crate::time::timerfd_create
|
||||
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[repr(i32)]
|
||||
#[non_exhaustive]
|
||||
pub enum TimerfdClockId {
|
||||
/// `CLOCK_REALTIME`—A clock that tells the "real" time.
|
||||
///
|
||||
/// This is a clock that tells the amount of time elapsed since the
|
||||
/// Unix epoch, 1970-01-01T00:00:00Z. The clock is externally settable, so
|
||||
/// it is not monotonic. Successive reads may see decreasing times, so it
|
||||
/// isn't reliable for measuring durations.
|
||||
Realtime = c::CLOCK_REALTIME,
|
||||
|
||||
/// `CLOCK_MONOTONIC`—A clock that tells an abstract time.
|
||||
///
|
||||
/// Unlike `Realtime`, this clock is not based on a fixed known epoch, so
|
||||
/// individual times aren't meaningful. However, since it isn't settable,
|
||||
/// it is reliable for measuring durations.
|
||||
///
|
||||
/// This clock does not advance while the system is suspended; see
|
||||
/// `Boottime` for a clock that does.
|
||||
Monotonic = c::CLOCK_MONOTONIC,
|
||||
|
||||
/// `CLOCK_BOOTTIME`—Like `Monotonic`, but advances while suspended.
|
||||
///
|
||||
/// This clock is similar to `Monotonic`, but does advance while the system
|
||||
/// is suspended.
|
||||
Boottime = c::CLOCK_BOOTTIME,
|
||||
|
||||
/// `CLOCK_REALTIME_ALARM`—Like `Realtime`, but wakes a suspended system.
|
||||
///
|
||||
/// This clock is like `Realtime`, but can wake up a suspended system.
|
||||
///
|
||||
/// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
|
||||
RealtimeAlarm = c::CLOCK_REALTIME_ALARM,
|
||||
|
||||
/// `CLOCK_BOOTTIME_ALARM`—Like `Boottime`, but wakes a suspended system.
|
||||
///
|
||||
/// This clock is like `Boottime`, but can wake up a suspended system.
|
||||
///
|
||||
/// Use of this clock requires the `CAP_WAKE_ALARM` Linux capability.
|
||||
BoottimeAlarm = c::CLOCK_BOOTTIME_ALARM,
|
||||
}
|
||||
226
vendor/rustix/src/backend/libc/weak.rs
vendored
Normal file
226
vendor/rustix/src/backend/libc/weak.rs
vendored
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
// Implementation derived from `weak` in Rust's
|
||||
// library/std/src/sys/unix/weak.rs at revision
|
||||
// fd0cb0cdc21dd9c06025277d772108f8d42cb25f.
|
||||
|
||||
//! Support for "weak linkage" to symbols on Unix
|
||||
//!
|
||||
//! Some I/O operations we do in libstd require newer versions of OSes but we
|
||||
//! need to maintain binary compatibility with older releases for now. In order
|
||||
//! to use the new functionality when available we use this module for
|
||||
//! detection.
|
||||
//!
|
||||
//! One option to use here is weak linkage, but that is unfortunately only
|
||||
//! really workable on Linux. Hence, use dlsym to get the symbol value at
|
||||
//! runtime. This is also done for compatibility with older versions of glibc,
|
||||
//! and to avoid creating dependencies on `GLIBC_PRIVATE` symbols. It assumes
|
||||
//! that we've been dynamically linked to the library the symbol comes from,
|
||||
//! but that is currently always the case for things like libpthread/libc.
|
||||
//!
|
||||
//! A long time ago this used weak linkage for the `__pthread_get_minstack`
|
||||
//! symbol, but that caused Debian to detect an unnecessarily strict versioned
|
||||
//! dependency on libc6 (#23628).
|
||||
|
||||
// There are a variety of `#[cfg]`s controlling which targets are involved in
|
||||
// each instance of `weak!` and `syscall!`. Rather than trying to unify all of
|
||||
// that, we'll just allow that some unix targets don't use this module at all.
|
||||
#![allow(dead_code, unused_macros)]
|
||||
#![allow(clippy::doc_markdown)]
|
||||
|
||||
use crate::ffi::CStr;
|
||||
use core::ffi::c_void;
|
||||
use core::ptr::null_mut;
|
||||
use core::sync::atomic::{self, AtomicPtr, Ordering};
|
||||
use core::{marker, mem};
|
||||
|
||||
const NULL: *mut c_void = null_mut();
|
||||
const INVALID: *mut c_void = 1 as *mut c_void;
|
||||
|
||||
macro_rules! weak {
|
||||
($vis:vis fn $name:ident($($t:ty),*) -> $ret:ty) => (
|
||||
#[allow(non_upper_case_globals)]
|
||||
$vis static $name: $crate::backend::weak::Weak<unsafe extern fn($($t),*) -> $ret> =
|
||||
$crate::backend::weak::Weak::new(concat!(stringify!($name), '\0'));
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) struct Weak<F> {
|
||||
name: &'static str,
|
||||
addr: AtomicPtr<c_void>,
|
||||
_marker: marker::PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F> Weak<F> {
|
||||
pub(crate) const fn new(name: &'static str) -> Self {
|
||||
Self {
|
||||
name,
|
||||
addr: AtomicPtr::new(INVALID),
|
||||
_marker: marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get(&self) -> Option<F> {
|
||||
assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
|
||||
unsafe {
|
||||
// Relaxed is fine here because we fence before reading through the
|
||||
// pointer (see the comment below).
|
||||
match self.addr.load(Ordering::Relaxed) {
|
||||
INVALID => self.initialize(),
|
||||
NULL => None,
|
||||
addr => {
|
||||
let func = mem::transmute_copy::<*mut c_void, F>(&addr);
|
||||
// The caller is presumably going to read through this value
|
||||
// (by calling the function we've dlsymed). This means we'd
|
||||
// need to have loaded it with at least C11's consume
|
||||
// ordering in order to be guaranteed that the data we read
|
||||
// from the pointer isn't from before the pointer was
|
||||
// stored. Rust has no equivalent to memory_order_consume,
|
||||
// so we use an acquire fence (sorry, ARM).
|
||||
//
|
||||
// Now, in practice this likely isn't needed even on CPUs
|
||||
// where relaxed and consume mean different things. The
|
||||
// symbols we're loading are probably present (or not) at
|
||||
// init, and even if they aren't the runtime dynamic loader
|
||||
// is extremely likely have sufficient barriers internally
|
||||
// (possibly implicitly, for example the ones provided by
|
||||
// invoking `mprotect`).
|
||||
//
|
||||
// That said, none of that's *guaranteed*, and so we fence.
|
||||
atomic::fence(Ordering::Acquire);
|
||||
Some(func)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cold because it should only happen during first-time initialization.
|
||||
#[cold]
|
||||
unsafe fn initialize(&self) -> Option<F> {
|
||||
let val = fetch(self.name);
|
||||
// This synchronizes with the acquire fence in `get`.
|
||||
self.addr.store(val, Ordering::Release);
|
||||
|
||||
match val {
|
||||
NULL => None,
|
||||
addr => Some(mem::transmute_copy::<*mut c_void, F>(&addr)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn fetch(name: &str) -> *mut c_void {
|
||||
let name = match CStr::from_bytes_with_nul(name.as_bytes()) {
|
||||
Ok(c_str) => c_str,
|
||||
Err(..) => return null_mut(),
|
||||
};
|
||||
libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr().cast())
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
|
||||
macro_rules! syscall {
|
||||
(fn $name:ident($($arg_name:ident: $t:ty),*) via $_sys_name:ident -> $ret:ty) => (
|
||||
unsafe fn $name($($arg_name: $t),*) -> $ret {
|
||||
weak! { fn $name($($t),*) -> $ret }
|
||||
|
||||
if let Some(fun) = $name.get() {
|
||||
fun($($arg_name),*)
|
||||
} else {
|
||||
libc_errno::set_errno(libc_errno::Errno(libc::ENOSYS));
|
||||
-1
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
macro_rules! syscall {
|
||||
(fn $name:ident($($arg_name:ident: $t:ty),*) via $sys_name:ident -> $ret:ty) => (
|
||||
unsafe fn $name($($arg_name:$t),*) -> $ret {
|
||||
// This looks like a hack, but concat_idents only accepts idents
|
||||
// (not paths).
|
||||
use libc::*;
|
||||
|
||||
trait AsSyscallArg {
|
||||
type SyscallArgType;
|
||||
fn into_syscall_arg(self) -> Self::SyscallArgType;
|
||||
}
|
||||
|
||||
// Pass pointer types as pointers, to preserve provenance.
|
||||
impl<T> AsSyscallArg for *mut T {
|
||||
type SyscallArgType = *mut T;
|
||||
fn into_syscall_arg(self) -> Self::SyscallArgType { self }
|
||||
}
|
||||
impl<T> AsSyscallArg for *const T {
|
||||
type SyscallArgType = *const T;
|
||||
fn into_syscall_arg(self) -> Self::SyscallArgType { self }
|
||||
}
|
||||
|
||||
// Pass `BorrowedFd` values as the integer value.
|
||||
impl AsSyscallArg for $crate::fd::BorrowedFd<'_> {
|
||||
type SyscallArgType = c::c_long;
|
||||
fn into_syscall_arg(self) -> Self::SyscallArgType {
|
||||
$crate::fd::AsRawFd::as_raw_fd(&self) as _
|
||||
}
|
||||
}
|
||||
|
||||
// Coerce integer values into `c_long`.
|
||||
impl AsSyscallArg for i32 {
|
||||
type SyscallArgType = c::c_long;
|
||||
fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
|
||||
}
|
||||
impl AsSyscallArg for u32 {
|
||||
type SyscallArgType = c::c_long;
|
||||
fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
|
||||
}
|
||||
impl AsSyscallArg for usize {
|
||||
type SyscallArgType = c::c_long;
|
||||
fn into_syscall_arg(self) -> Self::SyscallArgType { self as _ }
|
||||
}
|
||||
|
||||
// `concat_idents is unstable, so we take an extra `sys_name`
|
||||
// parameter and have our users do the concat for us for now.
|
||||
/*
|
||||
syscall(
|
||||
concat_idents!(SYS_, $name),
|
||||
$($arg_name.into_syscall_arg()),*
|
||||
) as $ret
|
||||
*/
|
||||
|
||||
syscall($sys_name, $($arg_name.into_syscall_arg()),*) as $ret
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! weakcall {
|
||||
($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
|
||||
$vis unsafe fn $name($($arg_name: $t),*) -> $ret {
|
||||
weak! { fn $name($($t),*) -> $ret }
|
||||
|
||||
// Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
|
||||
// interposition, but if it's not found just fail.
|
||||
if let Some(fun) = $name.get() {
|
||||
fun($($arg_name),*)
|
||||
} else {
|
||||
libc_errno::set_errno(libc_errno::Errno(libc::ENOSYS));
|
||||
-1
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// A combination of `weakcall` and `syscall`. Use the libc function if it's
|
||||
/// available, and fall back to `libc::syscall` otherwise.
|
||||
macro_rules! weak_or_syscall {
|
||||
($vis:vis fn $name:ident($($arg_name:ident: $t:ty),*) via $sys_name:ident -> $ret:ty) => (
|
||||
$vis unsafe fn $name($($arg_name: $t),*) -> $ret {
|
||||
weak! { fn $name($($t),*) -> $ret }
|
||||
|
||||
// Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
|
||||
// interposition, but if it's not found just fail.
|
||||
if let Some(fun) = $name.get() {
|
||||
fun($($arg_name),*)
|
||||
} else {
|
||||
syscall! { fn $name($($arg_name: $t),*) via $sys_name -> $ret }
|
||||
$name($($arg_name),*)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
82
vendor/rustix/src/backend/libc/winsock_c.rs
vendored
Normal file
82
vendor/rustix/src/backend/libc/winsock_c.rs
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
//! Adapt the Winsock2 API to resemble a POSIX-style libc API.
|
||||
|
||||
#![allow(unused_imports)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use windows_sys::Win32::Networking::WinSock;
|
||||
|
||||
pub(crate) use libc::{
|
||||
c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong,
|
||||
c_ushort, c_void, ssize_t,
|
||||
};
|
||||
pub(crate) type socklen_t = i32;
|
||||
|
||||
// windows-sys declares these constants as unsigned. For better compatibility
|
||||
// with Unix-family APIs, redeclare them as signed. Filed upstream:
|
||||
// <https://github.com/microsoft/windows-rs/issues/1718>
|
||||
pub(crate) const AF_INET: i32 = WinSock::AF_INET as _;
|
||||
pub(crate) const AF_INET6: i32 = WinSock::AF_INET6 as _;
|
||||
pub(crate) const AF_UNSPEC: i32 = WinSock::AF_UNSPEC as _;
|
||||
pub(crate) const SO_TYPE: i32 = WinSock::SO_TYPE as _;
|
||||
pub(crate) const SO_REUSEADDR: i32 = WinSock::SO_REUSEADDR as _;
|
||||
pub(crate) const SO_BROADCAST: i32 = WinSock::SO_BROADCAST as _;
|
||||
pub(crate) const SO_LINGER: i32 = WinSock::SO_LINGER as _;
|
||||
pub(crate) const SOL_SOCKET: i32 = WinSock::SOL_SOCKET as _;
|
||||
pub(crate) const SO_RCVTIMEO: i32 = WinSock::SO_RCVTIMEO as _;
|
||||
pub(crate) const SO_SNDTIMEO: i32 = WinSock::SO_SNDTIMEO as _;
|
||||
pub(crate) const IP_TTL: i32 = WinSock::IP_TTL as _;
|
||||
pub(crate) const TCP_NODELAY: i32 = WinSock::TCP_NODELAY as _;
|
||||
pub(crate) const IP_ADD_MEMBERSHIP: i32 = WinSock::IP_ADD_MEMBERSHIP as _;
|
||||
pub(crate) const IP_DROP_MEMBERSHIP: i32 = WinSock::IP_DROP_MEMBERSHIP as _;
|
||||
pub(crate) const IP_MULTICAST_TTL: i32 = WinSock::IP_MULTICAST_TTL as _;
|
||||
pub(crate) const IP_MULTICAST_LOOP: i32 = WinSock::IP_MULTICAST_LOOP as _;
|
||||
pub(crate) const IPV6_ADD_MEMBERSHIP: i32 = WinSock::IPV6_ADD_MEMBERSHIP as _;
|
||||
pub(crate) const IPV6_DROP_MEMBERSHIP: i32 = WinSock::IPV6_DROP_MEMBERSHIP as _;
|
||||
pub(crate) const IPV6_MULTICAST_LOOP: i32 = WinSock::IPV6_MULTICAST_LOOP as _;
|
||||
pub(crate) const IPV6_V6ONLY: i32 = WinSock::IPV6_V6ONLY as _;
|
||||
pub(crate) const POLLERR: i16 = WinSock::POLLERR as _;
|
||||
pub(crate) const POLLIN: i16 = WinSock::POLLIN as _;
|
||||
pub(crate) const POLLNVAL: i16 = WinSock::POLLNVAL as _;
|
||||
pub(crate) const POLLHUP: i16 = WinSock::POLLHUP as _;
|
||||
pub(crate) const POLLPRI: i16 = WinSock::POLLPRI as _;
|
||||
pub(crate) const POLLOUT: i16 = WinSock::POLLOUT as _;
|
||||
pub(crate) const POLLRDNORM: i16 = WinSock::POLLRDNORM as _;
|
||||
pub(crate) const POLLWRNORM: i16 = WinSock::POLLWRNORM as _;
|
||||
pub(crate) const POLLRDBAND: i16 = WinSock::POLLRDBAND as _;
|
||||
pub(crate) const POLLWRBAND: i16 = WinSock::POLLWRBAND as _;
|
||||
|
||||
// As above, cast the types for better compatibility, and also rename these to
|
||||
// their Unix names.
|
||||
pub(crate) const SHUT_RDWR: i32 = WinSock::SD_BOTH as _;
|
||||
pub(crate) const SHUT_RD: i32 = WinSock::SD_RECEIVE as _;
|
||||
pub(crate) const SHUT_WR: i32 = WinSock::SD_SEND as _;
|
||||
|
||||
// Include the contents of `WinSock`, renaming as needed to match POSIX.
|
||||
//
|
||||
// Use `WSA_E_CANCELLED` for `ECANCELED` instead of `WSAECANCELLED`, because
|
||||
// `WSAECANCELLED` will be removed in the future.
|
||||
// <https://docs.microsoft.com/en-us/windows/win32/api/ws2spi/nc-ws2spi-lpnsplookupserviceend#remarks>
|
||||
pub(crate) use WinSock::{
|
||||
closesocket as close, ioctlsocket as ioctl, WSAPoll as poll, ADDRESS_FAMILY as sa_family_t,
|
||||
ADDRINFOA as addrinfo, IN6_ADDR as in6_addr, IN_ADDR as in_addr, IPV6_MREQ as ipv6_mreq,
|
||||
IP_MREQ as ip_mreq, LINGER as linger, SOCKADDR as sockaddr, SOCKADDR_IN as sockaddr_in,
|
||||
SOCKADDR_IN6 as sockaddr_in6, SOCKADDR_STORAGE as sockaddr_storage, WSAEACCES as EACCES,
|
||||
WSAEADDRINUSE as EADDRINUSE, WSAEADDRNOTAVAIL as EADDRNOTAVAIL,
|
||||
WSAEAFNOSUPPORT as EAFNOSUPPORT, WSAEALREADY as EALREADY, WSAEBADF as EBADF,
|
||||
WSAECONNABORTED as ECONNABORTED, WSAECONNREFUSED as ECONNREFUSED, WSAECONNRESET as ECONNRESET,
|
||||
WSAEDESTADDRREQ as EDESTADDRREQ, WSAEDISCON as EDISCON, WSAEDQUOT as EDQUOT,
|
||||
WSAEFAULT as EFAULT, WSAEHOSTDOWN as EHOSTDOWN, WSAEHOSTUNREACH as EHOSTUNREACH,
|
||||
WSAEINPROGRESS as EINPROGRESS, WSAEINTR as EINTR, WSAEINVAL as EINVAL,
|
||||
WSAEINVALIDPROCTABLE as EINVALIDPROCTABLE, WSAEINVALIDPROVIDER as EINVALIDPROVIDER,
|
||||
WSAEISCONN as EISCONN, WSAELOOP as ELOOP, WSAEMFILE as EMFILE, WSAEMSGSIZE as EMSGSIZE,
|
||||
WSAENAMETOOLONG as ENAMETOOLONG, WSAENETDOWN as ENETDOWN, WSAENETRESET as ENETRESET,
|
||||
WSAENETUNREACH as ENETUNREACH, WSAENOBUFS as ENOBUFS, WSAENOMORE as ENOMORE,
|
||||
WSAENOPROTOOPT as ENOPROTOOPT, WSAENOTCONN as ENOTCONN, WSAENOTEMPTY as ENOTEMPTY,
|
||||
WSAENOTSOCK as ENOTSOCK, WSAEOPNOTSUPP as EOPNOTSUPP, WSAEPFNOSUPPORT as EPFNOSUPPORT,
|
||||
WSAEPROCLIM as EPROCLIM, WSAEPROTONOSUPPORT as EPROTONOSUPPORT, WSAEPROTOTYPE as EPROTOTYPE,
|
||||
WSAEPROVIDERFAILEDINIT as EPROVIDERFAILEDINIT, WSAEREFUSED as EREFUSED, WSAEREMOTE as EREMOTE,
|
||||
WSAESHUTDOWN as ESHUTDOWN, WSAESOCKTNOSUPPORT as ESOCKTNOSUPPORT, WSAESTALE as ESTALE,
|
||||
WSAETIMEDOUT as ETIMEDOUT, WSAETOOMANYREFS as ETOOMANYREFS, WSAEUSERS as EUSERS,
|
||||
WSAEWOULDBLOCK as EWOULDBLOCK, WSAEWOULDBLOCK as EAGAIN, WSAPOLLFD as pollfd,
|
||||
WSA_E_CANCELLED as ECANCELED, *,
|
||||
};
|
||||
268
vendor/rustix/src/backend/linux_raw/arch/inline/aarch64.rs
vendored
Normal file
268
vendor/rustix/src/backend/linux_raw/arch/inline/aarch64.rs
vendored
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
//! aarch64 Linux system calls.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
compile_error!("arm64-ilp32 is not supported yet");
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
lateout("x0") r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
in("x0") a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
in("x2") a2.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
in("x2") a2.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
in("x2") a2.to_asm(),
|
||||
in("x3") a3.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
in("x2") a2.to_asm(),
|
||||
in("x3") a3.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
in("x2") a2.to_asm(),
|
||||
in("x3") a3.to_asm(),
|
||||
in("x4") a4.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
in("x2") a2.to_asm(),
|
||||
in("x3") a3.to_asm(),
|
||||
in("x4") a4.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
in("x2") a2.to_asm(),
|
||||
in("x3") a3.to_asm(),
|
||||
in("x4") a4.to_asm(),
|
||||
in("x5") a5.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("x8") nr.to_asm(),
|
||||
inlateout("x0") a0.to_asm() => r0,
|
||||
in("x1") a1.to_asm(),
|
||||
in("x2") a2.to_asm(),
|
||||
in("x3") a3.to_asm(),
|
||||
in("x4") a4.to_asm(),
|
||||
in("x5") a5.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
265
vendor/rustix/src/backend/linux_raw/arch/inline/arm.rs
vendored
Normal file
265
vendor/rustix/src/backend/linux_raw/arch/inline/arm.rs
vendored
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
//! arm Linux system calls.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
lateout("r0") r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
in("r0") a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
in("r4") a4.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
in("r4") a4.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
in("r4") a4.to_asm(),
|
||||
in("r5") a5.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"svc 0",
|
||||
in("r7") nr.to_asm(),
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
in("r4") a4.to_asm(),
|
||||
in("r5") a5.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
543
vendor/rustix/src/backend/linux_raw/arch/inline/mips.rs
vendored
Normal file
543
vendor/rustix/src/backend/linux_raw/arch/inline/mips.rs
vendored
Normal file
|
|
@ -0,0 +1,543 @@
|
|||
//! mipsel Linux system calls.
|
||||
//!
|
||||
//! On mipsel, Linux indicates success or failure using `$a3` rather
|
||||
//! than by returning a negative error code as most other architectures do.
|
||||
//!
|
||||
//! Mips-family platforms have a special calling convention for `__NR_pipe`,
|
||||
//! however we use `__NR_pipe2` instead to avoid having to implement it.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, A6, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("$2" /*$v0*/) nr.to_asm(),
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
".set noat",
|
||||
"subu $sp, 32",
|
||||
"sw {}, 16($sp)",
|
||||
"syscall",
|
||||
"addu $sp, 32",
|
||||
".set at",
|
||||
in(reg) a4.to_asm(),
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
".set noat",
|
||||
"subu $sp, 32",
|
||||
"sw {}, 16($sp)",
|
||||
"syscall",
|
||||
"addu $sp, 32",
|
||||
".set at",
|
||||
in(reg) a4.to_asm(),
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
".set noat",
|
||||
"subu $sp, 32",
|
||||
"sw {}, 16($sp)",
|
||||
"sw {}, 20($sp)",
|
||||
"syscall",
|
||||
"addu $sp, 32",
|
||||
".set at",
|
||||
in(reg) a4.to_asm(),
|
||||
in(reg) a5.to_asm(),
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
".set noat",
|
||||
"subu $sp, 32",
|
||||
"sw {}, 16($sp)",
|
||||
"sw {}, 20($sp)",
|
||||
"syscall",
|
||||
"addu $sp, 32",
|
||||
".set at",
|
||||
in(reg) a4.to_asm(),
|
||||
in(reg) a5.to_asm(),
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall7_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
a6: ArgReg<'_, A6>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
".set noat",
|
||||
"subu $sp, 32",
|
||||
"sw {}, 16($sp)",
|
||||
"sw {}, 20($sp)",
|
||||
"sw {}, 24($sp)",
|
||||
"syscall",
|
||||
"addu $sp, 32",
|
||||
".set at",
|
||||
in(reg) a4.to_asm(),
|
||||
in(reg) a5.to_asm(),
|
||||
in(reg) a6.to_asm(),
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$t0*/) _,
|
||||
lateout("$9" /*$t1*/) _,
|
||||
lateout("$10" /*$t2*/) _,
|
||||
lateout("$11" /*$t3*/) _,
|
||||
lateout("$12" /*$t4*/) _,
|
||||
lateout("$13" /*$t5*/) _,
|
||||
lateout("$14" /*$t6*/) _,
|
||||
lateout("$15" /*$t7*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
466
vendor/rustix/src/backend/linux_raw/arch/inline/mips64.rs
vendored
Normal file
466
vendor/rustix/src/backend/linux_raw/arch/inline/mips64.rs
vendored
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
//! mips64el Linux system calls.
|
||||
//!
|
||||
//! On mips64el, Linux indicates success or failure using `$a3` (`$7`) rather
|
||||
//! than by returning a negative error code as most other architectures do.
|
||||
//!
|
||||
//! Mips-family platforms have a special calling convention for `__NR_pipe`,
|
||||
//! however we use `__NR_pipe2` instead to avoid having to implement it.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("$2" /*$v0*/) nr.to_asm(),
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
lateout("$7" /*$a3*/) err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
lateout("$8" /*$a4*/) _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
inlateout("$8" /*$a4*/) a4.to_asm() => _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
inlateout("$8" /*$a4*/) a4.to_asm() => _,
|
||||
lateout("$9" /*$a5*/) _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
inlateout("$8" /*$a4*/) a4.to_asm() => _,
|
||||
inlateout("$9" /*$a5*/) a5.to_asm() => _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let x0;
|
||||
let err: usize;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("$2" /*$v0*/) nr.to_asm() => x0,
|
||||
in("$4" /*$a0*/) a0.to_asm(),
|
||||
in("$5" /*$a1*/) a1.to_asm(),
|
||||
in("$6" /*$a2*/) a2.to_asm(),
|
||||
inlateout("$7" /*$a3*/) a3.to_asm() => err,
|
||||
inlateout("$8" /*$a4*/) a4.to_asm() => _,
|
||||
inlateout("$9" /*$a5*/) a5.to_asm() => _,
|
||||
lateout("$10" /*$a6*/) _,
|
||||
lateout("$11" /*$a7*/) _,
|
||||
lateout("$12" /*$t0*/) _,
|
||||
lateout("$13" /*$t1*/) _,
|
||||
lateout("$14" /*$t2*/) _,
|
||||
lateout("$15" /*$t3*/) _,
|
||||
lateout("$24" /*$t8*/) _,
|
||||
lateout("$25" /*$t9*/) _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(if err != 0 {
|
||||
(x0 as usize).wrapping_neg() as *mut _
|
||||
} else {
|
||||
x0
|
||||
})
|
||||
}
|
||||
18
vendor/rustix/src/backend/linux_raw/arch/inline/mod.rs
vendored
Normal file
18
vendor/rustix/src/backend/linux_raw/arch/inline/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
//! Inline asm for making system calls.
|
||||
//!
|
||||
//! Compilers should really have intrinsics for making system calls. They're
|
||||
//! much like regular calls, with custom calling conventions, and calling
|
||||
//! conventions are otherwise the compiler's job. But for now, use inline asm.
|
||||
|
||||
#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
|
||||
#[cfg_attr(all(target_arch = "arm", not(thumb_mode)), path = "arm.rs")]
|
||||
#[cfg_attr(all(target_arch = "arm", thumb_mode), path = "thumb.rs")]
|
||||
#[cfg_attr(target_arch = "mips", path = "mips.rs")]
|
||||
#[cfg_attr(target_arch = "mips64", path = "mips64.rs")]
|
||||
#[cfg_attr(target_arch = "powerpc64", path = "powerpc64.rs")]
|
||||
#[cfg_attr(target_arch = "riscv64", path = "riscv64.rs")]
|
||||
#[cfg_attr(target_arch = "x86", path = "x86.rs")]
|
||||
#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
|
||||
mod target_arch;
|
||||
|
||||
pub(in crate::backend) use self::target_arch::*;
|
||||
413
vendor/rustix/src/backend/linux_raw/arch/inline/powerpc64.rs
vendored
Normal file
413
vendor/rustix/src/backend/linux_raw/arch/inline/powerpc64.rs
vendored
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
//! powerpc64le Linux system calls.
|
||||
//!
|
||||
//! On powerpc64le, Linux indicates success or failure using `cr0.SO` rather
|
||||
//! than by returning a negative error code as most other architectures do. In
|
||||
//! theory we could immediately translate this into a `Result`, and it'd save a
|
||||
//! few branches. And in theory we could have specialized sequences for use
|
||||
//! with syscalls that are known to never fail. However, those would require
|
||||
//! more extensive changes in rustix's platform-independent code. For now, we
|
||||
//! check the flag and negate the error value to make PowerPC64 look like other
|
||||
//! architectures.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
lateout("r3") r0,
|
||||
lateout("r4") _,
|
||||
lateout("r5") _,
|
||||
lateout("r6") _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
lateout("r4") _,
|
||||
lateout("r5") _,
|
||||
lateout("r6") _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
lateout("r4") _,
|
||||
lateout("r5") _,
|
||||
lateout("r6") _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"sc",
|
||||
in("r0") nr.to_asm(),
|
||||
in("r3") a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
lateout("r5") _,
|
||||
lateout("r6") _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
lateout("r5") _,
|
||||
lateout("r6") _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
inlateout("r5") a2.to_asm() => _,
|
||||
lateout("r6") _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
inlateout("r5") a2.to_asm() => _,
|
||||
lateout("r6") _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
inlateout("r5") a2.to_asm() => _,
|
||||
inlateout("r6") a3.to_asm() => _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
inlateout("r5") a2.to_asm() => _,
|
||||
inlateout("r6") a3.to_asm() => _,
|
||||
lateout("r7") _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
inlateout("r5") a2.to_asm() => _,
|
||||
inlateout("r6") a3.to_asm() => _,
|
||||
inlateout("r7") a4.to_asm() => _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
inlateout("r5") a2.to_asm() => _,
|
||||
inlateout("r6") a3.to_asm() => _,
|
||||
inlateout("r7") a4.to_asm() => _,
|
||||
lateout("r8") _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
inlateout("r5") a2.to_asm() => _,
|
||||
inlateout("r6") a3.to_asm() => _,
|
||||
inlateout("r7") a4.to_asm() => _,
|
||||
inlateout("r8") a5.to_asm() => _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"sc",
|
||||
"bns 0f",
|
||||
"neg 3, 3",
|
||||
"0:",
|
||||
inlateout("r0") nr.to_asm() => _,
|
||||
inlateout("r3") a0.to_asm() => r0,
|
||||
inlateout("r4") a1.to_asm() => _,
|
||||
inlateout("r5") a2.to_asm() => _,
|
||||
inlateout("r6") a3.to_asm() => _,
|
||||
inlateout("r7") a4.to_asm() => _,
|
||||
inlateout("r8") a5.to_asm() => _,
|
||||
lateout("r9") _,
|
||||
lateout("r10") _,
|
||||
lateout("r11") _,
|
||||
lateout("r12") _,
|
||||
lateout("cr0") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
265
vendor/rustix/src/backend/linux_raw/arch/inline/riscv64.rs
vendored
Normal file
265
vendor/rustix/src/backend/linux_raw/arch/inline/riscv64.rs
vendored
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
//! riscv64 Linux system calls.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
lateout("a0") r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
in("a0") a0.to_asm(),
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
in("a2") a2.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
in("a2") a2.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
in("a2") a2.to_asm(),
|
||||
in("a3") a3.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
in("a2") a2.to_asm(),
|
||||
in("a3") a3.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
in("a2") a2.to_asm(),
|
||||
in("a3") a3.to_asm(),
|
||||
in("a4") a4.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
in("a2") a2.to_asm(),
|
||||
in("a3") a3.to_asm(),
|
||||
in("a4") a4.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
in("a2") a2.to_asm(),
|
||||
in("a3") a3.to_asm(),
|
||||
in("a4") a4.to_asm(),
|
||||
in("a5") a5.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"ecall",
|
||||
in("a7") nr.to_asm(),
|
||||
inlateout("a0") a0.to_asm() => r0,
|
||||
in("a1") a1.to_asm(),
|
||||
in("a2") a2.to_asm(),
|
||||
in("a3") a3.to_asm(),
|
||||
in("a4") a4.to_asm(),
|
||||
in("a5") a5.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
322
vendor/rustix/src/backend/linux_raw/arch/inline/thumb.rs
vendored
Normal file
322
vendor/rustix/src/backend/linux_raw/arch/inline/thumb.rs
vendored
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
//! arm Linux system calls, using thumb-mode.
|
||||
//!
|
||||
//! In thumb-mode, r7 is the frame pointer and is not permitted to be used in
|
||||
//! an inline asm operand, so we have to use a different register and copy it
|
||||
//! into r7 inside the inline asm.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
lateout("r0") r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
in("r0") a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
in("r4") a4.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
in("r4") a4.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
in("r4") a4.to_asm(),
|
||||
in("r5") a5.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"mov {tmp}, r7",
|
||||
"mov r7, {nr}",
|
||||
"svc 0",
|
||||
"mov r7, {tmp}",
|
||||
nr = in(reg) nr.to_asm(),
|
||||
tmp = out(reg) _,
|
||||
inlateout("r0") a0.to_asm() => r0,
|
||||
in("r1") a1.to_asm(),
|
||||
in("r2") a2.to_asm(),
|
||||
in("r3") a3.to_asm(),
|
||||
in("r4") a4.to_asm(),
|
||||
in("r5") a5.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
494
vendor/rustix/src/backend/linux_raw/arch/inline/x86.rs
vendored
Normal file
494
vendor/rustix/src/backend/linux_raw/arch/inline/x86.rs
vendored
Normal file
|
|
@ -0,0 +1,494 @@
|
|||
//! 32-bit x86 Linux system calls.
|
||||
//!
|
||||
//! There are two forms; `indirect_*` which take a callee, which allow calling
|
||||
//! through the vDSO when possible, and plain forms, which use the `int 0x80`
|
||||
//! instruction.
|
||||
//!
|
||||
//! Most `rustix` syscalls use the vsyscall mechanism rather than going using
|
||||
//! `int 0x80` sequences.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use crate::backend::vdso_wrappers::SyscallType;
|
||||
use core::arch::asm;
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall0(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"call {callee}",
|
||||
callee = in(reg) callee,
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall1(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"call {callee}",
|
||||
callee = in(reg) callee,
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall1_noreturn(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> ! {
|
||||
asm!(
|
||||
"call {callee}",
|
||||
callee = in(reg) callee,
|
||||
in("eax") nr.to_asm(),
|
||||
in("ebx") a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall2(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"call {callee}",
|
||||
callee = in(reg) callee,
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall3(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"call {callee}",
|
||||
callee = in(reg) callee,
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall4(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
// a3 should go in esi, but `asm!` won't let us use it as an operand.
|
||||
// temporarily swap it into place, and then swap it back afterward.
|
||||
//
|
||||
// We hard-code the callee operand to use edi instead of `in(reg)` because
|
||||
// even though we can't name esi as an operand, the compiler can use esi to
|
||||
// satisfy `in(reg)`.
|
||||
asm!(
|
||||
"xchg esi, {a3}",
|
||||
"call edi",
|
||||
"xchg esi, {a3}",
|
||||
a3 = in(reg) a3.to_asm(),
|
||||
in("edi") callee,
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall5(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
// Oof. a3 should go in esi, and `asm!` won't let us use that register as
|
||||
// an operand. And we can't request stack slots. And there are no other
|
||||
// registers free. Use eax as a temporary pointer to a slice, since it
|
||||
// gets clobbered as the return value anyway.
|
||||
asm!(
|
||||
"push esi",
|
||||
"push DWORD PTR [eax + 0]",
|
||||
"mov esi, DWORD PTR [eax + 4]",
|
||||
"mov eax, DWORD PTR [eax + 8]",
|
||||
"call DWORD PTR [esp]",
|
||||
"pop esi",
|
||||
"pop esi",
|
||||
inout("eax") &[callee as _, a3.to_asm(), nr.to_asm()] => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
in("edi") a4.to_asm(),
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall6(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
// Oof again. a3 should go in esi, and a5 should go in ebp, and `asm!`
|
||||
// won't let us use either of those registers as operands. And we can't
|
||||
// request stack slots. And there are no other registers free. Use eax as a
|
||||
// temporary pointer to a slice, since it gets clobbered as the return
|
||||
// value anyway.
|
||||
//
|
||||
// This is another reason that syscalls should be compiler intrinsics
|
||||
// rather than inline asm.
|
||||
asm!(
|
||||
"push ebp",
|
||||
"push esi",
|
||||
"push DWORD PTR [eax + 0]",
|
||||
"mov esi, DWORD PTR [eax + 4]",
|
||||
"mov ebp, DWORD PTR [eax + 8]",
|
||||
"mov eax, DWORD PTR [eax + 12]",
|
||||
"call DWORD PTR [esp]",
|
||||
"pop esi",
|
||||
"pop esi",
|
||||
"pop ebp",
|
||||
inout("eax") &[callee as _, a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
in("edi") a4.to_asm(),
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
in("eax") nr.to_asm(),
|
||||
in("ebx") a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"int $$0x80",
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
// a3 should go in esi, but `asm!` won't let us use it as an operand.
|
||||
// Temporarily swap it into place, and then swap it back afterward.
|
||||
asm!(
|
||||
"xchg esi, {a3}",
|
||||
"int $$0x80",
|
||||
"xchg esi, {a3}",
|
||||
a3 = in(reg) a3.to_asm(),
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"xchg esi, {a3}",
|
||||
"int $$0x80",
|
||||
"xchg esi, {a3}",
|
||||
a3 = in(reg) a3.to_asm(),
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
// As in `syscall4`, use xchg to handle a3. a4 should go in edi, and we can
|
||||
// use that register as an operand. Unlike in `indirect_syscall5`, we don't
|
||||
// have a `callee` operand taking up a register, so we have enough
|
||||
// registers and don't need to use a slice.
|
||||
asm!(
|
||||
"xchg esi, {a3}",
|
||||
"int $$0x80",
|
||||
"xchg esi, {a3}",
|
||||
a3 = in(reg) a3.to_asm(),
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
in("edi") a4.to_asm(),
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
// See the comments in `syscall5`.
|
||||
asm!(
|
||||
"xchg esi, {a3}",
|
||||
"int $$0x80",
|
||||
"xchg esi, {a3}",
|
||||
a3 = in(reg) a3.to_asm(),
|
||||
inlateout("eax") nr.to_asm() => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
in("edi") a4.to_asm(),
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
// See the comments in `indirect_syscall6`.
|
||||
asm!(
|
||||
"push ebp",
|
||||
"push esi",
|
||||
"mov esi, DWORD PTR [eax + 0]",
|
||||
"mov ebp, DWORD PTR [eax + 4]",
|
||||
"mov eax, DWORD PTR [eax + 8]",
|
||||
"int $$0x80",
|
||||
"pop esi",
|
||||
"pop ebp",
|
||||
inout("eax") &[a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
in("edi") a4.to_asm(),
|
||||
options(preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
// See the comments in `indirect_syscall6`.
|
||||
asm!(
|
||||
"push ebp",
|
||||
"push esi",
|
||||
"mov esi, DWORD PTR [eax + 0]",
|
||||
"mov ebp, DWORD PTR [eax + 4]",
|
||||
"mov eax, DWORD PTR [eax + 8]",
|
||||
"int $$0x80",
|
||||
"pop esi",
|
||||
"pop ebp",
|
||||
inout("eax") &[a3.to_asm(), a5.to_asm(), nr.to_asm()] => r0,
|
||||
in("ebx") a0.to_asm(),
|
||||
in("ecx") a1.to_asm(),
|
||||
in("edx") a2.to_asm(),
|
||||
in("edi") a4.to_asm(),
|
||||
options(preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
293
vendor/rustix/src/backend/linux_raw/arch/inline/x86_64.rs
vendored
Normal file
293
vendor/rustix/src/backend/linux_raw/arch/inline/x86_64.rs
vendored
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
//! x86-64 Linux system calls.
|
||||
|
||||
use crate::backend::reg::{
|
||||
ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0,
|
||||
};
|
||||
use core::arch::asm;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
compile_error!("x32 is not yet supported");
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("rax") nr.to_asm(),
|
||||
in("rdi") a0.to_asm(),
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
in("rdx") a2.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
in("rdx") a2.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
in("rdx") a2.to_asm(),
|
||||
in("r10") a3.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
in("rdx") a2.to_asm(),
|
||||
in("r10") a3.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
in("rdx") a2.to_asm(),
|
||||
in("r10") a3.to_asm(),
|
||||
in("r8") a4.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
in("rdx") a2.to_asm(),
|
||||
in("r10") a3.to_asm(),
|
||||
in("r8") a4.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
in("rdx") a2.to_asm(),
|
||||
in("r10") a3.to_asm(),
|
||||
in("r8") a4.to_asm(),
|
||||
in("r9") a5.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6_readonly(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
let r0;
|
||||
asm!(
|
||||
"syscall",
|
||||
inlateout("rax") nr.to_asm() => r0,
|
||||
in("rdi") a0.to_asm(),
|
||||
in("rsi") a1.to_asm(),
|
||||
in("rdx") a2.to_asm(),
|
||||
in("r10") a3.to_asm(),
|
||||
in("r8") a4.to_asm(),
|
||||
in("r9") a5.to_asm(),
|
||||
lateout("rcx") _,
|
||||
lateout("r11") _,
|
||||
options(nostack, preserves_flags, readonly)
|
||||
);
|
||||
FromAsm::from_asm(r0)
|
||||
}
|
||||
222
vendor/rustix/src/backend/linux_raw/arch/mod.rs
vendored
Normal file
222
vendor/rustix/src/backend/linux_raw/arch/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
//! Architecture-specific syscall code.
|
||||
//!
|
||||
//! `rustix` has inline assembly sequences using `asm!`, but that requires
|
||||
//! nightly Rust, so it also has out-of-line ("outline") assembly sequences
|
||||
//! in .s files. And 32-bit x86 is special (see comments below).
|
||||
//!
|
||||
//! This module also has a `choose` submodule which chooses a scheme and is
|
||||
//! what most of the `rustix` syscalls use.
|
||||
//!
|
||||
//! # Safety
|
||||
//!
|
||||
//! This contains the inline `asm` statements performing the syscall
|
||||
//! instructions and FFI declarations declaring the out-of-line ("outline")
|
||||
//! syscall instructions.
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
#![cfg_attr(not(feature = "all-apis"), allow(unused_imports))]
|
||||
// We'll use as many arguments as syscalls need.
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
// When inline asm is available, use it. Otherwise, use out-of-line asm. These
|
||||
// functions always use the machine's syscall instruction, even when it isn't
|
||||
// the fastest option available.
|
||||
#[cfg_attr(asm, path = "inline/mod.rs")]
|
||||
#[cfg_attr(not(asm), path = "outline/mod.rs")]
|
||||
pub(in crate::backend) mod asm;
|
||||
|
||||
// On most architectures, the architecture syscall instruction is fast, so use
|
||||
// it directly.
|
||||
#[cfg(any(
|
||||
target_arch = "arm",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64",
|
||||
target_arch = "powerpc64",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "x86_64",
|
||||
))]
|
||||
pub(in crate::backend) use self::asm as choose;
|
||||
|
||||
// On 32-bit x86, use vDSO wrappers for all syscalls. We could use the
|
||||
// architecture syscall instruction (`int 0x80`), but the vDSO kernel_vsyscall
|
||||
// mechanism is much faster.
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub(in crate::backend) use super::vdso_wrappers::x86_via_vdso as choose;
|
||||
|
||||
// This would be the code for always using `int 0x80` on 32-bit x86.
|
||||
//#[cfg(target_arch = "x86")]
|
||||
//pub(in crate::backend) use self::asm as choose;
|
||||
|
||||
// Macros for invoking system calls.
|
||||
//
|
||||
// These factor out:
|
||||
// - Calling `nr` on the syscall number to convert it into `SyscallNumber`.
|
||||
// - Calling `.into()` on each of the arguments to convert them into `ArgReg`.
|
||||
// - Qualifying the `syscall*` and `__NR_*` identifiers.
|
||||
// - Counting the number of arguments.
|
||||
macro_rules! syscall {
|
||||
($nr:ident) => {
|
||||
$crate::backend::arch::choose::syscall0($crate::backend::reg::nr(
|
||||
linux_raw_sys::general::$nr,
|
||||
))
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr) => {
|
||||
$crate::backend::arch::choose::syscall1(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr) => {
|
||||
$crate::backend::arch::choose::syscall2(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
|
||||
$crate::backend::arch::choose::syscall3(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
|
||||
$crate::backend::arch::choose::syscall4(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
|
||||
$crate::backend::arch::choose::syscall5(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
|
||||
$crate::backend::arch::choose::syscall6(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
$a5.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
|
||||
$crate::backend::arch::choose::syscall7(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
$a5.into(),
|
||||
$a6.into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! syscall_readonly {
|
||||
($nr:ident) => {
|
||||
$crate::backend::arch::choose::syscall0_readonly($crate::backend::reg::nr(
|
||||
linux_raw_sys::general::$nr,
|
||||
))
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr) => {
|
||||
$crate::backend::arch::choose::syscall1_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr) => {
|
||||
$crate::backend::arch::choose::syscall2_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr) => {
|
||||
$crate::backend::arch::choose::syscall3_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {
|
||||
$crate::backend::arch::choose::syscall4_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {
|
||||
$crate::backend::arch::choose::syscall5_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr) => {
|
||||
$crate::backend::arch::choose::syscall6_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
$a5.into(),
|
||||
)
|
||||
};
|
||||
|
||||
($nr:ident, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr, $a5:expr, $a6:expr) => {
|
||||
$crate::backend::arch::choose::syscall7_readonly(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
$a1.into(),
|
||||
$a2.into(),
|
||||
$a3.into(),
|
||||
$a4.into(),
|
||||
$a5.into(),
|
||||
$a6.into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "runtime")]
|
||||
macro_rules! syscall_noreturn {
|
||||
($nr:ident, $a0:expr) => {
|
||||
$crate::backend::arch::choose::syscall1_noreturn(
|
||||
$crate::backend::reg::nr(linux_raw_sys::general::$nr),
|
||||
$a0.into(),
|
||||
)
|
||||
};
|
||||
}
|
||||
119
vendor/rustix/src/backend/linux_raw/arch/outline/aarch64.s
vendored
Normal file
119
vendor/rustix/src/backend/linux_raw/arch/outline/aarch64.s
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
// Assembly code for making aarch64 syscalls.
|
||||
//
|
||||
// aarch64 syscall argument register ordering is the same as the aarch64
|
||||
// userspace argument register ordering except that the syscall number
|
||||
// (nr) is passed in w8.
|
||||
//
|
||||
// outline.rs takes care of reordering the nr argument to the end for us,
|
||||
// so we only need to move nr into w8.
|
||||
//
|
||||
// arm64-ilp32 is not yet supported.
|
||||
|
||||
.file "aarch64.s"
|
||||
.arch armv8-a
|
||||
|
||||
.section .text.rustix_syscall0_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall0_nr_last
|
||||
.hidden rustix_syscall0_nr_last
|
||||
.type rustix_syscall0_nr_last, @function
|
||||
rustix_syscall0_nr_last:
|
||||
.cfi_startproc
|
||||
mov w8, w0
|
||||
svc #0
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall1_nr_last
|
||||
.hidden rustix_syscall1_nr_last
|
||||
.type rustix_syscall1_nr_last, @function
|
||||
rustix_syscall1_nr_last:
|
||||
.cfi_startproc
|
||||
mov w8, w1
|
||||
svc #0
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall1_noreturn_nr_last
|
||||
.hidden rustix_syscall1_noreturn_nr_last
|
||||
.type rustix_syscall1_noreturn_nr_last, @function
|
||||
rustix_syscall1_noreturn_nr_last:
|
||||
.cfi_startproc
|
||||
mov w8, w1
|
||||
svc #0
|
||||
brk #0x1
|
||||
.cfi_endproc
|
||||
.size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
|
||||
|
||||
.section .text.rustix_syscall2_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall2_nr_last
|
||||
.hidden rustix_syscall2_nr_last
|
||||
.type rustix_syscall2_nr_last, @function
|
||||
rustix_syscall2_nr_last:
|
||||
.cfi_startproc
|
||||
mov w8, w2
|
||||
svc #0
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
|
||||
|
||||
.section .text.rustix_syscall3_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall3_nr_last
|
||||
.hidden rustix_syscall3_nr_last
|
||||
.type rustix_syscall3_nr_last, @function
|
||||
rustix_syscall3_nr_last:
|
||||
.cfi_startproc
|
||||
mov w8, w3
|
||||
svc #0
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
|
||||
|
||||
.section .text.rustix_syscall4_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall4_nr_last
|
||||
.hidden rustix_syscall4_nr_last
|
||||
.type rustix_syscall4_nr_last, @function
|
||||
rustix_syscall4_nr_last:
|
||||
.cfi_startproc
|
||||
mov w8, w4
|
||||
svc #0
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
|
||||
|
||||
.section .text.rustix_syscall5_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall5_nr_last
|
||||
.hidden rustix_syscall5_nr_last
|
||||
.type rustix_syscall5_nr_last, @function
|
||||
rustix_syscall5_nr_last:
|
||||
.cfi_startproc
|
||||
mov w8, w5
|
||||
svc #0
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
|
||||
|
||||
.section .text.rustix_syscall6_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall6_nr_last
|
||||
.hidden rustix_syscall6_nr_last
|
||||
.type rustix_syscall6_nr_last, @function
|
||||
rustix_syscall6_nr_last:
|
||||
.cfi_startproc
|
||||
mov w8, w6
|
||||
svc #0
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
135
vendor/rustix/src/backend/linux_raw/arch/outline/arm.s
vendored
Normal file
135
vendor/rustix/src/backend/linux_raw/arch/outline/arm.s
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
// Assembly code for making arm syscalls.
|
||||
//
|
||||
// arm syscall argument register ordering is the similar to the arm
|
||||
// userspace argument register ordering except that the syscall number
|
||||
// (nr) is passed in r7.
|
||||
//
|
||||
// nr_last.rs takes care of reordering the nr argument to the end for us,
|
||||
// so we only need to move nr into r7 and take care of r4 and r5 if needed.
|
||||
|
||||
.file "arm.s"
|
||||
.arch armv5t
|
||||
|
||||
.section .text.rustix_syscall0_nr_last,"ax",%progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall0_nr_last
|
||||
.hidden rustix_syscall0_nr_last
|
||||
.type rustix_syscall0_nr_last, %function
|
||||
rustix_syscall0_nr_last:
|
||||
.fnstart
|
||||
.cantunwind
|
||||
push {r7, lr}
|
||||
mov r7, r0
|
||||
svc #0
|
||||
pop {r7, pc}
|
||||
.fnend
|
||||
.size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_nr_last,"ax",%progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall1_nr_last
|
||||
.hidden rustix_syscall1_nr_last
|
||||
.type rustix_syscall1_nr_last, %function
|
||||
rustix_syscall1_nr_last:
|
||||
.fnstart
|
||||
.cantunwind
|
||||
push {r7, lr}
|
||||
mov r7, r1
|
||||
svc #0
|
||||
pop {r7, pc}
|
||||
.fnend
|
||||
.size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_noreturn_nr_last,"ax",%progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall1_noreturn_nr_last
|
||||
.hidden rustix_syscall1_noreturn_nr_last
|
||||
.type rustix_syscall1_noreturn_nr_last, %function
|
||||
rustix_syscall1_noreturn_nr_last:
|
||||
.fnstart
|
||||
.cantunwind
|
||||
// Don't save r7 and lr; this is noreturn, so we'll never restore them.
|
||||
mov r7, r1
|
||||
svc #0
|
||||
udf #16 // Trap instruction
|
||||
.fnend
|
||||
.size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
|
||||
|
||||
.section .text.rustix_syscall2_nr_last,"ax",%progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall2_nr_last
|
||||
.hidden rustix_syscall2_nr_last
|
||||
.type rustix_syscall2_nr_last, %function
|
||||
rustix_syscall2_nr_last:
|
||||
.fnstart
|
||||
.cantunwind
|
||||
push {r7, lr}
|
||||
mov r7, r2
|
||||
svc #0
|
||||
pop {r7, pc}
|
||||
.fnend
|
||||
.size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
|
||||
|
||||
.section .text.rustix_syscall3_nr_last,"ax",%progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall3_nr_last
|
||||
.hidden rustix_syscall3_nr_last
|
||||
.type rustix_syscall3_nr_last, %function
|
||||
rustix_syscall3_nr_last:
|
||||
.fnstart
|
||||
.cantunwind
|
||||
push {r7, lr}
|
||||
mov r7, r3
|
||||
svc #0
|
||||
pop {r7, pc}
|
||||
.fnend
|
||||
.size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
|
||||
|
||||
.section .text.rustix_syscall4_nr_last,"ax",%progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall4_nr_last
|
||||
.hidden rustix_syscall4_nr_last
|
||||
.type rustix_syscall4_nr_last, %function
|
||||
rustix_syscall4_nr_last:
|
||||
.fnstart
|
||||
.cantunwind
|
||||
push {r7, lr}
|
||||
ldr r7, [sp, #8]
|
||||
svc #0
|
||||
pop {r7, pc}
|
||||
.fnend
|
||||
.size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
|
||||
|
||||
.section .text.rustix_syscall5_nr_last,"ax",%progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall5_nr_last
|
||||
.hidden rustix_syscall5_nr_last
|
||||
.type rustix_syscall5_nr_last, %function
|
||||
rustix_syscall5_nr_last:
|
||||
.fnstart
|
||||
.cantunwind
|
||||
push {r4, r7, r11, lr}
|
||||
ldr r7, [sp, #20]
|
||||
ldr r4, [sp, #16]
|
||||
svc #0
|
||||
pop {r4, r7, r11, pc}
|
||||
.fnend
|
||||
.size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
|
||||
|
||||
.section .text.rustix_syscall6_nr_last,"ax",%progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall6_nr_last
|
||||
.hidden rustix_syscall6_nr_last
|
||||
.type rustix_syscall6_nr_last, %function
|
||||
rustix_syscall6_nr_last:
|
||||
.fnstart
|
||||
.cantunwind
|
||||
push {r4, r5, r7, lr}
|
||||
add r7, sp, #16
|
||||
ldm r7, {r4, r5, r7}
|
||||
svc #0
|
||||
pop {r4, r5, r7, pc}
|
||||
.fnend
|
||||
.size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
|
||||
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_aarch64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_aarch64.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_arm.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_arm.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_mips.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_mips.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_mips64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_mips64.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_powerpc64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_powerpc64.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_riscv64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_riscv64.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_x86.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_x86.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_x86_64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/debug/librustix_outline_x86_64.a
vendored
Normal file
Binary file not shown.
213
vendor/rustix/src/backend/linux_raw/arch/outline/mips.s
vendored
Normal file
213
vendor/rustix/src/backend/linux_raw/arch/outline/mips.s
vendored
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
# Assembly code for making mips64 syscalls.
|
||||
#
|
||||
# mips64 syscall argument register ordering is the same as the mips64
|
||||
# userspace argument register ordering except that the syscall number
|
||||
# (nr) is passed in v0.
|
||||
#
|
||||
# outline.rs takes care of reordering the nr argument to the end for us,
|
||||
# so we only need to move nr into v0.
|
||||
|
||||
.file "mips.s"
|
||||
.section .mdebug.abi32
|
||||
.previous
|
||||
.abicalls
|
||||
|
||||
.section .text.rustix_syscall0_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall0_nr_last
|
||||
.hidden rustix_syscall0_nr_last
|
||||
.type rustix_syscall0_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall0_nr_last
|
||||
rustix_syscall0_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $4
|
||||
syscall
|
||||
negu $8, $2
|
||||
jr $31
|
||||
movn $2, $8, $7
|
||||
.end rustix_syscall0_nr_last
|
||||
.size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall1_nr_last
|
||||
.hidden rustix_syscall1_nr_last
|
||||
.type rustix_syscall1_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall1_nr_last
|
||||
rustix_syscall1_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $5
|
||||
syscall
|
||||
negu $8, $2
|
||||
jr $31
|
||||
movn $2, $8, $7
|
||||
.end rustix_syscall1_nr_last
|
||||
.size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall1_noreturn_nr_last
|
||||
.hidden rustix_syscall1_noreturn_nr_last
|
||||
.type rustix_syscall1_noreturn_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall1_noreturn_nr_last
|
||||
rustix_syscall1_noreturn_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $5
|
||||
syscall
|
||||
teq $zero, $zero
|
||||
.end rustix_syscall1_noreturn_nr_last
|
||||
.size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
|
||||
|
||||
.section .text.rustix_syscall2_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall2_nr_last
|
||||
.hidden rustix_syscall2_nr_last
|
||||
.type rustix_syscall2_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall2_nr_last
|
||||
rustix_syscall2_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $6
|
||||
syscall
|
||||
negu $8, $2
|
||||
jr $31
|
||||
movn $2, $8, $7
|
||||
.end rustix_syscall2_nr_last
|
||||
.size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
|
||||
|
||||
.section .text.rustix_syscall3_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall3_nr_last
|
||||
.hidden rustix_syscall3_nr_last
|
||||
.type rustix_syscall3_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall3_nr_last
|
||||
rustix_syscall3_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $7
|
||||
syscall
|
||||
negu $8, $2
|
||||
jr $31
|
||||
movn $2, $8, $7
|
||||
.end rustix_syscall3_nr_last
|
||||
.size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
|
||||
|
||||
.section .text.rustix_syscall4_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall4_nr_last
|
||||
.hidden rustix_syscall4_nr_last
|
||||
.type rustix_syscall4_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall4_nr_last
|
||||
rustix_syscall4_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
lw $2, 16($sp)
|
||||
syscall
|
||||
negu $8, $2
|
||||
jr $31
|
||||
movn $2, $8, $7
|
||||
.end rustix_syscall4_nr_last
|
||||
.size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
|
||||
|
||||
.section .text.rustix_syscall5_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall5_nr_last
|
||||
.hidden rustix_syscall5_nr_last
|
||||
.type rustix_syscall5_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall5_nr_last
|
||||
rustix_syscall5_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
lw $2, 20($sp)
|
||||
syscall
|
||||
negu $8, $2
|
||||
jr $31
|
||||
movn $2, $8, $7
|
||||
.end rustix_syscall5_nr_last
|
||||
.size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
|
||||
|
||||
.section .text.rustix_syscall6_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall6_nr_last
|
||||
.hidden rustix_syscall6_nr_last
|
||||
.type rustix_syscall6_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall6_nr_last
|
||||
rustix_syscall6_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
lw $2, 24($sp)
|
||||
syscall
|
||||
negu $8, $2
|
||||
jr $31
|
||||
movn $2, $8, $7
|
||||
.end rustix_syscall6_nr_last
|
||||
.size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
|
||||
.section .text.rustix_syscall7_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall7_nr_last
|
||||
.hidden rustix_syscall7_nr_last
|
||||
.type rustix_syscall7_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall7_nr_last
|
||||
rustix_syscall7_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
lw $2, 28($sp)
|
||||
syscall
|
||||
negu $8, $2
|
||||
jr $31
|
||||
movn $2, $8, $7
|
||||
.end rustix_syscall7_nr_last
|
||||
.size rustix_syscall7_nr_last, .-rustix_syscall7_nr_last
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
189
vendor/rustix/src/backend/linux_raw/arch/outline/mips64.s
vendored
Normal file
189
vendor/rustix/src/backend/linux_raw/arch/outline/mips64.s
vendored
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
# Assembly code for making mips64 syscalls.
|
||||
#
|
||||
# mips64 syscall argument register ordering is the same as the mips64
|
||||
# userspace argument register ordering except that the syscall number
|
||||
# (nr) is passed in v0.
|
||||
#
|
||||
# outline.rs takes care of reordering the nr argument to the end for us,
|
||||
# so we only need to move nr into v0.
|
||||
|
||||
.file "mips.s"
|
||||
.section .mdebug.abi64
|
||||
.previous
|
||||
.abicalls
|
||||
|
||||
.section .text.rustix_syscall0_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall0_nr_last
|
||||
.hidden rustix_syscall0_nr_last
|
||||
.type rustix_syscall0_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall0_nr_last
|
||||
rustix_syscall0_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $4
|
||||
syscall
|
||||
dnegu $12, $2
|
||||
jr $31
|
||||
movn $2, $12, $7
|
||||
.end rustix_syscall0_nr_last
|
||||
.size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall1_nr_last
|
||||
.hidden rustix_syscall1_nr_last
|
||||
.type rustix_syscall1_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall1_nr_last
|
||||
rustix_syscall1_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $5
|
||||
syscall
|
||||
dnegu $12, $2
|
||||
jr $31
|
||||
movn $2, $12, $7
|
||||
.end rustix_syscall1_nr_last
|
||||
.size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall1_noreturn_nr_last
|
||||
.hidden rustix_syscall1_noreturn_nr_last
|
||||
.type rustix_syscall1_noreturn_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall1_noreturn_nr_last
|
||||
rustix_syscall1_noreturn_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $5
|
||||
syscall
|
||||
teq $0, $0
|
||||
.end rustix_syscall1_noreturn_nr_last
|
||||
.size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
|
||||
|
||||
.section .text.rustix_syscall2_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall2_nr_last
|
||||
.hidden rustix_syscall2_nr_last
|
||||
.type rustix_syscall2_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall2_nr_last
|
||||
rustix_syscall2_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $6
|
||||
syscall
|
||||
dnegu $12, $2
|
||||
jr $31
|
||||
movn $2, $12, $7
|
||||
.end rustix_syscall2_nr_last
|
||||
.size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
|
||||
|
||||
.section .text.rustix_syscall3_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall3_nr_last
|
||||
.hidden rustix_syscall3_nr_last
|
||||
.type rustix_syscall3_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall3_nr_last
|
||||
rustix_syscall3_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $7
|
||||
syscall
|
||||
dnegu $12, $2
|
||||
jr $31
|
||||
movn $2, $12, $7
|
||||
.end rustix_syscall3_nr_last
|
||||
.size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
|
||||
|
||||
.section .text.rustix_syscall4_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall4_nr_last
|
||||
.hidden rustix_syscall4_nr_last
|
||||
.type rustix_syscall4_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall4_nr_last
|
||||
rustix_syscall4_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $8
|
||||
syscall
|
||||
dnegu $12, $2
|
||||
jr $31
|
||||
movn $2, $12, $7
|
||||
.end rustix_syscall4_nr_last
|
||||
.size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
|
||||
|
||||
.section .text.rustix_syscall5_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall5_nr_last
|
||||
.hidden rustix_syscall5_nr_last
|
||||
.type rustix_syscall5_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall5_nr_last
|
||||
rustix_syscall5_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $9
|
||||
syscall
|
||||
dnegu $12, $2
|
||||
jr $31
|
||||
movn $2, $12, $7
|
||||
.end rustix_syscall5_nr_last
|
||||
.size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
|
||||
|
||||
.section .text.rustix_syscall6_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall6_nr_last
|
||||
.hidden rustix_syscall6_nr_last
|
||||
.type rustix_syscall6_nr_last, @function
|
||||
.set nomips16
|
||||
.set nomicromips
|
||||
.ent rustix_syscall6_nr_last
|
||||
rustix_syscall6_nr_last:
|
||||
.frame $sp,0,$31
|
||||
.mask 0x00000000,0
|
||||
.fmask 0x00000000,0
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
move $2, $10
|
||||
syscall
|
||||
dnegu $12, $2
|
||||
jr $31
|
||||
movn $2, $12, $7
|
||||
.end rustix_syscall6_nr_last
|
||||
.size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
33
vendor/rustix/src/backend/linux_raw/arch/outline/mod.rs
vendored
Normal file
33
vendor/rustix/src/backend/linux_raw/arch/outline/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
//! Declare functions defined in out-of-line ("outline") asm files.
|
||||
//!
|
||||
//! Kernel calling conventions differ from userspace calling conventions,
|
||||
//! so we also define inline function wrappers which reorder the arguments
|
||||
//! so that they match with the kernel convention as closely as possible,
|
||||
//! to minimize the amount of out-of-line code we need.
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
mod x86;
|
||||
// For these architectures, pass the `nr` argument last.
|
||||
#[cfg(any(
|
||||
target_arch = "arm",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64",
|
||||
target_arch = "powerpc64",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "x86_64",
|
||||
))]
|
||||
mod nr_last;
|
||||
|
||||
#[cfg(any(
|
||||
target_arch = "arm",
|
||||
target_arch = "aarch64",
|
||||
target_arch = "mips",
|
||||
target_arch = "mips64",
|
||||
target_arch = "powerpc64",
|
||||
target_arch = "riscv64",
|
||||
target_arch = "x86_64",
|
||||
))]
|
||||
pub(in crate::backend) use nr_last::*;
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub(in crate::backend) use x86::*;
|
||||
166
vendor/rustix/src/backend/linux_raw/arch/outline/nr_last.rs
vendored
Normal file
166
vendor/rustix/src/backend/linux_raw/arch/outline/nr_last.rs
vendored
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
//! Syscall wrappers for platforms which pass the syscall number specially.
|
||||
//!
|
||||
//! Rustix aims to minimize the amount of assembly code it needs. To that end,
|
||||
//! this code reorders syscall arguments as close as feasible to the actual
|
||||
//! syscall convention before calling the assembly functions.
|
||||
//!
|
||||
//! Many architectures use a convention where the syscall number is passed in a
|
||||
//! special register, with the regular syscall arguments passed in either the
|
||||
//! same or similar registers as the platform C convention. This code
|
||||
//! approximates that order by passing the regular syscall arguments first, and
|
||||
//! the syscall number last. That way, the outline assembly code typically just
|
||||
//! needs to move the syscall number to its special register, and leave the
|
||||
//! other arguments mostly as they are.
|
||||
|
||||
#[cfg(target_arch = "mips")]
|
||||
use crate::backend::reg::A6;
|
||||
use crate::backend::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
|
||||
|
||||
// First we declare the actual assembly routines with `*_nr_last` names and
|
||||
// reordered arguments. If the signatures or calling conventions are ever
|
||||
// changed, the symbol names should also be updated accordingly, to avoid
|
||||
// collisions with other versions of this crate.
|
||||
//
|
||||
// We don't define `_readonly` versions of these because we have no way to tell
|
||||
// Rust that calls to our outline assembly are readonly.
|
||||
extern "C" {
|
||||
fn rustix_syscall0_nr_last(nr: SyscallNumber<'_>) -> RetReg<R0>;
|
||||
fn rustix_syscall1_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>;
|
||||
fn rustix_syscall1_noreturn_nr_last(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !;
|
||||
fn rustix_syscall2_nr_last(
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_syscall3_nr_last(
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_syscall4_nr_last(
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_syscall5_nr_last(
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_syscall6_nr_last(
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
#[cfg(target_arch = "mips")]
|
||||
fn rustix_syscall7_nr_last(
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
a6: ArgReg<'_, A6>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
}
|
||||
|
||||
// Then we define inline wrapper functions that do the reordering.
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
rustix_syscall0_nr_last(nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
rustix_syscall1_nr_last(a0, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
rustix_syscall1_noreturn_nr_last(a0, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall2_nr_last(a0, a1, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall3_nr_last(a0, a1, a2, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall4_nr_last(a0, a1, a2, a3, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall5_nr_last(a0, a1, a2, a3, a4, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall6_nr_last(a0, a1, a2, a3, a4, a5, nr)
|
||||
}
|
||||
#[cfg(target_arch = "mips")]
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall7(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
a6: ArgReg<'_, A6>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall7_nr_last(a0, a1, a2, a3, a4, a5, a6, nr)
|
||||
}
|
||||
|
||||
// Then we define the `_readonly` versions of the wrappers. We don't have
|
||||
// separate `_readonly` implementations, so these can just be aliases to
|
||||
// their non-`_readonly` counterparts.
|
||||
#[cfg(target_arch = "mips")]
|
||||
pub(in crate::backend) use syscall7 as syscall7_readonly;
|
||||
pub(in crate::backend) use {
|
||||
syscall0 as syscall0_readonly, syscall1 as syscall1_readonly, syscall2 as syscall2_readonly,
|
||||
syscall3 as syscall3_readonly, syscall4 as syscall4_readonly, syscall5 as syscall5_readonly,
|
||||
syscall6 as syscall6_readonly,
|
||||
};
|
||||
132
vendor/rustix/src/backend/linux_raw/arch/outline/powerpc64.s
vendored
Normal file
132
vendor/rustix/src/backend/linux_raw/arch/outline/powerpc64.s
vendored
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
# Assembly code for making powerpc64le syscalls.
|
||||
#
|
||||
# powerpc64le syscall argument register ordering is the same as the
|
||||
# powerpc64le userspace argument register ordering except that the syscall
|
||||
# number (nr) is passed in r0.
|
||||
#
|
||||
# outline.rs takes care of reordering the nr argument to the end for us,
|
||||
# so we only need to move nr into r0.
|
||||
|
||||
.file "powerpc64le.s"
|
||||
.machine power8
|
||||
.abiversion 2
|
||||
|
||||
.section .text.rustix_syscall0_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall0_nr_last
|
||||
.hidden rustix_syscall0_nr_last
|
||||
.type rustix_syscall0_nr_last, @function
|
||||
rustix_syscall0_nr_last:
|
||||
.cfi_startproc
|
||||
mr 0, 3
|
||||
sc
|
||||
bnslr
|
||||
neg 3, 3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall1_nr_last
|
||||
.hidden rustix_syscall1_nr_last
|
||||
.type rustix_syscall1_nr_last, @function
|
||||
rustix_syscall1_nr_last:
|
||||
.cfi_startproc
|
||||
mr 0, 4
|
||||
sc
|
||||
bnslr
|
||||
neg 3, 3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall1_noreturn_nr_last
|
||||
.hidden rustix_syscall1_noreturn_nr_last
|
||||
.type rustix_syscall1_noreturn_nr_last, @function
|
||||
rustix_syscall1_noreturn_nr_last:
|
||||
.cfi_startproc
|
||||
mr 0, 4
|
||||
sc
|
||||
trap
|
||||
.cfi_endproc
|
||||
.size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
|
||||
|
||||
.section .text.rustix_syscall2_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall2_nr_last
|
||||
.hidden rustix_syscall2_nr_last
|
||||
.type rustix_syscall2_nr_last, @function
|
||||
rustix_syscall2_nr_last:
|
||||
.cfi_startproc
|
||||
mr 0, 5
|
||||
sc
|
||||
bnslr
|
||||
neg 3, 3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
|
||||
|
||||
.section .text.rustix_syscall3_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall3_nr_last
|
||||
.hidden rustix_syscall3_nr_last
|
||||
.type rustix_syscall3_nr_last, @function
|
||||
rustix_syscall3_nr_last:
|
||||
.cfi_startproc
|
||||
mr 0, 6
|
||||
sc
|
||||
bnslr
|
||||
neg 3, 3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
|
||||
|
||||
.section .text.rustix_syscall4_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall4_nr_last
|
||||
.hidden rustix_syscall4_nr_last
|
||||
.type rustix_syscall4_nr_last, @function
|
||||
rustix_syscall4_nr_last:
|
||||
.cfi_startproc
|
||||
mr 0, 7
|
||||
sc
|
||||
bnslr
|
||||
neg 3, 3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
|
||||
|
||||
.section .text.rustix_syscall5_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall5_nr_last
|
||||
.hidden rustix_syscall5_nr_last
|
||||
.type rustix_syscall5_nr_last, @function
|
||||
rustix_syscall5_nr_last:
|
||||
.cfi_startproc
|
||||
mr 0, 8
|
||||
sc
|
||||
bnslr
|
||||
neg 3, 3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
|
||||
|
||||
.section .text.rustix_syscall6_nr_last,"ax",@progbits
|
||||
.p2align 2
|
||||
.weak rustix_syscall6_nr_last
|
||||
.hidden rustix_syscall6_nr_last
|
||||
.type rustix_syscall6_nr_last, @function
|
||||
rustix_syscall6_nr_last:
|
||||
.cfi_startproc
|
||||
mr 0, 9
|
||||
sc
|
||||
bnslr
|
||||
neg 3, 3
|
||||
blr
|
||||
.cfi_endproc
|
||||
.size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_aarch64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_aarch64.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_arm.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_arm.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_mips.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_mips.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_mips64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_mips64.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_powerpc64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_powerpc64.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_riscv64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_riscv64.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_x86.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_x86.a
vendored
Normal file
Binary file not shown.
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_x86_64.a
vendored
Normal file
BIN
vendor/rustix/src/backend/linux_raw/arch/outline/release/librustix_outline_x86_64.a
vendored
Normal file
Binary file not shown.
116
vendor/rustix/src/backend/linux_raw/arch/outline/riscv64.s
vendored
Normal file
116
vendor/rustix/src/backend/linux_raw/arch/outline/riscv64.s
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
# Assembly code for making riscv64 syscalls.
|
||||
#
|
||||
# riscv64 syscall argument register ordering is the same as the riscv64
|
||||
# userspace argument register ordering except that the syscall number
|
||||
# (nr) is passed in a7.
|
||||
#
|
||||
# nr_last.rs takes care of reordering the nr argument to the end for us,
|
||||
# so we only need to move nr into a7.
|
||||
|
||||
.file "riscv64.s"
|
||||
|
||||
.section .text.rustix_syscall0_nr_last,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall0_nr_last
|
||||
.hidden rustix_syscall0_nr_last
|
||||
.type rustix_syscall0_nr_last, @function
|
||||
rustix_syscall0_nr_last:
|
||||
.cfi_startproc
|
||||
mv a7, a0
|
||||
ecall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall0_nr_last, .-rustix_syscall0_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_nr_last,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall1_nr_last
|
||||
.hidden rustix_syscall1_nr_last
|
||||
.type rustix_syscall1_nr_last, @function
|
||||
rustix_syscall1_nr_last:
|
||||
.cfi_startproc
|
||||
mv a7, a1
|
||||
ecall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall1_nr_last, .-rustix_syscall1_nr_last
|
||||
|
||||
.section .text.rustix_syscall1_noreturn_nr_last,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall1_noreturn_nr_last
|
||||
.hidden rustix_syscall1_noreturn_nr_last
|
||||
.type rustix_syscall1_noreturn_nr_last, @function
|
||||
rustix_syscall1_noreturn_nr_last:
|
||||
.cfi_startproc
|
||||
mv a7, a1
|
||||
ecall
|
||||
unimp
|
||||
.cfi_endproc
|
||||
.size rustix_syscall1_noreturn_nr_last, .-rustix_syscall1_noreturn_nr_last
|
||||
|
||||
.section .text.rustix_syscall2_nr_last,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall2_nr_last
|
||||
.hidden rustix_syscall2_nr_last
|
||||
.type rustix_syscall2_nr_last, @function
|
||||
rustix_syscall2_nr_last:
|
||||
.cfi_startproc
|
||||
mv a7, a2
|
||||
ecall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall2_nr_last, .-rustix_syscall2_nr_last
|
||||
|
||||
.section .text.rustix_syscall3_nr_last,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall3_nr_last
|
||||
.hidden rustix_syscall3_nr_last
|
||||
.type rustix_syscall3_nr_last, @function
|
||||
rustix_syscall3_nr_last:
|
||||
.cfi_startproc
|
||||
mv a7, a3
|
||||
ecall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall3_nr_last, .-rustix_syscall3_nr_last
|
||||
|
||||
.section .text.rustix_syscall4_nr_last,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall4_nr_last
|
||||
.hidden rustix_syscall4_nr_last
|
||||
.type rustix_syscall4_nr_last, @function
|
||||
rustix_syscall4_nr_last:
|
||||
.cfi_startproc
|
||||
mv a7, a4
|
||||
ecall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall4_nr_last, .-rustix_syscall4_nr_last
|
||||
|
||||
.section .text.rustix_syscall5_nr_last,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall5_nr_last
|
||||
.hidden rustix_syscall5_nr_last
|
||||
.type rustix_syscall5_nr_last, @function
|
||||
rustix_syscall5_nr_last:
|
||||
.cfi_startproc
|
||||
mv a7, a5
|
||||
ecall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall5_nr_last, .-rustix_syscall5_nr_last
|
||||
|
||||
.section .text.rustix_syscall6_nr_last,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall6_nr_last
|
||||
.hidden rustix_syscall6_nr_last
|
||||
.type rustix_syscall6_nr_last, @function
|
||||
rustix_syscall6_nr_last:
|
||||
.cfi_startproc
|
||||
mv a7, a6
|
||||
ecall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
285
vendor/rustix/src/backend/linux_raw/arch/outline/x86.rs
vendored
Normal file
285
vendor/rustix/src/backend/linux_raw/arch/outline/x86.rs
vendored
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
//! Syscall wrappers for 32-bit x86.
|
||||
//!
|
||||
//! This module is similar to the `nr_last` module, except specialized for
|
||||
//! 32-bit x86.
|
||||
//!
|
||||
//! The syscall convention passes all arguments in registers. The closest we
|
||||
//! can easily get to that from Rust is to use the fastcall convention which
|
||||
//! passes the first two arguments in `ecx` and `edx`, which are the second
|
||||
//! and third Linux syscall arguments. To line them up, this function passes
|
||||
//! the second and third syscall argument as the first and second argument to
|
||||
//! the outline assembly, followed by the first syscall argument, and then the
|
||||
//! rest of the syscall arguments. The assembly code still has to do some work,
|
||||
//! but at least we can get up to two arguments into the right place for it.
|
||||
|
||||
#![allow(dead_code, unused_imports)]
|
||||
|
||||
use crate::backend::reg::{ArgReg, RetReg, SyscallNumber, A0, A1, A2, A3, A4, A5, R0};
|
||||
use crate::backend::vdso_wrappers::SyscallType;
|
||||
|
||||
// First we declare the actual assembly routines with `*_nr_last_fastcall`
|
||||
// names and reordered arguments. If the signatures or calling conventions are
|
||||
// ever changed, the symbol names should also be updated accordingly, to avoid
|
||||
// collisions with other versions of this crate.
|
||||
//
|
||||
// We don't define `_readonly` versions of these because we have no way to tell
|
||||
// Rust that calls to our outline assembly are readonly.
|
||||
extern "fastcall" {
|
||||
fn rustix_syscall0_nr_last_fastcall(nr: SyscallNumber<'_>) -> RetReg<R0>;
|
||||
fn rustix_syscall1_nr_last_fastcall(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> RetReg<R0>;
|
||||
fn rustix_syscall1_noreturn_nr_last_fastcall(a0: ArgReg<'_, A0>, nr: SyscallNumber<'_>) -> !;
|
||||
fn rustix_syscall2_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_syscall3_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_syscall4_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_syscall5_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_syscall6_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0>;
|
||||
}
|
||||
|
||||
// Then we define inline wrapper functions that do the reordering.
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall0(nr: SyscallNumber<'_>) -> RetReg<R0> {
|
||||
rustix_syscall0_nr_last_fastcall(nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> {
|
||||
rustix_syscall1_nr_last_fastcall(a0, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! {
|
||||
rustix_syscall1_noreturn_nr_last_fastcall(a0, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall2(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall2_nr_last_fastcall(a1, a0, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall3(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall3_nr_last_fastcall(a1, a2, a0, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall4(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall4_nr_last_fastcall(a1, a2, a0, a3, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall5(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall5_nr_last_fastcall(a1, a2, a0, a3, a4, nr)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn syscall6(
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_syscall6_nr_last_fastcall(a1, a2, a0, a3, a4, a5, nr)
|
||||
}
|
||||
|
||||
// Then we define the `_readonly` versions of the wrappers. We don't have
|
||||
// separate `_readonly` implementations, so these can just be aliases to
|
||||
// their non-`_readonly` counterparts.
|
||||
pub(in crate::backend) use {
|
||||
syscall0 as syscall0_readonly, syscall1 as syscall1_readonly, syscall2 as syscall2_readonly,
|
||||
syscall3 as syscall3_readonly, syscall4 as syscall4_readonly, syscall5 as syscall5_readonly,
|
||||
syscall6 as syscall6_readonly,
|
||||
};
|
||||
|
||||
// x86 prefers to route all syscalls through the vDSO, though this isn't
|
||||
// always possible, so it also has a special form for doing the dispatch.
|
||||
//
|
||||
// First we declare the actual assembly routines with `*_nr_last_fastcall`
|
||||
// names and reordered arguments. If the signatures or calling conventions are
|
||||
// ever changed, the symbol names should also be updated accordingly, to avoid
|
||||
// collisions with other versions of this crate.
|
||||
extern "fastcall" {
|
||||
fn rustix_indirect_syscall0_nr_last_fastcall(
|
||||
nr: SyscallNumber<'_>,
|
||||
callee: SyscallType,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_indirect_syscall1_nr_last_fastcall(
|
||||
a0: ArgReg<'_, A0>,
|
||||
nr: SyscallNumber<'_>,
|
||||
callee: SyscallType,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_indirect_syscall1_noreturn_nr_last_fastcall(
|
||||
a0: ArgReg<'_, A0>,
|
||||
nr: SyscallNumber<'_>,
|
||||
callee: SyscallType,
|
||||
) -> !;
|
||||
fn rustix_indirect_syscall2_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
nr: SyscallNumber<'_>,
|
||||
callee: SyscallType,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_indirect_syscall3_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
nr: SyscallNumber<'_>,
|
||||
callee: SyscallType,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_indirect_syscall4_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
nr: SyscallNumber<'_>,
|
||||
callee: SyscallType,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_indirect_syscall5_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
nr: SyscallNumber<'_>,
|
||||
callee: SyscallType,
|
||||
) -> RetReg<R0>;
|
||||
fn rustix_indirect_syscall6_nr_last_fastcall(
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
nr: SyscallNumber<'_>,
|
||||
callee: SyscallType,
|
||||
) -> RetReg<R0>;
|
||||
}
|
||||
|
||||
// Then we define inline wrapper functions that do the reordering.
|
||||
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall0(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_indirect_syscall0_nr_last_fastcall(nr, callee)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall1(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_indirect_syscall1_nr_last_fastcall(a0, nr, callee)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall1_noreturn(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
) -> ! {
|
||||
rustix_indirect_syscall1_noreturn_nr_last_fastcall(a0, nr, callee)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall2(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_indirect_syscall2_nr_last_fastcall(a1, a0, nr, callee)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall3(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_indirect_syscall3_nr_last_fastcall(a1, a2, a0, nr, callee)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall4(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_indirect_syscall4_nr_last_fastcall(a1, a2, a0, a3, nr, callee)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall5(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_indirect_syscall5_nr_last_fastcall(a1, a2, a0, a3, a4, nr, callee)
|
||||
}
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn indirect_syscall6(
|
||||
callee: SyscallType,
|
||||
nr: SyscallNumber<'_>,
|
||||
a0: ArgReg<'_, A0>,
|
||||
a1: ArgReg<'_, A1>,
|
||||
a2: ArgReg<'_, A2>,
|
||||
a3: ArgReg<'_, A3>,
|
||||
a4: ArgReg<'_, A4>,
|
||||
a5: ArgReg<'_, A5>,
|
||||
) -> RetReg<R0> {
|
||||
rustix_indirect_syscall6_nr_last_fastcall(a1, a2, a0, a3, a4, a5, nr, callee)
|
||||
}
|
||||
381
vendor/rustix/src/backend/linux_raw/arch/outline/x86.s
vendored
Normal file
381
vendor/rustix/src/backend/linux_raw/arch/outline/x86.s
vendored
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
// Assembly code for making x86 syscalls.
|
||||
//
|
||||
// On x86 we use the "fastcall" convention which passes the first two
|
||||
// arguments in ecx and edx. Outline.rs reorders the arguments to put
|
||||
// a1 and a2 in those registers so they we don't have to move them to
|
||||
// set up the kernel convention.
|
||||
//
|
||||
// "fastcall" expects callee to pop argument stack space, so we use
|
||||
// `ret imm` instructions to clean up the stack. We don't need callee
|
||||
// cleanup per se, it just comes along with using "fastcall".
|
||||
|
||||
.file "x86.s"
|
||||
.intel_syntax noprefix
|
||||
|
||||
.section .text.rustix_indirect_syscall0_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_indirect_syscall0_nr_last_fastcall
|
||||
.hidden rustix_indirect_syscall0_nr_last_fastcall
|
||||
.type rustix_indirect_syscall0_nr_last_fastcall, @function
|
||||
rustix_indirect_syscall0_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
mov eax,ecx
|
||||
call edx
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_indirect_syscall0_nr_last_fastcall, .-rustix_indirect_syscall0_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_indirect_syscall1_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_indirect_syscall1_nr_last_fastcall
|
||||
.hidden rustix_indirect_syscall1_nr_last_fastcall
|
||||
.type rustix_indirect_syscall1_nr_last_fastcall, @function
|
||||
rustix_indirect_syscall1_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,ecx
|
||||
mov eax,edx
|
||||
call DWORD PTR [esp+0x8]
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x4
|
||||
.cfi_endproc
|
||||
.size rustix_indirect_syscall1_nr_last_fastcall, .-rustix_indirect_syscall1_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_indirect_syscall1_noreturn_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_indirect_syscall1_noreturn_nr_last_fastcall
|
||||
.hidden rustix_indirect_syscall1_noreturn_nr_last_fastcall
|
||||
.type rustix_indirect_syscall1_noreturn_nr_last_fastcall, @function
|
||||
rustix_indirect_syscall1_noreturn_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
mov ebx,ecx
|
||||
mov eax,edx
|
||||
call DWORD PTR [esp+0x4]
|
||||
ud2
|
||||
.cfi_endproc
|
||||
.size rustix_indirect_syscall1_noreturn_nr_last_fastcall, .-rustix_indirect_syscall1_noreturn_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_indirect_syscall2_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_indirect_syscall2_nr_last_fastcall
|
||||
.hidden rustix_indirect_syscall2_nr_last_fastcall
|
||||
.type rustix_indirect_syscall2_nr_last_fastcall, @function
|
||||
rustix_indirect_syscall2_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,edx
|
||||
mov eax,DWORD PTR [esp+0x8]
|
||||
call DWORD PTR [esp+0xc]
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x8
|
||||
.cfi_endproc
|
||||
.size rustix_indirect_syscall2_nr_last_fastcall, .-rustix_indirect_syscall2_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_indirect_syscall3_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_indirect_syscall3_nr_last_fastcall
|
||||
.hidden rustix_indirect_syscall3_nr_last_fastcall
|
||||
.type rustix_indirect_syscall3_nr_last_fastcall, @function
|
||||
rustix_indirect_syscall3_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,DWORD PTR [esp+0x8]
|
||||
mov eax,DWORD PTR [esp+0xc]
|
||||
call DWORD PTR [esp+0x10]
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0xc
|
||||
.cfi_endproc
|
||||
.size rustix_indirect_syscall3_nr_last_fastcall, .-rustix_indirect_syscall3_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_indirect_syscall4_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_indirect_syscall4_nr_last_fastcall
|
||||
.hidden rustix_indirect_syscall4_nr_last_fastcall
|
||||
.type rustix_indirect_syscall4_nr_last_fastcall, @function
|
||||
rustix_indirect_syscall4_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
push esi
|
||||
.cfi_def_cfa_offset 12
|
||||
.cfi_offset esi, -12
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,DWORD PTR [esp+0xc]
|
||||
mov esi,DWORD PTR [esp+0x10]
|
||||
mov eax,DWORD PTR [esp+0x14]
|
||||
call DWORD PTR [esp+0x18]
|
||||
pop esi
|
||||
.cfi_def_cfa_offset 8
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x10
|
||||
.cfi_endproc
|
||||
.size rustix_indirect_syscall4_nr_last_fastcall, .-rustix_indirect_syscall4_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_indirect_syscall5_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_indirect_syscall5_nr_last_fastcall
|
||||
.hidden rustix_indirect_syscall5_nr_last_fastcall
|
||||
.type rustix_indirect_syscall5_nr_last_fastcall, @function
|
||||
rustix_indirect_syscall5_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
push esi
|
||||
.cfi_def_cfa_offset 12
|
||||
push edi
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset edi, -16
|
||||
.cfi_offset esi, -12
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,DWORD PTR [esp+0x10]
|
||||
mov esi,DWORD PTR [esp+0x14]
|
||||
mov edi,DWORD PTR [esp+0x18]
|
||||
mov eax,DWORD PTR [esp+0x1c]
|
||||
call DWORD PTR [esp+0x20]
|
||||
pop edi
|
||||
.cfi_def_cfa_offset 12
|
||||
pop esi
|
||||
.cfi_def_cfa_offset 8
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x14
|
||||
.cfi_endproc
|
||||
.size rustix_indirect_syscall5_nr_last_fastcall, .-rustix_indirect_syscall5_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_indirect_syscall6_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_indirect_syscall6_nr_last_fastcall
|
||||
.hidden rustix_indirect_syscall6_nr_last_fastcall
|
||||
.type rustix_indirect_syscall6_nr_last_fastcall, @function
|
||||
rustix_indirect_syscall6_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
push esi
|
||||
.cfi_def_cfa_offset 12
|
||||
push edi
|
||||
.cfi_def_cfa_offset 16
|
||||
push ebp
|
||||
.cfi_def_cfa_offset 20
|
||||
.cfi_offset ebp, -20
|
||||
.cfi_offset edi, -16
|
||||
.cfi_offset esi, -12
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,DWORD PTR [esp+0x14]
|
||||
mov esi,DWORD PTR [esp+0x18]
|
||||
mov edi,DWORD PTR [esp+0x1c]
|
||||
mov ebp,DWORD PTR [esp+0x20]
|
||||
mov eax,DWORD PTR [esp+0x24]
|
||||
call DWORD PTR [esp+0x28]
|
||||
pop ebp
|
||||
.cfi_def_cfa_offset 16
|
||||
pop edi
|
||||
.cfi_def_cfa_offset 12
|
||||
pop esi
|
||||
.cfi_def_cfa_offset 8
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x18
|
||||
.cfi_endproc
|
||||
.size rustix_indirect_syscall6_nr_last_fastcall, .-rustix_indirect_syscall6_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_syscall0_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall0_nr_last_fastcall
|
||||
.hidden rustix_syscall0_nr_last_fastcall
|
||||
.type rustix_syscall0_nr_last_fastcall, @function
|
||||
rustix_syscall0_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
mov eax,ecx
|
||||
int 0x80
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall0_nr_last_fastcall, .-rustix_syscall0_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_syscall1_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall1_nr_last_fastcall
|
||||
.hidden rustix_syscall1_nr_last_fastcall
|
||||
.type rustix_syscall1_nr_last_fastcall, @function
|
||||
rustix_syscall1_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_offset ebx, -8
|
||||
mov eax,edx
|
||||
mov ebx,ecx
|
||||
int 0x80
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall1_nr_last_fastcall, .-rustix_syscall1_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_syscall1_noreturn_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall1_noreturn_nr_last_fastcall
|
||||
.hidden rustix_syscall1_noreturn_nr_last_fastcall
|
||||
.type rustix_syscall1_noreturn_nr_last_fastcall, @function
|
||||
rustix_syscall1_noreturn_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
mov eax,edx
|
||||
mov ebx,ecx
|
||||
int 0x80
|
||||
ud2
|
||||
.cfi_endproc
|
||||
.size rustix_syscall1_noreturn_nr_last_fastcall, .-rustix_syscall1_noreturn_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_syscall2_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall2_nr_last_fastcall
|
||||
.hidden rustix_syscall2_nr_last_fastcall
|
||||
.type rustix_syscall2_nr_last_fastcall, @function
|
||||
rustix_syscall2_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,edx
|
||||
mov eax,DWORD PTR [esp+0x8]
|
||||
int 0x80
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x4
|
||||
.cfi_endproc
|
||||
.size rustix_syscall2_nr_last_fastcall, .-rustix_syscall2_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_syscall3_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall3_nr_last_fastcall
|
||||
.hidden rustix_syscall3_nr_last_fastcall
|
||||
.type rustix_syscall3_nr_last_fastcall, @function
|
||||
rustix_syscall3_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,DWORD PTR [esp+0x8]
|
||||
mov eax,DWORD PTR [esp+0xc]
|
||||
int 0x80
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x8
|
||||
.cfi_endproc
|
||||
.size rustix_syscall3_nr_last_fastcall, .-rustix_syscall3_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_syscall4_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall4_nr_last_fastcall
|
||||
.hidden rustix_syscall4_nr_last_fastcall
|
||||
.type rustix_syscall4_nr_last_fastcall, @function
|
||||
rustix_syscall4_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
push esi
|
||||
.cfi_def_cfa_offset 12
|
||||
.cfi_offset esi, -12
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,DWORD PTR [esp+0xc]
|
||||
mov esi,DWORD PTR [esp+0x10]
|
||||
mov eax,DWORD PTR [esp+0x14]
|
||||
int 0x80
|
||||
pop esi
|
||||
.cfi_def_cfa_offset 8
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0xc
|
||||
.cfi_endproc
|
||||
.size rustix_syscall4_nr_last_fastcall, .-rustix_syscall4_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_syscall5_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall5_nr_last_fastcall
|
||||
.hidden rustix_syscall5_nr_last_fastcall
|
||||
.type rustix_syscall5_nr_last_fastcall, @function
|
||||
rustix_syscall5_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
push edi
|
||||
.cfi_def_cfa_offset 12
|
||||
push esi
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_offset esi, -16
|
||||
.cfi_offset edi, -12
|
||||
.cfi_offset ebx, -8
|
||||
mov ebx,DWORD PTR [esp+0x10]
|
||||
mov esi,DWORD PTR [esp+0x14]
|
||||
mov edi,DWORD PTR [esp+0x18]
|
||||
mov eax,DWORD PTR [esp+0x1c]
|
||||
int 0x80
|
||||
pop esi
|
||||
.cfi_def_cfa_offset 12
|
||||
pop edi
|
||||
.cfi_def_cfa_offset 8
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x10
|
||||
.cfi_endproc
|
||||
.size rustix_syscall5_nr_last_fastcall, .-rustix_syscall5_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_syscall6_nr_last_fastcall,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_syscall6_nr_last_fastcall
|
||||
.hidden rustix_syscall6_nr_last_fastcall
|
||||
.type rustix_syscall6_nr_last_fastcall, @function
|
||||
rustix_syscall6_nr_last_fastcall:
|
||||
.cfi_startproc
|
||||
push ebp
|
||||
.cfi_def_cfa_offset 8
|
||||
push ebx
|
||||
.cfi_def_cfa_offset 12
|
||||
push edi
|
||||
.cfi_def_cfa_offset 16
|
||||
push esi
|
||||
.cfi_def_cfa_offset 20
|
||||
.cfi_offset esi, -20
|
||||
.cfi_offset edi, -16
|
||||
.cfi_offset ebx, -12
|
||||
.cfi_offset ebp, -8
|
||||
mov ebx,DWORD PTR [esp+0x14]
|
||||
mov esi,DWORD PTR [esp+0x18]
|
||||
mov edi,DWORD PTR [esp+0x1c]
|
||||
mov ebp,DWORD PTR [esp+0x20]
|
||||
mov eax,DWORD PTR [esp+0x24]
|
||||
int 0x80
|
||||
pop esi
|
||||
.cfi_def_cfa_offset 16
|
||||
pop edi
|
||||
.cfi_def_cfa_offset 12
|
||||
pop ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
pop ebp
|
||||
.cfi_def_cfa_offset 4
|
||||
ret 0x14
|
||||
.cfi_endproc
|
||||
.size rustix_syscall6_nr_last_fastcall, .-rustix_syscall6_nr_last_fastcall
|
||||
|
||||
.section .text.rustix_int_0x80,"ax",@progbits
|
||||
.p2align 4
|
||||
.weak rustix_int_0x80
|
||||
.hidden rustix_int_0x80
|
||||
.type rustix_int_0x80, @function
|
||||
rustix_int_0x80:
|
||||
.cfi_startproc
|
||||
int 0x80
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_int_0x80, .-rustix_int_0x80
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue