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
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
|
||||
122
vendor/rustix/src/backend/linux_raw/arch/outline/x86_64.s
vendored
Normal file
122
vendor/rustix/src/backend/linux_raw/arch/outline/x86_64.s
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Assembly code for making x86-64 syscalls.
|
||||
//
|
||||
// x86-64 syscall argument register ordering is the same as the x86-64
|
||||
// userspace argument register ordering except that a3 is passed in r10
|
||||
// instead of rcx, and the syscall number (nr) is passed in eax.
|
||||
//
|
||||
// outline.rs takes care of reordering the nr argument to the end for us,
|
||||
// so we only need to move nr into eax and move rcx into r10 as needed.
|
||||
//
|
||||
// x32 is not yet supported.
|
||||
|
||||
.file "x86_64.s"
|
||||
.intel_syntax noprefix
|
||||
|
||||
.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
|
||||
mov eax,edi
|
||||
syscall
|
||||
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
|
||||
mov eax,esi
|
||||
syscall
|
||||
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
|
||||
mov eax,esi
|
||||
syscall
|
||||
ud2
|
||||
.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
|
||||
mov eax,edx
|
||||
syscall
|
||||
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
|
||||
mov eax,ecx
|
||||
syscall
|
||||
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
|
||||
mov eax,r8d
|
||||
mov r10,rcx
|
||||
syscall
|
||||
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
|
||||
mov eax,r9d
|
||||
mov r10,rcx
|
||||
syscall
|
||||
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
|
||||
mov eax,DWORD PTR [rsp+0x8]
|
||||
mov r10,rcx
|
||||
syscall
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size rustix_syscall6_nr_last, .-rustix_syscall6_nr_last
|
||||
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
29
vendor/rustix/src/backend/linux_raw/c.rs
vendored
Normal file
29
vendor/rustix/src/backend/linux_raw/c.rs
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
//! Adapt the Linux API to resemble a POSIX-style libc API.
|
||||
//!
|
||||
//! The linux_raw backend doesn't use actual libc; this just defines certain
|
||||
//! types that are convenient to have defined.
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
pub(crate) use linux_raw_sys::ctypes::*;
|
||||
pub(crate) use linux_raw_sys::errno::EINVAL;
|
||||
pub(crate) use linux_raw_sys::general::{
|
||||
AF_DECnet, __kernel_sa_family_t as sa_family_t, __kernel_sockaddr_storage as sockaddr_storage,
|
||||
in6_addr, in_addr, iovec, ip_mreq, ipv6_mreq, linger, sockaddr, sockaddr_in, sockaddr_in6,
|
||||
sockaddr_un, socklen_t, AF_APPLETALK, AF_ASH, AF_ATMPVC, AF_ATMSVC, AF_AX25, AF_BLUETOOTH,
|
||||
AF_BRIDGE, AF_CAN, AF_ECONET, AF_IEEE802154, AF_INET, AF_INET6, AF_IPX, AF_IRDA, AF_ISDN,
|
||||
AF_IUCV, AF_KEY, AF_LLC, AF_NETBEUI, AF_NETLINK, AF_NETROM, AF_PACKET, AF_PHONET, AF_PPPOX,
|
||||
AF_RDS, AF_ROSE, AF_RXRPC, AF_SECURITY, AF_SNA, AF_TIPC, AF_UNIX, AF_UNSPEC, AF_WANPIPE,
|
||||
AF_X25, IPPROTO_AH, IPPROTO_BEETPH, IPPROTO_COMP, IPPROTO_DCCP, IPPROTO_EGP, IPPROTO_ENCAP,
|
||||
IPPROTO_ESP, IPPROTO_ETHERNET, IPPROTO_FRAGMENT, IPPROTO_GRE, IPPROTO_ICMP, IPPROTO_ICMPV6,
|
||||
IPPROTO_IDP, IPPROTO_IGMP, IPPROTO_IP, IPPROTO_IPIP, IPPROTO_IPV6, IPPROTO_MH, IPPROTO_MPLS,
|
||||
IPPROTO_MPTCP, IPPROTO_MTP, IPPROTO_PIM, IPPROTO_PUP, IPPROTO_RAW, IPPROTO_ROUTING,
|
||||
IPPROTO_RSVP, IPPROTO_SCTP, IPPROTO_TCP, IPPROTO_TP, IPPROTO_UDP, IPPROTO_UDPLITE,
|
||||
IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP, IPV6_MULTICAST_LOOP, IPV6_V6ONLY, IP_ADD_MEMBERSHIP,
|
||||
IP_DROP_MEMBERSHIP, IP_MULTICAST_LOOP, IP_MULTICAST_TTL, IP_TTL, MSG_CMSG_CLOEXEC, MSG_CONFIRM,
|
||||
MSG_DONTROUTE, MSG_DONTWAIT, MSG_EOR, MSG_ERRQUEUE, MSG_MORE, MSG_NOSIGNAL, MSG_OOB, MSG_PEEK,
|
||||
MSG_TRUNC, MSG_WAITALL, O_CLOEXEC, O_NONBLOCK, SHUT_RD, SHUT_RDWR, SHUT_WR, SOCK_DGRAM,
|
||||
SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET, SOCK_STREAM, SOL_SOCKET, SO_BROADCAST, SO_LINGER,
|
||||
SO_PASSCRED, SO_RCVTIMEO_NEW, SO_RCVTIMEO_OLD, SO_REUSEADDR, SO_SNDTIMEO_NEW, SO_SNDTIMEO_OLD,
|
||||
SO_TYPE, TCP_NODELAY,
|
||||
};
|
||||
790
vendor/rustix/src/backend/linux_raw/conv.rs
vendored
Normal file
790
vendor/rustix/src/backend/linux_raw/conv.rs
vendored
Normal file
|
|
@ -0,0 +1,790 @@
|
|||
//! Convert values to [`ArgReg`] and from [`RetReg`].
|
||||
//!
|
||||
//! System call arguments and return values are all communicated with inline
|
||||
//! asm and FFI as `*mut Opaque`. To protect these raw pointers from escaping
|
||||
//! or being accidentally misused as they travel through the code, we wrap
|
||||
//! them in [`ArgReg`] and [`RetReg`] structs. This file provides `From`
|
||||
//! implementations and explicit conversion functions for converting values
|
||||
//! into and out of these wrapper structs.
|
||||
//!
|
||||
//! # Safety
|
||||
//!
|
||||
//! Some of this code is `unsafe` in order to work with raw file descriptors,
|
||||
//! and some is `unsafe` to interpret the values in a `RetReg`.
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use super::c;
|
||||
use super::fd::{AsRawFd, BorrowedFd, FromRawFd, RawFd};
|
||||
#[cfg(not(debug_assertions))]
|
||||
use super::io::errno::decode_usize_infallible;
|
||||
#[cfg(feature = "runtime")]
|
||||
use super::io::errno::try_decode_error;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
use super::io::errno::try_decode_u64;
|
||||
use super::io::errno::{
|
||||
try_decode_c_int, try_decode_c_uint, try_decode_raw_fd, try_decode_usize, try_decode_void,
|
||||
try_decode_void_star,
|
||||
};
|
||||
use super::reg::{raw_arg, ArgNumber, ArgReg, RetReg, R0};
|
||||
#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
|
||||
use super::time::types::ClockId;
|
||||
#[cfg(feature = "time")]
|
||||
use super::time::types::TimerfdClockId;
|
||||
use crate::fd::OwnedFd;
|
||||
use crate::ffi::CStr;
|
||||
#[cfg(feature = "fs")]
|
||||
use crate::fs::{FileType, Mode, OFlags};
|
||||
use crate::io;
|
||||
use crate::process::{Pid, Resource, Signal};
|
||||
use crate::utils::{as_mut_ptr, as_ptr};
|
||||
use core::mem::MaybeUninit;
|
||||
use core::ptr::null_mut;
|
||||
#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
|
||||
use linux_raw_sys::general::__kernel_clockid_t;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
use linux_raw_sys::general::__kernel_loff_t;
|
||||
#[cfg(feature = "net")]
|
||||
use linux_raw_sys::general::socklen_t;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[cfg(feature = "fs")]
|
||||
use linux_raw_sys::general::O_LARGEFILE;
|
||||
|
||||
/// Convert `SYS_*` constants for socketcall.
|
||||
#[cfg(target_arch = "x86")]
|
||||
#[inline]
|
||||
pub(super) fn x86_sys<'a, Num: ArgNumber>(sys: u32) -> ArgReg<'a, Num> {
|
||||
pass_usize(sys as usize)
|
||||
}
|
||||
|
||||
/// Pass the "low" half of the endian-specific memory encoding of a `u64`, for
|
||||
/// 32-bit architectures.
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[inline]
|
||||
pub(super) fn lo<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num> {
|
||||
#[cfg(target_endian = "little")]
|
||||
let x = x >> 32;
|
||||
#[cfg(target_endian = "big")]
|
||||
let x = x & 0xffff_ffff;
|
||||
|
||||
pass_usize(x as usize)
|
||||
}
|
||||
|
||||
/// Pass the "high" half of the endian-specific memory encoding of a `u64`, for
|
||||
/// 32-bit architectures.
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[inline]
|
||||
pub(super) fn hi<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num> {
|
||||
#[cfg(target_endian = "little")]
|
||||
let x = x & 0xffff_ffff;
|
||||
#[cfg(target_endian = "big")]
|
||||
let x = x >> 32;
|
||||
|
||||
pass_usize(x as usize)
|
||||
}
|
||||
|
||||
/// Pass a zero, or null, argument.
|
||||
#[inline]
|
||||
pub(super) fn zero<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
|
||||
raw_arg(null_mut())
|
||||
}
|
||||
|
||||
/// Pass the `mem::size_of` of a type.
|
||||
#[inline]
|
||||
pub(super) fn size_of<'a, T: Sized, Num: ArgNumber>() -> ArgReg<'a, Num> {
|
||||
pass_usize(core::mem::size_of::<T>())
|
||||
}
|
||||
|
||||
/// Pass an arbitrary `usize` value.
|
||||
///
|
||||
/// For passing pointers, use `void_star` or other functions which take a raw
|
||||
/// pointer instead of casting to `usize`, so that provenance is preserved.
|
||||
#[inline]
|
||||
pub(super) fn pass_usize<'a, Num: ArgNumber>(t: usize) -> ArgReg<'a, Num> {
|
||||
raw_arg(t as *mut _)
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber, T> From<*mut T> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(c: *mut T) -> ArgReg<'a, Num> {
|
||||
raw_arg(c.cast())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber, T> From<*const T> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(c: *const T) -> ArgReg<'a, Num> {
|
||||
let mut_ptr = c as *mut T;
|
||||
raw_arg(mut_ptr.cast())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<&'a CStr> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(c: &'a CStr) -> Self {
|
||||
let mut_ptr = c.as_ptr() as *mut u8;
|
||||
raw_arg(mut_ptr.cast())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<Option<&'a CStr>> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(t: Option<&'a CStr>) -> Self {
|
||||
raw_arg(match t {
|
||||
Some(s) => {
|
||||
let mut_ptr = s.as_ptr() as *mut u8;
|
||||
mut_ptr.cast()
|
||||
}
|
||||
None => null_mut(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Pass a borrowed file-descriptor argument.
|
||||
impl<'a, Num: ArgNumber> From<BorrowedFd<'a>> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(fd: BorrowedFd<'a>) -> Self {
|
||||
// Safety: `BorrowedFd` ensures that the file descriptor is valid, and the
|
||||
// lifetime parameter on the resulting `ArgReg` ensures that the result is
|
||||
// bounded by the `BorrowedFd`'s lifetime.
|
||||
unsafe { raw_fd(fd.as_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Pass a raw file-descriptor argument. Most users should use [`ArgReg::from`]
|
||||
/// instead, to preserve I/O safety as long as possible.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `fd` must be a valid open file descriptor.
|
||||
#[inline]
|
||||
pub(super) unsafe fn raw_fd<'a, Num: ArgNumber>(fd: RawFd) -> ArgReg<'a, Num> {
|
||||
// Use `no_fd` when passing `-1` is intended.
|
||||
#[cfg(feature = "fs")]
|
||||
debug_assert!(fd == crate::fs::cwd().as_raw_fd() || fd >= 0);
|
||||
|
||||
// Don't pass the `io_uring_register_files_skip` sentry value this way.
|
||||
#[cfg(feature = "io_uring")]
|
||||
debug_assert_ne!(
|
||||
fd,
|
||||
crate::io_uring::io_uring_register_files_skip().as_raw_fd()
|
||||
);
|
||||
|
||||
// Linux doesn't look at the high bits beyond the `c_int`, so use
|
||||
// zero-extension rather than sign-extension because it's a smaller
|
||||
// instruction.
|
||||
let fd: c::c_int = fd;
|
||||
pass_usize(fd as c::c_uint as usize)
|
||||
}
|
||||
|
||||
/// Deliberately pass `-1` to a file-descriptor argument, for system calls
|
||||
/// like `mmap` where this indicates the argument is omitted.
|
||||
#[inline]
|
||||
pub(super) fn no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
|
||||
pass_usize(!0_usize)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<Num> {
|
||||
let mut_ptr = v.as_ptr() as *mut T;
|
||||
raw_arg(mut_ptr.cast())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn slice<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
|
||||
v: &[T],
|
||||
) -> (ArgReg<Num0>, ArgReg<Num1>) {
|
||||
(slice_just_addr(v), pass_usize(v.len()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
|
||||
v: &mut [T],
|
||||
) -> (ArgReg<Num0>, ArgReg<Num1>) {
|
||||
(raw_arg(v.as_mut_ptr().cast()), pass_usize(v.len()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<Num> {
|
||||
let mut_ptr = as_ptr(t) as *mut T;
|
||||
raw_arg(mut_ptr.cast())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<Num> {
|
||||
raw_arg(as_mut_ptr(t).cast())
|
||||
}
|
||||
|
||||
/// Convert an optional mutable reference into a `usize` for passing to a
|
||||
/// syscall.
|
||||
#[inline]
|
||||
pub(super) fn opt_mut<T: Sized, Num: ArgNumber>(t: Option<&mut T>) -> ArgReg<Num> {
|
||||
// This optimizes into the equivalent of `transmute(t)`, and has the
|
||||
// advantage of not requiring `unsafe`.
|
||||
match t {
|
||||
Some(t) => by_mut(t),
|
||||
None => raw_arg(null_mut()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an optional immutable reference into a `usize` for passing to a
|
||||
/// syscall.
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
|
||||
#[inline]
|
||||
pub(super) fn opt_ref<T: Sized, Num: ArgNumber>(t: Option<&T>) -> ArgReg<Num> {
|
||||
// This optimizes into the equivalent of `transmute(t)`, and has the
|
||||
// advantage of not requiring `unsafe`.
|
||||
match t {
|
||||
Some(t) => by_ref(t),
|
||||
None => raw_arg(null_mut()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `c_int` into an `ArgReg`.
|
||||
///
|
||||
/// Be sure to use `raw_fd` to pass `RawFd` values.
|
||||
#[inline]
|
||||
pub(super) fn c_int<'a, Num: ArgNumber>(i: c::c_int) -> ArgReg<'a, Num> {
|
||||
pass_usize(i as usize)
|
||||
}
|
||||
|
||||
/// Convert a `c_uint` into an `ArgReg`.
|
||||
#[inline]
|
||||
pub(super) fn c_uint<'a, Num: ArgNumber>(i: c::c_uint) -> ArgReg<'a, Num> {
|
||||
pass_usize(i as usize)
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[inline]
|
||||
pub(super) fn loff_t<'a, Num: ArgNumber>(i: __kernel_loff_t) -> ArgReg<'a, Num> {
|
||||
pass_usize(i as usize)
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[inline]
|
||||
pub(super) fn loff_t_from_u64<'a, Num: ArgNumber>(i: u64) -> ArgReg<'a, Num> {
|
||||
// `loff_t` is signed, but syscalls which expect `loff_t` return `EINVAL`
|
||||
// if it's outside the signed `i64` range, so we can silently cast.
|
||||
pass_usize(i as usize)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
|
||||
impl<'a, Num: ArgNumber> From<ClockId> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(i: ClockId) -> Self {
|
||||
pass_usize(i as __kernel_clockid_t as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "time")]
|
||||
impl<'a, Num: ArgNumber> From<TimerfdClockId> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(i: TimerfdClockId) -> Self {
|
||||
pass_usize(i as __kernel_clockid_t as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
#[inline]
|
||||
pub(super) fn socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num> {
|
||||
pass_usize(i as usize)
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<Mode> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(mode: Mode) -> Self {
|
||||
pass_usize(mode.bits() as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(pair: (Mode, FileType)) -> Self {
|
||||
pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<crate::fs::AtFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::fs::AtFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<crate::fs::MemfdFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::fs::MemfdFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<crate::fs::RenameFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::fs::RenameFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<crate::fs::StatxFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::fs::StatxFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<crate::io::FdFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::io::FdFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<crate::io::PipeFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::io::PipeFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<crate::io::DupFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::io::DupFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<crate::io::ReadWriteFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::io::ReadWriteFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<crate::io::EventfdFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::io::EventfdFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<crate::io::epoll::CreateFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::io::epoll::CreateFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mm")]
|
||||
impl<'a, Num: ArgNumber> From<crate::backend::mm::types::ProtFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::backend::mm::types::ProtFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mm")]
|
||||
impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MsyncFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::backend::mm::types::MsyncFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mm")]
|
||||
impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MremapFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::backend::mm::types::MremapFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mm")]
|
||||
impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::backend::mm::types::MlockFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mm")]
|
||||
impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MapFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::backend::mm::types::MapFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mm")]
|
||||
impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MprotectFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::backend::mm::types::MprotectFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "mm")]
|
||||
impl<'a, Num: ArgNumber> From<crate::backend::mm::types::UserfaultfdFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::backend::mm::types::UserfaultfdFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<crate::backend::process::types::MembarrierCommand>
|
||||
for ArgReg<'a, Num>
|
||||
{
|
||||
#[inline]
|
||||
fn from(cmd: crate::backend::process::types::MembarrierCommand) -> Self {
|
||||
c_uint(cmd as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<crate::process::Cpuid> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(cpuid: crate::process::Cpuid) -> Self {
|
||||
c_uint(cpuid.as_raw())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[inline]
|
||||
pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> ArgReg<'a, Num> {
|
||||
pass_usize(dev as usize)
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[inline]
|
||||
pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> io::Result<ArgReg<'a, Num>> {
|
||||
use core::convert::TryInto;
|
||||
Ok(pass_usize(dev.try_into().map_err(|_err| io::Errno::INVAL)?))
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[cfg(feature = "fs")]
|
||||
#[inline]
|
||||
fn oflags_bits(oflags: OFlags) -> c::c_uint {
|
||||
let mut bits = oflags.bits();
|
||||
// Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL`
|
||||
// when both are set.
|
||||
if !oflags.contains(OFlags::PATH) {
|
||||
bits |= O_LARGEFILE;
|
||||
}
|
||||
bits
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[cfg(feature = "fs")]
|
||||
#[inline]
|
||||
const fn oflags_bits(oflags: OFlags) -> c::c_uint {
|
||||
oflags.bits()
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<OFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(oflags: OFlags) -> Self {
|
||||
pass_usize(oflags_bits(oflags) as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an `OFlags` into a `u64` for use in the `open_how` struct.
|
||||
#[cfg(feature = "fs")]
|
||||
#[inline]
|
||||
pub(super) fn oflags_for_open_how(oflags: OFlags) -> u64 {
|
||||
u64::from(oflags_bits(oflags))
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<crate::fs::FallocateFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::fs::FallocateFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `Resource` into a syscall argument.
|
||||
impl<'a, Num: ArgNumber> From<Resource> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(resource: Resource) -> Self {
|
||||
c_uint(resource as c::c_uint)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<Pid> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(pid: Pid) -> Self {
|
||||
pass_usize(pid.as_raw_nonzero().get() as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn negative_pid<'a, Num: ArgNumber>(pid: Pid) -> ArgReg<'a, Num> {
|
||||
pass_usize(pid.as_raw_nonzero().get().wrapping_neg() as usize)
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber> From<Signal> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(sig: Signal) -> Self {
|
||||
pass_usize(sig as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<crate::fs::Advice> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(advice: crate::fs::Advice) -> Self {
|
||||
c_uint(advice as c::c_uint)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<crate::fs::SealFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::fs::SealFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "io_uring")]
|
||||
impl<'a, Num: ArgNumber> From<crate::io_uring::IoringEnterFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::io_uring::IoringEnterFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "time")]
|
||||
impl<'a, Num: ArgNumber> From<crate::time::TimerfdFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::time::TimerfdFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "time")]
|
||||
impl<'a, Num: ArgNumber> From<crate::time::TimerfdTimerFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::time::TimerfdTimerFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rand")]
|
||||
impl<'a, Num: ArgNumber> From<crate::rand::GetRandomFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::rand::GetRandomFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl<'a, Num: ArgNumber> From<crate::net::RecvFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::net::RecvFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl<'a, Num: ArgNumber> From<crate::net::SendFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::net::SendFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl<'a, Num: ArgNumber> From<crate::net::AcceptFlags> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(flags: crate::net::AcceptFlags) -> Self {
|
||||
c_uint(flags.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl<'a, Num: ArgNumber> From<crate::net::AddressFamily> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(family: crate::net::AddressFamily) -> Self {
|
||||
c_uint(family.0.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl<'a, Num: ArgNumber> From<(crate::net::SocketType, crate::net::SocketFlags)>
|
||||
for ArgReg<'a, Num>
|
||||
{
|
||||
#[inline]
|
||||
fn from(pair: (crate::net::SocketType, crate::net::SocketFlags)) -> Self {
|
||||
c_uint(pair.0 .0 | pair.1.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "thread")]
|
||||
impl<'a, Num: ArgNumber> From<(crate::thread::FutexOperation, crate::thread::FutexFlags)>
|
||||
for ArgReg<'a, Num>
|
||||
{
|
||||
#[inline]
|
||||
fn from(pair: (crate::thread::FutexOperation, crate::thread::FutexFlags)) -> Self {
|
||||
c_uint(pair.0 as u32 | pair.1.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
impl<'a, Num: ArgNumber> From<crate::fs::Access> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(access: crate::fs::Access) -> Self {
|
||||
c_uint(access.bits())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl<'a, Num: ArgNumber> From<crate::net::SocketType> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(type_: crate::net::SocketType) -> Self {
|
||||
c_uint(type_.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl<'a, Num: ArgNumber> From<crate::net::Protocol> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(protocol: crate::net::Protocol) -> Self {
|
||||
c_uint(protocol.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> {
|
||||
#[inline]
|
||||
fn from(t: &'a mut MaybeUninit<T>) -> Self {
|
||||
raw_arg(t.as_mut_ptr().cast())
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively returns `()` on
|
||||
/// success.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that this is the return value of a syscall which
|
||||
/// just returns 0 on success.
|
||||
#[inline]
|
||||
pub(super) unsafe fn ret(raw: RetReg<R0>) -> io::Result<()> {
|
||||
try_decode_void(raw)
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that doesn't return on success.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that this is the return value of a syscall which
|
||||
/// doesn't return on success.
|
||||
#[cfg(feature = "runtime")]
|
||||
#[inline]
|
||||
pub(super) unsafe fn ret_error(raw: RetReg<R0>) -> io::Errno {
|
||||
try_decode_error(raw)
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively always returns
|
||||
/// `()`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that this is the return value of a syscall which
|
||||
/// always returns `()`.
|
||||
#[inline]
|
||||
pub(super) unsafe fn ret_infallible(raw: RetReg<R0>) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
try_decode_void(raw).unwrap()
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
drop(raw);
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively returns a
|
||||
/// `c_int` on success.
|
||||
#[inline]
|
||||
pub(super) fn ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int> {
|
||||
try_decode_c_int(raw)
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively returns a
|
||||
/// `c_uint` on success.
|
||||
#[inline]
|
||||
pub(super) fn ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint> {
|
||||
try_decode_c_uint(raw)
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively returns a `u64`
|
||||
/// on success.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[inline]
|
||||
pub(super) fn ret_u64(raw: RetReg<R0>) -> io::Result<u64> {
|
||||
try_decode_u64(raw)
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively returns a
|
||||
/// `usize` on success.
|
||||
#[inline]
|
||||
pub(super) fn ret_usize(raw: RetReg<R0>) -> io::Result<usize> {
|
||||
try_decode_usize(raw)
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively always
|
||||
/// returns a `usize`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function must only be used with return values from infallible
|
||||
/// syscalls.
|
||||
#[inline]
|
||||
pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
try_decode_usize(raw).unwrap()
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
decode_usize_infallible(raw)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively returns an
|
||||
/// `OwnedFd` on success.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that this is the return value of a syscall which
|
||||
/// returns an owned file descriptor.
|
||||
#[inline]
|
||||
pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> {
|
||||
let raw_fd = try_decode_raw_fd(raw)?;
|
||||
Ok(crate::backend::fd::OwnedFd::from_raw_fd(raw_fd))
|
||||
}
|
||||
|
||||
/// Convert the return value of `dup2` and `dup3`.
|
||||
///
|
||||
/// When these functions succeed, they return the same value as their second
|
||||
/// argument, so we don't construct a new `OwnedFd`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that this is the return value of a syscall which
|
||||
/// returns a file descriptor.
|
||||
#[inline]
|
||||
pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> {
|
||||
let _raw_fd = try_decode_raw_fd(raw)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert a `usize` returned from a syscall that effectively returns a
|
||||
/// `*mut c_void` on success.
|
||||
#[inline]
|
||||
pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> {
|
||||
try_decode_void_star(raw)
|
||||
}
|
||||
176
vendor/rustix/src/backend/linux_raw/elf.rs
vendored
Normal file
176
vendor/rustix/src/backend/linux_raw/elf.rs
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
//! The ELF ABI.
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
#![cfg_attr(
|
||||
all(not(target_vendor = "mustang"), feature = "use-libc-auxv"),
|
||||
allow(dead_code)
|
||||
)]
|
||||
|
||||
pub(super) const SELFMAG: usize = 4;
|
||||
pub(super) const ELFMAG: [u8; SELFMAG] = [0x7f, b'E', b'L', b'F'];
|
||||
pub(super) const EI_CLASS: usize = 4;
|
||||
pub(super) const EI_DATA: usize = 5;
|
||||
pub(super) const EI_VERSION: usize = 6;
|
||||
pub(super) const EI_OSABI: usize = 7;
|
||||
pub(super) const EI_ABIVERSION: usize = 8;
|
||||
pub(super) const EV_CURRENT: u8 = 1;
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub(super) const ELFCLASS: u8 = 1; // ELFCLASS32
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub(super) const ELFCLASS: u8 = 2; // ELFCLASS64
|
||||
#[cfg(target_endian = "little")]
|
||||
pub(super) const ELFDATA: u8 = 1; // ELFDATA2LSB
|
||||
#[cfg(target_endian = "big")]
|
||||
pub(super) const ELFDATA: u8 = 2; // ELFDATA2MSB
|
||||
pub(super) const ELFOSABI_SYSV: u8 = 0;
|
||||
pub(super) const ELFOSABI_LINUX: u8 = 3;
|
||||
// At present all of our supported platforms use 0.
|
||||
pub(super) const ELFABIVERSION: u8 = 0;
|
||||
pub(super) const ET_DYN: u16 = 3;
|
||||
pub(super) const EI_NIDENT: usize = 16;
|
||||
pub(super) const SHN_UNDEF: u16 = 0;
|
||||
pub(super) const SHN_ABS: u16 = 0xfff1;
|
||||
pub(super) const PN_XNUM: u16 = 0xffff;
|
||||
pub(super) const PT_LOAD: u32 = 1;
|
||||
pub(super) const PT_DYNAMIC: u32 = 2;
|
||||
pub(super) const PT_INTERP: u32 = 3;
|
||||
pub(super) const PT_PHDR: u32 = 6;
|
||||
pub(super) const PT_TLS: u32 = 7;
|
||||
pub(super) const PT_GNU_STACK: u32 = 0x6474_e551;
|
||||
pub(super) const PT_GNU_RELRO: u32 = 0x6474_e552;
|
||||
pub(super) const PF_X: u32 = 1;
|
||||
pub(super) const PF_W: u32 = 2;
|
||||
pub(super) const PF_R: u32 = 4;
|
||||
pub(super) const DT_NULL: i32 = 0;
|
||||
pub(super) const DT_HASH: i32 = 4;
|
||||
pub(super) const DT_STRTAB: i32 = 5;
|
||||
pub(super) const DT_SYMTAB: i32 = 6;
|
||||
pub(super) const DT_SYMENT: i32 = 11;
|
||||
pub(super) const DT_VERSYM: i32 = 0x6fff_fff0;
|
||||
pub(super) const DT_VERDEF: i32 = 0x6fff_fffc;
|
||||
pub(super) const STB_WEAK: u8 = 2;
|
||||
pub(super) const STB_GLOBAL: u8 = 1;
|
||||
pub(super) const STT_NOTYPE: u8 = 0;
|
||||
pub(super) const STT_FUNC: u8 = 2;
|
||||
pub(super) const STN_UNDEF: u32 = 0;
|
||||
pub(super) const VER_FLG_BASE: u16 = 0x1;
|
||||
pub(super) const VER_DEF_CURRENT: u16 = 1;
|
||||
pub(super) const STV_DEFAULT: u8 = 0;
|
||||
#[cfg(target_arch = "arm")]
|
||||
pub(super) const EM_CURRENT: u16 = 40; // EM_ARM
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub(super) const EM_CURRENT: u16 = 3; // EM_386
|
||||
#[cfg(target_arch = "powerpc64")]
|
||||
pub(super) const EM_CURRENT: u16 = 21; // EM_PPC64
|
||||
#[cfg(any(target_arch = "mips", target_arch = "mips64"))]
|
||||
pub(super) const EM_CURRENT: u16 = 8; // EM_MIPS
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub(super) const EM_CURRENT: u16 = 62; // EM_X86_64
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub(super) const EM_CURRENT: u16 = 183; // EM_AARCH64
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub(super) const EM_CURRENT: u16 = 243; // EM_RISCV
|
||||
|
||||
#[inline]
|
||||
pub(super) const fn ELF_ST_VISIBILITY(o: u8) -> u8 {
|
||||
o & 0x03
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) const fn ELF_ST_BIND(val: u8) -> u8 {
|
||||
val >> 4
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) const fn ELF_ST_TYPE(val: u8) -> u8 {
|
||||
val & 0xf
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(super) struct Elf_Ehdr {
|
||||
pub(super) e_ident: [u8; EI_NIDENT],
|
||||
pub(super) e_type: u16,
|
||||
pub(super) e_machine: u16,
|
||||
pub(super) e_version: u32,
|
||||
pub(super) e_entry: usize,
|
||||
pub(super) e_phoff: usize,
|
||||
pub(super) e_shoff: usize,
|
||||
pub(super) e_flags: u32,
|
||||
pub(super) e_ehsize: u16,
|
||||
pub(super) e_phentsize: u16,
|
||||
pub(super) e_phnum: u16,
|
||||
pub(super) e_shentsize: u16,
|
||||
pub(super) e_shnum: u16,
|
||||
pub(super) e_shstrndx: u16,
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[repr(C)]
|
||||
pub(super) struct Elf_Phdr {
|
||||
pub(super) p_type: u32,
|
||||
pub(super) p_offset: usize,
|
||||
pub(super) p_vaddr: usize,
|
||||
pub(super) p_paddr: usize,
|
||||
pub(super) p_filesz: usize,
|
||||
pub(super) p_memsz: usize,
|
||||
pub(super) p_flags: u32,
|
||||
pub(super) p_align: usize,
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[repr(C)]
|
||||
pub(super) struct Elf_Phdr {
|
||||
pub(super) p_type: u32,
|
||||
pub(super) p_flags: u32,
|
||||
pub(super) p_offset: usize,
|
||||
pub(super) p_vaddr: usize,
|
||||
pub(super) p_paddr: usize,
|
||||
pub(super) p_filesz: usize,
|
||||
pub(super) p_memsz: usize,
|
||||
pub(super) p_align: usize,
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[repr(C)]
|
||||
pub(super) struct Elf_Sym {
|
||||
pub(super) st_name: u32,
|
||||
pub(super) st_value: usize,
|
||||
pub(super) st_size: usize,
|
||||
pub(super) st_info: u8,
|
||||
pub(super) st_other: u8,
|
||||
pub(super) st_shndx: u16,
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[repr(C)]
|
||||
pub(super) struct Elf_Sym {
|
||||
pub(super) st_name: u32,
|
||||
pub(super) st_info: u8,
|
||||
pub(super) st_other: u8,
|
||||
pub(super) st_shndx: u16,
|
||||
pub(super) st_value: usize,
|
||||
pub(super) st_size: usize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(super) struct Elf_Dyn {
|
||||
pub(super) d_tag: i32,
|
||||
pub(super) d_val: usize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(super) struct Elf_Verdef {
|
||||
pub(super) vd_version: u16,
|
||||
pub(super) vd_flags: u16,
|
||||
pub(super) vd_ndx: u16,
|
||||
pub(super) vd_cnt: u16,
|
||||
pub(super) vd_hash: u32,
|
||||
pub(super) vd_aux: u32,
|
||||
pub(super) vd_next: u32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub(super) struct Elf_Verdaux {
|
||||
pub(super) vda_name: u32,
|
||||
pub(super) _vda_next: u32,
|
||||
}
|
||||
225
vendor/rustix/src/backend/linux_raw/fs/dir.rs
vendored
Normal file
225
vendor/rustix/src/backend/linux_raw/fs/dir.rs
vendored
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
use crate::fd::{AsFd, BorrowedFd, OwnedFd};
|
||||
use crate::ffi::{CStr, CString};
|
||||
use crate::fs::{
|
||||
fcntl_getfl, fstat, fstatfs, fstatvfs, openat, FileType, Mode, OFlags, Stat, StatFs, StatVfs,
|
||||
};
|
||||
use crate::io;
|
||||
use crate::process::fchdir;
|
||||
use crate::utils::as_ptr;
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use core::mem::size_of;
|
||||
use linux_raw_sys::general::{linux_dirent64, SEEK_SET};
|
||||
|
||||
/// `DIR*`
|
||||
pub struct Dir {
|
||||
/// The `OwnedFd` that we read directory entries from.
|
||||
fd: OwnedFd,
|
||||
|
||||
buf: Vec<u8>,
|
||||
pos: usize,
|
||||
next: Option<u64>,
|
||||
}
|
||||
|
||||
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> {
|
||||
let flags = fcntl_getfl(fd)?;
|
||||
let fd_for_dir = openat(fd, cstr!("."), flags | OFlags::CLOEXEC, Mode::empty())?;
|
||||
|
||||
Ok(Self {
|
||||
fd: fd_for_dir,
|
||||
buf: Vec::new(),
|
||||
pos: 0,
|
||||
next: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// `rewinddir(self)`
|
||||
#[inline]
|
||||
pub fn rewind(&mut self) {
|
||||
self.pos = self.buf.len();
|
||||
self.next = Some(0);
|
||||
}
|
||||
|
||||
/// `readdir(self)`, where `None` means the end of the directory.
|
||||
pub fn read(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
if let Some(next) = self.next.take() {
|
||||
match crate::backend::fs::syscalls::_seek(self.fd.as_fd(), next as i64, SEEK_SET) {
|
||||
Ok(_) => (),
|
||||
Err(err) => return Some(Err(err)),
|
||||
}
|
||||
}
|
||||
|
||||
// Compute linux_dirent64 field offsets.
|
||||
let z = linux_dirent64 {
|
||||
d_ino: 0_u64,
|
||||
d_off: 0_i64,
|
||||
d_type: 0_u8,
|
||||
d_reclen: 0_u16,
|
||||
d_name: Default::default(),
|
||||
};
|
||||
let base = as_ptr(&z) as usize;
|
||||
let offsetof_d_reclen = (as_ptr(&z.d_reclen) as usize) - base;
|
||||
let offsetof_d_name = (as_ptr(&z.d_name) as usize) - base;
|
||||
let offsetof_d_ino = (as_ptr(&z.d_ino) as usize) - base;
|
||||
let offsetof_d_type = (as_ptr(&z.d_type) as usize) - base;
|
||||
|
||||
// Test if we need more entries, and if so, read more.
|
||||
if self.buf.len() - self.pos < size_of::<linux_dirent64>() {
|
||||
match self.read_more()? {
|
||||
Ok(()) => (),
|
||||
Err(e) => return Some(Err(e)),
|
||||
}
|
||||
}
|
||||
|
||||
// We successfully read an entry. Extract the fields.
|
||||
let pos = self.pos;
|
||||
|
||||
// Do an unaligned u16 load.
|
||||
let d_reclen = u16::from_ne_bytes([
|
||||
self.buf[pos + offsetof_d_reclen],
|
||||
self.buf[pos + offsetof_d_reclen + 1],
|
||||
]);
|
||||
assert!(self.buf.len() - pos >= d_reclen as usize);
|
||||
self.pos += d_reclen as usize;
|
||||
|
||||
// Read the NUL-terminated name from the `d_name` field. Without
|
||||
// `unsafe`, we need to scan for the NUL twice: once to obtain a size
|
||||
// for the slice, and then once within `CStr::from_bytes_with_nul`.
|
||||
let name_start = pos + offsetof_d_name;
|
||||
let name_len = self.buf[name_start..]
|
||||
.iter()
|
||||
.position(|x| *x == b'\0')
|
||||
.unwrap();
|
||||
let name =
|
||||
CStr::from_bytes_with_nul(&self.buf[name_start..name_start + name_len + 1]).unwrap();
|
||||
let name = name.to_owned();
|
||||
assert!(name.as_bytes().len() <= self.buf.len() - name_start);
|
||||
|
||||
// Do an unaligned u64 load.
|
||||
let d_ino = u64::from_ne_bytes([
|
||||
self.buf[pos + offsetof_d_ino],
|
||||
self.buf[pos + offsetof_d_ino + 1],
|
||||
self.buf[pos + offsetof_d_ino + 2],
|
||||
self.buf[pos + offsetof_d_ino + 3],
|
||||
self.buf[pos + offsetof_d_ino + 4],
|
||||
self.buf[pos + offsetof_d_ino + 5],
|
||||
self.buf[pos + offsetof_d_ino + 6],
|
||||
self.buf[pos + offsetof_d_ino + 7],
|
||||
]);
|
||||
|
||||
let d_type = self.buf[pos + offsetof_d_type];
|
||||
|
||||
// Check that our types correspond to the `linux_dirent64` types.
|
||||
let _ = linux_dirent64 {
|
||||
d_ino,
|
||||
d_off: 0,
|
||||
d_type,
|
||||
d_reclen,
|
||||
d_name: Default::default(),
|
||||
};
|
||||
|
||||
Some(Ok(DirEntry {
|
||||
d_ino,
|
||||
d_type,
|
||||
name,
|
||||
}))
|
||||
}
|
||||
|
||||
fn read_more(&mut self) -> Option<io::Result<()>> {
|
||||
let og_len = self.buf.len();
|
||||
// Capacity increment currently chosen by wild guess.
|
||||
self.buf
|
||||
.resize(self.buf.capacity() + 32 * size_of::<linux_dirent64>(), 0);
|
||||
let nread = match crate::backend::fs::syscalls::getdents(self.fd.as_fd(), &mut self.buf) {
|
||||
Ok(nread) => nread,
|
||||
Err(err) => {
|
||||
self.buf.resize(og_len, 0);
|
||||
return Some(Err(err));
|
||||
}
|
||||
};
|
||||
self.buf.resize(nread, 0);
|
||||
self.pos = 0;
|
||||
if nread == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
/// `fstat(self)`
|
||||
#[inline]
|
||||
pub fn stat(&self) -> io::Result<Stat> {
|
||||
fstat(&self.fd)
|
||||
}
|
||||
|
||||
/// `fstatfs(self)`
|
||||
#[inline]
|
||||
pub fn statfs(&self) -> io::Result<StatFs> {
|
||||
fstatfs(&self.fd)
|
||||
}
|
||||
|
||||
/// `fstatvfs(self)`
|
||||
#[inline]
|
||||
pub fn statvfs(&self) -> io::Result<StatVfs> {
|
||||
fstatvfs(&self.fd)
|
||||
}
|
||||
|
||||
/// `fchdir(self)`
|
||||
#[inline]
|
||||
pub fn chdir(&self) -> io::Result<()> {
|
||||
fchdir(&self.fd)
|
||||
}
|
||||
}
|
||||
|
||||
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", &self.fd).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// `struct dirent`
|
||||
#[derive(Debug)]
|
||||
pub struct DirEntry {
|
||||
d_ino: u64,
|
||||
d_type: u8,
|
||||
name: CString,
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
/// Returns the file name of this directory entry.
|
||||
#[inline]
|
||||
pub fn file_name(&self) -> &CStr {
|
||||
&self.name
|
||||
}
|
||||
|
||||
/// Returns the type of this directory entry.
|
||||
#[inline]
|
||||
pub fn file_type(&self) -> FileType {
|
||||
FileType::from_dirent_d_type(self.d_type)
|
||||
}
|
||||
|
||||
/// Return the inode number of this directory entry.
|
||||
#[inline]
|
||||
pub fn ino(&self) -> u64 {
|
||||
self.d_ino
|
||||
}
|
||||
}
|
||||
19
vendor/rustix/src/backend/linux_raw/fs/makedev.rs
vendored
Normal file
19
vendor/rustix/src/backend/linux_raw/fs/makedev.rs
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use crate::fs::Dev;
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn makedev(maj: u32, min: u32) -> Dev {
|
||||
((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)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn major(dev: Dev) -> u32 {
|
||||
(((dev >> 31 >> 1) & 0xffff_f000) | ((dev >> 8) & 0x0000_0fff)) as u32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn minor(dev: Dev) -> u32 {
|
||||
(((dev >> 12) & 0xffff_ff00) | (dev & 0x0000_00ff)) as u32
|
||||
}
|
||||
4
vendor/rustix/src/backend/linux_raw/fs/mod.rs
vendored
Normal file
4
vendor/rustix/src/backend/linux_raw/fs/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
pub(crate) mod dir;
|
||||
pub(crate) mod makedev;
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
1384
vendor/rustix/src/backend/linux_raw/fs/syscalls.rs
vendored
Normal file
1384
vendor/rustix/src/backend/linux_raw/fs/syscalls.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
646
vendor/rustix/src/backend/linux_raw/fs/types.rs
vendored
Normal file
646
vendor/rustix/src/backend/linux_raw/fs/types.rs
vendored
Normal file
|
|
@ -0,0 +1,646 @@
|
|||
use super::super::c;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
/// `*_OK` constants for use with [`accessat`].
|
||||
///
|
||||
/// [`accessat`]: fn.accessat.html
|
||||
pub struct Access: c::c_uint {
|
||||
/// `R_OK`
|
||||
const READ_OK = linux_raw_sys::general::R_OK;
|
||||
|
||||
/// `W_OK`
|
||||
const WRITE_OK = linux_raw_sys::general::W_OK;
|
||||
|
||||
/// `X_OK`
|
||||
const EXEC_OK = linux_raw_sys::general::X_OK;
|
||||
|
||||
/// `F_OK`
|
||||
const EXISTS = linux_raw_sys::general::F_OK;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `AT_*` constants for use with [`openat`], [`statat`], and other `*at`
|
||||
/// functions.
|
||||
///
|
||||
/// [`openat`]: crate::fs::openat
|
||||
/// [`statat`]: crate::fs::statat
|
||||
pub struct AtFlags: c::c_uint {
|
||||
/// `AT_REMOVEDIR`
|
||||
const REMOVEDIR = linux_raw_sys::general::AT_REMOVEDIR;
|
||||
|
||||
/// `AT_SYMLINK_FOLLOW`
|
||||
const SYMLINK_FOLLOW = linux_raw_sys::general::AT_SYMLINK_FOLLOW;
|
||||
|
||||
/// `AT_SYMLINK_NOFOLLOW`
|
||||
const SYMLINK_NOFOLLOW = linux_raw_sys::general::AT_SYMLINK_NOFOLLOW;
|
||||
|
||||
/// `AT_EMPTY_PATH`
|
||||
const EMPTY_PATH = linux_raw_sys::general::AT_EMPTY_PATH;
|
||||
|
||||
/// `AT_EACCESS`
|
||||
const EACCESS = linux_raw_sys::general::AT_EACCESS;
|
||||
|
||||
/// `AT_STATX_SYNC_AS_STAT`
|
||||
const STATX_SYNC_AS_STAT = linux_raw_sys::general::AT_STATX_SYNC_AS_STAT;
|
||||
|
||||
/// `AT_STATX_FORCE_SYNC`
|
||||
const STATX_FORCE_SYNC = linux_raw_sys::general::AT_STATX_FORCE_SYNC;
|
||||
|
||||
/// `AT_STATX_DONT_SYNC`
|
||||
const STATX_DONT_SYNC = linux_raw_sys::general::AT_STATX_DONT_SYNC;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `S_I*` constants for use with [`openat`], [`chmodat`], and [`fchmod`].
|
||||
///
|
||||
/// [`openat`]: crate::fs::openat
|
||||
/// [`chmodat`]: crate::fs::chmodat
|
||||
/// [`fchmod`]: crate::fs::fchmod
|
||||
pub struct Mode: RawMode {
|
||||
/// `S_IRWXU`
|
||||
const RWXU = linux_raw_sys::general::S_IRWXU;
|
||||
|
||||
/// `S_IRUSR`
|
||||
const RUSR = linux_raw_sys::general::S_IRUSR;
|
||||
|
||||
/// `S_IWUSR`
|
||||
const WUSR = linux_raw_sys::general::S_IWUSR;
|
||||
|
||||
/// `S_IXUSR`
|
||||
const XUSR = linux_raw_sys::general::S_IXUSR;
|
||||
|
||||
/// `S_IRWXG`
|
||||
const RWXG = linux_raw_sys::general::S_IRWXG;
|
||||
|
||||
/// `S_IRGRP`
|
||||
const RGRP = linux_raw_sys::general::S_IRGRP;
|
||||
|
||||
/// `S_IWGRP`
|
||||
const WGRP = linux_raw_sys::general::S_IWGRP;
|
||||
|
||||
/// `S_IXGRP`
|
||||
const XGRP = linux_raw_sys::general::S_IXGRP;
|
||||
|
||||
/// `S_IRWXO`
|
||||
const RWXO = linux_raw_sys::general::S_IRWXO;
|
||||
|
||||
/// `S_IROTH`
|
||||
const ROTH = linux_raw_sys::general::S_IROTH;
|
||||
|
||||
/// `S_IWOTH`
|
||||
const WOTH = linux_raw_sys::general::S_IWOTH;
|
||||
|
||||
/// `S_IXOTH`
|
||||
const XOTH = linux_raw_sys::general::S_IXOTH;
|
||||
|
||||
/// `S_ISUID`
|
||||
const SUID = linux_raw_sys::general::S_ISUID;
|
||||
|
||||
/// `S_ISGID`
|
||||
const SGID = linux_raw_sys::general::S_ISGID;
|
||||
|
||||
/// `S_ISVTX`
|
||||
const SVTX = linux_raw_sys::general::S_ISVTX;
|
||||
}
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
/// Construct a `Mode` from the mode bits of the `st_mode` field of a
|
||||
/// `Stat`.
|
||||
#[inline]
|
||||
pub const fn from_raw_mode(st_mode: RawMode) -> Self {
|
||||
Self::from_bits_truncate(st_mode)
|
||||
}
|
||||
|
||||
/// Construct an `st_mode` value from `Stat`.
|
||||
#[inline]
|
||||
pub const fn as_raw_mode(self) -> RawMode {
|
||||
self.bits()
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `O_*` constants for use with [`openat`].
|
||||
///
|
||||
/// [`openat`]: crate::fs::openat
|
||||
pub struct OFlags: c::c_uint {
|
||||
/// `O_ACCMODE`
|
||||
const ACCMODE = linux_raw_sys::general::O_ACCMODE;
|
||||
|
||||
/// Similar to `ACCMODE`, but just includes the read/write flags, and
|
||||
/// no other flags.
|
||||
///
|
||||
/// Some implementations include `O_PATH` in `O_ACCMODE`, when
|
||||
/// sometimes we really just want the read/write bits. Caution is
|
||||
/// indicated, as the presence of `O_PATH` may mean that the read/write
|
||||
/// bits don't have their usual meaning.
|
||||
const RWMODE = linux_raw_sys::general::O_RDONLY |
|
||||
linux_raw_sys::general::O_WRONLY |
|
||||
linux_raw_sys::general::O_RDWR;
|
||||
|
||||
/// `O_APPEND`
|
||||
const APPEND = linux_raw_sys::general::O_APPEND;
|
||||
|
||||
/// `O_CREAT`
|
||||
#[doc(alias = "CREAT")]
|
||||
const CREATE = linux_raw_sys::general::O_CREAT;
|
||||
|
||||
/// `O_DIRECTORY`
|
||||
const DIRECTORY = linux_raw_sys::general::O_DIRECTORY;
|
||||
|
||||
/// `O_DSYNC`. Linux 2.6.32 only supports `O_SYNC`.
|
||||
const DSYNC = linux_raw_sys::general::O_SYNC;
|
||||
|
||||
/// `O_EXCL`
|
||||
const EXCL = linux_raw_sys::general::O_EXCL;
|
||||
|
||||
/// `O_FSYNC`. Linux 2.6.32 only supports `O_SYNC`.
|
||||
const FSYNC = linux_raw_sys::general::O_SYNC;
|
||||
|
||||
/// `O_NOFOLLOW`
|
||||
const NOFOLLOW = linux_raw_sys::general::O_NOFOLLOW;
|
||||
|
||||
/// `O_NONBLOCK`
|
||||
const NONBLOCK = linux_raw_sys::general::O_NONBLOCK;
|
||||
|
||||
/// `O_RDONLY`
|
||||
const RDONLY = linux_raw_sys::general::O_RDONLY;
|
||||
|
||||
/// `O_WRONLY`
|
||||
const WRONLY = linux_raw_sys::general::O_WRONLY;
|
||||
|
||||
/// `O_RDWR`
|
||||
const RDWR = linux_raw_sys::general::O_RDWR;
|
||||
|
||||
/// `O_NOCTTY`
|
||||
const NOCTTY = linux_raw_sys::general::O_NOCTTY;
|
||||
|
||||
/// `O_RSYNC`. Linux 2.6.32 only supports `O_SYNC`.
|
||||
const RSYNC = linux_raw_sys::general::O_SYNC;
|
||||
|
||||
/// `O_SYNC`
|
||||
const SYNC = linux_raw_sys::general::O_SYNC;
|
||||
|
||||
/// `O_TRUNC`
|
||||
const TRUNC = linux_raw_sys::general::O_TRUNC;
|
||||
|
||||
/// `O_PATH`
|
||||
const PATH = linux_raw_sys::general::O_PATH;
|
||||
|
||||
/// `O_CLOEXEC`
|
||||
const CLOEXEC = linux_raw_sys::general::O_CLOEXEC;
|
||||
|
||||
/// `O_TMPFILE`
|
||||
const TMPFILE = linux_raw_sys::general::O_TMPFILE;
|
||||
|
||||
/// `O_NOATIME`
|
||||
const NOATIME = linux_raw_sys::general::O_NOATIME;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `RESOLVE_*` constants for use with [`openat2`].
|
||||
///
|
||||
/// [`openat2`]: crate::fs::openat2
|
||||
#[derive(Default)]
|
||||
pub struct ResolveFlags: u64 {
|
||||
/// `RESOLVE_NO_XDEV`
|
||||
const NO_XDEV = linux_raw_sys::general::RESOLVE_NO_XDEV as u64;
|
||||
|
||||
/// `RESOLVE_NO_MAGICLINKS`
|
||||
const NO_MAGICLINKS = linux_raw_sys::general::RESOLVE_NO_MAGICLINKS as u64;
|
||||
|
||||
/// `RESOLVE_NO_SYMLINKS`
|
||||
const NO_SYMLINKS = linux_raw_sys::general::RESOLVE_NO_SYMLINKS as u64;
|
||||
|
||||
/// `RESOLVE_BENEATH`
|
||||
const BENEATH = linux_raw_sys::general::RESOLVE_BENEATH as u64;
|
||||
|
||||
/// `RESOLVE_IN_ROOT`
|
||||
const IN_ROOT = linux_raw_sys::general::RESOLVE_IN_ROOT as u64;
|
||||
|
||||
/// `RESOLVE_CACHED` (since Linux 5.12)
|
||||
const CACHED = linux_raw_sys::general::RESOLVE_CACHED as u64;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `RENAME_*` constants for use with [`renameat_with`].
|
||||
///
|
||||
/// [`renameat_with`]: crate::fs::renameat_with
|
||||
pub struct RenameFlags: c::c_uint {
|
||||
/// `RENAME_EXCHANGE`
|
||||
const EXCHANGE = linux_raw_sys::general::RENAME_EXCHANGE;
|
||||
|
||||
/// `RENAME_NOREPLACE`
|
||||
const NOREPLACE = linux_raw_sys::general::RENAME_NOREPLACE;
|
||||
|
||||
/// `RENAME_WHITEOUT`
|
||||
const WHITEOUT = linux_raw_sys::general::RENAME_WHITEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/// `S_IF*` constants for use with [`mknodat`] and [`Stat`]'s `st_mode` field.
|
||||
///
|
||||
/// [`mknodat`]: crate::fs::mknodat
|
||||
/// [`Stat`]: crate::fs::Stat
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum FileType {
|
||||
/// `S_IFREG`
|
||||
RegularFile = linux_raw_sys::general::S_IFREG as isize,
|
||||
|
||||
/// `S_IFDIR`
|
||||
Directory = linux_raw_sys::general::S_IFDIR as isize,
|
||||
|
||||
/// `S_IFLNK`
|
||||
Symlink = linux_raw_sys::general::S_IFLNK as isize,
|
||||
|
||||
/// `S_IFIFO`
|
||||
Fifo = linux_raw_sys::general::S_IFIFO as isize,
|
||||
|
||||
/// `S_IFSOCK`
|
||||
Socket = linux_raw_sys::general::S_IFSOCK as isize,
|
||||
|
||||
/// `S_IFCHR`
|
||||
CharacterDevice = linux_raw_sys::general::S_IFCHR as isize,
|
||||
|
||||
/// `S_IFBLK`
|
||||
BlockDevice = linux_raw_sys::general::S_IFBLK as isize,
|
||||
|
||||
/// An unknown filesystem object.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
/// Construct a `FileType` from the `S_IFMT` bits of the `st_mode` field of
|
||||
/// a `Stat`.
|
||||
#[inline]
|
||||
pub const fn from_raw_mode(st_mode: RawMode) -> Self {
|
||||
match st_mode & linux_raw_sys::general::S_IFMT {
|
||||
linux_raw_sys::general::S_IFREG => Self::RegularFile,
|
||||
linux_raw_sys::general::S_IFDIR => Self::Directory,
|
||||
linux_raw_sys::general::S_IFLNK => Self::Symlink,
|
||||
linux_raw_sys::general::S_IFIFO => Self::Fifo,
|
||||
linux_raw_sys::general::S_IFSOCK => Self::Socket,
|
||||
linux_raw_sys::general::S_IFCHR => Self::CharacterDevice,
|
||||
linux_raw_sys::general::S_IFBLK => Self::BlockDevice,
|
||||
_ => Self::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct an `st_mode` value from `Stat`.
|
||||
#[inline]
|
||||
pub const fn as_raw_mode(self) -> RawMode {
|
||||
match self {
|
||||
Self::RegularFile => linux_raw_sys::general::S_IFREG,
|
||||
Self::Directory => linux_raw_sys::general::S_IFDIR,
|
||||
Self::Symlink => linux_raw_sys::general::S_IFLNK,
|
||||
Self::Fifo => linux_raw_sys::general::S_IFIFO,
|
||||
Self::Socket => linux_raw_sys::general::S_IFSOCK,
|
||||
Self::CharacterDevice => linux_raw_sys::general::S_IFCHR,
|
||||
Self::BlockDevice => linux_raw_sys::general::S_IFBLK,
|
||||
Self::Unknown => linux_raw_sys::general::S_IFMT,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a `FileType` from the `d_type` field of a `dirent`.
|
||||
#[inline]
|
||||
pub(crate) const fn from_dirent_d_type(d_type: u8) -> Self {
|
||||
match d_type as u32 {
|
||||
linux_raw_sys::general::DT_REG => Self::RegularFile,
|
||||
linux_raw_sys::general::DT_DIR => Self::Directory,
|
||||
linux_raw_sys::general::DT_LNK => Self::Symlink,
|
||||
linux_raw_sys::general::DT_SOCK => Self::Socket,
|
||||
linux_raw_sys::general::DT_FIFO => Self::Fifo,
|
||||
linux_raw_sys::general::DT_CHR => Self::CharacterDevice,
|
||||
linux_raw_sys::general::DT_BLK => Self::BlockDevice,
|
||||
// linux_raw_sys::general::DT_UNKNOWN |
|
||||
_ => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `POSIX_FADV_*` constants for use with [`fadvise`].
|
||||
///
|
||||
/// [`fadvise`]: crate::fs::fadvise
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
#[repr(u32)]
|
||||
pub enum Advice {
|
||||
/// `POSIX_FADV_NORMAL`
|
||||
Normal = linux_raw_sys::general::POSIX_FADV_NORMAL,
|
||||
|
||||
/// `POSIX_FADV_SEQUENTIAL`
|
||||
Sequential = linux_raw_sys::general::POSIX_FADV_SEQUENTIAL,
|
||||
|
||||
/// `POSIX_FADV_RANDOM`
|
||||
Random = linux_raw_sys::general::POSIX_FADV_RANDOM,
|
||||
|
||||
/// `POSIX_FADV_NOREUSE`
|
||||
NoReuse = linux_raw_sys::general::POSIX_FADV_NOREUSE,
|
||||
|
||||
/// `POSIX_FADV_WILLNEED`
|
||||
WillNeed = linux_raw_sys::general::POSIX_FADV_WILLNEED,
|
||||
|
||||
/// `POSIX_FADV_DONTNEED`
|
||||
DontNeed = linux_raw_sys::general::POSIX_FADV_DONTNEED,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `MFD_*` constants for use with [`memfd_create`].
|
||||
///
|
||||
/// [`memfd_create`]: crate::fs::memfd_create
|
||||
pub struct MemfdFlags: c::c_uint {
|
||||
/// `MFD_CLOEXEC`
|
||||
const CLOEXEC = linux_raw_sys::general::MFD_CLOEXEC;
|
||||
|
||||
/// `MFD_ALLOW_SEALING`
|
||||
const ALLOW_SEALING = linux_raw_sys::general::MFD_ALLOW_SEALING;
|
||||
|
||||
/// `MFD_HUGETLB` (since Linux 4.14)
|
||||
const HUGETLB = linux_raw_sys::general::MFD_HUGETLB;
|
||||
|
||||
/// `MFD_HUGE_64KB`
|
||||
const HUGE_64KB = linux_raw_sys::general::MFD_HUGE_64KB;
|
||||
/// `MFD_HUGE_512JB`
|
||||
const HUGE_512KB = linux_raw_sys::general::MFD_HUGE_512KB;
|
||||
/// `MFD_HUGE_1MB`
|
||||
const HUGE_1MB = linux_raw_sys::general::MFD_HUGE_1MB;
|
||||
/// `MFD_HUGE_2MB`
|
||||
const HUGE_2MB = linux_raw_sys::general::MFD_HUGE_2MB;
|
||||
/// `MFD_HUGE_8MB`
|
||||
const HUGE_8MB = linux_raw_sys::general::MFD_HUGE_8MB;
|
||||
/// `MFD_HUGE_16MB`
|
||||
const HUGE_16MB = linux_raw_sys::general::MFD_HUGE_16MB;
|
||||
/// `MFD_HUGE_32MB`
|
||||
const HUGE_32MB = linux_raw_sys::general::MFD_HUGE_32MB;
|
||||
/// `MFD_HUGE_256MB`
|
||||
const HUGE_256MB = linux_raw_sys::general::MFD_HUGE_256MB;
|
||||
/// `MFD_HUGE_512MB`
|
||||
const HUGE_512MB = linux_raw_sys::general::MFD_HUGE_512MB;
|
||||
/// `MFD_HUGE_1GB`
|
||||
const HUGE_1GB = linux_raw_sys::general::MFD_HUGE_1GB;
|
||||
/// `MFD_HUGE_2GB`
|
||||
const HUGE_2GB = linux_raw_sys::general::MFD_HUGE_2GB;
|
||||
/// `MFD_HUGE_16GB`
|
||||
const HUGE_16GB = linux_raw_sys::general::MFD_HUGE_16GB;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `F_SEAL_*` constants for use with [`fcntl_add_seals`] and
|
||||
/// [`fcntl_get_seals`].
|
||||
///
|
||||
/// [`fcntl_add_seals`]: crate::fs::fcntl_add_seals
|
||||
/// [`fcntl_get_seals`]: crate::fs::fcntl_get_seals
|
||||
pub struct SealFlags: u32 {
|
||||
/// `F_SEAL_SEAL`.
|
||||
const SEAL = linux_raw_sys::general::F_SEAL_SEAL;
|
||||
/// `F_SEAL_SHRINK`.
|
||||
const SHRINK = linux_raw_sys::general::F_SEAL_SHRINK;
|
||||
/// `F_SEAL_GROW`.
|
||||
const GROW = linux_raw_sys::general::F_SEAL_GROW;
|
||||
/// `F_SEAL_WRITE`.
|
||||
const WRITE = linux_raw_sys::general::F_SEAL_WRITE;
|
||||
/// `F_SEAL_FUTURE_WRITE` (since Linux 5.1)
|
||||
const FUTURE_WRITE = linux_raw_sys::general::F_SEAL_FUTURE_WRITE;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `STATX_*` constants for use with [`statx`].
|
||||
///
|
||||
/// [`statx`]: crate::fs::statx
|
||||
pub struct StatxFlags: u32 {
|
||||
/// `STATX_TYPE`
|
||||
const TYPE = linux_raw_sys::general::STATX_TYPE;
|
||||
|
||||
/// `STATX_MODE`
|
||||
const MODE = linux_raw_sys::general::STATX_MODE;
|
||||
|
||||
/// `STATX_NLINK`
|
||||
const NLINK = linux_raw_sys::general::STATX_NLINK;
|
||||
|
||||
/// `STATX_UID`
|
||||
const UID = linux_raw_sys::general::STATX_UID;
|
||||
|
||||
/// `STATX_GID`
|
||||
const GID = linux_raw_sys::general::STATX_GID;
|
||||
|
||||
/// `STATX_ATIME`
|
||||
const ATIME = linux_raw_sys::general::STATX_ATIME;
|
||||
|
||||
/// `STATX_MTIME`
|
||||
const MTIME = linux_raw_sys::general::STATX_MTIME;
|
||||
|
||||
/// `STATX_CTIME`
|
||||
const CTIME = linux_raw_sys::general::STATX_CTIME;
|
||||
|
||||
/// `STATX_INO`
|
||||
const INO = linux_raw_sys::general::STATX_INO;
|
||||
|
||||
/// `STATX_SIZE`
|
||||
const SIZE = linux_raw_sys::general::STATX_SIZE;
|
||||
|
||||
/// `STATX_BLOCKS`
|
||||
const BLOCKS = linux_raw_sys::general::STATX_BLOCKS;
|
||||
|
||||
/// `STATX_BASIC_STATS`
|
||||
const BASIC_STATS = linux_raw_sys::general::STATX_BASIC_STATS;
|
||||
|
||||
/// `STATX_BTIME`
|
||||
const BTIME = linux_raw_sys::general::STATX_BTIME;
|
||||
|
||||
/// `STATX_MNT_ID` (since Linux 5.8)
|
||||
const MNT_ID = linux_raw_sys::general::STATX_MNT_ID;
|
||||
|
||||
/// `STATX_ALL`
|
||||
const ALL = linux_raw_sys::general::STATX_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `FALLOC_FL_*` constants for use with [`fallocate`].
|
||||
///
|
||||
/// [`fallocate`]: crate::fs::fallocate
|
||||
pub struct FallocateFlags: u32 {
|
||||
/// `FALLOC_FL_KEEP_SIZE`
|
||||
const KEEP_SIZE = linux_raw_sys::general::FALLOC_FL_KEEP_SIZE;
|
||||
/// `FALLOC_FL_PUNCH_HOLE`
|
||||
const PUNCH_HOLE = linux_raw_sys::general::FALLOC_FL_PUNCH_HOLE;
|
||||
/// `FALLOC_FL_NO_HIDE_STALE`
|
||||
const NO_HIDE_STALE = linux_raw_sys::general::FALLOC_FL_NO_HIDE_STALE;
|
||||
/// `FALLOC_FL_COLLAPSE_RANGE`
|
||||
const COLLAPSE_RANGE = linux_raw_sys::general::FALLOC_FL_COLLAPSE_RANGE;
|
||||
/// `FALLOC_FL_ZERO_RANGE`
|
||||
const ZERO_RANGE = linux_raw_sys::general::FALLOC_FL_ZERO_RANGE;
|
||||
/// `FALLOC_FL_INSERT_RANGE`
|
||||
const INSERT_RANGE = linux_raw_sys::general::FALLOC_FL_INSERT_RANGE;
|
||||
/// `FALLOC_FL_UNSHARE_RANGE`
|
||||
const UNSHARE_RANGE = linux_raw_sys::general::FALLOC_FL_UNSHARE_RANGE;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `ST_*` constants for use with [`StatVfs`].
|
||||
pub struct StatVfsMountFlags: u64 {
|
||||
/// `ST_MANDLOCK`
|
||||
const MANDLOCK = linux_raw_sys::general::MS_MANDLOCK as u64;
|
||||
|
||||
/// `ST_NOATIME`
|
||||
const NOATIME = linux_raw_sys::general::MS_NOATIME as u64;
|
||||
|
||||
/// `ST_NODEV`
|
||||
const NODEV = linux_raw_sys::general::MS_NODEV as u64;
|
||||
|
||||
/// `ST_NODIRATIME`
|
||||
const NODIRATIME = linux_raw_sys::general::MS_NODIRATIME as u64;
|
||||
|
||||
/// `ST_NOEXEC`
|
||||
const NOEXEC = linux_raw_sys::general::MS_NOEXEC as u64;
|
||||
|
||||
/// `ST_NOSUID`
|
||||
const NOSUID = linux_raw_sys::general::MS_NOSUID as u64;
|
||||
|
||||
/// `ST_RDONLY`
|
||||
const RDONLY = linux_raw_sys::general::MS_RDONLY as u64;
|
||||
|
||||
/// `ST_RELATIME`
|
||||
const RELATIME = linux_raw_sys::general::MS_RELATIME as u64;
|
||||
|
||||
/// `ST_SYNCHRONOUS`
|
||||
const SYNCHRONOUS = linux_raw_sys::general::MS_SYNCHRONOUS as u64;
|
||||
}
|
||||
}
|
||||
|
||||
/// `LOCK_*` constants for use with [`flock`]
|
||||
///
|
||||
/// [`flock`]: crate::fs::flock
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[repr(u32)]
|
||||
pub enum FlockOperation {
|
||||
/// `LOCK_SH`
|
||||
LockShared = linux_raw_sys::general::LOCK_SH,
|
||||
/// `LOCK_EX`
|
||||
LockExclusive = linux_raw_sys::general::LOCK_EX,
|
||||
/// `LOCK_UN`
|
||||
Unlock = linux_raw_sys::general::LOCK_UN,
|
||||
/// `LOCK_SH | LOCK_NB`
|
||||
NonBlockingLockShared = linux_raw_sys::general::LOCK_SH | linux_raw_sys::general::LOCK_NB,
|
||||
/// `LOCK_EX | LOCK_NB`
|
||||
NonBlockingLockExclusive = linux_raw_sys::general::LOCK_EX | linux_raw_sys::general::LOCK_NB,
|
||||
/// `LOCK_UN | LOCK_NB`
|
||||
NonBlockingUnlock = linux_raw_sys::general::LOCK_UN | linux_raw_sys::general::LOCK_NB,
|
||||
}
|
||||
|
||||
/// `struct stat` for use with [`statat`] and [`fstat`].
|
||||
///
|
||||
/// [`statat`]: crate::fs::statat
|
||||
/// [`fstat`]: crate::fs::fstat
|
||||
// On 32-bit, and mips64, Linux's `struct stat64` has a 32-bit `st_mtime` and
|
||||
// friends, so we use our own struct, populated from `statx` where possible, to
|
||||
// avoid the y2038 bug.
|
||||
#[cfg(any(target_pointer_width = "32", target_arch = "mips64"))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[allow(missing_docs)]
|
||||
pub struct Stat {
|
||||
pub st_dev: u64,
|
||||
pub st_mode: u32,
|
||||
pub st_nlink: u32,
|
||||
pub st_uid: u32,
|
||||
pub st_gid: u32,
|
||||
pub st_rdev: u64,
|
||||
pub st_size: i64,
|
||||
pub st_blksize: u32,
|
||||
pub st_blocks: u64,
|
||||
pub st_atime: u64,
|
||||
pub st_atime_nsec: u32,
|
||||
pub st_mtime: u64,
|
||||
pub st_mtime_nsec: u32,
|
||||
pub st_ctime: u64,
|
||||
pub st_ctime_nsec: u32,
|
||||
pub st_ino: u64,
|
||||
}
|
||||
|
||||
/// `struct stat` for use with [`statat`] and [`fstat`].
|
||||
///
|
||||
/// [`statat`]: crate::fs::statat
|
||||
/// [`fstat`]: crate::fs::fstat
|
||||
#[cfg(all(target_pointer_width = "64", not(target_arch = "mips64")))]
|
||||
pub type Stat = linux_raw_sys::general::stat;
|
||||
|
||||
/// `struct statfs` for use with [`statfs`] and [`fstatfs`].
|
||||
///
|
||||
/// [`statfs`]: crate::fs::statfs
|
||||
/// [`fstatfs`]: crate::fs::fstatfs
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub type StatFs = linux_raw_sys::general::statfs64;
|
||||
|
||||
/// `struct statvfs` for use with [`statvfs`] and [`fstatvfs`].
|
||||
///
|
||||
/// [`statvfs`]: crate::fs::statvfs
|
||||
/// [`fstatvfs`]: crate::fs::fstatvfs
|
||||
#[allow(missing_docs)]
|
||||
pub struct StatVfs {
|
||||
pub f_bsize: u64,
|
||||
pub f_frsize: u64,
|
||||
pub f_blocks: u64,
|
||||
pub f_bfree: u64,
|
||||
pub f_bavail: u64,
|
||||
pub f_files: u64,
|
||||
pub f_ffree: u64,
|
||||
pub f_favail: u64,
|
||||
pub f_fsid: u64,
|
||||
pub f_flag: StatVfsMountFlags,
|
||||
pub f_namemax: u64,
|
||||
}
|
||||
|
||||
/// `struct statx` for use with [`statx`].
|
||||
///
|
||||
/// [`statx`]: crate::fs::statx
|
||||
pub type Statx = linux_raw_sys::general::statx;
|
||||
|
||||
/// `struct statx_timestamp` for use with [`Statx`].
|
||||
pub type StatxTimestamp = linux_raw_sys::general::statx_timestamp;
|
||||
|
||||
/// `mode_t`
|
||||
#[cfg(not(any(
|
||||
target_arch = "x86",
|
||||
target_arch = "sparc",
|
||||
target_arch = "avr",
|
||||
target_arch = "arm",
|
||||
)))]
|
||||
pub type RawMode = linux_raw_sys::general::__kernel_mode_t;
|
||||
|
||||
/// `mode_t
|
||||
#[cfg(any(
|
||||
target_arch = "x86",
|
||||
target_arch = "sparc",
|
||||
target_arch = "avr",
|
||||
target_arch = "arm",
|
||||
))]
|
||||
// Don't use `__kernel_mode_t` since it's `u16` which differs from `st_size`.
|
||||
pub type RawMode = c::c_uint;
|
||||
|
||||
/// `dev_t`
|
||||
// Within the kernel the dev_t is 32-bit, but userspace uses a 64-bit field.
|
||||
pub type Dev = u64;
|
||||
|
||||
/// `__fsword_t`
|
||||
#[cfg(not(target_arch = "mips64"))]
|
||||
pub type FsWord = linux_raw_sys::general::__fsword_t;
|
||||
|
||||
/// `__fsword_t`
|
||||
#[cfg(target_arch = "mips64")]
|
||||
pub type FsWord = i64;
|
||||
|
||||
pub use linux_raw_sys::general::{UTIME_NOW, UTIME_OMIT};
|
||||
|
||||
/// `PROC_SUPER_MAGIC`—The magic number for the procfs filesystem.
|
||||
pub const PROC_SUPER_MAGIC: FsWord = linux_raw_sys::general::PROC_SUPER_MAGIC as FsWord;
|
||||
|
||||
/// `NFS_SUPER_MAGIC`—The magic number for the NFS filesystem.
|
||||
pub const NFS_SUPER_MAGIC: FsWord = linux_raw_sys::general::NFS_SUPER_MAGIC as FsWord;
|
||||
555
vendor/rustix/src/backend/linux_raw/io/epoll.rs
vendored
Normal file
555
vendor/rustix/src/backend/linux_raw/io/epoll.rs
vendored
Normal file
|
|
@ -0,0 +1,555 @@
|
|||
//! 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() {}
|
||||
//! ```
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
|
||||
use super::super::c;
|
||||
use crate::backend::io::syscalls::{epoll_add, epoll_create, epoll_del, epoll_mod, epoll_wait};
|
||||
use crate::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::fd::{FromRawFd, IntoRawFd};
|
||||
use crate::io;
|
||||
use alloc::vec::Vec;
|
||||
use bitflags::bitflags;
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::Deref;
|
||||
use core::ptr::null;
|
||||
|
||||
bitflags! {
|
||||
/// `EPOLL_*` for use with [`Epoll::new`].
|
||||
pub struct CreateFlags: c::c_uint {
|
||||
/// `EPOLL_CLOEXEC`
|
||||
const CLOEXEC = linux_raw_sys::general::EPOLL_CLOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// `EPOLL*` for use with [`Epoll::add`].
|
||||
#[derive(Default)]
|
||||
pub struct EventFlags: u32 {
|
||||
/// `EPOLLIN`
|
||||
const IN = linux_raw_sys::general::EPOLLIN as u32;
|
||||
|
||||
/// `EPOLLOUT`
|
||||
const OUT = linux_raw_sys::general::EPOLLOUT as u32;
|
||||
|
||||
/// `EPOLLPRI`
|
||||
const PRI = linux_raw_sys::general::EPOLLPRI as u32;
|
||||
|
||||
/// `EPOLLERR`
|
||||
const ERR = linux_raw_sys::general::EPOLLERR as u32;
|
||||
|
||||
/// `EPOLLHUP`
|
||||
const HUP = linux_raw_sys::general::EPOLLHUP as u32;
|
||||
|
||||
/// `EPOLLET`
|
||||
const ET = linux_raw_sys::general::EPOLLET as u32;
|
||||
|
||||
/// `EPOLLONESHOT`
|
||||
const ONESHOT = linux_raw_sys::general::EPOLLONESHOT as u32;
|
||||
|
||||
/// `EPOLLWAKEUP`
|
||||
const WAKEUP = linux_raw_sys::general::EPOLLWAKEUP as u32;
|
||||
|
||||
/// `EPOLLEXCLUSIVE`
|
||||
const EXCLUSIVE = linux_raw_sys::general::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> of OwnedFd`.
|
||||
///
|
||||
/// This may be used with [`OwnedFd`], or higher-level types like
|
||||
/// [`std::fs::File`] or [`std::net::TcpStream`].
|
||||
#[cfg(feature = "std")]
|
||||
pub struct Owning<'context, T: Into<OwnedFd> + From<OwnedFd>> {
|
||||
_phantom: PhantomData<&'context T>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "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(feature = "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 raw_fd = data.into().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 {
|
||||
let raw_fd = target.consume().as_raw_fd();
|
||||
|
||||
// Safety: 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.
|
||||
unsafe { T::from(io_lifetimes::OwnedFd::from_raw_fd(raw_fd)) }
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
Ok(Self {
|
||||
epoll_fd: epoll_create(flags)?,
|
||||
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);
|
||||
epoll_add(
|
||||
self.epoll_fd.as_fd(),
|
||||
raw_fd,
|
||||
&linux_raw_sys::general::epoll_event {
|
||||
events: event_flags.bits(),
|
||||
data: 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 {
|
||||
epoll_mod(
|
||||
self.epoll_fd.as_fd(),
|
||||
raw_fd,
|
||||
&linux_raw_sys::general::epoll_event {
|
||||
events: event_flags.bits(),
|
||||
data: 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();
|
||||
epoll_del(self.epoll_fd.as_fd(), raw_fd)?;
|
||||
}
|
||||
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 = epoll_wait(
|
||||
self.epoll_fd.as_fd(),
|
||||
event_list.events[..].as_mut_ptr().cast(),
|
||||
event_list.events.capacity(),
|
||||
timeout,
|
||||
)?;
|
||||
event_list.events.set_len(nfds);
|
||||
event_list.context = &self.context;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "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(feature = "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(feature = "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(feature = "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(feature = "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(feature = "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> {
|
||||
self.iter.next().map(|event| {
|
||||
// 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.
|
||||
let decoded = unsafe { (*self.context).decode(event.encoded) };
|
||||
|
||||
(event.event_flags, decoded)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A record of an event that occurred.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(target_arch = "x86_64", repr(packed))]
|
||||
struct Event {
|
||||
// Match the layout of `linux_raw_sys::general::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()
|
||||
}
|
||||
}
|
||||
517
vendor/rustix/src/backend/linux_raw/io/errno.rs
vendored
Normal file
517
vendor/rustix/src/backend/linux_raw/io/errno.rs
vendored
Normal file
|
|
@ -0,0 +1,517 @@
|
|||
//! The `rustix` `Errno` type.
|
||||
//!
|
||||
//! This type holds an OS error code, which conceptually corresponds to an
|
||||
//! `errno` value.
|
||||
//!
|
||||
//! # Safety
|
||||
//!
|
||||
//! Linux uses error codes in `-4095..0`; we use rustc attributes to describe
|
||||
//! this restricted range of values.
|
||||
#![allow(unsafe_code)]
|
||||
#![cfg_attr(not(rustc_attrs), allow(unused_unsafe))]
|
||||
|
||||
use super::super::c;
|
||||
use crate::backend::fd::RawFd;
|
||||
use crate::backend::reg::{RetNumber, RetReg};
|
||||
use crate::io;
|
||||
use linux_raw_sys::errno;
|
||||
|
||||
/// The error type for `rustix` APIs.
|
||||
///
|
||||
/// This is similar to `std::io::Error`, but only holds an OS error code,
|
||||
/// and no extra error value.
|
||||
#[repr(transparent)]
|
||||
#[doc(alias = "errno")]
|
||||
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
|
||||
// Linux returns negated error codes, and we leave them in negated form, so
|
||||
// error codes are in `-4095..0`.
|
||||
#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0xf001))]
|
||||
#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xffff))]
|
||||
pub struct Errno(u16);
|
||||
|
||||
impl Errno {
|
||||
/// Extract an `Errno` value from a `std::io::Error`.
|
||||
///
|
||||
/// This isn't a `From` conversion because it's expected to be relatively
|
||||
/// uncommon.
|
||||
#[cfg(feature = "std")]
|
||||
#[inline]
|
||||
pub fn from_io_error(io_err: &std::io::Error) -> Option<Self> {
|
||||
io_err.raw_os_error().and_then(|raw| {
|
||||
// `std::io::Error` could theoretically have arbitrary "OS error"
|
||||
// values, so check that they're in Linux's range.
|
||||
if (1..4096).contains(&raw) {
|
||||
Some(Self::from_errno(raw as u32))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Extract the raw OS error number from this error.
|
||||
#[inline]
|
||||
pub const fn raw_os_error(self) -> i32 {
|
||||
(self.0 as i16 as i32).wrapping_neg()
|
||||
}
|
||||
|
||||
/// Construct an `Errno` from a raw OS error number.
|
||||
#[inline]
|
||||
pub const fn from_raw_os_error(raw: i32) -> Self {
|
||||
Self::from_errno(raw as u32)
|
||||
}
|
||||
|
||||
/// Convert from a C errno value (which is positive) to an `Errno`.
|
||||
const fn from_errno(raw: u32) -> Self {
|
||||
// We store error values in negated form, so that we don't have to negate
|
||||
// them after every syscall.
|
||||
let encoded = raw.wrapping_neg() as u16;
|
||||
|
||||
// TODO: Use Range::contains, once that's `const`.
|
||||
const_assert!(encoded >= 0xf001);
|
||||
|
||||
// Safety: Linux syscalls return negated error values in the range
|
||||
// `-4095..0`, which we just asserted.
|
||||
unsafe { Self(encoded) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Check for an error from the result of a syscall which encodes a
|
||||
/// `c::c_int` on success.
|
||||
#[inline]
|
||||
pub(in crate::backend) fn try_decode_c_int<Num: RetNumber>(
|
||||
raw: RetReg<Num>,
|
||||
) -> io::Result<c::c_int> {
|
||||
if raw.is_in_range(-4095..0) {
|
||||
// Safety: `raw` must be in `-4095..0`, and we just checked that raw is
|
||||
// in that range.
|
||||
return Err(unsafe { Errno(raw.decode_error_code()) });
|
||||
}
|
||||
|
||||
Ok(raw.decode_c_int())
|
||||
}
|
||||
|
||||
/// Check for an error from the result of a syscall which encodes a
|
||||
/// `c::c_uint` on success.
|
||||
#[inline]
|
||||
pub(in crate::backend) fn try_decode_c_uint<Num: RetNumber>(
|
||||
raw: RetReg<Num>,
|
||||
) -> io::Result<c::c_uint> {
|
||||
if raw.is_in_range(-4095..0) {
|
||||
// Safety: `raw` must be in `-4095..0`, and we just checked that raw is
|
||||
// in that range.
|
||||
return Err(unsafe { Errno(raw.decode_error_code()) });
|
||||
}
|
||||
|
||||
Ok(raw.decode_c_uint())
|
||||
}
|
||||
|
||||
/// Check for an error from the result of a syscall which encodes a `usize` on
|
||||
/// success.
|
||||
#[inline]
|
||||
pub(in crate::backend) fn try_decode_usize<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<usize> {
|
||||
if raw.is_in_range(-4095..0) {
|
||||
// Safety: `raw` must be in `-4095..0`, and we just checked that raw is
|
||||
// in that range.
|
||||
return Err(unsafe { Errno(raw.decode_error_code()) });
|
||||
}
|
||||
|
||||
Ok(raw.decode_usize())
|
||||
}
|
||||
|
||||
/// Check for an error from the result of a syscall which encodes a
|
||||
/// `*mut c_void` on success.
|
||||
#[inline]
|
||||
pub(in crate::backend) fn try_decode_void_star<Num: RetNumber>(
|
||||
raw: RetReg<Num>,
|
||||
) -> io::Result<*mut c::c_void> {
|
||||
if raw.is_in_range(-4095..0) {
|
||||
// Safety: `raw` must be in `-4095..0`, and we just checked that raw is
|
||||
// in that range.
|
||||
return Err(unsafe { Errno(raw.decode_error_code()) });
|
||||
}
|
||||
|
||||
Ok(raw.decode_void_star())
|
||||
}
|
||||
|
||||
/// Check for an error from the result of a syscall which encodes a
|
||||
/// `u64` on success.
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[inline]
|
||||
pub(in crate::backend) fn try_decode_u64<Num: RetNumber>(raw: RetReg<Num>) -> io::Result<u64> {
|
||||
if raw.is_in_range(-4095..0) {
|
||||
// Safety: `raw` must be in `-4095..0`, and we just checked that raw is
|
||||
// in that range.
|
||||
return Err(unsafe { Errno(raw.decode_error_code()) });
|
||||
}
|
||||
|
||||
Ok(raw.decode_u64())
|
||||
}
|
||||
|
||||
/// Check for an error from the result of a syscall which encodes a file
|
||||
/// descriptor on success.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This must only be used with syscalls which return file descriptors on
|
||||
/// success.
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn try_decode_raw_fd<Num: RetNumber>(
|
||||
raw: RetReg<Num>,
|
||||
) -> io::Result<RawFd> {
|
||||
// Instead of using `check_result` here, we just check for negative, since
|
||||
// this function is only used for system calls which return file
|
||||
// descriptors, and this produces smaller code.
|
||||
if raw.is_negative() {
|
||||
debug_assert!(raw.is_in_range(-4095..0));
|
||||
|
||||
// Tell the optimizer that we know the value is in the error range.
|
||||
// This helps it avoid unnecessary integer conversions.
|
||||
#[cfg(core_intrinsics)]
|
||||
{
|
||||
core::intrinsics::assume(raw.is_in_range(-4095..0));
|
||||
}
|
||||
|
||||
return Err(Errno(raw.decode_error_code()));
|
||||
}
|
||||
|
||||
Ok(raw.decode_raw_fd())
|
||||
}
|
||||
|
||||
/// Check for an error from the result of a syscall which encodes no value on
|
||||
/// success. On success, return the unconsumed `raw` value.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This must only be used with syscalls which return no value on success.
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn try_decode_void<Num: RetNumber>(
|
||||
raw: RetReg<Num>,
|
||||
) -> io::Result<()> {
|
||||
// Instead of using `check_result` here, we just check for zero, since this
|
||||
// function is only used for system calls which have no other return value,
|
||||
// and this produces smaller code.
|
||||
if raw.is_nonzero() {
|
||||
debug_assert!(raw.is_in_range(-4095..0));
|
||||
|
||||
// Tell the optimizer that we know the value is in the error range.
|
||||
// This helps it avoid unnecessary integer conversions.
|
||||
#[cfg(core_intrinsics)]
|
||||
{
|
||||
core::intrinsics::assume(raw.is_in_range(-4095..0));
|
||||
}
|
||||
|
||||
return Err(Errno(raw.decode_error_code()));
|
||||
}
|
||||
|
||||
raw.decode_void();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check for an error from the result of a syscall which does not return on
|
||||
/// success. On success, return the unconsumed `raw` value.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This must only be used with syscalls which do not return on success.
|
||||
#[cfg(feature = "runtime")]
|
||||
#[inline]
|
||||
pub(in crate::backend) unsafe fn try_decode_error<Num: RetNumber>(raw: RetReg<Num>) -> io::Errno {
|
||||
debug_assert!(raw.is_in_range(-4095..0));
|
||||
|
||||
// Tell the optimizer that we know the value is in the error range.
|
||||
// This helps it avoid unnecessary integer conversions.
|
||||
#[cfg(core_intrinsics)]
|
||||
{
|
||||
core::intrinsics::assume(raw.is_in_range(-4095..0));
|
||||
}
|
||||
|
||||
Errno(raw.decode_error_code())
|
||||
}
|
||||
|
||||
/// Return the contained `usize` value.
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[inline]
|
||||
pub(in crate::backend) fn decode_usize_infallible<Num: RetNumber>(raw: RetReg<Num>) -> usize {
|
||||
raw.decode_usize()
|
||||
}
|
||||
|
||||
impl Errno {
|
||||
/// `EACCES`
|
||||
#[doc(alias = "ACCES")]
|
||||
pub const ACCESS: Self = Self::from_errno(errno::EACCES);
|
||||
/// `EADDRINUSE`
|
||||
pub const ADDRINUSE: Self = Self::from_errno(errno::EADDRINUSE);
|
||||
/// `EADDRNOTAVAIL`
|
||||
pub const ADDRNOTAVAIL: Self = Self::from_errno(errno::EADDRNOTAVAIL);
|
||||
/// `EADV`
|
||||
pub const ADV: Self = Self::from_errno(errno::EADV);
|
||||
/// `EAFNOSUPPORT`
|
||||
pub const AFNOSUPPORT: Self = Self::from_errno(errno::EAFNOSUPPORT);
|
||||
/// `EAGAIN`
|
||||
pub const AGAIN: Self = Self::from_errno(errno::EAGAIN);
|
||||
/// `EALREADY`
|
||||
pub const ALREADY: Self = Self::from_errno(errno::EALREADY);
|
||||
/// `EBADE`
|
||||
pub const BADE: Self = Self::from_errno(errno::EBADE);
|
||||
/// `EBADF`
|
||||
pub const BADF: Self = Self::from_errno(errno::EBADF);
|
||||
/// `EBADFD`
|
||||
pub const BADFD: Self = Self::from_errno(errno::EBADFD);
|
||||
/// `EBADMSG`
|
||||
pub const BADMSG: Self = Self::from_errno(errno::EBADMSG);
|
||||
/// `EBADR`
|
||||
pub const BADR: Self = Self::from_errno(errno::EBADR);
|
||||
/// `EBADRQC`
|
||||
pub const BADRQC: Self = Self::from_errno(errno::EBADRQC);
|
||||
/// `EBADSLT`
|
||||
pub const BADSLT: Self = Self::from_errno(errno::EBADSLT);
|
||||
/// `EBFONT`
|
||||
pub const BFONT: Self = Self::from_errno(errno::EBFONT);
|
||||
/// `EBUSY`
|
||||
pub const BUSY: Self = Self::from_errno(errno::EBUSY);
|
||||
/// `ECANCELED`
|
||||
pub const CANCELED: Self = Self::from_errno(errno::ECANCELED);
|
||||
/// `ECHILD`
|
||||
pub const CHILD: Self = Self::from_errno(errno::ECHILD);
|
||||
/// `ECHRNG`
|
||||
pub const CHRNG: Self = Self::from_errno(errno::ECHRNG);
|
||||
/// `ECOMM`
|
||||
pub const COMM: Self = Self::from_errno(errno::ECOMM);
|
||||
/// `ECONNABORTED`
|
||||
pub const CONNABORTED: Self = Self::from_errno(errno::ECONNABORTED);
|
||||
/// `ECONNREFUSED`
|
||||
pub const CONNREFUSED: Self = Self::from_errno(errno::ECONNREFUSED);
|
||||
/// `ECONNRESET`
|
||||
pub const CONNRESET: Self = Self::from_errno(errno::ECONNRESET);
|
||||
/// `EDEADLK`
|
||||
pub const DEADLK: Self = Self::from_errno(errno::EDEADLK);
|
||||
/// `EDEADLOCK`
|
||||
pub const DEADLOCK: Self = Self::from_errno(errno::EDEADLOCK);
|
||||
/// `EDESTADDRREQ`
|
||||
pub const DESTADDRREQ: Self = Self::from_errno(errno::EDESTADDRREQ);
|
||||
/// `EDOM`
|
||||
pub const DOM: Self = Self::from_errno(errno::EDOM);
|
||||
/// `EDOTDOT`
|
||||
pub const DOTDOT: Self = Self::from_errno(errno::EDOTDOT);
|
||||
/// `EDQUOT`
|
||||
pub const DQUOT: Self = Self::from_errno(errno::EDQUOT);
|
||||
/// `EEXIST`
|
||||
pub const EXIST: Self = Self::from_errno(errno::EEXIST);
|
||||
/// `EFAULT`
|
||||
pub const FAULT: Self = Self::from_errno(errno::EFAULT);
|
||||
/// `EFBIG`
|
||||
pub const FBIG: Self = Self::from_errno(errno::EFBIG);
|
||||
/// `EHOSTDOWN`
|
||||
pub const HOSTDOWN: Self = Self::from_errno(errno::EHOSTDOWN);
|
||||
/// `EHOSTUNREACH`
|
||||
pub const HOSTUNREACH: Self = Self::from_errno(errno::EHOSTUNREACH);
|
||||
/// `EHWPOISON`
|
||||
pub const HWPOISON: Self = Self::from_errno(errno::EHWPOISON);
|
||||
/// `EIDRM`
|
||||
pub const IDRM: Self = Self::from_errno(errno::EIDRM);
|
||||
/// `EILSEQ`
|
||||
pub const ILSEQ: Self = Self::from_errno(errno::EILSEQ);
|
||||
/// `EINPROGRESS`
|
||||
pub const INPROGRESS: Self = Self::from_errno(errno::EINPROGRESS);
|
||||
/// `EINTR`.
|
||||
///
|
||||
/// For a convenient way to retry system calls that exit with `INTR`, use
|
||||
/// [`retry_on_intr`].
|
||||
///
|
||||
/// [`retry_on_intr`]: io::retry_on_intr
|
||||
pub const INTR: Self = Self::from_errno(errno::EINTR);
|
||||
/// `EINVAL`
|
||||
pub const INVAL: Self = Self::from_errno(errno::EINVAL);
|
||||
/// `EIO`
|
||||
pub const IO: Self = Self::from_errno(errno::EIO);
|
||||
/// `EISCONN`
|
||||
pub const ISCONN: Self = Self::from_errno(errno::EISCONN);
|
||||
/// `EISDIR`
|
||||
pub const ISDIR: Self = Self::from_errno(errno::EISDIR);
|
||||
/// `EISNAM`
|
||||
pub const ISNAM: Self = Self::from_errno(errno::EISNAM);
|
||||
/// `EKEYEXPIRED`
|
||||
pub const KEYEXPIRED: Self = Self::from_errno(errno::EKEYEXPIRED);
|
||||
/// `EKEYREJECTED`
|
||||
pub const KEYREJECTED: Self = Self::from_errno(errno::EKEYREJECTED);
|
||||
/// `EKEYREVOKED`
|
||||
pub const KEYREVOKED: Self = Self::from_errno(errno::EKEYREVOKED);
|
||||
/// `EL2HLT`
|
||||
pub const L2HLT: Self = Self::from_errno(errno::EL2HLT);
|
||||
/// `EL2NSYNC`
|
||||
pub const L2NSYNC: Self = Self::from_errno(errno::EL2NSYNC);
|
||||
/// `EL3HLT`
|
||||
pub const L3HLT: Self = Self::from_errno(errno::EL3HLT);
|
||||
/// `EL3RST`
|
||||
pub const L3RST: Self = Self::from_errno(errno::EL3RST);
|
||||
/// `ELIBACC`
|
||||
pub const LIBACC: Self = Self::from_errno(errno::ELIBACC);
|
||||
/// `ELIBBAD`
|
||||
pub const LIBBAD: Self = Self::from_errno(errno::ELIBBAD);
|
||||
/// `ELIBEXEC`
|
||||
pub const LIBEXEC: Self = Self::from_errno(errno::ELIBEXEC);
|
||||
/// `ELIBMAX`
|
||||
pub const LIBMAX: Self = Self::from_errno(errno::ELIBMAX);
|
||||
/// `ELIBSCN`
|
||||
pub const LIBSCN: Self = Self::from_errno(errno::ELIBSCN);
|
||||
/// `ELNRNG`
|
||||
pub const LNRNG: Self = Self::from_errno(errno::ELNRNG);
|
||||
/// `ELOOP`
|
||||
pub const LOOP: Self = Self::from_errno(errno::ELOOP);
|
||||
/// `EMEDIUMTYPE`
|
||||
pub const MEDIUMTYPE: Self = Self::from_errno(errno::EMEDIUMTYPE);
|
||||
/// `EMFILE`
|
||||
pub const MFILE: Self = Self::from_errno(errno::EMFILE);
|
||||
/// `EMLINK`
|
||||
pub const MLINK: Self = Self::from_errno(errno::EMLINK);
|
||||
/// `EMSGSIZE`
|
||||
pub const MSGSIZE: Self = Self::from_errno(errno::EMSGSIZE);
|
||||
/// `EMULTIHOP`
|
||||
pub const MULTIHOP: Self = Self::from_errno(errno::EMULTIHOP);
|
||||
/// `ENAMETOOLONG`
|
||||
pub const NAMETOOLONG: Self = Self::from_errno(errno::ENAMETOOLONG);
|
||||
/// `ENAVAIL`
|
||||
pub const NAVAIL: Self = Self::from_errno(errno::ENAVAIL);
|
||||
/// `ENETDOWN`
|
||||
pub const NETDOWN: Self = Self::from_errno(errno::ENETDOWN);
|
||||
/// `ENETRESET`
|
||||
pub const NETRESET: Self = Self::from_errno(errno::ENETRESET);
|
||||
/// `ENETUNREACH`
|
||||
pub const NETUNREACH: Self = Self::from_errno(errno::ENETUNREACH);
|
||||
/// `ENFILE`
|
||||
pub const NFILE: Self = Self::from_errno(errno::ENFILE);
|
||||
/// `ENOANO`
|
||||
pub const NOANO: Self = Self::from_errno(errno::ENOANO);
|
||||
/// `ENOBUFS`
|
||||
pub const NOBUFS: Self = Self::from_errno(errno::ENOBUFS);
|
||||
/// `ENOCSI`
|
||||
pub const NOCSI: Self = Self::from_errno(errno::ENOCSI);
|
||||
/// `ENODATA`
|
||||
#[doc(alias = "NOATTR")]
|
||||
pub const NODATA: Self = Self::from_errno(errno::ENODATA);
|
||||
/// `ENODEV`
|
||||
pub const NODEV: Self = Self::from_errno(errno::ENODEV);
|
||||
/// `ENOENT`
|
||||
pub const NOENT: Self = Self::from_errno(errno::ENOENT);
|
||||
/// `ENOEXEC`
|
||||
pub const NOEXEC: Self = Self::from_errno(errno::ENOEXEC);
|
||||
/// `ENOKEY`
|
||||
pub const NOKEY: Self = Self::from_errno(errno::ENOKEY);
|
||||
/// `ENOLCK`
|
||||
pub const NOLCK: Self = Self::from_errno(errno::ENOLCK);
|
||||
/// `ENOLINK`
|
||||
pub const NOLINK: Self = Self::from_errno(errno::ENOLINK);
|
||||
/// `ENOMEDIUM`
|
||||
pub const NOMEDIUM: Self = Self::from_errno(errno::ENOMEDIUM);
|
||||
/// `ENOMEM`
|
||||
pub const NOMEM: Self = Self::from_errno(errno::ENOMEM);
|
||||
/// `ENOMSG`
|
||||
pub const NOMSG: Self = Self::from_errno(errno::ENOMSG);
|
||||
/// `ENONET`
|
||||
pub const NONET: Self = Self::from_errno(errno::ENONET);
|
||||
/// `ENOPKG`
|
||||
pub const NOPKG: Self = Self::from_errno(errno::ENOPKG);
|
||||
/// `ENOPROTOOPT`
|
||||
pub const NOPROTOOPT: Self = Self::from_errno(errno::ENOPROTOOPT);
|
||||
/// `ENOSPC`
|
||||
pub const NOSPC: Self = Self::from_errno(errno::ENOSPC);
|
||||
/// `ENOSR`
|
||||
pub const NOSR: Self = Self::from_errno(errno::ENOSR);
|
||||
/// `ENOSTR`
|
||||
pub const NOSTR: Self = Self::from_errno(errno::ENOSTR);
|
||||
/// `ENOSYS`
|
||||
pub const NOSYS: Self = Self::from_errno(errno::ENOSYS);
|
||||
/// `ENOTBLK`
|
||||
pub const NOTBLK: Self = Self::from_errno(errno::ENOTBLK);
|
||||
/// `ENOTCONN`
|
||||
pub const NOTCONN: Self = Self::from_errno(errno::ENOTCONN);
|
||||
/// `ENOTDIR`
|
||||
pub const NOTDIR: Self = Self::from_errno(errno::ENOTDIR);
|
||||
/// `ENOTEMPTY`
|
||||
pub const NOTEMPTY: Self = Self::from_errno(errno::ENOTEMPTY);
|
||||
/// `ENOTNAM`
|
||||
pub const NOTNAM: Self = Self::from_errno(errno::ENOTNAM);
|
||||
/// `ENOTRECOVERABLE`
|
||||
pub const NOTRECOVERABLE: Self = Self::from_errno(errno::ENOTRECOVERABLE);
|
||||
/// `ENOTSOCK`
|
||||
pub const NOTSOCK: Self = Self::from_errno(errno::ENOTSOCK);
|
||||
/// `ENOTSUP`
|
||||
// On Linux, `ENOTSUP` has the same value as `EOPNOTSUPP`.
|
||||
pub const NOTSUP: Self = Self::from_errno(errno::EOPNOTSUPP);
|
||||
/// `ENOTTY`
|
||||
pub const NOTTY: Self = Self::from_errno(errno::ENOTTY);
|
||||
/// `ENOTUNIQ`
|
||||
pub const NOTUNIQ: Self = Self::from_errno(errno::ENOTUNIQ);
|
||||
/// `ENXIO`
|
||||
pub const NXIO: Self = Self::from_errno(errno::ENXIO);
|
||||
/// `EOPNOTSUPP`
|
||||
pub const OPNOTSUPP: Self = Self::from_errno(errno::EOPNOTSUPP);
|
||||
/// `EOVERFLOW`
|
||||
pub const OVERFLOW: Self = Self::from_errno(errno::EOVERFLOW);
|
||||
/// `EOWNERDEAD`
|
||||
pub const OWNERDEAD: Self = Self::from_errno(errno::EOWNERDEAD);
|
||||
/// `EPERM`
|
||||
pub const PERM: Self = Self::from_errno(errno::EPERM);
|
||||
/// `EPFNOSUPPORT`
|
||||
pub const PFNOSUPPORT: Self = Self::from_errno(errno::EPFNOSUPPORT);
|
||||
/// `EPIPE`
|
||||
pub const PIPE: Self = Self::from_errno(errno::EPIPE);
|
||||
/// `EPROTO`
|
||||
pub const PROTO: Self = Self::from_errno(errno::EPROTO);
|
||||
/// `EPROTONOSUPPORT`
|
||||
pub const PROTONOSUPPORT: Self = Self::from_errno(errno::EPROTONOSUPPORT);
|
||||
/// `EPROTOTYPE`
|
||||
pub const PROTOTYPE: Self = Self::from_errno(errno::EPROTOTYPE);
|
||||
/// `ERANGE`
|
||||
pub const RANGE: Self = Self::from_errno(errno::ERANGE);
|
||||
/// `EREMCHG`
|
||||
pub const REMCHG: Self = Self::from_errno(errno::EREMCHG);
|
||||
/// `EREMOTE`
|
||||
pub const REMOTE: Self = Self::from_errno(errno::EREMOTE);
|
||||
/// `EREMOTEIO`
|
||||
pub const REMOTEIO: Self = Self::from_errno(errno::EREMOTEIO);
|
||||
/// `ERESTART`
|
||||
pub const RESTART: Self = Self::from_errno(errno::ERESTART);
|
||||
/// `ERFKILL`
|
||||
pub const RFKILL: Self = Self::from_errno(errno::ERFKILL);
|
||||
/// `EROFS`
|
||||
pub const ROFS: Self = Self::from_errno(errno::EROFS);
|
||||
/// `ESHUTDOWN`
|
||||
pub const SHUTDOWN: Self = Self::from_errno(errno::ESHUTDOWN);
|
||||
/// `ESOCKTNOSUPPORT`
|
||||
pub const SOCKTNOSUPPORT: Self = Self::from_errno(errno::ESOCKTNOSUPPORT);
|
||||
/// `ESPIPE`
|
||||
pub const SPIPE: Self = Self::from_errno(errno::ESPIPE);
|
||||
/// `ESRCH`
|
||||
pub const SRCH: Self = Self::from_errno(errno::ESRCH);
|
||||
/// `ESRMNT`
|
||||
pub const SRMNT: Self = Self::from_errno(errno::ESRMNT);
|
||||
/// `ESTALE`
|
||||
pub const STALE: Self = Self::from_errno(errno::ESTALE);
|
||||
/// `ESTRPIPE`
|
||||
pub const STRPIPE: Self = Self::from_errno(errno::ESTRPIPE);
|
||||
/// `ETIME`
|
||||
pub const TIME: Self = Self::from_errno(errno::ETIME);
|
||||
/// `ETIMEDOUT`
|
||||
pub const TIMEDOUT: Self = Self::from_errno(errno::ETIMEDOUT);
|
||||
/// `E2BIG`
|
||||
#[doc(alias = "2BIG")]
|
||||
pub const TOOBIG: Self = Self::from_errno(errno::E2BIG);
|
||||
/// `ETOOMANYREFS`
|
||||
pub const TOOMANYREFS: Self = Self::from_errno(errno::ETOOMANYREFS);
|
||||
/// `ETXTBSY`
|
||||
pub const TXTBSY: Self = Self::from_errno(errno::ETXTBSY);
|
||||
/// `EUCLEAN`
|
||||
pub const UCLEAN: Self = Self::from_errno(errno::EUCLEAN);
|
||||
/// `EUNATCH`
|
||||
pub const UNATCH: Self = Self::from_errno(errno::EUNATCH);
|
||||
/// `EUSERS`
|
||||
pub const USERS: Self = Self::from_errno(errno::EUSERS);
|
||||
/// `EWOULDBLOCK`
|
||||
pub const WOULDBLOCK: Self = Self::from_errno(errno::EWOULDBLOCK);
|
||||
/// `EXDEV`
|
||||
pub const XDEV: Self = Self::from_errno(errno::EXDEV);
|
||||
/// `EXFULL`
|
||||
pub const XFULL: Self = Self::from_errno(errno::EXFULL);
|
||||
}
|
||||
98
vendor/rustix/src/backend/linux_raw/io/io_slice.rs
vendored
Normal file
98
vendor/rustix/src/backend/linux_raw/io/io_slice.rs
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
//! The following is derived from Rust's
|
||||
//! library/std/src/sys/unix/io.rs
|
||||
//! dca3f1b786efd27be3b325ed1e01e247aa589c3b.
|
||||
|
||||
#![allow(unsafe_code)]
|
||||
use super::super::c;
|
||||
use core::marker::PhantomData;
|
||||
use core::slice;
|
||||
use linux_raw_sys::general::__kernel_size_t;
|
||||
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSlice.html>
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct IoSlice<'a> {
|
||||
vec: c::iovec,
|
||||
_p: PhantomData<&'a [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> IoSlice<'a> {
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSlice.html#method.new>
|
||||
#[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() as _,
|
||||
},
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSlice.html#method.advance>
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
if self.vec.iov_len < n as _ {
|
||||
panic!("advancing IoSlice beyond its length");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.vec.iov_len -= n as __kernel_size_t;
|
||||
self.vec.iov_base = self.vec.iov_base.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSlice.html#method.as_slice>
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) }
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html>
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceMut<'a> {
|
||||
vec: c::iovec,
|
||||
_p: PhantomData<&'a mut [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> IoSliceMut<'a> {
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html#method.new>
|
||||
#[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() as _,
|
||||
},
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html#method.advance>
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
if self.vec.iov_len < n as _ {
|
||||
panic!("advancing IoSliceMut beyond its length");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.vec.iov_len -= n as __kernel_size_t;
|
||||
self.vec.iov_base = self.vec.iov_base.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html#method.as_slice>
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len as usize) }
|
||||
}
|
||||
|
||||
/// <https://doc.rust-lang.org/nightly/std/io/struct.IoSliceMut.html#method.as_slice_mut>
|
||||
#[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 as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
7
vendor/rustix/src/backend/linux_raw/io/mod.rs
vendored
Normal file
7
vendor/rustix/src/backend/linux_raw/io/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
pub mod epoll;
|
||||
pub(crate) mod errno;
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) mod io_slice;
|
||||
pub(crate) mod poll_fd;
|
||||
pub(crate) mod syscalls;
|
||||
pub(crate) mod types;
|
||||
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