1 //! Libc call arguments and return values are often things like `c_int`,
2 //! `c_uint`, or libc-specific pointer types. This module provides functions
3 //! for converting between rustix's types and libc types.
4
5 use super::c;
6 #[cfg(all(feature = "alloc", not(any(windows, target_os = "espidf"))))]
7 use super::fd::IntoRawFd;
8 use super::fd::{AsRawFd, BorrowedFd, FromRawFd, LibcFd, OwnedFd, RawFd};
9 #[cfg(not(windows))]
10 use crate::ffi::CStr;
11 use crate::io;
12
13 #[cfg(not(windows))]
14 #[inline]
c_str(c: &CStr) -> *const c::c_char15 pub(super) fn c_str(c: &CStr) -> *const c::c_char {
16 c.as_ptr()
17 }
18
19 #[cfg(not(any(windows, target_os = "espidf", target_os = "vita", target_os = "wasi")))]
20 #[inline]
no_fd() -> LibcFd21 pub(super) fn no_fd() -> LibcFd {
22 -1
23 }
24
25 #[inline]
borrowed_fd(fd: BorrowedFd<'_>) -> LibcFd26 pub(super) fn borrowed_fd(fd: BorrowedFd<'_>) -> LibcFd {
27 fd.as_raw_fd() as LibcFd
28 }
29
30 #[cfg(all(
31 feature = "alloc",
32 not(any(windows, target_os = "espidf", target_os = "redox"))
33 ))]
34 #[inline]
owned_fd(fd: OwnedFd) -> LibcFd35 pub(super) fn owned_fd(fd: OwnedFd) -> LibcFd {
36 fd.into_raw_fd() as LibcFd
37 }
38
39 #[inline]
ret(raw: c::c_int) -> io::Result<()>40 pub(super) fn ret(raw: c::c_int) -> io::Result<()> {
41 if raw == 0 {
42 Ok(())
43 } else {
44 Err(io::Errno::last_os_error())
45 }
46 }
47
48 #[cfg(apple)]
49 #[inline]
nonnegative_ret(raw: c::c_int) -> io::Result<()>50 pub(super) fn nonnegative_ret(raw: c::c_int) -> io::Result<()> {
51 if raw >= 0 {
52 Ok(())
53 } else {
54 Err(io::Errno::last_os_error())
55 }
56 }
57
58 #[cfg(not(any(windows, target_os = "wasi")))]
59 #[inline]
ret_infallible(raw: c::c_int)60 pub(super) unsafe fn ret_infallible(raw: c::c_int) {
61 debug_assert_eq!(raw, 0, "unexpected error: {:?}", io::Errno::last_os_error());
62 }
63
64 #[inline]
ret_c_int(raw: c::c_int) -> io::Result<c::c_int>65 pub(super) fn ret_c_int(raw: c::c_int) -> io::Result<c::c_int> {
66 if raw == -1 {
67 Err(io::Errno::last_os_error())
68 } else {
69 Ok(raw)
70 }
71 }
72
73 #[cfg(any(linux_kernel, all(target_os = "redox", feature = "event")))]
74 #[inline]
ret_u32(raw: c::c_int) -> io::Result<u32>75 pub(super) fn ret_u32(raw: c::c_int) -> io::Result<u32> {
76 if raw == -1 {
77 Err(io::Errno::last_os_error())
78 } else {
79 Ok(raw as u32)
80 }
81 }
82
83 #[inline]
ret_usize(raw: c::ssize_t) -> io::Result<usize>84 pub(super) fn ret_usize(raw: c::ssize_t) -> io::Result<usize> {
85 if raw == -1 {
86 Err(io::Errno::last_os_error())
87 } else {
88 debug_assert!(raw >= 0);
89 Ok(raw as usize)
90 }
91 }
92
93 #[cfg(not(windows))]
94 #[cfg(feature = "fs")]
95 #[inline]
ret_off_t(raw: c::off_t) -> io::Result<c::off_t>96 pub(super) fn ret_off_t(raw: c::off_t) -> io::Result<c::off_t> {
97 if raw == -1 {
98 Err(io::Errno::last_os_error())
99 } else {
100 Ok(raw)
101 }
102 }
103
104 #[cfg(not(any(windows, target_os = "wasi")))]
105 #[inline]
ret_pid_t(raw: c::pid_t) -> io::Result<c::pid_t>106 pub(super) fn ret_pid_t(raw: c::pid_t) -> io::Result<c::pid_t> {
107 if raw == -1 {
108 Err(io::Errno::last_os_error())
109 } else {
110 Ok(raw)
111 }
112 }
113
114 /// Convert a `c_int` returned from a libc function to an `OwnedFd`, if valid.
115 ///
116 /// # Safety
117 ///
118 /// The caller must ensure that this is the return value of a libc function
119 /// which returns an owned file descriptor.
120 #[inline]
ret_owned_fd(raw: LibcFd) -> io::Result<OwnedFd>121 pub(super) unsafe fn ret_owned_fd(raw: LibcFd) -> io::Result<OwnedFd> {
122 if raw == !0 {
123 Err(io::Errno::last_os_error())
124 } else {
125 Ok(OwnedFd::from_raw_fd(raw as RawFd))
126 }
127 }
128
129 #[cfg(not(any(windows, target_os = "wasi")))]
130 #[inline]
ret_discarded_fd(raw: LibcFd) -> io::Result<()>131 pub(super) fn ret_discarded_fd(raw: LibcFd) -> io::Result<()> {
132 if raw == !0 {
133 Err(io::Errno::last_os_error())
134 } else {
135 Ok(())
136 }
137 }
138
139 #[cfg(all(feature = "alloc", not(any(windows, target_os = "wasi"))))]
140 #[inline]
ret_discarded_char_ptr(raw: *mut c::c_char) -> io::Result<()>141 pub(super) fn ret_discarded_char_ptr(raw: *mut c::c_char) -> io::Result<()> {
142 if raw.is_null() {
143 Err(io::Errno::last_os_error())
144 } else {
145 Ok(())
146 }
147 }
148
149 /// Convert the buffer-length argument value of a `send` or `recv` call.
150 #[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
151 #[inline]
send_recv_len(len: usize) -> usize152 pub(super) fn send_recv_len(len: usize) -> usize {
153 len
154 }
155
156 /// Convert the buffer-length argument value of a `send` or `recv` call.
157 #[cfg(windows)]
158 #[inline]
send_recv_len(len: usize) -> i32159 pub(super) fn send_recv_len(len: usize) -> i32 {
160 // On Windows, the length argument has type `i32`; saturate the length,
161 // since `send` and `recv` are allowed to send and recv less data than
162 // requested.
163 len.try_into().unwrap_or(i32::MAX)
164 }
165
166 /// Convert the return value of a `send` or `recv` call.
167 #[cfg(not(any(windows, target_os = "redox", target_os = "wasi")))]
168 #[inline]
ret_send_recv(len: isize) -> io::Result<usize>169 pub(super) fn ret_send_recv(len: isize) -> io::Result<usize> {
170 ret_usize(len)
171 }
172
173 /// Convert the return value of a `send` or `recv` call.
174 #[cfg(windows)]
175 #[inline]
ret_send_recv(len: i32) -> io::Result<usize>176 pub(super) fn ret_send_recv(len: i32) -> io::Result<usize> {
177 ret_usize(len as isize)
178 }
179
180 /// Convert the value to the `msg_iovlen` field of a `msghdr` struct.
181 #[cfg(all(
182 not(any(windows, target_os = "espidf", target_os = "redox", target_os = "wasi")),
183 any(
184 target_os = "android",
185 all(
186 target_os = "linux",
187 not(target_env = "musl"),
188 not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
189 )
190 )
191 ))]
192 #[inline]
msg_iov_len(len: usize) -> c::size_t193 pub(super) fn msg_iov_len(len: usize) -> c::size_t {
194 len
195 }
196
197 /// Convert the value to the `msg_iovlen` field of a `msghdr` struct.
198 #[cfg(all(
199 not(any(
200 windows,
201 target_os = "espidf",
202 target_os = "redox",
203 target_os = "vita",
204 target_os = "wasi"
205 )),
206 not(any(
207 target_os = "android",
208 all(
209 target_os = "linux",
210 not(target_env = "musl"),
211 not(all(target_env = "uclibc", any(target_arch = "arm", target_arch = "mips")))
212 )
213 ))
214 ))]
215 #[inline]
msg_iov_len(len: usize) -> c::c_int216 pub(crate) fn msg_iov_len(len: usize) -> c::c_int {
217 len.try_into().unwrap_or(c::c_int::MAX)
218 }
219
220 /// Convert the value to a `socklen_t`.
221 #[cfg(any(
222 bsd,
223 solarish,
224 target_env = "musl",
225 target_os = "aix",
226 target_os = "emscripten",
227 target_os = "fuchsia",
228 target_os = "haiku",
229 target_os = "nto",
230 ))]
231 #[inline]
msg_control_len(len: usize) -> c::socklen_t232 pub(crate) fn msg_control_len(len: usize) -> c::socklen_t {
233 len.try_into().unwrap_or(c::socklen_t::MAX)
234 }
235
236 /// Convert the value to a `size_t`.
237 #[cfg(not(any(
238 bsd,
239 solarish,
240 windows,
241 target_env = "musl",
242 target_os = "aix",
243 target_os = "emscripten",
244 target_os = "espidf",
245 target_os = "fuchsia",
246 target_os = "haiku",
247 target_os = "nto",
248 target_os = "redox",
249 target_os = "vita",
250 target_os = "wasi",
251 )))]
252 #[inline]
msg_control_len(len: usize) -> c::size_t253 pub(crate) fn msg_control_len(len: usize) -> c::size_t {
254 len
255 }
256