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
10pub struct OpenFile {
12 pub(crate) path: CString,
13 pub(crate) flags: i32,
14 pub(crate) mode: libc::mode_t,
15}
16
17impl OpenFile {
18 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
86pub 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 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
120pub 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 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
154pub struct Unlink {
156 pub(crate) path: CString,
157 pub(crate) dir: bool,
158}
159
160impl Unlink {
161 pub fn new(path: CString, dir: bool) -> Self {
163 Self { path, dir }
164 }
165}
166
167pub struct CreateDir {
169 pub(crate) path: CString,
170 pub(crate) mode: libc::mode_t,
171}
172
173impl CreateDir {
174 pub fn new(path: CString, mode: libc::mode_t) -> Self {
176 Self { path, mode }
177 }
178}
179
180pub struct Rename {
182 pub(crate) old_path: CString,
183 pub(crate) new_path: CString,
184}
185
186impl Rename {
187 pub fn new(old_path: CString, new_path: CString) -> Self {
189 Self { old_path, new_path }
190 }
191}
192
193pub struct Symlink {
195 pub(crate) source: CString,
196 pub(crate) target: CString,
197}
198
199impl Symlink {
200 pub fn new(source: CString, target: CString) -> Self {
202 Self { source, target }
203 }
204}
205
206pub struct HardLink {
208 pub(crate) source: CString,
209 pub(crate) target: CString,
210}
211
212impl HardLink {
213 pub fn new(source: CString, target: CString) -> Self {
215 Self { source, target }
216 }
217}
218
219pub struct CreateSocket {
221 pub(crate) domain: i32,
222 pub(crate) socket_type: i32,
223 pub(crate) protocol: i32,
224}
225
226impl CreateSocket {
227 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
247pub 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 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 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
277pub 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 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
303pub 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 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
331pub 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 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
357pub 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 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
385pub 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 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
443pub 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 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
499pub enum Interest {
500 Readable,
502 Writable,
504}
505
506pub struct PollOnce<S> {
508 pub(crate) fd: S,
509 pub(crate) interest: Interest,
510}
511
512impl<S> PollOnce<S> {
513 pub fn new(fd: S, interest: Interest) -> Self {
515 Self { fd, interest }
516 }
517}