]> git.proxmox.com Git - rustc.git/blame - vendor/rustix-0.37.22/src/backend/libc/io/syscalls.rs
New upstream version 1.73.0+dfsg1
[rustc.git] / vendor / rustix-0.37.22 / src / backend / libc / io / syscalls.rs
CommitLineData
fe692bf9
FG
1//! libc syscalls supporting `rustix::io`.
2
3use super::super::c;
4#[cfg(any(
5 target_os = "android",
6 all(target_os = "linux", not(target_env = "gnu")),
7))]
8use super::super::conv::syscall_ret_usize;
9use super::super::conv::{borrowed_fd, ret, ret_c_int, ret_discarded_fd, ret_owned_fd, ret_usize};
10use super::super::offset::{libc_pread, libc_pwrite};
11#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))]
12use super::super::offset::{libc_preadv, libc_pwritev};
13#[cfg(all(target_os = "linux", target_env = "gnu"))]
14use super::super::offset::{libc_preadv2, libc_pwritev2};
15use crate::fd::{AsFd, BorrowedFd, OwnedFd, RawFd};
16#[cfg(not(any(target_os = "aix", target_os = "wasi")))]
17use crate::io::DupFlags;
18#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "illumos"))]
19use crate::io::EventfdFlags;
20#[cfg(not(any(apple, target_os = "aix", target_os = "haiku", target_os = "wasi")))]
21use crate::io::PipeFlags;
22use crate::io::{self, FdFlags, IoSlice, IoSliceMut, PollFd};
23use core::cmp::min;
24use core::convert::TryInto;
25use core::mem::MaybeUninit;
26#[cfg(all(feature = "fs", feature = "net"))]
27use libc_errno::errno;
28#[cfg(linux_kernel)]
29use {
30 super::super::conv::syscall_ret_owned_fd,
31 crate::io::{IoSliceRaw, ReadWriteFlags, SpliceFlags},
32 crate::utils::optional_as_mut_ptr,
33};
34#[cfg(bsd)]
35use {crate::io::kqueue::Event, crate::utils::as_ptr, core::ptr::null};
36#[cfg(solarish)]
37use {crate::io::port::Event, crate::utils::as_mut_ptr, core::ptr::null_mut};
38
39pub(crate) fn read(fd: BorrowedFd<'_>, buf: &mut [u8]) -> io::Result<usize> {
40 unsafe {
41 ret_usize(c::read(
42 borrowed_fd(fd),
43 buf.as_mut_ptr().cast(),
44 min(buf.len(), READ_LIMIT),
45 ))
46 }
47}
48
49pub(crate) fn write(fd: BorrowedFd<'_>, buf: &[u8]) -> io::Result<usize> {
50 unsafe {
51 ret_usize(c::write(
52 borrowed_fd(fd),
53 buf.as_ptr().cast(),
54 min(buf.len(), READ_LIMIT),
55 ))
56 }
57}
58
59pub(crate) fn pread(fd: BorrowedFd<'_>, buf: &mut [u8], offset: u64) -> io::Result<usize> {
60 let len = min(buf.len(), READ_LIMIT);
61
62 // Silently cast; we'll get `EINVAL` if the value is negative.
63 let offset = offset as i64;
64
65 unsafe {
66 ret_usize(libc_pread(
67 borrowed_fd(fd),
68 buf.as_mut_ptr().cast(),
69 len,
70 offset,
71 ))
72 }
73}
74
75pub(crate) fn pwrite(fd: BorrowedFd<'_>, buf: &[u8], offset: u64) -> io::Result<usize> {
76 let len = min(buf.len(), READ_LIMIT);
77
78 // Silently cast; we'll get `EINVAL` if the value is negative.
79 let offset = offset as i64;
80
81 unsafe {
82 ret_usize(libc_pwrite(
83 borrowed_fd(fd),
84 buf.as_ptr().cast(),
85 len,
86 offset,
87 ))
88 }
89}
90
91pub(crate) fn readv(fd: BorrowedFd<'_>, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
92 unsafe {
93 ret_usize(c::readv(
94 borrowed_fd(fd),
95 bufs.as_ptr().cast::<c::iovec>(),
96 min(bufs.len(), max_iov()) as c::c_int,
97 ))
98 }
99}
100
101pub(crate) fn writev(fd: BorrowedFd<'_>, bufs: &[IoSlice]) -> io::Result<usize> {
102 unsafe {
103 ret_usize(c::writev(
104 borrowed_fd(fd),
105 bufs.as_ptr().cast::<c::iovec>(),
106 min(bufs.len(), max_iov()) as c::c_int,
107 ))
108 }
109}
110
111#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))]
112pub(crate) fn preadv(
113 fd: BorrowedFd<'_>,
114 bufs: &mut [IoSliceMut],
115 offset: u64,
116) -> io::Result<usize> {
117 // Silently cast; we'll get `EINVAL` if the value is negative.
118 let offset = offset as i64;
119 unsafe {
120 ret_usize(libc_preadv(
121 borrowed_fd(fd),
122 bufs.as_ptr().cast::<c::iovec>(),
123 min(bufs.len(), max_iov()) as c::c_int,
124 offset,
125 ))
126 }
127}
128
129#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "solaris")))]
130pub(crate) fn pwritev(fd: BorrowedFd<'_>, bufs: &[IoSlice], offset: u64) -> io::Result<usize> {
131 // Silently cast; we'll get `EINVAL` if the value is negative.
132 let offset = offset as i64;
133 unsafe {
134 ret_usize(libc_pwritev(
135 borrowed_fd(fd),
136 bufs.as_ptr().cast::<c::iovec>(),
137 min(bufs.len(), max_iov()) as c::c_int,
138 offset,
139 ))
140 }
141}
142
143#[cfg(all(target_os = "linux", target_env = "gnu"))]
144pub(crate) fn preadv2(
145 fd: BorrowedFd<'_>,
146 bufs: &mut [IoSliceMut],
147 offset: u64,
148 flags: ReadWriteFlags,
149) -> io::Result<usize> {
150 // Silently cast; we'll get `EINVAL` if the value is negative.
151 let offset = offset as i64;
152 unsafe {
153 ret_usize(libc_preadv2(
154 borrowed_fd(fd),
155 bufs.as_ptr().cast::<c::iovec>(),
156 min(bufs.len(), max_iov()) as c::c_int,
157 offset,
158 flags.bits(),
159 ))
160 }
161}
162
163/// At present, `libc` only has `preadv2` defined for glibc. On other
164/// ABIs, use `c::syscall`.
165#[cfg(any(
166 target_os = "android",
167 all(target_os = "linux", not(target_env = "gnu")),
168))]
169#[inline]
170pub(crate) fn preadv2(
171 fd: BorrowedFd<'_>,
172 bufs: &mut [IoSliceMut],
173 offset: u64,
174 flags: ReadWriteFlags,
175) -> io::Result<usize> {
176 // Silently cast; we'll get `EINVAL` if the value is negative.
177 let offset = offset as i64;
178 unsafe {
179 syscall_ret_usize(c::syscall(
180 c::SYS_preadv2,
181 borrowed_fd(fd),
182 bufs.as_ptr().cast::<c::iovec>(),
183 min(bufs.len(), max_iov()) as c::c_int,
184 offset,
185 flags.bits(),
186 ))
187 }
188}
189
190#[cfg(all(target_os = "linux", target_env = "gnu"))]
191pub(crate) fn pwritev2(
192 fd: BorrowedFd<'_>,
193 bufs: &[IoSlice],
194 offset: u64,
195 flags: ReadWriteFlags,
196) -> io::Result<usize> {
197 // Silently cast; we'll get `EINVAL` if the value is negative.
198 let offset = offset as i64;
199 unsafe {
200 ret_usize(libc_pwritev2(
201 borrowed_fd(fd),
202 bufs.as_ptr().cast::<c::iovec>(),
203 min(bufs.len(), max_iov()) as c::c_int,
204 offset,
205 flags.bits(),
206 ))
207 }
208}
209
210/// At present, `libc` only has `pwritev2` defined for glibc. On other
211/// ABIs, use `c::syscall`.
212#[cfg(any(
213 target_os = "android",
214 all(target_os = "linux", not(target_env = "gnu")),
215))]
216#[inline]
217pub(crate) fn pwritev2(
218 fd: BorrowedFd<'_>,
219 bufs: &[IoSlice],
220 offset: u64,
221 flags: ReadWriteFlags,
222) -> io::Result<usize> {
223 // Silently cast; we'll get `EINVAL` if the value is negative.
224 let offset = offset as i64;
225 unsafe {
226 syscall_ret_usize(c::syscall(
227 c::SYS_pwritev2,
228 borrowed_fd(fd),
229 bufs.as_ptr().cast::<c::iovec>(),
230 min(bufs.len(), max_iov()) as c::c_int,
231 offset,
232 flags.bits(),
233 ))
234 }
235}
236
237// These functions are derived from Rust's library/std/src/sys/unix/fd.rs at
238// revision 326ef470a8b379a180d6dc4bbef08990698a737a.
239
240// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, with the
241// manual page quoting that if the count of bytes to read is greater than
242// `SSIZE_MAX` the result is “unspecified”.
243//
244// On macOS, however, apparently the 64-bit libc is either buggy or
245// intentionally showing odd behavior by rejecting any read with a size larger
246// than or equal to `INT_MAX`. To handle both of these the read size is capped
247// on both platforms.
248#[cfg(target_os = "macos")]
249const READ_LIMIT: usize = c::c_int::MAX as usize - 1;
250#[cfg(not(target_os = "macos"))]
251const READ_LIMIT: usize = c::ssize_t::MAX as usize;
252
253#[cfg(bsd)]
254const fn max_iov() -> usize {
255 c::IOV_MAX as usize
256}
257
258#[cfg(any(linux_kernel, target_os = "emscripten", target_os = "nto"))]
259const fn max_iov() -> usize {
260 c::UIO_MAXIOV as usize
261}
262
263#[cfg(not(any(
264 bsd,
265 linux_kernel,
266 target_os = "emscripten",
267 target_os = "nto",
268 target_os = "horizon",
269)))]
270const fn max_iov() -> usize {
271 16 // The minimum value required by POSIX.
272}
273
274pub(crate) unsafe fn close(raw_fd: RawFd) {
275 let _ = c::close(raw_fd as c::c_int);
276}
277
278#[cfg(linux_kernel)]
279pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
280 unsafe { syscall_ret_owned_fd(c::syscall(c::SYS_eventfd2, initval, flags.bits())) }
281}
282
283#[cfg(any(target_os = "freebsd", target_os = "illumos"))]
284pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
add651ee
FG
285 // `eventfd` was added in FreeBSD 13, so it isn't available on FreeBSD 12.
286 #[cfg(target_os = "freebsd")]
287 unsafe {
288 weakcall! {
289 fn eventfd(
290 initval: c::c_uint,
291 flags: c::c_int
292 ) -> c::c_int
293 }
294 ret_owned_fd(eventfd(initval, flags.bits()))
295 }
296
297 #[cfg(target_os = "illumos")]
298 unsafe {
299 ret_owned_fd(c::eventfd(initval, flags.bits()))
300 }
fe692bf9
FG
301}
302
303#[cfg(linux_kernel)]
304#[inline]
305pub(crate) fn ioctl_blksszget(fd: BorrowedFd) -> io::Result<u32> {
306 let mut result = MaybeUninit::<c::c_uint>::uninit();
307 unsafe {
308 ret(c::ioctl(borrowed_fd(fd), c::BLKSSZGET, result.as_mut_ptr()))?;
309 Ok(result.assume_init() as u32)
310 }
311}
312
313#[cfg(linux_kernel)]
314#[inline]
315pub(crate) fn ioctl_blkpbszget(fd: BorrowedFd) -> io::Result<u32> {
316 let mut result = MaybeUninit::<c::c_uint>::uninit();
317 unsafe {
318 ret(c::ioctl(
319 borrowed_fd(fd),
320 c::BLKPBSZGET,
321 result.as_mut_ptr(),
322 ))?;
323 Ok(result.assume_init() as u32)
324 }
325}
326
327#[cfg(not(target_os = "redox"))]
328pub(crate) fn ioctl_fionread(fd: BorrowedFd<'_>) -> io::Result<u64> {
329 let mut nread = MaybeUninit::<c::c_int>::uninit();
330 unsafe {
331 ret(c::ioctl(borrowed_fd(fd), c::FIONREAD, nread.as_mut_ptr()))?;
332 // `FIONREAD` returns the number of bytes silently casted to a `c_int`,
333 // even when this is lossy. The best we can do is convert it back to a
334 // `u64` without sign-extending it back first.
335 Ok(u64::from(nread.assume_init() as c::c_uint))
336 }
337}
338
339pub(crate) fn ioctl_fionbio(fd: BorrowedFd<'_>, value: bool) -> io::Result<()> {
340 unsafe {
341 let data = value as c::c_int;
342 ret(c::ioctl(borrowed_fd(fd), c::FIONBIO, &data))
343 }
344}
345
346// Sparc lacks `FICLONE`.
347#[cfg(all(linux_kernel, not(any(target_arch = "sparc", target_arch = "sparc64"))))]
348pub(crate) fn ioctl_ficlone(fd: BorrowedFd<'_>, src_fd: BorrowedFd<'_>) -> io::Result<()> {
349 unsafe {
350 ret(c::ioctl(
351 borrowed_fd(fd),
352 c::FICLONE as _,
353 borrowed_fd(src_fd),
354 ))
355 }
356}
357
358#[cfg(linux_kernel)]
359#[inline]
360pub(crate) fn ext4_ioc_resize_fs(fd: BorrowedFd<'_>, blocks: u64) -> io::Result<()> {
361 // TODO: Fix linux-raw-sys to define ioctl codes for sparc.
362 #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
363 const EXT4_IOC_RESIZE_FS: u32 = 0x8008_6610;
364
365 #[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))]
366 use linux_raw_sys::ioctl::EXT4_IOC_RESIZE_FS;
367
368 unsafe { ret(c::ioctl(borrowed_fd(fd), EXT4_IOC_RESIZE_FS as _, &blocks)) }
369}
370
371#[cfg(not(any(target_os = "redox", target_os = "wasi")))]
372#[cfg(all(feature = "fs", feature = "net"))]
373pub(crate) fn is_read_write(fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
374 let (mut read, mut write) = crate::fs::fd::_is_file_read_write(fd)?;
375 let mut not_socket = false;
376 if read {
377 // Do a `recv` with `PEEK` and `DONTWAIT` for 1 byte. A 0 indicates
378 // the read side is shut down; an `EWOULDBLOCK` indicates the read
379 // side is still open.
380 match unsafe {
381 c::recv(
382 borrowed_fd(fd),
383 MaybeUninit::<[u8; 1]>::uninit()
384 .as_mut_ptr()
385 .cast::<c::c_void>(),
386 1,
387 c::MSG_PEEK | c::MSG_DONTWAIT,
388 )
389 } {
390 0 => read = false,
391 -1 => {
392 #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK`
393 match errno().0 {
394 c::EAGAIN | c::EWOULDBLOCK => (),
395 c::ENOTSOCK => not_socket = true,
396 err => return Err(io::Errno(err)),
397 }
398 }
399 _ => (),
400 }
401 }
402 if write && !not_socket {
403 // Do a `send` with `DONTWAIT` for 0 bytes. An `EPIPE` indicates
404 // the write side is shut down.
405 if unsafe { c::send(borrowed_fd(fd), [].as_ptr(), 0, c::MSG_DONTWAIT) } == -1 {
406 #[allow(unreachable_patterns)] // `EAGAIN` may equal `EWOULDBLOCK`
407 match errno().0 {
408 c::EAGAIN | c::EWOULDBLOCK => (),
409 c::ENOTSOCK => (),
410 c::EPIPE => write = false,
411 err => return Err(io::Errno(err)),
412 }
413 }
414 }
415 Ok((read, write))
416}
417
418#[cfg(target_os = "wasi")]
419#[cfg(all(feature = "fs", feature = "net"))]
420pub(crate) fn is_read_write(_fd: BorrowedFd<'_>) -> io::Result<(bool, bool)> {
421 todo!("Implement is_read_write for WASI in terms of fd_fdstat_get");
422}
423
424pub(crate) fn fcntl_getfd(fd: BorrowedFd<'_>) -> io::Result<FdFlags> {
425 unsafe { ret_c_int(c::fcntl(borrowed_fd(fd), c::F_GETFD)).map(FdFlags::from_bits_truncate) }
426}
427
428pub(crate) fn fcntl_setfd(fd: BorrowedFd<'_>, flags: FdFlags) -> io::Result<()> {
429 unsafe { ret(c::fcntl(borrowed_fd(fd), c::F_SETFD, flags.bits())) }
430}
431
432#[cfg(not(target_os = "wasi"))]
433pub(crate) fn fcntl_dupfd_cloexec(fd: BorrowedFd<'_>, min: RawFd) -> io::Result<OwnedFd> {
434 unsafe { ret_owned_fd(c::fcntl(borrowed_fd(fd), c::F_DUPFD_CLOEXEC, min)) }
435}
436
437#[cfg(not(target_os = "wasi"))]
438pub(crate) fn dup(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
439 unsafe { ret_owned_fd(c::dup(borrowed_fd(fd))) }
440}
441
442#[cfg(not(target_os = "wasi"))]
443pub(crate) fn dup2(fd: BorrowedFd<'_>, new: &mut OwnedFd) -> io::Result<()> {
444 unsafe { ret_discarded_fd(c::dup2(borrowed_fd(fd), borrowed_fd(new.as_fd()))) }
445}
446
447#[cfg(not(any(
448 apple,
449 target_os = "aix",
450 target_os = "android",
451 target_os = "dragonfly",
452 target_os = "haiku",
453 target_os = "redox",
454 target_os = "wasi",
455)))]
456pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()> {
457 unsafe {
458 ret_discarded_fd(c::dup3(
459 borrowed_fd(fd),
460 borrowed_fd(new.as_fd()),
461 flags.bits(),
462 ))
463 }
464}
465
466#[cfg(any(
467 apple,
468 target_os = "android",
469 target_os = "dragonfly",
470 target_os = "haiku",
471 target_os = "redox",
472))]
473pub(crate) fn dup3(fd: BorrowedFd<'_>, new: &mut OwnedFd, _flags: DupFlags) -> io::Result<()> {
474 // Android 5.0 has `dup3`, but libc doesn't have bindings. Emulate it
475 // using `dup2`. We don't need to worry about the difference between
476 // `dup2` and `dup3` when the file descriptors are equal because we
477 // have an `&mut OwnedFd` which means `fd` doesn't alias it.
478 dup2(fd, new)
479}
480
481#[cfg(apple)]
482pub(crate) fn ioctl_fioclex(fd: BorrowedFd<'_>) -> io::Result<()> {
483 unsafe {
484 ret(c::ioctl(
485 borrowed_fd(fd),
486 c::FIOCLEX,
487 core::ptr::null_mut::<u8>(),
488 ))
489 }
490}
491
492#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
493pub(crate) fn ioctl_tiocexcl(fd: BorrowedFd) -> io::Result<()> {
494 unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCEXCL as _)) }
495}
496
497#[cfg(not(any(target_os = "haiku", target_os = "redox", target_os = "wasi")))]
498pub(crate) fn ioctl_tiocnxcl(fd: BorrowedFd) -> io::Result<()> {
499 unsafe { ret(c::ioctl(borrowed_fd(fd), c::TIOCNXCL as _)) }
500}
501
502#[cfg(bsd)]
503pub(crate) fn kqueue() -> io::Result<OwnedFd> {
504 unsafe { ret_owned_fd(c::kqueue()) }
505}
506
507#[cfg(bsd)]
508pub(crate) unsafe fn kevent(
509 kq: BorrowedFd<'_>,
510 changelist: &[Event],
511 eventlist: &mut [MaybeUninit<Event>],
512 timeout: Option<&c::timespec>,
513) -> io::Result<c::c_int> {
514 ret_c_int(c::kevent(
515 borrowed_fd(kq),
516 changelist.as_ptr().cast(),
517 changelist
518 .len()
519 .try_into()
520 .map_err(|_| io::Errno::OVERFLOW)?,
521 eventlist.as_mut_ptr().cast(),
522 eventlist
523 .len()
524 .try_into()
525 .map_err(|_| io::Errno::OVERFLOW)?,
526 timeout.map_or(null(), as_ptr),
527 ))
528}
529
530#[cfg(not(target_os = "wasi"))]
531pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> {
532 unsafe {
533 let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
534 ret(c::pipe(result.as_mut_ptr().cast::<i32>()))?;
535 let [p0, p1] = result.assume_init();
536 Ok((p0, p1))
537 }
538}
539
540#[cfg(not(any(apple, target_os = "aix", target_os = "haiku", target_os = "wasi")))]
541pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> {
542 unsafe {
543 let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit();
544 ret(c::pipe2(result.as_mut_ptr().cast::<i32>(), flags.bits()))?;
545 let [p0, p1] = result.assume_init();
546 Ok((p0, p1))
547 }
548}
549
550#[inline]
551pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usize> {
552 let nfds = fds
553 .len()
554 .try_into()
555 .map_err(|_convert_err| io::Errno::INVAL)?;
556
557 ret_c_int(unsafe { c::poll(fds.as_mut_ptr().cast(), nfds, timeout) })
558 .map(|nready| nready as usize)
559}
560
561#[cfg(linux_kernel)]
562#[inline]
563pub fn splice(
564 fd_in: BorrowedFd,
565 off_in: Option<&mut u64>,
566 fd_out: BorrowedFd,
567 off_out: Option<&mut u64>,
568 len: usize,
569 flags: SpliceFlags,
570) -> io::Result<usize> {
571 let off_in = optional_as_mut_ptr(off_in).cast();
572 let off_out = optional_as_mut_ptr(off_out).cast();
573
574 unsafe {
575 ret_usize(c::splice(
576 borrowed_fd(fd_in),
577 off_in,
578 borrowed_fd(fd_out),
579 off_out,
580 len,
581 flags.bits(),
582 ))
583 }
584}
585
586#[cfg(linux_kernel)]
587#[inline]
588pub unsafe fn vmsplice(
589 fd: BorrowedFd,
590 bufs: &[IoSliceRaw],
591 flags: SpliceFlags,
592) -> io::Result<usize> {
593 ret_usize(c::vmsplice(
594 borrowed_fd(fd),
595 bufs.as_ptr().cast::<c::iovec>(),
596 min(bufs.len(), max_iov()),
597 flags.bits(),
598 ))
599}
600
601#[cfg(solarish)]
602pub(crate) fn port_create() -> io::Result<OwnedFd> {
603 unsafe { ret_owned_fd(c::port_create()) }
604}
605
606#[cfg(solarish)]
607pub(crate) unsafe fn port_associate(
608 port: BorrowedFd<'_>,
609 source: c::c_int,
610 object: c::uintptr_t,
611 events: c::c_int,
612 user: *mut c::c_void,
613) -> io::Result<()> {
614 ret(c::port_associate(
615 borrowed_fd(port),
616 source,
617 object,
618 events,
619 user,
620 ))
621}
622
623#[cfg(solarish)]
624pub(crate) unsafe fn port_dissociate(
625 port: BorrowedFd<'_>,
626 source: c::c_int,
627 object: c::uintptr_t,
628) -> io::Result<()> {
629 ret(c::port_dissociate(borrowed_fd(port), source, object))
630}
631
632#[cfg(solarish)]
633pub(crate) fn port_get(
634 port: BorrowedFd<'_>,
635 timeout: Option<&mut c::timespec>,
636) -> io::Result<Event> {
637 let mut event = MaybeUninit::<c::port_event>::uninit();
638 let timeout = timeout.map_or(null_mut(), as_mut_ptr);
639
640 unsafe {
641 ret(c::port_get(borrowed_fd(port), event.as_mut_ptr(), timeout))?;
642 }
643
644 // If we're done, initialize the event and return it.
645 Ok(Event(unsafe { event.assume_init() }))
646}
647
648#[cfg(solarish)]
649pub(crate) fn port_getn(
650 port: BorrowedFd<'_>,
651 timeout: Option<&mut c::timespec>,
652 events: &mut Vec<Event>,
653 mut nget: u32,
654) -> io::Result<()> {
655 let timeout = timeout.map_or(null_mut(), as_mut_ptr);
656 unsafe {
657 ret(c::port_getn(
658 borrowed_fd(port),
659 events.as_mut_ptr().cast(),
660 events.len().try_into().unwrap(),
661 &mut nget,
662 timeout,
663 ))?;
664 }
665
666 // Update the vector length.
667 unsafe {
668 events.set_len(nget.try_into().unwrap());
669 }
670
671 Ok(())
672}
673
674#[cfg(solarish)]
675pub(crate) fn port_send(
676 port: BorrowedFd<'_>,
677 events: c::c_int,
678 userdata: *mut c::c_void,
679) -> io::Result<()> {
680 unsafe { ret(c::port_send(borrowed_fd(port), events, userdata)) }
681}