1b8a62b91Sopenharmony_ci//! Libc call arguments and return values are often things like `c_int`,
2b8a62b91Sopenharmony_ci//! `c_uint`, or libc-specific pointer types. This module provides functions
3b8a62b91Sopenharmony_ci//! for converting between rustix's types and libc types.
4b8a62b91Sopenharmony_ci
5b8a62b91Sopenharmony_ci#![allow(dead_code)]
6b8a62b91Sopenharmony_ci
7b8a62b91Sopenharmony_ciuse super::c;
8b8a62b91Sopenharmony_ciuse super::fd::{AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, LibcFd, OwnedFd, RawFd};
9b8a62b91Sopenharmony_ci#[cfg(not(windows))]
10b8a62b91Sopenharmony_ci#[cfg(feature = "fs")]
11b8a62b91Sopenharmony_ciuse super::offset::libc_off_t;
12b8a62b91Sopenharmony_ci#[cfg(not(windows))]
13b8a62b91Sopenharmony_ciuse crate::ffi::CStr;
14b8a62b91Sopenharmony_ciuse crate::io;
15b8a62b91Sopenharmony_ci#[cfg(windows)]
16b8a62b91Sopenharmony_ciuse core::convert::TryInto;
17b8a62b91Sopenharmony_ci
18b8a62b91Sopenharmony_ci#[cfg(not(windows))]
19b8a62b91Sopenharmony_ci#[inline]
20b8a62b91Sopenharmony_cipub(super) fn c_str(c: &CStr) -> *const c::c_char {
21b8a62b91Sopenharmony_ci    c.as_ptr()
22b8a62b91Sopenharmony_ci}
23b8a62b91Sopenharmony_ci
24b8a62b91Sopenharmony_ci#[cfg(not(windows))]
25b8a62b91Sopenharmony_ci#[inline]
26b8a62b91Sopenharmony_cipub(super) fn no_fd() -> LibcFd {
27b8a62b91Sopenharmony_ci    -1
28b8a62b91Sopenharmony_ci}
29b8a62b91Sopenharmony_ci
30b8a62b91Sopenharmony_ci#[inline]
31b8a62b91Sopenharmony_cipub(super) fn borrowed_fd(fd: BorrowedFd<'_>) -> LibcFd {
32b8a62b91Sopenharmony_ci    fd.as_raw_fd() as LibcFd
33b8a62b91Sopenharmony_ci}
34b8a62b91Sopenharmony_ci
35b8a62b91Sopenharmony_ci#[inline]
36b8a62b91Sopenharmony_cipub(super) fn owned_fd(fd: OwnedFd) -> LibcFd {
37b8a62b91Sopenharmony_ci    fd.into_raw_fd() as LibcFd
38b8a62b91Sopenharmony_ci}
39b8a62b91Sopenharmony_ci
40b8a62b91Sopenharmony_ci#[inline]
41b8a62b91Sopenharmony_cipub(super) fn ret(raw: c::c_int) -> io::Result<()> {
42b8a62b91Sopenharmony_ci    if raw == 0 {
43b8a62b91Sopenharmony_ci        Ok(())
44b8a62b91Sopenharmony_ci    } else {
45b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
46b8a62b91Sopenharmony_ci    }
47b8a62b91Sopenharmony_ci}
48b8a62b91Sopenharmony_ci
49b8a62b91Sopenharmony_ci#[inline]
50b8a62b91Sopenharmony_cipub(super) fn syscall_ret(raw: c::c_long) -> io::Result<()> {
51b8a62b91Sopenharmony_ci    if raw == 0 {
52b8a62b91Sopenharmony_ci        Ok(())
53b8a62b91Sopenharmony_ci    } else {
54b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
55b8a62b91Sopenharmony_ci    }
56b8a62b91Sopenharmony_ci}
57b8a62b91Sopenharmony_ci
58b8a62b91Sopenharmony_ci#[inline]
59b8a62b91Sopenharmony_cipub(super) fn nonnegative_ret(raw: c::c_int) -> io::Result<()> {
60b8a62b91Sopenharmony_ci    if raw >= 0 {
61b8a62b91Sopenharmony_ci        Ok(())
62b8a62b91Sopenharmony_ci    } else {
63b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
64b8a62b91Sopenharmony_ci    }
65b8a62b91Sopenharmony_ci}
66b8a62b91Sopenharmony_ci
67b8a62b91Sopenharmony_ci#[inline]
68b8a62b91Sopenharmony_cipub(super) unsafe fn ret_infallible(raw: c::c_int) {
69b8a62b91Sopenharmony_ci    debug_assert_eq!(raw, 0, "unexpected error: {:?}", io::Errno::last_os_error());
70b8a62b91Sopenharmony_ci}
71b8a62b91Sopenharmony_ci
72b8a62b91Sopenharmony_ci#[inline]
73b8a62b91Sopenharmony_cipub(super) fn ret_c_int(raw: c::c_int) -> io::Result<c::c_int> {
74b8a62b91Sopenharmony_ci    if raw == -1 {
75b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
76b8a62b91Sopenharmony_ci    } else {
77b8a62b91Sopenharmony_ci        Ok(raw)
78b8a62b91Sopenharmony_ci    }
79b8a62b91Sopenharmony_ci}
80b8a62b91Sopenharmony_ci
81b8a62b91Sopenharmony_ci#[inline]
82b8a62b91Sopenharmony_cipub(super) fn ret_u32(raw: c::c_int) -> io::Result<u32> {
83b8a62b91Sopenharmony_ci    if raw == -1 {
84b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
85b8a62b91Sopenharmony_ci    } else {
86b8a62b91Sopenharmony_ci        Ok(raw as u32)
87b8a62b91Sopenharmony_ci    }
88b8a62b91Sopenharmony_ci}
89b8a62b91Sopenharmony_ci
90b8a62b91Sopenharmony_ci#[inline]
91b8a62b91Sopenharmony_cipub(super) fn ret_ssize_t(raw: c::ssize_t) -> io::Result<c::ssize_t> {
92b8a62b91Sopenharmony_ci    if raw == -1 {
93b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
94b8a62b91Sopenharmony_ci    } else {
95b8a62b91Sopenharmony_ci        Ok(raw)
96b8a62b91Sopenharmony_ci    }
97b8a62b91Sopenharmony_ci}
98b8a62b91Sopenharmony_ci
99b8a62b91Sopenharmony_ci#[inline]
100b8a62b91Sopenharmony_cipub(super) fn syscall_ret_ssize_t(raw: c::c_long) -> io::Result<c::ssize_t> {
101b8a62b91Sopenharmony_ci    if raw == -1 {
102b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
103b8a62b91Sopenharmony_ci    } else {
104b8a62b91Sopenharmony_ci        Ok(raw as c::ssize_t)
105b8a62b91Sopenharmony_ci    }
106b8a62b91Sopenharmony_ci}
107b8a62b91Sopenharmony_ci
108b8a62b91Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
109b8a62b91Sopenharmony_ci#[inline]
110b8a62b91Sopenharmony_cipub(super) fn syscall_ret_u32(raw: c::c_long) -> io::Result<u32> {
111b8a62b91Sopenharmony_ci    if raw == -1 {
112b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
113b8a62b91Sopenharmony_ci    } else {
114b8a62b91Sopenharmony_ci        let r32 = raw as u32;
115b8a62b91Sopenharmony_ci
116b8a62b91Sopenharmony_ci        // Converting `raw` to `u32` should be lossless.
117b8a62b91Sopenharmony_ci        debug_assert_eq!(r32 as c::c_long, raw);
118b8a62b91Sopenharmony_ci
119b8a62b91Sopenharmony_ci        Ok(r32)
120b8a62b91Sopenharmony_ci    }
121b8a62b91Sopenharmony_ci}
122b8a62b91Sopenharmony_ci
123b8a62b91Sopenharmony_ci#[cfg(not(windows))]
124b8a62b91Sopenharmony_ci#[cfg(feature = "fs")]
125b8a62b91Sopenharmony_ci#[inline]
126b8a62b91Sopenharmony_cipub(super) fn ret_off_t(raw: libc_off_t) -> io::Result<libc_off_t> {
127b8a62b91Sopenharmony_ci    if raw == -1 {
128b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
129b8a62b91Sopenharmony_ci    } else {
130b8a62b91Sopenharmony_ci        Ok(raw)
131b8a62b91Sopenharmony_ci    }
132b8a62b91Sopenharmony_ci}
133b8a62b91Sopenharmony_ci
134b8a62b91Sopenharmony_ci#[cfg(not(windows))]
135b8a62b91Sopenharmony_ci#[inline]
136b8a62b91Sopenharmony_cipub(super) fn ret_pid_t(raw: c::pid_t) -> io::Result<c::pid_t> {
137b8a62b91Sopenharmony_ci    if raw == -1 {
138b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
139b8a62b91Sopenharmony_ci    } else {
140b8a62b91Sopenharmony_ci        Ok(raw)
141b8a62b91Sopenharmony_ci    }
142b8a62b91Sopenharmony_ci}
143b8a62b91Sopenharmony_ci
144b8a62b91Sopenharmony_ci/// Convert a `c_int` returned from a libc function to an `OwnedFd`, if valid.
145b8a62b91Sopenharmony_ci///
146b8a62b91Sopenharmony_ci/// # Safety
147b8a62b91Sopenharmony_ci///
148b8a62b91Sopenharmony_ci/// The caller must ensure that this is the return value of a libc function
149b8a62b91Sopenharmony_ci/// which returns an owned file descriptor.
150b8a62b91Sopenharmony_ci#[inline]
151b8a62b91Sopenharmony_cipub(super) unsafe fn ret_owned_fd(raw: LibcFd) -> io::Result<OwnedFd> {
152b8a62b91Sopenharmony_ci    if raw == !0 {
153b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
154b8a62b91Sopenharmony_ci    } else {
155b8a62b91Sopenharmony_ci        Ok(OwnedFd::from_raw_fd(raw as RawFd))
156b8a62b91Sopenharmony_ci    }
157b8a62b91Sopenharmony_ci}
158b8a62b91Sopenharmony_ci
159b8a62b91Sopenharmony_ci#[inline]
160b8a62b91Sopenharmony_cipub(super) fn ret_discarded_fd(raw: LibcFd) -> io::Result<()> {
161b8a62b91Sopenharmony_ci    if raw == !0 {
162b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
163b8a62b91Sopenharmony_ci    } else {
164b8a62b91Sopenharmony_ci        Ok(())
165b8a62b91Sopenharmony_ci    }
166b8a62b91Sopenharmony_ci}
167b8a62b91Sopenharmony_ci
168b8a62b91Sopenharmony_ci#[inline]
169b8a62b91Sopenharmony_cipub(super) fn ret_discarded_char_ptr(raw: *mut c::c_char) -> io::Result<()> {
170b8a62b91Sopenharmony_ci    if raw.is_null() {
171b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
172b8a62b91Sopenharmony_ci    } else {
173b8a62b91Sopenharmony_ci        Ok(())
174b8a62b91Sopenharmony_ci    }
175b8a62b91Sopenharmony_ci}
176b8a62b91Sopenharmony_ci
177b8a62b91Sopenharmony_ci/// Convert a `c_long` returned from `syscall` to an `OwnedFd`, if valid.
178b8a62b91Sopenharmony_ci///
179b8a62b91Sopenharmony_ci/// # Safety
180b8a62b91Sopenharmony_ci///
181b8a62b91Sopenharmony_ci/// The caller must ensure that this is the return value of a `syscall` call
182b8a62b91Sopenharmony_ci/// which returns an owned file descriptor.
183b8a62b91Sopenharmony_ci#[cfg(not(windows))]
184b8a62b91Sopenharmony_ci#[inline]
185b8a62b91Sopenharmony_cipub(super) unsafe fn syscall_ret_owned_fd(raw: c::c_long) -> io::Result<OwnedFd> {
186b8a62b91Sopenharmony_ci    if raw == -1 {
187b8a62b91Sopenharmony_ci        Err(io::Errno::last_os_error())
188b8a62b91Sopenharmony_ci    } else {
189b8a62b91Sopenharmony_ci        Ok(OwnedFd::from_raw_fd(raw as RawFd))
190b8a62b91Sopenharmony_ci    }
191b8a62b91Sopenharmony_ci}
192b8a62b91Sopenharmony_ci
193b8a62b91Sopenharmony_ci/// Convert the buffer-length argument value of a `send` or `recv` call.
194b8a62b91Sopenharmony_ci#[cfg(not(windows))]
195b8a62b91Sopenharmony_ci#[inline]
196b8a62b91Sopenharmony_cipub(super) fn send_recv_len(len: usize) -> usize {
197b8a62b91Sopenharmony_ci    len
198b8a62b91Sopenharmony_ci}
199b8a62b91Sopenharmony_ci
200b8a62b91Sopenharmony_ci/// Convert the buffer-length argument value of a `send` or `recv` call.
201b8a62b91Sopenharmony_ci#[cfg(windows)]
202b8a62b91Sopenharmony_ci#[inline]
203b8a62b91Sopenharmony_cipub(super) fn send_recv_len(len: usize) -> i32 {
204b8a62b91Sopenharmony_ci    // On Windows, the length argument has type `i32`; saturate the length,
205b8a62b91Sopenharmony_ci    // since `send` and `recv` are allowed to send and recv less data than
206b8a62b91Sopenharmony_ci    // requested.
207b8a62b91Sopenharmony_ci    len.try_into().unwrap_or(i32::MAX)
208b8a62b91Sopenharmony_ci}
209b8a62b91Sopenharmony_ci
210b8a62b91Sopenharmony_ci/// Convert the return value of a `send` or `recv` call.
211b8a62b91Sopenharmony_ci#[cfg(not(windows))]
212b8a62b91Sopenharmony_ci#[inline]
213b8a62b91Sopenharmony_cipub(super) fn ret_send_recv(len: isize) -> io::Result<c::ssize_t> {
214b8a62b91Sopenharmony_ci    ret_ssize_t(len)
215b8a62b91Sopenharmony_ci}
216b8a62b91Sopenharmony_ci
217b8a62b91Sopenharmony_ci/// Convert the return value of a `send` or `recv` call.
218b8a62b91Sopenharmony_ci#[cfg(windows)]
219b8a62b91Sopenharmony_ci#[inline]
220b8a62b91Sopenharmony_cipub(super) fn ret_send_recv(len: i32) -> io::Result<c::ssize_t> {
221b8a62b91Sopenharmony_ci    ret_ssize_t(len as isize)
222b8a62b91Sopenharmony_ci}
223