1use std::{
2 ffi::CString,
3 marker::PhantomPinned,
4 net::Shutdown,
5 os::fd::{AsFd, AsRawFd, OwnedFd},
6 pin::Pin,
7};
8
9use compio_buf::{IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
10#[cfg(not(any(
11 all(target_os = "linux", not(target_env = "musl")),
12 target_os = "android",
13 target_os = "l4re",
14 target_os = "hurd"
15)))]
16use libc::{ftruncate as ftruncate64, off_t as off64_t};
17#[cfg(any(
18 all(target_os = "linux", not(target_env = "musl")),
19 target_os = "android",
20 target_os = "l4re",
21 target_os = "hurd"
22))]
23use libc::{ftruncate64, off64_t};
24use pin_project_lite::pin_project;
25use socket2::{SockAddr, SockAddrStorage, socklen_t};
26
27use crate::{op::*, sys::aio::*, sys_slice::*};
28
29pub struct OpenFile {
31 pub(crate) path: CString,
32 pub(crate) flags: i32,
33 pub(crate) mode: libc::mode_t,
34}
35
36impl OpenFile {
37 pub fn new(path: CString, flags: i32, mode: libc::mode_t) -> Self {
39 Self { path, flags, mode }
40 }
41}
42
43#[derive(Debug)]
44pub struct TruncateFile<S: AsFd> {
47 pub(crate) fd: S,
48 pub(crate) size: u64,
49}
50
51impl<S: AsFd> TruncateFile<S> {
52 pub fn new(fd: S, size: u64) -> Self {
54 Self { fd, size }
55 }
56
57 pub(crate) fn truncate(&self) -> std::io::Result<usize> {
58 let size: off64_t = self
59 .size
60 .try_into()
61 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?;
62 crate::syscall!(ftruncate64(self.fd.as_fd().as_raw_fd(), size)).map(|v| v as _)
63 }
64}
65
66#[cfg(not(gnulinux))]
67pub use libc::stat as Stat;
68#[cfg(gnulinux)]
69pub use libc::stat64 as Stat;
70#[cfg(gnulinux)]
71pub(crate) use libc::statx as Statx;
72
73#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
74#[repr(C)]
75pub(crate) struct StatxTimestamp {
76 pub tv_sec: i64,
77 pub tv_nsec: u32,
78 pub __statx_timestamp_pad1: [i32; 1],
79}
80
81#[cfg(all(target_os = "linux", not(target_env = "gnu")))]
82#[repr(C)]
83pub(crate) struct Statx {
84 pub stx_mask: u32,
85 pub stx_blksize: u32,
86 pub stx_attributes: u64,
87 pub stx_nlink: u32,
88 pub stx_uid: u32,
89 pub stx_gid: u32,
90 pub stx_mode: u16,
91 __statx_pad1: [u16; 1],
92 pub stx_ino: u64,
93 pub stx_size: u64,
94 pub stx_blocks: u64,
95 pub stx_attributes_mask: u64,
96 pub stx_atime: StatxTimestamp,
97 pub stx_btime: StatxTimestamp,
98 pub stx_ctime: StatxTimestamp,
99 pub stx_mtime: StatxTimestamp,
100 pub stx_rdev_major: u32,
101 pub stx_rdev_minor: u32,
102 pub stx_dev_major: u32,
103 pub stx_dev_minor: u32,
104 pub stx_mnt_id: u64,
105 pub stx_dio_mem_align: u32,
106 pub stx_dio_offset_align: u32,
107 __statx_pad3: [u64; 12],
108}
109
110#[cfg(target_os = "linux")]
111pub(crate) const fn statx_mask() -> u32 {
112 libc::STATX_TYPE
114 | libc::STATX_MODE
115 | libc::STATX_NLINK
116 | libc::STATX_UID
117 | libc::STATX_GID
118 | libc::STATX_ATIME
119 | libc::STATX_MTIME
120 | libc::STATX_CTIME
121 | libc::STATX_INO
122 | libc::STATX_SIZE
123 | libc::STATX_BLOCKS
124 | libc::STATX_BTIME
125 | libc::STATX_MNT_ID
126 | libc::STATX_DIOALIGN
127}
128
129#[cfg(target_os = "linux")]
130pub(crate) const fn statx_to_stat(statx: Statx) -> Stat {
131 let mut stat: Stat = unsafe { std::mem::zeroed() };
132 stat.st_dev = libc::makedev(statx.stx_dev_major, statx.stx_dev_minor) as _;
133 stat.st_ino = statx.stx_ino as _;
134 stat.st_nlink = statx.stx_nlink as _;
135 stat.st_mode = statx.stx_mode as _;
136 stat.st_uid = statx.stx_uid as _;
137 stat.st_gid = statx.stx_gid as _;
138 stat.st_rdev = libc::makedev(statx.stx_rdev_major, statx.stx_rdev_minor) as _;
139 stat.st_size = statx.stx_size as _;
140 stat.st_blksize = statx.stx_blksize as _;
141 stat.st_blocks = statx.stx_blocks as _;
142 stat.st_atime = statx.stx_atime.tv_sec as _;
143 stat.st_atime_nsec = statx.stx_atime.tv_nsec as _;
144 stat.st_mtime = statx.stx_mtime.tv_sec as _;
145 stat.st_mtime_nsec = statx.stx_mtime.tv_nsec as _;
146 stat.st_ctime = statx.stx_btime.tv_sec as _;
147 stat.st_ctime_nsec = statx.stx_btime.tv_nsec as _;
148 stat
149}
150
151pin_project! {
152 pub struct ReadVectoredAt<T: IoVectoredBufMut, S> {
154 pub(crate) fd: S,
155 pub(crate) offset: u64,
156 #[pin]
157 pub(crate) buffer: T,
158 pub(crate) slices: Vec<SysSlice>,
159 pub(crate) aiocb: aiocb,
160 _p: PhantomPinned,
161 }
162}
163
164impl<T: IoVectoredBufMut, S> ReadVectoredAt<T, S> {
165 pub fn new(fd: S, offset: u64, buffer: T) -> Self {
167 Self {
168 fd,
169 offset,
170 buffer,
171 slices: vec![],
172 aiocb: new_aiocb(),
173 _p: PhantomPinned,
174 }
175 }
176}
177
178impl<T: IoVectoredBufMut, S> IntoInner for ReadVectoredAt<T, S> {
179 type Inner = T;
180
181 fn into_inner(self) -> Self::Inner {
182 self.buffer
183 }
184}
185
186pin_project! {
187 pub struct WriteVectoredAt<T: IoVectoredBuf, S> {
189 pub(crate) fd: S,
190 pub(crate) offset: u64,
191 #[pin]
192 pub(crate) buffer: T,
193 pub(crate) slices: Vec<SysSlice>,
194 pub(crate) aiocb: aiocb,
195 _p: PhantomPinned,
196 }
197}
198impl<T: IoVectoredBuf, S> WriteVectoredAt<T, S> {
199 pub fn new(fd: S, offset: u64, buffer: T) -> Self {
201 Self {
202 fd,
203 offset,
204 buffer,
205 slices: vec![],
206 aiocb: new_aiocb(),
207 _p: PhantomPinned,
208 }
209 }
210}
211
212impl<T: IoVectoredBuf, S> IntoInner for WriteVectoredAt<T, S> {
213 type Inner = T;
214
215 fn into_inner(self) -> Self::Inner {
216 self.buffer
217 }
218}
219
220pin_project! {
221 pub struct ReadVectored<T: IoVectoredBufMut, S> {
223 pub(crate) fd: S,
224 #[pin]
225 pub(crate) buffer: T,
226 pub(crate) slices: Vec<SysSlice>,
227 _p: PhantomPinned,
228 }
229}
230
231impl<T: IoVectoredBufMut, S> ReadVectored<T, S> {
232 pub fn new(fd: S, buffer: T) -> Self {
234 Self {
235 fd,
236 buffer,
237 slices: vec![],
238 _p: PhantomPinned,
239 }
240 }
241}
242
243impl<T: IoVectoredBufMut, S> IntoInner for ReadVectored<T, S> {
244 type Inner = T;
245
246 fn into_inner(self) -> Self::Inner {
247 self.buffer
248 }
249}
250
251pin_project! {
252 pub struct WriteVectored<T: IoVectoredBuf, 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: IoVectoredBuf, S> WriteVectored<T, S> {
263 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: IoVectoredBuf, S> IntoInner for WriteVectored<T, S> {
275 type Inner = T;
276
277 fn into_inner(self) -> Self::Inner {
278 self.buffer
279 }
280}
281
282pub struct Unlink {
284 pub(crate) path: CString,
285 pub(crate) dir: bool,
286}
287
288impl Unlink {
289 pub fn new(path: CString, dir: bool) -> Self {
291 Self { path, dir }
292 }
293}
294
295pub struct CreateDir {
297 pub(crate) path: CString,
298 pub(crate) mode: libc::mode_t,
299}
300
301impl CreateDir {
302 pub fn new(path: CString, mode: libc::mode_t) -> Self {
304 Self { path, mode }
305 }
306}
307
308pub struct Rename {
310 pub(crate) old_path: CString,
311 pub(crate) new_path: CString,
312}
313
314impl Rename {
315 pub fn new(old_path: CString, new_path: CString) -> Self {
317 Self { old_path, new_path }
318 }
319}
320
321pub struct Symlink {
323 pub(crate) source: CString,
324 pub(crate) target: CString,
325}
326
327impl Symlink {
328 pub fn new(source: CString, target: CString) -> Self {
330 Self { source, target }
331 }
332}
333
334pub struct HardLink {
336 pub(crate) source: CString,
337 pub(crate) target: CString,
338}
339
340impl HardLink {
341 pub fn new(source: CString, target: CString) -> Self {
343 Self { source, target }
344 }
345}
346
347pub struct CreateSocket {
349 pub(crate) domain: i32,
350 pub(crate) socket_type: i32,
351 pub(crate) protocol: i32,
352}
353
354impl CreateSocket {
355 pub fn new(domain: i32, socket_type: i32, protocol: i32) -> Self {
357 Self {
358 domain,
359 socket_type,
360 protocol,
361 }
362 }
363}
364
365impl<S> ShutdownSocket<S> {
366 pub(crate) fn how(&self) -> i32 {
367 match self.how {
368 Shutdown::Write => libc::SHUT_WR,
369 Shutdown::Read => libc::SHUT_RD,
370 Shutdown::Both => libc::SHUT_RDWR,
371 }
372 }
373}
374
375pin_project! {
376 pub struct Accept<S> {
378 pub(crate) fd: S,
379 pub(crate) buffer: SockAddrStorage,
380 pub(crate) addr_len: socklen_t,
381 pub(crate) accepted_fd: Option<OwnedFd>,
382 _p: PhantomPinned,
383 }
384}
385
386impl<S> Accept<S> {
387 pub fn new(fd: S) -> Self {
389 let buffer = SockAddrStorage::zeroed();
390 let addr_len = buffer.size_of();
391 Self {
392 fd,
393 buffer,
394 addr_len,
395 accepted_fd: None,
396 _p: PhantomPinned,
397 }
398 }
399
400 pub fn into_addr(mut self) -> SockAddr {
402 std::mem::forget(self.accepted_fd.take());
403 unsafe { SockAddr::new(self.buffer, self.addr_len) }
404 }
405}
406
407pin_project! {
408 pub struct Recv<T: IoBufMut, S> {
413 pub(crate) fd: S,
414 #[pin]
415 pub(crate) buffer: T,
416 pub(crate) flags: i32,
417 _p: PhantomPinned,
418 }
419}
420
421impl<T: IoBufMut, S> Recv<T, S> {
422 pub fn new(fd: S, buffer: T, flags: i32) -> Self {
424 Self {
425 fd,
426 buffer,
427 flags,
428 _p: PhantomPinned,
429 }
430 }
431}
432
433impl<T: IoBufMut, S> IntoInner for Recv<T, S> {
434 type Inner = T;
435
436 fn into_inner(self) -> Self::Inner {
437 self.buffer
438 }
439}
440
441pin_project! {
442 pub struct Send<T: IoBuf, S> {
447 pub(crate) fd: S,
448 #[pin]
449 pub(crate) buffer: T,
450 pub(crate) flags: i32,
451 _p: PhantomPinned,
452 }
453}
454
455impl<T: IoBuf, S> Send<T, S> {
456 pub fn new(fd: S, buffer: T, flags: i32) -> Self {
458 Self {
459 fd,
460 buffer,
461 flags,
462 _p: PhantomPinned,
463 }
464 }
465}
466
467impl<T: IoBuf, S> IntoInner for Send<T, S> {
468 type Inner = T;
469
470 fn into_inner(self) -> Self::Inner {
471 self.buffer
472 }
473}
474
475pin_project! {
476 pub struct RecvVectored<T: IoVectoredBufMut, S> {
478 pub(crate) msg: libc::msghdr,
479 pub(crate) fd: S,
480 #[pin]
481 pub(crate) buffer: T,
482 pub(crate) slices: Vec<SysSlice>,
483 pub(crate) flags: i32,
484 _p: PhantomPinned,
485 }
486}
487
488impl<T: IoVectoredBufMut, S> RecvVectored<T, S> {
489 pub fn new(fd: S, buffer: T, flags: i32) -> Self {
491 Self {
492 msg: unsafe { std::mem::zeroed() },
493 fd,
494 buffer,
495 slices: vec![],
496 flags,
497 _p: PhantomPinned,
498 }
499 }
500
501 pub(crate) fn set_msg(self: Pin<&mut Self>) {
502 let this = self.project();
503
504 *this.slices = this.buffer.sys_slices_mut();
505 this.msg.msg_iov = this.slices.as_mut_ptr() as _;
506 this.msg.msg_iovlen = this.slices.len() as _;
507 }
508}
509
510impl<T: IoVectoredBufMut, S> IntoInner for RecvVectored<T, S> {
511 type Inner = T;
512
513 fn into_inner(self) -> Self::Inner {
514 self.buffer
515 }
516}
517
518pin_project! {
519 pub struct SendVectored<T: IoVectoredBuf, S> {
521 pub(crate) msg: libc::msghdr,
522 pub(crate) fd: S,
523 #[pin]
524 pub(crate) buffer: T,
525 pub(crate) slices: Vec<SysSlice>,
526 pub(crate) flags: i32,
527 _p: PhantomPinned,
528 }
529}
530
531impl<T: IoVectoredBuf, S> SendVectored<T, S> {
532 pub fn new(fd: S, buffer: T, flags: i32) -> Self {
534 Self {
535 msg: unsafe { std::mem::zeroed() },
536 fd,
537 buffer,
538 slices: vec![],
539 flags,
540 _p: PhantomPinned,
541 }
542 }
543
544 pub(crate) fn set_msg(self: Pin<&mut Self>) {
545 let this = self.project();
546
547 *this.slices = this.buffer.as_ref().sys_slices();
548 this.msg.msg_iov = this.slices.as_mut_ptr() as _;
549 this.msg.msg_iovlen = this.slices.len() as _;
550 }
551}
552
553impl<T: IoVectoredBuf, S> IntoInner for SendVectored<T, S> {
554 type Inner = T;
555
556 fn into_inner(self) -> Self::Inner {
557 self.buffer
558 }
559}
560
561pin_project! {
562 pub struct RecvMsg<T: IoVectoredBufMut, C: IoBufMut, S> {
564 pub(crate) msg: libc::msghdr,
565 pub(crate) addr: SockAddrStorage,
566 pub(crate) fd: S,
567 #[pin]
568 pub(crate) buffer: T,
569 pub(crate) control: C,
570 pub(crate) slices: Vec<SysSlice>,
571 pub(crate) flags: i32,
572 _p: PhantomPinned,
573 }
574}
575
576impl<T: IoVectoredBufMut, C: IoBufMut, S> RecvMsg<T, C, S> {
577 pub fn new(fd: S, buffer: T, control: C, flags: i32) -> Self {
583 assert!(
584 control.buf_ptr().cast::<libc::cmsghdr>().is_aligned(),
585 "misaligned control message buffer"
586 );
587 Self {
588 msg: unsafe { std::mem::zeroed() },
589 addr: SockAddrStorage::zeroed(),
590 fd,
591 buffer,
592 control,
593 slices: vec![],
594 flags,
595 _p: PhantomPinned,
596 }
597 }
598
599 pub(crate) fn set_msg(self: Pin<&mut Self>) {
600 let this = self.project();
601 *this.slices = this.buffer.sys_slices_mut();
602
603 this.msg.msg_name = this.addr as *mut _ as _;
604 this.msg.msg_namelen = this.addr.size_of() as _;
605 this.msg.msg_iov = this.slices.as_mut_ptr() as _;
606 this.msg.msg_iovlen = this.slices.len() as _;
607 this.msg.msg_control = this.control.buf_mut_ptr() as _;
608 this.msg.msg_controllen = this.control.buf_capacity() as _;
609 }
610}
611
612impl<T: IoVectoredBufMut, C: IoBufMut, S> IntoInner for RecvMsg<T, C, S> {
613 type Inner = ((T, C), SockAddrStorage, socklen_t, usize);
614
615 fn into_inner(self) -> Self::Inner {
616 (
617 (self.buffer, self.control),
618 self.addr,
619 self.msg.msg_namelen,
620 self.msg.msg_controllen as _,
621 )
622 }
623}
624
625pin_project! {
626 pub struct SendMsg<T: IoVectoredBuf, C: IoBuf, S> {
629 pub(crate) msg: libc::msghdr,
630 pub(crate) fd: S,
631 #[pin]
632 pub(crate) buffer: T,
633 #[pin]
634 pub(crate) control: C,
635 pub(crate) addr: SockAddr,
636 pub(crate) slices: Vec<SysSlice>,
637 pub(crate) flags: i32,
638 _p: PhantomPinned,
639 }
640}
641
642impl<T: IoVectoredBuf, C: IoBuf, S> SendMsg<T, C, S> {
643 pub fn new(fd: S, buffer: T, control: C, addr: SockAddr, flags: i32) -> Self {
649 assert!(
650 control.buf_ptr().cast::<libc::cmsghdr>().is_aligned(),
651 "misaligned control message buffer"
652 );
653 Self {
654 msg: unsafe { std::mem::zeroed() },
655 fd,
656 buffer,
657 control,
658 addr,
659 slices: vec![],
660 flags,
661 _p: PhantomPinned,
662 }
663 }
664
665 pub(crate) fn set_msg(self: Pin<&mut Self>) {
666 let this = self.project();
667 *this.slices = this.buffer.as_ref().sys_slices();
668 this.msg.msg_name = this.addr.as_ptr() as _;
669 this.msg.msg_namelen = this.addr.len();
670 this.msg.msg_iov = this.slices.as_ptr() as _;
671 this.msg.msg_iovlen = this.slices.len() as _;
672 this.msg.msg_control = this.control.buf_ptr() as _;
673 this.msg.msg_controllen = this.control.buf_len() as _;
674 }
675}
676
677impl<T: IoVectoredBuf, C: IoBuf, S> IntoInner for SendMsg<T, C, S> {
678 type Inner = (T, C);
679
680 fn into_inner(self) -> Self::Inner {
681 (self.buffer, self.control)
682 }
683}
684
685#[derive(Debug, Clone, Copy, PartialEq, Eq)]
687pub enum Interest {
688 Readable,
690 Writable,
692}
693
694pub struct PollOnce<S> {
696 pub(crate) fd: S,
697 pub(crate) interest: Interest,
698}
699
700impl<S> PollOnce<S> {
701 pub fn new(fd: S, interest: Interest) -> Self {
703 Self { fd, interest }
704 }
705}
706
707#[cfg(linux_all)]
709pub struct Splice<S1, S2> {
710 pub(crate) fd_in: S1,
711 pub(crate) offset_in: i64,
712 pub(crate) fd_out: S2,
713 pub(crate) offset_out: i64,
714 pub(crate) len: usize,
715 pub(crate) flags: u32,
716}
717
718#[cfg(linux_all)]
719impl<S1, S2> Splice<S1, S2> {
720 pub fn new(
726 fd_in: S1,
727 offset_in: i64,
728 fd_out: S2,
729 offset_out: i64,
730 len: usize,
731 flags: u32,
732 ) -> Self {
733 Self {
734 fd_in,
735 offset_in,
736 fd_out,
737 offset_out,
738 len,
739 flags,
740 }
741 }
742}