Skip to main content

compio_driver/sys/
unix_op.rs

1use std::{
2    ffi::CString,
3    io,
4    marker::PhantomPinned,
5    net::Shutdown,
6    os::fd::{AsFd, AsRawFd, OwnedFd},
7    pin::Pin,
8};
9
10use compio_buf::{IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
11#[cfg(not(gnulinux))]
12use libc::open;
13#[cfg(gnulinux)]
14use libc::open64 as open;
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, socklen_t};
31
32use crate::{op::*, sys::aio::*, sys_slice::*, syscall};
33
34/// Open or create a file with flags and mode.
35pub struct OpenFile {
36    pub(crate) path: CString,
37    pub(crate) flags: i32,
38    pub(crate) mode: libc::mode_t,
39}
40
41impl OpenFile {
42    /// Create [`OpenFile`].
43    pub fn new(path: CString, flags: i32, mode: libc::mode_t) -> Self {
44        Self { path, flags, mode }
45    }
46
47    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
48        Ok(syscall!(open(
49            self.path.as_ptr(),
50            self.flags | libc::O_CLOEXEC,
51            self.mode as libc::c_int
52        ))? as _)
53    }
54}
55
56impl CloseFile {
57    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
58        Ok(syscall!(libc::close(self.fd.as_fd().as_raw_fd()))? as _)
59    }
60}
61
62#[derive(Debug)]
63///  Truncates or extends the underlying file, updating the size of this file to
64/// become `size`.
65pub struct TruncateFile<S: AsFd> {
66    pub(crate) fd: S,
67    pub(crate) size: u64,
68}
69
70impl<S: AsFd> TruncateFile<S> {
71    /// Create [`TruncateFile`].
72    pub fn new(fd: S, size: u64) -> Self {
73        Self { fd, size }
74    }
75
76    pub(crate) fn call(&self) -> io::Result<usize> {
77        let size: off64_t = self
78            .size
79            .try_into()
80            .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
81        crate::syscall!(ftruncate64(self.fd.as_fd().as_raw_fd(), size)).map(|v| v as _)
82    }
83}
84
85#[cfg(not(gnulinux))]
86pub use libc::stat as Stat;
87#[cfg(gnulinux)]
88pub use libc::stat64 as Stat;
89#[cfg(gnulinux)]
90pub(crate) use libc::statx as Statx;
91
92#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
93#[repr(C)]
94pub(crate) struct StatxTimestamp {
95    pub tv_sec: i64,
96    pub tv_nsec: u32,
97    pub __statx_timestamp_pad1: [i32; 1],
98}
99
100#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
101#[repr(C)]
102pub(crate) struct Statx {
103    pub stx_mask: u32,
104    pub stx_blksize: u32,
105    pub stx_attributes: u64,
106    pub stx_nlink: u32,
107    pub stx_uid: u32,
108    pub stx_gid: u32,
109    pub stx_mode: u16,
110    __statx_pad1: [u16; 1],
111    pub stx_ino: u64,
112    pub stx_size: u64,
113    pub stx_blocks: u64,
114    pub stx_attributes_mask: u64,
115    pub stx_atime: StatxTimestamp,
116    pub stx_btime: StatxTimestamp,
117    pub stx_ctime: StatxTimestamp,
118    pub stx_mtime: StatxTimestamp,
119    pub stx_rdev_major: u32,
120    pub stx_rdev_minor: u32,
121    pub stx_dev_major: u32,
122    pub stx_dev_minor: u32,
123    pub stx_mnt_id: u64,
124    pub stx_dio_mem_align: u32,
125    pub stx_dio_offset_align: u32,
126    __statx_pad3: [u64; 12],
127}
128
129#[cfg(target_os = "linux")]
130pub(crate) const fn statx_mask() -> u32 {
131    // Set mask to ensure all known fields are filled
132    // libc::STATX_ALL | libc::STATX_MNT_ID | libc::STATX_DIOALIGN
133    0x3FFF
134}
135
136#[cfg(target_os = "linux")]
137pub(crate) const fn statx_to_stat(statx: Statx) -> Stat {
138    let mut stat: Stat = unsafe { std::mem::zeroed() };
139    stat.st_dev = libc::makedev(statx.stx_dev_major, statx.stx_dev_minor) as _;
140    stat.st_ino = statx.stx_ino as _;
141    stat.st_nlink = statx.stx_nlink as _;
142    stat.st_mode = statx.stx_mode as _;
143    stat.st_uid = statx.stx_uid as _;
144    stat.st_gid = statx.stx_gid as _;
145    stat.st_rdev = libc::makedev(statx.stx_rdev_major, statx.stx_rdev_minor) as _;
146    stat.st_size = statx.stx_size as _;
147    stat.st_blksize = statx.stx_blksize as _;
148    stat.st_blocks = statx.stx_blocks as _;
149    stat.st_atime = statx.stx_atime.tv_sec as _;
150    stat.st_atime_nsec = statx.stx_atime.tv_nsec as _;
151    stat.st_mtime = statx.stx_mtime.tv_sec as _;
152    stat.st_mtime_nsec = statx.stx_mtime.tv_nsec as _;
153    stat.st_ctime = statx.stx_btime.tv_sec as _;
154    stat.st_ctime_nsec = statx.stx_btime.tv_nsec as _;
155    stat
156}
157
158#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
159pub(crate) const fn stat_to_statx(stat: Stat) -> Statx {
160    let mut statx: Statx = unsafe { std::mem::zeroed() };
161    statx.stx_dev_major = libc::major(stat.st_dev as _) as _;
162    statx.stx_dev_minor = libc::minor(stat.st_dev as _) as _;
163    statx.stx_ino = stat.st_ino as _;
164    statx.stx_nlink = stat.st_nlink as _;
165    statx.stx_mode = stat.st_mode as _;
166    statx.stx_uid = stat.st_uid as _;
167    statx.stx_gid = stat.st_gid as _;
168    statx.stx_rdev_major = libc::major(stat.st_rdev as _) as _;
169    statx.stx_rdev_minor = libc::minor(stat.st_rdev as _) as _;
170    statx.stx_size = stat.st_size as _;
171    statx.stx_blksize = stat.st_blksize as _;
172    statx.stx_blocks = stat.st_blocks as _;
173    statx.stx_atime.tv_sec = stat.st_atime as _;
174    statx.stx_atime.tv_nsec = stat.st_atime_nsec as _;
175    statx.stx_mtime.tv_sec = stat.st_mtime as _;
176    statx.stx_mtime.tv_nsec = stat.st_mtime_nsec as _;
177    statx.stx_btime.tv_sec = stat.st_ctime as _;
178    statx.stx_btime.tv_nsec = stat.st_ctime_nsec as _;
179    statx
180}
181
182pin_project! {
183    /// Read a file at specified position into vectored buffer.
184    pub struct ReadVectoredAt<T: IoVectoredBufMut, S> {
185        pub(crate) fd: S,
186        pub(crate) offset: u64,
187        #[pin]
188        pub(crate) buffer: T,
189        pub(crate) slices: Vec<SysSlice>,
190        pub(crate) aiocb: aiocb,
191        _p: PhantomPinned,
192    }
193}
194
195impl<T: IoVectoredBufMut, S> ReadVectoredAt<T, S> {
196    /// Create [`ReadVectoredAt`].
197    pub fn new(fd: S, offset: u64, buffer: T) -> Self {
198        Self {
199            fd,
200            offset,
201            buffer,
202            slices: vec![],
203            aiocb: new_aiocb(),
204            _p: PhantomPinned,
205        }
206    }
207}
208
209impl<T: IoVectoredBufMut, S> IntoInner for ReadVectoredAt<T, S> {
210    type Inner = T;
211
212    fn into_inner(self) -> Self::Inner {
213        self.buffer
214    }
215}
216
217pin_project! {
218    /// Write a file at specified position from vectored buffer.
219    pub struct WriteVectoredAt<T: IoVectoredBuf, 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}
229impl<T: IoVectoredBuf, S> WriteVectoredAt<T, S> {
230    /// Create [`WriteVectoredAt`]
231    pub fn new(fd: S, offset: u64, buffer: T) -> Self {
232        Self {
233            fd,
234            offset,
235            buffer,
236            slices: vec![],
237            aiocb: new_aiocb(),
238            _p: PhantomPinned,
239        }
240    }
241}
242
243impl<T: IoVectoredBuf, S> IntoInner for WriteVectoredAt<T, S> {
244    type Inner = T;
245
246    fn into_inner(self) -> Self::Inner {
247        self.buffer
248    }
249}
250
251pin_project! {
252    /// Receive a file into vectored buffer.
253    pub struct ReadVectored<T: IoVectoredBufMut, S> {
254        pub(crate) fd: S,
255        #[pin]
256        pub(crate) buffer: T,
257        pub(crate) slices: Vec<SysSlice>,
258        _p: PhantomPinned,
259    }
260}
261
262impl<T: IoVectoredBufMut, S> ReadVectored<T, S> {
263    /// Create [`ReadVectored`].
264    pub fn new(fd: S, buffer: T) -> Self {
265        Self {
266            fd,
267            buffer,
268            slices: vec![],
269            _p: PhantomPinned,
270        }
271    }
272}
273
274impl<T: IoVectoredBufMut, S> IntoInner for ReadVectored<T, S> {
275    type Inner = T;
276
277    fn into_inner(self) -> Self::Inner {
278        self.buffer
279    }
280}
281
282pin_project! {
283    /// Send to a file from vectored buffer.
284    pub struct WriteVectored<T: IoVectoredBuf, S> {
285        pub(crate) fd: S,
286        #[pin]
287        pub(crate) buffer: T,
288        pub(crate) slices: Vec<SysSlice>,
289        _p: PhantomPinned,
290    }
291}
292
293impl<T: IoVectoredBuf, S> WriteVectored<T, S> {
294    /// Create [`WriteVectored`].
295    pub fn new(fd: S, buffer: T) -> Self {
296        Self {
297            fd,
298            buffer,
299            slices: vec![],
300            _p: PhantomPinned,
301        }
302    }
303}
304
305impl<T: IoVectoredBuf, S> IntoInner for WriteVectored<T, S> {
306    type Inner = T;
307
308    fn into_inner(self) -> Self::Inner {
309        self.buffer
310    }
311}
312
313/// Remove file or directory.
314pub struct Unlink {
315    pub(crate) path: CString,
316    pub(crate) dir: bool,
317}
318
319impl Unlink {
320    /// Create [`Unlink`].
321    pub fn new(path: CString, dir: bool) -> Self {
322        Self { path, dir }
323    }
324
325    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
326        if self.dir {
327            Ok(syscall!(libc::rmdir(self.path.as_ptr()))? as _)
328        } else {
329            Ok(syscall!(libc::unlink(self.path.as_ptr()))? as _)
330        }
331    }
332}
333
334/// Create a directory.
335pub struct CreateDir {
336    pub(crate) path: CString,
337    pub(crate) mode: libc::mode_t,
338}
339
340impl CreateDir {
341    /// Create [`CreateDir`].
342    pub fn new(path: CString, mode: libc::mode_t) -> Self {
343        Self { path, mode }
344    }
345
346    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
347        Ok(syscall!(libc::mkdir(self.path.as_ptr(), self.mode))? as _)
348    }
349}
350
351/// Rename a file or directory.
352pub struct Rename {
353    pub(crate) old_path: CString,
354    pub(crate) new_path: CString,
355}
356
357impl Rename {
358    /// Create [`Rename`].
359    pub fn new(old_path: CString, new_path: CString) -> Self {
360        Self { old_path, new_path }
361    }
362
363    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
364        Ok(syscall!(libc::rename(self.old_path.as_ptr(), self.new_path.as_ptr()))? as _)
365    }
366}
367
368/// Create a symlink.
369pub struct Symlink {
370    pub(crate) source: CString,
371    pub(crate) target: CString,
372}
373
374impl Symlink {
375    /// Create [`Symlink`]. `target` is a symlink to `source`.
376    pub fn new(source: CString, target: CString) -> Self {
377        Self { source, target }
378    }
379
380    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
381        Ok(syscall!(libc::symlink(self.source.as_ptr(), self.target.as_ptr()))? as _)
382    }
383}
384
385/// Create a hard link.
386pub struct HardLink {
387    pub(crate) source: CString,
388    pub(crate) target: CString,
389}
390
391impl HardLink {
392    /// Create [`HardLink`]. `target` is a hard link to `source`.
393    pub fn new(source: CString, target: CString) -> Self {
394        Self { source, target }
395    }
396
397    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
398        Ok(syscall!(libc::link(self.source.as_ptr(), self.target.as_ptr()))? as _)
399    }
400}
401
402/// Create a socket.
403pub struct CreateSocket {
404    pub(crate) domain: i32,
405    pub(crate) socket_type: i32,
406    pub(crate) protocol: i32,
407}
408
409impl CreateSocket {
410    /// Create [`CreateSocket`].
411    pub fn new(domain: i32, socket_type: i32, protocol: i32) -> Self {
412        Self {
413            domain,
414            socket_type,
415            protocol,
416        }
417    }
418}
419
420impl<S: AsFd> ShutdownSocket<S> {
421    pub(crate) fn how(&self) -> i32 {
422        match self.how {
423            Shutdown::Write => libc::SHUT_WR,
424            Shutdown::Read => libc::SHUT_RD,
425            Shutdown::Both => libc::SHUT_RDWR,
426        }
427    }
428
429    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
430        Ok(syscall!(libc::shutdown(self.fd.as_fd().as_raw_fd(), self.how()))? as _)
431    }
432}
433
434impl CloseSocket {
435    pub(crate) fn call(self: Pin<&mut Self>) -> io::Result<usize> {
436        Ok(syscall!(libc::close(self.fd.as_fd().as_raw_fd()))? as _)
437    }
438}
439
440pin_project! {
441    /// Accept a connection.
442    pub struct Accept<S> {
443        pub(crate) fd: S,
444        pub(crate) buffer: SockAddrStorage,
445        pub(crate) addr_len: socklen_t,
446        pub(crate) accepted_fd: Option<OwnedFd>,
447        _p: PhantomPinned,
448    }
449}
450
451impl<S> Accept<S> {
452    /// Create [`Accept`].
453    pub fn new(fd: S) -> Self {
454        let buffer = SockAddrStorage::zeroed();
455        let addr_len = buffer.size_of();
456        Self {
457            fd,
458            buffer,
459            addr_len,
460            accepted_fd: None,
461            _p: PhantomPinned,
462        }
463    }
464
465    /// Get the remote address from the inner buffer.
466    pub fn into_addr(mut self) -> SockAddr {
467        std::mem::forget(self.accepted_fd.take());
468        unsafe { SockAddr::new(self.buffer, self.addr_len) }
469    }
470}
471
472pin_project! {
473    /// Receive data from remote.
474    ///
475    /// It is only used for socket operations. If you want to read from a pipe, use
476    /// [`Read`].
477    pub struct Recv<T: IoBufMut, S> {
478        pub(crate) fd: S,
479        #[pin]
480        pub(crate) buffer: T,
481        pub(crate) flags: i32,
482        _p: PhantomPinned,
483    }
484}
485
486impl<T: IoBufMut, S> Recv<T, S> {
487    /// Create [`Recv`].
488    pub fn new(fd: S, buffer: T, flags: i32) -> Self {
489        Self {
490            fd,
491            buffer,
492            flags,
493            _p: PhantomPinned,
494        }
495    }
496}
497
498impl<T: IoBufMut, S> IntoInner for Recv<T, S> {
499    type Inner = T;
500
501    fn into_inner(self) -> Self::Inner {
502        self.buffer
503    }
504}
505
506pin_project! {
507    /// Send data to remote.
508    ///
509    /// It is only used for socket operations. If you want to write to a pipe, use
510    /// [`Write`].
511    pub struct Send<T: IoBuf, S> {
512        pub(crate) fd: S,
513        #[pin]
514        pub(crate) buffer: T,
515        pub(crate) flags: i32,
516        _p: PhantomPinned,
517    }
518}
519
520impl<T: IoBuf, S> Send<T, S> {
521    /// Create [`Send`].
522    pub fn new(fd: S, buffer: T, flags: i32) -> Self {
523        Self {
524            fd,
525            buffer,
526            flags,
527            _p: PhantomPinned,
528        }
529    }
530}
531
532impl<T: IoBuf, S> IntoInner for Send<T, S> {
533    type Inner = T;
534
535    fn into_inner(self) -> Self::Inner {
536        self.buffer
537    }
538}
539
540pin_project! {
541    /// Receive data from remote into vectored buffer.
542    pub struct RecvVectored<T: IoVectoredBufMut, S> {
543        pub(crate) msg: libc::msghdr,
544        pub(crate) fd: S,
545        #[pin]
546        pub(crate) buffer: T,
547        pub(crate) slices: Vec<SysSlice>,
548        pub(crate) flags: i32,
549        _p: PhantomPinned,
550    }
551}
552
553impl<T: IoVectoredBufMut, S> RecvVectored<T, S> {
554    /// Create [`RecvVectored`].
555    pub fn new(fd: S, buffer: T, flags: i32) -> Self {
556        Self {
557            msg: unsafe { std::mem::zeroed() },
558            fd,
559            buffer,
560            slices: vec![],
561            flags,
562            _p: PhantomPinned,
563        }
564    }
565
566    pub(crate) fn set_msg(self: Pin<&mut Self>) {
567        let this = self.project();
568
569        *this.slices = this.buffer.sys_slices_mut();
570        this.msg.msg_iov = this.slices.as_mut_ptr() as _;
571        this.msg.msg_iovlen = this.slices.len() as _;
572    }
573}
574
575impl<T: IoVectoredBufMut, S> IntoInner for RecvVectored<T, S> {
576    type Inner = T;
577
578    fn into_inner(self) -> Self::Inner {
579        self.buffer
580    }
581}
582
583pin_project! {
584    /// Send data to remote from vectored buffer.
585    pub struct SendVectored<T: IoVectoredBuf, S> {
586        pub(crate) msg: libc::msghdr,
587        pub(crate) fd: S,
588        #[pin]
589        pub(crate) buffer: T,
590        pub(crate) slices: Vec<SysSlice>,
591        pub(crate) flags: i32,
592        _p: PhantomPinned,
593    }
594}
595
596impl<T: IoVectoredBuf, S> SendVectored<T, S> {
597    /// Create [`SendVectored`].
598    pub fn new(fd: S, buffer: T, flags: i32) -> Self {
599        Self {
600            msg: unsafe { std::mem::zeroed() },
601            fd,
602            buffer,
603            slices: vec![],
604            flags,
605            _p: PhantomPinned,
606        }
607    }
608
609    pub(crate) fn set_msg(self: Pin<&mut Self>) {
610        let this = self.project();
611
612        *this.slices = this.buffer.as_ref().sys_slices();
613        this.msg.msg_iov = this.slices.as_mut_ptr() as _;
614        this.msg.msg_iovlen = this.slices.len() as _;
615    }
616}
617
618impl<T: IoVectoredBuf, S> IntoInner for SendVectored<T, S> {
619    type Inner = T;
620
621    fn into_inner(self) -> Self::Inner {
622        self.buffer
623    }
624}
625
626pin_project! {
627    /// Receive data and source address with ancillary data into vectored buffer.
628    pub struct RecvMsg<T: IoVectoredBufMut, C: IoBufMut, S> {
629        pub(crate) msg: libc::msghdr,
630        pub(crate) addr: SockAddrStorage,
631        pub(crate) fd: S,
632        #[pin]
633        pub(crate) buffer: T,
634        pub(crate) control: C,
635        pub(crate) slices: Vec<SysSlice>,
636        pub(crate) flags: i32,
637        _p: PhantomPinned,
638    }
639}
640
641impl<T: IoVectoredBufMut, C: IoBufMut, S> RecvMsg<T, C, S> {
642    /// Create [`RecvMsg`].
643    ///
644    /// # Panics
645    ///
646    /// This function will panic if the control message buffer is misaligned.
647    pub fn new(fd: S, buffer: T, control: C, flags: i32) -> Self {
648        assert!(
649            control.buf_ptr().cast::<libc::cmsghdr>().is_aligned(),
650            "misaligned control message buffer"
651        );
652        Self {
653            msg: unsafe { std::mem::zeroed() },
654            addr: SockAddrStorage::zeroed(),
655            fd,
656            buffer,
657            control,
658            slices: vec![],
659            flags,
660            _p: PhantomPinned,
661        }
662    }
663
664    pub(crate) fn set_msg(self: Pin<&mut Self>) {
665        let this = self.project();
666        *this.slices = this.buffer.sys_slices_mut();
667
668        this.msg.msg_name = this.addr as *mut _ as _;
669        this.msg.msg_namelen = this.addr.size_of() as _;
670        this.msg.msg_iov = this.slices.as_mut_ptr() as _;
671        this.msg.msg_iovlen = this.slices.len() as _;
672        this.msg.msg_control = this.control.buf_mut_ptr() as _;
673        this.msg.msg_controllen = this.control.buf_capacity() as _;
674    }
675}
676
677impl<T: IoVectoredBufMut, C: IoBufMut, S> IntoInner for RecvMsg<T, C, S> {
678    type Inner = ((T, C), SockAddrStorage, socklen_t, usize);
679
680    fn into_inner(self) -> Self::Inner {
681        (
682            (self.buffer, self.control),
683            self.addr,
684            self.msg.msg_namelen,
685            self.msg.msg_controllen as _,
686        )
687    }
688}
689
690pin_project! {
691    /// Send data to specified address accompanied by ancillary data from vectored
692    /// buffer.
693    pub struct SendMsg<T: IoVectoredBuf, C: IoBuf, S> {
694        pub(crate) msg: libc::msghdr,
695        pub(crate) fd: S,
696        #[pin]
697        pub(crate) buffer: T,
698        #[pin]
699        pub(crate) control: C,
700        pub(crate) addr: SockAddr,
701        pub(crate) slices: Vec<SysSlice>,
702        pub(crate) flags: i32,
703        _p: PhantomPinned,
704    }
705}
706
707impl<T: IoVectoredBuf, C: IoBuf, S> SendMsg<T, C, S> {
708    /// Create [`SendMsg`].
709    ///
710    /// # Panics
711    ///
712    /// This function will panic if the control message buffer is misaligned.
713    pub fn new(fd: S, buffer: T, control: C, addr: SockAddr, flags: i32) -> Self {
714        assert!(
715            control.buf_ptr().cast::<libc::cmsghdr>().is_aligned(),
716            "misaligned control message buffer"
717        );
718        Self {
719            msg: unsafe { std::mem::zeroed() },
720            fd,
721            buffer,
722            control,
723            addr,
724            slices: vec![],
725            flags,
726            _p: PhantomPinned,
727        }
728    }
729
730    pub(crate) fn set_msg(self: Pin<&mut Self>) {
731        let this = self.project();
732        *this.slices = this.buffer.as_ref().sys_slices();
733        this.msg.msg_name = this.addr.as_ptr() as _;
734        this.msg.msg_namelen = this.addr.len();
735        this.msg.msg_iov = this.slices.as_ptr() as _;
736        this.msg.msg_iovlen = this.slices.len() as _;
737        this.msg.msg_control = this.control.buf_ptr() as _;
738        this.msg.msg_controllen = this.control.buf_len() as _;
739    }
740}
741
742impl<T: IoVectoredBuf, C: IoBuf, S> IntoInner for SendMsg<T, C, S> {
743    type Inner = (T, C);
744
745    fn into_inner(self) -> Self::Inner {
746        (self.buffer, self.control)
747    }
748}
749
750/// The interest to poll a file descriptor.
751#[derive(Debug, Clone, Copy, PartialEq, Eq)]
752pub enum Interest {
753    /// Represents a read operation.
754    Readable,
755    /// Represents a write operation.
756    Writable,
757}
758
759/// Poll a file descriptor for specified [`Interest`].
760pub struct PollOnce<S> {
761    pub(crate) fd: S,
762    pub(crate) interest: Interest,
763}
764
765impl<S> PollOnce<S> {
766    /// Create [`PollOnce`].
767    pub fn new(fd: S, interest: Interest) -> Self {
768        Self { fd, interest }
769    }
770}
771
772/// Splice data between two file descriptors.
773#[cfg(linux_all)]
774pub struct Splice<S1, S2> {
775    pub(crate) fd_in: S1,
776    pub(crate) offset_in: i64,
777    pub(crate) fd_out: S2,
778    pub(crate) offset_out: i64,
779    pub(crate) len: usize,
780    pub(crate) flags: u32,
781}
782
783#[cfg(linux_all)]
784impl<S1, S2> Splice<S1, S2> {
785    /// Create [`Splice`].
786    ///
787    /// `offset_in` and `offset_out` specify the offset to read from and write
788    /// to. Use `-1` for pipe ends or to use/update the current file
789    /// position.
790    pub fn new(
791        fd_in: S1,
792        offset_in: i64,
793        fd_out: S2,
794        offset_out: i64,
795        len: usize,
796        flags: u32,
797    ) -> Self {
798        Self {
799            fd_in,
800            offset_in,
801            fd_out,
802            offset_out,
803            len,
804            flags,
805        }
806    }
807}