compio_driver/unix/
op.rs

1use std::{ffi::CString, marker::PhantomPinned, net::Shutdown, os::fd::OwnedFd};
2
3use compio_buf::{
4    IntoInner, IoBuf, IoBufMut, IoSlice, IoSliceMut, IoVectoredBuf, IoVectoredBufMut,
5};
6use socket2::{SockAddr, SockAddrStorage, socklen_t};
7
8use crate::op::*;
9
10/// Open or create a file with flags and mode.
11pub struct OpenFile {
12    pub(crate) path: CString,
13    pub(crate) flags: i32,
14    pub(crate) mode: libc::mode_t,
15}
16
17impl OpenFile {
18    /// Create [`OpenFile`].
19    pub fn new(path: CString, flags: i32, mode: libc::mode_t) -> Self {
20        Self { path, flags, mode }
21    }
22}
23
24#[cfg(gnulinux)]
25pub(crate) type Statx = libc::statx;
26
27#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
28#[repr(C)]
29pub(crate) struct StatxTimestamp {
30    pub tv_sec: i64,
31    pub tv_nsec: u32,
32    pub __statx_timestamp_pad1: [i32; 1],
33}
34
35#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
36#[repr(C)]
37pub(crate) struct Statx {
38    pub stx_mask: u32,
39    pub stx_blksize: u32,
40    pub stx_attributes: u64,
41    pub stx_nlink: u32,
42    pub stx_uid: u32,
43    pub stx_gid: u32,
44    pub stx_mode: u16,
45    __statx_pad1: [u16; 1],
46    pub stx_ino: u64,
47    pub stx_size: u64,
48    pub stx_blocks: u64,
49    pub stx_attributes_mask: u64,
50    pub stx_atime: StatxTimestamp,
51    pub stx_btime: StatxTimestamp,
52    pub stx_ctime: StatxTimestamp,
53    pub stx_mtime: StatxTimestamp,
54    pub stx_rdev_major: u32,
55    pub stx_rdev_minor: u32,
56    pub stx_dev_major: u32,
57    pub stx_dev_minor: u32,
58    pub stx_mnt_id: u64,
59    pub stx_dio_mem_align: u32,
60    pub stx_dio_offset_align: u32,
61    __statx_pad3: [u64; 12],
62}
63
64#[cfg(target_os = "linux")]
65pub(crate) const fn statx_to_stat(statx: Statx) -> libc::stat {
66    let mut stat: libc::stat = unsafe { std::mem::zeroed() };
67    stat.st_dev = libc::makedev(statx.stx_dev_major, statx.stx_dev_minor);
68    stat.st_ino = statx.stx_ino;
69    stat.st_nlink = statx.stx_nlink as _;
70    stat.st_mode = statx.stx_mode as _;
71    stat.st_uid = statx.stx_uid;
72    stat.st_gid = statx.stx_gid;
73    stat.st_rdev = libc::makedev(statx.stx_rdev_major, statx.stx_rdev_minor);
74    stat.st_size = statx.stx_size as _;
75    stat.st_blksize = statx.stx_blksize as _;
76    stat.st_blocks = statx.stx_blocks as _;
77    stat.st_atime = statx.stx_atime.tv_sec;
78    stat.st_atime_nsec = statx.stx_atime.tv_nsec as _;
79    stat.st_mtime = statx.stx_mtime.tv_sec;
80    stat.st_mtime_nsec = statx.stx_mtime.tv_nsec as _;
81    stat.st_ctime = statx.stx_btime.tv_sec;
82    stat.st_ctime_nsec = statx.stx_btime.tv_nsec as _;
83    stat
84}
85
86/// Read a file at specified position into vectored buffer.
87pub struct ReadVectoredAt<T: IoVectoredBufMut, S> {
88    pub(crate) fd: S,
89    pub(crate) offset: u64,
90    pub(crate) buffer: T,
91    pub(crate) slices: Vec<IoSliceMut>,
92    #[cfg(freebsd)]
93    pub(crate) aiocb: libc::aiocb,
94    _p: PhantomPinned,
95}
96
97impl<T: IoVectoredBufMut, S> ReadVectoredAt<T, S> {
98    /// Create [`ReadVectoredAt`].
99    pub fn new(fd: S, offset: u64, buffer: T) -> Self {
100        Self {
101            fd,
102            offset,
103            buffer,
104            slices: vec![],
105            #[cfg(freebsd)]
106            aiocb: unsafe { std::mem::zeroed() },
107            _p: PhantomPinned,
108        }
109    }
110}
111
112impl<T: IoVectoredBufMut, S> IntoInner for ReadVectoredAt<T, S> {
113    type Inner = T;
114
115    fn into_inner(self) -> Self::Inner {
116        self.buffer
117    }
118}
119
120/// Write a file at specified position from vectored buffer.
121pub struct WriteVectoredAt<T: IoVectoredBuf, S> {
122    pub(crate) fd: S,
123    pub(crate) offset: u64,
124    pub(crate) buffer: T,
125    pub(crate) slices: Vec<IoSlice>,
126    #[cfg(freebsd)]
127    pub(crate) aiocb: libc::aiocb,
128    _p: PhantomPinned,
129}
130
131impl<T: IoVectoredBuf, S> WriteVectoredAt<T, S> {
132    /// Create [`WriteVectoredAt`]
133    pub fn new(fd: S, offset: u64, buffer: T) -> Self {
134        Self {
135            fd,
136            offset,
137            buffer,
138            slices: vec![],
139            #[cfg(freebsd)]
140            aiocb: unsafe { std::mem::zeroed() },
141            _p: PhantomPinned,
142        }
143    }
144}
145
146impl<T: IoVectoredBuf, S> IntoInner for WriteVectoredAt<T, S> {
147    type Inner = T;
148
149    fn into_inner(self) -> Self::Inner {
150        self.buffer
151    }
152}
153
154/// Remove file or directory.
155pub struct Unlink {
156    pub(crate) path: CString,
157    pub(crate) dir: bool,
158}
159
160impl Unlink {
161    /// Create [`Unlink`].
162    pub fn new(path: CString, dir: bool) -> Self {
163        Self { path, dir }
164    }
165}
166
167/// Create a directory.
168pub struct CreateDir {
169    pub(crate) path: CString,
170    pub(crate) mode: libc::mode_t,
171}
172
173impl CreateDir {
174    /// Create [`CreateDir`].
175    pub fn new(path: CString, mode: libc::mode_t) -> Self {
176        Self { path, mode }
177    }
178}
179
180/// Rename a file or directory.
181pub struct Rename {
182    pub(crate) old_path: CString,
183    pub(crate) new_path: CString,
184}
185
186impl Rename {
187    /// Create [`Rename`].
188    pub fn new(old_path: CString, new_path: CString) -> Self {
189        Self { old_path, new_path }
190    }
191}
192
193/// Create a symlink.
194pub struct Symlink {
195    pub(crate) source: CString,
196    pub(crate) target: CString,
197}
198
199impl Symlink {
200    /// Create [`Symlink`]. `target` is a symlink to `source`.
201    pub fn new(source: CString, target: CString) -> Self {
202        Self { source, target }
203    }
204}
205
206/// Create a hard link.
207pub struct HardLink {
208    pub(crate) source: CString,
209    pub(crate) target: CString,
210}
211
212impl HardLink {
213    /// Create [`HardLink`]. `target` is a hard link to `source`.
214    pub fn new(source: CString, target: CString) -> Self {
215        Self { source, target }
216    }
217}
218
219/// Create a socket.
220pub struct CreateSocket {
221    pub(crate) domain: i32,
222    pub(crate) socket_type: i32,
223    pub(crate) protocol: i32,
224}
225
226impl CreateSocket {
227    /// Create [`CreateSocket`].
228    pub fn new(domain: i32, socket_type: i32, protocol: i32) -> Self {
229        Self {
230            domain,
231            socket_type,
232            protocol,
233        }
234    }
235}
236
237impl<S> ShutdownSocket<S> {
238    pub(crate) fn how(&self) -> i32 {
239        match self.how {
240            Shutdown::Write => libc::SHUT_WR,
241            Shutdown::Read => libc::SHUT_RD,
242            Shutdown::Both => libc::SHUT_RDWR,
243        }
244    }
245}
246
247/// Accept a connection.
248pub struct Accept<S> {
249    pub(crate) fd: S,
250    pub(crate) buffer: SockAddrStorage,
251    pub(crate) addr_len: socklen_t,
252    pub(crate) accepted_fd: Option<OwnedFd>,
253    _p: PhantomPinned,
254}
255
256impl<S> Accept<S> {
257    /// Create [`Accept`].
258    pub fn new(fd: S) -> Self {
259        let buffer = SockAddrStorage::zeroed();
260        let addr_len = buffer.size_of();
261        Self {
262            fd,
263            buffer,
264            addr_len,
265            accepted_fd: None,
266            _p: PhantomPinned,
267        }
268    }
269
270    /// Get the remote address from the inner buffer.
271    pub fn into_addr(mut self) -> SockAddr {
272        std::mem::forget(self.accepted_fd.take());
273        unsafe { SockAddr::new(self.buffer, self.addr_len) }
274    }
275}
276
277/// Receive data from remote.
278pub struct Recv<T: IoBufMut, S> {
279    pub(crate) fd: S,
280    pub(crate) buffer: T,
281    _p: PhantomPinned,
282}
283
284impl<T: IoBufMut, S> Recv<T, S> {
285    /// Create [`Recv`].
286    pub fn new(fd: S, buffer: T) -> Self {
287        Self {
288            fd,
289            buffer,
290            _p: PhantomPinned,
291        }
292    }
293}
294
295impl<T: IoBufMut, S> IntoInner for Recv<T, S> {
296    type Inner = T;
297
298    fn into_inner(self) -> Self::Inner {
299        self.buffer
300    }
301}
302
303/// Receive data from remote into vectored buffer.
304pub struct RecvVectored<T: IoVectoredBufMut, S> {
305    pub(crate) fd: S,
306    pub(crate) buffer: T,
307    pub(crate) slices: Vec<IoSliceMut>,
308    _p: PhantomPinned,
309}
310
311impl<T: IoVectoredBufMut, S> RecvVectored<T, S> {
312    /// Create [`RecvVectored`].
313    pub fn new(fd: S, buffer: T) -> Self {
314        Self {
315            fd,
316            buffer,
317            slices: vec![],
318            _p: PhantomPinned,
319        }
320    }
321}
322
323impl<T: IoVectoredBufMut, S> IntoInner for RecvVectored<T, S> {
324    type Inner = T;
325
326    fn into_inner(self) -> Self::Inner {
327        self.buffer
328    }
329}
330
331/// Send data to remote.
332pub struct Send<T: IoBuf, S> {
333    pub(crate) fd: S,
334    pub(crate) buffer: T,
335    _p: PhantomPinned,
336}
337
338impl<T: IoBuf, S> Send<T, S> {
339    /// Create [`Send`].
340    pub fn new(fd: S, buffer: T) -> Self {
341        Self {
342            fd,
343            buffer,
344            _p: PhantomPinned,
345        }
346    }
347}
348
349impl<T: IoBuf, S> IntoInner for Send<T, S> {
350    type Inner = T;
351
352    fn into_inner(self) -> Self::Inner {
353        self.buffer
354    }
355}
356
357/// Send data to remote from vectored buffer.
358pub struct SendVectored<T: IoVectoredBuf, S> {
359    pub(crate) fd: S,
360    pub(crate) buffer: T,
361    pub(crate) slices: Vec<IoSlice>,
362    _p: PhantomPinned,
363}
364
365impl<T: IoVectoredBuf, S> SendVectored<T, S> {
366    /// Create [`SendVectored`].
367    pub fn new(fd: S, buffer: T) -> Self {
368        Self {
369            fd,
370            buffer,
371            slices: vec![],
372            _p: PhantomPinned,
373        }
374    }
375}
376
377impl<T: IoVectoredBuf, S> IntoInner for SendVectored<T, S> {
378    type Inner = T;
379
380    fn into_inner(self) -> Self::Inner {
381        self.buffer
382    }
383}
384
385/// Receive data and source address with ancillary data into vectored buffer.
386pub struct RecvMsg<T: IoVectoredBufMut, C: IoBufMut, S> {
387    pub(crate) msg: libc::msghdr,
388    pub(crate) addr: SockAddrStorage,
389    pub(crate) fd: S,
390    pub(crate) buffer: T,
391    pub(crate) control: C,
392    pub(crate) slices: Vec<IoSliceMut>,
393    _p: PhantomPinned,
394}
395
396impl<T: IoVectoredBufMut, C: IoBufMut, S> RecvMsg<T, C, S> {
397    /// Create [`RecvMsg`].
398    ///
399    /// # Panics
400    ///
401    /// This function will panic if the control message buffer is misaligned.
402    pub fn new(fd: S, buffer: T, control: C) -> Self {
403        assert!(
404            control.as_buf_ptr().cast::<libc::cmsghdr>().is_aligned(),
405            "misaligned control message buffer"
406        );
407        Self {
408            addr: unsafe { std::mem::zeroed() },
409            msg: unsafe { std::mem::zeroed() },
410            fd,
411            buffer,
412            control,
413            slices: vec![],
414            _p: PhantomPinned,
415        }
416    }
417
418    pub(crate) unsafe fn set_msg(&mut self) {
419        self.slices = self.buffer.io_slices_mut();
420
421        self.msg.msg_name = std::ptr::addr_of_mut!(self.addr) as _;
422        self.msg.msg_namelen = std::mem::size_of_val(&self.addr) as _;
423        self.msg.msg_iov = self.slices.as_mut_ptr() as _;
424        self.msg.msg_iovlen = self.slices.len() as _;
425        self.msg.msg_control = self.control.as_buf_mut_ptr() as _;
426        self.msg.msg_controllen = self.control.buf_capacity() as _;
427    }
428}
429
430impl<T: IoVectoredBufMut, C: IoBufMut, S> IntoInner for RecvMsg<T, C, S> {
431    type Inner = ((T, C), SockAddrStorage, socklen_t, usize);
432
433    fn into_inner(self) -> Self::Inner {
434        (
435            (self.buffer, self.control),
436            self.addr,
437            self.msg.msg_namelen,
438            self.msg.msg_controllen as _,
439        )
440    }
441}
442
443/// Send data to specified address accompanied by ancillary data from vectored
444/// buffer.
445pub struct SendMsg<T: IoVectoredBuf, C: IoBuf, S> {
446    pub(crate) msg: libc::msghdr,
447    pub(crate) fd: S,
448    pub(crate) buffer: T,
449    pub(crate) control: C,
450    pub(crate) addr: SockAddr,
451    pub(crate) slices: Vec<IoSlice>,
452    _p: PhantomPinned,
453}
454
455impl<T: IoVectoredBuf, C: IoBuf, S> SendMsg<T, C, S> {
456    /// Create [`SendMsg`].
457    ///
458    /// # Panics
459    ///
460    /// This function will panic if the control message buffer is misaligned.
461    pub fn new(fd: S, buffer: T, control: C, addr: SockAddr) -> Self {
462        assert!(
463            control.as_buf_ptr().cast::<libc::cmsghdr>().is_aligned(),
464            "misaligned control message buffer"
465        );
466        Self {
467            msg: unsafe { std::mem::zeroed() },
468            fd,
469            buffer,
470            control,
471            addr,
472            slices: vec![],
473            _p: PhantomPinned,
474        }
475    }
476
477    pub(crate) unsafe fn set_msg(&mut self) {
478        self.slices = self.buffer.io_slices();
479
480        self.msg.msg_name = self.addr.as_ptr() as _;
481        self.msg.msg_namelen = self.addr.len();
482        self.msg.msg_iov = self.slices.as_ptr() as _;
483        self.msg.msg_iovlen = self.slices.len() as _;
484        self.msg.msg_control = self.control.as_buf_ptr() as _;
485        self.msg.msg_controllen = self.control.buf_len() as _;
486    }
487}
488
489impl<T: IoVectoredBuf, C: IoBuf, S> IntoInner for SendMsg<T, C, S> {
490    type Inner = (T, C);
491
492    fn into_inner(self) -> Self::Inner {
493        (self.buffer, self.control)
494    }
495}
496
497/// The interest to poll a file descriptor.
498#[derive(Debug, Clone, Copy, PartialEq, Eq)]
499pub enum Interest {
500    /// Represents a read operation.
501    Readable,
502    /// Represents a write operation.
503    Writable,
504}
505
506/// Poll a file descriptor for specified [`Interest`].
507pub struct PollOnce<S> {
508    pub(crate) fd: S,
509    pub(crate) interest: Interest,
510}
511
512impl<S> PollOnce<S> {
513    /// Create [`PollOnce`].
514    pub fn new(fd: S, interest: Interest) -> Self {
515        Self { fd, interest }
516    }
517}