summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/imp/libc/process/syscalls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/imp/libc/process/syscalls.rs')
-rw-r--r--vendor/rustix/src/imp/libc/process/syscalls.rs419
1 files changed, 419 insertions, 0 deletions
diff --git a/vendor/rustix/src/imp/libc/process/syscalls.rs b/vendor/rustix/src/imp/libc/process/syscalls.rs
new file mode 100644
index 000000000..9874f617f
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/process/syscalls.rs
@@ -0,0 +1,419 @@
+//! libc syscalls supporting `rustix::process`.
+
+use super::super::c;
+#[cfg(not(any(target_os = "wasi", target_os = "fuchsia")))]
+use super::super::conv::borrowed_fd;
+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(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(),
+ ))
+ .map(|()| 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)) }
+}