Skip to main content

compio_driver/sys/op/fs/
iour.rs

1use io_uring::{opcode, types::*};
2use rustix::fs::{self, OFlags};
3
4use crate::{IourOpCode as OpCode, OpEntry, sys::op::*};
5
6unsafe impl<S: AsFd> OpCode for OpenFile<S> {
7    type Control = ();
8
9    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
10        opcode::OpenAt::new(Fd(self.dirfd.as_fd().as_raw_fd()), self.path.as_ptr())
11            .flags(self.flags.union(OFlags::CLOEXEC).bits() as _)
12            .mode(self.mode.bits())
13            .build()
14            .into()
15    }
16
17    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
18        self.call(control)
19    }
20
21    unsafe fn set_result(&mut self, _: &mut Self::Control, res: &io::Result<usize>, _: &Extra) {
22        if let Ok(fd) = res {
23            // SAFETY: fd is a valid fd returned from kernel
24            let fd = unsafe { OwnedFd::from_raw_fd(*fd as _) };
25            self.opened_fd = Some(fd);
26        }
27    }
28}
29
30unsafe impl OpCode for CloseFile {
31    type Control = ();
32
33    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
34        opcode::Close::new(Fd(self.fd.as_fd().as_raw_fd()))
35            .build()
36            .into()
37    }
38
39    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
40        self.call(control)
41    }
42}
43
44unsafe impl<S: AsFd> OpCode for TruncateFile<S> {
45    type Control = ();
46
47    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
48        opcode::Ftruncate::new(Fd(self.fd.as_fd().as_raw_fd()), self.size)
49            .build()
50            .into()
51    }
52
53    fn call_blocking(&mut self, _: &mut Self::Control) -> io::Result<usize> {
54        self.call()
55    }
56}
57
58/// Get metadata of an opened file.
59pub struct FileStat<S> {
60    pub(crate) fd: S,
61    pub(crate) stat: fs::Statx,
62}
63
64impl<S> FileStat<S> {
65    /// Create [`FileStat`].
66    pub fn new(fd: S) -> Self {
67        Self {
68            fd,
69            stat: unsafe { std::mem::zeroed() },
70        }
71    }
72}
73
74unsafe impl<S: AsFd> OpCode for FileStat<S> {
75    type Control = ();
76
77    fn create_entry(&mut self, _control: &mut Self::Control) -> OpEntry {
78        static EMPTY_NAME: &[u8] = b"\0";
79        opcode::Statx::new(
80            Fd(self.fd.as_fd().as_fd().as_raw_fd()),
81            EMPTY_NAME.as_ptr().cast(),
82            &raw mut self.stat as _,
83        )
84        .flags(libc::AT_EMPTY_PATH)
85        .mask(STATX_MASK.bits())
86        .build()
87        .into()
88    }
89
90    fn call_blocking(&mut self, _control: &mut Self::Control) -> io::Result<usize> {
91        self.stat = pal::statx(self.fd.as_fd(), c"", false)?;
92
93        Ok(0)
94    }
95}
96
97impl<S> IntoInner for FileStat<S> {
98    type Inner = Stat;
99
100    fn into_inner(self) -> Self::Inner {
101        statx_to_stat(self.stat)
102    }
103}
104
105/// Get metadata from path.
106pub struct PathStat<S: AsFd> {
107    pub(crate) dirfd: S,
108    pub(crate) path: CString,
109    pub(crate) stat: fs::Statx,
110    pub(crate) follow_symlink: bool,
111}
112
113impl<S: AsFd> PathStat<S> {
114    /// Create [`PathStat`].
115    pub fn new(dirfd: S, path: CString, follow_symlink: bool) -> Self {
116        Self {
117            dirfd,
118            path,
119            stat: unsafe { std::mem::zeroed() },
120            follow_symlink,
121        }
122    }
123}
124
125unsafe impl<S: AsFd> OpCode for PathStat<S> {
126    type Control = ();
127
128    fn create_entry(&mut self, _control: &mut Self::Control) -> OpEntry {
129        let mut flags = libc::AT_EMPTY_PATH;
130        if !self.follow_symlink {
131            flags |= libc::AT_SYMLINK_NOFOLLOW;
132        }
133        opcode::Statx::new(
134            Fd(self.dirfd.as_fd().as_raw_fd()),
135            self.path.as_ptr(),
136            &raw mut self.stat as _,
137        )
138        .flags(flags)
139        .mask(STATX_MASK.bits())
140        .build()
141        .into()
142    }
143
144    fn call_blocking(&mut self, _control: &mut Self::Control) -> io::Result<usize> {
145        self.stat = statx(self.dirfd.as_fd(), &self.path, self.follow_symlink)?;
146
147        Ok(0)
148    }
149}
150
151impl<S: AsFd> IntoInner for PathStat<S> {
152    type Inner = Stat;
153
154    fn into_inner(self) -> Self::Inner {
155        statx_to_stat(self.stat)
156    }
157}
158
159unsafe impl<S: AsFd> OpCode for Sync<S> {
160    type Control = ();
161
162    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
163        opcode::Fsync::new(Fd(self.fd.as_fd().as_raw_fd()))
164            .flags(if self.datasync {
165                FsyncFlags::DATASYNC
166            } else {
167                FsyncFlags::empty()
168            })
169            .build()
170            .into()
171    }
172}
173
174unsafe impl<S: AsFd> OpCode for Unlink<S> {
175    type Control = ();
176
177    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
178        opcode::UnlinkAt::new(Fd(self.dirfd.as_fd().as_raw_fd()), self.path.as_ptr())
179            .flags(if self.dir { libc::AT_REMOVEDIR } else { 0 })
180            .build()
181            .into()
182    }
183
184    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
185        self.call(control)
186    }
187}
188
189unsafe impl<S: AsFd> OpCode for CreateDir<S> {
190    type Control = ();
191
192    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
193        opcode::MkDirAt::new(Fd(self.dirfd.as_fd().as_raw_fd()), self.path.as_ptr())
194            .mode(self.mode.bits())
195            .build()
196            .into()
197    }
198
199    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
200        self.call(control)
201    }
202}
203
204unsafe impl<S1: AsFd, S2: AsFd> OpCode for Rename<S1, S2> {
205    type Control = ();
206
207    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
208        opcode::RenameAt::new(
209            Fd(self.old_dirfd.as_fd().as_raw_fd()),
210            self.old_path.as_ptr(),
211            Fd(self.new_dirfd.as_fd().as_raw_fd()),
212            self.new_path.as_ptr(),
213        )
214        .build()
215        .into()
216    }
217
218    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
219        self.call(control)
220    }
221}
222
223unsafe impl<S: AsFd> OpCode for Symlink<S> {
224    type Control = ();
225
226    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
227        opcode::SymlinkAt::new(
228            Fd(self.dirfd.as_fd().as_raw_fd()),
229            self.source.as_ptr(),
230            self.target.as_ptr(),
231        )
232        .build()
233        .into()
234    }
235
236    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
237        self.call(control)
238    }
239}
240
241unsafe impl<S1: AsFd, S2: AsFd> OpCode for HardLink<S1, S2> {
242    type Control = ();
243
244    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
245        opcode::LinkAt::new(
246            Fd(self.source_dirfd.as_fd().as_raw_fd()),
247            self.source.as_ptr(),
248            Fd(self.target_dirfd.as_fd().as_raw_fd()),
249            self.target.as_ptr(),
250        )
251        .build()
252        .into()
253    }
254
255    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
256        self.call(control)
257    }
258}
259
260unsafe impl<S1: AsFd, S2: AsFd> OpCode for Splice<S1, S2> {
261    type Control = ();
262
263    fn create_entry(&mut self, _: &mut Self::Control) -> OpEntry {
264        opcode::Splice::new(
265            Fd(self.fd_in.as_fd().as_raw_fd()),
266            self.offset_in,
267            Fd(self.fd_out.as_fd().as_raw_fd()),
268            self.offset_out,
269            self.len.try_into().unwrap_or(u32::MAX),
270        )
271        .flags(self.flags.bits())
272        .build()
273        .into()
274    }
275
276    fn call_blocking(&mut self, control: &mut Self::Control) -> io::Result<usize> {
277        self.call(control)
278    }
279}