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