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