rustix/backend/libc/system/
syscalls.rs

1//! libc syscalls supporting `rustix::process`.
2
3use super::types::RawUname;
4use crate::backend::c;
5#[cfg(not(target_os = "wasi"))]
6use crate::backend::conv::ret_infallible;
7#[cfg(target_os = "linux")]
8use crate::system::RebootCommand;
9use core::mem::MaybeUninit;
10#[cfg(linux_kernel)]
11use {
12    crate::backend::conv::c_str, crate::fd::BorrowedFd, crate::ffi::CStr, crate::system::Sysinfo,
13};
14#[cfg(not(any(
15    target_os = "emscripten",
16    target_os = "espidf",
17    target_os = "redox",
18    target_os = "vita",
19    target_os = "wasi"
20)))]
21use {crate::backend::conv::ret, crate::io};
22
23#[cfg(not(target_os = "wasi"))]
24#[inline]
25pub(crate) fn uname() -> RawUname {
26    let mut uname = MaybeUninit::<RawUname>::uninit();
27    unsafe {
28        let r = c::uname(uname.as_mut_ptr());
29
30        // On POSIX, `uname` is documented to return non-negative on success
31        // instead of the usual 0, though some specific systems do document
32        // that they always use zero allowing us to skip this check.
33        #[cfg(not(any(apple, freebsdlike, linux_like, target_os = "netbsd")))]
34        let r = core::cmp::min(r, 0);
35
36        ret_infallible(r);
37        uname.assume_init()
38    }
39}
40
41#[cfg(linux_kernel)]
42pub(crate) fn sysinfo() -> Sysinfo {
43    let mut info = MaybeUninit::<Sysinfo>::uninit();
44    unsafe {
45        ret_infallible(c::sysinfo(info.as_mut_ptr()));
46        info.assume_init()
47    }
48}
49
50#[cfg(not(any(
51    target_os = "emscripten",
52    target_os = "espidf",
53    target_os = "horizon",
54    target_os = "redox",
55    target_os = "vita",
56    target_os = "wasi"
57)))]
58pub(crate) fn sethostname(name: &[u8]) -> io::Result<()> {
59    unsafe {
60        ret(c::sethostname(
61            name.as_ptr().cast(),
62            name.len().try_into().map_err(|_| io::Errno::INVAL)?,
63        ))
64    }
65}
66
67#[cfg(not(any(
68    target_os = "android",
69    target_os = "cygwin",
70    target_os = "emscripten",
71    target_os = "espidf",
72    target_os = "illumos",
73    target_os = "haiku",
74    target_os = "horizon",
75    target_os = "redox",
76    target_os = "solaris",
77    target_os = "vita",
78    target_os = "wasi",
79)))]
80pub(crate) fn setdomainname(name: &[u8]) -> io::Result<()> {
81    unsafe {
82        ret(c::setdomainname(
83            name.as_ptr().cast(),
84            name.len().try_into().map_err(|_| io::Errno::INVAL)?,
85        ))
86    }
87}
88
89// <https://github.com/rust-lang/libc/pull/4212>
90#[cfg(target_os = "android")]
91pub(crate) fn setdomainname(name: &[u8]) -> io::Result<()> {
92    syscall! {
93        fn setdomainname(
94            name: *const c::c_char,
95            len: c::size_t
96        ) via SYS_setdomainname -> c::c_int
97    }
98
99    unsafe {
100        ret(setdomainname(
101            name.as_ptr().cast(),
102            name.len().try_into().map_err(|_| io::Errno::INVAL)?,
103        ))
104    }
105}
106
107#[cfg(target_os = "linux")]
108pub(crate) fn reboot(cmd: RebootCommand) -> io::Result<()> {
109    unsafe { ret(c::reboot(cmd as i32)) }
110}
111
112#[cfg(linux_kernel)]
113#[inline]
114pub(crate) fn init_module(image: &[u8], param_values: &CStr) -> io::Result<()> {
115    syscall! {
116        fn init_module(
117            module_image: *const c::c_void,
118            len: c::c_ulong,
119            param_values: *const c::c_char
120        ) via SYS_init_module -> c::c_int
121    }
122
123    unsafe {
124        ret(init_module(
125            image.as_ptr().cast(),
126            image.len() as _,
127            c_str(param_values),
128        ))
129    }
130}
131
132#[cfg(linux_kernel)]
133#[inline]
134pub(crate) fn finit_module(
135    fd: BorrowedFd<'_>,
136    param_values: &CStr,
137    flags: c::c_int,
138) -> io::Result<()> {
139    use crate::fd::AsRawFd as _;
140
141    syscall! {
142        fn finit_module(
143            fd: c::c_int,
144            param_values: *const c::c_char,
145            flags: c::c_int
146        ) via SYS_finit_module -> c::c_int
147    }
148
149    unsafe { ret(finit_module(fd.as_raw_fd(), c_str(param_values), flags)) }
150}
151
152#[cfg(linux_kernel)]
153#[inline]
154pub(crate) fn delete_module(name: &CStr, flags: c::c_int) -> io::Result<()> {
155    syscall! {
156        fn delete_module(
157            name: *const c::c_char,
158            flags: c::c_int
159        ) via SYS_delete_module -> c::c_int
160    }
161    unsafe { ret(delete_module(c_str(name), flags)) }
162}