1use std::{
2 ffi::CString,
3 io,
4 marker::PhantomPinned,
5 net::Shutdown,
6 os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd},
7 pin::Pin,
8};
9
10use compio_buf::{IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
11#[cfg(not(gnulinux))]
12use libc::openat;
13#[cfg(gnulinux)]
14use libc::openat64 as openat;
15#[cfg(not(any(
16 all(target_os = "linux", not(target_env = "musl")),
17 target_os = "android",
18 target_os = "l4re",
19 target_os = "hurd"
20)))]
21use libc::{ftruncate as ftruncate64, off_t as off64_t};
22#[cfg(any(
23 all(target_os = "linux", not(target_env = "musl")),
24 target_os = "android",
25 target_os = "l4re",
26 target_os = "hurd"
27))]
28use libc::{ftruncate64, off64_t};
29use pin_project_lite::pin_project;
30use socket2::{SockAddr, SockAddrStorage, Socket as Socket2, socklen_t};
31
32use crate::{op::*, sys::aio::*, sys_slice::*, syscall};
33
34pub struct CurrentDir;
37
38impl AsRawFd for CurrentDir {
39 fn as_raw_fd(&self) -> RawFd {
40 libc::AT_FDCWD
41 }
42}
43
44impl AsFd for CurrentDir {
45 fn as_fd(&self) -> BorrowedFd<'_> {
46 unsafe { BorrowedFd::borrow_raw(libc::AT_FDCWD) }
47 }
48}
49
50pin_project! {
51 pub struct OpenFile<S: AsFd> {
53 pub(crate) dirfd: S,
54 pub(crate) path: CString,
55 pub(crate) flags: i32,
56 pub(crate) mode: libc::mode_t,
57 pub(crate) opened_fd: Option<OwnedFd>,
58 }
59}
60
61impl<S: AsFd> OpenFile<S> {
62 pub fn new(dirfd: S, path: CString, flags: i32, mode: libc::mode_t) -> Self {
64 Self {
65 dirfd,
66 path,
67 flags,
68 mode,
69 opened_fd: None,
70 }
71 }
72
73 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
74 Ok(syscall!(openat(
75 self.dirfd.as_fd().as_raw_fd(),
76 self.path.as_ptr(),
77 self.flags | libc::O_CLOEXEC,
78 self.mode as libc::c_int
79 ))? as _)
80 }
81}
82
83impl<S: AsFd> IntoInner for OpenFile<S> {
84 type Inner = OwnedFd;
85
86 fn into_inner(self) -> Self::Inner {
87 self.opened_fd.expect("file not opened")
88 }
89}
90
91impl CloseFile {
92 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
93 Ok(syscall!(libc::close(self.fd.as_fd().as_raw_fd()))? as _)
94 }
95}
96
97#[derive(Debug)]
98pub struct TruncateFile<S: AsFd> {
101 pub(crate) fd: S,
102 pub(crate) size: u64,
103}
104
105impl<S: AsFd> TruncateFile<S> {
106 pub fn new(fd: S, size: u64) -> Self {
108 Self { fd, size }
109 }
110
111 pub(crate) fn call(&self) -> io::Result<usize> {
112 let size: off64_t = self
113 .size
114 .try_into()
115 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
116 crate::syscall!(ftruncate64(self.fd.as_fd().as_raw_fd(), size)).map(|v| v as _)
117 }
118}
119
120#[cfg(not(gnulinux))]
121pub use libc::stat as Stat;
122#[cfg(gnulinux)]
123pub use libc::stat64 as Stat;
124#[cfg(gnulinux)]
125pub(crate) use libc::statx as Statx;
126
127#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
128#[repr(C)]
129pub(crate) struct StatxTimestamp {
130 pub tv_sec: i64,
131 pub tv_nsec: u32,
132 pub __statx_timestamp_pad1: [i32; 1],
133}
134
135#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
136#[repr(C)]
137pub(crate) struct Statx {
138 pub stx_mask: u32,
139 pub stx_blksize: u32,
140 pub stx_attributes: u64,
141 pub stx_nlink: u32,
142 pub stx_uid: u32,
143 pub stx_gid: u32,
144 pub stx_mode: u16,
145 __statx_pad1: [u16; 1],
146 pub stx_ino: u64,
147 pub stx_size: u64,
148 pub stx_blocks: u64,
149 pub stx_attributes_mask: u64,
150 pub stx_atime: StatxTimestamp,
151 pub stx_btime: StatxTimestamp,
152 pub stx_ctime: StatxTimestamp,
153 pub stx_mtime: StatxTimestamp,
154 pub stx_rdev_major: u32,
155 pub stx_rdev_minor: u32,
156 pub stx_dev_major: u32,
157 pub stx_dev_minor: u32,
158 pub stx_mnt_id: u64,
159 pub stx_dio_mem_align: u32,
160 pub stx_dio_offset_align: u32,
161 __statx_pad3: [u64; 12],
162}
163
164#[cfg(target_os = "linux")]
165pub(crate) const fn statx_mask() -> u32 {
166 0x3FFF
169}
170
171#[cfg(target_os = "linux")]
172pub(crate) const fn statx_to_stat(statx: Statx) -> Stat {
173 let mut stat: Stat = unsafe { std::mem::zeroed() };
174 stat.st_dev = libc::makedev(statx.stx_dev_major, statx.stx_dev_minor) as _;
175 stat.st_ino = statx.stx_ino as _;
176 stat.st_nlink = statx.stx_nlink as _;
177 stat.st_mode = statx.stx_mode as _;
178 stat.st_uid = statx.stx_uid as _;
179 stat.st_gid = statx.stx_gid as _;
180 stat.st_rdev = libc::makedev(statx.stx_rdev_major, statx.stx_rdev_minor) as _;
181 stat.st_size = statx.stx_size as _;
182 stat.st_blksize = statx.stx_blksize as _;
183 stat.st_blocks = statx.stx_blocks as _;
184 stat.st_atime = statx.stx_atime.tv_sec as _;
185 stat.st_atime_nsec = statx.stx_atime.tv_nsec as _;
186 stat.st_mtime = statx.stx_mtime.tv_sec as _;
187 stat.st_mtime_nsec = statx.stx_mtime.tv_nsec as _;
188 stat.st_ctime = statx.stx_btime.tv_sec as _;
189 stat.st_ctime_nsec = statx.stx_btime.tv_nsec as _;
190 stat
191}
192
193#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
194pub(crate) const fn stat_to_statx(stat: Stat) -> Statx {
195 let mut statx: Statx = unsafe { std::mem::zeroed() };
196 statx.stx_dev_major = libc::major(stat.st_dev as _) as _;
197 statx.stx_dev_minor = libc::minor(stat.st_dev as _) as _;
198 statx.stx_ino = stat.st_ino as _;
199 statx.stx_nlink = stat.st_nlink as _;
200 statx.stx_mode = stat.st_mode as _;
201 statx.stx_uid = stat.st_uid as _;
202 statx.stx_gid = stat.st_gid as _;
203 statx.stx_rdev_major = libc::major(stat.st_rdev as _) as _;
204 statx.stx_rdev_minor = libc::minor(stat.st_rdev as _) as _;
205 statx.stx_size = stat.st_size as _;
206 statx.stx_blksize = stat.st_blksize as _;
207 statx.stx_blocks = stat.st_blocks as _;
208 statx.stx_atime.tv_sec = stat.st_atime as _;
209 statx.stx_atime.tv_nsec = stat.st_atime_nsec as _;
210 statx.stx_mtime.tv_sec = stat.st_mtime as _;
211 statx.stx_mtime.tv_nsec = stat.st_mtime_nsec as _;
212 statx.stx_btime.tv_sec = stat.st_ctime as _;
213 statx.stx_btime.tv_nsec = stat.st_ctime_nsec as _;
214 statx
215}
216
217pin_project! {
218 pub struct ReadVectoredAt<T: IoVectoredBufMut, S> {
220 pub(crate) fd: S,
221 pub(crate) offset: u64,
222 #[pin]
223 pub(crate) buffer: T,
224 pub(crate) slices: Vec<SysSlice>,
225 pub(crate) aiocb: aiocb,
226 _p: PhantomPinned,
227 }
228}
229
230impl<T: IoVectoredBufMut, S> ReadVectoredAt<T, S> {
231 pub fn new(fd: S, offset: u64, buffer: T) -> Self {
233 Self {
234 fd,
235 offset,
236 buffer,
237 slices: vec![],
238 aiocb: new_aiocb(),
239 _p: PhantomPinned,
240 }
241 }
242}
243
244impl<T: IoVectoredBufMut, S> IntoInner for ReadVectoredAt<T, S> {
245 type Inner = T;
246
247 fn into_inner(self) -> Self::Inner {
248 self.buffer
249 }
250}
251
252pin_project! {
253 pub struct WriteVectoredAt<T: IoVectoredBuf, S> {
255 pub(crate) fd: S,
256 pub(crate) offset: u64,
257 #[pin]
258 pub(crate) buffer: T,
259 pub(crate) slices: Vec<SysSlice>,
260 pub(crate) aiocb: aiocb,
261 _p: PhantomPinned,
262 }
263}
264impl<T: IoVectoredBuf, S> WriteVectoredAt<T, S> {
265 pub fn new(fd: S, offset: u64, buffer: T) -> Self {
267 Self {
268 fd,
269 offset,
270 buffer,
271 slices: vec![],
272 aiocb: new_aiocb(),
273 _p: PhantomPinned,
274 }
275 }
276}
277
278impl<T: IoVectoredBuf, S> IntoInner for WriteVectoredAt<T, S> {
279 type Inner = T;
280
281 fn into_inner(self) -> Self::Inner {
282 self.buffer
283 }
284}
285
286pin_project! {
287 pub struct ReadVectored<T: IoVectoredBufMut, S> {
289 pub(crate) fd: S,
290 #[pin]
291 pub(crate) buffer: T,
292 pub(crate) slices: Vec<SysSlice>,
293 _p: PhantomPinned,
294 }
295}
296
297impl<T: IoVectoredBufMut, S> ReadVectored<T, S> {
298 pub fn new(fd: S, buffer: T) -> Self {
300 Self {
301 fd,
302 buffer,
303 slices: vec![],
304 _p: PhantomPinned,
305 }
306 }
307}
308
309impl<T: IoVectoredBufMut, S> IntoInner for ReadVectored<T, S> {
310 type Inner = T;
311
312 fn into_inner(self) -> Self::Inner {
313 self.buffer
314 }
315}
316
317pin_project! {
318 pub struct WriteVectored<T: IoVectoredBuf, S> {
320 pub(crate) fd: S,
321 #[pin]
322 pub(crate) buffer: T,
323 pub(crate) slices: Vec<SysSlice>,
324 _p: PhantomPinned,
325 }
326}
327
328impl<T: IoVectoredBuf, S> WriteVectored<T, S> {
329 pub fn new(fd: S, buffer: T) -> Self {
331 Self {
332 fd,
333 buffer,
334 slices: vec![],
335 _p: PhantomPinned,
336 }
337 }
338}
339
340impl<T: IoVectoredBuf, S> IntoInner for WriteVectored<T, S> {
341 type Inner = T;
342
343 fn into_inner(self) -> Self::Inner {
344 self.buffer
345 }
346}
347
348pub struct Unlink<S: AsFd> {
350 pub(crate) dirfd: S,
351 pub(crate) path: CString,
352 pub(crate) dir: bool,
353}
354
355impl<S: AsFd> Unlink<S> {
356 pub fn new(dirfd: S, path: CString, dir: bool) -> Self {
358 Self { dirfd, path, dir }
359 }
360
361 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
362 Ok(syscall!(libc::unlinkat(
363 self.dirfd.as_fd().as_raw_fd(),
364 self.path.as_ptr(),
365 if self.dir { libc::AT_REMOVEDIR } else { 0 }
366 ))? as _)
367 }
368}
369
370pub struct CreateDir<S: AsFd> {
372 pub(crate) dirfd: S,
373 pub(crate) path: CString,
374 pub(crate) mode: libc::mode_t,
375}
376
377impl<S: AsFd> CreateDir<S> {
378 pub fn new(dirfd: S, path: CString, mode: libc::mode_t) -> Self {
380 Self { dirfd, path, mode }
381 }
382
383 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
384 Ok(syscall!(libc::mkdirat(
385 self.dirfd.as_fd().as_raw_fd(),
386 self.path.as_ptr(),
387 self.mode
388 ))? as _)
389 }
390}
391
392pub struct Rename<S1: AsFd, S2: AsFd> {
394 pub(crate) old_dirfd: S1,
395 pub(crate) old_path: CString,
396 pub(crate) new_dirfd: S2,
397 pub(crate) new_path: CString,
398}
399
400impl<S1: AsFd, S2: AsFd> Rename<S1, S2> {
401 pub fn new(old_dirfd: S1, old_path: CString, new_dirfd: S2, new_path: CString) -> Self {
403 Self {
404 old_dirfd,
405 old_path,
406 new_dirfd,
407 new_path,
408 }
409 }
410
411 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
412 Ok(syscall!(libc::renameat(
413 self.old_dirfd.as_fd().as_raw_fd(),
414 self.old_path.as_ptr(),
415 self.new_dirfd.as_fd().as_raw_fd(),
416 self.new_path.as_ptr()
417 ))? as _)
418 }
419}
420
421pub struct Symlink<S: AsFd> {
423 pub(crate) source: CString,
424 pub(crate) dirfd: S,
425 pub(crate) target: CString,
426}
427
428impl<S: AsFd> Symlink<S> {
429 pub fn new(source: CString, dirfd: S, target: CString) -> Self {
431 Self {
432 source,
433 dirfd,
434 target,
435 }
436 }
437
438 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
439 Ok(syscall!(libc::symlinkat(
440 self.source.as_ptr(),
441 self.dirfd.as_fd().as_raw_fd(),
442 self.target.as_ptr()
443 ))? as _)
444 }
445}
446
447pub struct HardLink<S1: AsFd, S2: AsFd> {
449 pub(crate) source_dirfd: S1,
450 pub(crate) source: CString,
451 pub(crate) target_dirfd: S2,
452 pub(crate) target: CString,
453}
454
455impl<S1: AsFd, S2: AsFd> HardLink<S1, S2> {
456 pub fn new(source_dirfd: S1, source: CString, target_dirfd: S2, target: CString) -> Self {
458 Self {
459 source_dirfd,
460 source,
461 target_dirfd,
462 target,
463 }
464 }
465
466 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
467 Ok(syscall!(libc::linkat(
468 self.source_dirfd.as_fd().as_raw_fd(),
469 self.source.as_ptr(),
470 self.target_dirfd.as_fd().as_raw_fd(),
471 self.target.as_ptr(),
472 0
473 ))? as _)
474 }
475}
476
477pin_project! {
478 pub struct CreateSocket {
480 pub(crate) domain: i32,
481 pub(crate) socket_type: i32,
482 pub(crate) protocol: i32,
483 pub(crate) opened_fd: Option<Socket2>,
484 }
485}
486
487impl CreateSocket {
488 pub fn new(domain: i32, socket_type: i32, protocol: i32) -> Self {
490 Self {
491 domain,
492 socket_type,
493 protocol,
494 opened_fd: None,
495 }
496 }
497}
498
499impl IntoInner for CreateSocket {
500 type Inner = Socket2;
501
502 fn into_inner(self) -> Self::Inner {
503 self.opened_fd.expect("socket not created")
504 }
505}
506
507impl<S: AsFd> ShutdownSocket<S> {
508 pub(crate) fn how(&self) -> i32 {
509 match self.how {
510 Shutdown::Write => libc::SHUT_WR,
511 Shutdown::Read => libc::SHUT_RD,
512 Shutdown::Both => libc::SHUT_RDWR,
513 }
514 }
515
516 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
517 Ok(syscall!(libc::shutdown(self.fd.as_fd().as_raw_fd(), self.how()))? as _)
518 }
519}
520
521impl CloseSocket {
522 pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
523 Ok(syscall!(libc::close(self.fd.as_fd().as_raw_fd()))? as _)
524 }
525}
526
527pin_project! {
528 pub struct Accept<S> {
530 pub(crate) fd: S,
531 pub(crate) buffer: SockAddrStorage,
532 pub(crate) addr_len: socklen_t,
533 pub(crate) accepted_fd: Option<Socket2>,
534 _p: PhantomPinned,
535 }
536}
537
538impl<S> Accept<S> {
539 pub fn new(fd: S) -> Self {
541 let buffer = SockAddrStorage::zeroed();
542 let addr_len = buffer.size_of();
543 Self {
544 fd,
545 buffer,
546 addr_len,
547 accepted_fd: None,
548 _p: PhantomPinned,
549 }
550 }
551}
552
553impl<S> IntoInner for Accept<S> {
554 type Inner = (Socket2, SockAddr);
555
556 fn into_inner(mut self) -> Self::Inner {
557 let socket = self.accepted_fd.take().expect("socket not accepted");
558 (socket, unsafe { SockAddr::new(self.buffer, self.addr_len) })
559 }
560}
561
562pin_project! {
563 pub struct Recv<T: IoBufMut, S> {
568 pub(crate) fd: S,
569 #[pin]
570 pub(crate) buffer: T,
571 pub(crate) flags: i32,
572 _p: PhantomPinned,
573 }
574}
575
576impl<T: IoBufMut, S> Recv<T, S> {
577 pub fn new(fd: S, buffer: T, flags: i32) -> Self {
579 Self {
580 fd,
581 buffer,
582 flags,
583 _p: PhantomPinned,
584 }
585 }
586}
587
588impl<T: IoBufMut, S> IntoInner for Recv<T, S> {
589 type Inner = T;
590
591 fn into_inner(self) -> Self::Inner {
592 self.buffer
593 }
594}
595
596pin_project! {
597 pub struct Send<T: IoBuf, S> {
602 pub(crate) fd: S,
603 #[pin]
604 pub(crate) buffer: T,
605 pub(crate) flags: i32,
606 _p: PhantomPinned,
607 }
608}
609
610impl<T: IoBuf, S> Send<T, S> {
611 pub fn new(fd: S, buffer: T, flags: i32) -> Self {
613 Self {
614 fd,
615 buffer,
616 flags,
617 _p: PhantomPinned,
618 }
619 }
620}
621
622impl<T: IoBuf, S> IntoInner for Send<T, S> {
623 type Inner = T;
624
625 fn into_inner(self) -> Self::Inner {
626 self.buffer
627 }
628}
629
630pin_project! {
631 pub struct RecvVectored<T: IoVectoredBufMut, S> {
633 pub(crate) msg: libc::msghdr,
634 pub(crate) fd: S,
635 #[pin]
636 pub(crate) buffer: T,
637 pub(crate) slices: Vec<SysSlice>,
638 pub(crate) flags: i32,
639 _p: PhantomPinned,
640 }
641}
642
643impl<T: IoVectoredBufMut, S> RecvVectored<T, S> {
644 pub fn new(fd: S, buffer: T, flags: i32) -> Self {
646 Self {
647 msg: unsafe { std::mem::zeroed() },
648 fd,
649 buffer,
650 slices: vec![],
651 flags,
652 _p: PhantomPinned,
653 }
654 }
655
656 pub(crate) fn set_msg(self: Pin<&mut Self>) {
657 let this = self.project();
658
659 *this.slices = this.buffer.sys_slices_mut();
660 this.msg.msg_iov = this.slices.as_mut_ptr() as _;
661 this.msg.msg_iovlen = this.slices.len() as _;
662 }
663}
664
665impl<T: IoVectoredBufMut, S> IntoInner for RecvVectored<T, S> {
666 type Inner = T;
667
668 fn into_inner(self) -> Self::Inner {
669 self.buffer
670 }
671}
672
673pin_project! {
674 pub struct SendVectored<T: IoVectoredBuf, S> {
676 pub(crate) msg: libc::msghdr,
677 pub(crate) fd: S,
678 #[pin]
679 pub(crate) buffer: T,
680 pub(crate) slices: Vec<SysSlice>,
681 pub(crate) flags: i32,
682 _p: PhantomPinned,
683 }
684}
685
686impl<T: IoVectoredBuf, S> SendVectored<T, S> {
687 pub fn new(fd: S, buffer: T, flags: i32) -> Self {
689 Self {
690 msg: unsafe { std::mem::zeroed() },
691 fd,
692 buffer,
693 slices: vec![],
694 flags,
695 _p: PhantomPinned,
696 }
697 }
698
699 pub(crate) fn set_msg(self: Pin<&mut Self>) {
700 let this = self.project();
701
702 *this.slices = this.buffer.as_ref().sys_slices();
703 this.msg.msg_iov = this.slices.as_mut_ptr() as _;
704 this.msg.msg_iovlen = this.slices.len() as _;
705 }
706}
707
708impl<T: IoVectoredBuf, S> IntoInner for SendVectored<T, S> {
709 type Inner = T;
710
711 fn into_inner(self) -> Self::Inner {
712 self.buffer
713 }
714}
715
716pin_project! {
717 pub struct RecvMsg<T: IoVectoredBufMut, C: IoBufMut, S> {
719 pub(crate) msg: libc::msghdr,
720 pub(crate) addr: SockAddrStorage,
721 pub(crate) fd: S,
722 #[pin]
723 pub(crate) buffer: T,
724 pub(crate) control: C,
725 pub(crate) slices: Vec<SysSlice>,
726 pub(crate) flags: i32,
727 _p: PhantomPinned,
728 }
729}
730
731impl<T: IoVectoredBufMut, C: IoBufMut, S> RecvMsg<T, C, S> {
732 pub fn new(fd: S, buffer: T, control: C, flags: i32) -> Self {
738 assert!(
739 control.buf_ptr().cast::<libc::cmsghdr>().is_aligned(),
740 "misaligned control message buffer"
741 );
742 Self {
743 msg: unsafe { std::mem::zeroed() },
744 addr: SockAddrStorage::zeroed(),
745 fd,
746 buffer,
747 control,
748 slices: vec![],
749 flags,
750 _p: PhantomPinned,
751 }
752 }
753
754 pub(crate) fn set_msg(self: Pin<&mut Self>) {
755 let this = self.project();
756 *this.slices = this.buffer.sys_slices_mut();
757
758 this.msg.msg_name = this.addr as *mut _ as _;
759 this.msg.msg_namelen = this.addr.size_of() as _;
760 this.msg.msg_iov = this.slices.as_mut_ptr() as _;
761 this.msg.msg_iovlen = this.slices.len() as _;
762 this.msg.msg_control = this.control.buf_mut_ptr() as _;
763 this.msg.msg_controllen = this.control.buf_capacity() as _;
764 }
765}
766
767impl<T: IoVectoredBufMut, C: IoBufMut, S> IntoInner for RecvMsg<T, C, S> {
768 type Inner = ((T, C), SockAddrStorage, socklen_t, usize);
769
770 fn into_inner(self) -> Self::Inner {
771 (
772 (self.buffer, self.control),
773 self.addr,
774 self.msg.msg_namelen,
775 self.msg.msg_controllen as _,
776 )
777 }
778}
779
780pin_project! {
781 pub struct SendMsg<T: IoVectoredBuf, C: IoBuf, S> {
784 pub(crate) msg: libc::msghdr,
785 pub(crate) fd: S,
786 #[pin]
787 pub(crate) buffer: T,
788 #[pin]
789 pub(crate) control: C,
790 pub(crate) addr: Option<SockAddr>,
791 pub(crate) slices: Vec<SysSlice>,
792 pub(crate) flags: i32,
793 _p: PhantomPinned,
794 }
795}
796
797impl<T: IoVectoredBuf, C: IoBuf, S> SendMsg<T, C, S> {
798 pub fn new(fd: S, buffer: T, control: C, addr: Option<SockAddr>, flags: i32) -> Self {
804 assert!(
805 control.buf_ptr().cast::<libc::cmsghdr>().is_aligned(),
806 "misaligned control message buffer"
807 );
808 Self {
809 msg: unsafe { std::mem::zeroed() },
810 fd,
811 buffer,
812 control,
813 addr,
814 slices: vec![],
815 flags,
816 _p: PhantomPinned,
817 }
818 }
819
820 pub(crate) fn set_msg(self: Pin<&mut Self>) {
821 let this = self.project();
822 *this.slices = this.buffer.as_ref().sys_slices();
823 match this.addr.as_ref() {
824 Some(addr) => {
825 this.msg.msg_name = addr.as_ptr() as _;
826 this.msg.msg_namelen = addr.len();
827 }
828 None => {
829 this.msg.msg_name = std::ptr::null_mut();
830 this.msg.msg_namelen = 0;
831 }
832 }
833 this.msg.msg_iov = this.slices.as_ptr() as _;
834 this.msg.msg_iovlen = this.slices.len() as _;
835 this.msg.msg_control = this.control.buf_ptr() as _;
836 this.msg.msg_controllen = this.control.buf_len() as _;
837 }
838}
839
840impl<T: IoVectoredBuf, C: IoBuf, S> IntoInner for SendMsg<T, C, S> {
841 type Inner = (T, C);
842
843 fn into_inner(self) -> Self::Inner {
844 (self.buffer, self.control)
845 }
846}
847
848#[derive(Debug, Clone, Copy, PartialEq, Eq)]
850pub enum Interest {
851 Readable,
853 Writable,
855}
856
857pub struct PollOnce<S> {
859 pub(crate) fd: S,
860 pub(crate) interest: Interest,
861}
862
863impl<S> PollOnce<S> {
864 pub fn new(fd: S, interest: Interest) -> Self {
866 Self { fd, interest }
867 }
868}
869
870#[cfg(linux_all)]
872pub struct Splice<S1, S2> {
873 pub(crate) fd_in: S1,
874 pub(crate) offset_in: i64,
875 pub(crate) fd_out: S2,
876 pub(crate) offset_out: i64,
877 pub(crate) len: usize,
878 pub(crate) flags: u32,
879}
880
881#[cfg(linux_all)]
882impl<S1, S2> Splice<S1, S2> {
883 pub fn new(
889 fd_in: S1,
890 offset_in: i64,
891 fd_out: S2,
892 offset_out: i64,
893 len: usize,
894 flags: u32,
895 ) -> Self {
896 Self {
897 fd_in,
898 offset_in,
899 fd_out,
900 offset_out,
901 len,
902 flags,
903 }
904 }
905}